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 +
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
+ +Gear +
Icons made by Fermam Aziz from www.flaticon.com is licensed by CC 3.0 BY
+ +Import, Export +
Icons made by Anatoly from www.flaticon.com is licensed by CC 3.0 BY
+ +Cross +
Icons made by Balraj Chana from www.flaticon.com is licensed by CC 3.0 BY
+ +Previous, Next, Expand, Camera +
Icons made by Gregor Cresnar from www.flaticon.com is licensed by CC 3.0 BY
+ +Organization +
Icons made by Good Ware from www.flaticon.com is licensed by CC 3.0 BY
+ +Left sidebar +
Icons made by Those Icons from www.flaticon.com is licensed by CC 3.0 BY
+ +Link button +
Icons made by Google from www.flaticon.com is licensed by CC 3.0 BY
+ +Back square button +
Icons made by GraphicsBay from www.flaticon.com is licensed by CC 3.0 BY
+ +Settings +
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
+ +Placeholder +
Icons made by Those Icons from www.flaticon.com is licensed by CC 3.0 BY
+ +Error +
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
+ +Settings +
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
+ +Zoom In, Zoom Out +
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
+ +Dodecahedron(mesh) +
Icons made by Pixel perfect from www.flaticon.com is licensed by CC 3.0 BY
+ +Cube +
Icons made by Retinaicons from www.flaticon.com is licensed by CC 3.0 BY
+ +Clipping +
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
+ +View 3d pre-defined orientation +
Icons made by Pixel perfect from www.flaticon.com is licensed by CC 3.0 BY
+ +Stop(dark-theme) +
Icons made by Alfredo Hernandez from www.flaticon.com is licensed by CC 3.0 BY
+ +File (sheet) +
Icons made by Picol from www.flaticon.com is licensed by CC 3.0 BY
+ +List (XdeDocumentItem) +
Icons made by Smartline from www.flaticon.com is licensed by CC 3.0 BY
+ +Hierarchy (Assembly) +
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
+
Icons made by Dave Gandy from www.flaticon.com is licensed by CC 3.0 BY
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; + using const_index_type = std::add_const_t; + using iterator = bounds_iterator; + using const_iterator = bounds_iterator; + using difference_type = std::ptrdiff_t; + using sliced_type = static_bounds; + using mapping_type = contiguous_mapping_tag; + + constexpr static_bounds(const static_bounds&) = default; + + template + struct BoundsRangeConvertible2; + + template > + static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type) -> Ret; + + template + static auto helpBoundsRangeConvertible(SourceType, TargetType, ...) -> std::false_type; + + template + struct BoundsRangeConvertible2 + : decltype(helpBoundsRangeConvertible( + SourceType(), TargetType(), + std::integral_constant())) + { + }; + + template + struct BoundsRangeConvertible2 : std::true_type + { + }; + + template + struct BoundsRangeConvertible + : decltype(helpBoundsRangeConvertible( + SourceType(), TargetType(), + std::integral_constant::value || + TargetType::CurrentRange == dynamic_range || + SourceType::CurrentRange == dynamic_range)>())) + { + }; + + template + struct BoundsRangeConvertible : std::true_type + { + }; + + template , + details::BoundsRanges>::value>> + constexpr static_bounds(const static_bounds& other) : m_ranges(other.m_ranges) + { + Expects((MyRanges::DynamicNum == 0 && details::BoundsRanges::DynamicNum == 0) || + MyRanges::DynamicNum > 0 || other.m_ranges.totalSize() >= m_ranges.totalSize()); + } + + constexpr static_bounds(std::initializer_list il) + : m_ranges(static_cast(il.begin())) + { + // Size of the initializer list must match the rank of the array + Expects((MyRanges::DynamicNum == 0 && il.size() == 1 && *il.begin() == static_size) || + MyRanges::DynamicNum == il.size()); + // Size of the range must be less than the max element of the size type + Expects(m_ranges.totalSize() <= PTRDIFF_MAX); + } + + constexpr static_bounds() = default; + + constexpr sliced_type slice() const GSL_NOEXCEPT + { + return sliced_type{static_cast&>(m_ranges)}; + } + + constexpr size_type stride() const GSL_NOEXCEPT { return rank > 1 ? slice().size() : 1; } + + constexpr size_type size() const GSL_NOEXCEPT { return m_ranges.totalSize(); } + + constexpr size_type total_size() const GSL_NOEXCEPT { return m_ranges.totalSize(); } + + constexpr size_type linearize(const index_type& idx) const { return m_ranges.linearize(idx); } + + constexpr bool contains(const index_type& idx) const GSL_NOEXCEPT + { + return m_ranges.contains(idx) != -1; + } + + constexpr size_type operator[](std::size_t idx) const GSL_NOEXCEPT + { + return m_ranges.elementNum(idx); + } + + template + constexpr size_type extent() const GSL_NOEXCEPT + { + static_assert(Dim < rank, + "dimension should be less than rank (dimension count starts from 0)"); + return details::createTypeListIndexer(m_ranges).template get().elementNum(); + } + + template + constexpr size_type extent(IntType dim) const GSL_NOEXCEPT + { + static_assert(std::is_integral::value, + "Dimension parameter must be supplied as an integral type."); + auto real_dim = narrow_cast(dim); + Expects(real_dim < rank); + + return m_ranges.elementNum(real_dim); + } + + constexpr index_type index_bounds() const GSL_NOEXCEPT + { + size_type extents[rank] = {}; + m_ranges.serialize(extents); + return {extents}; + } + + template + constexpr bool operator==(const static_bounds& rhs) const GSL_NOEXCEPT + { + return this->size() == rhs.size(); + } + + template + constexpr bool operator!=(const static_bounds& rhs) const GSL_NOEXCEPT + { + return !(*this == rhs); + } + + constexpr const_iterator begin() const GSL_NOEXCEPT + { + return const_iterator(*this, index_type{}); + } + + constexpr const_iterator end() const GSL_NOEXCEPT + { + return const_iterator(*this, this->index_bounds()); + } +}; + +template +class strided_bounds +{ + template + friend class strided_bounds; + +public: + static const std::size_t rank = Rank; + using value_type = std::ptrdiff_t; + using reference = std::add_lvalue_reference_t; + using const_reference = std::add_const_t; + using size_type = value_type; + using difference_type = value_type; + using index_type = multi_span_index; + using const_index_type = std::add_const_t; + using iterator = bounds_iterator; + using const_iterator = bounds_iterator; + static const value_type dynamic_rank = rank; + static const value_type static_size = dynamic_range; + using sliced_type = std::conditional_t, void>; + using mapping_type = generalized_mapping_tag; + + constexpr strided_bounds(const strided_bounds&) GSL_NOEXCEPT = default; + + constexpr strided_bounds& operator=(const strided_bounds&) GSL_NOEXCEPT = default; + + constexpr strided_bounds(const value_type (&values)[rank], index_type strides) + : m_extents(values), m_strides(std::move(strides)) + { + } + + constexpr strided_bounds(const index_type& extents, const index_type& strides) GSL_NOEXCEPT + : m_extents(extents), + m_strides(strides) + { + } + + constexpr index_type strides() const GSL_NOEXCEPT { return m_strides; } + + constexpr size_type total_size() const GSL_NOEXCEPT + { + size_type ret = 0; + for (std::size_t i = 0; i < rank; ++i) { + ret += (m_extents[i] - 1) * m_strides[i]; + } + return ret + 1; + } + + constexpr size_type size() const GSL_NOEXCEPT + { + size_type ret = 1; + for (std::size_t i = 0; i < rank; ++i) { + ret *= m_extents[i]; + } + return ret; + } + + constexpr bool contains(const index_type& idx) const GSL_NOEXCEPT + { + for (std::size_t i = 0; i < rank; ++i) { + if (idx[i] < 0 || idx[i] >= m_extents[i]) return false; + } + return true; + } + + constexpr size_type linearize(const index_type& idx) const GSL_NOEXCEPT + { + size_type ret = 0; + for (std::size_t i = 0; i < rank; i++) { + Expects(idx[i] < m_extents[i]); // index is out of bounds of the array + ret += idx[i] * m_strides[i]; + } + return ret; + } + + constexpr size_type stride() const GSL_NOEXCEPT { return m_strides[0]; } + + template 1), typename Ret = std::enable_if_t> + constexpr sliced_type slice() const + { + return {details::shift_left(m_extents), details::shift_left(m_strides)}; + } + + template + constexpr size_type extent() const GSL_NOEXCEPT + { + static_assert(Dim < Rank, + "dimension should be less than rank (dimension count starts from 0)"); + return m_extents[Dim]; + } + + constexpr index_type index_bounds() const GSL_NOEXCEPT { return m_extents; } + constexpr const_iterator begin() const GSL_NOEXCEPT + { + return const_iterator{*this, index_type{}}; + } + + constexpr const_iterator end() const GSL_NOEXCEPT + { + return const_iterator{*this, index_bounds()}; + } + +private: + index_type m_extents; + index_type m_strides; +}; + +template +struct is_bounds : std::integral_constant +{ +}; +template +struct is_bounds> : std::integral_constant +{ +}; +template +struct is_bounds> : std::integral_constant +{ +}; + +template +class bounds_iterator +{ +public: + static const std::size_t rank = IndexType::rank; + using iterator_category = std::random_access_iterator_tag; + using value_type = IndexType; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + using index_type = value_type; + using index_size_type = typename IndexType::value_type; + template + explicit bounds_iterator(const Bounds& bnd, value_type curr) GSL_NOEXCEPT + : boundary_(bnd.index_bounds()), + curr_(std::move(curr)) + { + static_assert(is_bounds::value, "Bounds type must be provided"); + } + + constexpr reference operator*() const GSL_NOEXCEPT { return curr_; } + + constexpr pointer operator->() const GSL_NOEXCEPT { return &curr_; } + + constexpr bounds_iterator& operator++() GSL_NOEXCEPT + { + for (std::size_t i = rank; i-- > 0;) { + if (curr_[i] < boundary_[i] - 1) { + curr_[i]++; + return *this; + } + curr_[i] = 0; + } + // If we're here we've wrapped over - set to past-the-end. + curr_ = boundary_; + return *this; + } + + constexpr bounds_iterator operator++(int) GSL_NOEXCEPT + { + auto ret = *this; + ++(*this); + return ret; + } + + constexpr bounds_iterator& operator--() GSL_NOEXCEPT + { + if (!less(curr_, boundary_)) { + // if at the past-the-end, set to last element + for (std::size_t i = 0; i < rank; ++i) { + curr_[i] = boundary_[i] - 1; + } + return *this; + } + for (std::size_t i = rank; i-- > 0;) { + if (curr_[i] >= 1) { + curr_[i]--; + return *this; + } + curr_[i] = boundary_[i] - 1; + } + // If we're here the preconditions were violated + // "pre: there exists s such that r == ++s" + Expects(false); + return *this; + } + + constexpr bounds_iterator operator--(int) GSL_NOEXCEPT + { + auto ret = *this; + --(*this); + return ret; + } + + constexpr bounds_iterator operator+(difference_type n) const GSL_NOEXCEPT + { + bounds_iterator ret{*this}; + return ret += n; + } + + constexpr bounds_iterator& operator+=(difference_type n) GSL_NOEXCEPT + { + auto linear_idx = linearize(curr_) + n; + std::remove_const_t stride = 0; + stride[rank - 1] = 1; + for (std::size_t i = rank - 1; i-- > 0;) { + stride[i] = stride[i + 1] * boundary_[i + 1]; + } + for (std::size_t i = 0; i < rank; ++i) { + curr_[i] = linear_idx / stride[i]; + linear_idx = linear_idx % stride[i]; + } + // index is out of bounds of the array + Expects(!less(curr_, index_type{}) && !less(boundary_, curr_)); + return *this; + } + + constexpr bounds_iterator operator-(difference_type n) const GSL_NOEXCEPT + { + bounds_iterator ret{*this}; + return ret -= n; + } + + constexpr bounds_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; } + + constexpr difference_type operator-(const bounds_iterator& rhs) const GSL_NOEXCEPT + { + return linearize(curr_) - linearize(rhs.curr_); + } + + constexpr value_type operator[](difference_type n) const GSL_NOEXCEPT { return *(*this + n); } + + constexpr bool operator==(const bounds_iterator& rhs) const GSL_NOEXCEPT + { + return curr_ == rhs.curr_; + } + + constexpr bool operator!=(const bounds_iterator& rhs) const GSL_NOEXCEPT + { + return !(*this == rhs); + } + + constexpr bool operator<(const bounds_iterator& rhs) const GSL_NOEXCEPT + { + return less(curr_, rhs.curr_); + } + + constexpr bool operator<=(const bounds_iterator& rhs) const GSL_NOEXCEPT + { + return !(rhs < *this); + } + + constexpr bool operator>(const bounds_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; } + + constexpr bool operator>=(const bounds_iterator& rhs) const GSL_NOEXCEPT + { + return !(rhs > *this); + } + + void swap(bounds_iterator& rhs) GSL_NOEXCEPT + { + std::swap(boundary_, rhs.boundary_); + std::swap(curr_, rhs.curr_); + } + +private: + constexpr bool less(index_type& one, index_type& other) const GSL_NOEXCEPT + { + for (std::size_t i = 0; i < rank; ++i) { + if (one[i] < other[i]) return true; + } + return false; + } + + constexpr index_size_type linearize(const value_type& idx) const GSL_NOEXCEPT + { + // TODO: Smarter impl. + // Check if past-the-end + index_size_type multiplier = 1; + index_size_type res = 0; + if (!less(idx, boundary_)) { + res = 1; + for (std::size_t i = rank; i-- > 0;) { + res += (idx[i] - 1) * multiplier; + multiplier *= boundary_[i]; + } + } + else + { + for (std::size_t i = rank; i-- > 0;) { + res += idx[i] * multiplier; + multiplier *= boundary_[i]; + } + } + return res; + } + + value_type boundary_; + std::remove_const_t curr_; +}; + +template +bounds_iterator operator+(typename bounds_iterator::difference_type n, + const bounds_iterator& rhs) GSL_NOEXCEPT +{ + return rhs + n; +} + +namespace details +{ + template + constexpr std::enable_if_t< + std::is_same::value, + typename Bounds::index_type> + make_stride(const Bounds& bnd) GSL_NOEXCEPT + { + return bnd.strides(); + } + + // Make a stride vector from bounds, assuming contiguous memory. + template + constexpr std::enable_if_t< + std::is_same::value, + typename Bounds::index_type> + make_stride(const Bounds& bnd) GSL_NOEXCEPT + { + auto extents = bnd.index_bounds(); + typename Bounds::size_type stride[Bounds::rank] = {}; + + stride[Bounds::rank - 1] = 1; + for (std::size_t i = 1; i < Bounds::rank; ++i) { + stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i]; + } + return {stride}; + } + + template + void verifyBoundsReshape(const BoundsSrc& src, const BoundsDest& dest) + { + static_assert(is_bounds::value && is_bounds::value, + "The src type and dest type must be bounds"); + static_assert(std::is_same::value, + "The source type must be a contiguous bounds"); + static_assert(BoundsDest::static_size == dynamic_range || + BoundsSrc::static_size == dynamic_range || + BoundsDest::static_size == BoundsSrc::static_size, + "The source bounds must have same size as dest bounds"); + Expects(src.size() == dest.size()); + } + +} // namespace details + +template +class contiguous_span_iterator; +template +class general_span_iterator; + +template +struct dim_t +{ + static const std::ptrdiff_t value = DimSize; +}; +template <> +struct dim_t +{ + static const std::ptrdiff_t value = dynamic_range; + const std::ptrdiff_t dvalue; + constexpr dim_t(std::ptrdiff_t size) GSL_NOEXCEPT : dvalue(size) {} +}; + +template = 0)>> +constexpr dim_t dim() GSL_NOEXCEPT +{ + return dim_t(); +} + +template > +constexpr dim_t dim(std::ptrdiff_t n) GSL_NOEXCEPT +{ + return dim_t<>(n); +} + +template +class multi_span; +template +class strided_span; + +namespace details +{ + template + struct SpanTypeTraits + { + using value_type = T; + using size_type = std::size_t; + }; + + template + struct SpanTypeTraits::type> + { + using value_type = typename Traits::span_traits::value_type; + using size_type = typename Traits::span_traits::size_type; + }; + + template + struct SpanArrayTraits + { + using type = multi_span; + using value_type = T; + using bounds_type = static_bounds; + using pointer = T*; + using reference = T&; + }; + template + struct SpanArrayTraits : SpanArrayTraits + { + }; + + template + BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::true_type) // dynamic size + { + Expects(totalSize >= 0 && totalSize <= PTRDIFF_MAX); + return BoundsType{totalSize}; + } + template + BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::false_type) // static size + { + Expects(BoundsType::static_size <= totalSize); + return {}; + } + template + BoundsType newBoundsHelper(std::ptrdiff_t totalSize) + { + static_assert(BoundsType::dynamic_rank <= 1, "dynamic rank must less or equal to 1"); + return newBoundsHelperImpl( + totalSize, std::integral_constant()); + } + + struct Sep + { + }; + + template + T static_as_multi_span_helper(Sep, Args... args) + { + return T{narrow_cast(args)...}; + } + template + std::enable_if_t< + !std::is_same>::value && !std::is_same::value, T> + static_as_multi_span_helper(Arg, Args... args) + { + return static_as_multi_span_helper(args...); + } + template + T static_as_multi_span_helper(dim_t val, Args... args) + { + return static_as_multi_span_helper(args..., val.dvalue); + } + + template + struct static_as_multi_span_static_bounds_helper + { + using type = static_bounds<(Dimensions::value)...>; + }; + + template + struct is_multi_span_oracle : std::false_type + { + }; + + template + struct is_multi_span_oracle> + : std::true_type + { + }; + + template + struct is_multi_span_oracle> : std::true_type + { + }; + + template + struct is_multi_span : is_multi_span_oracle> + { + }; +} + +template +class multi_span +{ + // TODO do we still need this? + template + friend class multi_span; + +public: + using bounds_type = static_bounds; + static const std::size_t Rank = bounds_type::rank; + using size_type = typename bounds_type::size_type; + using index_type = typename bounds_type::index_type; + using value_type = ValueType; + using const_value_type = std::add_const_t; + using pointer = std::add_pointer_t; + using reference = std::add_lvalue_reference_t; + using iterator = contiguous_span_iterator; + using const_span = multi_span; + using const_iterator = contiguous_span_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using sliced_type = + std::conditional_t>; + +private: + pointer data_; + bounds_type bounds_; + + friend iterator; + friend const_iterator; + +public: + // default constructor - same as constructing from nullptr_t + constexpr multi_span() GSL_NOEXCEPT : multi_span(nullptr, bounds_type{}) + { + static_assert(bounds_type::dynamic_rank != 0 || + (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), + "Default construction of multi_span only possible " + "for dynamic or fixed, zero-length spans."); + } + + // construct from nullptr - get an empty multi_span + constexpr multi_span(std::nullptr_t) GSL_NOEXCEPT : multi_span(nullptr, bounds_type{}) + { + static_assert(bounds_type::dynamic_rank != 0 || + (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), + "nullptr_t construction of multi_span only possible " + "for dynamic or fixed, zero-length spans."); + } + + // construct from nullptr with size of 0 (helps with template function calls) + template ::value>> + constexpr multi_span(std::nullptr_t, IntType size) GSL_NOEXCEPT + : multi_span(nullptr, bounds_type{}) + { + static_assert(bounds_type::dynamic_rank != 0 || + (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), + "nullptr_t construction of multi_span only possible " + "for dynamic or fixed, zero-length spans."); + Expects(size == 0); + } + + // construct from a single element + constexpr multi_span(reference data) GSL_NOEXCEPT : multi_span(&data, bounds_type{1}) + { + static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 || + bounds_type::static_size == 1, + "Construction from a single element only possible " + "for dynamic or fixed spans of length 0 or 1."); + } + + // prevent constructing from temporaries for single-elements + constexpr multi_span(value_type&&) = delete; + + // construct from pointer + length + constexpr multi_span(pointer ptr, size_type size) GSL_NOEXCEPT + : multi_span(ptr, bounds_type{size}) + { + } + + // construct from pointer + length - multidimensional + constexpr multi_span(pointer data, bounds_type bounds) GSL_NOEXCEPT : data_(data), + bounds_(std::move(bounds)) + { + Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0); + } + + // construct from begin,end pointer pair + template ::value && + details::LessThan::value>> + constexpr multi_span(pointer begin, Ptr end) + : multi_span(begin, + details::newBoundsHelper(static_cast(end) - begin)) + { + Expects(begin != nullptr && end != nullptr && begin <= static_cast(end)); + } + + // construct from n-dimensions static array + template > + constexpr multi_span(T (&arr)[N]) + : multi_span(reinterpret_cast(arr), bounds_type{typename Helper::bounds_type{}}) + { + static_assert(std::is_convertible::value, + "Cannot convert from source type to target multi_span type."); + static_assert(std::is_convertible::value, + "Cannot construct a multi_span from an array with fewer elements."); + } + + // construct from n-dimensions dynamic array (e.g. new int[m][4]) + // (precedence will be lower than the 1-dimension pointer) + template > + constexpr multi_span(T* const& data, size_type size) + : multi_span(reinterpret_cast(data), typename Helper::bounds_type{size}) + { + static_assert(std::is_convertible::value, + "Cannot convert from source type to target multi_span type."); + } + + // construct from std::array + template + constexpr multi_span(std::array& arr) + : multi_span(arr.data(), bounds_type{static_bounds{}}) + { + static_assert( + std::is_convertible(*)[]>::value, + "Cannot convert from source type to target multi_span type."); + static_assert(std::is_convertible, bounds_type>::value, + "You cannot construct a multi_span from a std::array of smaller size."); + } + + // construct from const std::array + template + constexpr multi_span(const std::array& arr) + : multi_span(arr.data(), bounds_type{static_bounds{}}) + { + static_assert(std::is_convertible(*)[]>::value, + "Cannot convert from source type to target multi_span type."); + static_assert(std::is_convertible, bounds_type>::value, + "You cannot construct a multi_span from a std::array of smaller size."); + } + + // prevent constructing from temporary std::array + template + constexpr multi_span(std::array&& arr) = delete; + + // construct from containers + // future: could use contiguous_iterator_traits to identify only contiguous containers + // type-requirements: container must have .size(), operator[] which are value_type compatible + template ::value && + std::is_convertible::value && + std::is_same().size(), + *std::declval().data())>, + DataType>::value>> + constexpr multi_span(Cont& cont) + : multi_span(static_cast(cont.data()), + details::newBoundsHelper(narrow_cast(cont.size()))) + { + } + + // prevent constructing from temporary containers + template ::value && + std::is_convertible::value && + std::is_same().size(), + *std::declval().data())>, + DataType>::value>> + explicit constexpr multi_span(Cont&& cont) = delete; + + // construct from a convertible multi_span + template , + typename = std::enable_if_t::value && + std::is_convertible::value>> + constexpr multi_span(multi_span other) GSL_NOEXCEPT + : data_(other.data_), + bounds_(other.bounds_) + { + } + + // trivial copy and move + constexpr multi_span(const multi_span&) = default; + constexpr multi_span(multi_span&&) = default; + + // trivial assignment + constexpr multi_span& operator=(const multi_span&) = default; + constexpr multi_span& operator=(multi_span&&) = default; + + // first() - extract the first Count elements into a new multi_span + template + constexpr multi_span first() const GSL_NOEXCEPT + { + static_assert(Count >= 0, "Count must be >= 0."); + static_assert(bounds_type::static_size == dynamic_range || + Count <= bounds_type::static_size, + "Count is out of bounds."); + + Expects(bounds_type::static_size != dynamic_range || Count <= this->size()); + return {this->data(), Count}; + } + + // first() - extract the first count elements into a new multi_span + constexpr multi_span first(size_type count) const GSL_NOEXCEPT + { + Expects(count >= 0 && count <= this->size()); + return {this->data(), count}; + } + + // last() - extract the last Count elements into a new multi_span + template + constexpr multi_span last() const GSL_NOEXCEPT + { + static_assert(Count >= 0, "Count must be >= 0."); + static_assert(bounds_type::static_size == dynamic_range || + Count <= bounds_type::static_size, + "Count is out of bounds."); + + Expects(bounds_type::static_size != dynamic_range || Count <= this->size()); + return {this->data() + this->size() - Count, Count}; + } + + // last() - extract the last count elements into a new multi_span + constexpr multi_span last(size_type count) const GSL_NOEXCEPT + { + Expects(count >= 0 && count <= this->size()); + return {this->data() + this->size() - count, count}; + } + + // subspan() - create a subview of Count elements starting at Offset + template + constexpr multi_span subspan() const GSL_NOEXCEPT + { + static_assert(Count >= 0, "Count must be >= 0."); + static_assert(Offset >= 0, "Offset must be >= 0."); + static_assert(bounds_type::static_size == dynamic_range || + ((Offset <= bounds_type::static_size) && + Count <= bounds_type::static_size - Offset), + "You must describe a sub-range within bounds of the multi_span."); + + Expects(bounds_type::static_size != dynamic_range || + (Offset <= this->size() && Count <= this->size() - Offset)); + return {this->data() + Offset, Count}; + } + + // subspan() - create a subview of count elements starting at offset + // supplying dynamic_range for count will consume all available elements from offset + constexpr multi_span + subspan(size_type offset, size_type count = dynamic_range) const GSL_NOEXCEPT + { + Expects((offset >= 0 && offset <= this->size()) && + (count == dynamic_range || (count <= this->size() - offset))); + return {this->data() + offset, count == dynamic_range ? this->length() - offset : count}; + } + + // section - creates a non-contiguous, strided multi_span from a contiguous one + constexpr strided_span section(index_type origin, + index_type extents) const GSL_NOEXCEPT + { + size_type size = this->bounds().total_size() - this->bounds().linearize(origin); + return {&this->operator[](origin), size, + strided_bounds{extents, details::make_stride(bounds())}}; + } + + // length of the multi_span in elements + constexpr size_type size() const GSL_NOEXCEPT { return bounds_.size(); } + + // length of the multi_span in elements + constexpr size_type length() const GSL_NOEXCEPT { return this->size(); } + + // length of the multi_span in bytes + constexpr size_type size_bytes() const GSL_NOEXCEPT + { + return narrow_cast(sizeof(value_type)) * this->size(); + } + + // length of the multi_span in bytes + constexpr size_type length_bytes() const GSL_NOEXCEPT { return this->size_bytes(); } + + constexpr bool empty() const GSL_NOEXCEPT { return this->size() == 0; } + + static constexpr std::size_t rank() { return Rank; } + + template + constexpr size_type extent() const GSL_NOEXCEPT + { + static_assert(Dim < Rank, + "Dimension should be less than rank (dimension count starts from 0)."); + return bounds_.template extent(); + } + + template + constexpr size_type extent(IntType dim) const GSL_NOEXCEPT + { + return bounds_.extent(dim); + } + + constexpr bounds_type bounds() const GSL_NOEXCEPT { return bounds_; } + + constexpr pointer data() const GSL_NOEXCEPT { return data_; } + + template + constexpr reference operator()(FirstIndex idx) + { + return this->operator[](narrow_cast(idx)); + } + + template + constexpr reference operator()(FirstIndex firstIndex, OtherIndices... indices) + { + index_type idx = {narrow_cast(firstIndex), + narrow_cast(indices)...}; + return this->operator[](idx); + } + + constexpr reference operator[](const index_type& idx) const GSL_NOEXCEPT + { + return data_[bounds_.linearize(idx)]; + } + + template 1), typename Ret = std::enable_if_t> + constexpr Ret operator[](size_type idx) const GSL_NOEXCEPT + { + Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array + const size_type ridx = idx * bounds_.stride(); + + // index is out of bounds of the underlying data + Expects(ridx < bounds_.total_size()); + return Ret{data_ + ridx, bounds_.slice()}; + } + + constexpr iterator begin() const GSL_NOEXCEPT { return iterator{this, true}; } + + constexpr iterator end() const GSL_NOEXCEPT { return iterator{this, false}; } + + constexpr const_iterator cbegin() const GSL_NOEXCEPT + { + return const_iterator{reinterpret_cast(this), true}; + } + + constexpr const_iterator cend() const GSL_NOEXCEPT + { + return const_iterator{reinterpret_cast(this), false}; + } + + constexpr reverse_iterator rbegin() const GSL_NOEXCEPT { return reverse_iterator{end()}; } + + constexpr reverse_iterator rend() const GSL_NOEXCEPT { return reverse_iterator{begin()}; } + + constexpr const_reverse_iterator crbegin() const GSL_NOEXCEPT + { + return const_reverse_iterator{cend()}; + } + + constexpr const_reverse_iterator crend() const GSL_NOEXCEPT + { + return const_reverse_iterator{cbegin()}; + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator==(const multi_span& other) const GSL_NOEXCEPT + { + return bounds_.size() == other.bounds_.size() && + (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator!=(const multi_span& other) const GSL_NOEXCEPT + { + return !(*this == other); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator<(const multi_span& other) const GSL_NOEXCEPT + { + return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator<=(const multi_span& other) const GSL_NOEXCEPT + { + return !(other < *this); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator>(const multi_span& other) const GSL_NOEXCEPT + { + return (other < *this); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator>=(const multi_span& other) const GSL_NOEXCEPT + { + return !(*this < other); + } +}; + +// +// Free functions for manipulating spans +// + +// reshape a multi_span into a different dimensionality +// DimCount and Enabled here are workarounds for a bug in MSVC 2015 +template 0), typename = std::enable_if_t> +constexpr auto as_multi_span(SpanType s, Dimensions2... dims) + -> multi_span +{ + static_assert(details::is_multi_span::value, + "Variadic as_multi_span() is for reshaping existing spans."); + using BoundsType = + typename multi_span::bounds_type; + auto tobounds = details::static_as_multi_span_helper(dims..., details::Sep{}); + details::verifyBoundsReshape(s.bounds(), tobounds); + return {s.data(), tobounds}; +} + +// convert a multi_span to a multi_span +template +multi_span as_bytes(multi_span s) GSL_NOEXCEPT +{ + static_assert(std::is_trivial>::value, + "The value_type of multi_span must be a trivial type."); + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +// convert a multi_span to a multi_span (a writeable byte multi_span) +// this is not currently a portable function that can be relied upon to work +// on all implementations. It should be considered an experimental extension +// to the standard GSL interface. +template +multi_span as_writeable_bytes(multi_span s) GSL_NOEXCEPT +{ + static_assert(std::is_trivial>::value, + "The value_type of multi_span must be a trivial type."); + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +// convert a multi_span to a multi_span +// this is not currently a portable function that can be relied upon to work +// on all implementations. It should be considered an experimental extension +// to the standard GSL interface. +template +constexpr auto +as_multi_span(multi_span s) GSL_NOEXCEPT -> multi_span< + const U, static_cast( + multi_span::bounds_type::static_size != dynamic_range + ? (static_cast( + multi_span::bounds_type::static_size) / + sizeof(U)) + : dynamic_range)> +{ + using ConstByteSpan = multi_span; + static_assert( + std::is_trivial>::value && + (ConstByteSpan::bounds_type::static_size == dynamic_range || + ConstByteSpan::bounds_type::static_size % narrow_cast(sizeof(U)) == 0), + "Target type must be a trivial type and its size must match the byte array size"); + + Expects((s.size_bytes() % narrow_cast(sizeof(U))) == 0 && + (s.size_bytes() / narrow_cast(sizeof(U))) < PTRDIFF_MAX); + return {reinterpret_cast(s.data()), + s.size_bytes() / narrow_cast(sizeof(U))}; +} + +// convert a multi_span to a multi_span +// this is not currently a portable function that can be relied upon to work +// on all implementations. It should be considered an experimental extension +// to the standard GSL interface. +template +constexpr auto as_multi_span(multi_span s) GSL_NOEXCEPT + -> multi_span( + multi_span::bounds_type::static_size != dynamic_range + ? static_cast( + multi_span::bounds_type::static_size) / + sizeof(U) + : dynamic_range)> +{ + using ByteSpan = multi_span; + static_assert( + std::is_trivial>::value && + (ByteSpan::bounds_type::static_size == dynamic_range || + ByteSpan::bounds_type::static_size % static_cast(sizeof(U)) == 0), + "Target type must be a trivial type and its size must match the byte array size"); + + Expects((s.size_bytes() % sizeof(U)) == 0); + return {reinterpret_cast(s.data()), + s.size_bytes() / narrow_cast(sizeof(U))}; +} + +template +constexpr auto as_multi_span(T* const& ptr, dim_t... args) + -> multi_span, Dimensions...> +{ + return {reinterpret_cast*>(ptr), + details::static_as_multi_span_helper>(args..., + details::Sep{})}; +} + +template +constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) -> + typename details::SpanArrayTraits::type +{ + return {reinterpret_cast*>(arr), len}; +} + +template +constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits::type +{ + return {arr}; +} + +template +constexpr multi_span as_multi_span(const std::array& arr) +{ + return {arr}; +} + +template +constexpr multi_span as_multi_span(const std::array&&) = delete; + +template +constexpr multi_span as_multi_span(std::array& arr) +{ + return {arr}; +} + +template +constexpr multi_span as_multi_span(T* begin, T* end) +{ + return {begin, end}; +} + +template +constexpr auto as_multi_span(Cont& arr) -> std::enable_if_t< + !details::is_multi_span>::value, + multi_span, dynamic_range>> +{ + Expects(arr.size() < PTRDIFF_MAX); + return {arr.data(), narrow_cast(arr.size())}; +} + +template +constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t< + !details::is_multi_span>::value, + multi_span, dynamic_range>> = delete; + +// from basic_string which doesn't have nonconst .data() member like other contiguous containers +template +constexpr auto as_multi_span(std::basic_string& str) + -> multi_span +{ + Expects(str.size() < PTRDIFF_MAX); + return {&str[0], narrow_cast(str.size())}; +} + +// strided_span is an extension that is not strictly part of the GSL at this time. +// It is kept here while the multidimensional interface is still being defined. +template +class strided_span +{ +public: + using bounds_type = strided_bounds; + using size_type = typename bounds_type::size_type; + using index_type = typename bounds_type::index_type; + using value_type = ValueType; + using const_value_type = std::add_const_t; + using pointer = std::add_pointer_t; + using reference = std::add_lvalue_reference_t; + using iterator = general_span_iterator; + using const_strided_span = strided_span; + using const_iterator = general_span_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using sliced_type = + std::conditional_t>; + +private: + pointer data_; + bounds_type bounds_; + + friend iterator; + friend const_iterator; + template + friend class strided_span; + +public: + // from raw data + constexpr strided_span(pointer ptr, size_type size, bounds_type bounds) + : data_(ptr), bounds_(std::move(bounds)) + { + Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0); + // Bounds cross data boundaries + Expects(this->bounds().total_size() <= size); + (void) size; + } + + // from static array of size N + template + constexpr strided_span(value_type (&values)[N], bounds_type bounds) + : strided_span(values, N, std::move(bounds)) + { + } + + // from array view + template ::value, + typename = std::enable_if_t> + constexpr strided_span(multi_span av, bounds_type bounds) + : strided_span(av.data(), av.bounds().total_size(), std::move(bounds)) + { + } + + // convertible + template ::value>> + constexpr strided_span(const strided_span& other) + : data_(other.data_), bounds_(other.bounds_) + { + } + + // convert from bytes + template + constexpr strided_span< + typename std::enable_if::value, OtherValueType>::type, + Rank> + as_strided_span() const + { + static_assert((sizeof(OtherValueType) >= sizeof(value_type)) && + (sizeof(OtherValueType) % sizeof(value_type) == 0), + "OtherValueType should have a size to contain a multiple of ValueTypes"); + auto d = narrow_cast(sizeof(OtherValueType) / sizeof(value_type)); + + size_type size = this->bounds().total_size() / d; + return {const_cast(reinterpret_cast(this->data())), + size, + bounds_type{resize_extent(this->bounds().index_bounds(), d), + resize_stride(this->bounds().strides(), d)}}; + } + + constexpr strided_span section(index_type origin, index_type extents) const + { + size_type size = this->bounds().total_size() - this->bounds().linearize(origin); + return {&this->operator[](origin), size, + bounds_type{extents, details::make_stride(bounds())}}; + } + + constexpr reference operator[](const index_type& idx) const + { + return data_[bounds_.linearize(idx)]; + } + + template 1), typename Ret = std::enable_if_t> + constexpr Ret operator[](size_type idx) const + { + Expects(idx < bounds_.size()); // index is out of bounds of the array + const size_type ridx = idx * bounds_.stride(); + + // index is out of bounds of the underlying data + Expects(ridx < bounds_.total_size()); + return {data_ + ridx, bounds_.slice().total_size(), bounds_.slice()}; + } + + constexpr bounds_type bounds() const GSL_NOEXCEPT { return bounds_; } + + template + constexpr size_type extent() const GSL_NOEXCEPT + { + static_assert(Dim < Rank, + "dimension should be less than Rank (dimension count starts from 0)"); + return bounds_.template extent(); + } + + constexpr size_type size() const GSL_NOEXCEPT { return bounds_.size(); } + + constexpr pointer data() const GSL_NOEXCEPT { return data_; } + + constexpr explicit operator bool() const GSL_NOEXCEPT { return data_ != nullptr; } + + constexpr iterator begin() const { return iterator{this, true}; } + + constexpr iterator end() const { return iterator{this, false}; } + + constexpr const_iterator cbegin() const + { + return const_iterator{reinterpret_cast(this), true}; + } + + constexpr const_iterator cend() const + { + return const_iterator{reinterpret_cast(this), false}; + } + + constexpr reverse_iterator rbegin() const { return reverse_iterator{end()}; } + + constexpr reverse_iterator rend() const { return reverse_iterator{begin()}; } + + constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator{cend()}; } + + constexpr const_reverse_iterator crend() const { return const_reverse_iterator{cbegin()}; } + + template , std::remove_cv_t>::value>> + constexpr bool + operator==(const strided_span& other) const GSL_NOEXCEPT + { + return bounds_.size() == other.bounds_.size() && + (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator!=(const strided_span& other) const GSL_NOEXCEPT + { + return !(*this == other); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator<(const strided_span& other) const GSL_NOEXCEPT + { + return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator<=(const strided_span& other) const GSL_NOEXCEPT + { + return !(other < *this); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator>(const strided_span& other) const GSL_NOEXCEPT + { + return (other < *this); + } + + template , std::remove_cv_t>::value>> + constexpr bool + operator>=(const strided_span& other) const GSL_NOEXCEPT + { + return !(*this < other); + } + +private: + static index_type resize_extent(const index_type& extent, std::ptrdiff_t d) + { + // The last dimension of the array needs to contain a multiple of new type elements + Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0)); + + index_type ret = extent; + ret[Rank - 1] /= d; + + return ret; + } + + template > + static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr) + { + // Only strided arrays with regular strides can be resized + Expects(strides[Rank - 1] == 1); + + return strides; + } + + template 1), typename = std::enable_if_t> + static index_type resize_stride(const index_type& strides, std::ptrdiff_t d) + { + // Only strided arrays with regular strides can be resized + Expects(strides[Rank - 1] == 1); + // The strides must have contiguous chunks of + // memory that can contain a multiple of new type elements + Expects(strides[Rank - 2] >= d && (strides[Rank - 2] % d == 0)); + + for (std::size_t i = Rank - 1; i > 0; --i) { + // Only strided arrays with regular strides can be resized + Expects((strides[i - 1] >= strides[i]) && (strides[i - 1] % strides[i] == 0)); + } + + index_type ret = strides / d; + ret[Rank - 1] = 1; + + return ret; + } +}; + +template +class contiguous_span_iterator +{ +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = typename Span::value_type; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + +private: + template + friend class multi_span; + + pointer data_; + const Span* m_validator; + void validateThis() const + { + // iterator is out of range of the array + Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size()); + } + contiguous_span_iterator(const Span* container, bool isbegin) + : data_(isbegin ? container->data_ : container->data_ + container->size()) + , m_validator(container) + { + } + +public: + reference operator*() const GSL_NOEXCEPT + { + validateThis(); + return *data_; + } + pointer operator->() const GSL_NOEXCEPT + { + validateThis(); + return data_; + } + contiguous_span_iterator& operator++() GSL_NOEXCEPT + { + ++data_; + return *this; + } + contiguous_span_iterator operator++(int) GSL_NOEXCEPT + { + auto ret = *this; + ++(*this); + return ret; + } + contiguous_span_iterator& operator--() GSL_NOEXCEPT + { + --data_; + return *this; + } + contiguous_span_iterator operator--(int) GSL_NOEXCEPT + { + auto ret = *this; + --(*this); + return ret; + } + contiguous_span_iterator operator+(difference_type n) const GSL_NOEXCEPT + { + contiguous_span_iterator ret{*this}; + return ret += n; + } + contiguous_span_iterator& operator+=(difference_type n) GSL_NOEXCEPT + { + data_ += n; + return *this; + } + contiguous_span_iterator operator-(difference_type n) const GSL_NOEXCEPT + { + contiguous_span_iterator ret{*this}; + return ret -= n; + } + contiguous_span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; } + difference_type operator-(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT + { + Expects(m_validator == rhs.m_validator); + return data_ - rhs.data_; + } + reference operator[](difference_type n) const GSL_NOEXCEPT { return *(*this + n); } + bool operator==(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT + { + Expects(m_validator == rhs.m_validator); + return data_ == rhs.data_; + } + bool operator!=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT + { + return !(*this == rhs); + } + bool operator<(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT + { + Expects(m_validator == rhs.m_validator); + return data_ < rhs.data_; + } + bool operator<=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT + { + return !(rhs < *this); + } + bool operator>(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; } + bool operator>=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT + { + return !(rhs > *this); + } + void swap(contiguous_span_iterator& rhs) GSL_NOEXCEPT + { + std::swap(data_, rhs.data_); + std::swap(m_validator, rhs.m_validator); + } +}; + +template +contiguous_span_iterator operator+(typename contiguous_span_iterator::difference_type n, + const contiguous_span_iterator& rhs) GSL_NOEXCEPT +{ + return rhs + n; +} + +template +class general_span_iterator +{ +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = typename Span::value_type; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + +private: + template + friend class strided_span; + + const Span* m_container; + typename Span::bounds_type::iterator m_itr; + general_span_iterator(const Span* container, bool isbegin) + : m_container(container) + , m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end()) + { + } + +public: + reference operator*() GSL_NOEXCEPT { return (*m_container)[*m_itr]; } + pointer operator->() GSL_NOEXCEPT { return &(*m_container)[*m_itr]; } + general_span_iterator& operator++() GSL_NOEXCEPT + { + ++m_itr; + return *this; + } + general_span_iterator operator++(int) GSL_NOEXCEPT + { + auto ret = *this; + ++(*this); + return ret; + } + general_span_iterator& operator--() GSL_NOEXCEPT + { + --m_itr; + return *this; + } + general_span_iterator operator--(int) GSL_NOEXCEPT + { + auto ret = *this; + --(*this); + return ret; + } + general_span_iterator operator+(difference_type n) const GSL_NOEXCEPT + { + general_span_iterator ret{*this}; + return ret += n; + } + general_span_iterator& operator+=(difference_type n) GSL_NOEXCEPT + { + m_itr += n; + return *this; + } + general_span_iterator operator-(difference_type n) const GSL_NOEXCEPT + { + general_span_iterator ret{*this}; + return ret -= n; + } + general_span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; } + difference_type operator-(const general_span_iterator& rhs) const GSL_NOEXCEPT + { + Expects(m_container == rhs.m_container); + return m_itr - rhs.m_itr; + } + value_type operator[](difference_type n) const GSL_NOEXCEPT { return (*m_container)[m_itr[n]]; } + + bool operator==(const general_span_iterator& rhs) const GSL_NOEXCEPT + { + Expects(m_container == rhs.m_container); + return m_itr == rhs.m_itr; + } + bool operator!=(const general_span_iterator& rhs) const GSL_NOEXCEPT { return !(*this == rhs); } + bool operator<(const general_span_iterator& rhs) const GSL_NOEXCEPT + { + Expects(m_container == rhs.m_container); + return m_itr < rhs.m_itr; + } + bool operator<=(const general_span_iterator& rhs) const GSL_NOEXCEPT { return !(rhs < *this); } + bool operator>(const general_span_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; } + bool operator>=(const general_span_iterator& rhs) const GSL_NOEXCEPT { return !(rhs > *this); } + void swap(general_span_iterator& rhs) GSL_NOEXCEPT + { + std::swap(m_itr, rhs.m_itr); + std::swap(m_container, rhs.m_container); + } +}; + +template +general_span_iterator operator+(typename general_span_iterator::difference_type n, + const general_span_iterator& rhs) GSL_NOEXCEPT +{ + return rhs + n; +} + +} // namespace gsl + +#undef GSL_NOEXCEPT + +#ifdef _MSC_VER +#if _MSC_VER < 1910 + +#undef constexpr +#pragma pop_macro("constexpr") +#endif // _MSC_VER < 1910 + +#pragma warning(pop) + +#endif // _MSC_VER + +#endif // GSL_MULTI_SPAN_H diff --git a/src/3rdparty/gsl/pointers b/src/3rdparty/gsl/pointers new file mode 100644 index 00000000..ad15ce30 --- /dev/null +++ b/src/3rdparty/gsl/pointers @@ -0,0 +1,187 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_POINTERS_H +#define GSL_POINTERS_H + +#include // for Ensures, Expects + +#include // for forward +#include // for ptrdiff_t, nullptr_t, ostream, size_t +#include // for shared_ptr, unique_ptr +#include // for hash +#include // for enable_if_t, is_convertible, is_assignable + +#if defined(_MSC_VER) && _MSC_VER < 1910 +#pragma push_macro("constexpr") +#define constexpr /*constexpr*/ + +#endif // defined(_MSC_VER) && _MSC_VER < 1910 + +namespace gsl +{ + +// +// GSL.owner: ownership pointers +// +using std::unique_ptr; +using std::shared_ptr; + +// +// owner +// +// owner is designed as a bridge for code that must deal directly with owning pointers for some reason +// +// T must be a pointer type +// - disallow construction from any type other than pointer type +// +template ::value>> +using owner = T; + +// +// not_null +// +// Restricts a pointer or smart pointer to only hold non-null values. +// +// Has zero size overhead over T. +// +// If T is a pointer (i.e. T == U*) then +// - allow construction from U* +// - disallow construction from nullptr_t +// - disallow default construction +// - ensure construction from null U* fails +// - allow implicit conversion to U* +// +template +class not_null +{ +public: + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); + + template ::value>> + constexpr explicit not_null(U&& u) : ptr_(std::forward(u)) + { + Expects(ptr_ != nullptr); + } + + template ::value>> + constexpr not_null(const not_null& other) : not_null(other.get()) + { + } + + not_null(not_null&& other) = default; + not_null(const not_null& other) = default; + not_null& operator=(const not_null& other) = default; + + constexpr T get() const + { + Ensures(ptr_ != nullptr); + return ptr_; + } + + constexpr operator T() const { return get(); } + constexpr T operator->() const { return get(); } + constexpr decltype(auto) operator*() const { return *get(); } + + // prevents compilation when someone attempts to assign a null pointer constant + not_null(std::nullptr_t) = delete; + not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + not_null& operator++() = delete; + not_null& operator--() = delete; + not_null operator++(int) = delete; + not_null operator--(int) = delete; + not_null& operator+=(std::ptrdiff_t) = delete; + not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; + +private: + T ptr_; +}; + +template +std::ostream& operator<<(std::ostream& os, const not_null& val) +{ + os << val.get(); + return os; +} + +template +auto operator==(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() == rhs.get()) +{ + return lhs.get() == rhs.get(); +} + +template +auto operator!=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() != rhs.get()) +{ + return lhs.get() != rhs.get(); +} + +template +auto operator<(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() < rhs.get()) +{ + return lhs.get() < rhs.get(); +} + +template +auto operator<=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() <= rhs.get()) +{ + return lhs.get() <= rhs.get(); +} + +template +auto operator>(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() > rhs.get()) +{ + return lhs.get() > rhs.get(); +} + +template +auto operator>=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() >= rhs.get()) +{ + return lhs.get() >= rhs.get(); +} + +// more unwanted operators +template +std::ptrdiff_t operator-(const not_null&, const not_null&) = delete; +template +not_null operator-(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(std::ptrdiff_t, const not_null&) = delete; + +} // namespace gsl + +namespace std +{ +template +struct hash> +{ + std::size_t operator()(const gsl::not_null& value) const { return hash{}(value); } +}; + +} // namespace std + +#if defined(_MSC_VER) && _MSC_VER < 1910 +#undef constexpr +#pragma pop_macro("constexpr") + +#endif // defined(_MSC_VER) && _MSC_VER < 1910 + +#endif // GSL_POINTERS_H diff --git a/src/3rdparty/gsl/span b/src/3rdparty/gsl/span new file mode 100644 index 00000000..928a41d6 --- /dev/null +++ b/src/3rdparty/gsl/span @@ -0,0 +1,752 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_SPAN_H +#define GSL_SPAN_H + +#include "gsl_assert" // for Expects +#include "gsl_byte" // for byte +#include "gsl_util" // for narrow_cast, narrow + +#include // for lexicographical_compare +#include // for array +#include // for ptrdiff_t, size_t, nullptr_t +#include // for reverse_iterator, distance, random_access_... +#include +#include +#include // for enable_if_t, declval, is_convertible, inte... +#include + +#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 : 4702) // unreachable code + +// 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) + +#if _MSC_VER < 1910 +#pragma push_macro("constexpr") +#define constexpr /*constexpr*/ +#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND + +#endif // _MSC_VER < 1910 +#else // _MSC_VER + +// See if we have enough C++17 power to use a static constexpr data member +// without needing an out-of-line definition +#if !(defined(__cplusplus) && (__cplusplus >= 201703L)) +#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND +#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L)) + +#endif // _MSC_VER + +namespace gsl +{ + +// [views.constants], constants +constexpr const std::ptrdiff_t dynamic_extent = -1; + +template +class span; + +// implementation details +namespace details +{ + template + struct is_span_oracle : std::false_type + { + }; + + template + struct is_span_oracle> : std::true_type + { + }; + + template + struct is_span : public is_span_oracle> + { + }; + + template + struct is_std_array_oracle : std::false_type + { + }; + + template + struct is_std_array_oracle> : std::true_type + { + }; + + template + struct is_std_array : public is_std_array_oracle> + { + }; + + template + struct is_allowed_extent_conversion + : public std::integral_constant + { + }; + + template + struct is_allowed_element_type_conversion + : public std::integral_constant::value> + { + }; + + template + class span_iterator + { + using element_type_ = typename Span::element_type; + + public: + +#ifdef _MSC_VER + // Tell Microsoft standard library that span_iterators are checked. + using _Unchecked_type = typename Span::pointer; +#endif + + using iterator_category = std::random_access_iterator_tag; + using value_type = std::remove_cv_t; + using difference_type = typename Span::index_type; + + using reference = std::conditional_t&; + using pointer = std::add_pointer_t; + + span_iterator() = default; + + constexpr span_iterator(const Span* span, typename Span::index_type idx) noexcept + : span_(span), index_(idx) + {} + + friend span_iterator; + template* = nullptr> + constexpr span_iterator(const span_iterator& other) noexcept + : span_iterator(other.span_, other.index_) + { + } + + constexpr reference operator*() const + { + Expects(index_ != span_->size()); + return *(span_->data() + index_); + } + + constexpr pointer operator->() const + { + Expects(index_ != span_->size()); + return span_->data() + index_; + } + + constexpr span_iterator& operator++() + { + Expects(0 <= index_ && index_ != span_->size()); + ++index_; + return *this; + } + + constexpr span_iterator operator++(int) + { + auto ret = *this; + ++(*this); + return ret; + } + + constexpr span_iterator& operator--() + { + Expects(index_ != 0 && index_ <= span_->size()); + --index_; + return *this; + } + + constexpr span_iterator operator--(int) + { + auto ret = *this; + --(*this); + return ret; + } + + constexpr span_iterator operator+(difference_type n) const + { + auto ret = *this; + return ret += n; + } + + friend constexpr span_iterator operator+(difference_type n, span_iterator const& rhs) + { + return rhs + n; + } + + constexpr span_iterator& operator+=(difference_type n) + { + Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); + index_ += n; + return *this; + } + + constexpr span_iterator operator-(difference_type n) const + { + auto ret = *this; + return ret -= n; + } + + constexpr span_iterator& operator-=(difference_type n) { return *this += -n; } + + constexpr difference_type operator-(span_iterator rhs) const + { + Expects(span_ == rhs.span_); + return index_ - rhs.index_; + } + + constexpr reference operator[](difference_type n) const + { + return *(*this + n); + } + + constexpr friend bool operator==(span_iterator lhs, + span_iterator rhs) noexcept + { + return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_; + } + + constexpr friend bool operator!=(span_iterator lhs, + span_iterator rhs) noexcept + { + return !(lhs == rhs); + } + + constexpr friend bool operator<(span_iterator lhs, + span_iterator rhs) noexcept + { + return lhs.index_ < rhs.index_; + } + + constexpr friend bool operator<=(span_iterator lhs, + span_iterator rhs) noexcept + { + return !(rhs < lhs); + } + + constexpr friend bool operator>(span_iterator lhs, + span_iterator rhs) noexcept + { + return rhs < lhs; + } + + constexpr friend bool operator>=(span_iterator lhs, + span_iterator rhs) noexcept + { + return !(rhs > lhs); + } + +#ifdef _MSC_VER + // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ + // to unwrap span_iterator to a pointer type after a range check in STL + // algorithm calls + friend constexpr void _Verify_range(span_iterator lhs, + span_iterator rhs) noexcept + { // test that [lhs, rhs) forms a valid range inside an STL algorithm + Expects(lhs.span_ == rhs.span_ // range spans have to match + && lhs.index_ <= rhs.index_); // range must not be transposed + } + + constexpr void _Verify_offset(const difference_type n) const noexcept + { // test that the iterator *this + n is a valid range in an STL + // algorithm call + Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); + } + + constexpr pointer _Unwrapped() const noexcept + { // after seeking *this to a high water mark, or using one of the + // _Verify_xxx functions above, unwrap this span_iterator to a raw + // pointer + return span_->data() + index_; + } + + // Tell the STL that span_iterator should not be unwrapped if it can't + // validate in advance, even in release / optimized builds: +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const bool _Unwrap_when_unverified = false; +#else + static constexpr bool _Unwrap_when_unverified = false; +#endif + constexpr void _Seek_to(const pointer p) noexcept + { // adjust the position of *this to previously verified location p + // after _Unwrapped + index_ = p - span_->data(); + } +#endif + + protected: + const Span* span_ = nullptr; + std::ptrdiff_t index_ = 0; + }; + + template + class extent_type + { + public: + using index_type = std::ptrdiff_t; + + static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size."); + + constexpr extent_type() noexcept {} + + template + constexpr extent_type(extent_type ext) + { + static_assert(Other == Ext || Other == dynamic_extent, + "Mismatch between fixed-size extent and size of initializing data."); + Expects(ext.size() == Ext); + } + + constexpr extent_type(index_type size) { Expects(size == Ext); } + + constexpr index_type size() const noexcept { return Ext; } + }; + + template <> + class extent_type + { + public: + using index_type = std::ptrdiff_t; + + template + explicit constexpr extent_type(extent_type ext) : size_(ext.size()) + { + } + + explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); } + + constexpr index_type size() const noexcept { return size_; } + + private: + index_type size_; + }; + + template + struct calculate_subspan_type + { + using type = span; + }; +} // namespace details + +// [span], class template span +template +class span +{ +public: + // constants and types + using element_type = ElementType; + using value_type = std::remove_cv_t; + using index_type = std::ptrdiff_t; + using pointer = element_type*; + using reference = element_type&; + + using iterator = details::span_iterator, false>; + using const_iterator = details::span_iterator, true>; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + using size_type = index_type; + +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const index_type extent { Extent }; +#else + static constexpr index_type extent { Extent }; +#endif + + // [span.cons], span constructors, copy, assignment, and destructor + template " SFINAE, + // since "std::enable_if_t" is ill-formed when Extent is greater than 0. + class = std::enable_if_t<(Dependent || Extent <= 0)>> + constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) + { + } + + constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {} + + constexpr span(pointer firstElem, pointer lastElem) + : storage_(firstElem, std::distance(firstElem, lastElem)) + { + } + + template + constexpr span(element_type (&arr)[N]) noexcept + : storage_(KnownNotNull{&arr[0]}, details::extent_type()) + { + } + + template > + constexpr span(std::array& arr) noexcept + : storage_(&arr[0], details::extent_type()) + { + } + + template + constexpr span(const std::array, N>& arr) noexcept + : storage_(&arr[0], details::extent_type()) + { + } + + // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement + // on Container to be a contiguous sequence container. + template ::value && !details::is_std_array::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr span(Container& cont) : span(cont.data(), narrow(cont.size())) + { + } + + template ::value && !details::is_span::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr span(const Container& cont) : span(cont.data(), narrow(cont.size())) + { + } + + constexpr span(const span& other) noexcept = default; + + template < + class OtherElementType, std::ptrdiff_t OtherExtent, + class = std::enable_if_t< + details::is_allowed_extent_conversion::value && + details::is_allowed_element_type_conversion::value>> + constexpr span(const span& other) + : storage_(other.data(), details::extent_type(other.size())) + { + } + + ~span() noexcept = default; + constexpr span& operator=(const span& other) noexcept = default; + + // [span.sub], span subviews + template + constexpr span first() const + { + Expects(Count >= 0 && Count <= size()); + return {data(), Count}; + } + + template + constexpr span last() const + { + Expects(Count >= 0 && size() - Count >= 0); + return {data() + (size() - Count), Count}; + } + + template + constexpr auto subspan() const -> typename details::calculate_subspan_type::type + { + Expects((Offset >= 0 && size() - Offset >= 0) && + (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size()))); + + return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; + } + + constexpr span first(index_type count) const + { + Expects(count >= 0 && count <= size()); + return {data(), count}; + } + + constexpr span last(index_type count) const + { + return make_subspan(size() - count, dynamic_extent, subspan_selector{}); + } + + constexpr span subspan(index_type offset, + index_type count = dynamic_extent) const + { + return make_subspan(offset, count, subspan_selector{}); + } + + + // [span.obs], span observers + constexpr index_type size() const noexcept { return storage_.size(); } + constexpr index_type size_bytes() const noexcept + { + return size() * narrow_cast(sizeof(element_type)); + } + constexpr bool empty() const noexcept { return size() == 0; } + + // [span.elem], span element access + constexpr reference operator[](index_type idx) const + { + Expects(idx >= 0 && idx < storage_.size()); + return data()[idx]; + } + + constexpr reference at(index_type idx) const { return this->operator[](idx); } + constexpr reference operator()(index_type idx) const { return this->operator[](idx); } + constexpr pointer data() const noexcept { return storage_.data(); } + + // [span.iter], span iterator support + constexpr iterator begin() const noexcept { return {this, 0}; } + constexpr iterator end() const noexcept { return {this, size()}; } + + constexpr const_iterator cbegin() const noexcept { return {this, 0}; } + constexpr const_iterator cend() const noexcept { return {this, size()}; } + + constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } + constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } + + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } + constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } + +#ifdef _MSC_VER + // Tell MSVC how to unwrap spans in range-based-for + constexpr pointer _Unchecked_begin() const noexcept { return data(); } + constexpr pointer _Unchecked_end() const noexcept { return data() + size(); } +#endif // _MSC_VER + +private: + + // Needed to remove unnecessary null check in subspans + struct KnownNotNull + { + pointer p; + }; + + // this implementation detail class lets us take advantage of the + // empty base class optimization to pay for only storage of a single + // pointer in the case of fixed-size spans + template + class storage_type : public ExtentType + { + public: + // KnownNotNull parameter is needed to remove unnecessary null check + // in subspans and constructors from arrays + template + constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p) + { + Expects(ExtentType::size() >= 0); + } + + + template + constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) + { + Expects(ExtentType::size() >= 0); + Expects(data || ExtentType::size() == 0); + } + + constexpr pointer data() const noexcept { return data_; } + + private: + pointer data_; + }; + + storage_type> storage_; + + // The rest is needed to remove unnecessary null check + // in subspans and constructors from arrays + constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {} + + template + class subspan_selector {}; + + template + span make_subspan(index_type offset, + index_type count, + subspan_selector) const + { + span tmp(*this); + return tmp.subspan(offset, count); + } + + span make_subspan(index_type offset, + index_type count, + subspan_selector) const + { + Expects(offset >= 0 && size() - offset >= 0); + if (count == dynamic_extent) + { + return { KnownNotNull{ data() + offset }, size() - offset }; + } + + Expects(count >= 0 && size() - offset >= count); + return { KnownNotNull{ data() + offset }, count }; + } +}; + +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) +template +constexpr const typename span::index_type span::extent; +#endif + + +// [span.comparison], span comparison operators +template +constexpr bool operator==(span l, + span r) +{ + return std::equal(l.begin(), l.end(), r.begin(), r.end()); +} + +template +constexpr bool operator!=(span l, + span r) +{ + return !(l == r); +} + +template +constexpr bool operator<(span l, + span r) +{ + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +} + +template +constexpr bool operator<=(span l, + span r) +{ + return !(l > r); +} + +template +constexpr bool operator>(span l, + span r) +{ + return r < l; +} + +template +constexpr bool operator>=(span l, + span r) +{ + return !(l < r); +} + +namespace details +{ + // if we only supported compilers with good constexpr support then + // this pair of classes could collapse down to a constexpr function + + // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as + // constexpr + // and so will fail compilation of the template + template + struct calculate_byte_size + : std::integral_constant(sizeof(ElementType) * + static_cast(Extent))> + { + }; + + template + struct calculate_byte_size + : std::integral_constant + { + }; +} + +// [span.objectrep], views of object representation +template +span::value> +as_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template ::value>> +span::value> +as_writeable_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +// +// make_span() - Utility functions for creating spans +// +template +constexpr span make_span(ElementType* ptr, typename span::index_type count) +{ + return span(ptr, count); +} + +template +constexpr span make_span(ElementType* firstElem, ElementType* lastElem) +{ + return span(firstElem, lastElem); +} + +template +constexpr span make_span(ElementType (&arr)[N]) noexcept +{ + return span(arr); +} + +template +constexpr span make_span(Container& cont) +{ + return span(cont); +} + +template +constexpr span make_span(const Container& cont) +{ + return span(cont); +} + +template +constexpr span make_span(Ptr& cont, std::ptrdiff_t count) +{ + return span(cont, count); +} + +template +constexpr span make_span(Ptr& cont) +{ + return span(cont); +} + +// Specialization of gsl::at for span +template +constexpr ElementType& at(span s, index i) +{ + // No bounds checking here because it is done in span::operator[] called below + return s[i]; +} + +} // namespace gsl + +#ifdef _MSC_VER +#if _MSC_VER < 1910 +#undef constexpr +#pragma pop_macro("constexpr") + +#endif // _MSC_VER < 1910 + +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_SPAN_H diff --git a/src/3rdparty/gsl/string_span b/src/3rdparty/gsl/string_span new file mode 100644 index 00000000..c08f2467 --- /dev/null +++ b/src/3rdparty/gsl/string_span @@ -0,0 +1,730 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_STRING_SPAN_H +#define GSL_STRING_SPAN_H + +#include // for Ensures, Expects +#include // for narrow_cast +#include // for operator!=, operator==, dynamic_extent + +#include // for equal, lexicographical_compare +#include // for array +#include // for ptrdiff_t, size_t, nullptr_t +#include // for PTRDIFF_MAX +#include +#include // for basic_string, allocator, char_traits +#include // for declval, is_convertible, enable_if_t, add_... + +#ifdef _MSC_VER +#pragma warning(push) + +// 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) + +#if _MSC_VER < 1910 +#pragma push_macro("constexpr") +#define constexpr /*constexpr*/ + +#endif // _MSC_VER < 1910 +#endif // _MSC_VER + +// In order to test the library, we need it to throw exceptions that we can catch +#ifdef GSL_THROW_ON_CONTRACT_VIOLATION +#define GSL_NOEXCEPT /*noexcept*/ +#else +#define GSL_NOEXCEPT noexcept +#endif // GSL_THROW_ON_CONTRACT_VIOLATION + +namespace gsl +{ +// +// czstring and wzstring +// +// These are "tag" typedefs for C-style strings (i.e. null-terminated character arrays) +// that allow static analysis to help find bugs. +// +// There are no additional features/semantics that we can find a way to add inside the +// type system for these types that will not either incur significant runtime costs or +// (sometimes needlessly) break existing programs when introduced. +// + +template +using basic_zstring = CharT*; + +template +using czstring = basic_zstring; + +template +using cwzstring = basic_zstring; + +template +using cu16zstring = basic_zstring; + +template +using cu32zstring = basic_zstring; + +template +using zstring = basic_zstring; + +template +using wzstring = basic_zstring; + +template +using u16zstring = basic_zstring; + +template +using u32zstring = basic_zstring; + +namespace details +{ + template + std::ptrdiff_t string_length(const CharT* str, std::ptrdiff_t n) + { + if (str == nullptr || n <= 0) return 0; + + const span str_span{str, n}; + + std::ptrdiff_t len = 0; + while (len < n && str_span[len]) len++; + + return len; + } +} + +// +// ensure_sentinel() +// +// Provides a way to obtain an span from a contiguous sequence +// that ends with a (non-inclusive) sentinel value. +// +// Will fail-fast if sentinel cannot be found before max elements are examined. +// +template +span ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX) +{ + auto cur = seq; + while ((cur - seq) < max && *cur != Sentinel) ++cur; + Ensures(*cur == Sentinel); + return {seq, cur - seq}; +} + +// +// ensure_z - creates a span for a zero terminated strings. +// Will fail fast if a null-terminator cannot be found before +// the limit of size_type. +// +template +span ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRDIFF_MAX) +{ + return ensure_sentinel(sz, max); +} + +template +span ensure_z(CharT (&sz)[N]) +{ + return ensure_z(&sz[0], static_cast(N)); +} + +template +span::type, dynamic_extent> +ensure_z(Cont& cont) +{ + return ensure_z(cont.data(), static_cast(cont.size())); +} + +template +class basic_string_span; + +namespace details +{ + template + struct is_basic_string_span_oracle : std::false_type + { + }; + + template + struct is_basic_string_span_oracle> : std::true_type + { + }; + + template + struct is_basic_string_span : is_basic_string_span_oracle> + { + }; +} + +// +// string_span and relatives +// +template +class basic_string_span +{ +public: + using element_type = CharT; + using pointer = std::add_pointer_t; + using reference = std::add_lvalue_reference_t; + using const_reference = std::add_lvalue_reference_t>; + using impl_type = span; + + using index_type = typename impl_type::index_type; + using iterator = typename impl_type::iterator; + using const_iterator = typename impl_type::const_iterator; + using reverse_iterator = typename impl_type::reverse_iterator; + using const_reverse_iterator = typename impl_type::const_reverse_iterator; + + // default (empty) + constexpr basic_string_span() GSL_NOEXCEPT = default; + + // copy + constexpr basic_string_span(const basic_string_span& other) GSL_NOEXCEPT = default; + + // assign + constexpr basic_string_span& operator=(const basic_string_span& other) GSL_NOEXCEPT = default; + + constexpr basic_string_span(pointer ptr, index_type length) : span_(ptr, length) {} + constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {} + + // From static arrays - if 0-terminated, remove 0 from the view + // All other containers allow 0s within the length, so we do not remove them + template + constexpr basic_string_span(element_type (&arr)[N]) : span_(remove_z(arr)) + { + } + + template > + constexpr basic_string_span(std::array& arr) GSL_NOEXCEPT : span_(arr) + { + } + + template > + constexpr basic_string_span(const std::array& arr) GSL_NOEXCEPT + : span_(arr) + { + } + + // Container signature should work for basic_string after C++17 version exists + template + constexpr basic_string_span(std::basic_string& str) + : span_(&str[0], narrow_cast(str.length())) + { + } + + template + constexpr basic_string_span(const std::basic_string& str) + : span_(&str[0], str.length()) + { + } + + // from containers. Containers must have a pointer type and data() function signatures + template ::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr basic_string_span(Container& cont) : span_(cont) + { + } + + template ::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr basic_string_span(const Container& cont) : span_(cont) + { + } + + // from string_span + template < + class OtherValueType, std::ptrdiff_t OtherExtent, + class = std::enable_if_t::impl_type, impl_type>::value>> + constexpr basic_string_span(basic_string_span other) + : span_(other.data(), other.length()) + { + } + + template + constexpr basic_string_span first() const + { + return {span_.template first()}; + } + + constexpr basic_string_span first(index_type count) const + { + return {span_.first(count)}; + } + + template + constexpr basic_string_span last() const + { + return {span_.template last()}; + } + + constexpr basic_string_span last(index_type count) const + { + return {span_.last(count)}; + } + + template + constexpr basic_string_span subspan() const + { + return {span_.template subspan()}; + } + + constexpr basic_string_span + subspan(index_type offset, index_type count = dynamic_extent) const + { + return {span_.subspan(offset, count)}; + } + + constexpr reference operator[](index_type idx) const { return span_[idx]; } + constexpr reference operator()(index_type idx) const { return span_[idx]; } + + constexpr pointer data() const { return span_.data(); } + + constexpr index_type length() const GSL_NOEXCEPT { return span_.size(); } + constexpr index_type size() const GSL_NOEXCEPT { return span_.size(); } + constexpr index_type size_bytes() const GSL_NOEXCEPT { return span_.size_bytes(); } + constexpr index_type length_bytes() const GSL_NOEXCEPT { return span_.length_bytes(); } + constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; } + + constexpr iterator begin() const GSL_NOEXCEPT { return span_.begin(); } + constexpr iterator end() const GSL_NOEXCEPT { return span_.end(); } + + constexpr const_iterator cbegin() const GSL_NOEXCEPT { return span_.cbegin(); } + constexpr const_iterator cend() const GSL_NOEXCEPT { return span_.cend(); } + + constexpr reverse_iterator rbegin() const GSL_NOEXCEPT { return span_.rbegin(); } + constexpr reverse_iterator rend() const GSL_NOEXCEPT { return span_.rend(); } + + constexpr const_reverse_iterator crbegin() const GSL_NOEXCEPT { return span_.crbegin(); } + constexpr const_reverse_iterator crend() const GSL_NOEXCEPT { return span_.crend(); } + +private: + static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) + { + return {sz, details::string_length(sz, max)}; + } + + template + static impl_type remove_z(element_type (&sz)[N]) + { + return remove_z(&sz[0], narrow_cast(N)); + } + + impl_type span_; +}; + +template +using string_span = basic_string_span; + +template +using cstring_span = basic_string_span; + +template +using wstring_span = basic_string_span; + +template +using cwstring_span = basic_string_span; + +template +using u16string_span = basic_string_span; + +template +using cu16string_span = basic_string_span; + +template +using u32string_span = basic_string_span; + +template +using cu32string_span = basic_string_span; + +// +// to_string() allow (explicit) conversions from string_span to string +// + +template +std::basic_string::type> +to_string(basic_string_span view) +{ + return {view.data(), static_cast(view.length())}; +} + +template , + typename Allocator = std::allocator, typename gCharT, std::ptrdiff_t Extent> +std::basic_string to_basic_string(basic_string_span view) +{ + return {view.data(), static_cast(view.length())}; +} + +template +basic_string_span::value> +as_bytes(basic_string_span s) noexcept +{ + return { reinterpret_cast(s.data()), s.size_bytes() }; +} + +template ::value>> +basic_string_span::value> +as_writeable_bytes(basic_string_span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +// zero-terminated string span, used to convert +// zero-terminated spans to legacy strings +template +class basic_zstring_span +{ +public: + using value_type = CharT; + using const_value_type = std::add_const_t; + + using pointer = std::add_pointer_t; + using const_pointer = std::add_pointer_t; + + using zstring_type = basic_zstring; + using const_zstring_type = basic_zstring; + + using impl_type = span; + using string_span_type = basic_string_span; + + constexpr basic_zstring_span(impl_type s) GSL_NOEXCEPT : span_(s) + { + // expects a zero-terminated span + Expects(s[s.size() - 1] == '\0'); + } + + // copy + constexpr basic_zstring_span(const basic_zstring_span& other) = default; + + // move + constexpr basic_zstring_span(basic_zstring_span&& other) = default; + + // assign + constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default; + + // move assign + constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default; + + constexpr bool empty() const GSL_NOEXCEPT { return span_.size() == 0; } + + constexpr string_span_type as_string_span() const GSL_NOEXCEPT + { + auto sz = span_.size(); + return { span_.data(), sz > 1 ? sz - 1 : 0 }; + } + constexpr string_span_type ensure_z() const GSL_NOEXCEPT { return gsl::ensure_z(span_); } + + constexpr const_zstring_type assume_z() const GSL_NOEXCEPT { return span_.data(); } + +private: + impl_type span_; +}; + +template +using zstring_span = basic_zstring_span; + +template +using wzstring_span = basic_zstring_span; + +template +using u16zstring_span = basic_zstring_span; + +template +using u32zstring_span = basic_zstring_span; + +template +using czstring_span = basic_zstring_span; + +template +using cwzstring_span = basic_zstring_span; + +template +using cu16zstring_span = basic_zstring_span; + +template +using cu32zstring_span = basic_zstring_span; + +// operator == +template ::value || + std::is_convertible>>::value>> +bool operator==(const gsl::basic_string_span& one, const T& other) GSL_NOEXCEPT +{ + const gsl::basic_string_span> tmp(other); + return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); +} + +template ::value && + std::is_convertible>>::value>> +bool operator==(const T& one, const gsl::basic_string_span& other) GSL_NOEXCEPT +{ + gsl::basic_string_span> tmp(one); + return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end()); +} + +// operator != +template , Extent>>::value>> +bool operator!=(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return !(one == other); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> +bool operator!=(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return !(one == other); +} + +// operator< +template , Extent>>::value>> +bool operator<(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + const gsl::basic_string_span, Extent> tmp(other); + return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> +bool operator<(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + gsl::basic_string_span, Extent> tmp(one); + return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator<(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + gsl::basic_string_span, Extent> tmp(other); + return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator<(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + gsl::basic_string_span, Extent> tmp(one); + return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); +} +#endif + +// operator <= +template , Extent>>::value>> +bool operator<=(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return !(other < one); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> +bool operator<=(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return !(other < one); +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator<=(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return !(other < one); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator<=(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return !(other < one); +} +#endif + +// operator> +template , Extent>>::value>> +bool operator>(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return other < one; +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> +bool operator>(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return other < one; +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator>(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return other < one; +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator>(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return other < one; +} +#endif + +// operator >= +template , Extent>>::value>> +bool operator>=(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return !(one < other); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> +bool operator>=(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return !(one < other); +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator>=(gsl::basic_string_span one, const T& other) GSL_NOEXCEPT +{ + return !(one < other); +} + +template < + typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> +bool operator>=(const T& one, gsl::basic_string_span other) GSL_NOEXCEPT +{ + return !(one < other); +} +#endif +} // namespace gsl + +#undef GSL_NOEXCEPT + +#ifdef _MSC_VER +#pragma warning(pop) + +#if _MSC_VER < 1910 +#undef constexpr +#pragma pop_macro("constexpr") + +#endif // _MSC_VER < 1910 +#endif // _MSC_VER + +#endif // GSL_STRING_SPAN_H diff --git a/src/app/button_flat.cpp b/src/app/button_flat.cpp new file mode 100644 index 00000000..1c60febb --- /dev/null +++ b/src/app/button_flat.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "button_flat.h" +#include "theme.h" + +#include +#include +#include +#include +#include + +#include + +namespace Mayo { + +ButtonFlat::ButtonFlat(QWidget *parent) + : QWidget(parent), + m_iconSize(16, 16), + m_hoverBrush(mayoTheme()->color(Theme::Color::ButtonFlat_Hover)), + m_checkedBrush(mayoTheme()->color(Theme::Color::ButtonFlat_Checked)) +{ + this->setBackgroundBrush(mayoTheme()->color(Theme::Color::ButtonFlat_Background)); + this->setFixedSize(24, 24); +} + +bool ButtonFlat::isCheckable() const +{ + return m_isCheckable; +} + +void ButtonFlat::setCheckable(bool on) +{ + m_isCheckable = on; +} + +bool ButtonFlat::isChecked() const +{ + return m_isCheckable ? m_isChecked : false; +} + +void ButtonFlat::setChecked(bool on) +{ + if (m_isCheckable) { + if (m_defaultAction != nullptr) + m_defaultAction->setChecked(on); + else + m_isChecked = on; + this->update(); + } +} + +const QIcon &ButtonFlat::icon() const +{ + return m_icon; +} + +void ButtonFlat::setIcon(const QIcon &icon) +{ + m_icon = icon; +} + +const QSize &ButtonFlat::iconSize() const +{ + return m_iconSize; +} + +void ButtonFlat::setIconSize(const QSize &size) +{ + m_iconSize = size; +} + +QAction *ButtonFlat::defaultAction() const +{ + return m_defaultAction; +} + +void ButtonFlat::setDefaultAction(QAction *action) +{ + m_defaultAction = action; + this->syncToAction(); + QObject::connect(action, &QAction::triggered, this, &ButtonFlat::clicked); + QObject::connect(action, &QAction::changed, this, &ButtonFlat::syncToAction); +} + +const QBrush &ButtonFlat::hoverBrush() const +{ + return m_hoverBrush; +} + +void ButtonFlat::setHoverBrush(const QBrush &brush) +{ + m_hoverBrush = brush; + this->update(); +} + +const QBrush &ButtonFlat::checkedBrush() const +{ + return m_checkedBrush; +} + +void ButtonFlat::setCheckedBrush(const QBrush &brush) +{ + m_checkedBrush = brush; + this->update(); +} + +const QBrush &ButtonFlat::backgroundBrush() const +{ + return this->palette().button(); +} + +void ButtonFlat::setBackgroundBrush(const QBrush &brush) +{ + QPalette pal = this->palette(); + pal.setBrush(QPalette::Button, brush); + this->setPalette(pal); +} + +void ButtonFlat::paintEvent(QPaintEvent*) +{ + QPainter painter(this); + const QRect frame = this->frameGeometry(); + const QRect surface(0, 0, frame.width(), frame.height()); + //const QPoint mousePos = this->mapFromGlobal(QCursor::pos()); + const bool isEnabled = this->isEnabled(); + + if (isEnabled && this->isChecked()) + painter.fillRect(surface, m_checkedBrush); + else if (isEnabled && m_isMouseHover) + painter.fillRect(surface, m_hoverBrush); + else + painter.fillRect(surface, this->backgroundBrush()); + const QRect iconRect( + (surface.width() - m_iconSize.width()) / 2, + (surface.height() - m_iconSize.height()) / 2, + m_iconSize.width(), + m_iconSize.height()); + const QIcon::Mode iconMode = isEnabled ? QIcon::Normal : QIcon::Disabled; + m_icon.paint(&painter, iconRect, Qt::AlignCenter, iconMode); +} + +void ButtonFlat::enterEvent(QEvent* event) +{ + m_isMouseHover = true; + this->update(); + QWidget::enterEvent(event); +} + +void ButtonFlat::leaveEvent(QEvent* event) +{ + m_isMouseHover = false; + this->update(); + QWidget::leaveEvent(event); +} + +void ButtonFlat::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (m_defaultAction != nullptr) { + QSignalBlocker sigBlock(this); Q_UNUSED(sigBlock); + m_defaultAction->trigger(); + } + if (m_isCheckable) + this->setChecked(!m_isChecked); + emit clicked(); + } + QWidget::mouseReleaseEvent(event); +} + +void ButtonFlat::syncToAction() +{ + this->setIcon(m_defaultAction->icon()); + this->setToolTip(m_defaultAction->toolTip()); + this->setEnabled(m_defaultAction->isEnabled()); + this->setVisible(m_defaultAction->isVisible()); + this->setChecked(m_defaultAction->isChecked()); + this->setCheckable(m_defaultAction->isCheckable()); +} + +} // namespace Mayo diff --git a/src/app/button_flat.h b/src/app/button_flat.h new file mode 100644 index 00000000..076b9476 --- /dev/null +++ b/src/app/button_flat.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +class QAction; + +namespace Mayo { + +class ButtonFlat : public QWidget { + Q_OBJECT +public: + ButtonFlat(QWidget* parent = nullptr); + + bool isCheckable() const; + void setCheckable(bool on); + + bool isChecked() const; + void setChecked(bool on); + + const QIcon& icon() const; + void setIcon(const QIcon& icon); + + const QSize& iconSize() const; + void setIconSize(const QSize& size); + + QAction* defaultAction() const; + void setDefaultAction(QAction* action); + + const QBrush& hoverBrush() const; + void setHoverBrush(const QBrush& brush); + + const QBrush& checkedBrush() const; + void setCheckedBrush(const QBrush& brush); + + const QBrush& backgroundBrush() const; + void setBackgroundBrush(const QBrush& brush); + +signals: + void clicked(); + +protected: + void paintEvent(QPaintEvent* event) override; + void enterEvent(QEvent* event) override; + void leaveEvent(QEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + +private: + void syncToAction(); + + bool m_isMouseHover = false; + bool m_isCheckable = false; + bool m_isChecked = false; + QIcon m_icon; + QSize m_iconSize; + QBrush m_hoverBrush; + QBrush m_checkedBrush; + QAction* m_defaultAction = nullptr; +}; + +} // namespace Mayo diff --git a/src/app/dialog_about.cpp b/src/app/dialog_about.cpp new file mode 100644 index 00000000..d7b58c6a --- /dev/null +++ b/src/app/dialog_about.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "dialog_about.h" + +#include "ui_dialog_about.h" +#include "version.h" +#include +#ifdef HAVE_GMIO +# include +#endif + +namespace Mayo { + +DialogAbout::DialogAbout(QWidget *parent) + : QDialog(parent), + m_ui(new Ui_DialogAbout) +{ + m_ui->setupUi(this); + m_ui->label_AppByOrg->setText( + tr("%1 By %2").arg(QApplication::applicationName(), + QApplication::organizationName())); + + m_ui->label_Version->setText( + m_ui->label_Version->text().arg(strVersion).arg(QT_POINTER_SIZE * 8)); + m_ui->label_BuildDateTime->setText( + m_ui->label_BuildDateTime->text().arg(__DATE__).arg(__TIME__)); + m_ui->label_Qt->setText(m_ui->label_Qt->text().arg(QT_VERSION_STR)); + m_ui->label_Occ->setText(m_ui->label_Occ->text().arg(OCC_VERSION_COMPLETE)); +#ifdef HAVE_GMIO + m_ui->label_Gmio->setText(m_ui->label_Gmio->text().arg(GMIO_VERSION_STR)); +#else + m_ui->label_Gmio->hide(); +#endif +} + +DialogAbout::~DialogAbout() +{ + delete m_ui; +} + +} // namespace Mayo diff --git a/src/app/dialog_about.h b/src/app/dialog_about.h new file mode 100644 index 00000000..ec262cb8 --- /dev/null +++ b/src/app/dialog_about.h @@ -0,0 +1,23 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include + +namespace Mayo { + +class DialogAbout : public QDialog { + Q_OBJECT +public: + DialogAbout(QWidget *parent = nullptr); + ~DialogAbout(); + +private: + class Ui_DialogAbout* m_ui = nullptr; +}; + +} // namespace Mayo diff --git a/src/dialog_about.ui b/src/app/dialog_about.ui similarity index 70% rename from src/dialog_about.ui rename to src/app/dialog_about.ui index 9b0e2adf..13f1837b 100644 --- a/src/dialog_about.ui +++ b/src/app/dialog_about.ui @@ -6,77 +6,16 @@ 0 0 - 270 - 181 + 288 + 175 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - About + + true + @@ -96,15 +35,15 @@ - :/images/fougue_logo.png + :/images/appicon_64.png - - true + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - + 75 diff --git a/src/dialog_export_options.cpp b/src/app/dialog_export_options.cpp similarity index 83% rename from src/dialog_export_options.cpp rename to src/app/dialog_export_options.cpp index c1d23b6a..aef4956c 100644 --- a/src/dialog_export_options.cpp +++ b/src/app/dialog_export_options.cpp @@ -1,32 +1,10 @@ /**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. +** Copyright (c) 2020, Fougue Ltd. ** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt ****************************************************************************/ +#ifdef HAVE_GMIO #include "dialog_export_options.h" #include "options.h" @@ -205,3 +183,5 @@ void DialogExportOptions::accept() } } // namespace Mayo + +#endif // HAVE_GMIO diff --git a/src/app/dialog_export_options.h b/src/app/dialog_export_options.h new file mode 100644 index 00000000..8862bbe2 --- /dev/null +++ b/src/app/dialog_export_options.h @@ -0,0 +1,35 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/application.h" + +#include + +namespace Mayo { + +#ifdef HAVE_GMIO +class DialogExportOptions : public QDialog { + Q_OBJECT +public: + DialogExportOptions(QWidget *parent = nullptr); + ~DialogExportOptions(); + + Application::PartFormat partFormat() const; + void setPartFormat(Application::PartFormat format); + + Application::ExportOptions currentExportOptions() const; + + void accept() override; + +private: + Application::PartFormat m_partFormat = Application::PartFormat::Unknown; + class Ui_DialogExportOptions* m_ui = nullptr; +}; +#endif + +} // namespace Mayo diff --git a/src/dialog_export_options.ui b/src/app/dialog_export_options.ui similarity index 99% rename from src/dialog_export_options.ui rename to src/app/dialog_export_options.ui index 00a8b3bf..f94eef6a 100644 --- a/src/dialog_export_options.ui +++ b/src/app/dialog_export_options.ui @@ -13,6 +13,9 @@ Export Options + + true + diff --git a/src/app/dialog_inspect_xde.cpp b/src/app/dialog_inspect_xde.cpp new file mode 100644 index 00000000..db69dd40 --- /dev/null +++ b/src/app/dialog_inspect_xde.cpp @@ -0,0 +1,344 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "dialog_inspect_xde.h" + +#include "../base/caf_utils.h" +#include "../base/qmeta_tdf_label.h" +#include "../base/string_utils.h" +#include "settings.h" +#include "settings_keys.h" +#include "ui_dialog_inspect_xde.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace Mayo { + +namespace Internal { + +enum TreeWidgetItemRole { + TreeWidgetItem_TdfLabelRole = Qt::UserRole + 1 +}; + +static const char* rawText(TNaming_Evolution evolution) +{ + switch (evolution) { + case TNaming_PRIMITIVE : return "PRIMITIVE"; + case TNaming_GENERATED : return "GENERATED"; + case TNaming_MODIFY : return "MODIFY"; + case TNaming_DELETE : return "DELETE"; + case TNaming_REPLACE : return "REPLACE"; + case TNaming_SELECTED : return "SELECTED"; + } + return "??"; +} + +static void loadLabelAttributes(const TDF_Label& label, QTreeWidgetItem* treeItem) +{ + for (TDF_AttributeIterator it(label); it.More(); it.Next()) { + const Handle_TDF_Attribute ptrAttr = it.Value(); + const Standard_GUID& attrId = ptrAttr->ID(); + QString text; + QString value; + if (attrId == TDataStd_Name::GetID()) { + const auto& name = static_cast(*ptrAttr); + text = "TDataStd_Name"; + value = occ::QtUtils::toQString(name.Get()); + } +#if 0 + else if (attrId == TDataStd_TreeNode::GetID()) { + const auto& node = static_cast(*ptrAttr); + text = QString("TDataStd_TreeNode [%1]").arg(area.Get()); + } +#endif + else if (attrId == XCAFDoc_Area::GetID()) { + const auto& area = static_cast(*ptrAttr); + text = "XCAFDoc_Area"; + value = StringUtils::text(area.Get(), Settings::instance()->defaultTextOptions()); + } + else if (attrId == XCAFDoc_Centroid::GetID()) { + const auto& centroid = static_cast(*ptrAttr); + text = "XCAFDoc_Centroid"; + value = StringUtils::text(centroid.Get(), Settings::instance()->defaultTextOptions()); + } + else if (attrId == XCAFDoc_Volume::GetID()) { + const auto& volume = static_cast(*ptrAttr); + text = "XCAFDoc_Volume"; + value = StringUtils::text(volume.Get(), Settings::instance()->defaultTextOptions()); + } + else if (attrId == XCAFDoc_Color::GetID()) { + const auto& color = static_cast(*ptrAttr); + text = "XCAFDoc_Color"; + value = StringUtils::text(color.GetColor()); + } + else if (attrId == XCAFDoc_Location::GetID()) { + const auto& location = static_cast(*ptrAttr); + text = "XCAFDoc_Location"; + value = StringUtils::text(location.Get().Transformation(), Settings::instance()->defaultTextOptions()); + } + else if (attrId == TNaming_NamedShape::GetID()) { + const auto& namedShape = static_cast(*ptrAttr); + text = "TNaming_NamedShape"; + value = DialogInspectXde::tr("ShapeType=%1, Evolution=%2") + .arg(StringUtils::rawText(namedShape.Get().ShapeType())) + .arg(rawText(namedShape.Evolution())); + } + else { + std::stringstream sstream; + ptrAttr->Dump(sstream); + QString strDump = QString::fromStdString(sstream.str()); + + int i = 0; + while (i < strDump.size() && strDump.at(i).isSpace()) ++i; + + const int wordStart = i; + while (i < strDump.size() && !strDump.at(i).isSpace()) ++i; + + const int wordEnd = i; + while (i < strDump.size() && strDump.at(i).isSpace()) ++i; + + const int dataStart = i; + text = wordStart < strDump.size() ? + strDump.mid(wordStart, wordEnd - wordStart) : + QStringLiteral("??"); + strDump = strDump.right(strDump.size() - dataStart); + value = strDump.replace(QChar('\n'), QString(" ")); + } + + auto attrTreeItem = new QTreeWidgetItem; + attrTreeItem->setText(0, text); + attrTreeItem->setText(1, value); + treeItem->addChild(attrTreeItem); + } +} + +static QTreeWidgetItem* createOccColorTreeItem( + const QString& text, const Quantity_Color& color) +{ + auto itemColor = new QTreeWidgetItem; + itemColor->setText(0, text); + itemColor->setText(1, StringUtils::text(color)); + QPixmap pixColor(24, 16); + pixColor.fill(occ::QtUtils::toQColor(color)); + itemColor->setIcon(1, pixColor); + return itemColor; +} + +static void loadLabelColorProperties( + const TDF_Label& label, + const Handle_XCAFDoc_ColorTool& colorTool, + QTreeWidgetItem* treeItem) +{ + using ColorProperty = std::tuple; + auto listColorProperty = { + ColorProperty("IsColor", colorTool->IsColor(label)), + ColorProperty("IsSet_ColorGen", colorTool->IsSet(label, XCAFDoc_ColorGen)), + ColorProperty("IsSet_ColorSurf", colorTool->IsSet(label, XCAFDoc_ColorSurf)), + ColorProperty("IsSet_ColorCurv", colorTool->IsSet(label, XCAFDoc_ColorCurv)), + ColorProperty("IsVisible", colorTool->IsVisible(label)) + }; + QList listItemProp; + const QString strYes = DialogInspectXde::tr("Yes"); + const QString strNo = DialogInspectXde::tr("No"); + for (const ColorProperty& prop : listColorProperty) { + auto itemProp = new QTreeWidgetItem; + const bool isPropOn = std::get<1>(prop); + itemProp->setText(0, std::get<0>(prop)); + itemProp->setText(1, isPropOn ? strYes : strNo); + itemProp->setForeground(1, isPropOn ? Qt::green : Qt::red); + listItemProp.push_back(itemProp); + } + + Quantity_Color color; + if (colorTool->GetColor(label, color)) + listItemProp.push_back(createOccColorTreeItem("Color", color)); + + if (colorTool->GetColor(label, XCAFDoc_ColorGen, color)) + listItemProp.push_back(createOccColorTreeItem("Color_ColorGen", color)); + + if (colorTool->GetColor(label, XCAFDoc_ColorSurf, color)) + listItemProp.push_back(createOccColorTreeItem("Color_ColorSurf", color)); + + if (colorTool->GetColor(label, XCAFDoc_ColorCurv, color)) + listItemProp.push_back(createOccColorTreeItem("Color_ColorCurv", color)); + + treeItem->addChildren(listItemProp); +} + +static void loadLabelShapeProperties( + const TDF_Label& label, + const Handle_XCAFDoc_ShapeTool shapeTool, + QTreeWidgetItem* treeItem) +{ + QList listItemProp; + + TopoDS_Shape shape; + if (XCAFDoc_ShapeTool::GetShape(label, shape)) { + auto itemShapeType = new QTreeWidgetItem; + itemShapeType->setText(0, DialogInspectXde::tr("ShapeType")); + const char* cstrShapeType = StringUtils::rawText(shape.ShapeType()); + itemShapeType->setText(1, QString::fromLatin1(cstrShapeType)); + listItemProp.push_back(itemShapeType); + } + + using ShapeProperty = std::tuple; + auto listShapeProperty = { + ShapeProperty("IsShape", XCAFDoc_ShapeTool::IsShape(label)), + ShapeProperty("IsTopLevel", shapeTool->IsTopLevel(label)), + ShapeProperty("IsFree", XCAFDoc_ShapeTool::IsFree(label)), + ShapeProperty("IsAssembly", XCAFDoc_ShapeTool::IsAssembly(label)), + ShapeProperty("IsComponent", XCAFDoc_ShapeTool::IsComponent(label)), + ShapeProperty("IsSimpleShape", XCAFDoc_ShapeTool::IsSimpleShape(label)), + ShapeProperty("IsCompound", XCAFDoc_ShapeTool::IsCompound(label)), + ShapeProperty("IsSubShape", XCAFDoc_ShapeTool::IsSubShape(label)), + ShapeProperty("IsExternRef", XCAFDoc_ShapeTool::IsExternRef(label)), + ShapeProperty("IsReference", XCAFDoc_ShapeTool::IsReference(label)) + }; + const QString strYes = DialogInspectXde::tr("Yes"); + const QString strNo = DialogInspectXde::tr("No"); + for (const ShapeProperty& prop : listShapeProperty) { + auto itemProp = new QTreeWidgetItem; + const bool isPropOn = std::get<1>(prop); + itemProp->setText(0, std::get<0>(prop)); + itemProp->setText(1, isPropOn ? strYes : strNo); + itemProp->setForeground(1, isPropOn ? Qt::green : Qt::red); + listItemProp.push_back(itemProp); + } + + if (XCAFDoc_ShapeTool::IsReference(label)) { + TDF_Label labelRef; + if (XCAFDoc_ShapeTool::GetReferredShape(label, labelRef)) { + auto itemRefShape = new QTreeWidgetItem; + itemRefShape->setText(0, DialogInspectXde::tr("ReferredShape")); + const QString textItemRefShape = + CafUtils::labelTag(labelRef) + + " " + + CafUtils::labelAttrStdName(labelRef); + itemRefShape->setText(1, textItemRefShape); + listItemProp.push_back(itemRefShape); + } + } + + treeItem->addChildren(listItemProp); +} + +static void loadLabel(const TDF_Label &label, QTreeWidgetItem *treeItem) +{ + treeItem->setData(0, TreeWidgetItem_TdfLabelRole, QVariant::fromValue(label)); + treeItem->setText(0, CafUtils::labelTag(label)); + + const QString stdName = CafUtils::labelAttrStdName(label); + if (!stdName.isEmpty()) + treeItem->setText(0, treeItem->text(0) + " " + stdName); +} + +static void deepLoadChildrenLabels( + const TDF_Label &label, QTreeWidgetItem *treeItem) +{ + for (TDF_ChildIterator it(label, Standard_False); it.More(); it.Next()) { + const TDF_Label childLabel = it.Value(); + auto childTreeItem = new QTreeWidgetItem(treeItem); + loadLabel(childLabel, childTreeItem); + deepLoadChildrenLabels(childLabel, childTreeItem); + } +} + +} // namespace Internal + +DialogInspectXde::DialogInspectXde(QWidget *parent) + : QDialog(parent), + m_ui(new Ui_DialogInspectXde) +{ + m_ui->setupUi(this); + QObject::connect( + m_ui->treeWidget_Document, &QTreeWidget::itemClicked, + this, &DialogInspectXde::onLabelTreeWidgetItemClicked); +} + +DialogInspectXde::~DialogInspectXde() +{ + delete m_ui; +} + +void DialogInspectXde::load(const Handle_TDocStd_Document &doc) +{ + m_doc = doc; + if (!XCAFDoc_DocumentTool::IsXCAFDocument(doc)) { + qtgui::QWidgetUtils::asyncMsgBoxCritical( + this, tr("Error"), tr("This document is not suitable for XDE")); + return; + } + + if (!doc.IsNull()) { + const TDF_Label label = doc->Main(); + auto treeItem = new QTreeWidgetItem; + Internal::loadLabel(label, treeItem); + Internal::deepLoadChildrenLabels(label, treeItem); + m_ui->treeWidget_Document->addTopLevelItem(treeItem); + treeItem->setExpanded(true); + } +} + +void DialogInspectXde::onLabelTreeWidgetItemClicked( + QTreeWidgetItem *item, int /*column*/) +{ + const QVariant varLabel = item->data(0, Internal::TreeWidgetItem_TdfLabelRole); + if (varLabel.isValid()) { + m_ui->treeWidget_LabelProps->clear(); + const TDF_Label label = varLabel.value(); + if (label.HasAttribute()) { + auto itemAttrs = new QTreeWidgetItem; + itemAttrs->setText(0, tr("Attributes")); + Internal::loadLabelAttributes(label, itemAttrs); + m_ui->treeWidget_LabelProps->addTopLevelItem(itemAttrs); + } + + if (XCAFDoc_ShapeTool::IsShape(label)) { + const Handle_XCAFDoc_ShapeTool shapeTool = + XCAFDoc_DocumentTool::ShapeTool(m_doc->Main()); + auto itemShapeProps = new QTreeWidgetItem(m_ui->treeWidget_LabelProps); + itemShapeProps->setText(0, tr("Shape specific")); + Internal::loadLabelShapeProperties(label, shapeTool, itemShapeProps); + } + + const Handle_XCAFDoc_ColorTool colorTool = + XCAFDoc_DocumentTool::ColorTool(m_doc->Main()); + if (colorTool->IsColor(label) || XCAFDoc_ShapeTool::IsShape(label)) { + auto itemColorProps = new QTreeWidgetItem(m_ui->treeWidget_LabelProps); + itemColorProps->setText(0, tr("Color specific")); + Internal::loadLabelColorProperties(label, colorTool, itemColorProps); + } + } + + m_ui->treeWidget_LabelProps->expandAll(); + for (int i = 0; i < m_ui->treeWidget_LabelProps->columnCount(); ++i) + m_ui->treeWidget_LabelProps->resizeColumnToContents(i); +} + +} // namespace Mayo diff --git a/src/app/dialog_inspect_xde.h b/src/app/dialog_inspect_xde.h new file mode 100644 index 00000000..32d8614f --- /dev/null +++ b/src/app/dialog_inspect_xde.h @@ -0,0 +1,30 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +class QTreeWidgetItem; + +namespace Mayo { + +class DialogInspectXde : public QDialog { + Q_OBJECT +public: + DialogInspectXde(QWidget *parent = nullptr); + ~DialogInspectXde(); + + void load(const Handle_TDocStd_Document& doc); + +private: + void onLabelTreeWidgetItemClicked(QTreeWidgetItem* item, int column); + + class Ui_DialogInspectXde* m_ui = nullptr; + Handle_TDocStd_Document m_doc; +}; + +} // namespace Mayo diff --git a/src/app/dialog_inspect_xde.ui b/src/app/dialog_inspect_xde.ui new file mode 100644 index 00000000..d8227f9f --- /dev/null +++ b/src/app/dialog_inspect_xde.ui @@ -0,0 +1,108 @@ + + + Mayo::DialogInspectXde + + + + 0 + 0 + 449 + 377 + + + + XDE + + + true + + + + + + Qt::Horizontal + + + + false + + + + 1 + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::NoSelection + + + 2 + + + false + + + + 1 + + + + + 2 + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + Mayo::DialogInspectXde + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Mayo::DialogInspectXde + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/app/dialog_options.cpp b/src/app/dialog_options.cpp new file mode 100644 index 00000000..5ee4c851 --- /dev/null +++ b/src/app/dialog_options.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "dialog_options.h" + +#include "../base/application.h" +#include "../base/property_enumeration.h" +#include "../base/occt_enums.h" +#include "../base/unit_system.h" +#include "settings.h" +#include "settings_keys.h" +#include "ui_dialog_options.h" + +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static QPixmap colorPixmap(const QColor& color) +{ + QPixmap pix(16, 16); + pix.fill(color); + return pix; +} + +} // namespace Internal + +DialogOptions::DialogOptions(QWidget *parent) + : QDialog(parent), + m_ui(new Ui_DialogOptions) +{ + m_ui->setupUi(this); +#ifndef HAVE_GMIO + m_ui->groupBox_StlIo->hide(); + this->adjustSize(); +#endif + + auto settings = Settings::instance(); + + // STL import/export + auto btnGrp_stlIoLib = new QButtonGroup(this); + btnGrp_stlIoLib->addButton(m_ui->radioBtn_UseGmio); + btnGrp_stlIoLib->addButton(m_ui->radioBtn_UseOcc); + + const auto lib = settings->valueAsEnum(Keys::Base_StlIoLibrary); + m_ui->radioBtn_UseGmio->setChecked(lib == Application::StlIoLibrary::Gmio); + m_ui->radioBtn_UseOcc->setChecked(lib == Application::StlIoLibrary::OpenCascade); + + // BRep shape defaults + m_brepShapeDefaultColor = settings->valueAs(Keys::Gpx_BrepShapeDefaultColor); + m_ui->toolBtn_BRepShapeDefaultColor->setIcon(Internal::colorPixmap(m_brepShapeDefaultColor)); + QObject::connect(m_ui->toolBtn_BRepShapeDefaultColor, &QAbstractButton::clicked, [=]{ + const QColor startColor = settings->valueAs(Keys::Gpx_BrepShapeDefaultColor); + this->chooseColor(startColor, [=](QColor color) { + m_ui->toolBtn_BRepShapeDefaultColor->setIcon(Internal::colorPixmap(color)); + m_brepShapeDefaultColor = color; + }); + }); + for (const Enumeration::Item& m : OcctEnums::Graphic3d_NameOfMaterial().items()) + m_ui->comboBox_BRepShapeDefaultMaterial->addItem(m.name, m.value); + m_ui->comboBox_BRepShapeDefaultMaterial->setCurrentIndex( + m_ui->comboBox_BRepShapeDefaultMaterial->findData( + settings->valueAsEnum(Keys::Gpx_BrepShapeDefaultMaterial))); + + // Mesh defaults + m_meshDefaultColor = settings->valueAs(Keys::Gpx_MeshDefaultColor); + m_ui->toolBtn_MeshDefaultColor->setIcon(Internal::colorPixmap(m_meshDefaultColor)); + QObject::connect(m_ui->toolBtn_MeshDefaultColor, &QAbstractButton::clicked, [=]{ + const QColor startColor = settings->valueAs(Keys::Gpx_MeshDefaultColor); + this->chooseColor(startColor, [=](QColor color) { + m_ui->toolBtn_MeshDefaultColor->setIcon(Internal::colorPixmap(color)); + m_meshDefaultColor = color; + }); + }); + for (const Enumeration::Item& m : OcctEnums::Graphic3d_NameOfMaterial().items()) + m_ui->comboBox_MeshDefaultMaterial->addItem(m.name, m.value); + m_ui->comboBox_MeshDefaultMaterial->setCurrentIndex( + m_ui->comboBox_MeshDefaultMaterial->findData( + settings->valueAsEnum(Keys::Gpx_MeshDefaultMaterial))); + m_ui->checkBox_MeshShowEdges->setChecked(settings->valueAs(Keys::Gpx_MeshDefaultShowEdges)); + m_ui->checkBox_MeshShowNodes->setChecked(settings->valueAs(Keys::Gpx_MeshDefaultShowNodes)); + + // Clip planes + m_ui->checkBox_Capping->setChecked(settings->valueAs(Keys::Gui_ClipPlaneCappingOn)); + for (const Enumeration::Item& m : OcctEnums::Aspect_HatchStyle().items()) + m_ui->comboBox_CappingHatch->addItem(m.name, m.value); + m_ui->comboBox_CappingHatch->setCurrentIndex( + m_ui->comboBox_CappingHatch->findData( + settings->valueAsEnum(Keys::Gui_ClipPlaneCappingHatch))); + QObject::connect( + m_ui->checkBox_Capping, &QAbstractButton::clicked, + m_ui->widget_CappingHatch, &QWidget::setEnabled); + m_ui->widget_CappingHatch->setEnabled(m_ui->checkBox_Capping->isChecked()); + + // Units + m_ui->comboBox_UnitSystem->addItem(tr("SI"), UnitSystem::SI); + m_ui->comboBox_UnitSystem->addItem(tr("Imperial UK"), UnitSystem::ImperialUK); + m_ui->comboBox_UnitSystem->setCurrentIndex( + m_ui->comboBox_UnitSystem->findData(settings->unitSystemSchema())); + m_ui->spinBox_Decimals->setValue(settings->unitSystemDecimals()); +} + +DialogOptions::~DialogOptions() +{ + delete m_ui; +} + +void DialogOptions::accept() +{ + auto settings = Settings::instance(); + + // STL import/export + if (m_ui->radioBtn_UseGmio->isChecked()) + settings->setValue(Keys::Base_StlIoLibrary, int(Application::StlIoLibrary::Gmio)); + else if (m_ui->radioBtn_UseOcc->isChecked()) + settings->setValue(Keys::Base_StlIoLibrary, int(Application::StlIoLibrary::OpenCascade)); + + // BRep shape defaults + settings->setValue(Keys::Gpx_BrepShapeDefaultColor, m_brepShapeDefaultColor); + settings->setValue( Keys::Gpx_BrepShapeDefaultMaterial, m_ui->comboBox_BRepShapeDefaultMaterial->currentData()); + + // Mesh defaults + settings->setValue(Keys::Gpx_MeshDefaultColor, m_meshDefaultColor); + settings->setValue(Keys::Gpx_MeshDefaultMaterial, m_ui->comboBox_MeshDefaultMaterial->currentData()); + settings->setValue(Keys::Gpx_MeshDefaultShowEdges, m_ui->checkBox_MeshShowEdges->isChecked()); + settings->setValue(Keys::Gpx_MeshDefaultShowNodes, m_ui->checkBox_MeshShowNodes->isChecked()); + + // Clip planes + settings->setValue(Keys::Gui_ClipPlaneCappingOn, m_ui->checkBox_Capping->isChecked()); + settings->setValue(Keys::Gui_ClipPlaneCappingHatch, m_ui->comboBox_CappingHatch->currentData()); + + // Units + settings->setValue(Keys::Base_UnitSystemSchema, m_ui->comboBox_UnitSystem->currentData()); + settings->setValue(Keys::Base_UnitSystemDecimals, m_ui->spinBox_Decimals->value()); + + QDialog::accept(); +} + +void DialogOptions::chooseColor( + const QColor& currentColor, + const std::function& continuation) +{ + auto dlg = new QColorDialog(this); + dlg->setCurrentColor(currentColor); + QObject::connect(dlg, &QDialog::finished, [=](int result) { + if (result == QDialog::Accepted) + continuation(dlg->selectedColor()); + }); + qtgui::QWidgetUtils::asyncDialogExec(dlg); +} + +} // namespace Mayo diff --git a/src/app/dialog_options.h b/src/app/dialog_options.h new file mode 100644 index 00000000..37f5a456 --- /dev/null +++ b/src/app/dialog_options.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +class DialogOptions : public QDialog { + Q_OBJECT +public: + DialogOptions(QWidget *parent = nullptr); + ~DialogOptions(); + + void accept() override; + +private: + void chooseColor( + const QColor& currentColor, + const std::function& continuation); + + class Ui_DialogOptions* m_ui = nullptr; + QColor m_brepShapeDefaultColor; + QColor m_meshDefaultColor; +}; + +} // namespace Mayo diff --git a/src/dialog_options.ui b/src/app/dialog_options.ui similarity index 76% rename from src/dialog_options.ui rename to src/app/dialog_options.ui index 1b2591e3..ec2e876b 100644 --- a/src/dialog_options.ui +++ b/src/app/dialog_options.ui @@ -6,8 +6,8 @@ 0 0 - 379 - 359 + 191 + 482 @@ -18,6 +18,9 @@ font-weight: bold; } + + true + @@ -44,70 +47,6 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - :/images/widget_pseudo_fold.png - - - - - - - - 1 - 0 - - - - Import to StlMesh_Mesh - - - - - - - - - - :/images/widget_pseudo_fold.png - - - - - - - - 1 - 0 - - - - Import to Poly_Triangulation wrapped in TopoDS_Shape - - - - - - @@ -280,6 +219,110 @@ + + + + Clip planes + + + true + + + + 20 + + + 4 + + + + + Capping + + + true + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Capping hatch + + + + + + + + + + + + + + + + Units + + + true + + + + 20 + + + 0 + + + + + System + + + + + + + + + + Decimals + + + + + + + 1 + + + 12 + + + 2 + + + + + + @@ -309,10 +352,10 @@ groupBox_MeshGpx buttonBox verticalSpacer + groupBox_ClipPlanes + groupBox_Units - - - + buttonBox diff --git a/src/dialog_save_image_view.cpp b/src/app/dialog_save_image_view.cpp similarity index 67% rename from src/dialog_save_image_view.cpp rename to src/app/dialog_save_image_view.cpp index 984723f4..e5b965a9 100644 --- a/src/dialog_save_image_view.cpp +++ b/src/app/dialog_save_image_view.cpp @@ -1,38 +1,14 @@ /**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. +** Copyright (c) 2020, Fougue Ltd. ** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt ****************************************************************************/ #include "dialog_save_image_view.h" - -#include "widget_occ_view.h" #include "ui_dialog_save_image_view.h" -#include "fougtools/qttools/gui/qwidget_utils.h" +#include "../gpx/gpx_utils.h" +#include #include #include #include @@ -48,16 +24,16 @@ namespace Internal { static QImage qtImageTemp(const Image_PixMap& occImg) { const QImage img(occImg.Data(), - occImg.Width(), - occImg.Height(), + static_cast(occImg.Width()), + static_cast(occImg.Height()), static_cast(occImg.SizeRowBytes()), - QImage::Format_ARGB32); + QImage::Format_RGBA8888); return img; } } // namespace Internal -DialogSaveImageView::DialogSaveImageView(const WidgetOccView* view, QWidget *parent) +DialogSaveImageView::DialogSaveImageView(const Handle_V3d_View& view, QWidget *parent) : QDialog(parent), m_ui(new Ui_DialogSaveImageView), m_view(view) @@ -80,8 +56,8 @@ DialogSaveImageView::DialogSaveImageView(const WidgetOccView* view, QWidget *par previewBtn, &QAbstractButton::clicked, this, &DialogSaveImageView::preview); - m_ui->edit_Width->setValue(view->geometry().width()); - m_ui->edit_Height->setValue(view->geometry().height()); + m_ui->edit_Width->setValue(GpxUtils::AspectWindow_width(view->Window())); + m_ui->edit_Height->setValue(GpxUtils::AspectWindow_height(view->Window())); } DialogSaveImageView::~DialogSaveImageView() @@ -115,8 +91,8 @@ void DialogSaveImageView::saveFile() nullptr; Image_PixMap occPix; - bool saveOk = false; - if (saveOk = this->createImageView(&occPix)) { + bool saveOk = this->createImageView(&occPix); + if (saveOk) { const QImage img = Internal::qtImageTemp(occPix); saveOk = img.save(fileName, format); } @@ -159,13 +135,14 @@ void DialogSaveImageView::preview() bool DialogSaveImageView::createImageView(Image_PixMap* img) const { img->SetTopDown(true); - const Standard_Boolean ok = m_view->occV3dView()->ToPixMap( + const bool ok = + m_view->ToPixMap( *img, m_ui->edit_Width->value(), m_ui->edit_Height->value(), Graphic3d_BT_RGBA, m_ui->checkBox_KeepRatio->isChecked()); - return ok == Standard_True; + return ok; } } // namespace Mayo diff --git a/src/app/dialog_save_image_view.h b/src/app/dialog_save_image_view.h new file mode 100644 index 00000000..e405036d --- /dev/null +++ b/src/app/dialog_save_image_view.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +class Image_PixMap; + +namespace Mayo { + +class DialogSaveImageView : public QDialog { + Q_OBJECT +public: + DialogSaveImageView(const Handle_V3d_View& view, QWidget *parent = nullptr); + ~DialogSaveImageView(); + +private: + void saveFile(); + void clipboardCopy(); + void preview(); + + bool createImageView(Image_PixMap* img) const; + + class Ui_DialogSaveImageView* m_ui = nullptr; + Handle_V3d_View m_view; +}; + +} // namespace Mayo diff --git a/src/dialog_save_image_view.ui b/src/app/dialog_save_image_view.ui similarity index 98% rename from src/dialog_save_image_view.ui rename to src/app/dialog_save_image_view.ui index 74a9af07..a0c7ab64 100644 --- a/src/dialog_save_image_view.ui +++ b/src/app/dialog_save_image_view.ui @@ -13,6 +13,9 @@ Save View to Image + + true + diff --git a/src/dialog_task_manager.cpp b/src/app/dialog_task_manager.cpp similarity index 57% rename from src/dialog_task_manager.cpp rename to src/app/dialog_task_manager.cpp index 9693f9b2..e426edd6 100644 --- a/src/dialog_task_manager.cpp +++ b/src/app/dialog_task_manager.cpp @@ -1,38 +1,18 @@ /**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. +** Copyright (c) 2020, Fougue Ltd. ** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt ****************************************************************************/ #include "dialog_task_manager.h" +#include "../base/string_utils.h" +#include "settings.h" #include "ui_dialog_task_manager.h" -#include "fougtools/qttools/task/manager.h" -#include "fougtools/qttools/task/progress.h" +#include "theme.h" +#include +#include #include #include #include @@ -41,12 +21,11 @@ namespace Mayo { -namespace Internal { +// -- +// -- DialogTaskManager::TaskWidget +// -- -static const char TaskWidget_taskIdProp[] = "Mayo::TaskId"; - -class TaskWidget : public QWidget -{ +class DialogTaskManager::TaskWidget : public QWidget { public: TaskWidget(QWidget* parent = nullptr); @@ -58,6 +37,8 @@ class TaskWidget : public QWidget void stopUnboundedProgressTimer(); bool hasUnboundedProgressTimer() const; + static const char TaskIdProp[]; + private: void onUnboundedProgressTimeout(); @@ -65,7 +46,9 @@ class TaskWidget : public QWidget int m_unboundedProgressValue = 0; }; -TaskWidget::TaskWidget(QWidget *parent) +const char DialogTaskManager::TaskWidget::TaskIdProp[] = "Mayo::TaskId"; + +DialogTaskManager::TaskWidget::TaskWidget(QWidget* parent) : QWidget(parent), m_label(new QLabel(this)), m_progress(new QProgressBar(this)), @@ -74,11 +57,9 @@ TaskWidget::TaskWidget(QWidget *parent) QFont labelFont = m_label->font(); labelFont.setBold(true); m_label->setFont(labelFont); - m_progress->setRange(0, 100); m_progress->setValue(0); - - m_interruptBtn->setIcon(QPixmap(":/images/no.png")); + m_interruptBtn->setIcon(mayoTheme()->icon(Theme::Icon::Stop)); m_interruptBtn->setAutoRaise(true); auto progressLayout = new QHBoxLayout; @@ -92,7 +73,7 @@ TaskWidget::TaskWidget(QWidget *parent) this->setLayout(mainLayout); } -void TaskWidget::createUnboundedProgressTimer() +void DialogTaskManager::TaskWidget::createUnboundedProgressTimer() { if (!this->hasUnboundedProgressTimer()) { m_unboundedProgressTimer = new QTimer(this); @@ -103,33 +84,34 @@ void TaskWidget::createUnboundedProgressTimer() } } -void TaskWidget::stopUnboundedProgressTimer() +void DialogTaskManager::TaskWidget::stopUnboundedProgressTimer() { - if (m_unboundedProgressTimer != nullptr) + if (m_unboundedProgressTimer) m_unboundedProgressTimer->stop(); } -bool TaskWidget::hasUnboundedProgressTimer() const +bool DialogTaskManager::TaskWidget::hasUnboundedProgressTimer() const { return m_unboundedProgressTimer != nullptr; } -void TaskWidget::onUnboundedProgressTimeout() +void DialogTaskManager::TaskWidget::onUnboundedProgressTimeout() { m_unboundedProgressValue += 5; m_progress->setValue(m_unboundedProgressValue % 100); } -} // namespace Internal +// -- +// -- DialogTaskManager +// -- -DialogTaskManager::DialogTaskManager(QWidget *parent) +DialogTaskManager::DialogTaskManager(QWidget* parent) : QDialog(parent), m_ui(new Ui_DialogTaskManager) { - this->setWindowFlags( - Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); - m_ui->setupUi(this); + this->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); + this->setWindowModality(Qt::WindowModal); auto taskMgr = qttask::Manager::globalInstance(); QObject::connect( @@ -144,7 +126,6 @@ DialogTaskManager::DialogTaskManager(QWidget *parent) QObject::connect( taskMgr, &qttask::Manager::progressStep, this, &DialogTaskManager::onTaskProgressStep); - this->setWindowModality(Qt::WindowModal); } DialogTaskManager::~DialogTaskManager() @@ -152,50 +133,36 @@ DialogTaskManager::~DialogTaskManager() delete m_ui; } -bool DialogTaskManager::isRunning() const -{ - return m_isRunning; -} - -void DialogTaskManager::execWithTask(quint64 taskId) -{ - m_isRunning = true; - this->onTaskStarted(taskId, QString()); - this->exec(); -} - void DialogTaskManager::onTaskStarted(quint64 taskId, const QString& title) { if (!m_isRunning) this->show(); - auto widget = new Internal::TaskWidget(m_ui->scrollAreaContents); - widget->m_interruptBtn->setProperty(Internal::TaskWidget_taskIdProp, taskId); + auto widget = new TaskWidget(m_ui->scrollAreaContents); + widget->m_interruptBtn->setProperty(TaskWidget::TaskIdProp, taskId); QObject::connect( widget->m_interruptBtn, &QToolButton::clicked, this, &DialogTaskManager::interruptTask); m_ui->contentsLayout->insertWidget(0, widget); m_taskIdToWidget.insert(taskId, widget); - ++m_taskCount; - if (!title.isEmpty()) - this->onTaskProgressStep(taskId, title); + this->onTaskProgressStep(taskId, QString()); } void DialogTaskManager::onTaskEnded(quint64 taskId) { - Internal::TaskWidget* widget = this->taskWidget(taskId); - if (widget != nullptr) { + TaskWidget* widget = this->taskWidget(taskId); + if (widget) { if (widget->hasUnboundedProgressTimer()) widget->stopUnboundedProgressTimer(); + m_ui->contentsLayout->removeWidget(widget); delete widget; m_taskIdToWidget.remove(taskId); } --m_taskCount; - if (m_taskCount == 0) { m_isRunning = false; this->accept(); @@ -204,8 +171,8 @@ void DialogTaskManager::onTaskEnded(quint64 taskId) void DialogTaskManager::onTaskProgress(quint64 taskId, int percent) { - Internal::TaskWidget* widget = this->taskWidget(taskId); - if (widget != nullptr) { + TaskWidget* widget = this->taskWidget(taskId); + if (widget) { if (percent >= 0) { widget->m_progress->setValue(percent); } @@ -218,27 +185,36 @@ void DialogTaskManager::onTaskProgress(quint64 taskId, int percent) void DialogTaskManager::onTaskProgressStep(quint64 taskId, const QString& name) { - Internal::TaskWidget* widget = this->taskWidget(taskId); - if (widget != nullptr) - widget->m_label->setText(name); + const QString taskTitle = qttask::Manager::globalInstance()->taskTitle(taskId); + TaskWidget* widget = this->taskWidget(taskId); + if (widget) { + QString text = taskTitle; + if (!name.isEmpty()) { + if (!text.isEmpty()) + StringUtils::append(&text, tr(" / "), Settings::instance()->locale()); + + StringUtils::append(&text, name, Settings::instance()->locale()); + } + + widget->m_label->setText(text); + } } void DialogTaskManager::interruptTask() { auto interruptBtn = qobject_cast(this->sender()); - if (interruptBtn != nullptr - && interruptBtn->dynamicPropertyNames().contains(Internal::TaskWidget_taskIdProp)) + if (interruptBtn + && interruptBtn->dynamicPropertyNames().contains(TaskWidget::TaskIdProp)) { - const quint64 taskId = - interruptBtn->property(Internal::TaskWidget_taskIdProp).toULongLong(); + const quint64 taskId = interruptBtn->property(TaskWidget::TaskIdProp).toULongLong(); qttask::Manager::globalInstance()->requestAbort(taskId); } } -Internal::TaskWidget *DialogTaskManager::taskWidget(quint64 taskId) +DialogTaskManager::TaskWidget* DialogTaskManager::taskWidget(quint64 taskId) { auto it = m_taskIdToWidget.find(taskId); return it != m_taskIdToWidget.end() ? it.value() : nullptr; } -} // namespace RondPointApp +} // namespace Mayo diff --git a/src/app/dialog_task_manager.h b/src/app/dialog_task_manager.h new file mode 100644 index 00000000..938ebde0 --- /dev/null +++ b/src/app/dialog_task_manager.h @@ -0,0 +1,36 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +class DialogTaskManager : public QDialog { + Q_OBJECT +public: + DialogTaskManager(QWidget* parent = nullptr); + ~DialogTaskManager(); + +private: + class TaskWidget; + TaskWidget* taskWidget(quint64 taskId); + + void onTaskStarted(quint64 taskId, const QString& title); + void onTaskEnded(quint64 taskId); + void onTaskProgress(quint64 taskId, int percent); + void onTaskProgressStep(quint64 taskId, const QString& name); + void interruptTask(); + + class Ui_DialogTaskManager* m_ui = nullptr; + QHash m_taskIdToWidget; + bool m_isRunning = false; + unsigned m_taskCount = 0; +}; + +} // namespace Mayo diff --git a/src/dialog_task_manager.ui b/src/app/dialog_task_manager.ui similarity index 75% rename from src/dialog_task_manager.ui rename to src/app/dialog_task_manager.ui index 457d7ddb..5532ed7f 100644 --- a/src/dialog_task_manager.ui +++ b/src/app/dialog_task_manager.ui @@ -13,7 +13,22 @@ Tasks + + true + + + 0 + + + 0 + + + 0 + + + 0 + @@ -24,8 +39,8 @@ 0 0 - 473 - 191 + 491 + 209 diff --git a/src/app/main.cpp b/src/app/main.cpp new file mode 100644 index 00000000..8fc751bb --- /dev/null +++ b/src/app/main.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "../base/application.h" +#include "../base/unit_system.h" +#include "../gpx/gpx_document_item_factory.h" +#include "../gpx/gpx_mesh_item.h" +#include "../gpx/gpx_xde_document_item.h" +#include "mainwindow.h" +#include "settings.h" +#include "settings_keys.h" +#include "theme.h" +#include "version.h" +#include "widget_model_tree.h" +#include "widget_model_tree_builder_xde.h" +#include "widget_model_tree_builder_mesh.h" + +#include +#include +#include +#include +#include + +namespace Mayo { + +class Main { Q_DECLARE_TR_FUNCTIONS(Main) }; + +struct CommandLineArguments { + QString themeName; + QStringList listFileToOpen; +}; + +static CommandLineArguments processCommandLine() +{ + CommandLineArguments args; + + // Configure command-line parser + QCommandLineParser cmdParser; + cmdParser.setApplicationDescription( + Main::tr("Mayo, an open-source 3D viewer based on Qt5/OpenCascade")); + cmdParser.addHelpOption(); + + const QCommandLineOption cmdOptionTheme( + "theme", + Main::tr("Theme for the UI(classic|dark)"), + Main::tr("name")); + cmdParser.addOption(cmdOptionTheme); + + cmdParser.addPositionalArgument( + Main::tr("files"), + Main::tr("Files to open at startup, optionally"), + Main::tr("[files...]")); + + cmdParser.process(QApplication::arguments()); + + // Retrieve arguments + args.themeName = "dark"; + if (cmdParser.isSet(cmdOptionTheme)) + args.themeName = cmdParser.value(cmdOptionTheme); + args.listFileToOpen = cmdParser.positionalArguments(); + + return args; +} + +static std::unique_ptr globalTheme; + +// Declared in theme.h +Theme* mayoTheme() +{ + return globalTheme.get(); +} + +static int runApp(QApplication* app) +{ + const CommandLineArguments args = processCommandLine(); + Mayo::Application::setOpenCascadeEnvironment("opencascade.conf"); + + // Register Gpx factory functions + GpxDocumentItemFactory::instance()->registerCreatorFunction( + XdeDocumentItem::TypeName, + &GpxDocumentItemFactory::createGpx); + GpxDocumentItemFactory::instance()->registerCreatorFunction( + MeshItem::TypeName, + &GpxDocumentItemFactory::createGpx); + + // Default values + auto settings = Settings::instance(); + settings->setDefaultValue(Keys::App_RecentFiles, QStringList()); + settings->setDefaultValue(Keys::App_MainWindowLastOpenDir, QString()); + settings->setDefaultValue(Keys::App_MainWindowLastSelectedFilter, QString()); + settings->setDefaultValue(Keys::App_MainWindowLinkWithDocumentSelector, false); + settings->setDefaultValue(Keys::Base_StlIoLibrary, static_cast(Application::StlIoLibrary::OpenCascade)); + settings->setDefaultValue(Keys::Base_UnitSystemSchema, UnitSystem::SI); + settings->setDefaultValue(Keys::Base_UnitSystemDecimals, 2); + settings->setDefaultValue(Keys::Gpx_BrepShapeDefaultColor, QColor(Qt::gray)); + settings->setDefaultValue(Keys::Gpx_BrepShapeDefaultMaterial, Graphic3d_NOM_PLASTIC); + settings->setDefaultValue(Keys::Gpx_MeshDefaultColor, QColor(Qt::gray)); + settings->setDefaultValue(Keys::Gpx_MeshDefaultMaterial, Graphic3d_NOM_PLASTIC); + settings->setDefaultValue(Keys::Gpx_MeshDefaultShowEdges, false); + settings->setDefaultValue(Keys::Gpx_MeshDefaultShowNodes, false); + settings->setDefaultValue(Keys::Gui_ClipPlaneCappingHatch, Aspect_HS_SOLID); + settings->setDefaultValue(Keys::Gui_ClipPlaneCappingOn, true); + settings->setDefaultValue(Keys::Gui_DefaultShowOriginTrihedron, true); + + { + auto fnUpdateDefaults = [=]{ + GpxMeshItem::DefaultValues defaults; + defaults.showEdges = settings->valueAs(Keys::Gpx_MeshDefaultShowEdges); + defaults.showNodes = settings->valueAs(Keys::Gpx_MeshDefaultShowNodes); + defaults.color = settings->valueAs(Keys::Gpx_MeshDefaultColor); + defaults.material = settings->valueAsEnum(Keys::Gpx_MeshDefaultMaterial); + GpxMeshItem::setDefaultValues(defaults); + }; + fnUpdateDefaults(); + QObject::connect(Settings::instance(), &Settings::valueChanged, [=](const QString& key) { + if (key == Keys::Gpx_MeshDefaultShowEdges + || key == Keys::Gpx_MeshDefaultShowNodes + || key == Keys::Gpx_MeshDefaultColor + || key == Keys::Gpx_MeshDefaultMaterial) + { + fnUpdateDefaults(); + } + }); + } + + { + auto fnUpdateDefaults = [=]{ + GpxXdeDocumentItem::DefaultValues defaults; + defaults.color = settings->valueAs(Keys::Gpx_BrepShapeDefaultColor); + defaults.material = settings->valueAsEnum(Keys::Gpx_BrepShapeDefaultMaterial); + GpxXdeDocumentItem::setDefaultValues(defaults); + }; + fnUpdateDefaults(); + QObject::connect(Settings::instance(), &Settings::valueChanged, [=](const QString& key) { + if (key == Keys::Gpx_BrepShapeDefaultColor + || key == Keys::Gpx_BrepShapeDefaultMaterial) + { + fnUpdateDefaults(); + } + }); + } + + // Register WidgetModelTreeBuilter prototypes + WidgetModelTree::addPrototypeBuilder(new WidgetModelTreeBuilder_Mesh); + WidgetModelTree::addPrototypeBuilder(new WidgetModelTreeBuilder_Xde); + + // Create theme + globalTheme.reset(createTheme(args.themeName)); + if (!globalTheme) { + const QString errorText = + Main::tr("ERROR: Failed to load theme '%1'").arg(args.themeName); + std::cerr << qUtf8Printable(errorText) << std::endl; + return -1; + } + mayoTheme()->setup(); + + // Create MainWindow + MainWindow mainWindow; + mainWindow.setWindowTitle(QApplication::applicationName()); + mainWindow.show(); + if (!args.listFileToOpen.empty()) { + QTimer::singleShot(0, [&]{ + mainWindow.openDocumentsFromList(args.listFileToOpen); + }); + } + + return app->exec(); +} + +} // namespace Mayo + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + QApplication::setOrganizationName("Fougue Ltd"); + QApplication::setOrganizationDomain("www.fougue.pro"); + QApplication::setApplicationName("Mayo"); + return Mayo::runApp(&app); +} diff --git a/src/app/mainwindow.cpp b/src/app/mainwindow.cpp new file mode 100644 index 00000000..d17fc839 --- /dev/null +++ b/src/app/mainwindow.cpp @@ -0,0 +1,1029 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "mainwindow.h" +#include "ui_mainwindow.h" + +#include "../base/application.h" +#include "../base/application_item_selection_model.h" +#include "../base/document.h" +#include "../base/document_item.h" +#include "../base/xde_document_item.h" +#include "../gpx/gpx_utils.h" +#include "../gui/gui_application.h" +#include "../gui/gui_document.h" +#include "../gui/gui_document_list_model.h" +#include "dialog_about.h" +#include "dialog_export_options.h" +#include "dialog_inspect_xde.h" +#include "dialog_options.h" +#include "dialog_save_image_view.h" +#include "dialog_task_manager.h" +#include "settings.h" +#include "settings_keys.h" +#include "theme.h" +#include "widget_file_system.h" +#include "widget_gui_document.h" +#include "widget_message_indicator.h" +#include "widget_model_tree.h" +#include "widget_occ_view_controller.h" +#include "widget_properties_editor.h" + +#ifdef Q_OS_WIN +# include "windows/win_taskbar_global_progress.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static Application::PartFormat partFormatFromFilter(const QString& filter) +{ + for (Application::PartFormat format : Application::partFormats()) { + if (filter == Application::partFormatFilter(format)) + return format; + } + + return Application::PartFormat::Unknown; +} + +// TODO: move in Options +struct ImportExportSettings { + QString openDir; + QString selectedFilter; + + static ImportExportSettings load() + { + return { + Settings::instance()->valueAs(Keys::App_MainWindowLastOpenDir), + Settings::instance()->valueAs(Keys::App_MainWindowLastSelectedFilter) + }; + } + + static void save(const ImportExportSettings& sets) + { + Settings::instance()->setValue(Keys::App_MainWindowLastOpenDir, sets.openDir); + Settings::instance()->setValue(Keys::App_MainWindowLastSelectedFilter, sets.selectedFilter); + } +}; + +struct OpenFileNames { + QStringList listFilepath; + ImportExportSettings lastIoSettings; + Application::PartFormat selectedFormat; + + enum GetOption { + GetOne, + GetMany + }; + + static OpenFileNames get( + QWidget* parentWidget, + OpenFileNames::GetOption option = OpenFileNames::GetMany) + { + OpenFileNames result; + result.selectedFormat = Application::PartFormat::Unknown; + result.lastIoSettings = ImportExportSettings::load(); + QStringList listPartFormatFilter = Application::partFormatFilters(); + const QString allFilesFilter = Application::tr("All files(*.*)"); + listPartFormatFilter.append(allFilesFilter); + const QString dlgTitle = Application::tr("Select Part File"); + const QString& dlgOpenDir = result.lastIoSettings.openDir; + const QString dlgFilter = listPartFormatFilter.join(QLatin1String(";;")); + QString* dlgPtrSelFilter = &result.lastIoSettings.selectedFilter; + if (option == OpenFileNames::GetOne) { + const QString filepath = + QFileDialog::getOpenFileName( + parentWidget, dlgTitle, dlgOpenDir, dlgFilter, dlgPtrSelFilter); + result.listFilepath.clear(); + result.listFilepath.push_back(filepath); + } + else { + result.listFilepath = + QFileDialog::getOpenFileNames( + parentWidget, dlgTitle, dlgOpenDir, dlgFilter, dlgPtrSelFilter); + } + + if (!result.listFilepath.isEmpty()) { + result.lastIoSettings.openDir = + QFileInfo(result.listFilepath.front()).canonicalPath(); + result.selectedFormat = + result.lastIoSettings.selectedFilter != allFilesFilter ? + partFormatFromFilter(result.lastIoSettings.selectedFilter) : + Application::PartFormat::Unknown; + ImportExportSettings::save(result.lastIoSettings); + } + + return result; + } +}; + +static void msgBoxErrorFileFormat(QWidget* parent, const QString& filepath) +{ + qtgui::QWidgetUtils::asyncMsgBoxCritical( + parent, + MainWindow::tr("Error"), + MainWindow::tr("'%1'\nUnknown file format").arg(filepath)); +} + +static void prependRecentFile(QStringList* listRecentFile, const QString& filepath) +{ + constexpr int sizeLimit = 10; + const QString absFilepath = + QDir::toNativeSeparators(QFileInfo(filepath).absoluteFilePath()); + for (const QString& recentFile : *listRecentFile) { + if (recentFile == absFilepath) + return; + } + + listRecentFile->insert(listRecentFile->begin(), absFilepath); + while (listRecentFile->size() > sizeLimit) + listRecentFile->pop_back(); +} + +} // namespace Internal + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), + m_ui(new Ui_MainWindow), + m_listRecentFile(Settings::instance()->valueAs(Keys::App_RecentFiles)) +{ + m_ui->setupUi(this); + m_ui->widget_ModelTree->loadConfiguration(Settings::instance(), "GUI/MainWindow"); + + m_ui->splitter_Main->setChildrenCollapsible(false); + m_ui->splitter_Main->setStretchFactor(0, 1); + m_ui->splitter_Main->setStretchFactor(1, 3); + + m_ui->splitter_ModelTree->setStretchFactor(0, 1); + m_ui->splitter_ModelTree->setStretchFactor(1, 2); + + m_ui->stack_LeftContents->setCurrentIndex(0); + + m_ui->widget_Properties->setRowHeightFactor(1.4); + m_ui->widget_Properties->clear(); + + m_ui->btn_PreviousGuiDocument->setDefaultAction(m_ui->actionPreviousDoc); + m_ui->btn_NextGuiDocument->setDefaultAction(m_ui->actionNextDoc); + m_ui->btn_CloseGuiDocument->setDefaultAction(m_ui->actionCloseDoc); + + m_ui->actionAboutMayo->setText(tr("About %1").arg(QApplication::applicationName())); + m_ui->actionImport->setIcon(mayoTheme()->icon(Theme::Icon::Import)); + m_ui->actionExportSelectedItems->setIcon(mayoTheme()->icon(Theme::Icon::Export)); + m_ui->actionZoomIn->setIcon(mayoTheme()->icon(Theme::Icon::ZoomIn)); + m_ui->actionZoomOut->setIcon(mayoTheme()->icon(Theme::Icon::ZoomOut)); + m_ui->actionPreviousDoc->setIcon(mayoTheme()->icon(Theme::Icon::Back)); + m_ui->actionNextDoc->setIcon(mayoTheme()->icon(Theme::Icon::Next)); + m_ui->actionCloseDoc->setIcon(mayoTheme()->icon(Theme::Icon::Cross)); + m_ui->actionSaveImageView->setIcon(mayoTheme()->icon(Theme::Icon::Camera)); + m_ui->actionToggleLeftSidebar->setIcon(mayoTheme()->icon(Theme::Icon::LeftSidebar)); + m_ui->btn_CloseLeftSideBar->setIcon(mayoTheme()->icon(Theme::Icon::BackSquare)); + + m_ui->actionToggleLeftSidebar->setChecked(m_ui->widget_Left->isVisible()); + m_ui->actionToggleFullscreen->setChecked(this->isFullScreen()); + m_ui->actionToggleOriginTrihedron->setChecked(false); + + mayoTheme()->setupHeaderComboBox(m_ui->combo_LeftContents); + mayoTheme()->setupHeaderComboBox(m_ui->combo_GuiDocuments); + QString labelMainHomeText = m_ui->label_MainHome->text(); + labelMainHomeText.replace( + QRegularExpression("color:#[0-9a-fA-F]{6,6};"), // ex: color:#0000ff + QString("color:%1;").arg(qApp->palette().color(QPalette::Link).name())); + m_ui->label_MainHome->setText(labelMainHomeText); + + auto sigComboIndexChanged = qOverload(&QComboBox::currentIndexChanged); + // "File" actions + QObject::connect( + m_ui->actionNewDoc, &QAction::triggered, + this, &MainWindow::newDocument); + QObject::connect( + m_ui->actionOpen, &QAction::triggered, + this, &MainWindow::openDocuments); + QObject::connect( + m_ui->actionImport, &QAction::triggered, + this, &MainWindow::importInCurrentDoc); + QObject::connect( + m_ui->actionExportSelectedItems, &QAction::triggered, + this, &MainWindow::exportSelectedItems); + QObject::connect( + m_ui->actionCloseDoc, &QAction::triggered, + this, &MainWindow::closeCurrentDocument); + QObject::connect( + m_ui->actionCloseAllDocuments, &QAction::triggered, + this, &MainWindow::closeAllDocuments); + QObject::connect( + m_ui->actionCloseAllExcept, &QAction::triggered, + this, &MainWindow::closeAllDocumentsExceptCurrent); + QObject::connect( + m_ui->actionQuit, &QAction::triggered, + this, &MainWindow::quitApp); + QObject::connect( + m_ui->label_MainHome, &QLabel::linkActivated, + this, &MainWindow::onHomePageLinkActivated); + QObject::connect( + m_ui->menu_File, &QMenu::aboutToShow, + this, &MainWindow::createMenuRecentFiles); + // "Display" actions + { + auto group = new QActionGroup(m_ui->menu_Projection); + group->setExclusive(true); + group->addAction(m_ui->actionProjectionOrthographic); + group->addAction(m_ui->actionProjectionPerspective); + } + QObject::connect(m_ui->menu_Projection, &QMenu::triggered, this, [=](QAction* action){ + if (this->currentWidgetGuiDocument()) { + const GuiDocument* guiDoc = this->currentWidgetGuiDocument()->guiDocument(); + guiDoc->v3dView()->Camera()->SetProjectionType( + action == m_ui->actionProjectionOrthographic ? + Graphic3d_Camera::Projection_Orthographic : + Graphic3d_Camera::Projection_Perspective); + guiDoc->v3dView()->Update(); + } + }); + QObject::connect( + m_ui->actionToggleOriginTrihedron, &QAction::toggled, + this, &MainWindow::toggleCurrentDocOriginTrihedron); + QObject::connect( + m_ui->actionZoomIn, &QAction::triggered, + this, &MainWindow::zoomInCurrentDoc); + QObject::connect( + m_ui->actionZoomOut, &QAction::triggered, + this, &MainWindow::zoomOutCurrentDoc); + // "Tools" actions + QObject::connect( + m_ui->actionSaveImageView, &QAction::triggered, + this, &MainWindow::saveImageView); + QObject::connect( + m_ui->actionInspectXDE, &QAction::triggered, + this, &MainWindow::inspectXde); + QObject::connect( + m_ui->actionOptions, &QAction::triggered, + this, &MainWindow::editOptions); + // "Help" actions + QObject::connect( + m_ui->actionReportBug, &QAction::triggered, + this, &MainWindow::reportbug); + QObject::connect( + m_ui->actionAboutMayo, &QAction::triggered, + this, &MainWindow::aboutMayo); + // "Window" actions and navigation in documents + QObject::connect( + m_ui->actionToggleFullscreen, &QAction::toggled, + this, &MainWindow::toggleFullscreen); + QObject::connect( + m_ui->actionToggleLeftSidebar, &QAction::toggled, + this, &MainWindow::toggleLeftSidebar); + QObject::connect(m_ui->actionPreviousDoc, &QAction::triggered, [=]{ + this->setCurrentDocumentIndex(this->currentDocumentIndex() - 1); + }); + QObject::connect(m_ui->actionNextDoc, &QAction::triggered, [=]{ + this->setCurrentDocumentIndex(this->currentDocumentIndex() + 1); + }); + QObject::connect( + m_ui->combo_GuiDocuments, sigComboIndexChanged, + this, &MainWindow::currentDocumentIndexChanged); + QObject::connect( + this, &MainWindow::currentDocumentIndexChanged, + this, &MainWindow::onCurrentDocumentIndexChanged); + QObject::connect( + m_ui->widget_FileSystem, &WidgetFileSystem::locationActivated, + this, &MainWindow::onWidgetFileSystemLocationActivated); + // Left header bar of controls + QObject::connect( + m_ui->btn_CloseLeftSideBar, &QAbstractButton::clicked, + this, &MainWindow::toggleLeftSidebar); + // ... + QObject::connect( + m_ui->combo_LeftContents, sigComboIndexChanged, + this, &MainWindow::onLeftContentsPageChanged); + QObject::connect( + GuiApplication::instance(), &GuiApplication::guiDocumentAdded, + this, &MainWindow::onGuiDocumentAdded); + QObject::connect( + GuiApplication::instance()->selectionModel(), + &ApplicationItemSelectionModel::changed, + this, + &MainWindow::onApplicationItemSelectionChanged); + QObject::connect( + m_ui->listView_OpenedDocuments, &QListView::clicked, + [=](const QModelIndex& index) { + this->setCurrentDocumentIndex(index.row()); + }); + QObject::connect( + this, &MainWindow::operationFinished, + this, &MainWindow::onOperationFinished); + + // Creation of annex objects + { + // Opened documents GUI + auto listViewBtns = + new qtgui::ItemViewButtons(m_ui->listView_OpenedDocuments, this); + listViewBtns->addButton( + 1, mayoTheme()->icon(Theme::Icon::Cross), m_ui->actionCloseDoc->toolTip()); + listViewBtns->setButtonDetection(1, -1, QVariant()); + listViewBtns->setButtonDisplayColumn(1, 0); + listViewBtns->setButtonDisplayModes( + 1, qtgui::ItemViewButtons::DisplayOnDetection); + listViewBtns->setButtonItemSide( + 1, qtgui::ItemViewButtons::ItemRightSide); + const int iconSize = this->style()->pixelMetric(QStyle::PM_ListViewIconSize); + listViewBtns->setButtonIconSize(1, QSize(iconSize * 0.66, iconSize * 0.66)); + listViewBtns->installDefaultItemDelegate(); + QObject::connect( + listViewBtns, &qtgui::ItemViewButtons::buttonClicked, + [=](int btnId, const QModelIndex& index) { + if (btnId == 1) + this->closeDocument(index.row()); + }); + } + + new DialogTaskManager(this); + + // BEWARE MainWindow::onGuiDocumentAdded() must be called before + // MainWindow::onCurrentDocumentIndexChanged() + auto guiDocModel = new GuiDocumentListModel(GuiApplication::instance()); + m_ui->combo_GuiDocuments->setModel(guiDocModel); + m_ui->listView_OpenedDocuments->setModel(guiDocModel); + + // Finialize setup + this->setAcceptDrops(true); + m_ui->widget_LeftHeader->installEventFilter(this); + m_ui->widget_ControlGuiDocuments->installEventFilter(this); + m_ui->stack_GuiDocuments->installEventFilter(this); + this->onLeftContentsPageChanged(m_ui->stack_LeftContents->currentIndex()); + this->updateControlsActivation(); + m_ui->widget_MouseCoords->hide(); + + this->onCurrentDocumentIndexChanged(-1); +} + +MainWindow::~MainWindow() +{ + m_ui->widget_ModelTree->saveConfiguration(Settings::instance(), "GUI/MainWindow"); + delete m_ui; + Settings::instance()->setValue(Keys::App_RecentFiles, m_listRecentFile); +} + +bool MainWindow::eventFilter(QObject* watched, QEvent* event) +{ + auto fnSizeBtn = [](const QWidget* container, const QWidget* widgetHeightRef) { + const int btnSideLen = widgetHeightRef->frameGeometry().height(); + const QList listBtn = container->findChildren(); + for (QAbstractButton* btn : listBtn) + btn->setFixedSize(btnSideLen, btnSideLen); + }; + const QEvent::Type eventType = event->type(); + if (watched == m_ui->widget_ControlGuiDocuments && eventType == QEvent::Show) { + fnSizeBtn(m_ui->widget_ControlGuiDocuments, m_ui->combo_GuiDocuments); + return true; + } + + if (watched == m_ui->widget_LeftHeader && eventType == QEvent::Show) { + fnSizeBtn(m_ui->widget_LeftHeader, m_ui->combo_LeftContents); + return true; + } + + if (watched == m_ui->stack_GuiDocuments) { + if (eventType == QEvent::Enter || eventType == QEvent::Leave) { + m_ui->widget_MouseCoords->setHidden(eventType == QEvent::Leave); + return true; + } + } + + return false; +} + +void MainWindow::dragEnterEvent(QDragEnterEvent* event) +{ + if (event->mimeData()->hasUrls()) + event->acceptProposedAction(); +} + +void MainWindow::dropEvent(QDropEvent* event) +{ + const QList listUrl = event->mimeData()->urls(); + QStringList listFilePath; + for (const QUrl& url : listUrl) { + if (url.isLocalFile()) + listFilePath.push_back(url.toLocalFile()); + } + + event->acceptProposedAction(); + this->openDocumentsFromList(listFilePath); +} + +void MainWindow::showEvent(QShowEvent* event) +{ + QMainWindow::showEvent(event); +#ifdef Q_OS_WIN + constexpr Qt::FindChildOption findMode = Qt::FindDirectChildrenOnly; + auto winProgress = this->findChild(QString(), findMode); + if (!winProgress) + winProgress = new WinTaskbarGlobalProgress(this); + winProgress->setWindow(this->windowHandle()); +#endif +} + +void MainWindow::newDocument() +{ + static unsigned docSequenceId = 0; + auto doc = new Document; + doc->setLabel(tr("Anonymous%1").arg(++docSequenceId)); + Application::instance()->addDocument(doc); +} + +void MainWindow::openDocuments() +{ + const auto resFileNames = Internal::OpenFileNames::get(this); + if (!resFileNames.listFilepath.isEmpty()) + this->openDocumentsFromList(resFileNames.listFilepath); +} + +void MainWindow::importInCurrentDoc() +{ + auto widgetGuiDoc = this->currentWidgetGuiDocument(); + if (widgetGuiDoc) { + Document* doc = widgetGuiDoc->guiDocument()->document(); + const auto resFileNames = Internal::OpenFileNames::get(this); + if (!resFileNames.listFilepath.isEmpty()) { + const Application::PartFormat userFormat = resFileNames.selectedFormat; + const bool hasUserFormat = userFormat != Application::PartFormat::Unknown; + for (const QString& filepath : resFileNames.listFilepath) { + const Application::PartFormat fileFormat = + hasUserFormat ? userFormat : Application::findPartFormat(filepath); + if (fileFormat != Application::PartFormat::Unknown) { + this->runImportTask(doc, fileFormat, filepath); + Internal::prependRecentFile(&m_listRecentFile, filepath); + } + else { + Internal::msgBoxErrorFileFormat(this, filepath); + } + } + } + } +} + +void MainWindow::runImportTask( + Document* doc, Application::PartFormat format, const QString& filepath) +{ + auto task = qttask::Manager::globalInstance()->newTask(); + task->setTaskTitle(QFileInfo(filepath).fileName()); + task->run([=]{ + QTime chrono; + chrono.start(); + const Application::IoResult result = + Application::instance()->importInDocument( + doc, format, filepath, &task->progress()); + QString msg; + if (result) { + msg = tr("Import time '%1': %2ms") + .arg(QFileInfo(filepath).fileName()) + .arg(chrono.elapsed()); + } else { + msg = tr("Failed to import part:\n %1\nError: %2") + .arg(filepath, result.errorText()); + } + + emit operationFinished(result.valid(), msg); + }); +} + +void MainWindow::runExportTask( + Span appItems, + Application::PartFormat format, + const Application::ExportOptions& opts, + const QString& filepath) +{ + auto task = qttask::Manager::globalInstance()->newTask(); + task->setTaskTitle(QFileInfo(filepath).fileName()); + task->run([=]{ + QTime chrono; + chrono.start(); + const Application::IoResult result = + Application::instance()->exportApplicationItems( + appItems, format, opts, filepath, &task->progress()); + QString msg; + if (result) { + msg = tr("Export time '%1': %2ms") + .arg(QFileInfo(filepath).fileName()) + .arg(chrono.elapsed()); + } else { + msg = tr("Failed to export part:\n %1\nError: %2") + .arg(filepath).arg(result.errorText()); + } + + emit operationFinished(result.valid(), msg); + }); +} + +void MainWindow::exportSelectedItems() +{ + static const Application::ExportOptions defaultOpts; + auto lastSettings = Internal::ImportExportSettings::load(); + const QString filepath = + QFileDialog::getSaveFileName( + this, + tr("Select Output File"), + lastSettings.openDir, + Application::partFormatFilters().join(QLatin1String(";;")), + &lastSettings.selectedFilter); + if (!filepath.isEmpty()) { + lastSettings.openDir = QFileInfo(filepath).canonicalPath(); + const Application::PartFormat format = + Internal::partFormatFromFilter(lastSettings.selectedFilter); + Span spanAppItem = + GuiApplication::instance()->selectionModel()->selectedItems(); + if (Application::hasExportOptionsForFormat(format)) { +#ifdef HAVE_GMIO + auto dlg = new DialogExportOptions(this); + dlg->setPartFormat(format); + QObject::connect(dlg, &QDialog::accepted, [=]{ + const Application::ExportOptions opts = dlg->currentExportOptions(); + this->runExportTask(vecDocItem, format, opts, filepath); + Internal::ImportExportSettings::save(lastSettings); + }); + qtgui::QWidgetUtils::asyncDialogExec(dlg); +#else + this->runExportTask(spanAppItem, format, defaultOpts, filepath); + Internal::ImportExportSettings::save(lastSettings); +#endif + } + else { + this->runExportTask(spanAppItem, format, defaultOpts, filepath); + Internal::ImportExportSettings::save(lastSettings); + } + } +} + +void MainWindow::quitApp() +{ + QApplication::quit(); +} + +void MainWindow::toggleCurrentDocOriginTrihedron() +{ + WidgetGuiDocument* widget = this->currentWidgetGuiDocument(); + if (widget) { + widget->guiDocument()->toggleOriginTrihedronVisibility(); + widget->guiDocument()->updateV3dViewer(); + } +} + +void MainWindow::zoomInCurrentDoc() +{ + this->currentWidgetGuiDocument()->controller()->zoomIn(); +} + +void MainWindow::zoomOutCurrentDoc() +{ + this->currentWidgetGuiDocument()->controller()->zoomOut(); +} + +void MainWindow::editOptions() +{ + auto dlg = new DialogOptions(this); + qtgui::QWidgetUtils::asyncDialogExec(dlg); +} + +void MainWindow::saveImageView() +{ + auto widgetGuiDoc = this->currentWidgetGuiDocument(); + auto dlg = new DialogSaveImageView(widgetGuiDoc->guiDocument()->v3dView()); + qtgui::QWidgetUtils::asyncDialogExec(dlg); +} + +void MainWindow::inspectXde() +{ + const Span spanAppItem = + GuiApplication::instance()->selectionModel()->selectedItems(); + const XdeDocumentItem* xdeDocItem = nullptr; + for (const ApplicationItem& appItem : spanAppItem) { + xdeDocItem = dynamic_cast(appItem.documentItem()); + if (xdeDocItem) + break; + } + + if (xdeDocItem) { + auto dlg = new DialogInspectXde(this); + dlg->load(xdeDocItem->cafDoc()); + qtgui::QWidgetUtils::asyncDialogExec(dlg); + } +} + +void MainWindow::toggleFullscreen() +{ + if (this->isFullScreen()) { + if (m_previousWindowState.testFlag(Qt::WindowMaximized)) + this->showMaximized(); + else + this->showNormal(); + } + else { + m_previousWindowState = this->windowState(); + this->showFullScreen(); + } +} + +void MainWindow::toggleLeftSidebar() +{ + const bool isVisible = m_ui->widget_Left->isVisible(); + m_ui->widget_Left->setVisible(!isVisible); +} + +void MainWindow::aboutMayo() +{ + auto dlg = new DialogAbout(this); + qtgui::QWidgetUtils::asyncDialogExec(dlg); +} + +void MainWindow::reportbug() +{ + QDesktopServices::openUrl(QUrl(QStringLiteral("https://github.com/fougue/mayo/issues"))); +} + +void MainWindow::onApplicationItemSelectionChanged() +{ + WidgetModelTree* uiModelTree = m_ui->widget_ModelTree; + WidgetPropertiesEditor* uiProps = m_ui->widget_Properties; + + uiProps->clear(); + Span spanAppItem = GuiApplication::instance()->selectionModel()->selectedItems(); + if (spanAppItem.size() == 1) { + const ApplicationItem& item = spanAppItem.at(0); + if (item.isDocumentItemNode()) { + m_ptrCurrentNodeProperties = item.documentItem()->propertiesAtNode(item.documentItemNode().id); + PropertyOwnerSignals* nodeProps = m_ptrCurrentNodeProperties.get(); + uiProps->editProperties(nodeProps); + if (nodeProps) { + QObject::connect(nodeProps, &PropertyOwnerSignals::propertyChanged, [=]{ + uiModelTree->refreshItemText(item); + }); + } + } + else if (item.isDocumentItem()) { + WidgetPropertiesEditor::Group* grpData = uiProps->addGroup(tr("Data")); + uiProps->editProperties(item.documentItem(), grpData); + WidgetPropertiesEditor::Group* grpGpx = uiProps->addGroup(tr("Graphics")); + const GuiDocument* guiDoc = GuiApplication::instance()->findGuiDocument(item.document()); + GpxDocumentItem* gpxDocItem = guiDoc->findItemGpx(item.documentItem()); + uiProps->editProperties(gpxDocItem, grpGpx); + } + else if (item.isDocument()) { + uiProps->editProperties(item.document()); + } + + const bool isLinkWithDocumentSelectorOn = + Settings::instance()->valueAs(Keys::App_MainWindowLinkWithDocumentSelector); + if (isLinkWithDocumentSelectorOn) { + const Document* doc = item.document(); + const int index = Application::instance()->indexOfDocument(doc); + if (index != -1) + this->setCurrentDocumentIndex(index); + } + } + else { + // TODO + uiProps->clear(); + } + + this->updateControlsActivation(); +} + +void MainWindow::onOperationFinished(bool ok, const QString &msg) +{ + if (ok) + WidgetMessageIndicator::showMessage(msg, this); + else + qtgui::QWidgetUtils::asyncMsgBoxCritical(this, tr("Error"), msg); +} + +void MainWindow::onHomePageLinkActivated(const QString &link) +{ + if (link == "NewDocument") + m_ui->actionNewDoc->trigger(); + else if (link == "OpenDocuments") + m_ui->actionOpen->trigger(); +} + +void MainWindow::onGuiDocumentAdded(GuiDocument* guiDoc) +{ + auto widget = new WidgetGuiDocument(guiDoc); + if (Settings::instance()->valueAs(Keys::Gui_DefaultShowOriginTrihedron)) { + guiDoc->toggleOriginTrihedronVisibility(); + guiDoc->updateV3dViewer(); + } + + V3dViewController* ctrl = widget->controller(); + QObject::connect(ctrl, &V3dViewController::mouseMoved, [=](const QPoint& pos2d) { + auto selector = guiDoc->aisInteractiveContext()->MainSelector(); + selector->Pick(pos2d.x(), pos2d.y(), guiDoc->v3dView()); + const gp_Pnt pos3d = + selector->NbPicked() > 0 ? + selector->PickedPoint(1) : + GpxUtils::V3dView_to3dPosition(guiDoc->v3dView(), pos2d.x(), pos2d.y()); + m_ui->label_ValuePosX->setText(QString::number(pos3d.X(), 'f', 3)); + m_ui->label_ValuePosY->setText(QString::number(pos3d.Y(), 'f', 3)); + m_ui->label_ValuePosZ->setText(QString::number(pos3d.Z(), 'f', 3)); + }); + + m_ui->stack_GuiDocuments->addWidget(widget); + this->updateControlsActivation(); + const int newDocIndex = Application::instance()->documentCount() - 1; + QTimer::singleShot(0, [=]{ this->setCurrentDocumentIndex(newDocIndex); }); +} + +void MainWindow::onWidgetFileSystemLocationActivated(const QFileInfo &loc) +{ + this->openDocumentsFromList(QStringList(loc.absoluteFilePath())); +} + +void MainWindow::onLeftContentsPageChanged(int pageId) +{ + m_ui->stack_LeftContents->setCurrentIndex(pageId); + QWidget* placeHolder = this->recreateLeftHeaderPlaceHolder(); + if (m_ui->stack_LeftContents->currentWidget() == m_ui->page_ModelTree && placeHolder) { + const int btnSideLen = m_ui->combo_LeftContents->frameGeometry().height(); + auto btnSettings = new QToolButton(placeHolder); + btnSettings->setAutoRaise(true); + btnSettings->setFixedSize(btnSideLen, btnSideLen); + btnSettings->setIcon(mayoTheme()->icon(Theme::Icon::Gear)); + btnSettings->setToolTip(tr("Options")); + placeHolder->layout()->addWidget(btnSettings); + btnSettings->setMenu(this->createMenuModelTreeSettings()); + btnSettings->setPopupMode(QToolButton::InstantPopup); + } + else { + delete placeHolder; + } +} + +void MainWindow::onCurrentDocumentIndexChanged(int idx) +{ + m_ui->stack_GuiDocuments->setCurrentIndex(idx); + QAbstractItemView* view = m_ui->listView_OpenedDocuments; + view->setCurrentIndex(view->model()->index(idx, 0)); + + this->updateControlsActivation(); + + auto funcFilepathQuoted = [](const QString& filepath) { + for (QChar c : filepath) { + if (c.isSpace()) + return "\"" + filepath + "\""; + } + return filepath; + }; + const Document* doc = Application::instance()->documentAt(idx); + const QString textActionClose = + doc ? + tr("Close %1").arg(funcFilepathQuoted(doc->label())) : + tr("Close"); + const QString textActionCloseAllExcept = + doc ? + tr("Close all except %1").arg(funcFilepathQuoted(doc->label())) : + tr("Close all except current"); + const QString docFilePath = + doc ? doc->filePath() : QString(); + m_ui->actionCloseDoc->setText(textActionClose); + m_ui->actionCloseAllExcept->setText(textActionCloseAllExcept); + m_ui->widget_FileSystem->setLocation(docFilePath); + + if (this->currentWidgetGuiDocument()) { + const GuiDocument* guiDoc = this->currentWidgetGuiDocument()->guiDocument(); + // Sync action with current visibility status of origin trihedron + { + QSignalBlocker sigBlk(m_ui->actionToggleOriginTrihedron); Q_UNUSED(sigBlk); + m_ui->actionToggleOriginTrihedron->setChecked(guiDoc->isOriginTrihedronVisible()); + } + // Sync menu with current projection type + { + const Graphic3d_Camera::Projection viewProjectionType = + guiDoc->v3dView()->Camera()->ProjectionType(); + Q_ASSERT(viewProjectionType == Graphic3d_Camera::Projection_Perspective + || viewProjectionType == Graphic3d_Camera::Projection_Orthographic); + QAction* actionProjection = + viewProjectionType == Graphic3d_Camera::Projection_Perspective ? + m_ui->actionProjectionPerspective : + m_ui->actionProjectionOrthographic; + QSignalBlocker sigBlk(m_ui->menu_Projection); Q_UNUSED(sigBlk); + actionProjection->setChecked(true); + } + } + else { + m_ui->actionToggleOriginTrihedron->setChecked(false); + } + } + +void MainWindow::closeCurrentDocument() +{ + this->closeDocument(this->currentDocumentIndex()); +} + +void MainWindow::closeDocument(WidgetGuiDocument *widget) +{ + if (widget) { + Document* doc = widget->guiDocument()->document(); + m_ui->stack_GuiDocuments->removeWidget(widget); + widget->deleteLater(); + Application::instance()->eraseDocument(doc); + this->updateControlsActivation(); + } +} + +void MainWindow::closeDocument(int docIndex) +{ + if (0 <= docIndex && docIndex < m_ui->stack_GuiDocuments->count()) + this->closeDocument(this->widgetGuiDocument(docIndex)); +} + +void MainWindow::closeAllDocumentsExceptCurrent() +{ + WidgetGuiDocument* current = this->currentWidgetGuiDocument(); + std::vector vecWidget; + for (int i = 0; i < m_ui->stack_GuiDocuments->count(); ++i) + vecWidget.push_back(this->widgetGuiDocument(i)); + + for (WidgetGuiDocument* widget : vecWidget) { + if (widget != current) + this->closeDocument(widget); + } +} + +void MainWindow::closeAllDocuments() +{ + while (m_ui->stack_GuiDocuments->count() > 0) + this->closeCurrentDocument(); +} + +void MainWindow::openDocumentsFromList(const QStringList& listFilePath) +{ + auto app = Application::instance(); + for (const QString& filePath : listFilePath) { + const QFileInfo loc(filePath); + const int docId = app->findDocumentByLocation(loc); + if (docId == -1) { + const QString locAbsoluteFilePath = QDir::toNativeSeparators(loc.absoluteFilePath()); + const Application::PartFormat fileFormat = Application::findPartFormat(locAbsoluteFilePath); + if (fileFormat != Application::PartFormat::Unknown) { + auto doc = new Document; + doc->setLabel(loc.fileName()); + doc->setFilePath(locAbsoluteFilePath); + app->addDocument(doc); + this->runImportTask(doc, fileFormat, locAbsoluteFilePath); + Internal::prependRecentFile(&m_listRecentFile, locAbsoluteFilePath); + } + else { + Internal::msgBoxErrorFileFormat(this, locAbsoluteFilePath); + } + } + else { + if (listFilePath.size() == 1) + this->setCurrentDocumentIndex(docId); + } + } +} + +void MainWindow::updateControlsActivation() +{ + const QWidget* currMainPage = m_ui->stack_Main->currentWidget(); + const int appDocumentsCount = Application::instance()->documentCount(); + const bool appDocumentsEmpty = appDocumentsCount == 0; + QWidget* newMainPage = appDocumentsEmpty ? m_ui->page_MainHome : m_ui->page_MainControl; + if (currMainPage != newMainPage) + m_ui->stack_Main->setCurrentWidget(newMainPage); + + m_ui->actionImport->setEnabled(!appDocumentsEmpty); + m_ui->menu_Projection->setEnabled(!appDocumentsEmpty); + m_ui->actionProjectionOrthographic->setEnabled(!appDocumentsEmpty); + m_ui->actionProjectionPerspective->setEnabled(!appDocumentsEmpty); + m_ui->actionToggleOriginTrihedron->setEnabled(!appDocumentsEmpty); + m_ui->actionZoomIn->setEnabled(!appDocumentsEmpty); + m_ui->actionZoomOut->setEnabled(!appDocumentsEmpty); + m_ui->actionSaveImageView->setEnabled(!appDocumentsEmpty); + m_ui->actionCloseDoc->setEnabled(!appDocumentsEmpty); + m_ui->actionCloseAllDocuments->setEnabled(!appDocumentsEmpty); + m_ui->actionCloseAllExcept->setEnabled(!appDocumentsEmpty); + const int currentDocIndex = this->currentDocumentIndex(); + m_ui->actionPreviousDoc->setEnabled(!appDocumentsEmpty && currentDocIndex > 0); + m_ui->actionNextDoc->setEnabled(!appDocumentsEmpty && currentDocIndex < appDocumentsCount - 1); + m_ui->actionExportSelectedItems->setEnabled(!appDocumentsEmpty); + m_ui->actionToggleLeftSidebar->setEnabled(newMainPage != m_ui->page_MainHome); + m_ui->combo_GuiDocuments->setEnabled(!appDocumentsEmpty); + + Span spanSelectedAppItem = + GuiApplication::instance()->selectionModel()->selectedItems(); + const ApplicationItem firstAppItem = + !spanSelectedAppItem.empty() ? + spanSelectedAppItem.at(0) : ApplicationItem(); + m_ui->actionInspectXDE->setEnabled( + spanSelectedAppItem.size() == 1 + && sameType(firstAppItem.documentItem())); +} + +int MainWindow::currentDocumentIndex() const +{ + return m_ui->combo_GuiDocuments->currentIndex(); +} + +void MainWindow::setCurrentDocumentIndex(int idx) +{ + m_ui->combo_GuiDocuments->setCurrentIndex(idx); +} + +WidgetGuiDocument* MainWindow::widgetGuiDocument(int idx) const +{ + return qobject_cast(m_ui->stack_GuiDocuments->widget(idx)); +} + +WidgetGuiDocument* MainWindow::currentWidgetGuiDocument() const +{ + return this->widgetGuiDocument(this->currentDocumentIndex()); +} + +QWidget* MainWindow::findLeftHeaderPlaceHolder() const +{ + return m_ui->widget_LeftHeader->findChild( + "LeftHeaderPlaceHolder", Qt::FindDirectChildrenOnly); +} + +QWidget* MainWindow::recreateLeftHeaderPlaceHolder() +{ + QWidget* placeHolder = this->findLeftHeaderPlaceHolder(); + delete placeHolder; + placeHolder = new QWidget(m_ui->widget_LeftHeader); + placeHolder->setObjectName("LeftHeaderPlaceHolder"); + auto layoutPlaceHolder = new QHBoxLayout(placeHolder); + layoutPlaceHolder->setContentsMargins(0, 0, 0, 0); + layoutPlaceHolder->setSpacing(0); + m_ui->Layout_WidgetLeftHeader->insertWidget(2, placeHolder); + return placeHolder; +} + +QMenu* MainWindow::createMenuModelTreeSettings() +{ + auto menu = new QMenu(this->findLeftHeaderPlaceHolder()); + menu->setToolTipsVisible(true); + + { // Link with document selector + auto settings = Settings::instance(); + const bool isLinked = settings->valueAs(Keys::App_MainWindowLinkWithDocumentSelector); + QAction* action = menu->addAction(tr("Link With Document Selector")); + action->setCheckable(true); + action->setChecked(isLinked); + QObject::connect(action, &QAction::triggered, [=](bool on) { + settings->setValue(Keys::App_MainWindowLinkWithDocumentSelector, on); + }); + } + + menu->addSeparator(); + const std::vector vecAction = m_ui->widget_ModelTree->createConfigurationActions(menu); + for (QAction* action : vecAction) + menu->addAction(action); + + return menu; +} + +QMenu* MainWindow::createMenuRecentFiles() +{ + QMenu* menu = m_ui->actionRecentFiles->menu(); + if (!menu) + menu = new QMenu(this); + + menu->clear(); + int idFile = 0; + for (const QString& file : m_listRecentFile) { + const QString entryRecentFile = tr("%1 | %2").arg(++idFile).arg(file); + menu->addAction(entryRecentFile, [=]{ this->openDocumentsFromList(QStringList(file)); }); + } + + if (!m_listRecentFile.empty()) { + menu->addSeparator(); + menu->addAction(tr("Clear menu"), [=]{ + menu->clear(); + m_listRecentFile.clear(); + }); + } + + m_ui->actionRecentFiles->setMenu(menu); + return menu; +} + +} // namespace Mayo diff --git a/src/app/mainwindow.h b/src/app/mainwindow.h new file mode 100644 index 00000000..37fe81da --- /dev/null +++ b/src/app/mainwindow.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/application.h" +#include "../base/application_item.h" +#include "../base/application_item_selection_model.h" +#include +#include +class QFileInfo; + +namespace Mayo { + +class Document; +class GuiDocument; +class WidgetGuiDocument; + +class MainWindow : public QMainWindow { + Q_OBJECT +public: + MainWindow(QWidget* parent = nullptr); + ~MainWindow(); + + void openDocumentsFromList(const QStringList& listFilePath); + + bool eventFilter(QObject* watched, QEvent* event) override; + +signals: + void operationFinished(bool ok, const QString& msg); + void currentDocumentIndexChanged(int docIdx); + +protected: + void dragEnterEvent(QDragEnterEvent* event) override; + void dropEvent(QDropEvent* event) override; + void showEvent(QShowEvent* event) override; + +private: + void newDocument(); + void openDocuments(); + void importInCurrentDoc(); + void exportSelectedItems(); + void quitApp(); + void toggleCurrentDocOriginTrihedron(); + void zoomInCurrentDoc(); + void zoomOutCurrentDoc(); + void editOptions(); + void saveImageView(); + void inspectXde(); + void toggleFullscreen(); + void toggleLeftSidebar(); + void aboutMayo(); + void reportbug(); + + void onApplicationItemSelectionChanged(); + void onOperationFinished(bool ok, const QString& msg); + void onHomePageLinkActivated(const QString& link); + void onGuiDocumentAdded(GuiDocument* guiDoc); + void onWidgetFileSystemLocationActivated(const QFileInfo& loc); + void onLeftContentsPageChanged(int pageId); + void onCurrentDocumentIndexChanged(int idx); + + void closeCurrentDocument(); + void closeDocument(WidgetGuiDocument* widget); + void closeDocument(int docIndex); + void closeAllDocumentsExceptCurrent(); + void closeAllDocuments(); + + void runImportTask( + Document* doc, + Application::PartFormat format, + const QString& filepath); + void runExportTask( + Span appItems, + Application::PartFormat format, + const Application::ExportOptions& opts, + const QString& filepath); + + void updateControlsActivation(); + + int currentDocumentIndex() const; + void setCurrentDocumentIndex(int idx); + + WidgetGuiDocument* widgetGuiDocument(int idx) const; + WidgetGuiDocument* currentWidgetGuiDocument() const; + QWidget* findLeftHeaderPlaceHolder() const; + QWidget* recreateLeftHeaderPlaceHolder(); + QMenu* createMenuModelTreeSettings(); + QMenu* createMenuRecentFiles(); + + class Ui_MainWindow* m_ui = nullptr; + Qt::WindowStates m_previousWindowState = Qt::WindowNoState; + QStringList m_listRecentFile; + std::unique_ptr m_ptrCurrentNodeProperties; +}; + +} // namespace Mayo diff --git a/src/app/mainwindow.ui b/src/app/mainwindow.ui new file mode 100644 index 00000000..5389587d --- /dev/null +++ b/src/app/mainwindow.ui @@ -0,0 +1,830 @@ + + + Mayo::MainWindow + + + + 0 + 0 + 764 + 572 + + + + Mayo + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + + + 20 + + + + + + 20 + + + + + + + + :/images/appicon_128.png + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + <html><head/><body><p><span style=" font-size:10pt;">You can create a </span><a href="NewDocument"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">New Document</span></a></p><p><span style=" font-size:10pt;">or </span><a href="OpenDocuments"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Open Existing Documents</span></a></p></body></html> + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + false + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 1 + + + 0 + + + 0 + + + 4 + + + 0 + + + + + + 1 + 0 + + + + + 0 + 22 + + + + + Model tree + + + + + Opened documents + + + + + File system + + + + + + + + QFrame::Plain + + + Qt::Vertical + + + + + + + Close Left Side Bar + + + + :/images/themes/classic/left-arrow-cross_16.png:/images/themes/classic/left-arrow-cross_16.png + + + true + + + + + + + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + + 0 + 1 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + Qt::ElideMiddle + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + 0 + + + 1 + + + 0 + + + 0 + + + 1 + + + + + + 1 + + + 2 + + + 0 + + + 0 + + + 0 + + + + + + :/images/themes/classic/back_32.png:/images/themes/classic/back_32.png + + + + 12 + 12 + + + + true + + + + + + + + :/images/themes/classic/next_32.png:/images/themes/classic/next_32.png + + + + 12 + 12 + + + + true + + + + + + + + 0 + 22 + + + + QComboBox::AdjustToContents + + + + + + + QFrame::Plain + + + Qt::Vertical + + + + + + + + :/images/themes/classic/cross_32.png:/images/themes/classic/cross_32.png + + + + 12 + 12 + + + + true + + + + + + + QFrame::Plain + + + Qt::Vertical + + + + + + + + 1 + 0 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + X= + + + + + + + ? + + + + + + + + + 0 + + + + + Y= + + + + + + + ? + + + + + + + + + 0 + + + + + Z= + + + + + + + ? + + + + + + + + + + + + + + + + 2 + 0 + + + + + + + + + + + + + + + + + + 0 + 0 + 764 + 21 + + + + + &File + + + + + + + + + + + + + + + + + &Help + + + + + + + + &Tools + + + + + + + + + &Window + + + + + + + + + + &Display + + + + Projection + + + + + + + + + + + + + + + + + + + New + + + Ctrl+N + + + + + Import + + + + + Quit + + + + + Open + + + Ctrl+O + + + + + About Mayo + + + + + Report Bug + + + + + Options + + + + + + :/images/themes/classic/camera_32.png:/images/themes/classic/camera_32.png + + + Save View to Image + + + + + Export selected items + + + + + Inspect XDE + + + + + + :/images/previous.png:/images/previous.png + + + Previous Document + + + Previous Document + + + Alt+Left + + + + + + :/images/next.png:/images/next.png + + + Next Document + + + Next Document + + + Alt+Right + + + + + + :/images/close.png:/images/close.png + + + Close "%1" + + + Ctrl+W + + + + + true + + + Fullscreen + + + Switch Fullscreen/Normal + + + F11 + + + + + true + + + + :/images/themes/classic/left-sidebar_32.png:/images/themes/classic/left-sidebar_32.png + + + Show Left Sidebar + + + Show/Hide Left Sidebar + + + Alt+0 + + + + + Recent files + + + + + true + + + Show Origin Trihedron + + + Show/Hide Origin Trihedron + + + + + Zoom In + + + Ctrl++ + + + + + Zoom Out + + + Ctrl+- + + + + + Close all + + + Ctrl+Shift+W + + + + + Close all except "%1" + + + + + true + + + Perspective + + + + + true + + + Orthographic + + + + + + + WidgetModelTree + QWidget +
widget_model_tree.h
+ 1 +
+ + WidgetFileSystem + QWidget +
widget_file_system.h
+ 1 +
+ + WidgetPropertiesEditor + QWidget +
widget_properties_editor.h
+ 1 +
+
+ + +
diff --git a/src/occt_window.cpp b/src/app/occt_window.cpp similarity index 96% rename from src/occt_window.cpp rename to src/app/occt_window.cpp index 26630d31..6c54d7f2 100644 --- a/src/occt_window.cpp +++ b/src/app/occt_window.cpp @@ -1,3 +1,4 @@ +// Excerpted from $OCC/samples/qt/Common/src #include "occt_window.h" IMPLEMENT_STANDARD_RTTIEXT(OcctWindow,Aspect_Window) @@ -7,7 +8,7 @@ IMPLEMENT_STANDARD_RTTIEXT(OcctWindow,Aspect_Window) // purpose : // ======================================================================= OcctWindow::OcctWindow ( QWidget* theWidget, const Quantity_NameOfColor theBackColor ) -: Aspect_Window(), +: Aspect_Window(), myWidget( theWidget ) { SetBackground (theBackColor); @@ -139,10 +140,10 @@ Aspect_TypeOfResize OcctWindow::DoResize() const // function : Ratio // purpose : // ======================================================================= -Quantity_Ratio OcctWindow::Ratio() const +Standard_Real OcctWindow::Ratio() const { QRect aRect = myWidget->rect(); - return Quantity_Ratio( aRect.right() - aRect.left() ) / Quantity_Ratio( aRect.bottom() - aRect.top() ); + return Standard_Real( aRect.right() - aRect.left() ) / Standard_Real( aRect.bottom() - aRect.top() ); } // ======================================================================= diff --git a/src/occt_window.h b/src/app/occt_window.h similarity index 90% rename from src/occt_window.h rename to src/app/occt_window.h index ce3941a0..6fe4b706 100644 --- a/src/occt_window.h +++ b/src/app/occt_window.h @@ -1,34 +1,35 @@ +// Excerpted from $OCC/samples/qt/Common/src #pragma once #include -#include #include +class OcctWindow; /* - OcctWindow class implements Aspect_Window interface using Qt API - as a platform-independent source of window geometry information. - A similar class should be used instead of platform-specific OCCT - classes (WNT_Window, Xw_Window) in any Qt 5 application using OCCT + OcctWindow class implements Aspect_Window interface using Qt API + as a platform-independent source of window geometry information. + A similar class should be used instead of platform-specific OCCT + classes (WNT_Window, Xw_Window) in any Qt 5 application using OCCT 3D visualization. - With Qt 5, the requirement for a Qt-based application to rely fully - on Qt public API and stop using platform-specific APIs looks mandatory. - An example of this is changed QWidget event sequence: when a widget is - first shown on the screen, a resize event is generated before the + With Qt 5, the requirement for a Qt-based application to rely fully + on Qt public API and stop using platform-specific APIs looks mandatory. + An example of this is changed QWidget event sequence: when a widget is + first shown on the screen, a resize event is generated before the underlying native window is resized correctly, however the QWidget instance - already holds correct size information at that moment. The OCCT classes - acting as a source of window geometry for V3d_View class (WNT_Window, Xw_Window) - are no longer compatible with changed Qt behavior because they rely on - platform-specific API that cannot return correct window geometry information - in some cases. A reasonable solution is to provide a Qt-based implementation + already holds correct size information at that moment. The OCCT classes + acting as a source of window geometry for V3d_View class (WNT_Window, Xw_Window) + are no longer compatible with changed Qt behavior because they rely on + platform-specific API that cannot return correct window geometry information + in some cases. A reasonable solution is to provide a Qt-based implementation of Aspect_Window interface at application level. */ class OcctWindow : public Aspect_Window { public: - + //! Constructor OcctWindow( QWidget* theWidget, const Quantity_NameOfColor theBackColor = Quantity_NOC_MATRAGRAY ); @@ -59,7 +60,7 @@ class OcctWindow : public Aspect_Window //! Opens the window . virtual void Map() const; - + //! Closes the window . virtual void Unmap() const; @@ -68,13 +69,11 @@ class OcctWindow : public Aspect_Window //! Returns The Window RATIO equal to the physical //! WIDTH/HEIGHT dimensions. - virtual Quantity_Ratio Ratio() const; + virtual Standard_Real Ratio() const; virtual void Size( Standard_Integer& theWidth, Standard_Integer& theHeight ) const; -#if OCC_VERSION_HEX >= 0x070000 virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return NULL; } -#endif DEFINE_STANDARD_RTTIEXT(OcctWindow,Aspect_Window) @@ -85,5 +84,3 @@ class OcctWindow : public Aspect_Window Standard_Integer myYBottom; QWidget* myWidget; }; - -typedef Handle(OcctWindow) Handle_OcctWindow; diff --git a/src/app/settings.cpp b/src/app/settings.cpp new file mode 100644 index 00000000..93c70326 --- /dev/null +++ b/src/app/settings.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "settings.h" + +namespace Mayo { + +Settings* Settings::instance() +{ + static Settings settings; + return &settings; +} + +const QLocale& Settings::locale() const +{ + return m_locale; +} + +void Settings::setLocale(const QLocale& locale) +{ + m_locale = locale; +} + +QVariant Settings::value(const QString& key) const +{ + return m_settings.value(key, this->defaultValue(key)); +} + +void Settings::setValue(const QString& key, const QVariant& value) +{ + const QVariant oldValue = m_settings.value(key); + if (value != oldValue) { + m_settings.setValue(key, value); + emit valueChanged(key, value); + } +} + +const QVariant& Settings::defaultValue(const QString& key) const +{ + static const QVariant nullVar; + auto it = m_mapDefaultValue.find(key); + return it != m_mapDefaultValue.cend() ? it->second : nullVar; +} + +void Settings::setDefaultValue(const QString& key, const QVariant& value) +{ + auto it = m_mapDefaultValue.find(key); + if (it != m_mapDefaultValue.end()) + it->second = value; + else + m_mapDefaultValue.insert({ key, value }); +} + +UnitSystem::Schema Settings::unitSystemSchema() const +{ + return this->valueAsEnum("Base/UnitSystemSchema"); +} + +int Settings::unitSystemDecimals() const +{ + return this->valueAs("Base/UnitSystemDecimals"); +} + +StringUtils::TextOptions Settings::defaultTextOptions() const +{ + StringUtils::TextOptions opts; + opts.locale = this->locale(); + opts.unitDecimals = this->unitSystemDecimals(); + opts.unitSchema = this->unitSystemSchema(); + return opts; +} + +Settings::Settings() + : m_locale(QLocale::system()) +{ +} + +} // namespace Mayo diff --git a/src/app/settings.h b/src/app/settings.h new file mode 100644 index 00000000..d34bbeea --- /dev/null +++ b/src/app/settings.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +#include "../base/unit_system.h" +#include "../base/string_utils.h" + +namespace Mayo { + +class Settings : public QObject { + Q_OBJECT +public: + static Settings* instance(); + + const QLocale& locale() const; + void setLocale(const QLocale& locale); + + QVariant value(const QString& key) const; + template T valueAs(const QString& key) const; + template ENUM valueAsEnum(const QString& key) const; + void setValue(const QString& key, const QVariant& value); + + const QVariant& defaultValue(const QString& key) const; + void setDefaultValue(const QString& key, const QVariant& value); + + UnitSystem::Schema unitSystemSchema() const; + int unitSystemDecimals() const; + StringUtils::TextOptions defaultTextOptions() const; + +signals: + void valueChanged(const QString& key, const QVariant& value); + +private: + Settings(); + + QSettings m_settings; + QLocale m_locale; + std::unordered_map m_mapDefaultValue; +}; + + + +// -- +// -- Implementation +// -- + +template ENUM Settings::valueAsEnum(const QString& key) const +{ + // TODO Check returned value is QVariant-convertible to 'int' + return static_cast(this->value(key).toInt()); +} + +template T Settings::valueAs(const QString& key) const +{ + // TODO Check returned value is QVariant-convertible to 'T' + return this->value(key).value(); +} + +} // namespace Mayo diff --git a/src/app/settings_keys.h b/src/app/settings_keys.h new file mode 100644 index 00000000..3a154701 --- /dev/null +++ b/src/app/settings_keys.h @@ -0,0 +1,30 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +namespace Mayo { +namespace Keys { + +const char App_RecentFiles[] = "App/RecentFiles"; +const char App_MainWindowLastOpenDir[] = "App/MainWindowLastOpenDir"; +const char App_MainWindowLastSelectedFilter[] = "App/MainWindowLastSelectedFilter"; +const char App_MainWindowLinkWithDocumentSelector[] = "App/MainWindowLinkWithDocumentSelector"; +const char Base_StlIoLibrary[] = "Base/stlIoLibrary"; +const char Base_UnitSystemDecimals[] = "Base/UnitSystemDecimals"; +const char Base_UnitSystemSchema[] = "Base/UnitSystemSchema"; +const char Gpx_BrepShapeDefaultColor[] = "Gpx/BRepShapeDefaultColor"; +const char Gpx_BrepShapeDefaultMaterial[] = "Gpx/BRepShapeDefaultMaterial"; +const char Gpx_MeshDefaultColor[] = "Gpx/MeshDefaultColor"; +const char Gpx_MeshDefaultMaterial[] = "Gpx/MeshDefaultMaterial"; +const char Gpx_MeshDefaultShowEdges[] = "Gpx/MeshDefaultShowEdges"; +const char Gpx_MeshDefaultShowNodes[] = "Gpx/MeshDefaultShowNodes"; +const char Gui_ClipPlaneCappingHatch[] = "Gui/ClipPlaneCappingHatch"; +const char Gui_ClipPlaneCappingOn[] = "Gui/ClipPlaneCappingOn"; +const char Gui_DefaultShowOriginTrihedron[] = "Gui/defaultShowOriginTrihedron"; + +} // namespace Keys +} // namespace Mayo diff --git a/src/app/theme.cpp b/src/app/theme.cpp new file mode 100644 index 00000000..91493618 --- /dev/null +++ b/src/app/theme.cpp @@ -0,0 +1,313 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "theme.h" +#include "../base/span.h" + +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static QString cssFlatComboBox( + const QString& urlPixDownArrow, + const QString& urlPixDownArrowDisabled) +{ + const QPalette appPalette = qApp->palette(); + const QString css = QString( + "QComboBox {" + " border-style: solid;" + " background: %1;" + " padding: 2px 15px 2px 10px;" + "}\n" + "QComboBox:hover {" + " border-style: solid;" + " background: %2;" + " padding: 2px 15px 2px 10px;" + "}\n" + "QComboBox::drop-down {" + " subcontrol-origin: padding;" + " subcontrol-position: top right;" + " width: 15px;" + " border-left-width: 0px;" + " border-top-right-radius: 3px;" + " border-bottom-right-radius: 3px;" + "}\n" + "QComboBox::down-arrow { image: url(%3); }\n" + "QComboBox::down-arrow:disabled { image: url(%4); }\n" + ).arg(appPalette.color(QPalette::Window).name(), + appPalette.color(QPalette::Window).darker(110).name(), + urlPixDownArrow, + urlPixDownArrowDisabled); + return css; +} + +static QPixmap invertedPixmap(const QPixmap& pix) +{ + QPixmap pixInv; + QImage img = pix.toImage(); + img.invertPixels(); + return QPixmap::fromImage(img); +} + +static QString iconFileName(Theme::Icon icn) +{ + switch (icn) { + case Theme::Icon::File: return "file.svg"; + case Theme::Icon::Import: return "import.svg"; + case Theme::Icon::Edit: return "edit.svg"; + case Theme::Icon::Export: return "export.svg"; + case Theme::Icon::Expand: return "expand.svg"; + case Theme::Icon::Cross: return "cross.svg"; + case Theme::Icon::Link: return "link.svg"; + case Theme::Icon::Back: return "back.svg"; + case Theme::Icon::Next: return "next.svg"; + case Theme::Icon::Camera: return "camera.svg"; + case Theme::Icon::LeftSidebar: return "left-sidebar.svg"; + case Theme::Icon::BackSquare: return "back-square.svg"; + case Theme::Icon::IndicatorDown: return "indicator-down_8.png"; + case Theme::Icon::Stop: return "stop.svg"; + case Theme::Icon::Gear: return "gear.svg"; + case Theme::Icon::ZoomIn: return "zoom-in.svg"; + case Theme::Icon::ZoomOut: return "zoom-out.svg"; + case Theme::Icon::ClipPlane: return "clip-plane.svg"; + case Theme::Icon::View3dIso: return "view-iso.svg"; + case Theme::Icon::View3dLeft: return "view-left.svg"; + case Theme::Icon::View3dRight: return "view-right.svg"; + case Theme::Icon::View3dTop: return "view-top.svg"; + case Theme::Icon::View3dBottom: return "view-bottom.svg"; + case Theme::Icon::View3dFront: return "view-front.svg"; + case Theme::Icon::View3dBack: return "view-back.svg"; + case Theme::Icon::ItemMesh: return "item-mesh.svg"; + case Theme::Icon::ItemXde: return "item-xde.svg"; + case Theme::Icon::XdeAssembly: return "xde-assembly.svg"; + case Theme::Icon::XdeSimpleShape: return "xde-simple-shape.svg"; + } + return QString(); +} + +static Span themeIcons() +{ + static const Theme::Icon arrayIcons[] = { + Theme::Icon::File, + Theme::Icon::Import, + Theme::Icon::Edit, + Theme::Icon::Export, + Theme::Icon::Expand, + Theme::Icon::Cross, + Theme::Icon::Link, + Theme::Icon::Back, + Theme::Icon::Next, + Theme::Icon::Camera, + Theme::Icon::LeftSidebar, + Theme::Icon::BackSquare, + Theme::Icon::IndicatorDown, + Theme::Icon::Stop, + Theme::Icon::Gear, + Theme::Icon::ZoomIn, + Theme::Icon::ZoomOut, + Theme::Icon::ClipPlane, + Theme::Icon::View3dIso, + Theme::Icon::View3dLeft, + Theme::Icon::View3dRight, + Theme::Icon::View3dTop, + Theme::Icon::View3dBottom, + Theme::Icon::View3dFront, + Theme::Icon::View3dBack, + Theme::Icon::ItemMesh, + Theme::Icon::ItemXde, + Theme::Icon::XdeAssembly, + Theme::Icon::XdeSimpleShape + }; + return arrayIcons; +} + +static const QIcon nullQIcon = {}; + +class ThemeClassic : public Theme { +public: + QColor color(Color role) const override + { + const QPalette appPalette = qApp->palette(); + switch (role) { + case Theme::Color::Palette_Base: + return appPalette.color(QPalette::Base); + case Theme::Color::Palette_Window: + return appPalette.color(QPalette::Window); + case Theme::Color::Palette_Button: + case Theme::Color::ButtonFlat_Background: + case Theme::Color::ButtonView3d_Background: + return appPalette.color(QPalette::Button); + case Theme::Color::ButtonFlat_Hover: + return appPalette.color(QPalette::Button).darker(110); + case Theme::Color::ButtonFlat_Checked: + return appPalette.color(QPalette::Button).darker(125); + case Theme::Color::ButtonView3d_Hover: + case Theme::Color::ButtonView3d_Checked: + return QColor(65, 200, 250); + case Theme::Color::View3d_BackgroundGradientStart: + return QColor(128, 148, 255); + case Theme::Color::View3d_BackgroundGradientEnd: + return Qt::white; + case Theme::Color::MessageIndicator_Background: + return QColor(128, 200, 255); + case Theme::Color::MessageIndicator_Text: + return appPalette.color(QPalette::WindowText); + } + return QColor(); + } + + const QIcon& icon(Icon icn) const override + { + auto it = m_mapIcon.find(icn); + return it != m_mapIcon.cend() ? it->second : nullQIcon; + } + + void setup() override + { + const QString icnBasePath = ":/images/themes/classic/"; + for (const Icon icn : themeIcons()) { + const QString icnFileName = iconFileName(icn); + m_mapIcon.emplace(icn, QIcon(QPixmap(icnBasePath + icnFileName))); + } + } + + void setupHeaderComboBox(QComboBox* cb) + { + const QString urlDown(":/images/themes/classic/indicator-down_8.png"); + const QString urlDownDisabled(":/images/themes/classic/indicator-down-disabled_8.png"); + cb->setStyleSheet(cssFlatComboBox(urlDown, urlDownDisabled)); + } + +private: + std::unordered_map m_mapIcon; +}; + +class ThemeDark : public Theme { +public: + QColor color(Color role) const override + { + const QPalette appPalette = qApp->palette(); + switch (role) { + case Theme::Color::Palette_Base: + return appPalette.color(QPalette::Base); + case Theme::Color::Palette_Window: + return appPalette.color(QPalette::Window); + case Theme::Color::Palette_Button: + case Theme::Color::ButtonFlat_Background: + return appPalette.color(QPalette::Button); + case Theme::Color::ButtonFlat_Hover: + return appPalette.color(QPalette::Button).darker(110); + case Theme::Color::ButtonFlat_Checked: + return appPalette.color(QPalette::Button).darker(125); + case Theme::Color::ButtonView3d_Background: + return appPalette.color(QPalette::Button).lighter(125); + case Theme::Color::ButtonView3d_Hover: + case Theme::Color::ButtonView3d_Checked: + return appPalette.color(QPalette::Button).lighter(160); + case Theme::Color::View3d_BackgroundGradientStart: + return QColor(100, 100, 100); + case Theme::Color::View3d_BackgroundGradientEnd: + return QColor(200, 200, 200); + case Theme::Color::MessageIndicator_Background: + return appPalette.color(QPalette::Highlight).lighter(125); + case Theme::Color::MessageIndicator_Text: + return appPalette.color(QPalette::WindowText); + } + return QColor(); + } + + const QIcon& icon(Icon icn) const override + { + auto it = m_mapIcon.find(icn); + return it != m_mapIcon.cend() ? it->second : nullQIcon; + } + + void setup() override + { + const QString icnBasePath = ":/images/themes/dark/"; + for (const Icon icn : themeIcons()) { + const QString icnFileName = iconFileName(icn); + QPixmap pix(icnBasePath + icnFileName); + if (icn != Icon::Stop) + pix = invertedPixmap(pix); + m_mapIcon.emplace(icn, pix); + } + + qApp->setStyle(QStyleFactory::create("Fusion")); + QPalette p = qApp->palette(); + p.setColor(QPalette::Base, QColor(80, 80, 80)); + p.setColor(QPalette::Window, QColor(53, 53, 53)); + p.setColor(QPalette::Button, QColor(73, 73, 73)); + p.setColor(QPalette::Highlight, QColor(110, 110, 110)); + p.setColor(QPalette::Text, Qt::white); + p.setColor(QPalette::ButtonText, Qt::white); + p.setColor(QPalette::WindowText, Qt::white); + const QColor linkColor(115, 131, 191); + p.setColor(QPalette::Link, linkColor); + p.setColor(QPalette::LinkVisited, linkColor); + + const QColor disabledGray(40, 40, 40); + const QColor disabledTextGray(128, 128, 128); + p.setColor(QPalette::Disabled, QPalette::Window, disabledGray); + p.setColor(QPalette::Disabled, QPalette::Base, disabledGray); + p.setColor(QPalette::Disabled, QPalette::AlternateBase, disabledGray); + p.setColor(QPalette::Disabled, QPalette::Button, disabledGray); + p.setColor(QPalette::Disabled, QPalette::Text, disabledTextGray); + p.setColor(QPalette::Disabled, QPalette::ButtonText, disabledTextGray); + p.setColor(QPalette::Disabled, QPalette::WindowText, disabledTextGray); + qApp->setPalette(p); + + const QString css = + "QFrame[frameShape=\"5\"] { color: gray; margin-top: 2px; margin-bottom: 2px; } " + "QAbstractItemView { background: #505050; } " + "QAbstractItemView::item:hover { background: #606060; }" + "QLineEdit { background: #505050; }" + "QMenu { background: #505050; border: 1px solid rgb(100,100,100); }" + "QMenu::item:selected { background: rgb(110,110,110); }" + "QTextEdit { background: #505050; }" + "QSpinBox { background: #505050; }" + "QDoubleSpinBox { background: #505050; }" + "QToolButton:checked { background: #383838; }" + "QToolButton:pressed { background: #383838; }" + "QComboBox { background: #505050; } " + "QGroupBox { border: 1px solid #808080; margin-top: 4ex; } " + "QFileDialog { background: #505050; } " + "QComboBox:editable { background: #505050; } " + "QComboBox::disabled { background: rgb(40,40,40); } " + "QProgressBar { background: #505050; }"; + qApp->setStyleSheet(css); + } + + void setupHeaderComboBox(QComboBox* cb) + { + const QString urlDown(":/images/themes/dark/indicator-down_8.png"); + const QString urlDownDisabled(":/images/themes/classic/indicator-down-disabled_8.png"); + cb->setStyleSheet(cssFlatComboBox(urlDown, urlDownDisabled)); + } + +private: + std::unordered_map m_mapIcon; +}; + +} // namespace Internal + +Theme* createTheme(const QString& key) +{ + if (key == "classic") + return new Internal::ThemeClassic; + if (key == "dark") + return new Internal::ThemeDark; + return nullptr; +} + +} // namespace Mayo diff --git a/src/app/theme.h b/src/app/theme.h new file mode 100644 index 00000000..8ea34926 --- /dev/null +++ b/src/app/theme.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +class QComboBox; + +namespace Mayo { + +class Theme { +public: + enum class Color { + Palette_Base, + Palette_Window, + Palette_Button, + ButtonFlat_Background, + ButtonFlat_Hover, + ButtonFlat_Checked, + ButtonView3d_Background, + ButtonView3d_Hover, + ButtonView3d_Checked, + View3d_BackgroundGradientStart, + View3d_BackgroundGradientEnd, + MessageIndicator_Background, + MessageIndicator_Text + }; + + enum class Icon { + File, + Import, + Edit, + Export, + Expand, + Cross, + Link, + Back, + Next, + Camera, + LeftSidebar, + BackSquare, + IndicatorDown, + Stop, + Gear, + ZoomIn, + ZoomOut, + ClipPlane, + View3dIso, + View3dLeft, + View3dRight, + View3dTop, + View3dBottom, + View3dFront, + View3dBack, + // + ItemMesh, + ItemXde, + // + XdeAssembly, + XdeSimpleShape + }; + + virtual const QIcon& icon(Icon icn) const = 0; + virtual QColor color(Color role) const = 0; + + virtual void setup() = 0; + virtual void setupHeaderComboBox(QComboBox* cb) = 0; + +protected: + Theme() = default; + friend Theme* mayoTheme(); +}; + +Theme* createTheme(const QString& key); +Theme* mayoTheme(); + +} // namespace Mayo diff --git a/src/app/version.h.in b/src/app/version.h.in new file mode 100644 index 00000000..18773f5b --- /dev/null +++ b/src/app/version.h.in @@ -0,0 +1,12 @@ +#pragma once + +namespace Mayo { + +const char strVersion[] = \"$$MAYO_VERSION\"; +const char strVersionCommitId[] = \"$$MAYO_VERSION_COMMIT\"; +const unsigned versionRevisionNumber = $$MAYO_VERSION_REVNUM; +const unsigned versionMajor = $$MAYO_VERSION_MAJ; +const unsigned versionMinor = $$MAYO_VERSION_MIN; +const unsigned versionPatch = $$MAYO_VERSION_PAT; + +} // namespace Mayo diff --git a/src/app/widget_clip_planes.cpp b/src/app/widget_clip_planes.cpp new file mode 100644 index 00000000..dcaf5035 --- /dev/null +++ b/src/app/widget_clip_planes.cpp @@ -0,0 +1,281 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_clip_planes.h" + +#include "../base/bnd_utils.h" +#include "../base/math_utils.h" +#include "../gpx/gpx_utils.h" +#include "settings.h" +#include "settings_keys.h" +#include "ui_widget_clip_planes.h" + +#include +#include +#include + +namespace Mayo { + +WidgetClipPlanes::WidgetClipPlanes(const Handle_V3d_View& view3d, QWidget* parent) + : QWidget(parent), + m_ui(new Ui_WidgetClipPlanes), + m_view(view3d) +{ + m_ui->setupUi(this); + + m_vecClipPlaneData = { + { new Graphic3d_ClipPlane(gp_Pln({}, gp_Dir(1, 0, 0))), + UiClipPlane(m_ui->check_X, m_ui->widget_X) }, + { new Graphic3d_ClipPlane(gp_Pln({}, gp_Dir(0, 1, 0))), + UiClipPlane(m_ui->check_Y, m_ui->widget_Y) }, + { new Graphic3d_ClipPlane(gp_Pln({}, gp_Dir(0, 0, 1))), + UiClipPlane(m_ui->check_Z, m_ui->widget_Z) }, + { new Graphic3d_ClipPlane(gp_Pln({}, gp_Dir(1, 1, 1))), + UiClipPlane(m_ui->check_Custom, m_ui->widget_Custom) } + }; + + const auto settings = Settings::instance(); + for (ClipPlaneData& data : m_vecClipPlaneData) { + data.ui.widget_Control->setEnabled(data.ui.check_On->isChecked()); + this->connectUi(&data); + data.gpx->SetCapping(settings->valueAs(Keys::Gui_ClipPlaneCappingOn)); + if (data.gpx->IsCapping()) { + GpxUtils::Gpx3dClipPlane_setCappingHatch( + data.gpx, + settings->valueAsEnum(Keys::Gui_ClipPlaneCappingHatch)); + } + + Graphic3d_MaterialAspect clipMaterial(Graphic3d_NOM_STEEL); + Quantity_NameOfColor colorName; + if (&data == &m_vecClipPlaneData.at(0)) + colorName = Quantity_NOC_RED1; + else if (&data == &m_vecClipPlaneData.at(1)) + colorName = Quantity_NOC_GREEN1; + else if (&data == &m_vecClipPlaneData.at(2)) + colorName = Quantity_NOC_BLUE1; + else + colorName = Quantity_NOC_GRAY; + + clipMaterial.SetColor(Quantity_Color(colorName)); + data.gpx->SetCappingMaterial(clipMaterial); + } + + QObject::connect( + settings, &Settings::valueChanged, + this, [=](const QString& key, const QVariant& value) { + if (key == Keys::Gui_ClipPlaneCappingOn) { + for (ClipPlaneData& data : m_vecClipPlaneData) + data.gpx->SetCapping(value.toBool()); + m_view->Redraw(); + } + }); + QObject::connect( + settings, &Settings::valueChanged, + this, [=](const QString& key, const QVariant& value) { + if (key == Keys::Gui_ClipPlaneCappingHatch) { + const auto hatch = static_cast(value.toInt()); + for (ClipPlaneData& data : m_vecClipPlaneData) + GpxUtils::Gpx3dClipPlane_setCappingHatch(data.gpx, hatch); + m_view->Redraw(); + } + }); + + m_ui->widget_CustomDir->setVisible(false); +} + +WidgetClipPlanes::~WidgetClipPlanes() +{ + delete m_ui; +} + +void WidgetClipPlanes::setRanges(const Bnd_Box& bndBox) +{ + m_bndBox = bndBox; + const bool isBndBoxVoid = bndBox.IsVoid(); + const auto bbc = BndBoxCoords::get(bndBox); + for (ClipPlaneData& data : m_vecClipPlaneData) { + const gp_Dir& n = data.gpx->ToPlane().Axis().Direction(); + this->setPlaneRange(&data, MathUtils::planeRange(bbc, n)); + data.ui.check_On->setEnabled(!isBndBoxVoid); + if (isBndBoxVoid) + data.ui.check_On->setChecked(false); + } + + m_view->Redraw(); +} + +void WidgetClipPlanes::setClippingOn(bool on) +{ + for (ClipPlaneData& data : m_vecClipPlaneData) + data.gpx->SetOn(on ? data.ui.check_On->isChecked() : false); + + m_view->Redraw(); +} + +void WidgetClipPlanes::connectUi(ClipPlaneData* data) +{ + UiClipPlane& ui = data->ui; + const Handle_Graphic3d_ClipPlane& gpx = data->gpx; + QAbstractSlider* posSlider = ui.posSlider(); + QDoubleSpinBox* posSpin = ui.posSpin(); + auto signalSpinValueChanged = qOverload(&QDoubleSpinBox::valueChanged); + + QObject::connect(ui.check_On, &QCheckBox::clicked, [=](bool on) { + ui.widget_Control->setEnabled(on); + this->setPlaneOn(gpx, on); + m_view->Redraw(); + }); + + if (data->ui.customXDirSpin()) { + auto widgetDir = ui.widget_Control->findChild("widget_CustomDir"); + QObject::connect(ui.check_On, &QAbstractButton::clicked, [=](bool on) { + widgetDir->setVisible(on); + QWidget* panel = this->parentWidget() ? this->parentWidget() : this; + if (on) { + panel->adjustSize(); + } + else { + const QSize sz = panel->size(); + const int offset = ui.customXDirSpin()->frameGeometry().height(); + panel->resize(sz.width(), sz.height() - offset); + } + }); + } + + QObject::connect(posSpin, signalSpinValueChanged, [=](double pos) { + QSignalBlocker sigBlock(posSlider); Q_UNUSED(sigBlock); + const double dPct = ui.spinValueToSliderValue(pos); + posSlider->setValue(qRound(dPct)); + GpxUtils::Gpx3dClipPlane_setPosition(gpx, pos); + m_view->Redraw(); + }); + + QObject::connect(posSlider, &QSlider::valueChanged, [=](int pct) { + const double pos = ui.sliderValueToSpinValue(pct); + QSignalBlocker sigBlock(posSpin); Q_UNUSED(sigBlock); + posSpin->setValue(pos); + GpxUtils::Gpx3dClipPlane_setPosition(gpx, pos); + m_view->Redraw(); + }); + + QObject::connect(ui.inverseBtn(), &QAbstractButton::clicked, [=]{ + const gp_Dir invNormal = gpx->ToPlane().Axis().Direction().Reversed(); + GpxUtils::Gpx3dClipPlane_setNormal(gpx, invNormal); + GpxUtils::Gpx3dClipPlane_setPosition(gpx, data->ui.posSpin()->value()); + m_view->Redraw(); + }); + + // Custom plane normal + QDoubleSpinBox* customXDirSpin = ui.customXDirSpin(); + QDoubleSpinBox* customYDirSpin = ui.customYDirSpin(); + QDoubleSpinBox* customZDirSpin = ui.customZDirSpin(); + auto funcConnectDirSpin = [=](QDoubleSpinBox* dirSpin) { + QObject::connect(dirSpin, signalSpinValueChanged, [=]{ + const gp_Vec vecNormal( + customXDirSpin->value(), + customYDirSpin->value(), + customZDirSpin->value()); + if (vecNormal.Magnitude() > Precision::Confusion()) { + const gp_Dir normal(vecNormal); + const auto bbc = BndBoxCoords::get(m_bndBox); + this->setPlaneRange(data, MathUtils::planeRange(bbc, normal)); + GpxUtils::Gpx3dClipPlane_setNormal(gpx, normal); + m_view->Redraw(); + } + }); + }; + if (customXDirSpin) { + funcConnectDirSpin(customXDirSpin); + funcConnectDirSpin(customYDirSpin); + funcConnectDirSpin(customZDirSpin); + QObject::connect(ui.inverseBtn(), &QAbstractButton::clicked, [=]{ + QSignalBlocker sigBlockX(customXDirSpin); Q_UNUSED(sigBlockX); + QSignalBlocker sigBlockY(customYDirSpin); Q_UNUSED(sigBlockY); + QSignalBlocker sigBlockZ(customZDirSpin); Q_UNUSED(sigBlockZ); + const gp_Dir& n = gpx->ToPlane().Axis().Direction(); + customXDirSpin->setValue(n.X()); + customYDirSpin->setValue(n.Y()); + customZDirSpin->setValue(n.Z()); + }); + } +} + +void WidgetClipPlanes::setPlaneOn(const Handle_Graphic3d_ClipPlane& plane, bool on) +{ + plane->SetOn(on); + if (!GpxUtils::V3dView_hasClipPlane(m_view, plane)) + m_view->AddClipPlane(plane); +} + +void WidgetClipPlanes::setPlaneRange(ClipPlaneData* data, const Range& range) +{ + const double rmin = range.first; + const double rmax = range.second; + QDoubleSpinBox* posSpin = data->ui.posSpin(); + QAbstractSlider* posSlider = data->ui.posSlider(); + const double currPlanePos = posSpin->value(); + const double gap = (rmax - rmin) * 0.01; + const double mid = rmin + (rmax - rmin) / 2.; + const bool isCurrPlanePosValid = rmin <= currPlanePos && currPlanePos <= rmax; + const bool isEmptyPosSpinRange = + std::abs(posSpin->maximum() - posSpin->minimum()) < Precision::Confusion(); + const bool useMidValue = isEmptyPosSpinRange || !isCurrPlanePosValid; + const double newPlanePos = useMidValue ? mid : currPlanePos; + posSpin->setRange(rmin - gap, rmax + gap); + posSpin->setSingleStep(std::abs(posSpin->maximum() - posSpin->minimum()) / 100.); + if (useMidValue) { + GpxUtils::Gpx3dClipPlane_setPosition(data->gpx, newPlanePos); + posSpin->setValue(newPlanePos); + posSlider->setValue(data->ui.spinValueToSliderValue(newPlanePos)); + } +} + +WidgetClipPlanes::UiClipPlane::UiClipPlane(QCheckBox* checkOn, QWidget* widgetControl) + : check_On(checkOn), widget_Control(widgetControl) +{ } + +QDoubleSpinBox* WidgetClipPlanes::UiClipPlane::posSpin() const { + return this->widget_Control->findChild( + QString(), Qt::FindDirectChildrenOnly); +} + +QAbstractSlider* WidgetClipPlanes::UiClipPlane::posSlider() const { + return this->widget_Control->findChild( + QString(), Qt::FindDirectChildrenOnly); +} + +QAbstractButton* WidgetClipPlanes::UiClipPlane::inverseBtn() const { + return this->widget_Control->findChild( + QString(), Qt::FindDirectChildrenOnly); +} + +QDoubleSpinBox* WidgetClipPlanes::UiClipPlane::customXDirSpin() const { + return this->widget_Control->findChild("spin_CustomDirX"); +} + +QDoubleSpinBox* WidgetClipPlanes::UiClipPlane::customYDirSpin() const { + return this->widget_Control->findChild("spin_CustomDirY"); +} + +QDoubleSpinBox* WidgetClipPlanes::UiClipPlane::customZDirSpin() const { + return this->widget_Control->findChild("spin_CustomDirZ"); +} + +double WidgetClipPlanes::UiClipPlane::spinValueToSliderValue(double val) const { + QDoubleSpinBox* spin = this->posSpin(); + QAbstractSlider* slider = this->posSlider(); + return MathUtils::mappedValue( + val, spin->minimum(), spin->maximum(), slider->minimum(), slider->maximum()); +} + +double WidgetClipPlanes::UiClipPlane::sliderValueToSpinValue(double val) const { + QDoubleSpinBox* spin = this->posSpin(); + QAbstractSlider* slider = this->posSlider(); + return MathUtils::mappedValue( + val, slider->minimum(), slider->maximum(), spin->minimum(), spin->maximum()); +} + +} // namespace Mayo diff --git a/src/app/widget_clip_planes.h b/src/app/widget_clip_planes.h new file mode 100644 index 00000000..6a42d73f --- /dev/null +++ b/src/app/widget_clip_planes.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +class QCheckBox; +class QDoubleSpinBox; +class QAbstractSlider; +class QAbstractButton; + +namespace Mayo { + +class WidgetClipPlanes : public QWidget { + Q_OBJECT +public: + WidgetClipPlanes(const Handle_V3d_View& view3d, QWidget* parent = nullptr); + ~WidgetClipPlanes(); + + void setRanges(const Bnd_Box& box); + void setClippingOn(bool on); + +private: + struct UiClipPlane { + QCheckBox* check_On; + QWidget* widget_Control; + + UiClipPlane(QCheckBox* checkOn, QWidget* widgetControl); + QDoubleSpinBox* posSpin() const; + QAbstractSlider* posSlider() const; + QAbstractButton* inverseBtn() const; + QDoubleSpinBox* customXDirSpin() const; + QDoubleSpinBox* customYDirSpin() const; + QDoubleSpinBox* customZDirSpin() const; + double spinValueToSliderValue(double val) const; + double sliderValueToSpinValue(double val) const; + }; + + struct ClipPlaneData { + Handle_Graphic3d_ClipPlane gpx; + UiClipPlane ui; + }; + + using Range = std::pair; + + void connectUi(ClipPlaneData* data); + + void setPlaneOn(const Handle_Graphic3d_ClipPlane& plane, bool on); + void setPlaneRange(ClipPlaneData* data, const Range& range); + + class Ui_WidgetClipPlanes* m_ui; + Handle_V3d_View m_view; + std::vector m_vecClipPlaneData; + Bnd_Box m_bndBox; +}; + +} // namespace Mayo diff --git a/src/app/widget_clip_planes.ui b/src/app/widget_clip_planes.ui new file mode 100644 index 00000000..f2c77c6f --- /dev/null +++ b/src/app/widget_clip_planes.ui @@ -0,0 +1,334 @@ + + + Mayo::WidgetClipPlanes + + + + 0 + 0 + 249 + 112 + + + + Edit clip planes + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + X plane + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0.000000000000000 + + + + + + + 100 + + + Qt::Horizontal + + + + + + + Reverse plane + + + +/- + + + + + + + + + + Y plane + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0.000000000000000 + + + + + + + 100 + + + Qt::Horizontal + + + + + + + Reverse plane + + + +/- + + + + + + + + + + Z plane + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0.000000000000000 + + + + + + + 100 + + + Qt::Horizontal + + + + + + + Reverse plane + + + +/- + + + + + + + + + + Custom + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 2 + + + + + Reverse plane + + + +/- + + + + + + + 0.000000000000000 + + + + + + + 100 + + + Qt::Horizontal + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + X + + + -1.000000000000000 + + + 1.000000000000000 + + + 0.050000000000000 + + + 1.000000000000000 + + + + + + + Y + + + -1.000000000000000 + + + 1.000000000000000 + + + 0.050000000000000 + + + 1.000000000000000 + + + + + + + Z + + + -1.000000000000000 + + + 1.000000000000000 + + + 0.050000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + + diff --git a/src/app/widget_file_system.cpp b/src/app/widget_file_system.cpp new file mode 100644 index 00000000..34c91664 --- /dev/null +++ b/src/app/widget_file_system.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_file_system.h" + +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static std::pair fileSizeQuantity(uint64_t sizeBytes) +{ + if (sizeBytes < 1024 ) + return { sizeBytes, WidgetFileSystem::tr("B") }; + else if (sizeBytes < 1024*1024) + return { sizeBytes / 1024, WidgetFileSystem::tr("KB") }; + else + return { sizeBytes / (1024*1024), WidgetFileSystem::tr("MB") }; +} + +static QString absolutePath(const QFileInfo& fi) +{ + return fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath(); +} + +} // namespace Internal + +WidgetFileSystem::WidgetFileSystem(QWidget *parent) + : QWidget(parent), + m_treeWidget(new QTreeWidget(this)) +{ + auto layout = new QVBoxLayout; + layout->addWidget(m_treeWidget); + layout->setContentsMargins(0, 0, 0, 0); + this->setLayout(layout); + + m_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_treeWidget->setColumnCount(1); + m_treeWidget->setIndentation(0); + + QObject::connect( + m_treeWidget, &QTreeWidget::itemActivated, + this, &WidgetFileSystem::onTreeItemActivated); +} + +QFileInfo WidgetFileSystem::currentLocation() const +{ + return m_location; +} + +void WidgetFileSystem::setLocation(const QFileInfo &fiLoc) +{ + const QString pathCurrLocation = Internal::absolutePath(m_location); + const QString pathLoc = Internal::absolutePath(fiLoc); + if (pathCurrLocation == pathLoc) { + for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) { + QTreeWidgetItem* item = m_treeWidget->topLevelItem(i); + if (item->text(0) == fiLoc.fileName()) { + m_treeWidget->clearSelection(); + item->setSelected(true); + break; + } + } + } + else { + m_treeWidget->clear(); + QTreeWidgetItem* itemToBeSelected = nullptr; + QList listItem; + if (fiLoc.exists()) { + const QDir dir(pathLoc); + const QFileInfoList listEntryFileInfo = + dir.entryInfoList( + QDir::Files | QDir::AllDirs | QDir::NoDot, + QDir::DirsFirst); + for (const QFileInfo& fi : listEntryFileInfo) { + auto item = new QTreeWidgetItem; + if (fi.fileName() != QLatin1String(".")) { + item->setText(0, fi.fileName()); + item->setIcon(0, m_fileIconProvider.icon(fi)); + const auto sizeQty = Internal::fileSizeQuantity(fi.size()); + const QString itemTooltip = + tr("%1\nSize: %2%3\nLast modified: %4") + .arg(QDir::toNativeSeparators(fi.absoluteFilePath())) + .arg(sizeQty.first).arg(sizeQty.second) + .arg(fi.lastModified().toString(Qt::SystemLocaleShortDate)); + item->setToolTip(0, itemTooltip); + if (fi.fileName() == fiLoc.fileName()) + itemToBeSelected = item; + } + listItem.push_back(item); + } + } + m_treeWidget->addTopLevelItems(listItem); + m_treeWidget->headerItem()->setText(0, fiLoc.dir().dirName()); + if (itemToBeSelected != nullptr) + itemToBeSelected->setSelected(true); + } + m_location = fiLoc; +} + +void WidgetFileSystem::onTreeItemActivated(QTreeWidgetItem *item, int column) +{ + if (item != nullptr && column == 0) { + if (item->text(0) == QLatin1String("..")) { + this->setLocation(m_location.absoluteDir().path()); + } + else { + const QDir dir(Internal::absolutePath(m_location)); + const QFileInfo fi(dir, item->text(0)); + if (fi.isDir()) + this->setLocation(fi); + else + emit this->locationActivated(fi); + } + } +} + +} // namespace Mayo diff --git a/src/app/widget_file_system.h b/src/app/widget_file_system.h new file mode 100644 index 00000000..366bf967 --- /dev/null +++ b/src/app/widget_file_system.h @@ -0,0 +1,36 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +class QTreeWidget; +class QTreeWidgetItem; + +namespace Mayo { + +class WidgetFileSystem : public QWidget { + Q_OBJECT +public: + WidgetFileSystem(QWidget* parent = nullptr); + + QFileInfo currentLocation() const; + void setLocation(const QFileInfo& fiLoc); + +signals: + void locationActivated(const QFileInfo& loc); + +private: + void onTreeItemActivated(QTreeWidgetItem* item, int column); + + QTreeWidget* m_treeWidget = nullptr; + QFileInfo m_location; + QFileIconProvider m_fileIconProvider; +}; + +} // namespace Mayo diff --git a/src/app/widget_gui_document.cpp b/src/app/widget_gui_document.cpp new file mode 100644 index 00000000..41813326 --- /dev/null +++ b/src/app/widget_gui_document.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_gui_document.h" + +#include "../gpx/gpx_utils.h" +#include "../gpx/v3d_view_camera_animation.h" +#include "../gui/gui_document.h" +#include "button_flat.h" +#include "theme.h" +#include "widget_clip_planes.h" +#include "widget_occ_view.h" +#include "widget_occ_view_controller.h" + +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static ButtonFlat* createViewBtn( + QWidget* parent, Theme::Icon icon, const QString& tooltip) +{ + auto btn = new ButtonFlat(parent); + btn->setBackgroundBrush(mayoTheme()->color(Theme::Color::ButtonView3d_Background)); + btn->setCheckedBrush(mayoTheme()->color(Theme::Color::ButtonView3d_Checked)); + btn->setHoverBrush(mayoTheme()->color(Theme::Color::ButtonView3d_Hover)); + btn->setIcon(mayoTheme()->icon(icon)); + btn->setIconSize(QSize(18, 18)); + btn->setFixedSize(24, 24); + btn->setToolTip(tooltip); + return btn; +} + +class PanelView3d : public QWidget { +public: + PanelView3d(QWidget* parent = nullptr) + : QWidget(parent) + {} + +protected: + void paintEvent(QPaintEvent*) override + { + WidgetGuiDocument::paintPanel(this); + } +}; + +const int widgetMargin = 4; + +} // namespace Internal + +WidgetGuiDocument::WidgetGuiDocument(GuiDocument* guiDoc, QWidget* parent) + : QWidget(parent), + m_guiDoc(guiDoc), + m_qtOccView(new WidgetOccView(guiDoc->v3dView(), this)), + m_controller(new WidgetOccViewController(m_qtOccView)), + m_cameraAnimation(new V3dViewCameraAnimation(guiDoc->v3dView(), this)) +{ + m_cameraAnimation->setEasingCurve(QEasingCurve::OutExpo); + auto layout = new QVBoxLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_qtOccView); + this->setLayout(layout); + + auto btnFitAll = Internal::createViewBtn(this, Theme::Icon::Expand, tr("Fit All")); + auto btnViewIso = Internal::createViewBtn(this, Theme::Icon::View3dIso, tr("Isometric")); + auto btnViewBack = Internal::createViewBtn(this, Theme::Icon::View3dBack, tr("Back")); + auto btnViewFront = Internal::createViewBtn(this, Theme::Icon::View3dFront, tr("Front")); + auto btnViewLeft = Internal::createViewBtn(this, Theme::Icon::View3dLeft, tr("Left")); + auto btnViewRight = Internal::createViewBtn(this, Theme::Icon::View3dRight, tr("Right")); + auto btnViewTop = Internal::createViewBtn(this, Theme::Icon::View3dTop, tr("Top")); + auto btnViewBottom = Internal::createViewBtn(this, Theme::Icon::View3dBottom, tr("Bottom")); + auto btnEditClipping = Internal::createViewBtn(this, Theme::Icon::ClipPlane, tr("Edit clip planes")); + btnEditClipping->setCheckable(true); + const int margin = Internal::widgetMargin; + btnFitAll->move(margin, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewIso, btnFitAll, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewBack, btnViewIso, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewFront, btnViewBack, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewLeft, btnViewFront, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewRight, btnViewLeft, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewTop, btnViewRight, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnViewBottom, btnViewTop, margin); + qtgui::QWidgetUtils::moveWidgetRightTo(btnEditClipping, btnViewBottom, margin); + + this->connectViewProjButton(btnViewIso, V3d_XposYnegZpos); + this->connectViewProjButton(btnViewIso, V3d_XposYnegZpos); + this->connectViewProjButton(btnViewBack, V3d_Xneg); + this->connectViewProjButton(btnViewFront, V3d_Xpos); + this->connectViewProjButton(btnViewLeft, V3d_Ypos); + this->connectViewProjButton(btnViewRight, V3d_Yneg); + this->connectViewProjButton(btnViewTop, V3d_Zpos); + this->connectViewProjButton(btnViewBottom, V3d_Zneg); + QObject::connect(btnFitAll, &ButtonFlat::clicked, [=]{ + m_cameraAnimation->configure(&GpxUtils::V3dView_fitAll); + m_cameraAnimation->start(QAbstractAnimation::KeepWhenStopped); + }); + QObject::connect( + m_controller, &V3dViewController::dynamicActionStarted, + m_cameraAnimation, &V3dViewCameraAnimation::stop); + QObject::connect( + m_controller, &V3dViewController::viewScaled, + m_cameraAnimation, &V3dViewCameraAnimation::stop); + QObject::connect( + btnEditClipping, &ButtonFlat::clicked, + this, &WidgetGuiDocument::toggleWidgetClipPlanes); + + const QRect rectFirstBtn = btnFitAll->frameGeometry(); + const QRect rectLastBtn = btnEditClipping->frameGeometry(); + m_rectControls.setCoords( + rectFirstBtn.left(), rectFirstBtn.top(), + rectLastBtn.right(), rectLastBtn.bottom()); +} + +GuiDocument* WidgetGuiDocument::guiDocument() const +{ + return m_guiDoc; +} + +V3dViewController* WidgetGuiDocument::controller() const +{ + return m_controller; +} + +QRect WidgetGuiDocument::rectControls() const +{ + return m_rectControls; +} + +void WidgetGuiDocument::paintPanel(QWidget* widget) +{ + QPainter painter(widget); + const QRect frame = widget->frameGeometry(); + const QRect surface(0, 0, frame.width(), frame.height()); + const QColor panelColor = mayoTheme()->color(Theme::Color::Palette_Window); + painter.fillRect(surface, panelColor); +} + +void WidgetGuiDocument::connectViewProjButton(ButtonFlat* btn, V3d_TypeOfOrientation proj) +{ + QObject::connect(btn, &ButtonFlat::clicked, [=]{ + m_cameraAnimation->configure([=](Handle_V3d_View view) { + view->SetProj(proj); + GpxUtils::V3dView_fitAll(view); + }); + m_cameraAnimation->start(QAbstractAnimation::KeepWhenStopped); + }); +} + +void WidgetGuiDocument::toggleWidgetClipPlanes() +{ + if (!m_widgetClipPlanes) { + auto panel = new Internal::PanelView3d(this); + auto widget = new WidgetClipPlanes(m_guiDoc->v3dView(), panel); + qtgui::QWidgetUtils::addContentsWidget(panel, widget); + panel->show(); + panel->adjustSize(); + const int margin = Internal::widgetMargin; + panel->move(margin, m_rectControls.bottom() + margin); + m_widgetClipPlanes = widget; + QObject::connect( + m_guiDoc, &GuiDocument::gpxBoundingBoxChanged, + widget, &WidgetClipPlanes::setRanges); + widget->setRanges(m_guiDoc->gpxBoundingBox()); + } + else { + QWidget* panel = m_widgetClipPlanes->parentWidget(); + panel->setHidden(!panel->isHidden()); + m_widgetClipPlanes->setClippingOn(panel->isVisible()); + } +} + +} // namespace Mayo diff --git a/src/app/widget_gui_document.h b/src/app/widget_gui_document.h new file mode 100644 index 00000000..1890e09b --- /dev/null +++ b/src/app/widget_gui_document.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +class ButtonFlat; +class GuiDocument; +class V3dViewCameraAnimation; +class V3dViewController; +class WidgetClipPlanes; +class WidgetOccView; + +class WidgetGuiDocument : public QWidget { + Q_OBJECT +public: + WidgetGuiDocument(GuiDocument* guiDoc, QWidget* parent = nullptr); + + GuiDocument* guiDocument() const; + V3dViewController* controller() const; + + QRect rectControls() const; + + static void paintPanel(QWidget* widget); + +private: + void connectViewProjButton(ButtonFlat* btn, V3d_TypeOfOrientation proj); + void toggleWidgetClipPlanes(); + + GuiDocument* m_guiDoc = nullptr; + WidgetOccView* m_qtOccView = nullptr; + V3dViewController* m_controller = nullptr; + V3dViewCameraAnimation* m_cameraAnimation = nullptr; + WidgetClipPlanes* m_widgetClipPlanes = nullptr; + QRect m_rectControls; +}; + +} // namespace Mayo diff --git a/src/widget_message_indicator.cpp b/src/app/widget_message_indicator.cpp similarity index 50% rename from src/widget_message_indicator.cpp rename to src/app/widget_message_indicator.cpp index 39814526..15c414fd 100644 --- a/src/widget_message_indicator.cpp +++ b/src/app/widget_message_indicator.cpp @@ -1,39 +1,17 @@ /**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. +** Copyright (c) 2020, Fougue Ltd. ** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt ****************************************************************************/ #include "widget_message_indicator.h" +#include "theme.h" #include #include #include -#include #include +#include namespace Mayo { @@ -58,14 +36,15 @@ WidgetMessageIndicator::WidgetMessageIndicator(const QString& msg, QWidget* pare const qreal rectHeight = m_messageRect.height() + 10; this->setGeometry( QRect(5, parent->height() - rectHeight - 5, rectWidth, rectHeight)); + parent->installEventFilter(this); } } qreal WidgetMessageIndicator::opacity() const { return m_opacity; - } + void WidgetMessageIndicator::setOpacity(qreal value) { m_opacity = value; @@ -75,10 +54,8 @@ void WidgetMessageIndicator::setOpacity(qreal value) void WidgetMessageIndicator::run() { this->show(); - QTimer::singleShot( - 1500 + m_message.length() * 60, - this, - &WidgetMessageIndicator::runInternal); + const int duration = 1500 + m_message.length() * 60; + QTimer::singleShot(duration, this, &WidgetMessageIndicator::runInternal); } void WidgetMessageIndicator::paintEvent(QPaintEvent*) @@ -87,18 +64,13 @@ void WidgetMessageIndicator::paintEvent(QPaintEvent*) p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing); p.setOpacity(m_opacity); - QPainterPath boxPath; - const QRectF boxRect( - 0, 0, m_messageRect.width() + 18, m_messageRect.height() + 8); - boxPath.addRoundedRect(boxRect, 8, 8); - QLinearGradient boxGrad(0, 0, 0, boxRect.height()); - boxGrad.setColorAt(0, QColor(214, 235, 255)); - boxGrad.setColorAt(1, QColor(128, 200, 255)); - p.fillPath(boxPath, boxGrad); + const QRectF& msgRect = m_messageRect; + const QRectF boxRect(0, 0, msgRect.width() + 18, msgRect.height() + 8); + p.fillRect(boxRect, mayoTheme()->color(Theme::Color::MessageIndicator_Background)); p.setFont(Internal::indicatorFont(this->font())); - const QRectF textRect( - 9, 4, m_messageRect.width() + 4, m_messageRect.height()); + const QRectF textRect(9, 4, msgRect.width() + 4, msgRect.height()); + p.setPen(mayoTheme()->color(Theme::Color::MessageIndicator_Text)); p.drawText(textRect, m_message); } @@ -106,6 +78,7 @@ void WidgetMessageIndicator::runInternal() { auto anim = new QPropertyAnimation(this, "opacity", this); anim->setDuration(200); + anim->setStartValue(1.); anim->setEndValue(0.); QObject::connect( anim, &QAbstractAnimation::finished, @@ -118,4 +91,17 @@ void WidgetMessageIndicator::showMessage(const QString& msg, QWidget* parent) (new WidgetMessageIndicator(msg, parent))->run(); } +bool WidgetMessageIndicator::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == this->parentWidget() && event->type() == QEvent::Resize) { + auto eventResize = static_cast(event); + if (eventResize->size().height() != eventResize->oldSize().height()) { + const qreal rectHeight = m_messageRect.height() + 10; + this->move(5, eventResize->size().height() - rectHeight - 5); + return true; + } + } + return false; +} + } // namespace Mayo diff --git a/src/app/widget_message_indicator.h b/src/app/widget_message_indicator.h new file mode 100644 index 00000000..2fe9fa82 --- /dev/null +++ b/src/app/widget_message_indicator.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include + +namespace Mayo { + +/*! Provides an auto-shading application message + * + * Use directly MessageIndicator::showMessage() instead of manually creating + * MessageIndicator.\n + * Messages are displayed at widget's bottom-left corner and during a time + * proportional to the length of the message. + */ +class WidgetMessageIndicator : public QWidget { + Q_OBJECT + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity USER true) +public: + WidgetMessageIndicator(const QString& msg, QWidget* parent = nullptr); + + qreal opacity() const; + void setOpacity(qreal value); + + void run(); + + static void showMessage(const QString& msg, QWidget* parent); + + bool eventFilter(QObject* watched, QEvent* event) override; + +protected: + void paintEvent(QPaintEvent*) override; + +private: + void runInternal(); + + const QString m_message; + QRectF m_messageRect; + qreal m_opacity = 1.; +}; + +} // namespace Mayo diff --git a/src/app/widget_model_tree.cpp b/src/app/widget_model_tree.cpp new file mode 100644 index 00000000..3ba53f6f --- /dev/null +++ b/src/app/widget_model_tree.cpp @@ -0,0 +1,432 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_model_tree.h" + +#include "../base/application.h" +#include "../base/application_item_selection_model.h" +#include "../base/string_utils.h" +#include "../base/document.h" +#include "../base/document_item.h" +#include "../gui/gui_application.h" +#include "settings.h" +#include "theme.h" +#include "widget_model_tree_builder.h" + +#include + +#include +#include +#include + +#include +#include + +Q_DECLARE_METATYPE(Mayo::DocumentItemNode) + +namespace Mayo { +namespace Internal { + +using PtrBuilder = std::unique_ptr; +static std::vector& arrayPrototypeBuilder() +{ + static std::vector vecPtrBuilder; + if (vecPtrBuilder.empty()) + vecPtrBuilder.emplace_back(new WidgetModelTreeBuilder); // Fallback + + return vecPtrBuilder; +} + +template +static WidgetModelTreeBuilder* findSupportBuilder( + Span spanBuilder, PREDICATE fn) +{ + for (int i = 1; i < spanBuilder.size(); ++i) { + if (fn(spanBuilder.at(i))) + return spanBuilder.at(i); + } + + return spanBuilder.at(0); // Fallback +} + +class TreeWidget : public QTreeWidget { +public: + TreeWidget(QWidget* parent = nullptr) + : QTreeWidget(parent) + {} + + QModelIndex indexFromItem(QTreeWidgetItem* item, int column = 0) const { + return QTreeWidget::indexFromItem(item, column); + } + + QTreeWidgetItem* itemFromIndex(const QModelIndex& index) const { + return QTreeWidget::itemFromIndex(index); + } +}; + +} // namespace Internal +} // namespace Mayo +#include "ui_widget_model_tree.h" + +namespace Mayo { + +namespace Internal { + +enum TreeItemRole { + TreeItemTypeRole = Qt::UserRole + 1, + TreeItemDocumentRole, + TreeItemDocumentItemRole, + TreeItemDocumentItemNodeRole +}; + +enum TreeItemType { + TreeItemType_Unknown = 0, + TreeItemType_Document = 1, + TreeItemType_DocumentItem = 2, + TreeItemType_DocumentItemNode = 3 +}; + +template T* qVariantToPtr(const QVariant& var) { + return static_cast(var.value()); +} + +template QVariant ptrToQVariant(T* ptr) { + return qVariantFromValue(reinterpret_cast(ptr)); +} + +static TreeItemType treeItemType(const QTreeWidgetItem* treeItem) +{ + const QVariant varType = treeItem->data(0, TreeItemTypeRole); + return varType.isValid() ? + static_cast(varType.toInt()) : + Internal::TreeItemType_Unknown; +} + +static Document* treeItemDocument(const QTreeWidgetItem* treeItem) +{ + const QVariant var = treeItem->data(0, TreeItemDocumentRole); + return var.isValid() ? qVariantToPtr(var) : nullptr; +} + +static DocumentItem* treeItemDocumentItem(const QTreeWidgetItem* treeItem) +{ + const QVariant var = treeItem->data(0, TreeItemDocumentItemRole); + return var.isValid() ? qVariantToPtr(var) : nullptr; +} + +static DocumentItemNode treeItemDocumentItemNode(const QTreeWidgetItem* treeItem) +{ + const QVariant var = treeItem->data(0, TreeItemDocumentItemNodeRole); + return var.isValid() ? var.value() : DocumentItemNode::null(); +} + +static void setTreeItemDocument(QTreeWidgetItem* treeItem, Document* doc) +{ + treeItem->setData(0, TreeItemTypeRole, Internal::TreeItemType_Document); + treeItem->setData(0, TreeItemDocumentRole, ptrToQVariant(doc)); +} + +static void setTreeItemDocumentItem(QTreeWidgetItem* treeItem, DocumentItem* docItem) +{ + treeItem->setData(0, TreeItemTypeRole, Internal::TreeItemType_DocumentItem); + treeItem->setData(0, TreeItemDocumentItemRole, ptrToQVariant(docItem)); +} + +static void setTreeItemDocumentItemNode( + QTreeWidgetItem* treeItem, const DocumentItemNode& node) +{ + treeItem->setData(0, TreeItemTypeRole, Internal::TreeItemType_DocumentItemNode); + treeItem->setData(0, TreeItemDocumentItemNodeRole, QVariant::fromValue(node)); +} + +static ApplicationItem toApplicationItem(const QTreeWidgetItem* treeItem) +{ + const TreeItemType type = Internal::treeItemType(treeItem); + if (type == Internal::TreeItemType_Document) + return ApplicationItem(Internal::treeItemDocument(treeItem)); + else if (type == Internal::TreeItemType_DocumentItem) + return ApplicationItem(Internal::treeItemDocumentItem(treeItem)); + else if (type == Internal::TreeItemType_DocumentItemNode) + return ApplicationItem(Internal::treeItemDocumentItemNode(treeItem)); + + return ApplicationItem(); +} + +} // namespace Internal + +WidgetModelTree::WidgetModelTree(QWidget* widget) + : QWidget(widget), + m_ui(new Ui_WidgetModelTree) +{ + m_ui->setupUi(this); + m_ui->treeWidget_Model->setUniformRowHeights(true); + for (const Internal::PtrBuilder& ptrBuilder : Internal::arrayPrototypeBuilder()) { + m_vecBuilder.push_back(ptrBuilder->clone()); + m_vecBuilder.back()->setTreeWidget(m_ui->treeWidget_Model); + } + + // Add action "Remove item from document" + auto modelTreeBtns = new qtgui::ItemViewButtons(m_ui->treeWidget_Model, this); + constexpr int idBtnRemove = 1; + modelTreeBtns->addButton( + idBtnRemove, + mayoTheme()->icon(Theme::Icon::Cross), + tr("Remove from document")); + modelTreeBtns->setButtonDetection( + idBtnRemove, + Internal::TreeItemTypeRole, + QVariant(Internal::TreeItemType_DocumentItem)); + modelTreeBtns->setButtonDisplayColumn(idBtnRemove, 0); + modelTreeBtns->setButtonDisplayModes( + idBtnRemove, qtgui::ItemViewButtons::DisplayOnDetection); + modelTreeBtns->setButtonItemSide( + idBtnRemove, qtgui::ItemViewButtons::ItemRightSide); + const int iconSize = this->style()->pixelMetric(QStyle::PM_ListViewIconSize); + modelTreeBtns->setButtonIconSize( + idBtnRemove, QSize(iconSize * 0.66, iconSize * 0.66)); + modelTreeBtns->installDefaultItemDelegate(); + QObject::connect( + modelTreeBtns, &qtgui::ItemViewButtons::buttonClicked, + [=](int btnId, const QModelIndex& index) { + if (btnId == idBtnRemove) { + QTreeWidgetItem* treeItem = m_ui->treeWidget_Model->itemFromIndex(index); + DocumentItem* docItem = Internal::treeItemDocumentItem(treeItem); + docItem->document()->eraseRootItem(docItem); + } + }); + + auto app = Application::instance(); + QObject::connect( + app, &Application::documentAdded, + this, &WidgetModelTree::onDocumentAdded); + QObject::connect( + app, &Application::documentErased, + this, &WidgetModelTree::onDocumentErased); + QObject::connect( + app, &Application::documentPropertyChanged, + this, &WidgetModelTree::onDocumentPropertyChanged); + QObject::connect( + app, &Application::documentItemAdded, + this, &WidgetModelTree::onDocumentItemAdded); + QObject::connect( + app, &Application::documentItemErased, + this, &WidgetModelTree::onDocumentItemErased); + QObject::connect( + app, &Application::documentItemPropertyChanged, + this, &WidgetModelTree::onDocumentItemPropertyChanged); + QObject::connect( + m_ui->treeWidget_Model->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + &WidgetModelTree::onTreeWidgetDocumentSelectionChanged); +} + +WidgetModelTree::~WidgetModelTree() +{ + delete m_ui; + for (WidgetModelTreeBuilder* builder : m_vecBuilder) + delete builder; +} + +void WidgetModelTree::refreshItemText(const ApplicationItem& appItem) +{ + if (appItem.isDocument()) { + const Document* doc = appItem.document(); + QTreeWidgetItem* treeItem = this->findTreeItem(doc); + if (treeItem) + this->findSupportBuilder(doc)->refreshTextTreeItem(doc, treeItem); + } + else if (appItem.isDocumentItem()) { + const DocumentItem* docItem = appItem.documentItem(); + QTreeWidgetItem* treeItem = this->findTreeItem(docItem); + if (treeItem) + this->findSupportBuilder(docItem)->refreshTextTreeItem(docItem, treeItem); + } + else if (appItem.isDocumentItemNode()) { + const DocumentItem* docItem = appItem.documentItem(); + const DocumentItemNode& node = appItem.documentItemNode(); + QTreeWidgetItem* treeItemDocItem = this->findTreeItem(docItem); + if (treeItemDocItem) + this->findSupportBuilder(docItem)->refreshTextTreeItem(node, treeItemDocItem); + } +} + +void WidgetModelTree::loadConfiguration(const Settings* settings, const QString& keyGroup) +{ + const QString keyModel = keyGroup + "/" + this->objectName(); + for (WidgetModelTreeBuilder* builder : m_vecBuilder) + builder->loadConfiguration(settings, keyModel); +} + +void WidgetModelTree::saveConfiguration(Settings* settings, const QString& keyGroup) +{ + const QString keyModel = keyGroup + "/" + this->objectName(); + for (WidgetModelTreeBuilder* builder : m_vecBuilder) + builder->saveConfiguration(settings, keyModel); +} + +std::vector WidgetModelTree::createConfigurationActions(QObject* parent) +{ + std::vector vecAction; + for (WidgetModelTreeBuilder* builder : m_vecBuilder) { + for (QAction* action : builder->createConfigurationActions(parent)) + vecAction.push_back(action); + } + + return vecAction; +} + +void WidgetModelTree::addPrototypeBuilder(WidgetModelTreeBuilder* builder) +{ + Internal::arrayPrototypeBuilder().emplace_back(builder); +} + +DocumentItemNode WidgetModelTree::documentItemNode(const QTreeWidgetItem* treeItem) +{ + return Internal::treeItemDocumentItemNode(treeItem); +} + +void WidgetModelTree::setDocumentItemNode( + QTreeWidgetItem* treeItem, const DocumentItemNode& node) +{ + Internal::setTreeItemDocumentItemNode(treeItem, node); +} + +bool WidgetModelTree::holdsDocument(const QTreeWidgetItem* treeItem) +{ + return Internal::treeItemType(treeItem) == Internal::TreeItemType_Document; +} + +bool WidgetModelTree::holdsDocumentItem(const QTreeWidgetItem* treeItem) +{ + return Internal::treeItemType(treeItem) == Internal::TreeItemType_DocumentItem; +} + +bool WidgetModelTree::holdsDocumentItemNode(const QTreeWidgetItem* treeItem) +{ + return Internal::treeItemType(treeItem) == Internal::TreeItemType_DocumentItemNode; +} + +void WidgetModelTree::onDocumentAdded(Document* doc) +{ + auto treeItem = new QTreeWidgetItem; + this->findSupportBuilder(doc)->fillTreeItem(treeItem, doc); + Internal::setTreeItemDocument(treeItem, doc); + Q_ASSERT(Internal::treeItemDocument(treeItem) == doc); + m_ui->treeWidget_Model->addTopLevelItem(treeItem); +} + +void WidgetModelTree::onDocumentErased(const Document* doc) +{ + delete this->findTreeItem(doc); +} + +void WidgetModelTree::onDocumentPropertyChanged(Document* doc, Property* prop) +{ + QTreeWidgetItem* treeItem = this->findTreeItem(doc); + if (treeItem && prop == &doc->propertyLabel) + this->findSupportBuilder(doc)->refreshTextTreeItem(doc, treeItem); +} + +QTreeWidgetItem* WidgetModelTree::loadDocumentItem(DocumentItem* docItem) +{ + auto treeItem = new QTreeWidgetItem; + Internal::setTreeItemDocumentItem(treeItem, docItem); + this->findSupportBuilder(docItem)->fillTreeItem(treeItem, docItem); + return treeItem; +} + +QTreeWidgetItem* WidgetModelTree::findTreeItem(const Document* doc) const +{ + for (int i = 0; i < m_ui->treeWidget_Model->topLevelItemCount(); ++i) { + QTreeWidgetItem* treeItem = m_ui->treeWidget_Model->topLevelItem(i); + if (Internal::treeItemDocument(treeItem) == doc) + return treeItem; + } + + return nullptr; +} + +QTreeWidgetItem* WidgetModelTree::findTreeItem(const DocumentItem* docItem) const +{ + QTreeWidgetItem* treeItemDoc = this->findTreeItem(docItem->document()); + if (treeItemDoc) { + for (QTreeWidgetItemIterator it(treeItemDoc); *it; ++it) { + if (Internal::treeItemDocumentItem(*it) == docItem) + return *it; + } + } + + return nullptr; +} + +WidgetModelTreeBuilder* WidgetModelTree::findSupportBuilder(const Document* doc) const +{ + auto it = std::find_if( + std::next(m_vecBuilder.cbegin()), + m_vecBuilder.cend(), + [=](WidgetModelTreeBuilder* builder) { return builder->supports(doc); }); + return it != m_vecBuilder.cend() ? *it : m_vecBuilder.front(); +} + +WidgetModelTreeBuilder* WidgetModelTree::findSupportBuilder(const DocumentItem* docItem) const +{ + auto it = std::find_if( + std::next(m_vecBuilder.cbegin()), + m_vecBuilder.cend(), + [=](WidgetModelTreeBuilder* builder) { return builder->supports(docItem); }); + return it != m_vecBuilder.cend() ? *it : m_vecBuilder.front(); +} + +void WidgetModelTree::onDocumentItemAdded(DocumentItem* docItem) +{ + QTreeWidgetItem* treeDocItem = this->loadDocumentItem(docItem); + QTreeWidgetItem* treeDoc = this->findTreeItem(docItem->document()); + if (treeDoc) { + treeDoc->addChild(treeDocItem); + treeDoc->setExpanded(true); + } +} + +void WidgetModelTree::onDocumentItemErased(const DocumentItem* docItem) +{ + QTreeWidgetItem* treeItem = this->findTreeItem(docItem); + delete treeItem; +} + +void WidgetModelTree::onDocumentItemPropertyChanged( + DocumentItem* docItem, Property* prop) +{ + QTreeWidgetItem* treeItem = this->findTreeItem(docItem); + if (treeItem && prop == &docItem->propertyLabel) + this->findSupportBuilder(docItem)->refreshTextTreeItem(docItem, treeItem); +} + +void WidgetModelTree::onTreeWidgetDocumentSelectionChanged( + const QItemSelection& selected, const QItemSelection& deselected) +{ + const QModelIndexList listSelectedIndex = selected.indexes(); + const QModelIndexList listDeselectedIndex = deselected.indexes(); + std::vector vecSelected; + std::vector vecDeselected; + vecSelected.reserve(listSelectedIndex.size()); + vecDeselected.reserve(listDeselectedIndex.size()); + for (const QModelIndex& index : listSelectedIndex) { + const QTreeWidgetItem* treeItem = m_ui->treeWidget_Model->itemFromIndex(index); + vecSelected.push_back(std::move(Internal::toApplicationItem(treeItem))); + } + + for (const QModelIndex& index : listDeselectedIndex) { + const QTreeWidgetItem* treeItem = m_ui->treeWidget_Model->itemFromIndex(index); + vecDeselected.push_back(std::move(Internal::toApplicationItem(treeItem))); + } + + GuiApplication::instance()->selectionModel()->add(vecSelected); + GuiApplication::instance()->selectionModel()->remove(vecDeselected); + //emit selectionChanged(); +} + +} // namespace Mayo diff --git a/src/app/widget_model_tree.h b/src/app/widget_model_tree.h new file mode 100644 index 00000000..d68166ef --- /dev/null +++ b/src/app/widget_model_tree.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/application_item.h" +#include "../base/property.h" + +#include +class QItemSelection; +class QTreeWidget; +class QTreeWidgetItem; + +namespace Mayo { + +class Settings; +class WidgetModelTreeBuilder; + +class WidgetModelTree : public QWidget { + Q_OBJECT +public: + using Item = ApplicationItem; + + WidgetModelTree(QWidget* widget = nullptr); + ~WidgetModelTree(); + + void refreshItemText(const ApplicationItem& appItem); + + void loadConfiguration(const Settings* settings, const QString& keyGroup); + void saveConfiguration(Settings* settings, const QString& keyGroup); + + std::vector createConfigurationActions(QObject* parent); + + // For builders + static void addPrototypeBuilder(WidgetModelTreeBuilder* builder); + + static DocumentItemNode documentItemNode(const QTreeWidgetItem* treeItem); + static void setDocumentItemNode(QTreeWidgetItem* treeItem, const DocumentItemNode& node); + + static bool holdsDocument(const QTreeWidgetItem* treeItem); + static bool holdsDocumentItem(const QTreeWidgetItem* treeItem); + static bool holdsDocumentItemNode(const QTreeWidgetItem* treeItem); + +private: + void onDocumentAdded(Document* doc); + void onDocumentErased(const Document* doc); + void onDocumentPropertyChanged(Document* doc, Property* prop); + void onDocumentItemAdded(DocumentItem* docItem); + void onDocumentItemErased(const DocumentItem* docItem); + void onDocumentItemPropertyChanged(DocumentItem* docItem, Property* prop); + + void onTreeWidgetDocumentSelectionChanged( + const QItemSelection& selected, const QItemSelection& deselected); + + QTreeWidgetItem* loadDocumentItem(DocumentItem* docItem); + + QTreeWidgetItem* findTreeItem(const Document* doc) const; + QTreeWidgetItem* findTreeItem(const DocumentItem* docItem) const; + + WidgetModelTreeBuilder* findSupportBuilder(const Document* doc) const; + WidgetModelTreeBuilder* findSupportBuilder(const DocumentItem* docItem) const; + + class Ui_WidgetModelTree* m_ui = nullptr; + std::vector m_vecBuilder; + QString m_refItemTextTemplate; +}; + +} // namespace Mayo diff --git a/src/widget_application_tree.ui b/src/app/widget_model_tree.ui similarity index 69% rename from src/widget_application_tree.ui rename to src/app/widget_model_tree.ui index e0bf3d6f..4242431c 100644 --- a/src/widget_application_tree.ui +++ b/src/app/widget_model_tree.ui @@ -1,7 +1,7 @@ - Mayo::WidgetApplicationTree - + Mayo::WidgetModelTree + 0 @@ -27,10 +27,13 @@ 0 - + QAbstractItemView::ExtendedSelection + + Qt::ElideNone + false @@ -43,6 +46,13 @@
+ + + Mayo::Internal::TreeWidget + QTreeWidget +
widget_model_tree.h
+
+
diff --git a/src/app/widget_model_tree_builder.cpp b/src/app/widget_model_tree_builder.cpp new file mode 100644 index 00000000..d5c99b01 --- /dev/null +++ b/src/app/widget_model_tree_builder.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_model_tree_builder.h" + +#include "../base/document.h" +#include "../base/document_item.h" +#include "widget_model_tree.h" +#include "theme.h" + +#include +#include + +namespace Mayo { + +WidgetModelTreeBuilder::~WidgetModelTreeBuilder() +{ +} + +void WidgetModelTreeBuilder::refreshTextTreeItem( + const Document* doc, QTreeWidgetItem* treeItem) +{ + treeItem->setText(0, WidgetModelTreeBuilder::labelText(doc->propertyLabel)); +} + +void WidgetModelTreeBuilder::refreshTextTreeItem( + const DocumentItem* docItem, QTreeWidgetItem* treeItem) +{ + treeItem->setText(0, WidgetModelTreeBuilder::labelText(docItem->propertyLabel)); +} + +void WidgetModelTreeBuilder::refreshTextTreeItem( + const DocumentItemNode&, QTreeWidgetItem*) +{ +} + +void WidgetModelTreeBuilder::fillTreeItem(QTreeWidgetItem* treeItem, Document* doc) +{ + treeItem->setText(0, WidgetModelTreeBuilder::labelText(doc->propertyLabel)); + treeItem->setIcon(0, mayoTheme()->icon(Theme::Icon::File)); + treeItem->setToolTip(0, doc->filePath()); +} + +void WidgetModelTreeBuilder::fillTreeItem(QTreeWidgetItem* treeItem, DocumentItem* docItem) +{ + treeItem->setText(0, WidgetModelTreeBuilder::labelText(docItem->propertyLabel)); +} + +void WidgetModelTreeBuilder::loadConfiguration(const Settings*, const QString&) +{ +} + +void WidgetModelTreeBuilder::saveConfiguration(Settings*, const QString&) +{ +} + +std::vector WidgetModelTreeBuilder::createConfigurationActions(QObject*) +{ + std::vector vecAction; + return vecAction; +} + +WidgetModelTreeBuilder* WidgetModelTreeBuilder::clone() const +{ + return new WidgetModelTreeBuilder; +} + +QString WidgetModelTreeBuilder::labelText(const PropertyQString& propLabel) +{ + const QString label = propLabel.value(); + return !label.isEmpty() ? label : WidgetModelTree::tr(""); +} + +} // namespace Mayo diff --git a/src/app/widget_model_tree_builder.h b/src/app/widget_model_tree_builder.h new file mode 100644 index 00000000..76d2a4a5 --- /dev/null +++ b/src/app/widget_model_tree_builder.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/property_builtins.h" +#include +#include +class QAction; +class QObject; +class QTreeWidget; +class QTreeWidgetItem; + +namespace Mayo { + +class Document; +class DocumentItem; +struct DocumentItemNode; +class Settings; + +// TODO Rename Builder -> Extension ? +class WidgetModelTreeBuilder { +public: + virtual ~WidgetModelTreeBuilder(); + + virtual bool supports(const Document*) const { return true; } + virtual bool supports(const DocumentItem*) const { return true; } + + virtual void refreshTextTreeItem(const Document* doc, QTreeWidgetItem* treeItem); + virtual void refreshTextTreeItem(const DocumentItem* docItem, QTreeWidgetItem* treeItem); + virtual void refreshTextTreeItem(const DocumentItemNode& node, QTreeWidgetItem* treeItemDocItem); + + virtual void fillTreeItem(QTreeWidgetItem* treeItem, Document* doc); + virtual void fillTreeItem(QTreeWidgetItem* treeItem, DocumentItem* docItem); + + QTreeWidget* treeWidget() const { return m_treeWidget; } + void setTreeWidget(QTreeWidget* tree) { m_treeWidget = tree; } + + virtual void loadConfiguration(const Settings* settings, const QString& keyGroup); + virtual void saveConfiguration(Settings* settings, const QString& keyGroup); + + virtual std::vector createConfigurationActions(QObject* parent); + + virtual WidgetModelTreeBuilder* clone() const; + +protected: + static QString labelText(const PropertyQString& propLabel); + +private: + QTreeWidget* m_treeWidget = nullptr; +}; + +} // namespace Mayo diff --git a/src/app/widget_model_tree_builder_mesh.cpp b/src/app/widget_model_tree_builder_mesh.cpp new file mode 100644 index 00000000..7bac4cda --- /dev/null +++ b/src/app/widget_model_tree_builder_mesh.cpp @@ -0,0 +1,34 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_model_tree_builder_mesh.h" + +#include "../base/mesh_item.h" +#include "theme.h" +#include "widget_model_tree.h" + +#include + +namespace Mayo { + +bool WidgetModelTreeBuilder_Mesh::supports(const DocumentItem* docItem) const +{ + return sameType(docItem); +} + +void WidgetModelTreeBuilder_Mesh::fillTreeItem(QTreeWidgetItem* treeItem, DocumentItem* docItem) +{ + WidgetModelTreeBuilder::fillTreeItem(treeItem, docItem); + Q_ASSERT(this->supports(docItem)); + treeItem->setIcon(0, mayoTheme()->icon(Theme::Icon::ItemMesh)); +} + +WidgetModelTreeBuilder* WidgetModelTreeBuilder_Mesh::clone() const +{ + return new WidgetModelTreeBuilder_Mesh; +} + +} // namespace Mayo diff --git a/src/app/widget_model_tree_builder_mesh.h b/src/app/widget_model_tree_builder_mesh.h new file mode 100644 index 00000000..54382927 --- /dev/null +++ b/src/app/widget_model_tree_builder_mesh.h @@ -0,0 +1,21 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "widget_model_tree_builder.h" + +namespace Mayo { + +class WidgetModelTreeBuilder_Mesh : public WidgetModelTreeBuilder { +public: + bool supports(const DocumentItem* docItem) const override; + void fillTreeItem(QTreeWidgetItem* treeItem, DocumentItem* docItem) override; + + WidgetModelTreeBuilder* clone() const override; +}; + +} // namespace Mayo diff --git a/src/app/widget_model_tree_builder_xde.cpp b/src/app/widget_model_tree_builder_xde.cpp new file mode 100644 index 00000000..f78af80d --- /dev/null +++ b/src/app/widget_model_tree_builder_xde.cpp @@ -0,0 +1,256 @@ +#include "widget_model_tree_builder_xde.h" + +#include "../base/xde_document_item.h" +#include "settings.h" +#include "theme.h" +#include "widget_model_tree.h" + +#include +#include +#include + +#include +#include + +namespace Mayo { + +namespace Internal { + +static QIcon shapeIcon(const TDF_Label& label) +{ + if (XdeDocumentItem::isShapeAssembly(label)) + return mayoTheme()->icon(Theme::Icon::XdeAssembly); + else if (XdeDocumentItem::isShapeReference(label)) + return QIcon(":/images/xde_reference_16.png"); // TODO move in Theme + else if (XdeDocumentItem::isShapeSimple(label)) + return mayoTheme()->icon(Theme::Icon::XdeSimpleShape); + + return QIcon(); +} + +static const char textTemplateReferenceOnly[] = "%instance"; +static const char textTemplateReferredOnly[] = "%referred"; +// UTF8 rightwards arrow : \xe2\x86\x92 +static const char textTemplateReferenceAndReferred[] = "%instance \xe2\x86\x92 %referred"; + +static const char keyRefItemTextTemplate[] = "/xde/reference_item_text_template"; + +} // namespace Internal + +WidgetModelTreeBuilder_Xde::WidgetModelTreeBuilder_Xde() + : m_refItemTextTemplate("%instance") +{ +} + +bool WidgetModelTreeBuilder_Xde::supports(const DocumentItem* docItem) const +{ + return sameType(docItem); +} + +void WidgetModelTreeBuilder_Xde::refreshTextTreeItem( + const DocumentItemNode& node, QTreeWidgetItem* treeItemDocItem) +{ + const TDF_Label labelNode = XdeDocumentItem::label(node); + TDF_LabelSequence seqLabelRefresh; + if (XdeDocumentItem::isShapeReference(labelNode) + && m_refItemTextTemplate.contains("%referred")) + { + XCAFDoc_ShapeTool::GetUsers( + XdeDocumentItem::shapeReferred(labelNode), + seqLabelRefresh, + false /* don't get sub children */); + } + else { + seqLabelRefresh.Append(labelNode); + } + + for (const TDF_Label& labelRefresh : seqLabelRefresh) { + QTreeWidgetItem* treeItemLabel = this->findTreeItem(treeItemDocItem, labelRefresh); + if (treeItemLabel) + this->refreshXdeAssemblyNodeItemText(treeItemLabel); + } +} + +void WidgetModelTreeBuilder_Xde::fillTreeItem(QTreeWidgetItem* treeItem, DocumentItem* docItem) +{ + WidgetModelTreeBuilder::fillTreeItem(treeItem, docItem); + Q_ASSERT(this->supports(docItem)); + treeItem->setIcon(0, mayoTheme()->icon(Theme::Icon::ItemXde)); + auto xdeDocItem = static_cast(docItem); + this->buildXdeTree(treeItem, xdeDocItem); +} + +QTreeWidgetItem* WidgetModelTreeBuilder_Xde::guiCreateXdeTreeNode( + QTreeWidgetItem* guiParentNode, TreeNodeId nodeId, XdeDocumentItem* docItem) +{ + auto guiNode = new QTreeWidgetItem(guiParentNode); + const QString stdName = docItem->findLabelName(nodeId); + guiNode->setText(0, stdName); + WidgetModelTree::setDocumentItemNode(guiNode, DocumentItemNode(docItem, nodeId)); + const QIcon icon = Internal::shapeIcon(docItem->assemblyTree().nodeData(nodeId)); + if (!icon.isNull()) + guiNode->setIcon(0, icon); + + return guiNode; +} + +void WidgetModelTreeBuilder_Xde::buildXdeTree( + QTreeWidgetItem* treeItem, XdeDocumentItem* docItem) +{ + std::unordered_map mapNodeIdToTreeItem; + std::unordered_set setRefNodeId; + const Tree& asmTree = docItem->assemblyTree(); + deepForeachTreeNode(asmTree, [&](TreeNodeId nodeId) { + const TreeNodeId nodeParentId = asmTree.nodeParent(nodeId); + const TDF_Label& nodeLabel = asmTree.nodeData(nodeId); + auto itParentFound = mapNodeIdToTreeItem.find(nodeParentId); + QTreeWidgetItem* guiParentNode = + itParentFound != mapNodeIdToTreeItem.end() ? + itParentFound->second : treeItem; + if (m_isMergeXdeReferredShapeOn) { + if (XdeDocumentItem::isShapeReference(nodeLabel)) { + mapNodeIdToTreeItem.insert({ nodeId, guiParentNode }); + setRefNodeId.insert(nodeId); + } + else { + auto guiNode = new QTreeWidgetItem(guiParentNode); + QString guiNodeText = XdeDocumentItem::findLabelName(nodeLabel); + TreeNodeId guiNodeId = nodeId; + if (setRefNodeId.find(nodeParentId) != setRefNodeId.cend()) { + const TDF_Label& refLabel = asmTree.nodeData(nodeParentId); + guiNodeText = this->referenceItemText(refLabel, nodeLabel); + guiNodeId = nodeParentId; + } + + guiNode->setText(0, guiNodeText); + WidgetModelTree::setDocumentItemNode( + guiNode, DocumentItemNode(docItem, guiNodeId)); + const QIcon icon = Internal::shapeIcon(nodeLabel); + if (!icon.isNull()) + guiNode->setIcon(0, icon); + + mapNodeIdToTreeItem.insert({ nodeId, guiNode }); + } + } + else { + auto guiNode = ThisType::guiCreateXdeTreeNode(guiParentNode, nodeId, docItem); + mapNodeIdToTreeItem.insert({ nodeId, guiNode }); + } + }); +} + +const QString& WidgetModelTreeBuilder_Xde::referenceItemTextTemplate() const +{ + return m_refItemTextTemplate; +} + +void WidgetModelTreeBuilder_Xde::setReferenceItemTextTemplate(const QString& textTemplate) +{ + if (textTemplate == m_refItemTextTemplate) + return; + + m_refItemTextTemplate = textTemplate; + for (QTreeWidgetItemIterator it(this->treeWidget()); *it; ++it) { + if (WidgetModelTree::holdsDocumentItemNode(*it)) + this->refreshXdeAssemblyNodeItemText(*it); + } +} + +void WidgetModelTreeBuilder_Xde::loadConfiguration( + const Settings* settings, const QString& keyGroup) +{ + const QString refTextTemplate = + settings->valueAs(keyGroup + Internal::keyRefItemTextTemplate); + this->setReferenceItemTextTemplate( + !refTextTemplate.isEmpty() ? refTextTemplate : Internal::textTemplateReferenceOnly); +} + +void WidgetModelTreeBuilder_Xde::saveConfiguration( + Settings* settings, const QString& keyGroup) +{ + settings->setValue( + keyGroup + Internal::keyRefItemTextTemplate, + m_refItemTextTemplate); +} + +std::vector WidgetModelTreeBuilder_Xde::createConfigurationActions(QObject* parent) +{ + // Note + // UTF8 rightwards arrow : \xe2\x86\x92 + + std::vector vecAction; + vecAction.push_back(new QAction(tr("Show only name of reference entities"), parent)); + vecAction.push_back(new QAction(tr("Show only name of referred entities"), parent)); + vecAction.push_back(new QAction(tr("Show name of both reference and referred entities"), parent)); + vecAction.at(0)->setData(Internal::textTemplateReferenceOnly); + vecAction.at(1)->setData(Internal::textTemplateReferredOnly); + vecAction.at(2)->setData(Internal::textTemplateReferenceAndReferred); + auto group = new QActionGroup(parent); + group->setExclusive(true); + for (QAction* action : vecAction) { + action->setCheckable(true); + group->addAction(action); + if (action->data().toString() == m_refItemTextTemplate) + action->setChecked(true); + } + + QObject::connect(group, &QActionGroup::triggered, [=](QAction* action) { + this->setReferenceItemTextTemplate(action->data().toString()); + }); + + return vecAction; +} + +WidgetModelTreeBuilder* WidgetModelTreeBuilder_Xde::clone() const +{ + auto builder = new WidgetModelTreeBuilder_Xde; + builder->m_isMergeXdeReferredShapeOn = this->m_isMergeXdeReferredShapeOn; + builder->m_refItemTextTemplate = this->m_refItemTextTemplate; + return builder; +} + +void WidgetModelTreeBuilder_Xde::refreshXdeAssemblyNodeItemText(QTreeWidgetItem* item) +{ + const DocumentItemNode docItemNode = WidgetModelTree::documentItemNode(item); + if (!sameType(docItemNode.documentItem)) + return; + + const TDF_Label label = XdeDocumentItem::label(docItemNode); + if (XdeDocumentItem::isShapeReference(label)) { + const TDF_Label& refLabel = label; + const TDF_Label referredLabel = XdeDocumentItem::shapeReferred(refLabel); + const QString itemText = this->referenceItemText(refLabel, referredLabel); + item->setText(0, itemText); + } + else { + item->setText(0, XdeDocumentItem::findLabelName(label)); + } +} + +QString WidgetModelTreeBuilder_Xde::referenceItemText( + const TDF_Label& refLabel, const TDF_Label& referredLabel) const +{ + const QString refName = XdeDocumentItem::findLabelName(refLabel).trimmed(); + const QString referredName = XdeDocumentItem::findLabelName(referredLabel).trimmed(); + QString itemText = m_refItemTextTemplate; + itemText.replace("%instance", refName) + .replace("%referred", referredName); + return itemText; +} + +QTreeWidgetItem* WidgetModelTreeBuilder_Xde::findTreeItem( + QTreeWidgetItem* parentTreeItem, const TDF_Label& label) const +{ + if (!parentTreeItem) + return nullptr; + + for (QTreeWidgetItemIterator it(parentTreeItem); *it; ++it) { + const DocumentItemNode docItemNode = WidgetModelTree::documentItemNode(*it); + if (XdeDocumentItem::label(docItemNode) == label) + return *it; + } + + return nullptr; +} + +} // namespace Mayo diff --git a/src/app/widget_model_tree_builder_xde.h b/src/app/widget_model_tree_builder_xde.h new file mode 100644 index 00000000..3deee70c --- /dev/null +++ b/src/app/widget_model_tree_builder_xde.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/libtree.h" +#include "widget_model_tree_builder.h" +#include +class TDF_Label; + +namespace Mayo { + +class XdeDocumentItem; + +class WidgetModelTreeBuilder_Xde : public WidgetModelTreeBuilder { + Q_DECLARE_TR_FUNCTIONS(WidgetModelTreeBuilder_Xde) +public: + WidgetModelTreeBuilder_Xde(); + + bool supports(const DocumentItem* docItem) const override; + void refreshTextTreeItem(const DocumentItemNode& node, QTreeWidgetItem* treeItemDocItem) override; + void fillTreeItem(QTreeWidgetItem* treeItem, DocumentItem* docItem) override; + + void loadConfiguration(const Settings* settings, const QString& keyGroup) override; + void saveConfiguration(Settings* settings, const QString& keyGroup) override; + std::vector createConfigurationActions(QObject* parent) override; + + WidgetModelTreeBuilder* clone() const override; + + const QString& referenceItemTextTemplate() const; + void setReferenceItemTextTemplate(const QString& textTemplate); + +private: + using ThisType = WidgetModelTreeBuilder_Xde; + using ParentType = WidgetModelTreeBuilder; + + static QTreeWidgetItem* guiCreateXdeTreeNode( + QTreeWidgetItem* guiParentNode, + TreeNodeId nodeId, + XdeDocumentItem* docItem); + + void buildXdeTree(QTreeWidgetItem* treeItem, XdeDocumentItem* docItem); + void refreshXdeAssemblyNodeItemText(QTreeWidgetItem* item); + QString referenceItemText( + const TDF_Label& refLabel, + const TDF_Label& referredLabel) const; + QTreeWidgetItem* findTreeItem( + QTreeWidgetItem* parentTreeItem, const TDF_Label& label) const; + + bool m_isMergeXdeReferredShapeOn = true; + QString m_refItemTextTemplate; +}; + +} // namespace Mayo diff --git a/src/app/widget_occ_view.cpp b/src/app/widget_occ_view.cpp new file mode 100644 index 00000000..51e39828 --- /dev/null +++ b/src/app/widget_occ_view.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_occ_view.h" +#include "occt_window.h" + +#include + +namespace Mayo { + +WidgetOccView::WidgetOccView(const Handle_V3d_View& view, QWidget* parent) + : QWidget(parent), + m_view(view) +{ + this->setMouseTracking(true); + + // Avoid Qt background clears to improve resizing speed + this->setAutoFillBackground(false); + this->setAttribute(Qt::WA_NoSystemBackground); + this->setAttribute(Qt::WA_PaintOnScreen); + this->setBackgroundRole(QPalette::NoRole); +} + +const Handle_V3d_View &WidgetOccView::v3dView() const +{ + return m_view; +} + +QPaintEngine* WidgetOccView::paintEngine() const +{ + return nullptr; +} + +void WidgetOccView::showEvent(QShowEvent*) +{ + if (m_view->Window().IsNull()) { + Handle_Aspect_Window hWnd = new OcctWindow(this); + m_view->SetWindow(hWnd); + if (!hWnd->IsMapped()) + hWnd->Map(); + m_view->MustBeResized(); + } +} + +void WidgetOccView::paintEvent(QPaintEvent*) +{ + m_view->Redraw(); +} + +void WidgetOccView::resizeEvent(QResizeEvent* event) +{ + if (!event->spontaneous()) // Workaround for infinite window shrink on Ubuntu + m_view->MustBeResized(); +} + +} // namespace Mayo diff --git a/src/app/widget_occ_view.h b/src/app/widget_occ_view.h new file mode 100644 index 00000000..994690ac --- /dev/null +++ b/src/app/widget_occ_view.h @@ -0,0 +1,36 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +//! Qt wrapper around the V3d_View class +//! +//! WidgetOccView does not handle input devices interaction like keyboard and +//! mouse. +class WidgetOccView : public QWidget { + Q_OBJECT +public: + WidgetOccView(const Handle_V3d_View& view, QWidget* parent = nullptr); + + const Handle_V3d_View& v3dView() const; + + QPaintEngine* paintEngine() const override; + +protected: + void showEvent(QShowEvent* event) override; + void paintEvent(QPaintEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + +private: + Handle_V3d_View m_view; +}; + +} // namespace Mayo diff --git a/src/app/widget_occ_view_controller.cpp b/src/app/widget_occ_view_controller.cpp new file mode 100644 index 00000000..2bf76b4c --- /dev/null +++ b/src/app/widget_occ_view_controller.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_occ_view_controller.h" +#include "widget_occ_view.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static const QCursor& rotateCursor() +{ + static QCursor cursor; + if (!cursor.bitmap()) { + const int rotateCursorWidth = 16; + const int rotateCursorHeight = 16; + const int rotateCursorByteCount = + ((rotateCursorWidth + 7) / 8) * rotateCursorHeight; + const int rotateCursorHotX = 6; + const int rotateCursorHotY = 8; + + static unsigned char rotateCursorBitmap[rotateCursorByteCount] = { + 0xf0, 0xef, 0x18, 0xb8, 0x0c, 0x90, 0xe4, 0x83, + 0x34, 0x86, 0x1c, 0x83, 0x00, 0x81, 0x00, 0xff, + 0xff, 0x00, 0x81, 0x00, 0xc1, 0x38, 0x61, 0x2c, + 0xc1, 0x27, 0x09, 0x30, 0x1d, 0x18, 0xf7, 0x0f + }; + + static unsigned char rotateCursorMaskBitmap[rotateCursorByteCount] = { + 0xf0,0xef,0xf8,0xff,0xfc,0xff,0xfc,0xff,0x3c,0xfe,0x1c,0xff,0x00,0xff,0x00, + 0xff,0xff,0x00,0xff,0x00,0xff,0x38,0x7f,0x3c,0xff,0x3f,0xff,0x3f,0xff,0x1f, + 0xf7,0x0f + }; + + const QBitmap cursorBmp = QBitmap::fromData( + QSize(rotateCursorWidth, rotateCursorHeight), + rotateCursorBitmap); + const QBitmap maskBmp = QBitmap::fromData( + QSize(rotateCursorWidth, rotateCursorHeight), + rotateCursorMaskBitmap); + const QCursor tempCursor( + cursorBmp, maskBmp, rotateCursorHotX, rotateCursorHotY); + cursor = std::move(tempCursor); + } + return cursor; +} + +} // namespace Internal + +WidgetOccViewController::WidgetOccViewController(WidgetOccView* widgetView) + : V3dViewController(widgetView->v3dView(), widgetView), + m_widgetView(widgetView), + m_prevCamera(new Graphic3d_Camera) +{ + widgetView->installEventFilter(this); +} + +bool WidgetOccViewController::eventFilter(QObject* watched, QEvent* event) +{ + if (watched != m_widgetView) + return false; + + Handle_V3d_View view = m_widgetView->v3dView(); + switch (event->type()) { + case QEvent::Enter: { + m_widgetView->grabKeyboard(); + break; + } + case QEvent::Leave: { + m_widgetView->releaseKeyboard(); + break; + } + case QEvent::KeyPress: { + auto keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Space + && keyEvent->modifiers() == Qt::NoModifier + && !keyEvent->isAutoRepeat()) + { + this->startDynamicAction(DynamicAction::InstantZoom); + m_prevCamera->Copy(view->Camera()); + const QPoint currPos = m_widgetView->mapFromGlobal(QCursor::pos()); + const int factor = 5; + const int dX = factor * 100; + view->StartZoomAtPoint(currPos.x(), currPos.y()); + view->ZoomAtPoint(currPos.x(), currPos.y(), currPos.x() + dX, currPos.y()); + } + + break; + } + case QEvent::KeyRelease: { + auto keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Space + && !keyEvent->isAutoRepeat() + && this->currentDynamicAction() == DynamicAction::InstantZoom) + { + this->stopDynamicAction(); + view->Camera()->Copy(m_prevCamera); + view->Update(); + } + + break; + } + case QEvent::MouseButtonPress: { + auto mouseEvent = static_cast(event); + const QPoint currPos = m_widgetView->mapFromGlobal(mouseEvent->globalPos()); + m_prevPos = currPos; + break; + } + case QEvent::MouseMove: { + auto mouseEvent = static_cast(event); + const QPoint currPos = m_widgetView->mapFromGlobal(mouseEvent->globalPos()); + const QPoint prevPos = m_prevPos; + m_prevPos = currPos; + if (mouseEvent->buttons() == Qt::LeftButton) { + if (!this->isRotationStarted()) { + this->setViewCursor(Internal::rotateCursor()); + this->startDynamicAction(DynamicAction::Rotation); + view->StartRotation(prevPos.x(), prevPos.y()); + } + + view->Rotation(currPos.x(), currPos.y()); + } + else if (mouseEvent->buttons() == Qt::RightButton) { + if (!this->isPanningStarted()) { + this->setViewCursor(Qt::SizeAllCursor); + this->startDynamicAction(DynamicAction::Panning); + } + + view->Pan(currPos.x() - prevPos.x(), prevPos.y() - currPos.y()); + } + else if (mouseEvent->buttons() == Qt::MiddleButton) { + if (!this->isWindowZoomingStarted()) { + this->setViewCursor(Qt::SizeBDiagCursor); + this->startDynamicAction(DynamicAction::WindowZoom); + m_posRubberBandStart = currPos; + } + + this->drawRubberBand(m_posRubberBandStart, currPos); + } + else { + emit mouseMoved(currPos); + } + + break; + } + case QEvent::MouseButtonRelease: { + auto mouseEvent = static_cast(event); + const bool hadDynamicAction = this->hasCurrentDynamicAction(); + if (this->isWindowZoomingStarted()) { + const QPoint currPos = m_widgetView->mapFromGlobal(mouseEvent->globalPos()); + this->windowFitAll(m_posRubberBandStart, currPos); + this->hideRubberBand(); + } + + this->setViewCursor(Qt::ArrowCursor); + this->stopDynamicAction(); + if (!hadDynamicAction) + emit mouseClicked(mouseEvent->button()); + + break; + } + case QEvent::Wheel: { + auto wheelEvent = static_cast(event); + if (wheelEvent->delta() > 0) + this->zoomIn(); + else + this->zoomOut(); + + break; + } + default: + break; + } // end switch + + return false; +} + +void WidgetOccViewController::setViewCursor(const QCursor &cursor) +{ + if (m_widgetView) + m_widgetView->setCursor(cursor); +} + +struct WidgetOccViewController::RubberBand : public V3dViewController::AbstractRubberBand { + RubberBand(QWidget* parent) + : m_rubberBand(QRubberBand::Rectangle, parent) + { + // QWidget::setStyle() is important, set to windows style will just draw + // rectangle frame, otherwise will draw a solid rectangle. + m_rubberBand.setStyle(QStyleFactory::create("windows")); + } + + void updateGeometry(const QRect& rect) override { + m_rubberBand.setGeometry(rect); + } + + void setVisible(bool on) override { + m_rubberBand.setVisible(on); + } + +private: + QRubberBand m_rubberBand; +}; + +V3dViewController::AbstractRubberBand* WidgetOccViewController::createRubberBand() +{ + return new RubberBand(m_widgetView); +} + +} // namespace Mayo diff --git a/src/app/widget_occ_view_controller.h b/src/app/widget_occ_view_controller.h new file mode 100644 index 00000000..eadb7ea5 --- /dev/null +++ b/src/app/widget_occ_view_controller.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../gpx/v3d_view_controller.h" + +#include +class QCursor; +class QRubberBand; + +namespace Mayo { + +class WidgetOccView; + +class WidgetOccViewController : public V3dViewController { + Q_OBJECT +public: + WidgetOccViewController(WidgetOccView* widgetView = nullptr); + + bool eventFilter(QObject* watched, QEvent* event) override; + +private: + void setViewCursor(const QCursor& cursor); + + AbstractRubberBand* createRubberBand() override; + struct RubberBand; + + WidgetOccView* m_widgetView = nullptr; + QPoint m_prevPos; + QPoint m_posRubberBandStart; + Handle_Graphic3d_Camera m_prevCamera; +}; + +} // namespace Mayo diff --git a/src/app/widget_properties_editor.cpp b/src/app/widget_properties_editor.cpp new file mode 100644 index 00000000..ac260639 --- /dev/null +++ b/src/app/widget_properties_editor.cpp @@ -0,0 +1,765 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_properties_editor.h" + +#include "../base/document.h" +#include "../base/document_item.h" +#include "../base/string_utils.h" +#include "../base/unit_system.h" +#include "../gpx/gpx_document_item.h" +#include "../gui/gui_application.h" +#include "../gui/gui_document.h" +#include "settings.h" +#include "settings_keys.h" +#include "theme.h" +#include "ui_widget_properties_editor.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +class PanelEditor : public QWidget { +public: + PanelEditor(QWidget* parent = nullptr) + : QWidget(parent) + {} + +protected: + void paintEvent(QPaintEvent*) override + { + QPainter painter(this); + + // This is needed by the "classic" theme, force a painted background + const QRect frame = this->frameGeometry(); + const QRect surface(0, 0, frame.width(), frame.height()); + const QColor panelColor = palette().color(QPalette::Base); + painter.fillRect(surface, panelColor); + + QStyleOption option; + option.initFrom(this); + option.state |= QStyle::State_HasFocus; + this->style()->drawPrimitive(QStyle::PE_FrameLineEdit, &option, &painter, this); + } +}; + +static QPixmap colorSquarePixmap(const QColor& c, int sideLen = 16) +{ + QPixmap pixColor(sideLen, sideLen); + pixColor.fill(c); + return pixColor; +} + +static QWidget* hSpacerWidget(QWidget* parent, int stretch = 1) +{ + auto widget = new QWidget(parent); + QSizePolicy sp = widget->sizePolicy(); + sp.setHorizontalStretch(stretch); + widget->setSizePolicy(sp); + return widget; +} + +static QString yesNoString(bool on) +{ + return on ? WidgetPropertiesEditor::tr("Yes") : WidgetPropertiesEditor::tr("No"); +} + +static QString toStringDHMS(QuantityTime time) +{ + const double duration_s = UnitSystem::seconds(time); + const double days = duration_s / 86400.; + const int dayCount = std::floor(days); + const double hours = (days - dayCount) * 24; + const int hourCount = std::floor(hours); + const double mins = (hours - hourCount) * 60; + const int minCount = std::floor(mins); + const double secs = (mins - minCount) * 60; + const int secCount = std::floor(secs); + QString text; + if (dayCount > 0) + text += WidgetPropertiesEditor::tr("%1d ").arg(dayCount); + if (hourCount > 0) + text += WidgetPropertiesEditor::tr("%1h ").arg(hourCount); + if (minCount > 0) + text += WidgetPropertiesEditor::tr("%1min ").arg(minCount); + if (secCount > 0) + text += WidgetPropertiesEditor::tr("%1s").arg(secCount); + return text.trimmed(); +} + +static UnitSystem::TranslateResult unitTranslate(const BasePropertyQuantity* prop) +{ + if (prop->quantityUnit() == Unit::Angle) { + auto propAngle = static_cast(prop); + return UnitSystem::degrees(propAngle->quantity()); + } + + return UnitSystem::translate( + Settings::instance()->unitSystemSchema(), + prop->quantityValue(), + prop->quantityUnit()); +} + +static QString propertyValueText(const PropertyBool* prop) { + return yesNoString(prop->value()); +} + +static QString propertyValueText(const PropertyInt* prop) { + return Settings::instance()->locale().toString(prop->value()); +} + +static QString propertyValueText(const PropertyDouble* prop) { + return StringUtils::text(prop->value(), Settings::instance()->defaultTextOptions()); +} + +static QString propertyValueText(const PropertyQByteArray* prop) { + return QString::fromUtf8(prop->value()); +} + +static QString propertyValueText(const PropertyQString* prop) { + return prop->value(); +} + +static QString propertyValueText(const PropertyQDateTime* prop) { + return Settings::instance()->locale().toString(prop->value()); +} + +static QString propertyValueText(const PropertyOccColor* prop) { + return StringUtils::text(prop->value()); +} + +static QString propertyValueText(const PropertyOccPnt* prop) { + return StringUtils::text(prop->value(), Settings::instance()->defaultTextOptions()); +} + +static QString propertyValueText(const PropertyOccTrsf* prop) { + return StringUtils::text(prop->value(), Settings::instance()->defaultTextOptions()); +} + +static QString propertyValueText(const PropertyEnumeration* prop) +{ + for (const Enumeration::Item& enumItem : prop->enumeration().items()) { + if (enumItem.value == prop->value()) + return enumItem.name; + } + + return QString(); +} + +static QString propertyValueText(const BasePropertyQuantity* prop) +{ + if (prop->quantityUnit() == Unit::Time) { + auto propTime = static_cast(prop); + return toStringDHMS(propTime->quantity()); + } + + const UnitSystem::TranslateResult trRes = unitTranslate(prop); + return WidgetPropertiesEditor::tr("%1%2") + .arg(StringUtils::text(trRes.value, Settings::instance()->defaultTextOptions())) + .arg(trRes.strUnit); +} + +static QString propertyValueText( + const BasePropertyQuantity* prop, + const WidgetPropertiesEditor::UnitTranslation& unitTr) +{ + const double trValue = prop->quantityValue() * unitTr.factor; + return WidgetPropertiesEditor::tr("%1%2") + .arg(StringUtils::text(trValue, Settings::instance()->defaultTextOptions())) + .arg(unitTr.strUnit); +} + +static bool handlePropertyValidationError( + const Result& resultValidation, + QWidget* propertyEditor, + const std::function& fnCallbackError = nullptr) +{ + if (!resultValidation) { + qtgui::QWidgetUtils::asyncMsgBoxCritical( + propertyEditor->parentWidget(), + WidgetPropertiesEditor::tr("Error"), + resultValidation.errorText()); + QSignalBlocker sigBlock(propertyEditor); Q_UNUSED(sigBlock); + if (fnCallbackError) + fnCallbackError(); + } + + return resultValidation.valid(); +} + +static QWidget* createPropertyEditor(BasePropertyQuantity* prop, QWidget* parent) +{ + auto editor = new QDoubleSpinBox(parent); + const UnitSystem::TranslateResult trRes = unitTranslate(prop); + editor->setSuffix(QString::fromUtf8(trRes.strUnit)); + editor->setDecimals(Settings::instance()->unitSystemDecimals()); + const double rangeMin = + prop->constraintsEnabled() ? + prop->minimum() : std::numeric_limits::min(); + const double rangeMax = + prop->constraintsEnabled() ? + prop->maximum() : std::numeric_limits::max(); + editor->setRange(rangeMin, rangeMax); + editor->setValue(trRes.value); + QObject::connect(editor, &QDoubleSpinBox::editingFinished, [=]{ + double value = editor->value(); + const double f = trRes.factor; + value = qFuzzyCompare(f, 1.) ? value : value * f; + if (!qFuzzyCompare(prop->quantityValue(), value)) { + const Result result = prop->setQuantityValue(value); + handlePropertyValidationError(result, editor, [=]{ + editor->setValue(trRes.value); + }); + } + }); + return editor; +} + +static QWidget* createPanelEditor(QWidget* parent) +{ + auto frame = new PanelEditor(parent); + auto layout = new QHBoxLayout(frame); + layout->setContentsMargins(2, 0, 0, 0); + return frame; +} + +static QWidget* createPropertyEditor(PropertyBool* prop, QWidget* parent) +{ + auto frame = createPanelEditor(parent); + auto editor = new QCheckBox(frame); + frame->layout()->addWidget(editor); + editor->setText(yesNoString(prop->value())); + editor->setChecked(prop->value()); + QObject::connect(editor, &QCheckBox::toggled, [=](bool on) { + const Result result = prop->setValue(on); + handlePropertyValidationError(result, editor, [=]{ + editor->setChecked(prop->value()); + }); + editor->setText(yesNoString(prop->value())); + }); + return frame; +} + +static QWidget* createPropertyEditor(PropertyInt* prop, QWidget* parent) +{ + auto editor = new QSpinBox(parent); + if (prop->constraintsEnabled()) { + editor->setRange(prop->minimum(), prop->maximum()); + editor->setSingleStep(prop->singleStep()); + } + + editor->setValue(prop->value()); + QObject::connect(editor, qOverload(&QSpinBox::valueChanged), [=](int val) { + const Result result = prop->setValue(val); + handlePropertyValidationError(result, editor, [=]{ + editor->setValue(prop->value()); + }); + }); + return editor; +} + +static QWidget* createPropertyEditor(PropertyDouble* prop, QWidget* parent) +{ + auto editor = new QDoubleSpinBox(parent); + if (prop->constraintsEnabled()) { + editor->setRange(prop->minimum(), prop->maximum()); + editor->setSingleStep(prop->singleStep()); + } + editor->setValue(prop->value()); + editor->setDecimals(Settings::instance()->unitSystemDecimals()); + QObject::connect(editor, qOverload(&QDoubleSpinBox::valueChanged), [=](double val) { + const Result result = prop->setValue(val); + handlePropertyValidationError(result, editor, [=]{ + editor->setValue(prop->value()); + }); + }); + return editor; +} + +static QWidget* createPropertyEditor(PropertyQString* prop, QWidget* parent) +{ + auto editor = new QLineEdit(parent); + editor->setText(prop->value()); + QObject::connect(editor, &QLineEdit::textChanged, [=](const QString& text) { + const Result result = prop->setValue(text); + handlePropertyValidationError(result, editor, [=]{ + editor->setText(prop->value()); + }); + }); + return editor; +} + +static QWidget* createPropertyEditor(PropertyEnumeration* prop, QWidget* parent) +{ + auto editor = new QComboBox(parent); + const Enumeration& enumDef = prop->enumeration(); + for (const Enumeration::Item& enumItem : enumDef.items()) + editor->addItem(enumItem.name, enumItem.value); + + editor->setCurrentIndex(editor->findData(prop->value())); + QObject::connect(editor, qOverload(&QComboBox::activated), [=](int index) { + const Result result = prop->setValue(editor->itemData(index).toInt()); + handlePropertyValidationError(result, editor, [=]{ + editor->setCurrentIndex(editor->findData(prop->value())); + }); + }); + return editor; +} + +static QWidget* createPropertyEditor(PropertyOccColor* prop, QWidget* parent) +{ + auto frame = createPanelEditor(parent); + + auto labelColor = new QLabel(frame); + const QColor inputColor = occ::QtUtils::toQColor(prop->value()); + labelColor->setPixmap(colorSquarePixmap(inputColor)); + + auto labelRgb = new QLabel(frame); + labelRgb->setText(propertyValueText(prop)); + + auto btnColor = new QToolButton(frame); + btnColor->setText("..."); + btnColor->setToolTip(WidgetPropertiesEditor::tr("Choose color ...")); + QObject::connect(btnColor, &QAbstractButton::clicked, [=]{ + auto dlg = new QColorDialog(frame); + dlg->setCurrentColor(inputColor); + QObject::connect(dlg, &QColorDialog::colorSelected, [=](const QColor& c) { + prop->setValue(occ::QtUtils::toOccColor(c)); + labelColor->setPixmap(colorSquarePixmap(c)); + }); + qtgui::QWidgetUtils::asyncDialogExec(dlg); + }); + + frame->layout()->addWidget(labelColor); + frame->layout()->addWidget(labelRgb); + frame->layout()->addWidget(btnColor); + frame->layout()->addWidget(hSpacerWidget(frame)); + + return frame; +} + +static QDoubleSpinBox* createOccPntCoordEditor( + QWidget* parent, + PropertyOccPnt* prop, + double (gp_Pnt::*funcGetCoord)() const, + void (gp_Pnt::*funcSetCoord)(double)) +{ + auto editor = new QDoubleSpinBox(parent); + const QuantityLength lenCoord = ((prop->value()).*funcGetCoord)() * Quantity_Millimeter; + const UnitSystem::TranslateResult trRes = + UnitSystem::translate(Settings::instance()->unitSystemSchema(), lenCoord); + //editor->setSuffix(QString::fromUtf8(trRes.strUnit)); + editor->setDecimals(Settings::instance()->unitSystemDecimals()); + editor->setButtonSymbols(QDoubleSpinBox::NoButtons); + editor->setRange(std::numeric_limits::min(), + std::numeric_limits::max()); + editor->setValue(trRes.value); + QSizePolicy sp = editor->sizePolicy(); + sp.setHorizontalPolicy(QSizePolicy::Expanding); + editor->setSizePolicy(sp); + editor->setMinimumWidth(25); + QObject::connect(editor, qOverload(&QDoubleSpinBox::valueChanged), [=](double value) { + const double f = trRes.factor; + value = qFuzzyCompare(f, 1.) ? value : value * f; + gp_Pnt pnt = prop->value(); + (pnt.*funcSetCoord)(value); + const Result result = prop->setValue(pnt); + handlePropertyValidationError(result, editor); + }); + return editor; +} + +static QWidget* createPropertyEditor(PropertyOccPnt* prop, QWidget* parent) +{ + auto frame = createPanelEditor(parent); + QLayout* frameLayout = frame->layout(); + frameLayout->addWidget(new QLabel("X", frame)); + frameLayout->addWidget(createOccPntCoordEditor(frame, prop, &gp_Pnt::X, &gp_Pnt::SetX)); + frameLayout->addWidget(new QLabel("Y", frame)); + frameLayout->addWidget(createOccPntCoordEditor(frame, prop, &gp_Pnt::Y, &gp_Pnt::SetY)); + frameLayout->addWidget(new QLabel("Z", frame)); + frameLayout->addWidget(createOccPntCoordEditor(frame, prop, &gp_Pnt::Z, &gp_Pnt::SetZ)); + return frame; +} + +class PropertyItemDelegate : public QStyledItemDelegate { +public: + PropertyItemDelegate(QObject* parent = nullptr) + : QStyledItemDelegate(parent) + {} + + double rowHeightFactor() const { return m_rowHeightFactor; } + void setRowHeightFactor(double v) { m_rowHeightFactor = v; } + + using UnitTranslation = WidgetPropertiesEditor::UnitTranslation; + bool overridePropertyUnitTranslation( + const BasePropertyQuantity* prop, UnitTranslation unitTr) + { + if (!prop || prop->quantityUnit() != unitTr.unit) + return false; + m_mapPropUnitTr.emplace(prop, unitTr); + return true; + } + + void paint(QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index) const override + { + if (index.column() == 1) { + const auto prop = qvariant_cast(index.data()); + if (prop && prop->dynTypeName() == PropertyOccColor::TypeName) { + auto propColor = static_cast(prop); + painter->save(); + + QApplication::style()->drawPrimitive( + QStyle::PE_PanelItemViewItem, + &option, + painter, + option.widget); + + const QColor color = occ::QtUtils::toQColor(propColor->value()); + const QPixmap pixColor = colorSquarePixmap(color, option.rect.height()); + painter->drawPixmap(option.rect.x(), option.rect.y(), pixColor); + const QString strColor = propertyValueText(propColor); + + QRect labelRect = option.rect; + labelRect.setX(option.rect.x() + pixColor.width() + 6); + QApplication::style()->drawItemText( + painter, + labelRect, + Qt::AlignLeft | Qt::AlignVCenter, + option.palette, + option.state.testFlag(QStyle::State_Enabled), + strColor); + + painter->restore(); + return; + } + } + + QStyledItemDelegate::paint(painter, option, index); + if (index.column() == 1 && !index.data().isNull()) { + const auto prop = qvariant_cast(index.data()); + if (!prop->isUserReadOnly() + && option.state.testFlag(QStyle::State_Enabled) + && option.state.testFlag(QStyle::State_MouseOver)) + { + const QSize itemSize = this->sizeHint(option, index); + const QSize pixItemSize = option.decorationSize * 0.75; + const QPixmap pixEdit = + mayoTheme()->icon(Theme::Icon::Edit).pixmap(pixItemSize); + painter->drawPixmap( + option.rect.x() + itemSize.width() + 4, + option.rect.y() + (itemSize.height() - pixItemSize.height()) / 2., + pixEdit); + } + } + } + + QString displayText(const QVariant& value, const QLocale&) const override + { + if (value.type() == QVariant::String) + return value.toString(); + else if (value.canConvert()) { + const auto prop = qvariant_cast(value); + //return propertyValueText(prop); + const char* propTypeName = prop ? prop->dynTypeName() : ""; + if (propTypeName == PropertyBool::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyInt::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyDouble::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyQByteArray::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyQString::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyQDateTime::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyOccColor::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyOccPnt::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyOccTrsf::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == PropertyEnumeration::TypeName) + return propertyValueText(static_cast(prop)); + if (propTypeName == BasePropertyQuantity::TypeName) { + auto qtyProp = static_cast(prop); + auto itFound = m_mapPropUnitTr.find(qtyProp); + if (itFound != m_mapPropUnitTr.cend()) + return propertyValueText(qtyProp, itFound->second); + else + return propertyValueText(qtyProp); + } + return WidgetPropertiesEditor::tr("ERROR no stringifier for property type '%1'") + .arg(propTypeName); + } + return QString(); + } + + QWidget* createEditor( + QWidget* parent, + const QStyleOptionViewItem&, + const QModelIndex& index) const override + { + if (index.column() == 0) + return nullptr; + auto prop = qvariant_cast(index.data()); + if (!prop || prop->isUserReadOnly()) + return nullptr; + const char* propTypeName = prop->dynTypeName(); + if (propTypeName == PropertyBool::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == PropertyInt::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == PropertyDouble::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == PropertyQString::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == PropertyOccColor::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == PropertyOccPnt::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == PropertyEnumeration::TypeName) + return createPropertyEditor(static_cast(prop), parent); + if (propTypeName == BasePropertyQuantity::TypeName) + return createPropertyEditor(static_cast(prop), parent); + return nullptr; + } + + void setModelData( + QWidget*, QAbstractItemModel*, const QModelIndex&) const override + { + // Disable default behavior that sets item data(property is changed directly) + } + + QSize sizeHint( + const QStyleOptionViewItem& option, + const QModelIndex& index) const override + { + const QSize baseSize = QStyledItemDelegate::sizeHint(option, index); + if (index.data(Qt::SizeHintRole).isNull()) + return QSize(baseSize.width(), m_rowHeightFactor * baseSize.height()); + return baseSize; + } + +private: + double m_rowHeightFactor = 1.; + std::unordered_map m_mapPropUnitTr; +}; + +} // namespace Internal + +struct WidgetPropertiesEditor::Group { + QTreeWidgetItem* treeItem; +}; + +class WidgetPropertiesEditor::Private { +public: + void createQtProperty(Property* property, QTreeWidgetItem* parentItem); + QTreeWidgetItem* addLineWidgetItem(QWidget* widget, int height); + QTreeWidgetItem* findTreeItem(const Property* property) const; + bool hasGroup(const WidgetPropertiesEditor::Group* group) const; + + Ui_WidgetPropertiesEditor* ui = nullptr; + Internal::PropertyItemDelegate* itemDelegate = nullptr; + std::vector vecProperty; + std::vector vecLineWidget; + std::vector vecGroup; +}; + +WidgetPropertiesEditor::WidgetPropertiesEditor(QWidget *parent) + : QWidget(parent), + d(new Private) +{ + d->ui = new Ui_WidgetPropertiesEditor; + d->ui->setupUi(this); + d->ui->treeWidget_Browser->setIndentation(0); + d->ui->treeWidget_Browser->setItemsExpandable(false); + d->ui->treeWidget_Browser->setRootIsDecorated(false); + d->itemDelegate = new Internal::PropertyItemDelegate(d->ui->treeWidget_Browser); + d->ui->treeWidget_Browser->setItemDelegate(d->itemDelegate); +} + +WidgetPropertiesEditor::~WidgetPropertiesEditor() +{ + delete d->ui; + delete d; +} + +WidgetPropertiesEditor::Group* WidgetPropertiesEditor::addGroup(const QString& name) +{ + Group grp = {}; + grp.treeItem = new QTreeWidgetItem; + grp.treeItem->setText(0, name); + grp.treeItem->setFirstColumnSpanned(true); + d->ui->treeWidget_Browser->addTopLevelItem(grp.treeItem); + grp.treeItem->setExpanded(true); + d->vecGroup.push_back(grp); + return &d->vecGroup.back(); +} + +void WidgetPropertiesEditor::setGroupName(Group* group, const QString& name) +{ + if (d->hasGroup(group)) + group->treeItem->setText(0, name); +} + +void WidgetPropertiesEditor::editProperties(PropertyOwner* propOwner, Group* grp) +{ + if (propOwner) { + d->ui->stack_Browser->setCurrentWidget(d->ui->page_BrowserDetails); + QTreeWidgetItem* parentTreeItem = d->hasGroup(grp) ? grp->treeItem : nullptr; + for (Property* prop : propOwner->properties()) + d->createQtProperty(prop, parentTreeItem); + d->ui->treeWidget_Browser->resizeColumnToContents(0); + d->ui->treeWidget_Browser->resizeColumnToContents(1); + } +} + +void WidgetPropertiesEditor::editProperty(Property* prop, Group* grp) +{ + if (prop) { + d->ui->stack_Browser->setCurrentWidget(d->ui->page_BrowserDetails); + QTreeWidgetItem* parentTreeItem = d->hasGroup(grp) ? grp->treeItem : nullptr; + d->createQtProperty(prop, parentTreeItem); + d->ui->treeWidget_Browser->resizeColumnToContents(0); + d->ui->treeWidget_Browser->resizeColumnToContents(1); + } +} + +void WidgetPropertiesEditor::clear() +{ + d->vecProperty.clear(); + d->vecLineWidget.clear(); + d->vecGroup.clear(); + d->ui->treeWidget_Browser->clear(); +} + +void WidgetPropertiesEditor::setPropertyEnabled(const Property* prop, bool on) +{ + QTreeWidgetItem* treeItem = d->findTreeItem(prop); + if (treeItem) { + if (on) + treeItem->setFlags(treeItem->flags() | Qt::ItemIsEnabled); + else + treeItem->setFlags(treeItem->flags() & ~Qt::ItemIsEnabled); + } +} + +void WidgetPropertiesEditor::setPropertySelectable(const Property* prop, bool on) +{ + QTreeWidgetItem* treeItem = d->findTreeItem(prop); + if (treeItem) { + if (on) + treeItem->setFlags(treeItem->flags() | Qt::ItemIsSelectable); + else + treeItem->setFlags(treeItem->flags() & ~Qt::ItemIsSelectable); + } +} + +void WidgetPropertiesEditor::addLineSpacer(int height) +{ + auto widget = new QWidget; + d->addLineWidgetItem(widget, height); +} + +void WidgetPropertiesEditor::addLineWidget(QWidget* widget, int height) +{ + d->addLineWidgetItem(widget, height); +} + +Span WidgetPropertiesEditor::lineWidgets() const +{ + return d->vecLineWidget; +} + +double WidgetPropertiesEditor::rowHeightFactor() const +{ + return d->itemDelegate->rowHeightFactor(); +} + +void WidgetPropertiesEditor::setRowHeightFactor(double v) +{ + d->itemDelegate->setRowHeightFactor(v); +} + +bool WidgetPropertiesEditor::overridePropertyUnitTranslation( + const BasePropertyQuantity* prop, UnitTranslation unitTr) +{ + return d->itemDelegate->overridePropertyUnitTranslation(prop, unitTr); +} + +void WidgetPropertiesEditor::Private::createQtProperty( + Property* property, QTreeWidgetItem* parentItem) +{ + this->vecProperty.push_back(property); + auto itemProp = new QTreeWidgetItem; + const QString labelSpacer = parentItem ? " " : ""; + itemProp->setText(0, labelSpacer + property->label()); + itemProp->setData(1, Qt::DisplayRole, QVariant::fromValue(property)); + itemProp->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + if (parentItem) + parentItem->addChild(itemProp); + else + this->ui->treeWidget_Browser->addTopLevelItem(itemProp); +} + +QTreeWidgetItem* WidgetPropertiesEditor::Private::addLineWidgetItem(QWidget* widget, int height) +{ + widget->setAutoFillBackground(true); + auto treeItem = new QTreeWidgetItem(this->ui->treeWidget_Browser); + treeItem->setFlags(Qt::ItemIsEnabled); + if (height > 0) { + treeItem->setSizeHint(0, QSize(100, height)); + treeItem->setSizeHint(1, QSize(100, height)); + } + this->vecLineWidget.push_back(widget); + this->ui->treeWidget_Browser->setFirstItemColumnSpanned(treeItem, true); + this->ui->treeWidget_Browser->setItemWidget(treeItem, 0, widget); + return treeItem; +} + +QTreeWidgetItem* WidgetPropertiesEditor::Private::findTreeItem(const Property* property) const +{ + for (QTreeWidgetItemIterator it(this->ui->treeWidget_Browser); *it; ++it) { + QTreeWidgetItem* treeItem = *it; + const QVariant value = treeItem->data(1, Qt::DisplayRole); + if (value.canConvert() + && qvariant_cast(value) == property) + { + return treeItem; + } + } + return nullptr; +} + +bool WidgetPropertiesEditor::Private::hasGroup(const Group *group) const +{ + return group + && group->treeItem + && group->treeItem->treeWidget() == ui->treeWidget_Browser; +} + +} // namespace Mayo diff --git a/src/app/widget_properties_editor.h b/src/app/widget_properties_editor.h new file mode 100644 index 00000000..ee729740 --- /dev/null +++ b/src/app/widget_properties_editor.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/property_builtins.h" +#include "../base/span.h" +#include "../base/unit.h" + +#include + +namespace Mayo { + +class WidgetPropertiesEditor : public QWidget { +public: + WidgetPropertiesEditor(QWidget* parent = nullptr); + ~WidgetPropertiesEditor(); + + struct Group; + Group* addGroup(const QString& name); + void setGroupName(Group* group, const QString& name); + + void editProperties(PropertyOwner* propOwner, Group* grp = nullptr); + void editProperty(Property* prop, Group* grp = nullptr); + void clear(); + + void setPropertyEnabled(const Property* prop, bool on); + void setPropertySelectable(const Property* prop, bool on); + + void addLineSpacer(int height); + void addLineWidget(QWidget* widget, int height = -1); + Span lineWidgets() const; + + double rowHeightFactor() const; + void setRowHeightFactor(double v); + + struct UnitTranslation { + Unit unit; + const char* strUnit; // UTF8 + double factor; + }; + bool overridePropertyUnitTranslation( + const BasePropertyQuantity* prop, UnitTranslation unitTr); + +private: + class Private; + Private* const d = nullptr; +}; + +} // namespace Mayo diff --git a/src/widget_document_item_props.ui b/src/app/widget_properties_editor.ui similarity index 65% rename from src/widget_document_item_props.ui rename to src/app/widget_properties_editor.ui index 5ed263cd..4f1aaade 100644 --- a/src/widget_document_item_props.ui +++ b/src/app/widget_properties_editor.ui @@ -1,7 +1,7 @@ - Mayo::WidgetDocumentItemProps - + Mayo::WidgetPropertiesEditor + 0 @@ -46,7 +46,24 @@ 0 - + + + QAbstractItemView::CurrentChanged|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + false + + + + Property + + + + + Value + + +
@@ -55,14 +72,6 @@
- - - QtTreePropertyBrowser - QWidget -
qttreepropertybrowser.h
- 1 -
-
diff --git a/src/app/widget_shape_selector.cpp b/src/app/widget_shape_selector.cpp new file mode 100644 index 00000000..e2883397 --- /dev/null +++ b/src/app/widget_shape_selector.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "widget_shape_selector.h" + +#include "../gui/gui_document.h" +#include "widget_gui_document.h" +#include "widget_occ_view_controller.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Mayo { + +static QString stringShapeTypePlural(TopAbs_ShapeEnum shapeType) +{ + switch (shapeType) { + case TopAbs_VERTEX: return WidgetShapeSelector::tr("Vertices"); + case TopAbs_EDGE: return WidgetShapeSelector::tr("Edges"); + case TopAbs_WIRE: return WidgetShapeSelector::tr("Wires"); + case TopAbs_FACE: return WidgetShapeSelector::tr("Faces"); + case TopAbs_SHELL: return WidgetShapeSelector::tr("Shells"); + case TopAbs_SOLID: return WidgetShapeSelector::tr("Solids"); + case TopAbs_COMPOUND: return WidgetShapeSelector::tr("Compounds"); + case TopAbs_COMPSOLID: return WidgetShapeSelector::tr("Connected solids"); + case TopAbs_SHAPE: return WidgetShapeSelector::tr("?Shapes?"); + } + return QString("?"); +} + +static const TopAbs_ShapeEnum allShapeTypes[] = { + TopAbs_VERTEX, TopAbs_EDGE, TopAbs_WIRE, TopAbs_FACE, TopAbs_SHELL, TopAbs_SOLID +}; + +WidgetShapeSelector::WidgetShapeSelector(WidgetGuiDocument* widgetGuiDoc) + : WidgetShapeSelector(allShapeTypes, widgetGuiDoc) +{ +} + +WidgetShapeSelector::WidgetShapeSelector( + Span spanShapeType, + WidgetGuiDocument* widgetGuiDoc) + : QWidget(widgetGuiDoc), + m_widgetGuiDoc(widgetGuiDoc), + m_selector(new GpxShapeSelector(widgetGuiDoc->guiDocument())) +{ + Q_ASSERT(widgetGuiDoc); + + this->setAutoFillBackground(true); + auto comboBox = new QComboBox(this); + m_comboBoxShapeType = comboBox; + for (TopAbs_ShapeEnum shapeType : spanShapeType) + comboBox->addItem(tr("Select %1").arg(stringShapeTypePlural(shapeType)), shapeType); + m_btnBox = new QDialogButtonBox(this); + m_btnBox->setCenterButtons(true); + + auto mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + mainLayout->addWidget(comboBox); + mainLayout->addWidget(m_btnBox); + + QObject::connect( + comboBox, QOverload::of(&QComboBox::activated), + this, &WidgetShapeSelector::onShapeSelectionModeChanged); + QObject::connect( + m_btnBox, &QDialogButtonBox::accepted, + this, &WidgetShapeSelector::accepted); + QObject::connect( + m_btnBox, &QDialogButtonBox::rejected, + this, &WidgetShapeSelector::rejected); + QObject::connect( + m_btnBox, &QDialogButtonBox::clicked, + this, &WidgetShapeSelector::buttonClicked); + m_selector->setViewController(widgetGuiDoc->controller()); + + auto escShortcut = new QShortcut(Qt::Key_Escape, this); + QObject::connect(escShortcut, &QShortcut::activated, this, &WidgetShapeSelector::rejected); + + this->onShapeSelectionModeChanged(comboBox->currentIndex()); +} + +WidgetShapeSelector::~WidgetShapeSelector() +{ + delete m_selector; +} + +void WidgetShapeSelector::addButton(QDialogButtonBox::StandardButton stdBtn) +{ + m_btnBox->addButton(stdBtn); +} + +void WidgetShapeSelector::addButton(QAbstractButton *btn, QDialogButtonBox::ButtonRole role) +{ + m_btnBox->addButton(btn, role); +} + +QDialogButtonBox::ButtonRole WidgetShapeSelector::buttonRole(QAbstractButton *btn) const +{ + return m_btnBox->buttonRole(btn); +} + +GpxShapeSelector* WidgetShapeSelector::selector() const +{ + return m_selector; +} + +void WidgetShapeSelector::onShapeSelectionModeChanged(int comboBoxItemId) +{ + bool okToInt = false; + const int iShapeType = + m_comboBoxShapeType->itemData(comboBoxItemId).toInt(&okToInt); + const TopAbs_ShapeEnum shapeType = + okToInt ? static_cast(iShapeType) : TopAbs_SHAPE; + m_selector->setShapeType(shapeType); +} + + +// -- +// -- ShapeSelector +// -- + +GpxShapeSelector::GpxShapeSelector(GuiDocument* guiDoc) + : QObject(guiDoc), + m_guiDocument(guiDoc), + m_shapeType(TopAbs_SHAPE) +{ + this->context()->RemoveFilters(); +} + +GpxShapeSelector::~GpxShapeSelector() +{ + this->clearSelection(); + this->context()->RemoveFilters(); +} + +V3dViewController* GpxShapeSelector::viewController() const +{ + return m_viewCtrl; +} + +void GpxShapeSelector::setViewController(V3dViewController *ctrl) +{ + if (ctrl == m_viewCtrl) + return; + + m_viewCtrl = ctrl; + QObject::connect( + ctrl, &V3dViewController::mouseMoved, + this, &GpxShapeSelector::onView3dMouseMove); + QObject::connect( + ctrl, &V3dViewController::mouseClicked, + this, &GpxShapeSelector::onView3dMouseClicked); +} + +TopAbs_ShapeEnum GpxShapeSelector::shapeType() const +{ + return m_shapeType; +} + +void GpxShapeSelector::setShapeType(TopAbs_ShapeEnum shapeEnum) +{ + m_shapeType = shapeEnum; + this->onShapeTypeChanged(shapeEnum); + emit shapeTypeChanged(shapeEnum); +} + +GpxShapeSelector::Mode GpxShapeSelector::mode() const +{ + return m_mode; +} + +void GpxShapeSelector::setMode(GpxShapeSelector::Mode mode) +{ + m_mode = mode; + this->clearSelection(); +} + +const Handle_AIS_InteractiveContext &GpxShapeSelector::context() const +{ + return m_guiDocument->aisInteractiveContext(); +} + +bool GpxShapeSelector::hasSelectedShapes() const +{ + this->context()->InitSelected(); + while (this->context()->MoreSelected()) { + auto brepOwner = Handle_StdSelect_BRepOwner::DownCast(this->context()->SelectedOwner()); + if (!brepOwner.IsNull() && brepOwner->HasShape()) + return true; + this->context()->NextSelected(); + } + return false; +} + +void GpxShapeSelector::clearSelection() +{ + this->context()->ClearDetected(true); + this->context()->ClearSelected(true); + emit shapeSelectionCleared(); +} + +void GpxShapeSelector::onShapeTypeChanged(TopAbs_ShapeEnum shapeEnum) +{ + this->clearSelection(); + this->context()->RemoveFilters(); + if (shapeEnum != TopAbs_SHAPE) + this->context()->AddFilter(new StdSelect_ShapeTypeFilter(shapeEnum)); +} + +void GpxShapeSelector::onView3dMouseMove(const QPoint& pos) +{ + this->context()->MoveTo(pos.x(), pos.y(), m_guiDocument->v3dView(), true); +} + +void GpxShapeSelector::onView3dMouseClicked(Qt::MouseButton btn) +{ + const bool hadSelected = this->hasSelectedShapes(); + auto detectedEntity = Handle_StdSelect_BRepOwner::DownCast(this->context()->DetectedOwner()); + AIS_StatusOfPick pickStatus = AIS_SOP_NothingSelected; + if (!this->context()->HasDetected()) { + this->context()->ClearSelected(true); + } + else { + if (m_mode == Mode::Single) + pickStatus = this->context()->Select(true); + else if (m_mode == Mode::Multi) + pickStatus = this->context()->ShiftSelect(true); + } + + if (m_mode == Mode::Multi && hadSelected && !this->hasSelectedShapes()) + emit shapeSelectionCleared(); + + if (pickStatus == AIS_SOP_Error + || pickStatus == AIS_SOP_NothingSelected + || pickStatus == AIS_SOP_Removed) + { + return; + } + + if (btn == Qt::LeftButton + && !detectedEntity.IsNull() + && detectedEntity->HasShape()) + { + emit shapeClicked(detectedEntity->Shape()); + } +} + +} // namespace Mayo diff --git a/src/app/widget_shape_selector.h b/src/app/widget_shape_selector.h new file mode 100644 index 00000000..0dab10f3 --- /dev/null +++ b/src/app/widget_shape_selector.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/span.h" +#include +#include +#include +#include +class QComboBox; +class TopoDS_Shape; + +namespace Mayo { + +class V3dViewController; +class GuiDocument; + +class GpxShapeSelector : public QObject { + Q_OBJECT +public: + GpxShapeSelector(GuiDocument* guiDoc); + ~GpxShapeSelector(); + + V3dViewController* viewController() const; + void setViewController(V3dViewController* ctrl); + + TopAbs_ShapeEnum shapeType() const; + void setShapeType(TopAbs_ShapeEnum shapeEnum); + + enum class Mode { + None, + Single, + Multi + }; + + Mode mode() const; + void setMode(Mode mode); + + void clearSelection(); + +signals: + void shapeTypeChanged(TopAbs_ShapeEnum shapeType); + void shapeClicked(const TopoDS_Shape& shape); + void shapeSelectionCleared(); + +protected: + virtual void onShapeTypeChanged(TopAbs_ShapeEnum shapeEnum); + virtual void onView3dMouseMove(const QPoint& pos); + virtual void onView3dMouseClicked(Qt::MouseButton btn); + + const Handle_AIS_InteractiveContext& context() const; + + bool hasSelectedShapes() const; + + GuiDocument* m_guiDocument = nullptr; + V3dViewController* m_viewCtrl = nullptr; + TopAbs_ShapeEnum m_shapeType; + Mode m_mode = Mode::Multi; +}; + +class WidgetGuiDocument; + +class WidgetShapeSelector : public QWidget { + Q_OBJECT +public: + WidgetShapeSelector(WidgetGuiDocument* widgetGuiDoc); + WidgetShapeSelector( + Span spanShapeType, + WidgetGuiDocument* widgetGuiDoc); + ~WidgetShapeSelector(); + + void addButton(QDialogButtonBox::StandardButton stdBtn); + void addButton(QAbstractButton* btn, QDialogButtonBox::ButtonRole role); + QDialogButtonBox::ButtonRole buttonRole(QAbstractButton* btn) const; + + GpxShapeSelector* selector() const; + +signals: + void buttonClicked(QAbstractButton* btn); + void accepted(); + void rejected(); + +private: + void onShapeSelectionModeChanged(int comboBoxItemId); + + Mayo::WidgetGuiDocument* m_widgetGuiDoc; + QComboBox* m_comboBoxShapeType; + QDialogButtonBox* m_btnBox; + GpxShapeSelector* m_selector; +}; + +} // namespace Mayo diff --git a/src/app/windows/win_taskbar_global_progress.cpp b/src/app/windows/win_taskbar_global_progress.cpp new file mode 100644 index 00000000..3b522005 --- /dev/null +++ b/src/app/windows/win_taskbar_global_progress.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "win_taskbar_global_progress.h" + +#include "../base/math_utils.h" + +#include +#include +#include + +namespace Mayo { + +WinTaskbarGlobalProgress::WinTaskbarGlobalProgress(QObject* parent) + : QObject(parent), + m_taskbarBtn(new QWinTaskbarButton(this)) +{ + auto taskMgr = qttask::Manager::globalInstance(); + QObject::connect( + taskMgr, &qttask::Manager::started, + this, [=](quint64 taskId) { this->onTaskProgress(taskId, 0); }); + QObject::connect( + taskMgr, &qttask::Manager::progress, + this, &WinTaskbarGlobalProgress::onTaskProgress); + QObject::connect( + taskMgr, &qttask::Manager::ended, + this, &WinTaskbarGlobalProgress::onTaskEnded); +} + +void WinTaskbarGlobalProgress::setWindow(QWindow* window) +{ + m_taskbarBtn->setWindow(window); +} + +void WinTaskbarGlobalProgress::onTaskProgress(quint64 taskId, int percent) +{ + auto it = m_mapTaskIdProgress.find(taskId); + if (it != m_mapTaskIdProgress.end()) + it->second = percent; + else + m_mapTaskIdProgress.insert({ taskId, percent }); + + this->updateTaskbar(); +} + +void WinTaskbarGlobalProgress::onTaskEnded(quint64 taskId) +{ + m_mapTaskIdProgress.erase(taskId); + this->updateTaskbar(); +} + +void WinTaskbarGlobalProgress::updateTaskbar() +{ + QWinTaskbarProgress* taskbarProgress = m_taskbarBtn->progress(); + if (m_mapTaskIdProgress.empty()) { + taskbarProgress->stop(); + taskbarProgress->hide(); + m_globalPct = 0; + return; + } + + int taskCount = 0; + int taskAccumPct = 0; + bool isProgressIndeterminate = false; + for (const auto& mapPair : m_mapTaskIdProgress) { + const int pct = mapPair.second; + if (pct >= 0) + taskAccumPct += pct; + else + isProgressIndeterminate = true; + + ++taskCount; + } + + taskbarProgress->show(); + taskbarProgress->resume(); + if (!isProgressIndeterminate) { + const int newGlobalPct = MathUtils::mappedValue(taskAccumPct, 0, taskCount * 100, 0, 100); + m_globalPct = std::max(newGlobalPct, m_globalPct); + taskbarProgress->setRange(0, 100); + taskbarProgress->setValue(m_globalPct); + } + else { + m_globalPct = 0; + taskbarProgress->setRange(0, 0); + } +} + +} // namespace Mayo diff --git a/src/app/windows/win_taskbar_global_progress.h b/src/app/windows/win_taskbar_global_progress.h new file mode 100644 index 00000000..0f2397b2 --- /dev/null +++ b/src/app/windows/win_taskbar_global_progress.h @@ -0,0 +1,35 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +// Module : GUI + +#include +#include +class QWindow; +class QWinTaskbarButton; + +namespace Mayo { + +class WinTaskbarGlobalProgress : public QObject { + Q_OBJECT +public: + WinTaskbarGlobalProgress(QObject* parent = nullptr); + + void setWindow(QWindow* window); + +private: + void onTaskProgress(quint64 taskId, int percent); + void onTaskEnded(quint64 taskId); + void updateTaskbar(); + + std::unordered_map m_mapTaskIdProgress; + QWinTaskbarButton* m_taskbarBtn = nullptr; + int m_globalPct = 0; +}; + +} // namespace Mayo diff --git a/src/application.cpp b/src/application.cpp deleted file mode 100644 index eebd0d79..00000000 --- a/src/application.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "application.h" - -#include "document.h" -#include "document_item.h" -#include "brep_shape_item.h" -#include "stl_mesh_item.h" -#include "options.h" -#include "fougtools/qttools/task/progress.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace Mayo { - -namespace Internal { - -static QMutex* globalMutex() -{ - static QMutex mutex; - return &mutex; -} - -static bool gmio_qttask_is_stop_requested(void* cookie) -{ - auto progress = static_cast(cookie); - return progress != nullptr ? progress->isAbortRequested() : false; -} - -static void gmio_qttask_handle_progress( - void* cookie, intmax_t value, intmax_t maxValue) -{ - auto progress = static_cast(cookie); - if (progress != nullptr && maxValue > 0) { - const auto pctNorm = value / static_cast(maxValue); - const auto pct = qRound(pctNorm * 100); - if (pct >= (progress->value() + 5)) - progress->setValue(pct); - } -} - -static gmio_task_iface gmio_qttask_create_task_iface(qttask::Progress* progress) -{ - gmio_task_iface task = {}; - task.cookie = progress; - task.func_is_stop_requested = gmio_qttask_is_stop_requested; - task.func_handle_progress = gmio_qttask_handle_progress; - return task; -} - -class OccImportProgress : public Message_ProgressIndicator -{ -public: - OccImportProgress(qttask::Progress* progress) - : m_progress(progress) - { - this->SetScale(0., 100., 1.); - } - - Standard_Boolean Show(const Standard_Boolean /*force*/) override - { - const Handle_TCollection_HAsciiString name = this->GetScope(1).GetName(); - if (!name.IsNull() && m_progress != nullptr) - m_progress->setStep(QString(name->ToCString())); - const Standard_Real pc = this->GetPosition(); // Always within [0,1] - const int minVal = 0; - const int maxVal = 100; - const int val = minVal + pc * (maxVal - minVal); - if (m_progress != nullptr) - m_progress->setValue(val); - return Standard_True; - } - - Standard_Boolean UserBreak() override - { - return m_progress != nullptr ? m_progress->isAbortRequested() : false; - } - -private: - qttask::Progress* m_progress = nullptr; -}; - -template // Either IGESControl_Reader or STEPControl_Reader -TopoDS_Shape loadShapeFromFile( - const QString& filepath, - IFSelect_ReturnStatus* error, - qttask::Progress* progress) -{ - QMutexLocker locker(globalMutex()); Q_UNUSED(locker); - Handle_Message_ProgressIndicator indicator = new OccImportProgress(progress); - TopoDS_Shape result; - - if (!indicator.IsNull()) - indicator->NewScope(30, "Loading file"); - READER reader; - *error = reader.ReadFile(filepath.toLocal8Bit().constData()); - if (!indicator.IsNull()) - indicator->EndScope(); - if (*error == IFSelect_RetDone) { - if (!indicator.IsNull()) { - reader.WS()->MapReader()->SetProgress(indicator); - indicator->NewScope(70, "Translating file"); - } - reader.NbRootsForTransfer(); - reader.TransferRoots(); - result = reader.OneShape(); - if (!indicator.IsNull()) { - indicator->EndScope(); - reader.WS()->MapReader()->SetProgress(nullptr); - } - } - return result; -} - -static BRepShapeItem* createBRepShapeItem( - const QString& filepath, const TopoDS_Shape& shape) -{ - auto partItem = new BRepShapeItem; - partItem->setFilePath(filepath); - partItem->propertyLabel.setValue(QFileInfo(filepath).baseName()); - partItem->setBRepShape(shape); - return partItem; -} - -static StlMeshItem* createStlMeshItem( - const QString& filepath, const Handle_StlMesh_Mesh& mesh) -{ - auto partItem = new StlMeshItem; - partItem->setFilePath(filepath); - partItem->propertyLabel.setValue(QFileInfo(filepath).baseName()); - partItem->propertyNodeCount.setValue(mesh->NbVertices()); - partItem->propertyTriangleCount.setValue(mesh->NbTriangles()); - partItem->setStlMesh(mesh); - return partItem; -} - -static QString gmioErrorToQString(int error) -{ - switch (error) { - // Core - case GMIO_ERROR_OK: - return QString(); - case GMIO_ERROR_UNKNOWN: - return Application::tr("GMIO_ERROR_UNKNOWN"); - case GMIO_ERROR_NULL_MEMBLOCK: - return Application::tr("GMIO_ERROR_NULL_MEMBLOCK"); - case GMIO_ERROR_INVALID_MEMBLOCK_SIZE: - return Application::tr("GMIO_ERROR_INVALID_MEMBLOCK_SIZE"); - case GMIO_ERROR_STREAM: - return Application::tr("GMIO_ERROR_STREAM"); - case GMIO_ERROR_TASK_STOPPED: - return Application::tr("GMIO_ERROR_TASK_STOPPED"); - case GMIO_ERROR_STDIO: - return Application::tr("GMIO_ERROR_STDIO"); - case GMIO_ERROR_BAD_LC_NUMERIC: - return Application::tr("GMIO_ERROR_BAD_LC_NUMERIC"); - // TODO: complete other core enum values - // STL - case GMIO_STL_ERROR_UNKNOWN_FORMAT: - return Application::tr("GMIO_STL_ERROR_UNKNOWN_FORMAT"); - case GMIO_STL_ERROR_NULL_FUNC_GET_TRIANGLE: - return Application::tr("GMIO_STL_ERROR_NULL_FUNC_GET_TRIANGLE"); - case GMIO_STL_ERROR_PARSING: - return Application::tr("GMIO_STL_ERROR_PARSING"); - case GMIO_STL_ERROR_INVALID_FLOAT32_PREC: - return Application::tr("GMIO_STL_ERROR_INVALID_FLOAT32_PREC"); - case GMIO_STL_ERROR_UNSUPPORTED_BYTE_ORDER: - return Application::tr("GMIO_STL_ERROR_UNSUPPORTED_BYTE_ORDER"); - case GMIO_STL_ERROR_HEADER_WRONG_SIZE: - return Application::tr("GMIO_STL_ERROR_HEADER_WRONG_SIZE"); - case GMIO_STL_ERROR_FACET_COUNT: - return Application::tr("GMIO_STL_ERROR_FACET_COUNT"); - } - return Application::tr("GMIO_ERROR_UNKNOWN"); -} - -static QString occReturnStatusToQString(IFSelect_ReturnStatus status) -{ - switch (status) { - case IFSelect_RetVoid: return Application::tr("IFSelect_RetVoid"); - case IFSelect_RetDone: return QString(); - case IFSelect_RetError: return Application::tr("IFSelect_RetError"); - case IFSelect_RetFail: return Application::tr("IFSelect_RetFail"); - case IFSelect_RetStop: return Application::tr("IFSelect_RetStop"); - } - return Application::tr("IFSelect Unknown"); -} - -const char* skipWhiteSpaces(const char* str, std::size_t len) -{ - std::size_t pos = 0; - while (std::isspace(str[pos]) && pos < len) - ++pos; - return str + pos; -} - -template -bool matchToken(const char* buffer, const char (&token)[N]) -{ - return std::strncmp(buffer, token, N - 1) == 0; -} - -Application::PartFormat findPartFormatFromContents( - const char *contentsBegin, std::size_t contentsBeginSize) -{ - // -- IGES ? - { - // regex : ^.{72}S\s*[0-9]+\s*[\n\r\f] - bool isIges = true; - if (contentsBeginSize >= 80 && contentsBegin[72] == 'S') { - for (int i = 73; i < 80 && isIges; ++i) { - if (contentsBegin[i] != ' ' && !std::isdigit(contentsBegin[i])) - isIges = false; - } - if (isIges && (contentsBegin[80] == '\n' - || contentsBegin[80] == '\r' - || contentsBegin[80] == '\f')) - { - const int sVal = std::atoi(contentsBegin + 73); - if (sVal == 1) - return Application::PartFormat::Iges; - } - } - } // IGES - - contentsBegin = skipWhiteSpaces(contentsBegin, contentsBeginSize); - - // -- STEP ? - { - // regex : ^\s*ISO-10303-21\s*;\s*HEADER - static const char stepIsoId[] = "ISO-10303-21"; - static const std::size_t stepIsoIdLen = sizeof(stepIsoId) - 1; - static const char stepHeaderToken[] = "HEADER"; - static const std::size_t stepHeaderTokenLen = sizeof(stepHeaderToken) - 1; - if (std::strncmp(contentsBegin, stepIsoId, stepIsoIdLen) == 0) { - auto charIt = skipWhiteSpaces( - contentsBegin + stepIsoIdLen, - contentsBeginSize - stepIsoIdLen); - if (*charIt == ';' - && (charIt - contentsBegin) < contentsBeginSize) - { - charIt = skipWhiteSpaces( - charIt + 1, - contentsBeginSize - (charIt - contentsBegin)); - if (std::strncmp(charIt, stepHeaderToken, stepHeaderTokenLen) - == 0) - { - return Application::PartFormat::Step; - } - } - } - } // STEP - - // -- OpenCascade BREP ? - { - // regex : ^\s*DBRep_DrawableShape - static const char occBRepToken[] = "DBRep_DrawableShape"; - if (matchToken(contentsBegin, occBRepToken)) - return Application::PartFormat::OccBrep; - } - - // Fallback case - return Application::PartFormat::Unknown; -} - -} // namespace Internal - -Application::Application(QObject *parent) - : QObject(parent) -{ -} - -Application *Application::instance() -{ - static Application app; - return &app; -} - -const std::vector &Application::documents() const -{ - return m_documents; -} - -Document *Application::addDocument(const QString &label) -{ - static unsigned docSequenceId = 0; - auto doc = new Document(this); - if (label.isEmpty()) { - doc->setLabel(tr("Anonymous%1") - .arg(docSequenceId > 0 ? - QString::number(docSequenceId) : - QString())); - } - else { - doc->setLabel(label); - } - QObject::connect( - doc, &Document::itemAdded, - this, &Application::documentItemAdded); - QObject::connect( - doc, &Document::itemPropertyChanged, - this, &Application::documentItemPropertyChanged); - m_documents.emplace_back(doc); - ++docSequenceId; - emit documentAdded(doc); - return doc; -} - -bool Application::eraseDocument(Document *doc) -{ - auto itFound = std::find(m_documents.cbegin(), m_documents.cend(), doc); - if (itFound != m_documents.cend()) { - m_documents.erase(itFound); - delete doc; - emit documentErased(doc); - return true; - } - return false; -} - -Application::IoResult Application::importInDocument( - Document* doc, - PartFormat format, - const QString &filepath, - qttask::Progress* progress) -{ - progress->setStep(QFileInfo(filepath).fileName()); - switch (format) { - case PartFormat::Iges: return this->importIges(doc, filepath, progress); - case PartFormat::Step: return this->importStep(doc, filepath, progress); - case PartFormat::OccBrep: return this->importOccBRep(doc, filepath, progress); - case PartFormat::Stl: return this->importStl(doc, filepath, progress); - case PartFormat::Unknown: break; - } - return { false, tr("Unknown error") }; -} - -Application::IoResult Application::exportDocumentItems( - const std::vector &docItems, - PartFormat format, - const ExportOptions &options, - const QString &filepath, - qttask::Progress *progress) -{ - progress->setStep(QFileInfo(filepath).fileName()); - switch (format) { - case PartFormat::Iges: - return this->exportIges(docItems, options, filepath, progress); - case PartFormat::Step: - return this->exportStep(docItems, options, filepath, progress); - case PartFormat::OccBrep: - return this->exportOccBRep(docItems, options, filepath, progress); - case PartFormat::Stl: - return this->exportStl(docItems, options, filepath, progress); - case PartFormat::Unknown: - break; - } - return { false, tr("Unknown error") }; -} - -bool Application::hasExportOptionsForFormat(Application::PartFormat format) -{ - return format == PartFormat::Stl; -} - -const std::vector &Application::partFormats() -{ - const static std::vector vecFormat = { - PartFormat::Iges, - PartFormat::Step, - PartFormat::OccBrep, - PartFormat::Stl - }; - return vecFormat; -} - -QString Application::partFormatFilter(Application::PartFormat format) -{ - switch (format) { - case PartFormat::Iges: return tr("IGES files(*.iges *.igs)"); - case PartFormat::Step: return tr("STEP files(*.step *.stp)"); - case PartFormat::OccBrep: return tr("OpenCascade BREP files(*.brep *.occ)"); - case PartFormat::Stl: return tr("STL files(*.stl *.stla)"); - case PartFormat::Unknown: break; - } - return QString(); -} - -QStringList Application::partFormatFilters() -{ - QStringList filters; - filters << Application::partFormatFilter(PartFormat::Iges) - << Application::partFormatFilter(PartFormat::Step) - << Application::partFormatFilter(PartFormat::OccBrep) - << Application::partFormatFilter(PartFormat::Stl); - return filters; -} - -Application::PartFormat Application::findPartFormat(const QString &filepath) -{ - QFile file(filepath); - if (file.open(QIODevice::ReadOnly)) { - gmio_stream qtstream = gmio_stream_qiodevice(&file); - const gmio_stl_format stlFormat = gmio_stl_format_probe(&qtstream); - if (stlFormat != GMIO_STL_FORMAT_UNKNOWN) - return Application::PartFormat::Stl; - std::array contentsBegin; - contentsBegin.fill(0); - file.read(contentsBegin.data(), contentsBegin.size()); - return Internal::findPartFormatFromContents( - contentsBegin.data(), contentsBegin.size()); - } - return PartFormat::Unknown; -} - -Application::IoResult Application::importIges( - Document* doc, const QString &filepath, qttask::Progress* progress) -{ - IFSelect_ReturnStatus err; - const TopoDS_Shape shape = - Internal::loadShapeFromFile( - filepath, &err, progress); - if (err == IFSelect_RetDone) - doc->addItem(Internal::createBRepShapeItem(filepath, shape)); - return { err == IFSelect_RetDone, Internal::occReturnStatusToQString(err) }; -} - -Application::IoResult Application::importStep( - Document* doc, const QString &filepath, qttask::Progress* progress) -{ - IFSelect_ReturnStatus err; - const TopoDS_Shape shape = - Internal::loadShapeFromFile( - filepath, &err, progress); - if (err == IFSelect_RetDone) - doc->addItem(Internal::createBRepShapeItem(filepath, shape)); - return { err == IFSelect_RetDone, Internal::occReturnStatusToQString(err) }; -} - -Application::IoResult Application::importOccBRep( - Document* doc, const QString &filepath, qttask::Progress* progress) -{ - TopoDS_Shape shape; - BRep_Builder brepBuilder; - Handle_Message_ProgressIndicator indicator = - new Internal::OccImportProgress(progress); - const bool ok = BRepTools::Read( - shape, filepath.toLocal8Bit().constData(), brepBuilder, indicator); - if (ok) - doc->addItem(Internal::createBRepShapeItem(filepath, shape)); - return { ok, ok ? QString() : tr("Unknown Error") }; -} - -Application::IoResult Application::importStl( - Document* doc, const QString &filepath, qttask::Progress* progress) -{ - Application::IoResult result = { false, QString() }; - const Options::StlIoLibrary lib = - Options::instance()->stlIoLibrary(); - const Options::GmioStlImportType gmioImpType = - Options::instance()->gmioStlImportType(); - if (lib == Options::StlIoLibrary::Gmio) { - QFile file(filepath); - if (file.open(QIODevice::ReadOnly)) { - gmio_stream stream = gmio_stream_qiodevice(&file); - gmio_stl_read_options options = {}; - options.func_stla_get_streamsize = &gmio_stla_infos_probe_streamsize; - options.task_iface = Internal::gmio_qttask_create_task_iface(progress); - int err = GMIO_ERROR_OK; - while (gmio_no_error(err) && !file.atEnd()) { - if (gmioImpType == Options::GmioStlImportType::OccStlMesh) { - Handle_StlMesh_Mesh stlMesh = new StlMesh_Mesh; - gmio_stl_mesh_creator_occmesh meshcreator(stlMesh); - err = gmio_stl_read(&stream, &meshcreator, &options); - if (gmio_no_error(err)) - doc->addItem(Internal::createStlMeshItem(filepath, stlMesh)); - } - else if (gmioImpType == Options::GmioStlImportType::OccPolyTriShape) { - gmio_stl_mesh_creator_occshape meshcreator; - err = gmio_stl_read(&stream, &meshcreator, &options); - if (gmio_no_error(err)) { - const TopoDS_Shape& shape = meshcreator.shape(); - doc->addItem(Internal::createBRepShapeItem(filepath, shape)); - } - } - } - result.ok = (err == GMIO_ERROR_OK); - if (!result.ok) - result.errorText = Internal::gmioErrorToQString(err); - } - } - else if (lib == Options::StlIoLibrary::OpenCascade) { - Handle_Message_ProgressIndicator indicator = - new Internal::OccImportProgress(progress); - Handle_StlMesh_Mesh stlMesh = RWStl::ReadFile( - OSD_Path(filepath.toLocal8Bit().constData()), indicator); - if (!stlMesh.IsNull()) - doc->addItem(Internal::createStlMeshItem(filepath, stlMesh)); - result.ok = !stlMesh.IsNull(); - if (!result.ok) - result.errorText = tr("Imported STL mesh is null"); - } - return result; -} - -Application::IoResult Application::exportIges( - const std::vector &docItems, - const ExportOptions& /*options*/, - const QString &filepath, - qttask::Progress *progress) -{ - QMutexLocker locker(Internal::globalMutex()); Q_UNUSED(locker); - Handle_Message_ProgressIndicator indicator = - new Internal::OccImportProgress(progress); - - IGESControl_Controller::Init(); - IGESControl_Writer writer( - Interface_Static::CVal("XSTEP.iges.unit"), - Interface_Static::IVal("XSTEP.iges.writebrep.mode")); - if (!indicator.IsNull()) - writer.TransferProcess()->SetProgress(indicator); - for (const DocumentItem* item : docItems) { - if (sameType(item)) { - auto brepItem = static_cast(item); - writer.AddShape(brepItem->brepShape()); - } - } - writer.ComputeModel(); - const Standard_Boolean ok = writer.Write(filepath.toLocal8Bit().constData()); - writer.TransferProcess()->SetProgress(nullptr); - return { ok == Standard_True, QString() }; -} - -Application::IoResult Application::exportStep( - const std::vector &docItems, - const ExportOptions& /*options*/, - const QString &filepath, - qttask::Progress *progress) -{ - QMutexLocker locker(Internal::globalMutex()); Q_UNUSED(locker); - Handle_Message_ProgressIndicator indicator = - new Internal::OccImportProgress(progress); - STEPControl_Writer writer; - if (!indicator.IsNull()) - writer.WS()->TransferWriter()->FinderProcess()->SetProgress(indicator); - for (const DocumentItem* item : docItems) { - if (sameType(item)) { - auto brepItem = static_cast(item); - writer.Transfer(brepItem->brepShape(), STEPControl_AsIs); - } - } - const IFSelect_ReturnStatus err = - writer.Write(filepath.toLocal8Bit().constData()); - writer.WS()->TransferWriter()->FinderProcess()->SetProgress(nullptr); - return { err == IFSelect_RetDone, Internal::occReturnStatusToQString(err) }; -} - -Application::IoResult Application::exportOccBRep( - const std::vector &docItems, - const ExportOptions& /*options*/, - const QString &filepath, - qttask::Progress *progress) -{ - std::vector vecShapePtr; - vecShapePtr.reserve(docItems.size()); - for (const DocumentItem* item : docItems) { - if (sameType(item)) { - const auto brepItem = static_cast(item); - vecShapePtr.push_back(&brepItem->brepShape()); - } - } - TopoDS_Shape shape; - if (vecShapePtr.size() > 1) { - TopoDS_Compound cmpd; - BRep_Builder builder; - builder.MakeCompound(cmpd); - for (const TopoDS_Shape* shapePtr : vecShapePtr) - builder.Add(cmpd, *shapePtr); - shape = cmpd; - } - else if (vecShapePtr.size() == 1) { - shape = *vecShapePtr.front(); - } - - Handle_Message_ProgressIndicator indicator = - new Internal::OccImportProgress(progress); - const Standard_Boolean ok = - BRepTools::Write(shape, filepath.toLocal8Bit().constData(), indicator); - if (ok == Standard_True) - return { true, QString() }; - return { false, tr("Unknown Error") }; -} - -Application::IoResult Application::exportStl( - const std::vector &docItems, - const ExportOptions& options, - const QString &filepath, - qttask::Progress *progress) -{ - const Options::StlIoLibrary lib = Options::instance()->stlIoLibrary(); - if (lib == Options::StlIoLibrary::Gmio) - return this->exportStl_gmio(docItems, options, filepath, progress); - else if (lib == Options::StlIoLibrary::OpenCascade) - return this->exportStl_OCC(docItems, options, filepath, progress); - return { false, tr("Unknown Error") }; -} - -Application::IoResult Application::exportStl_gmio( - const std::vector &docItems, - const Application::ExportOptions &options, - const QString &filepath, - qttask::Progress *progress) -{ - QFile file(filepath); - if (file.open(QIODevice::WriteOnly)) { - gmio_stream stream = gmio_stream_qiodevice(&file); - gmio_stl_write_options gmioOptions = {}; - gmioOptions.stla_float32_format = options.stlaFloat32Format; - gmioOptions.stla_float32_prec = options.stlaFloat32Precision; - gmioOptions.stla_solid_name = options.stlaSolidName.c_str(); - gmioOptions.task_iface = - Internal::gmio_qttask_create_task_iface(progress); - for (const DocumentItem* item : docItems) { - if (progress != nullptr) { - progress->setStep( - tr("Writting item %1") - .arg(item->propertyLabel.value())); - } - int error = GMIO_ERROR_OK; - if (sameType(item)) { - auto brepItem = static_cast(item); - const gmio_stl_mesh_occshape gmioMesh(brepItem->brepShape()); - error = gmio_stl_write( - options.stlFormat, &stream, &gmioMesh, &gmioOptions); - } - else if (sameType(item)) { - auto meshItem = static_cast(item); - const gmio_stl_mesh_occmesh gmioMesh(meshItem->stlMesh()); - error = gmio_stl_write( - options.stlFormat, &stream, &gmioMesh, &gmioOptions); - } - if (error != GMIO_ERROR_OK) - return { false, Internal::gmioErrorToQString(error) }; - } - return { true, QString() }; - } - return { false, file.errorString() }; -} - -Application::IoResult Application::exportStl_OCC( - const std::vector &docItems, - const Application::ExportOptions &options, - const QString &filepath, - qttask::Progress *progress) -{ - if (options.stlFormat != GMIO_STL_FORMAT_ASCII - && options.stlFormat != GMIO_STL_FORMAT_BINARY_LE) - { - return { false, tr("Format not supported") }; - } - if (!docItems.empty() && docItems.size() > 1) - return { false, tr("OpenCascade RWStl does not support multi-solids") }; - - if (docItems.size() > 0) { - const DocumentItem* item = docItems.front(); - if (sameType(item)) { - auto brepItem = static_cast(item); - StlAPI_Writer writer; - if (options.stlFormat == GMIO_STL_FORMAT_ASCII) - writer.ASCIIMode() = Standard_True; - else - writer.ASCIIMode() = Standard_False; - const StlAPI_ErrorStatus error = writer.Write( - brepItem->brepShape(), filepath.toLocal8Bit().constData()); - switch (error) { - case StlAPI_StatusOK: return { true, QString() }; - case StlAPI_MeshIsEmpty: return { false, tr("StlAPI_MeshIsEmpty") }; - case StlAPI_CannotOpenFile: return { false, tr("StlAPI_CannotOpenFile") }; - case StlAPI_WriteError: return { false, tr("StlAPI_WriteError") }; - } - } - else if (sameType(item)) { - Handle_Message_ProgressIndicator indicator = - new Internal::OccImportProgress(progress); - Standard_Boolean occOk = Standard_False; - auto meshItem = static_cast(item); - const QByteArray filepathLocal8b = filepath.toLocal8Bit(); - const OSD_Path osdFilepath(filepathLocal8b.constData()); - const Handle_StlMesh_Mesh& stlMesh = meshItem->stlMesh(); - if (options.stlFormat == GMIO_STL_FORMAT_ASCII) - occOk = RWStl::WriteAscii(stlMesh, osdFilepath, indicator); - else - occOk = RWStl::WriteBinary(stlMesh, osdFilepath, indicator); - const bool ok = occOk == Standard_True; - return { ok, ok ? QString() : tr("Unknown error") }; - } - } - return { true, QString() }; -} - -} // namespace Mayo diff --git a/src/base/application.cpp b/src/base/application.cpp new file mode 100644 index 00000000..bc4595d3 --- /dev/null +++ b/src/base/application.cpp @@ -0,0 +1,963 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "application.h" + +#include "document.h" +#include "document_item.h" +#include "caf_utils.h" +#include "xde_document_item.h" +#include "mesh_item.h" +#include "mesh_utils.h" +#include "string_utils.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_GMIO +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static std::mutex globalMutex; + +#ifdef HAVE_GMIO +static bool gmio_qttask_is_stop_requested(void* cookie) +{ + auto progress = static_cast(cookie); + return progress ? progress->isAbortRequested() : false; +} + +static void gmio_qttask_handle_progress( + void* cookie, intmax_t value, intmax_t maxValue) +{ + auto progress = static_cast(cookie); + if (progress && maxValue > 0) { + const auto pctNorm = value / static_cast(maxValue); + const auto pct = qRound(pctNorm * 100); + if (pct >= (progress->value() + 5)) + progress->setValue(pct); + } +} + +static gmio_task_iface gmio_qttask_create_task_iface(qttask::Progress* progress) +{ + gmio_task_iface task = {}; + task.cookie = progress; + task.func_is_stop_requested = gmio_qttask_is_stop_requested; + task.func_handle_progress = gmio_qttask_handle_progress; + return task; +} + +static QString gmioErrorToQString(int error) +{ + switch (error) { + // Core + case GMIO_ERROR_OK: + return QString(); + case GMIO_ERROR_UNKNOWN: + return Application::tr("GMIO_ERROR_UNKNOWN"); + case GMIO_ERROR_NULL_MEMBLOCK: + return Application::tr("GMIO_ERROR_NULL_MEMBLOCK"); + case GMIO_ERROR_INVALID_MEMBLOCK_SIZE: + return Application::tr("GMIO_ERROR_INVALID_MEMBLOCK_SIZE"); + case GMIO_ERROR_STREAM: + return Application::tr("GMIO_ERROR_STREAM"); + case GMIO_ERROR_TASK_STOPPED: + return Application::tr("GMIO_ERROR_TASK_STOPPED"); + case GMIO_ERROR_STDIO: + return Application::tr("GMIO_ERROR_STDIO"); + case GMIO_ERROR_BAD_LC_NUMERIC: + return Application::tr("GMIO_ERROR_BAD_LC_NUMERIC"); + // TODO: complete other core enum values + // STL + case GMIO_STL_ERROR_UNKNOWN_FORMAT: + return Application::tr("GMIO_STL_ERROR_UNKNOWN_FORMAT"); + case GMIO_STL_ERROR_NULL_FUNC_GET_TRIANGLE: + return Application::tr("GMIO_STL_ERROR_NULL_FUNC_GET_TRIANGLE"); + case GMIO_STL_ERROR_PARSING: + return Application::tr("GMIO_STL_ERROR_PARSING"); + case GMIO_STL_ERROR_INVALID_FLOAT32_PREC: + return Application::tr("GMIO_STL_ERROR_INVALID_FLOAT32_PREC"); + case GMIO_STL_ERROR_UNSUPPORTED_BYTE_ORDER: + return Application::tr("GMIO_STL_ERROR_UNSUPPORTED_BYTE_ORDER"); + case GMIO_STL_ERROR_HEADER_WRONG_SIZE: + return Application::tr("GMIO_STL_ERROR_HEADER_WRONG_SIZE"); + case GMIO_STL_ERROR_FACET_COUNT: + return Application::tr("GMIO_STL_ERROR_FACET_COUNT"); + } + + return Application::tr("GMIO_ERROR_UNKNOWN"); +} +#endif + +class OccProgress : public Message_ProgressIndicator +{ +public: + OccProgress(qttask::Progress* progress) + : m_progress(progress) + { + this->SetScale(0., 100., 1.); + } + + bool Show(const bool /*force*/) override + { + const Handle_TCollection_HAsciiString name = this->GetScope(1).GetName(); + if (!name.IsNull() && m_progress) + m_progress->setStep(QString(name->ToCString())); + + const double pc = this->GetPosition(); // Always within [0,1] + const int minVal = 0; + const int maxVal = 100; + const int val = minVal + pc * (maxVal - minVal); + if (m_progress) + m_progress->setValue(val); + + return true; + } + + bool UserBreak() override + { + return m_progress ? m_progress->isAbortRequested() : false; + } + +private: + qttask::Progress* m_progress = nullptr; +}; + +template // Either IGESControl_Reader or STEPControl_Reader +TopoDS_Shape loadShapeFromFile( + const QString& filepath, + IFSelect_ReturnStatus* error, + qttask::Progress* progress) +{ + std::lock_guard lock(globalMutex); Q_UNUSED(lock); + Handle_Message_ProgressIndicator indicator = new OccProgress(progress); + TopoDS_Shape result; + + if (!indicator.IsNull()) + indicator->NewScope(30, "Loading file"); + READER reader; + *error = reader.ReadFile(filepath.toLocal8Bit().constData()); + if (!indicator.IsNull()) + indicator->EndScope(); + if (*error == IFSelect_RetDone) { + if (!indicator.IsNull()) { + reader.WS()->MapReader()->SetProgress(indicator); + indicator->NewScope(70, "Translating file"); + } + reader.NbRootsForTransfer(); + reader.TransferRoots(); + result = reader.OneShape(); + if (!indicator.IsNull()) { + indicator->EndScope(); + reader.WS()->MapReader()->SetProgress(nullptr); + } + } + return result; +} + +template struct CafReaderTraits {}; + +template<> struct CafReaderTraits { + using ReaderType = IGESCAFControl_Reader; + static Handle_XSControl_WorkSession workSession(const ReaderType& reader) { + return reader.WS(); + } + static void setPropsMode(ReaderType*, bool) { /* N/A */ } +}; + +template<> struct CafReaderTraits { + using ReaderType = STEPCAFControl_Reader; + static Handle_XSControl_WorkSession workSession(const ReaderType& reader) { + return reader.Reader().WS(); + } + static void setPropsMode(ReaderType* reader, bool on) { + reader->SetPropsMode(on); + } +}; + +template // Either IGESCAFControl_Reader or STEPCAFControl_Reader +void loadCafDocumentFromFile( + const QString& filepath, + Handle_TDocStd_Document& doc, + IFSelect_ReturnStatus* error, + qttask::Progress* progress) +{ + std::lock_guard lock(globalMutex); Q_UNUSED(lock); + Handle_Message_ProgressIndicator indicator = new OccProgress(progress); + if (!indicator.IsNull()) + indicator->NewScope(30, "Loading file"); + + CAF_READER reader; + reader.SetColorMode(true); + reader.SetNameMode(true); + reader.SetLayerMode(true); + CafReaderTraits::setPropsMode(&reader, true); + *error = reader.ReadFile(filepath.toLocal8Bit().constData()); + if (!indicator.IsNull()) + indicator->EndScope(); + + if (*error == IFSelect_RetDone) { + Handle_XSControl_WorkSession ws = CafReaderTraits::workSession(reader); + if (!indicator.IsNull()) { + ws->MapReader()->SetProgress(indicator); + indicator->NewScope(70, "Translating file"); + } + + if (!reader.Transfer(doc)) + *error = IFSelect_RetFail; + + if (!indicator.IsNull()) { + indicator->EndScope(); + ws->MapReader()->SetProgress(nullptr); + } + } +} + +static TopoDS_Shape xdeDocumentWholeShape(const XdeDocumentItem* xdeDocItem) +{ + TopoDS_Shape shape; + const TDF_LabelSequence seqFreeShape = xdeDocItem->topLevelFreeShapes(); + if (seqFreeShape.Size() > 1) { + TopoDS_Compound cmpd; + BRep_Builder builder; + builder.MakeCompound(cmpd); + for (const TDF_Label& label : seqFreeShape) + builder.Add(cmpd, XdeDocumentItem::shape(label)); + shape = cmpd; + } + else if (seqFreeShape.Size() == 1) { + shape = XdeDocumentItem::shape(seqFreeShape.First()); + } + + return shape; +} + +static MeshItem* createMeshItem( + const QString& filepath, const Handle_Poly_Triangulation& mesh) +{ + auto partItem = new MeshItem; + partItem->propertyLabel.setValue(QFileInfo(filepath).baseName()); + partItem->propertyNodeCount.setValue(mesh->NbNodes()); + partItem->propertyTriangleCount.setValue(mesh->NbTriangles()); + partItem->propertyVolume.setQuantity( + MeshUtils::triangulationVolume(mesh) * Quantity_CubicMillimeter); + partItem->propertyArea.setQuantity( + MeshUtils::triangulationArea(mesh) * Quantity_SquaredMillimeter); + partItem->setTriangulation(mesh); + return partItem; +} + +static XdeDocumentItem* createXdeDocumentItem( + const QString& filepath, const Handle_TDocStd_Document& cafDoc) +{ + auto xdeDocItem = new XdeDocumentItem(cafDoc); + xdeDocItem->propertyLabel.setValue(QFileInfo(filepath).baseName()); + + const TopoDS_Shape shape = xdeDocumentWholeShape(xdeDocItem); + GProp_GProps system; + BRepGProp::VolumeProperties(shape, system); + xdeDocItem->propertyVolume.setQuantity( + std::max(system.Mass(), 0.) * Quantity_CubicMillimeter); + BRepGProp::SurfaceProperties(shape, system); + xdeDocItem->propertyArea.setQuantity( + std::max(system.Mass(), 0.) * Quantity_SquaredMillimeter); + + return xdeDocItem; +} + +static Application::PartFormat findPartFormatFromContents( + std::string_view contentsBegin, + uint64_t hintFullContentsSize) +{ + // -- Binary STL ? + constexpr size_t binaryStlHeaderSize = 80 + sizeof(uint32_t); + if (contentsBegin.size() >= binaryStlHeaderSize) { + constexpr uint32_t offset = 80; // Skip header + const uint8_t* bytes = reinterpret_cast(contentsBegin.data()); + const uint32_t facetsCount = + bytes[offset] + | (bytes[offset+1] << 8) + | (bytes[offset+2] << 16) + | (bytes[offset+3] << 24); + constexpr unsigned facetSize = (sizeof(float) * 12) + sizeof(uint16_t); + if ((facetSize * facetsCount + binaryStlHeaderSize) == hintFullContentsSize) + return Application::PartFormat::Stl; + } + + // -- IGES ? + { + // regex : ^.{72}S\s*[0-9]+\s*[\n\r\f] + bool isIges = true; + if (contentsBegin.size() >= 80 && contentsBegin[72] == 'S') { + for (int i = 73; i < 80 && isIges; ++i) { + if (contentsBegin[i] != ' ' && !std::isdigit(static_cast(contentsBegin[i]))) + isIges = false; + } + + const char c80 = contentsBegin[80]; + if (isIges && (c80 == '\n' || c80 == '\r' || c80 == '\f')) { + const int sVal = std::atoi(contentsBegin.data() + 73); + if (sVal == 1) + return Application::PartFormat::Iges; + } + } + } // IGES + + const std::locale& cLocale = std::locale::classic(); + auto fnIsSpace = [&](char c) { return std::isspace(c, cLocale); }; + auto fnMatchToken = [](std::string_view::const_iterator itBegin, std::string_view token) { + return std::strncmp(&(*itBegin), token.data(), token.size()) == 0; + }; + auto itContentsBegin = std::find_if_not(contentsBegin.cbegin(), contentsBegin.cend(), fnIsSpace); + + // -- STEP ? + { + // regex : ^\s*ISO-10303-21\s*;\s*HEADER + constexpr std::string_view stepIsoId = "ISO-10303-21"; + constexpr std::string_view stepHeaderToken = "HEADER"; + if (fnMatchToken(itContentsBegin, stepIsoId)) { + auto itChar = std::find_if_not(itContentsBegin + stepIsoId.size(), contentsBegin.cend(), fnIsSpace); + if (itChar != contentsBegin.cend() && *itChar == ';') { + itChar = std::find_if_not(itChar + 1, contentsBegin.cend(), fnIsSpace); + if (fnMatchToken(itChar, stepHeaderToken)) + return Application::PartFormat::Step; + } + } + } // STEP + + // -- OpenCascade BREP ? + { + // regex : ^\s*DBRep_DrawableShape + constexpr std::string_view occBRepToken = "DBRep_DrawableShape"; + if (fnMatchToken(itContentsBegin, occBRepToken)) + return Application::PartFormat::OccBrep; + } + + // -- ASCII STL ? + { + // regex : ^\s*solid + constexpr std::string_view asciiStlToken = "solid"; + if (fnMatchToken(itContentsBegin, asciiStlToken)) + return Application::PartFormat::Stl; + } + + // Fallback case + return Application::PartFormat::Unknown; +} + +} // namespace Internal + +Application::Application(QObject *parent) + : QObject(parent) +{ +} + +Application *Application::instance() +{ + static Application app; + return &app; +} + +int Application::documentCount() const +{ + return static_cast(m_documents.size()); +} + +Document* Application::documentAt(int index) const +{ + const bool validIndex = (0 <= index) && (index < this->documentCount()); + return validIndex ? m_documents.at(index) : nullptr; +} + +Span Application::documents() const +{ + return m_documents; +} + +void Application::addDocument(Document* doc) +{ + if (doc && this->indexOfDocument(doc) == -1) { + QObject::connect(doc, &Document::propertyChanged, [=](Property* prop) { + emit documentPropertyChanged(doc, prop); + }); + QObject::connect( + doc, &Document::itemAdded, + this, &Application::documentItemAdded); + QObject::connect( + doc, &Document::itemErased, + this, &Application::documentItemErased); + QObject::connect( + doc, &Document::itemPropertyChanged, + this, &Application::documentItemPropertyChanged); + m_documents.emplace_back(doc); + doc->setParent(this); + emit documentAdded(doc); + } +} + +bool Application::eraseDocument(Document* doc) +{ + auto itFound = std::find(m_documents.cbegin(), m_documents.cend(), doc); + if (itFound != m_documents.cend()) { + m_documents.erase(itFound); + doc->deleteLater(); + emit documentErased(doc); + return true; + } + return false; +} + +int Application::findDocumentByLocation(const QFileInfo& loc) const +{ + const QString locAbsoluteFilePath = loc.absoluteFilePath(); + auto itDocFound = std::find_if( + m_documents.cbegin(), + m_documents.cend(), + [=](const Document* doc) { + return QFileInfo(doc->filePath()).absoluteFilePath() == locAbsoluteFilePath; + }); + return itDocFound != m_documents.cend() ? itDocFound - m_documents.cbegin() : -1; +} + +int Application::indexOfDocument(const Document* doc) const +{ + auto itFound = std::find(m_documents.cbegin(), m_documents.cend(), doc); + return itFound != m_documents.cend() ? (itFound - m_documents.cbegin()) : -1; +} + +Application::IoResult Application::importInDocument( + Document* doc, + PartFormat format, + const QString& filepath, + qttask::Progress* progress) +{ + switch (format) { + case PartFormat::Iges: return this->importIges(doc, filepath, progress); + case PartFormat::Step: return this->importStep(doc, filepath, progress); + case PartFormat::OccBrep: return this->importOccBRep(doc, filepath, progress); + case PartFormat::Stl: return this->importStl(doc, filepath, progress); + case PartFormat::Unknown: break; + } + return IoResult::error(tr("Unknown error")); +} + +Application::IoResult Application::exportApplicationItems( + Span appItems, + PartFormat format, + const ExportOptions& options, + const QString& filepath, + qttask::Progress* progress) +{ + switch (format) { + case PartFormat::Iges: + return this->exportIges(appItems, options, filepath, progress); + case PartFormat::Step: + return this->exportStep(appItems, options, filepath, progress); + case PartFormat::OccBrep: + return this->exportOccBRep(appItems, options, filepath, progress); + case PartFormat::Stl: + return this->exportStl(appItems, options, filepath, progress); + case PartFormat::Unknown: + break; + } + return IoResult::error(tr("Unknown error")); +} + +bool Application::hasExportOptionsForFormat(Application::PartFormat format) +{ + return format == PartFormat::Stl; +} + +void Application::setOpenCascadeEnvironment(const QString& settingsFilepath) +{ + const QFileInfo fiSettingsFilepath(settingsFilepath); + if (!fiSettingsFilepath.exists() || !fiSettingsFilepath.isReadable()) { + qDebug() << settingsFilepath << "doesn't exist or is not readable"; + return; + } + + const QSettings occSettings(settingsFilepath, QSettings::IniFormat); + if (occSettings.status() != QSettings::NoError) { + qDebug() << settingsFilepath << "could not be loaded by QSettings"; + return; + } + + const char* arrayOptionName[] = { + "MMGT_OPT", + "MMGT_CLEAR", + "MMGT_REENTRANT", + "CSF_LANGUAGE", + "CSF_EXCEPTION_PROMPT" + }; + const char* arrayPathName[] = { + "CSF_SHMessage", + "CSF_MDTVTexturesDirectory", + "CSF_ShadersDirectory", + "CSF_XSMessage", + "CSF_TObjMessage", + "CSF_StandardDefaults", + "CSF_PluginDefaults", + "CSF_XCAFDefaults", + "CSF_TObjDefaults", + "CSF_StandardLiteDefaults", + "CSF_IGESDefaults", + "CSF_STEPDefaults", + "CSF_XmlOcafResource", + "CSF_MIGRATION_TYPES" + }; + + // Process options + for (const char* varName : arrayOptionName) { + const QLatin1String qVarName(varName); + if (!occSettings.contains(qVarName)) + continue; + + const QString strValue = occSettings.value(qVarName).toString(); + qputenv(varName, strValue.toUtf8()); + qDebug().noquote() << QString("%1 = %2").arg(qVarName).arg(strValue); + } + + // Process paths + for (const char* varName : arrayPathName) { + const QLatin1String qVarName(varName); + if (!occSettings.contains(qVarName)) + continue; + + QString strPath = occSettings.value(qVarName).toString(); + if (QFileInfo(strPath).isRelative()) + strPath = QCoreApplication::applicationDirPath() + QDir::separator() + strPath; + + strPath = QDir::toNativeSeparators(strPath); + qputenv(varName, strPath.toUtf8()); + qDebug().noquote() << QString("%1 = %2").arg(qVarName).arg(strPath); + } +} + +Span Application::partFormats() +{ + const static std::vector vecFormat = { + PartFormat::Iges, + PartFormat::Step, + PartFormat::OccBrep, + PartFormat::Stl + }; + return vecFormat; +} + +QString Application::partFormatFilter(Application::PartFormat format) +{ + switch (format) { + case PartFormat::Iges: return tr("IGES files(*.iges *.igs)"); + case PartFormat::Step: return tr("STEP files(*.step *.stp)"); + case PartFormat::OccBrep: return tr("OpenCascade BREP files(*.brep *.occ)"); + case PartFormat::Stl: return tr("STL files(*.stl *.stla)"); + case PartFormat::Unknown: break; + } + return QString(); +} + +QStringList Application::partFormatFilters() +{ + QStringList filters; + filters << Application::partFormatFilter(PartFormat::Iges) + << Application::partFormatFilter(PartFormat::Step) + << Application::partFormatFilter(PartFormat::OccBrep) + << Application::partFormatFilter(PartFormat::Stl); + return filters; +} + +Application::PartFormat Application::findPartFormat(const QString& filepath) +{ + QFile file(filepath); + if (file.open(QIODevice::ReadOnly)) { +#ifdef HAVE_GMIO + gmio_stream qtstream = gmio_stream_qiodevice(&file); + const gmio_stl_format stlFormat = gmio_stl_format_probe(&qtstream); + if (stlFormat != GMIO_STL_FORMAT_UNKNOWN) + return Application::PartFormat::Stl; +#endif + std::array contentsBegin; + contentsBegin.fill(0); + file.read(contentsBegin.data(), contentsBegin.size()); + return Internal::findPartFormatFromContents( + std::string_view(contentsBegin.data(), contentsBegin.size()), + file.size()); + } + return PartFormat::Unknown; +} + +Application::StlIoLibrary Application::stlIoLibrary() const +{ + return m_stlIoLibrary; +} + +void Application::setStlIoLibrary(Application::StlIoLibrary lib) +{ + m_stlIoLibrary = lib; +} + +Application::IoResult Application::importIges( + Document* doc, const QString& filepath, qttask::Progress* progress) +{ + IGESControl_Controller::Init(); + Handle_TDocStd_Document cafDoc = CafUtils::createXdeDocument(); + IFSelect_ReturnStatus err; + Internal::loadCafDocumentFromFile( + filepath, cafDoc, &err, progress); + if (err != IFSelect_RetDone) + return IoResult::error(StringUtils::rawText(err)); + + doc->addRootItem(Internal::createXdeDocumentItem(filepath, cafDoc)); + return IoResult::ok(); +} + +Application::IoResult Application::importStep( + Document* doc, const QString& filepath, qttask::Progress* progress) +{ + Interface_Static::SetIVal("read.stepcaf.subshapes.name", 1); + Handle_TDocStd_Document cafDoc = CafUtils::createXdeDocument(); + IFSelect_ReturnStatus err; + Internal::loadCafDocumentFromFile( + filepath, cafDoc, &err, progress); + if (err != IFSelect_RetDone) + return IoResult::error(StringUtils::rawText(err)); + + doc->addRootItem(Internal::createXdeDocumentItem(filepath, cafDoc)); + return IoResult::ok(); +} + +Application::IoResult Application::importOccBRep( + Document* doc, const QString& filepath, qttask::Progress* progress) +{ + TopoDS_Shape shape; + BRep_Builder brepBuilder; + Handle_Message_ProgressIndicator indicator = new Internal::OccProgress(progress); + const bool ok = BRepTools::Read( + shape, filepath.toLocal8Bit().constData(), brepBuilder, indicator); + if (!ok) + return IoResult::error(tr("Unknown Error")); + + Handle_TDocStd_Document cafDoc = CafUtils::createXdeDocument(); + Handle_XCAFDoc_ShapeTool shapeTool = + XCAFDoc_DocumentTool::ShapeTool(cafDoc->Main()); + const TDF_Label labelShape = shapeTool->NewShape(); + shapeTool->SetShape(labelShape, shape); + doc->addRootItem(Internal::createXdeDocumentItem(filepath, cafDoc)); + return IoResult::ok(); +} + +Application::IoResult Application::importStl( + Document* doc, const QString& filepath, qttask::Progress* progress) +{ + if (this->stlIoLibrary() == StlIoLibrary::Gmio) { +#ifdef HAVE_GMIO + QFile file(filepath); + if (file.open(QIODevice::ReadOnly)) { + gmio_stream stream = gmio_stream_qiodevice(&file); + gmio_stl_read_options options = {}; + options.func_stla_get_streamsize = &gmio_stla_infos_probe_streamsize; + options.task_iface = Internal::gmio_qttask_create_task_iface(progress); + int err = GMIO_ERROR_OK; + while (gmio_no_error(err) && !file.atEnd()) { + gmio_stl_mesh_creator_occpolytri meshcreator; + err = gmio_stl_read(&stream, &meshcreator, &options); + if (gmio_no_error(err)) { + const Handle_Poly_Triangulation& mesh = meshcreator.polytri(); + doc->addRootItem(Internal::createMeshItem(filepath, mesh)); + } + } + if (err != GMIO_ERROR_OK) + return IoResult::error(Internal::gmioErrorToQString(err)); + } +#endif // HAVE_GMIO + } + else if (this->stlIoLibrary() == StlIoLibrary::OpenCascade) { + Handle_Message_ProgressIndicator indicator = new Internal::OccProgress(progress); + const Handle_Poly_Triangulation mesh = RWStl::ReadFile( + OSD_Path(filepath.toLocal8Bit().constData()), indicator); + if (!mesh.IsNull()) + doc->addRootItem(Internal::createMeshItem(filepath, mesh)); + else + return IoResult::error(tr("Imported STL mesh is null")); + } + + return IoResult::ok(); +} + +Application::IoResult Application::exportIges( + Span appItems, + const ExportOptions& /*options*/, + const QString& filepath, + qttask::Progress* progress) +{ + std::lock_guard lock(Internal::globalMutex); Q_UNUSED(lock); + Handle_Message_ProgressIndicator indicator = new Internal::OccProgress(progress); + + IGESControl_Controller::Init(); + IGESCAFControl_Writer writer; + writer.SetColorMode(true); + writer.SetNameMode(true); + writer.SetLayerMode(true); + if (!indicator.IsNull()) + writer.TransferProcess()->SetProgress(indicator); + + for (const ApplicationItem& item : appItems) { + if (sameType(item.documentItem())) { + auto xdeDocItem = static_cast(item.documentItem()); + if (item.isDocumentItem()) + writer.Transfer(xdeDocItem->cafDoc()); + else if (item.isDocumentItemNode()) + writer.Transfer(XdeDocumentItem::label(item.documentItemNode())); + } + } + + writer.ComputeModel(); + const bool ok = writer.Write(filepath.toLocal8Bit().constData()); + writer.TransferProcess()->SetProgress(nullptr); + return ok ? IoResult::ok() : IoResult::error(tr("Unknown error")); +} + +Application::IoResult Application::exportStep( + Span appItems, + const ExportOptions& /*options*/, + const QString& filepath, + qttask::Progress *progress) +{ + std::lock_guard lock(Internal::globalMutex); Q_UNUSED(lock); + Interface_Static::SetIVal("write.stepcaf.subshapes.name", 1); + Handle_Message_ProgressIndicator indicator = new Internal::OccProgress(progress); + STEPCAFControl_Writer writer; + if (!indicator.IsNull()) + writer.ChangeWriter().WS()->TransferWriter()->FinderProcess()->SetProgress(indicator); + + for (const ApplicationItem& item : appItems) { + if (sameType(item.documentItem())) { + auto xdeDocItem = static_cast(item.documentItem()); + if (item.isDocumentItem()) + writer.Transfer(xdeDocItem->cafDoc()); + else if (item.isDocumentItemNode()) + writer.Transfer(XdeDocumentItem::label(item.documentItemNode())); + } + } + + const IFSelect_ReturnStatus err = writer.Write(filepath.toLocal8Bit().constData()); + writer.ChangeWriter().WS()->TransferWriter()->FinderProcess()->SetProgress(nullptr); + return err == IFSelect_RetDone ? + IoResult::ok() : + IoResult::error(StringUtils::rawText(err)); +} + +Application::IoResult Application::exportOccBRep( + Span appItems, + const ExportOptions& /*options*/, + const QString& filepath, + qttask::Progress* progress) +{ + std::vector vecShape; + vecShape.reserve(appItems.size()); + for (const ApplicationItem& item : appItems) { + if (sameType(item.documentItem())) { + auto xdeDocItem = static_cast(item.documentItem()); + if (item.isDocumentItem()) { + for (const TDF_Label& label : xdeDocItem->topLevelFreeShapes()) + vecShape.push_back(XdeDocumentItem::shape(label)); + } + else if (item.isDocumentItemNode()) { + const TDF_Label labelNode = XdeDocumentItem::label(item.documentItemNode()); + vecShape.push_back(XdeDocumentItem::shape(labelNode)); + } + } + } + + TopoDS_Shape shape; + if (vecShape.size() > 1) { + TopoDS_Compound cmpd; + BRep_Builder builder; + builder.MakeCompound(cmpd); + for (const TopoDS_Shape& subShape : vecShape) + builder.Add(cmpd, subShape); + shape = cmpd; + } + else if (vecShape.size() == 1) { + shape = vecShape.front(); + } + + Handle_Message_ProgressIndicator indicator = new Internal::OccProgress(progress); + if (!BRepTools::Write(shape, filepath.toLocal8Bit().constData(), indicator)) + return IoResult::error(tr("Unknown Error")); + + return IoResult::ok(); +} + +Application::IoResult Application::exportStl( + Span appItems, + const ExportOptions& options, + const QString& filepath, + qttask::Progress *progress) +{ + if (this->stlIoLibrary() == StlIoLibrary::Gmio) + return this->exportStl_gmio(appItems, options, filepath, progress); + else if (this->stlIoLibrary() == StlIoLibrary::OpenCascade) + return this->exportStl_OCC(appItems, options, filepath, progress); + + return IoResult::error(tr("Unknown Error")); +} + +Application::IoResult Application::exportStl_gmio( + Span appItems, + const Application::ExportOptions& options, + const QString& filepath, + qttask::Progress* progress) +{ + QFile file(filepath); +#ifdef HAVE_GMIO + if (file.open(QIODevice::WriteOnly)) { + gmio_stream stream = gmio_stream_qiodevice(&file); + gmio_stl_write_options gmioOptions = {}; + gmioOptions.stla_float32_format = options.stlaFloat32Format; + gmioOptions.stla_float32_prec = options.stlaFloat32Precision; + gmioOptions.stla_solid_name = options.stlaSolidName.c_str(); + gmioOptions.task_iface = + Internal::gmio_qttask_create_task_iface(progress); + for (const DocumentItem* item : docItems) { + if (progress) { + progress->setStep( + tr("Writing item %1") + .arg(item->propertyLabel.value())); + } + + int error = GMIO_ERROR_OK; + if (sameType(item)) { + auto xdeDocItem = static_cast(item); + const TopoDS_Shape shape = Internal::xdeDocumentWholeShape(xdeDocItem); + const gmio_stl_mesh_occshape gmioMesh(shape); + error = gmio_stl_write( + options.stlFormat, &stream, &gmioMesh, &gmioOptions); + } + else if (sameType(item)) { + auto meshItem = static_cast(item); + const gmio_stl_mesh_occpolytri gmioMesh(meshItem->triangulation()); + error = gmio_stl_write( + options.stlFormat, &stream, &gmioMesh, &gmioOptions); + } + + if (error != GMIO_ERROR_OK) + return IoResult::error(Internal::gmioErrorToQString(error)); + } + + return IoResult::ok(); + } +#endif // HAVE_GMIO + + return IoResult::error(file.errorString()); +} + +Application::IoResult Application::exportStl_OCC( + Span appItems, + const Application::ExportOptions& options, + const QString& filepath, + qttask::Progress* progress) +{ +#ifdef HAVE_GMIO + const bool isAsciiFormat = options.stlFormat == GMIO_STL_FORMAT_ASCII; + if (options.stlFormat != GMIO_STL_FORMAT_ASCII + && options.stlFormat != GMIO_STL_FORMAT_BINARY_LE) + { + return IoResult::error(tr("Format not supported")); + } +#else + const bool isAsciiFormat = options.stlFormat == ExportOptions::StlFormat::Ascii; +#endif + if (appItems.size() > 1) + return IoResult::error(tr("OpenCascade RWStl does not support multi-solids")); + + auto fnWriteShape = [=](const TopoDS_Shape& shape) { + StlAPI_Writer writer; + writer.ASCIIMode() = isAsciiFormat; + if (!writer.Write(shape, filepath.toLocal8Bit().constData())) + return IoResult::error(tr("Unknown StlAPI_Writer failure")); + return IoResult::ok(); + }; + + if (!appItems.empty()) { + const ApplicationItem& item = appItems.at(0); + if (sameType(item.documentItem())) { + auto xdeDocItem = static_cast(item.documentItem()); + if (item.isDocumentItem()) { + return fnWriteShape(Internal::xdeDocumentWholeShape(xdeDocItem)); + } + else if (item.isDocumentItemNode()) { + const TDF_Label label = XdeDocumentItem::label(item.documentItemNode()); + return fnWriteShape(XdeDocumentItem::shape(label)); + } + } + else if (sameType(item.documentItem())) { + Handle_Message_ProgressIndicator indicator = new Internal::OccProgress(progress); + bool ok = false; + auto meshItem = static_cast(item.documentItem()); + const QByteArray filepathLocal8b = filepath.toLocal8Bit(); + const OSD_Path osdFilepath(filepathLocal8b.constData()); + const Handle_Poly_Triangulation& mesh = meshItem->triangulation(); + if (isAsciiFormat) + ok = RWStl::WriteAscii(mesh, osdFilepath, indicator); + else + ok = RWStl::WriteBinary(mesh, osdFilepath, indicator); + + if (!ok) + return IoResult::error(tr("Unknown error")); + } + } + + return IoResult::ok(); +} + +} // namespace Mayo diff --git a/src/application.h b/src/base/application.h similarity index 56% rename from src/application.h rename to src/base/application.h index 775485a7..53b95f74 100644 --- a/src/application.h +++ b/src/base/application.h @@ -1,39 +1,23 @@ /**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. +** Copyright (c) 2020, Fougue Ltd. ** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt ****************************************************************************/ #pragma once -#include -#include +#include "application_item.h" +#include "result.h" +#include "span.h" + +#ifdef HAVE_GMIO +# include +# include +#endif #include #include #include +class QFileInfo; namespace qttask { class Progress; } @@ -43,10 +27,8 @@ class Document; class DocumentItem; class Property; -class Application : public QObject -{ +class Application : public QObject { Q_OBJECT - public: // -- Types enum class PartFormat { @@ -57,52 +39,71 @@ class Application : public QObject Stl }; - struct IoResult { - bool ok; - QString errorText; - operator bool() const { return ok; } - }; + using IoResult = Result; struct ExportOptions { +#ifdef HAVE_GMIO gmio_stl_format stlFormat = GMIO_STL_FORMAT_UNKNOWN; std::string stlaSolidName; gmio_float_text_format stlaFloat32Format = GMIO_FLOAT_TEXT_FORMAT_SHORTEST_LOWERCASE; uint8_t stlaFloat32Precision = 9; +#else + enum class StlFormat { + Ascii, + Binary + }; + StlFormat stlFormat = StlFormat::Binary; +#endif + }; + + enum class StlIoLibrary { + Gmio, + OpenCascade }; // -- API static Application* instance(); - const std::vector& documents() const; + Span documents() const; + int documentCount() const; + Document* documentAt(int index) const; + int findDocumentByLocation(const QFileInfo& loc) const; + int indexOfDocument(const Document* doc) const; - Document* addDocument(const QString& label = QString()); + void addDocument(Document* doc); bool eraseDocument(Document* doc); - static const std::vector& partFormats(); + static Span partFormats(); static QString partFormatFilter(PartFormat format); static QStringList partFormatFilters(); static PartFormat findPartFormat(const QString& filepath); + Application::StlIoLibrary stlIoLibrary() const; + void setStlIoLibrary(Application::StlIoLibrary lib); + IoResult importInDocument( Document* doc, PartFormat format, const QString& filepath, qttask::Progress* progress = nullptr); - IoResult exportDocumentItems( - const std::vector& docItems, + IoResult exportApplicationItems( + Span appItems, PartFormat format, const ExportOptions& options, const QString& filepath, qttask::Progress* progress = nullptr); static bool hasExportOptionsForFormat(PartFormat format); + static void setOpenCascadeEnvironment(const QString& settingsFilepath); + signals: void documentAdded(Document* doc); void documentErased(const Document* doc); + void documentPropertyChanged(Document* doc, Property* prop); void documentItemAdded(DocumentItem* docItem); - void documentItemPropertyChanged( - const DocumentItem* docItem, const Property* prop); + void documentItemErased(const DocumentItem* docItem); + void documentItemPropertyChanged(DocumentItem* docItem, Property* prop); // -- Implementation private: @@ -118,37 +119,38 @@ class Application : public QObject Document* doc, const QString& filepath, qttask::Progress* progress); IoResult exportIges( - const std::vector& docItems, + Span appItems, const ExportOptions& options, const QString& filepath, qttask::Progress* progress); IoResult exportStep( - const std::vector& docItems, + Span appItems, const ExportOptions& options, const QString& filepath, qttask::Progress* progress); IoResult exportOccBRep( - const std::vector& docItems, + Span appItems, const ExportOptions& options, const QString& filepath, qttask::Progress* progress); IoResult exportStl( - const std::vector& docItems, + Span appItems, const ExportOptions& options, const QString& filepath, qttask::Progress* progress); IoResult exportStl_gmio( - const std::vector& docItems, + Span appItems, const ExportOptions& options, const QString& filepath, qttask::Progress* progress); IoResult exportStl_OCC( - const std::vector& docItems, + Span appItems, const ExportOptions& options, const QString& filepath, qttask::Progress* progress); std::vector m_documents; + StlIoLibrary m_stlIoLibrary = StlIoLibrary::OpenCascade; }; } // namespace Mayo diff --git a/src/base/application_item.cpp b/src/base/application_item.cpp new file mode 100644 index 00000000..3f4133bb --- /dev/null +++ b/src/base/application_item.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "application_item.h" + +namespace Mayo { + +ApplicationItem::ApplicationItem(Document *doc) + : m_doc(doc), + m_docItem(nullptr), + m_docItemNode(DocumentItemNode::null()) +{ } + +ApplicationItem::ApplicationItem(DocumentItem *docItem) + : m_doc(nullptr), + m_docItem(docItem), + m_docItemNode(DocumentItemNode::null()) +{ } + +ApplicationItem::ApplicationItem(const DocumentItemNode &node) + : m_doc(nullptr), + m_docItem(nullptr), + m_docItemNode(node) +{ } + +bool ApplicationItem::isValid() const { + return this->isDocument() + || this->isDocumentItem() + || this->isDocumentItemNode(); +} + +bool ApplicationItem::isDocument() const { + return m_doc != nullptr; +} + +bool ApplicationItem::isDocumentItem() const { + return m_docItem != nullptr; +} + +bool ApplicationItem::isDocumentItemNode() const { + return m_docItemNode.isValid(); +} + +Document* ApplicationItem::document() const +{ + if (this->isDocument()) + return m_doc; + else if (this->isDocumentItem()) + return m_docItem->document(); + else if (this->isDocumentItemNode()) + return m_docItemNode.documentItem->document(); + + return nullptr; +} + +DocumentItem* ApplicationItem::documentItem() const +{ + if (this->isDocumentItem()) + return m_docItem; + else if (this->isDocumentItemNode()) + return m_docItemNode.documentItem; + + return nullptr; +} + +const DocumentItemNode& ApplicationItem::documentItemNode() const +{ + return this->isDocumentItemNode() ? + m_docItemNode : DocumentItemNode::null(); +} + +bool ApplicationItem::operator==(const ApplicationItem &other) const +{ + return m_doc == other.m_doc + && m_docItem == other.m_docItem + && m_docItemNode.documentItem == other.m_docItemNode.documentItem + && m_docItemNode.id == other.m_docItemNode.id; +} + +} // namespace Mayo diff --git a/src/base/application_item.h b/src/base/application_item.h new file mode 100644 index 00000000..34646d16 --- /dev/null +++ b/src/base/application_item.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "document_item.h" + +namespace Mayo { + +class ApplicationItem { +public: + ApplicationItem() = default; + ApplicationItem(Document* doc); + ApplicationItem(DocumentItem* docItem); + ApplicationItem(const DocumentItemNode& node); + + bool isValid() const; + bool isDocument() const; + bool isDocumentItem() const; + bool isDocumentItemNode() const; + + Document* document() const; + DocumentItem* documentItem() const; + const DocumentItemNode& documentItemNode() const; + + bool operator==(const ApplicationItem& other) const; + +private: + Document* m_doc; + DocumentItem* m_docItem; + DocumentItemNode m_docItemNode; +}; + +} // namespace Mayo diff --git a/src/base/application_item_selection_model.cpp b/src/base/application_item_selection_model.cpp new file mode 100644 index 00000000..1f47370e --- /dev/null +++ b/src/base/application_item_selection_model.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "application_item_selection_model.h" + +namespace Mayo { + +namespace Internal { + +static bool hasApplicationItem( + Span vec, const ApplicationItem& item) +{ + auto itFound = std::find(vec.cbegin(), vec.cend(), item); + return itFound != vec.cend(); +} + +static std::vector::iterator findApplicationItem( + std::vector& vec, const ApplicationItem& item) +{ + return std::find(vec.begin(), vec.end(), item); +} + +} // namespace Internal + +ApplicationItemSelectionModel::ApplicationItemSelectionModel(QObject *parent) + : QObject(parent) +{ +} + +Span ApplicationItemSelectionModel::selectedItems() const +{ + return m_vecSelectedItem; +} + +bool ApplicationItemSelectionModel::hasSelectedDocumentItems() const +{ + for (const ApplicationItem& item : m_vecSelectedItem) { + if (item.isDocumentItem()) + return true; + } + return false; +} + +std::vector ApplicationItemSelectionModel::selectedDocumentItems() const +{ + std::vector vecDocItem; + vecDocItem.reserve(m_vecSelectedItem.size()); + for (const ApplicationItem& item : m_vecSelectedItem) { + if (item.isDocumentItem()) + vecDocItem.push_back(item.documentItem()); + } + return vecDocItem; +} + +void ApplicationItemSelectionModel::add(const ApplicationItem &item) +{ + if (!Internal::hasApplicationItem(m_vecSelectedItem, item)) { + m_vecSelectedItem.push_back(item); + std::vector vecItem = { item }; + emit changed(vecItem, {}); + } +} + +void ApplicationItemSelectionModel::add(Span vecItem) +{ + std::vector signalVecItem; + for (const ApplicationItem& item : vecItem) { + if (!Internal::hasApplicationItem(m_vecSelectedItem, item)) { + m_vecSelectedItem.push_back(item); + signalVecItem.push_back(item); + } + } + if (!signalVecItem.empty()) + emit changed(signalVecItem, {}); +} + +void ApplicationItemSelectionModel::remove(const ApplicationItem &item) +{ + auto itFound = Internal::findApplicationItem(m_vecSelectedItem, item); + if (itFound != m_vecSelectedItem.end()) { + m_vecSelectedItem.erase(itFound); + std::vector vecItem = { item }; + emit changed({}, vecItem); + } +} + +void ApplicationItemSelectionModel::remove(Span vecItem) +{ + std::vector signalVecItem; + for (const ApplicationItem& item : vecItem) { + auto itFound = Internal::findApplicationItem(m_vecSelectedItem, item); + if (itFound != m_vecSelectedItem.end()) { + m_vecSelectedItem.erase(itFound); + signalVecItem.push_back(item); + } + } + if (!signalVecItem.empty()) + emit changed({}, signalVecItem); +} + +void ApplicationItemSelectionModel::clear() +{ + if (!m_vecSelectedItem.empty()) { + m_vecSelectedItem.clear(); + emit cleared(); + } +} + +} // namespace Mayo diff --git a/src/base/application_item_selection_model.h b/src/base/application_item_selection_model.h new file mode 100644 index 00000000..1fd83c90 --- /dev/null +++ b/src/base/application_item_selection_model.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "application_item.h" +#include "span.h" +#include + +namespace Mayo { + +class ApplicationItemSelectionModel : public QObject { + Q_OBJECT +public: + ApplicationItemSelectionModel(QObject* parent = nullptr); + + Span selectedItems() const; + + bool hasSelectedDocumentItems() const; + std::vector selectedDocumentItems() const; + + void add(const ApplicationItem& item); + void add(Span vecItem); + void remove(const ApplicationItem& item); + void remove(Span vecItem); +// void toggle(const ApplicationItem& item); +// void toggle(Span item); + + void clear(); + +signals: + void cleared(); + void changed(Span selected, + Span deselected); + +private: + std::vector m_vecSelectedItem; +}; + +} // namespace Mayo diff --git a/src/base/bnd_utils.cpp b/src/base/bnd_utils.cpp new file mode 100644 index 00000000..e1e71f82 --- /dev/null +++ b/src/base/bnd_utils.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "bnd_utils.h" + +namespace Mayo { + +gp_Pnt BndBoxCoords::center() const +{ + return { + (this->xmax + this->xmin) / 2., + (this->ymax + this->ymin) / 2., + (this->zmax + this->zmin) / 2. + }; +} + +std::array BndBoxCoords::vertices() const +{ + return {{ + { this->xmin, this->ymin, this->zmax }, + { this->xmax, this->ymin, this->zmax }, + { this->xmin, this->ymin, this->zmin }, + { this->xmax, this->ymin, this->zmin }, + { this->xmin, this->ymax, this->zmax }, + { this->xmax, this->ymax, this->zmax }, + { this->xmin, this->ymax, this->zmin }, + { this->xmax, this->ymax, this->zmin } + }}; +} + +BndBoxCoords BndBoxCoords::get(const Bnd_Box &box) +{ + BndBoxCoords bbc = {}; + if (!box.IsVoid()) + box.Get(bbc.xmin, bbc.ymin, bbc.zmin, bbc.xmax, bbc.ymax, bbc.zmax); + return bbc; +} + +void BndUtils::add(Bnd_Box *box, const Bnd_Box &other) +{ + const auto bbc = BndBoxCoords::get(other); + for (const gp_Pnt& pnt : bbc.vertices()) + box->Add(pnt); +} + +} // namespace Mayo diff --git a/src/base/bnd_utils.h b/src/base/bnd_utils.h new file mode 100644 index 00000000..623c32ee --- /dev/null +++ b/src/base/bnd_utils.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace Mayo { + +struct BndUtils { + static void add(Bnd_Box* box, const Bnd_Box& other); +}; + +struct BndBoxCoords { + double xmin; + double ymin; + double zmin; + double xmax; + double ymax; + double zmax; + + gp_Pnt center() const; + std::array vertices() const; + static BndBoxCoords get(const Bnd_Box& box); +}; + +} // namespace Mayo diff --git a/src/base/brep_utils.cpp b/src/base/brep_utils.cpp new file mode 100644 index 00000000..308caf8b --- /dev/null +++ b/src/base/brep_utils.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "brep_utils.h" + +#include +#include +#include +#include + +namespace Mayo { + +bool BRepUtils::moreComplex(TopAbs_ShapeEnum lhs, TopAbs_ShapeEnum rhs) +{ + return lhs < rhs; +} + +int BRepUtils::hashCode(const TopoDS_Shape& shape) +{ + return !shape.IsNull() ? shape.HashCode(INT_MAX) : -1; +} + +std::string BRepUtils::shapeToString(const TopoDS_Shape& shape) +{ + std::ostringstream oss(std::ios_base::out); + BRepTools::Write(shape, oss); + return oss.str(); +} + +TopoDS_Shape BRepUtils::shapeFromString(const std::string& str) +{ + TopoDS_Shape shape; + BRep_Builder brepBuilder; + std::istringstream iss(str, std::ios_base::in); + BRepTools::Read(shape, iss, brepBuilder); + return shape; +} + +} // namespace Mayo diff --git a/src/base/brep_utils.h b/src/base/brep_utils.h new file mode 100644 index 00000000..f379c3ad --- /dev/null +++ b/src/base/brep_utils.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +namespace Mayo { + +struct BRepUtils { + template + static void forEachSubShape(TopExp_Explorer& explorer, FUNC fn); + + template + static void forEachSubShape( + const TopoDS_Shape& shape, TopAbs_ShapeEnum shapeType, FUNC fn); + + template + static void forEachSubFace(const TopoDS_Shape& shape, FUNC fn); + + static bool moreComplex(TopAbs_ShapeEnum lhs, TopAbs_ShapeEnum rhs); + + static int hashCode(const TopoDS_Shape& shape); + + static std::string shapeToString(const TopoDS_Shape& shape); + static TopoDS_Shape shapeFromString(const std::string& str); +}; + + + +// -- +// -- Implementation +// -- + +template +void BRepUtils::forEachSubShape(TopExp_Explorer& explorer, FUNC fn) +{ + while (explorer.More()) { + fn(explorer.Current()); + explorer.Next(); + } +} + +template +void BRepUtils::forEachSubShape( + const TopoDS_Shape& shape, TopAbs_ShapeEnum shapeType, FUNC fn) +{ + TopExp_Explorer expl(shape, shapeType); + BRepUtils::forEachSubShape(expl, std::move(fn)); +} + +template +void BRepUtils::forEachSubFace(const TopoDS_Shape& shape, FUNC fn) +{ + for (TopExp_Explorer expl(shape, TopAbs_FACE); expl.More(); expl.Next()) + fn(TopoDS::Face(expl.Current())); +} + +} // namespace Mayo diff --git a/src/base/caf_utils.cpp b/src/base/caf_utils.cpp new file mode 100644 index 00000000..c2699ab8 --- /dev/null +++ b/src/base/caf_utils.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "caf_utils.h" + +#include +#include +#include + +#include + +#include + +namespace Mayo { + +namespace Internal { +static std::mutex mutex_XCAFApplication; +} // namespace Internal + +QLatin1String CafUtils::labelTag(const TDF_Label& label) +{ + static thread_local TCollection_AsciiString entry; + TDF_Tool::Entry(label, entry); + return QLatin1String(entry.ToCString(), entry.Length()); +} + +QString CafUtils::labelAttrStdName(const TDF_Label& label) +{ + Handle_TDataStd_Name attrName; + if (label.FindAttribute(TDataStd_Name::GetID(), attrName)) + return occ::QtUtils::toQString(attrName->Get()); + return QString(); +} + +Handle_TDocStd_Document CafUtils::createXdeDocument(const char *format) +{ + Handle_TDocStd_Document doc; + std::lock_guard lock(Internal::mutex_XCAFApplication); + XCAFApp_Application::GetApplication()->NewDocument(format, doc); + return doc; +} + +} // namespace Mayo diff --git a/src/base/caf_utils.h b/src/base/caf_utils.h new file mode 100644 index 00000000..d36cb028 --- /dev/null +++ b/src/base/caf_utils.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +namespace Mayo { + +struct CafUtils { + static QLatin1String labelTag(const TDF_Label& label); + static QString labelAttrStdName(const TDF_Label& label); + + static Handle_TDocStd_Document createXdeDocument(const char* format = "XmlXCAF"); +}; + +} // namespace Mayo + +namespace std { + +//! Specialization of C++11 std::hash<> functor for TDF_Label +template<> struct hash { + inline size_t operator()(const TDF_Label& lbl) const + { return qHash(Mayo::CafUtils::labelTag(lbl)); } +}; + +} // namespace std diff --git a/src/base/document.cpp b/src/base/document.cpp new file mode 100644 index 00000000..e3a6dfd2 --- /dev/null +++ b/src/base/document.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "application.h" +#include "document.h" +#include "document_item.h" + +namespace Mayo { + +Document::Document(QObject* parent) + : PropertyOwnerSignals(parent), + propertyLabel(this, tr("Label")), + propertyFilePath(this, tr("File path")) +{ + this->propertyFilePath.setUserReadOnly(true); +} + +Document::~Document() +{ + for (DocumentItem* item : m_rootItems) + delete item; +} + +const QString &Document::label() const +{ + return this->propertyLabel.value(); +} + +void Document::setLabel(const QString &v) +{ + this->propertyLabel.setValue(v); +} + +const QString &Document::filePath() const +{ + return this->propertyFilePath.value(); +} + +void Document::setFilePath(const QString &filepath) +{ + this->propertyFilePath.setValue(filepath); +} + +bool Document::eraseRootItem(DocumentItem *docItem) +{ + auto itFound = std::find(m_rootItems.cbegin(), m_rootItems.cend(), docItem); + if (itFound != m_rootItems.cend()) { + m_rootItems.erase(itFound); + emit itemErased(docItem); + delete docItem; + return true; + } + return false; +} + +Span Document::rootItems() const +{ + return m_rootItems; +} + +bool Document::isEmpty() const +{ + return m_rootItems.empty(); +} + +const char Document::TypeName[] = "Mayo::Document"; +const char* Document::dynTypeName() const +{ + return Document::TypeName; +} + +void Document::addRootItem(DocumentItem* item) +{ + item->setDocument(this); + m_rootItems.push_back(item); + emit itemAdded(item); +} + +} // namespace Mayo diff --git a/src/base/document.h b/src/base/document.h new file mode 100644 index 00000000..5a88baa4 --- /dev/null +++ b/src/base/document.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "application.h" +#include "property_builtins.h" +#include +#include + +namespace Mayo { + +class DocumentItem; + +class Document : public PropertyOwnerSignals { + Q_OBJECT +public: + Document(QObject* parent = Application::instance()); + virtual ~Document(); + + const QString& label() const; + void setLabel(const QString& v); + + const QString& filePath() const; + void setFilePath(const QString& filepath); + + void addRootItem(DocumentItem* item); + bool eraseRootItem(DocumentItem* docItem); + + Span rootItems() const; + bool isEmpty() const; + + PropertyQString propertyLabel; + PropertyQString propertyFilePath; + + static const char TypeName[]; + virtual const char* dynTypeName() const; + +signals: + void itemAdded(DocumentItem* docItem); + void itemErased(const DocumentItem* docItem); + void itemPropertyChanged(DocumentItem* docItem, Property* prop); + +private: + friend class Application; + friend class DocumentItem; + + std::vector m_rootItems; +}; + +} // namespace Mayo diff --git a/src/base/document_item.cpp b/src/base/document_item.cpp new file mode 100644 index 00000000..42dce8d5 --- /dev/null +++ b/src/base/document_item.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "document_item.h" + +#include "document.h" + +#include +#include +#include + +namespace Mayo { + +DocumentItem::DocumentItem() + : propertyLabel(this, QCoreApplication::translate("Mayo::DocumentItem", "Label")) +{ +} + +DocumentItem::~DocumentItem() +{ +} + +Document* DocumentItem::document() const +{ + return m_document; +} + +void DocumentItem::setDocument(Document* doc) +{ + m_document = doc; +} + +std::unique_ptr DocumentItem::propertiesAtNode(TreeNodeId) const +{ + return std::unique_ptr(); +} + +void DocumentItem::onPropertyChanged(Property* prop) +{ + if (m_document) + emit m_document->itemPropertyChanged(this, prop); +} + +PartItem::PartItem() + : propertyArea( + this, QCoreApplication::translate("Mayo::PartItem", "Computed area")), + propertyVolume( + this, QCoreApplication::translate("Mayo::PartItem", "Computed volume")) +{ +// this->propertyVolume.setRange(0., std::numeric_limits::max()); +// this->propertyArea.setRange(0., std::numeric_limits::max()); + this->propertyVolume.setUserReadOnly(true); + this->propertyArea.setUserReadOnly(true); +} + +bool PartItem::isNull() const +{ + return false; +} + +const char PartItem::TypeName[] = "247d246a-6316-4a99-b68e-bdcf565fa8aa"; +const char* PartItem::dynTypeName() const { return PartItem::TypeName; } + +bool sameType(const DocumentItem* lhs, const DocumentItem* rhs) +{ + if (lhs && rhs) + return std::strcmp(lhs->dynTypeName(), rhs->dynTypeName()) == 0; + + return false; +} + +DocumentItemNode::DocumentItemNode(DocumentItem* docItem, TreeNodeId nodeId) + : documentItem(docItem), + id(nodeId) +{ +} + +bool DocumentItemNode::isValid() const +{ + return this->documentItem && this->id != 0; +} + +const DocumentItemNode& DocumentItemNode::null() +{ + static const DocumentItemNode node = {}; + return node; +} + +} // namespace Mayo diff --git a/src/base/document_item.h b/src/base/document_item.h new file mode 100644 index 00000000..b99b55c5 --- /dev/null +++ b/src/base/document_item.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "property_builtins.h" +#include "libtree.h" +#include +#include +#include + +namespace Mayo { + +class Document; + +class DocumentItem : public PropertyOwner { +public: + DocumentItem(); + virtual ~DocumentItem(); + + Document* document() const; + void setDocument(Document* doc); + + PropertyQString propertyLabel; + + virtual std::unique_ptr propertiesAtNode(TreeNodeId nodeId) const; + + virtual const char* dynTypeName() const = 0; + +protected: + void onPropertyChanged(Property* prop) override; + +private: + Document* m_document = nullptr; +}; + +struct DocumentItemNode { + DocumentItemNode() = default; + DocumentItemNode(DocumentItem* docItem, TreeNodeId nodeId); + + bool isValid() const; + static const DocumentItemNode& null(); + + DocumentItem* documentItem; + TreeNodeId id; +}; + +class PartItem : public DocumentItem { +public: + PartItem(); + + virtual bool isNull() const; + + static const char TypeName[]; + const char* dynTypeName() const override; + + PropertyArea propertyArea; // Read-only + PropertyVolume propertyVolume; // Read-only +}; + +bool sameType(const DocumentItem* lhs, const DocumentItem* rhs); + +template bool sameType(const DocumentItem* item) +{ + return item ? std::strcmp(item->dynTypeName(), T::TypeName) == 0 : false; +} + +} // namespace Mayo diff --git a/src/base/geom_utils.cpp b/src/base/geom_utils.cpp new file mode 100644 index 00000000..b7ac27d3 --- /dev/null +++ b/src/base/geom_utils.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "geom_utils.h" +#include "math_utils.h" +#include +#include + +namespace Mayo { + +double GeomUtils::normalizedU(const Adaptor3d_Curve& curve, double u) +{ + const double uFirst = curve.FirstParameter(); + const double uLast = curve.LastParameter(); + const std::pair uRange = std::minmax(uFirst, uLast); + return MathUtils::mappedValue(u, uRange.first, uRange.second, 0, 1); +} + +gp_Pnt GeomUtils::d0(const Adaptor3d_Curve& curve, double u) +{ + gp_Pnt pnt; + curve.D0(u, pnt); + return pnt; +} + +gp_Vec GeomUtils::d1(const Adaptor3d_Curve& curve, double u) +{ + gp_Pnt pnt; + gp_Vec vec; + curve.D1(u, pnt, vec); + return vec; +} + +std::pair GeomUtils::d0d1(const Adaptor3d_Curve& curve, double u) +{ + gp_Pnt pnt; + gp_Vec vec; + curve.D1(u, pnt, vec); + return { pnt, vec }; +} + +} // namespace Mayo diff --git a/src/base/geom_utils.h b/src/base/geom_utils.h new file mode 100644 index 00000000..47ce7d15 --- /dev/null +++ b/src/base/geom_utils.h @@ -0,0 +1,23 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +class Adaptor3d_Curve; + +namespace Mayo { +namespace GeomUtils { + +double normalizedU(const Adaptor3d_Curve& curve, double u); +gp_Pnt d0(const Adaptor3d_Curve& curve, double u); +gp_Vec d1(const Adaptor3d_Curve& curve, double u); +std::pair d0d1(const Adaptor3d_Curve& curve, double u); + +} // namespace GeomUtils +} // namespace Mayo diff --git a/src/base/libtree.h b/src/base/libtree.h new file mode 100644 index 00000000..a74c29c4 --- /dev/null +++ b/src/base/libtree.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "span.h" +#include + +namespace Mayo { + +using TreeNodeId = uint32_t; + +template class Tree { +public: + Tree(); + + TreeNodeId nodeSiblingPrevious(TreeNodeId id) const; + TreeNodeId nodeSiblingNext(TreeNodeId id) const; + TreeNodeId nodeChildFirst(TreeNodeId id) const; + TreeNodeId nodeChildLast(TreeNodeId id) const; + TreeNodeId nodeParent(TreeNodeId id) const; + const T& nodeData(TreeNodeId id) const; + Span roots() const; + + void clear(); + TreeNodeId appendChild(TreeNodeId parentId, const T& data); + +private: + struct TreeNode { + TreeNodeId siblingPrevious; + TreeNodeId siblingNext; + TreeNodeId childFirst; + TreeNodeId childLast; + TreeNodeId parent; + T data; + }; + + TreeNodeId lastNodeId() const; + TreeNode* ptrNode(TreeNodeId id); + const TreeNode* ptrNode(TreeNodeId id) const; + + std::vector m_vecNode; + std::vector m_vecRoot; +}; + +template +void deepForeachTreeNode(const Tree& tree, const FUNC& func); + +template +void deepForeachTreeNode(TreeNodeId node, const Tree& tree, const FUNC& func); + + + +// -- +// -- Implementation +// -- + +template Tree::Tree() {} + +template TreeNodeId Tree::nodeSiblingPrevious(TreeNodeId id) const { + const TreeNode* node = this->ptrNode(id); + return node ? node->siblingPrevious : 0; +} + +template TreeNodeId Tree::nodeSiblingNext(TreeNodeId id) const { + const TreeNode* node = this->ptrNode(id); + return node ? node->siblingNext : 0; +} + +template TreeNodeId Tree::nodeChildFirst(TreeNodeId id) const { + const TreeNode* node = this->ptrNode(id); + return node ? node->childFirst : 0; +} + +template TreeNodeId Tree::nodeChildLast(TreeNodeId id) const { + const TreeNode* node = this->ptrNode(id); + return node ? node->childLast : 0; +} + +template TreeNodeId Tree::nodeParent(TreeNodeId id) const { + const TreeNode* node = this->ptrNode(id); + return node ? node->parent : 0; +} + +template const T& Tree::nodeData(TreeNodeId id) const { + static const T nullObject = {}; + const TreeNode* node = this->ptrNode(id); + return node ? node->data : nullObject; +} + +template +void Tree::clear() +{ + m_vecNode.clear(); + m_vecRoot.clear(); +} + +template +TreeNodeId Tree::appendChild(TreeNodeId parentId, const T& data) +{ + m_vecNode.push_back({}); + const TreeNodeId nodeId = this->lastNodeId(); + TreeNode* node = &m_vecNode.back(); + node->data = data; + node->parent = parentId; + node->siblingPrevious = this->nodeChildLast(parentId); + if (parentId != 0) { + TreeNode* parentNode = this->ptrNode(parentId); + if (parentNode->childFirst == 0) + parentNode->childFirst = nodeId; + + if (parentNode->childLast != 0) + this->ptrNode(parentNode->childLast)->siblingNext = nodeId; + + parentNode->childLast = nodeId; + } + else { + m_vecRoot.push_back(nodeId); + } + + return nodeId; +} + +template +Span Tree::roots() const { + return m_vecRoot; +} + +template +TreeNodeId Tree::lastNodeId() const { + return static_cast(m_vecNode.size()); +} + +template +typename Tree::TreeNode* Tree::ptrNode(TreeNodeId id) +{ + return id != 0 && id <= m_vecNode.size() ? &m_vecNode.at(id - 1) : nullptr; +} + +template +const typename Tree::TreeNode* Tree::ptrNode(TreeNodeId id) const +{ + return id != 0 && id <= m_vecNode.size() ? &m_vecNode.at(id - 1) : nullptr; +} + +template +void deepForeachTreeNode(TreeNodeId node, const Tree& tree, const FUNC& func) +{ + func(node); + const TreeNodeId childFirst = tree.nodeChildFirst(node); + for (auto it = childFirst; it != 0; it = tree.nodeSiblingNext(it)) + deepForeachTreeNode(it, tree, func); +} + +template +void deepForeachTreeNode(const Tree& tree, const FUNC& func) +{ + for (TreeNodeId node : tree.roots()) + deepForeachTreeNode(node, tree, func); +} + +} // namespace Mayo diff --git a/src/base/math_utils.cpp b/src/base/math_utils.cpp new file mode 100644 index 00000000..2984f667 --- /dev/null +++ b/src/base/math_utils.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "math_utils.h" +#include "bnd_utils.h" + +#include +#include +#include + +namespace Mayo { + +double MathUtils::mappedValue( + double val, double omin, double omax, double nmin, double nmax) +{ + return (((val - omin) * (nmax - nmin)) / (omax - omin)) + nmin; +} + +bool MathUtils::isReversedStandardDir(const gp_Dir& n) +{ + for (int i = 0; i < 3; ++i) { + const double c = n.XYZ().GetData()[i]; + if (c < 0 && (std::abs(c) - 1) < Precision::Confusion()) + return true; + } + return false; +} + +double MathUtils::planePosition(const gp_Pln& plane) +{ + const gp_Vec vecLoc(plane.Location().XYZ()); + const gp_Vec vecNormal(plane.Axis().Direction()); + return vecLoc.Dot(vecNormal); +} + +std::pair MathUtils::planeRange( + const BndBoxCoords &bbc, const gp_Dir &planeNormal) +{ + const gp_Vec n(MathUtils::isReversedStandardDir(planeNormal) ? + planeNormal.Reversed() : + planeNormal); + bool isMaxValid = false; + bool isMinValid = false; + double rmax; + double rmin; + for (const gp_Pnt& bndPoint : bbc.vertices()) { + const gp_Vec vec(bndPoint.XYZ()); + const double dot = n.Dot(vec); + rmax = isMaxValid ? std::max(rmax, dot) : dot; + rmin = isMinValid ? std::min(rmin, dot) : dot; + isMaxValid = true; + isMinValid = true; + } + if (isMaxValid && isMinValid) + return { rmin, rmax }; + return {}; +} + +} // namespace Mayo diff --git a/src/base/math_utils.h b/src/base/math_utils.h new file mode 100644 index 00000000..61f888b3 --- /dev/null +++ b/src/base/math_utils.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace Mayo { + +struct BndBoxCoords; + +struct MathUtils { + static double mappedValue( + double val, double omin, double omax, double nmin, double nmax); + + static bool isReversedStandardDir(const gp_Dir& n); + static double planePosition(const gp_Pln& plane); + static std::pair planeRange( + const BndBoxCoords& bbc, const gp_Dir& planeNormal); + + template static T lerp(T a, T b, U t); +}; + + +// -- +// -- Implementation +// -- + +template T MathUtils::lerp(T a, T b, U t) +{ + // TODO Call std::lerp() when available(C++20) + return T(a * (1 - t) + b * t); +} + +} // namespace Mayo diff --git a/src/base/mesh_item.cpp b/src/base/mesh_item.cpp new file mode 100644 index 00000000..8c41ffb7 --- /dev/null +++ b/src/base/mesh_item.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "mesh_item.h" + +#include + +namespace Mayo { + +MeshItem::MeshItem() + : propertyNodeCount( + this, QCoreApplication::translate("Mayo::MeshItem", "Node count")), + propertyTriangleCount( + this, QCoreApplication::translate("Mayo::MeshItem", "Triangle count")) +{ + this->propertyNodeCount.setUserReadOnly(true); + this->propertyTriangleCount.setUserReadOnly(true); +} + +const Handle_Poly_Triangulation& MeshItem::triangulation() const +{ + return m_triangulation; +} + +void MeshItem::setTriangulation(const Handle_Poly_Triangulation& mesh) +{ + m_triangulation = mesh; +} + +bool MeshItem::isNull() const +{ + return m_triangulation.IsNull(); +} + +const char MeshItem::TypeName[] = "2d441323-48db-4222-91b4-bdb7b5460c3f"; +const char* MeshItem::dynTypeName() const { return MeshItem::TypeName; } + +} // namespace Mayo diff --git a/src/base/mesh_item.h b/src/base/mesh_item.h new file mode 100644 index 00000000..91acbda3 --- /dev/null +++ b/src/base/mesh_item.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "document_item.h" +#include + +namespace Mayo { + +class MeshItem : public PartItem { +public: + MeshItem(); + + const Handle_Poly_Triangulation& triangulation() const; + void setTriangulation(const Handle_Poly_Triangulation& mesh); + + bool isNull() const override; + + static const char TypeName[]; + const char* dynTypeName() const override; + + PropertyInt propertyNodeCount; // Read-only + PropertyInt propertyTriangleCount; // Read-only + +private: + Handle_Poly_Triangulation m_triangulation; +}; + +} // namespace Mayo diff --git a/src/base/mesh_utils.cpp b/src/base/mesh_utils.cpp new file mode 100644 index 00000000..f2897ce0 --- /dev/null +++ b/src/base/mesh_utils.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "mesh_utils.h" +#include +#include + +namespace Mayo { + +double MeshUtils::triangleSignedVolume( + const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3) +{ + return p1.Dot(p2.Crossed(p3)) / 6.0f; +} + +double MeshUtils::triangleArea( + const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3) +{ + const double ax = p2.X() - p1.X(); + const double ay = p2.Y() - p1.Y(); + const double az = p2.Z() - p1.Z(); + const double bx = p3.X() - p1.X(); + const double by = p3.Y() - p1.Y(); + const double bz = p3.Z() - p1.Z(); + const double cx = ay*bz - az*by; + const double cy = az*bx - ax*bz; + const double cz = ax*by - ay*bx; + return 0.5 * std::sqrt(cx*cx + cy*cy + cz*cz); +} + +double MeshUtils::triangulationVolume( + const Handle_Poly_Triangulation& triangulation) +{ + double volume = 0; + const TColgp_Array1OfPnt& vecNode = triangulation->Nodes(); + // TODO Parallelize computation + for (const Poly_Triangle& tri : triangulation->Triangles()) { + int v1, v2, v3; + tri.Get(v1, v2, v3); + volume += MeshUtils::triangleSignedVolume( + vecNode.Value(v1).Coord(), + vecNode.Value(v2).Coord(), + vecNode.Value(v3).Coord()); + } + + return std::abs(volume); +} + +double MeshUtils::triangulationArea( + const Handle_Poly_Triangulation& triangulation) +{ + double area = 0; + const TColgp_Array1OfPnt& vecNode = triangulation->Nodes(); + // TODO Parallelize computation + for (const Poly_Triangle& tri : triangulation->Triangles()) { + int v1, v2, v3; + tri.Get(v1, v2, v3); + area += MeshUtils::triangleArea( + vecNode.Value(v1).Coord(), + vecNode.Value(v2).Coord(), + vecNode.Value(v3).Coord()); + } + + return area; +} + +// Adapted from http://cs.smith.edu/~jorourke/Code/polyorient.C +MeshUtils::Orientation MeshUtils::orientation(const AdaptorPolyline2d& polyline) +{ + const int pntCount = polyline.pointCount(); + if (pntCount < 2) + return Orientation::Unknown; + + gp_Pnt2d pntExtreme = polyline.pointAt(0); + int indexPntExtreme = 0; + for (int i = 1; i < pntCount; ++i) { + const gp_Pnt2d pnt = polyline.pointAt(i); + if (pnt.Y() < pntExtreme.Y() + || (qFuzzyCompare(pnt.Y(), pntExtreme.Y()) && (pnt.X() > pntExtreme.X()))) + { + pntExtreme = pnt; + indexPntExtreme = i; + } + } + + const gp_Pnt2d beforeExtremePnt = polyline.pointAt((indexPntExtreme + (pntCount - 1)) % pntCount); + const gp_Pnt2d afterExtremePnt = polyline.pointAt((indexPntExtreme + 1) % pntCount); + const gp_Pnt2d& a = beforeExtremePnt; + const gp_Pnt2d& b = pntExtreme; + const gp_Pnt2d& c = afterExtremePnt; + const double triangleArea = + a.X() * b.Y() - a.Y() * b.X() + + a.Y() * c.X() - a.X() * c.Y() + + b.Y() * c.X() - c.X() * b.Y(); + + auto fnQualifyArea = [](double area) { + if (area > 0) + return Orientation::CounterClockwise; + else if (area < 0) + return Orientation::Clockwise; + else + return Orientation::Unknown; + }; + + const Orientation orientation = fnQualifyArea(triangleArea); + if (orientation != Orientation::Unknown) { + return orientation; + } + else { + double polylineArea = 0.; + for (int i = 0; i < pntCount; ++i) { + const gp_Pnt2d pntBefore = polyline.pointAt((i + (pntCount - 1)) % pntCount); + const gp_Pnt2d pntCurrent = polyline.pointAt(i); + const gp_Pnt2d pntAfter = polyline.pointAt((i + 1) % pntCount); + polylineArea += pntCurrent.X() * (pntAfter.Y() - pntBefore.Y()); + } + + return fnQualifyArea(polylineArea); + } +} + +gp_Vec MeshUtils::directionAt(const MeshUtils::AdaptorPolyline3d& polyline, int i) +{ + const int pntCount = polyline.pointCount(); + if (pntCount > 1) { + const gp_Pnt& pnt = polyline.pointAt(i); + const int indexLastPos = pntCount - 1; + if (i < indexLastPos) { + const gp_Pnt& nextPnt = polyline.pointAt(i + 1); + return gp_Vec(pnt, nextPnt); + } + else if (i == indexLastPos) { + const gp_Pnt& prevPnt = polyline.pointAt(i - 1); + return gp_Vec(prevPnt, pnt); + } + } + + return gp_Vec(); +} + +} // namespace Mayo diff --git a/src/base/mesh_utils.h b/src/base/mesh_utils.h new file mode 100644 index 00000000..91373c72 --- /dev/null +++ b/src/base/mesh_utils.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +class gp_XYZ; + +namespace Mayo { + +struct MeshUtils { + static double triangleSignedVolume( + const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3); + static double triangleArea( + const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3); + + static double triangulationVolume(const Handle_Poly_Triangulation& triangulation); + static double triangulationArea(const Handle_Poly_Triangulation& triangulation); + + enum class Orientation { + Unknown, + Clockwise, + CounterClockwise + }; + + class AdaptorPolyline2d { + public: + virtual gp_Pnt2d pointAt(int index) const = 0; + virtual int pointCount() const = 0; + virtual bool empty() const { return this->pointCount() <= 0; } + }; + + class AdaptorPolyline3d { + public: + virtual const gp_Pnt& pointAt(int i) const = 0; + virtual int pointCount() const = 0; + virtual int empty() const { return this->pointCount() <= 0; } + }; + + static Orientation orientation(const AdaptorPolyline2d& polyline); + static gp_Vec directionAt(const AdaptorPolyline3d& polyline, int i); +}; + +} // namespace Mayo diff --git a/src/base/occt_enums.cpp b/src/base/occt_enums.cpp new file mode 100644 index 00000000..0990ce5e --- /dev/null +++ b/src/base/occt_enums.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "occt_enums.h" +#include + +namespace Mayo { + +const Enumeration& OcctEnums::Graphic3d_NameOfMaterial() +{ + static Enumeration enumeration; + if (enumeration.size() == 0) { + enumeration.addItem( + Graphic3d_NOM_BRASS, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Brass")); + enumeration.addItem( + Graphic3d_NOM_BRONZE, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Bronze")); + enumeration.addItem( + Graphic3d_NOM_COPPER, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Copper")); + enumeration.addItem( + Graphic3d_NOM_GOLD, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Gold")); + enumeration.addItem( + Graphic3d_NOM_PEWTER, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Pewter")); + enumeration.addItem( + Graphic3d_NOM_PLASTER, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Plaster")); + enumeration.addItem( + Graphic3d_NOM_PLASTIC, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Plastic")); + enumeration.addItem( + Graphic3d_NOM_SILVER, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Silver")); + enumeration.addItem( + Graphic3d_NOM_STEEL, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Steel")); + enumeration.addItem( + Graphic3d_NOM_STONE, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Stone")); + enumeration.addItem( + Graphic3d_NOM_SHINY_PLASTIC, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Shiny plastic")); + enumeration.addItem( + Graphic3d_NOM_SATIN, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Satin")); + enumeration.addItem( + Graphic3d_NOM_METALIZED, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Metalized")); + enumeration.addItem( + Graphic3d_NOM_NEON_GNC, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Neon gnc")); + enumeration.addItem( + Graphic3d_NOM_CHROME, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Chrome")); + enumeration.addItem( + Graphic3d_NOM_ALUMINIUM, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Aluminium")); + enumeration.addItem( + Graphic3d_NOM_OBSIDIAN, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Obsidian")); + enumeration.addItem( + Graphic3d_NOM_NEON_PHC, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Neon phc")); + enumeration.addItem( + Graphic3d_NOM_JADE, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Jade")); + enumeration.addItem( + Graphic3d_NOM_DEFAULT, + QCoreApplication::translate("Mayo::EnumGpxMaterial", "Default")); + } + + return enumeration; +} + +const Enumeration& OcctEnums::Aspect_HatchStyle() +{ + static Enumeration enumeration; + if (enumeration.size() == 0) { + enumeration.addItem( + Aspect_HS_SOLID, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Solid")); + enumeration.addItem( + Aspect_HS_HORIZONTAL, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Horizontal")); + enumeration.addItem( + Aspect_HS_HORIZONTAL_WIDE, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Horizontal sparse")); + enumeration.addItem( + Aspect_HS_VERTICAL, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Vertical")); + enumeration.addItem( + Aspect_HS_VERTICAL_WIDE, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Vertical sparse")); + enumeration.addItem( + Aspect_HS_DIAGONAL_45, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Diagonal_45")); + enumeration.addItem( + Aspect_HS_DIAGONAL_45_WIDE, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Diagonal_45 sparse")); + enumeration.addItem( + Aspect_HS_DIAGONAL_135, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Diagonal_135")); + enumeration.addItem( + Aspect_HS_DIAGONAL_135_WIDE, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Diagonal_135 sparse")); + enumeration.addItem( + Aspect_HS_GRID, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Grid")); + enumeration.addItem( + Aspect_HS_GRID_WIDE, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Grid sparse")); + enumeration.addItem( + Aspect_HS_GRID_DIAGONAL, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Grid diagonal")); + enumeration.addItem( + Aspect_HS_GRID_DIAGONAL_WIDE, + QCoreApplication::translate("Mayo::EnumHatchStyle", "Grid diagonal sparse")); + } + + return enumeration; +} + +} // namespace Mayo diff --git a/src/base/occt_enums.h b/src/base/occt_enums.h new file mode 100644 index 00000000..de58f1f4 --- /dev/null +++ b/src/base/occt_enums.h @@ -0,0 +1,21 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "property_enumeration.h" +#include +#include + +namespace Mayo { + +class OcctEnums { +public: + static const Enumeration& Graphic3d_NameOfMaterial(); + static const Enumeration& Aspect_HatchStyle(); +}; + +} // namespace Mayo diff --git a/src/base/property.cpp b/src/base/property.cpp new file mode 100644 index 00000000..ec9d39a4 --- /dev/null +++ b/src/base/property.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "property.h" + +#include "property_enumeration.h" +#include + +namespace Mayo { + +Span PropertyOwner::properties() const +{ + return m_properties; +} + +void PropertyOwner::onPropertyChanged(Property* /*prop*/) +{ +} + +Result PropertyOwner::isPropertyValid(const Property*) const +{ + return Result::ok(); +} + +void PropertyOwner::blockPropertyChanged(bool on) +{ + m_propertyChangedBlocked = on; +} + +bool PropertyOwner::isPropertyChangedBlocked() const +{ + return m_propertyChangedBlocked; +} + +void PropertyOwner::addProperty(Property* prop) +{ + m_properties.emplace_back(prop); +} + +void PropertyOwner::removeProperty(Property* prop) +{ + auto it = std::find(m_properties.begin(), m_properties.end(), prop); + if (it != m_properties.end()) + m_properties.erase(it); +} + +const QString &Property::label() const +{ + return m_label; +} + +bool Property::isUserReadOnly() const +{ + return m_isUserReadOnly; +} + +void Property::setUserReadOnly(bool on) +{ + m_isUserReadOnly = on; +} + +Property::Property(PropertyOwner* owner, const QString& label) + : m_owner(owner), + m_label(label) +{ + if (m_owner) + m_owner->addProperty(this); +} + +void Property::notifyChanged() +{ + if (m_owner && !m_owner->isPropertyChangedBlocked()) + m_owner->onPropertyChanged(this); +} + +Result Property::isValid() const +{ + if (m_owner) + return m_owner->isPropertyValid(this); + + return Result::ok(); +} + +bool Property::hasOwner() const +{ + return m_owner != nullptr; +} + + +PropertyChangedBlocker::PropertyChangedBlocker(PropertyOwner* owner) + : m_owner(owner) +{ + if (m_owner) + m_owner->blockPropertyChanged(true); +} + +PropertyChangedBlocker::~PropertyChangedBlocker() +{ + if (m_owner) + m_owner->blockPropertyChanged(false); +} + + +PropertyOwnerSignals::PropertyOwnerSignals(QObject* parent) + : QObject(parent) +{ +} + +void PropertyOwnerSignals::onPropertyChanged(Property* prop) +{ + PropertyOwner::onPropertyChanged(prop); + emit propertyChanged(prop); +} + +} // namespace Mayo diff --git a/src/base/property.h b/src/base/property.h new file mode 100644 index 00000000..b7f0131e --- /dev/null +++ b/src/base/property.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "span.h" +#include "result.h" + +#include +#include +#include +#include + +namespace Mayo { + +class Property; + +class PropertyOwner { +public: + // TODO change to computed properties, remove member m_properties + Span properties() const; + +protected: + virtual void onPropertyChanged(Property* prop); + virtual Result isPropertyValid(const Property* prop) const; + void blockPropertyChanged(bool on); + bool isPropertyChangedBlocked() const; + + void addProperty(Property* prop); + void removeProperty(Property* prop); + +private: + friend class Property; + friend struct PropertyChangedBlocker; + std::vector m_properties; + bool m_propertyChangedBlocked = false; +}; + +struct PropertyChangedBlocker { + PropertyChangedBlocker(PropertyOwner* owner); + ~PropertyChangedBlocker(); + PropertyOwner* const m_owner; +}; + +#define Mayo_PropertyChangedBlocker(owner) \ + Mayo::PropertyChangedBlocker __Mayo_PropertyChangedBlocker(owner); \ + Q_UNUSED(__Mayo_PropertyChangedBlocker); + +class Property { +public: + Property(PropertyOwner* owner, const QString& label); + Property() = delete; + Property(const Property&) = delete; + Property(Property&&) = delete; + Property& operator=(const Property&) = delete; + Property& operator=(Property&&) = delete; + virtual ~Property() = default; + + const QString& label() const; + + virtual QVariant valueAsVariant() const = 0; + virtual Result setValueFromVariant(const QVariant& value) = 0; + + bool isUserReadOnly() const; + void setUserReadOnly(bool on); + + virtual const char* dynTypeName() const = 0; + +protected: + void notifyChanged(); + Result isValid() const; + bool hasOwner() const; + + template + static Result setValueHelper( + Property* prop, T* ptrValue, const T& newValue); + +private: + PropertyOwner* const m_owner = nullptr; + const QString m_label; + bool m_isUserReadOnly = false; +}; + +class PropertyOwnerSignals : public QObject, public PropertyOwner { + Q_OBJECT +public: + PropertyOwnerSignals(QObject* parent = nullptr); + +signals: + void propertyChanged(Property* prop); + +protected: + void onPropertyChanged(Property* prop) override; +}; + + +// -- +// -- Implementation +// -- + +template Result Property::setValueHelper( + Property* prop, T* ptrValue, const T& newValue) +{ + Result result = Result::ok(); + if (prop->hasOwner()) { + const T previousValue = *ptrValue; + *ptrValue = newValue; + result = prop->isValid(); + if (result.valid()) + prop->notifyChanged(); + else + *ptrValue = previousValue; + } + else { + *ptrValue = newValue; + prop->notifyChanged(); + } + + return result; +} + +} // namespace Mayo + +Q_DECLARE_METATYPE(Mayo::Property*) +Q_DECLARE_METATYPE(const Mayo::Property*) diff --git a/src/base/property_builtins.cpp b/src/base/property_builtins.cpp new file mode 100644 index 00000000..c1726b32 --- /dev/null +++ b/src/base/property_builtins.cpp @@ -0,0 +1,33 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "property_builtins.h" + +namespace Mayo { + +const char *BasePropertyQuantity::dynTypeName() const +{ + return BasePropertyQuantity::TypeName; +} + +BasePropertyQuantity::BasePropertyQuantity(PropertyOwner *owner, const QString &label) + : Property(owner, label) +{ +} + +template<> const char PropertyBool::TypeName[] = "Mayo::PropertyBool"; +template<> const char GenericProperty/*PropertyInt*/::TypeName[] = "Mayo::PropertyInt"; +template<> const char GenericProperty/*PropertyDouble*/::TypeName[] = "Mayo::PropertyDouble"; +template<> const char PropertyQByteArray::TypeName[] = "Mayo::PropertyQByteArray"; +template<> const char PropertyQString::TypeName[] = "Mayo::PropertyQString"; +template<> const char PropertyQDateTime::TypeName[] = "Mayo::PropertyQDateTime"; +template<> const char PropertyOccColor::TypeName[] = "Mayo::PropertyOccColor"; +template<> const char PropertyOccPnt::TypeName[] = "Mayo::PropertyOccPnt"; +template<> const char PropertyOccTrsf::TypeName[] = "Mayo::PropertyOccTrsf"; + +const char BasePropertyQuantity::TypeName[] = "Mayo::BasePropertyQuantity"; + +} // namespace Mayo diff --git a/src/base/property_builtins.h b/src/base/property_builtins.h new file mode 100644 index 00000000..75ee81b4 --- /dev/null +++ b/src/base/property_builtins.h @@ -0,0 +1,283 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "property.h" +#include "result.h" +#include "qmeta_gp_pnt.h" +#include "qmeta_gp_trsf.h" +#include "qmeta_quantity_color.h" +#include "qmeta_quantity.h" + +#include +#include +#include + +namespace Mayo { + +template +class GenericProperty : public Property { +public: + using ValueType = T; + + GenericProperty(PropertyOwner* owner, const QString& label); + + const T& value() const; + Result setValue(const T& val); + + QVariant valueAsVariant() const override; + Result setValueFromVariant(const QVariant& variant) override; + + const char* dynTypeName() const override; + static const char TypeName[]; + +protected: + T m_value = {}; +}; + +template +class PropertyScalarConstraints { + static_assert(std::is_scalar::value, "Requires scalar type"); +public: + using ValueType = T; + + PropertyScalarConstraints() = default; + PropertyScalarConstraints(T minimum, T maximum, T singleStep); + + bool constraintsEnabled() const; + void setConstraintsEnabled(bool on); + + T minimum() const; + void setMinimum(T val); + + T maximum() const; + void setMaximum(T val); + + void setRange(T minVal, T maxVal); + + T singleStep() const; + void setSingleStep(T step); + +private: + T m_minimum; + T m_maximum; + T m_singleStep; + bool m_constraintsEnabled = false; +}; + +template +class GenericScalarProperty : + public GenericProperty, + public PropertyScalarConstraints +{ +public: + using ValueType = T; + GenericScalarProperty(PropertyOwner* owner, const QString& label); + GenericScalarProperty( + PropertyOwner* owner, const QString& label, + T minimum, T maximum, T singleStep); +}; + +class BasePropertyQuantity : + public Property, + public PropertyScalarConstraints +{ +public: + virtual Unit quantityUnit() const = 0; + virtual double quantityValue() const = 0; + virtual Result setQuantityValue(double v) = 0; + + const char* dynTypeName() const override; + static const char TypeName[]; + +protected: + BasePropertyQuantity(PropertyOwner* owner, const QString& label); +}; + +template +class GenericPropertyQuantity : public BasePropertyQuantity { +public: + using QuantityType = Quantity; + + GenericPropertyQuantity(PropertyOwner* owner, const QString& label); + + Unit quantityUnit() const override; + double quantityValue() const override; + Result setQuantityValue(double v) override; + + QVariant valueAsVariant() const override; + Result setValueFromVariant(const QVariant& variant) override; + + QuantityType quantity() const; + Result setQuantity(QuantityType qty); + +private: + QuantityType m_quantity = {}; +}; + +using PropertyBool = GenericProperty; +using PropertyInt = GenericScalarProperty; +using PropertyDouble = GenericScalarProperty; +using PropertyQByteArray = GenericProperty; +using PropertyQString = GenericProperty; +using PropertyQDateTime = GenericProperty; +using PropertyOccColor = GenericProperty; +using PropertyOccPnt = GenericProperty; +using PropertyOccTrsf = GenericProperty; + +using PropertyLength = GenericPropertyQuantity; +using PropertyArea = GenericPropertyQuantity; +using PropertyVolume = GenericPropertyQuantity; +using PropertyMass = GenericPropertyQuantity; +using PropertyTime = GenericPropertyQuantity; +using PropertyAngle = GenericPropertyQuantity; +using PropertyVelocity = GenericPropertyQuantity; + +// -- +// -- Implementation +// -- + +// GenericProperty<> + +template +GenericProperty::GenericProperty(PropertyOwner* owner, const QString& label) + : Property(owner, label) +{ } + +template const T& GenericProperty::value() const +{ return m_value; } + +template Result GenericProperty::setValue(const T& val) +{ + return Property::setValueHelper(this, &m_value, val); +} + +template QVariant GenericProperty::valueAsVariant() const +{ + return QVariant::fromValue(this->value()); +} + +template +Result GenericProperty::setValueFromVariant(const QVariant& variant) +{ + if (variant.canConvert()) + return this->setValue(variant.value()); + else + return Result::error("Incompatible type"); +} + +template const char* GenericProperty::dynTypeName() const +{ return TypeName; } + +// PropertyScalarConstraints<> + +template +PropertyScalarConstraints::PropertyScalarConstraints( + T minimum, T maximum, T singleStep) + : m_minimum(minimum), + m_maximum(maximum), + m_singleStep(singleStep), + m_constraintsEnabled(true) +{ } + +template bool PropertyScalarConstraints::constraintsEnabled() const +{ return m_constraintsEnabled; } + +template void PropertyScalarConstraints::setConstraintsEnabled(bool on) +{ m_constraintsEnabled = on; } + +template T PropertyScalarConstraints::minimum() const +{ return m_minimum; } + +template void PropertyScalarConstraints::setMinimum(T val) +{ m_minimum = val; } + +template T PropertyScalarConstraints::maximum() const +{ return m_maximum; } + +template void PropertyScalarConstraints::setMaximum(T val) +{ m_maximum = val; } + +template +void PropertyScalarConstraints::setRange(T minVal, T maxVal) +{ + this->setMinimum(minVal); + this->setMaximum(maxVal); +} + +template T PropertyScalarConstraints::singleStep() const +{ return m_singleStep; } + +template void PropertyScalarConstraints::setSingleStep(T step) +{ m_singleStep = step; } + +// GenericScalarProperty<> + +template +GenericScalarProperty::GenericScalarProperty( + PropertyOwner* owner, const QString& label) + : GenericProperty(owner, label) +{ } + +template +GenericScalarProperty::GenericScalarProperty( + PropertyOwner* owner, const QString& label, + T minimum, T maximum, T singleStep) + : GenericProperty(owner, label), + PropertyScalarConstraints(minimum, maximum, singleStep) +{ } + +// GenericPropertyQuantity<> + +template +GenericPropertyQuantity::GenericPropertyQuantity( + PropertyOwner* owner, const QString& label) + : BasePropertyQuantity(owner, label) +{ } + +template +Unit GenericPropertyQuantity::quantityUnit() const +{ return UNIT; } + +template +double GenericPropertyQuantity::quantityValue() const +{ + return this->quantity().value(); +} + +template +Result GenericPropertyQuantity::setQuantityValue(double v) +{ + return this->setQuantity(QuantityType(v)); +} + +template +QVariant GenericPropertyQuantity::valueAsVariant() const +{ + return QVariant::fromValue(this->quantity()); +} + +template +Result GenericPropertyQuantity::setValueFromVariant(const QVariant& variant) +{ + if (variant.canConvert()) + return this->setQuantity(variant.value()); + else + return Result::error("Incompatible quantity type"); +} + +template +Quantity GenericPropertyQuantity::quantity() const +{ return m_quantity; } + +template +Result GenericPropertyQuantity::setQuantity(Quantity qty) +{ + return Property::setValueHelper(this, &m_quantity, qty); +} + +} // namespace Mayo diff --git a/src/base/property_enumeration.cpp b/src/base/property_enumeration.cpp new file mode 100644 index 00000000..7fc60fe2 --- /dev/null +++ b/src/base/property_enumeration.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "property_enumeration.h" +#include + +namespace Mayo { + +void Enumeration::addItem(Value value, const QString& name) +{ + const Item item = { value, name}; + m_vecItem.emplace_back(std::move(item)); +} + +int Enumeration::size() const +{ + return int(m_vecItem.size()); +} + +int Enumeration::findIndex(Value value) const +{ + auto it = std::find_if( + m_vecItem.cbegin(), + m_vecItem.cend(), + [=](const Item& item) { return item.value == value; }); + return it != m_vecItem.cend() ? it - m_vecItem.cbegin() : -1; +} + +Enumeration::Value Enumeration::findValue(const QString& name) const +{ + for (const Item& item : m_vecItem) { + if (item.name == name) + return item.value; + } + + Q_ASSERT(false); + return -1; +} + +QString Enumeration::findName(Value value) const +{ + const int index = this->findIndex(value); + return index != -1 ? this->itemAt(index).name : QString(); +} + +Enumeration::Item Enumeration::itemAt(int index) const +{ + return m_vecItem.at(index); +} + +Span Enumeration::items() const +{ + return m_vecItem; +} + +PropertyEnumeration::PropertyEnumeration( + PropertyOwner* owner, + const QString& label, + const Enumeration* enumeration) + : Property(owner, label), + m_enumeration(enumeration) +{ + Q_ASSERT(m_enumeration != nullptr); + Q_ASSERT(m_enumeration->size() > 0); + m_value = m_enumeration->itemAt(0).value; +} + +const Enumeration& PropertyEnumeration::enumeration() const +{ + return *m_enumeration; +} + +QString PropertyEnumeration::name() const +{ + return m_enumeration->findName(m_value); +} + +Enumeration::Value PropertyEnumeration::value() const +{ + return m_value; +} + +Result PropertyEnumeration::setValue(Enumeration::Value v) +{ + // TODO: check v is an enumerated value of m_enumeration + return Property::setValueHelper(this, &m_value, v); +} + +QVariant PropertyEnumeration::valueAsVariant() const +{ + return QVariant::fromValue(m_value); +} + +Result PropertyEnumeration::setValueFromVariant(const QVariant& value) +{ + return this->setValue(value.toInt()); +} + +const char* PropertyEnumeration::dynTypeName() const +{ + return PropertyEnumeration::TypeName; +} + +const char PropertyEnumeration::TypeName[] = "Mayo::PropertyEnumeration"; + +} // namespace Mayo diff --git a/src/base/property_enumeration.h b/src/base/property_enumeration.h new file mode 100644 index 00000000..45c2ae87 --- /dev/null +++ b/src/base/property_enumeration.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "property.h" +#include "span.h" + +namespace Mayo { + +class Enumeration { +public: + using Value = int; + struct Item { + Value value; + QString name; + }; + + Enumeration() = default; + + void addItem(Value value, const QString& name); + int size() const; + + int findIndex(Value value) const; + QString findName(Value value) const; + Value findValue(const QString& name) const; + + Item itemAt(int index) const; + Span items() const; + +private: + std::vector m_vecItem; +}; + +class PropertyEnumeration : public Property { +public: + PropertyEnumeration( + PropertyOwner* owner, + const QString& label, + const Enumeration* enumeration); + + const Enumeration& enumeration() const; + + QString name() const; + Enumeration::Value value() const; + template T valueAs() const; + Result setValue(Enumeration::Value v); + + QVariant valueAsVariant() const override; + Result setValueFromVariant(const QVariant& value) override; + + const char* dynTypeName() const override; + static const char TypeName[]; + +private: + Enumeration::Value m_value; + const Enumeration* m_enumeration; +}; + + + +// -- Implementation + +template T PropertyEnumeration::valueAs() const +{ return static_cast(m_value); } + +} // namespace Mayo diff --git a/src/base/qmeta_gp_pnt.h b/src/base/qmeta_gp_pnt.h new file mode 100644 index 00000000..92aa0bc9 --- /dev/null +++ b/src/base/qmeta_gp_pnt.h @@ -0,0 +1,11 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +Q_DECLARE_METATYPE(gp_Pnt) diff --git a/src/base/qmeta_gp_trsf.h b/src/base/qmeta_gp_trsf.h new file mode 100644 index 00000000..6dad1c6f --- /dev/null +++ b/src/base/qmeta_gp_trsf.h @@ -0,0 +1,11 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +Q_DECLARE_METATYPE(gp_Trsf) diff --git a/src/base/qmeta_quantity.h b/src/base/qmeta_quantity.h new file mode 100644 index 00000000..979f87f2 --- /dev/null +++ b/src/base/qmeta_quantity.h @@ -0,0 +1,24 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "quantity.h" +#include +Q_DECLARE_METATYPE(Mayo::QuantityLength) +Q_DECLARE_METATYPE(Mayo::QuantityMass) +Q_DECLARE_METATYPE(Mayo::QuantityTime) +Q_DECLARE_METATYPE(Mayo::Quantity) +Q_DECLARE_METATYPE(Mayo::Quantity) +Q_DECLARE_METATYPE(Mayo::Quantity) +Q_DECLARE_METATYPE(Mayo::Quantity) +Q_DECLARE_METATYPE(Mayo::QuantityAngle) +Q_DECLARE_METATYPE(Mayo::QuantityArea) +Q_DECLARE_METATYPE(Mayo::QuantityVolume) +Q_DECLARE_METATYPE(Mayo::QuantityVelocity) +Q_DECLARE_METATYPE(Mayo::Quantity) +Q_DECLARE_METATYPE(Mayo::Quantity) +Q_DECLARE_METATYPE(Mayo::Quantity) diff --git a/src/base/qmeta_quantity_color.h b/src/base/qmeta_quantity_color.h new file mode 100644 index 00000000..66705433 --- /dev/null +++ b/src/base/qmeta_quantity_color.h @@ -0,0 +1,11 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +Q_DECLARE_METATYPE(Quantity_Color) diff --git a/src/base/qmeta_tdf_label.h b/src/base/qmeta_tdf_label.h new file mode 100644 index 00000000..a95a5133 --- /dev/null +++ b/src/base/qmeta_tdf_label.h @@ -0,0 +1,11 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +Q_DECLARE_METATYPE(TDF_Label) diff --git a/src/base/quantity.cpp b/src/base/quantity.cpp new file mode 100644 index 00000000..88c82fa8 --- /dev/null +++ b/src/base/quantity.cpp @@ -0,0 +1,11 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "quantity.h" + +namespace Mayo { + +} // namespace Mayo diff --git a/src/base/quantity.h b/src/base/quantity.h new file mode 100644 index 00000000..76363c99 --- /dev/null +++ b/src/base/quantity.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "unit.h" + +namespace Mayo { + +template class Quantity { + using Qty = Quantity; +public: + constexpr Quantity() = default; + constexpr explicit Quantity(double value): m_value(value) {} + + constexpr double value() const { return m_value; } + constexpr void setValue(double v) { m_value = v; } + constexpr Unit unit() const { return U; } + + constexpr Qty operator/(double v) const { return Qty(m_value / v); } + constexpr Qty operator+(Qty q) const { return Qty(m_value + q.value()); } + constexpr Qty operator-(Qty q) const { return Qty(m_value - q.value()); } + constexpr Qty operator-() const { return Qty(-m_value); } + + constexpr bool operator==(Qty q) const { return m_value == q.value(); } + constexpr bool operator<(Qty q) const { return m_value < q.value(); } + constexpr bool operator>(Qty q) const { return m_value > q.value(); } + constexpr bool operator<=(Qty q) const { return m_value <= q.value(); } + constexpr bool operator>=(Qty q) const { return m_value >= q.value(); } + + constexpr Qty& operator+=(Qty q) { return this->change(m_value + q.value()); } + constexpr Qty& operator-=(Qty q) { return this->change(m_value - q.value()); } + constexpr Qty& operator=(Qty q) { return this->change(q.value()); } + + constexpr static Qty null() { return Qty(0.); } + +private: + constexpr Qty& change(double v) { + m_value = v; + return *this; + } + + double m_value; +}; + +using QuantityLength = Quantity; +using QuantityArea = Quantity; +using QuantityVolume = Quantity; +using QuantityMass = Quantity; +using QuantityTime = Quantity; +using QuantityAngle = Quantity; +using QuantityVelocity = Quantity; + +template constexpr Quantity operator*(Quantity lhs, double rhs); +template constexpr Quantity operator*(double lhs, Quantity rhs); + +constexpr QuantityArea operator*(QuantityLength lhs, QuantityLength rhs); +constexpr QuantityVolume operator*(QuantityLength lhs, QuantityArea rhs); +constexpr QuantityVolume operator*(QuantityArea lhs, QuantityLength rhs); +constexpr QuantityVelocity operator/(QuantityLength lhs, QuantityTime rhs); +constexpr QuantityTime operator/(QuantityLength lhs, QuantityVelocity rhs); + +constexpr QuantityLength Quantity_Nanometer(1e-6); +constexpr QuantityLength Quantity_Micrometer(1e-3); +constexpr QuantityLength Quantity_Millimeter(1.); +constexpr QuantityLength Quantity_Centimeter(10.); +constexpr QuantityLength Quantity_Decimeter(100.); +constexpr QuantityLength Quantity_Meter(1000.); +constexpr QuantityLength Quantity_Kilometre(1e6); + +constexpr QuantityArea Quantity_SquaredMillimeter(1.); +constexpr QuantityArea Quantity_SquaredCentimer(100.); +constexpr QuantityArea Quantity_SquaredMeter(1e6); +constexpr QuantityArea Quantity_SquaredKilometer(1e12); + +constexpr QuantityVolume Quantity_CubicMillimeter(1.); +constexpr QuantityVolume Quantity_CubicCentimer(1000.); +constexpr QuantityVolume Quantity_CubicMeter(1e9); + +constexpr QuantityLength Quantity_Inch(25.4); +constexpr QuantityLength Quantity_Foot(304.8); +constexpr QuantityLength Quantity_Thou(0.0254); +constexpr QuantityLength Quantity_Yard(914.4); +constexpr QuantityLength Quantity_Mile(1609344.); + +constexpr QuantityVelocity Quantity_MillimeterPerSecond(1.); + +constexpr QuantityVolume Quantity_Liter(1e6); + +constexpr QuantityMass Quantity_Microgram(1e-9); +constexpr QuantityMass Quantity_Milligram(1e-6); +constexpr QuantityMass Quantity_Gram(0.001); +constexpr QuantityMass Quantity_Kilogram(1.); +constexpr QuantityMass Quantity_Ton(1000.); + +constexpr QuantityMass Quantity_Pound(0.45359237); +constexpr QuantityMass Quantity_Ounce(0.0283495231); +constexpr QuantityMass Quantity_Stone(6.35029318); +constexpr QuantityMass Quantity_Hundredweights(50.80234544); + +constexpr QuantityTime Quantity_Second(1.); +constexpr QuantityTime Quantity_Minute(60.); +constexpr QuantityTime Quantity_Hour(3600.); + +constexpr QuantityAngle Quantity_Degree(3.14159265358979323846 / 180.); +constexpr QuantityAngle Quantity_Radian(1.); + + + +// Implementation + +template constexpr Quantity operator*(Quantity lhs, double rhs) { + return Quantity(lhs.value() * rhs); +} + +template constexpr Quantity operator*(double lhs, Quantity rhs) { + return rhs * lhs; +} + +constexpr QuantityArea operator*(QuantityLength lhs, QuantityLength rhs) { + return QuantityArea(lhs.value() * rhs.value()); +} + +constexpr QuantityVolume operator*(QuantityLength lhs, QuantityArea rhs) { + return QuantityVolume(lhs.value() * rhs.value()); +} + +constexpr QuantityVolume operator*(QuantityArea lhs, QuantityLength rhs) { + return QuantityVolume(lhs.value() * rhs.value()); +} + +constexpr QuantityVelocity operator/(QuantityLength lhs, QuantityTime rhs) { + return QuantityVelocity(lhs.value() / rhs.value()); +} + +constexpr QuantityTime operator/(QuantityLength lhs, QuantityVelocity rhs) { + return QuantityTime(lhs.value() / rhs.value()); +} + +} // namespace Mayo diff --git a/src/base/result.cpp b/src/base/result.cpp new file mode 100644 index 00000000..7e5252d2 --- /dev/null +++ b/src/base/result.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "result.h" + +namespace Mayo { + +const QString& Result::errorText() const +{ + if (!m_isValid) + return m_errorText; + static const QString defaultErrorText; + return defaultErrorText; +} + +const Result& Result::ok() +{ + static const Result res(true); + return res; +} + +Result Result::error(const QString& errorText) +{ + Result res(false); + res.m_errorText = errorText; + return std::move(res); +} + +Result::Result(bool valid) + : m_isValid(valid) +{ +} + +} // namespace Mayo diff --git a/src/base/result.h b/src/base/result.h new file mode 100644 index 00000000..3fca4f09 --- /dev/null +++ b/src/base/result.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +template class Result { +public: + using Data = T; + + bool valid() const { return m_isValid; } + operator bool() const { return m_isValid; } + + T& get(); + const T& get() const; + + const QString& errorText() const; + + static Result ok(const T& data); + static Result ok(T&& data); + static Result error(const QString& errorText = QString()); + +private: + // TODO: union + T m_data; + QString m_errorText; + bool m_isValid; +}; + +template<> class Result { +public: + bool valid() const { return m_isValid; } + operator bool() const { return m_isValid; } + + const QString& errorText() const; + + static const Result& ok(); + static Result error(const QString& errorText = QString()); + +private: + Result(bool valid); + + QString m_errorText; + bool m_isValid; +}; + + +// -- +// -- Implementation +// -- + +template T& Result::get() +{ + if (m_isValid) + return m_data; + throw std::runtime_error("Data is invalid"); +} + +template const T& Result::get() const +{ + if (m_isValid) + return m_data; + throw std::runtime_error("Data is invalid"); +} + +template const QString& Result::errorText() const +{ + if (!m_isValid) + return m_errorText; + static const QString defaultErrorText; + return defaultErrorText; +} + +template Result Result::error(const QString& errorText) +{ + Result res; + res.m_isValid = false; + res.m_errorText = errorText; + return std::move(res); +} + +template Result Result::ok(const T& data) +{ + Result res; + res.m_isValid = true; + res.m_data = data; + return std::move(res); +} + +template Result Result::ok(T&& data) +{ + Result res; + res.m_isValid = true; + res.m_data = std::move(data); + return std::move(res); +} + +} // namespace Mayo diff --git a/src/base/span.h b/src/base/span.h new file mode 100644 index 00000000..213a83b6 --- /dev/null +++ b/src/base/span.h @@ -0,0 +1,15 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include + +namespace Mayo { + +template using Span = gsl::span; + +} // namespace Mayo diff --git a/src/base/string_utils.cpp b/src/base/string_utils.cpp new file mode 100644 index 00000000..1939a91c --- /dev/null +++ b/src/base/string_utils.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "string_utils.h" + +#include "unit_system.h" +#include +#include +#include +#include + +namespace Mayo { + +static QChar lastChar(const QString& str) +{ + return str.at(str.size() - 1); +} + +static QString valueText(double value, const StringUtils::TextOptions& opt) +{ + const double c = std::abs(value) < Precision::Confusion() ? 0. : value; + QString str = opt.locale.toString(c, 'f', opt.unitDecimals); + const QChar chDecPnt = opt.locale.decimalPoint(); + const int posPnt = str.indexOf(chDecPnt); + if (posPnt != -1) { // Remove useless trailing zeroes + while (lastChar(str) == opt.locale.zeroDigit()) + str.chop(1); + if (lastChar(str) == chDecPnt) + str.chop(1); + } + return str; +} + +static QString coordsText(const gp_XYZ& coords, const StringUtils::TextOptions& opt) +{ + const QString strX = valueText(coords.X(), opt); + const QString strY = valueText(coords.Y(), opt); + const QString strZ = valueText(coords.Z(), opt); + return StringUtils::tr("(%1 %2 %3)").arg(strX, strY, strZ); +} + +static QString pntCoordText(double coord, const StringUtils::TextOptions& opt) +{ + const UnitSystem::TranslateResult trCoord = + UnitSystem::translate(opt.unitSchema, coord * Quantity_Millimeter); + const QString strValue = valueText(trCoord.value, opt); + return strValue + trCoord.strUnit; +} + +QString StringUtils::text(double value, const TextOptions& opt) +{ + return valueText(value, opt); +} + +QString StringUtils::text(const gp_Pnt& pos, const TextOptions& opt) +{ + const QString strX = pntCoordText(pos.X(), opt); + const QString strY = pntCoordText(pos.Y(), opt); + const QString strZ = pntCoordText(pos.Z(), opt); + return tr("(%1 %2 %3)").arg(strX, strY, strZ); +} + +QString StringUtils::text(const gp_Dir& dir, const StringUtils::TextOptions& opt) +{ + return coordsText(dir.XYZ(), opt); +} + +QString StringUtils::text(const gp_Trsf& trsf, const TextOptions& opt) +{ + gp_XYZ axisRotation; + double angleRotation; + trsf.GetRotation(axisRotation, angleRotation); + const UnitSystem::TranslateResult trAngleRotation = + UnitSystem::degrees(angleRotation * Quantity_Radian); + return tr("[%1; %2%3; %4]").arg( + coordsText(axisRotation, opt), + valueText(trAngleRotation.value, opt), + QString::fromUtf8(trAngleRotation.strUnit), + StringUtils::text(gp_Pnt(trsf.TranslationPart()), opt)); +} + +QString StringUtils::text(const Quantity_Color& color, const QString& format) +{ + const int red = color.Red() * 255; + const int green = color.Green() * 255; + const int blue = color.Blue() * 255; + return format.arg(red).arg(green).arg(blue); +} + +const char* StringUtils::rawText(TopAbs_ShapeEnum shapeType) +{ + // TODO Replace maybe by TopAbs::ShapeTypeToString() + switch (shapeType) { + case TopAbs_COMPOUND: return "TopAbs_COMPOUND"; + case TopAbs_COMPSOLID: return "TopAbs_COMPSOLID"; + case TopAbs_SOLID: return "TopAbs_SOLID"; + case TopAbs_SHELL: return "TopAbs_SHELL"; + case TopAbs_FACE: return "TopAbs_FACE"; + case TopAbs_WIRE: return "TopAbs_WIRE"; + case TopAbs_EDGE: return "TopAbs_EDGE"; + case TopAbs_VERTEX: return "TopAbs_VERTEX"; + case TopAbs_SHAPE: return "TopAbs_SHAPE"; + } + return "??"; +} + +const char* StringUtils::rawText(IFSelect_ReturnStatus status) +{ + switch (status) { + case IFSelect_RetVoid: return "IFSelect_RetVoid"; + case IFSelect_RetDone: return "IFSelect_RetDone"; + case IFSelect_RetError: return "IFSelect_RetError"; + case IFSelect_RetFail: return "IFSelect_RetFail"; + case IFSelect_RetStop: return "IFSelect_RetStop"; + } + return "??"; +} + +void StringUtils::append(QString* dst, const QString& str, const QLocale& locale) +{ + if (locale.textDirection() == Qt::LeftToRight) + dst->append(str); + else + dst->prepend(str); +} + +} // namespace Mayo diff --git a/src/base/string_utils.h b/src/base/string_utils.h new file mode 100644 index 00000000..0a743aab --- /dev/null +++ b/src/base/string_utils.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "unit_system.h" +#include +#include +#include +#include +#include +class Quantity_Color; +class gp_Pnt; +class gp_Dir; +class gp_Trsf; + +namespace Mayo { + +class StringUtils { + Q_DECLARE_TR_FUNCTIONS(Mayo::StringUtils) +public: + struct TextOptions { + QLocale locale; + UnitSystem::Schema unitSchema; + int unitDecimals; + }; + + static QString text(double value, const TextOptions& opt); + static QString text(const gp_Pnt& pos, const TextOptions& opt); + static QString text(const gp_Dir& pos, const TextOptions& opt); + static QString text(const gp_Trsf& trsf, const TextOptions& opt); + static QString text( + const Quantity_Color& color, + const QString& format = "R:%1 G:%2 B:%3"); + static const char* rawText(TopAbs_ShapeEnum shapeType); + static const char* rawText(IFSelect_ReturnStatus status); + + static void append(QString* dst, const QString& str, const QLocale& locale = QLocale()); +}; + +} // namespace Mayo diff --git a/src/base/unit.cpp b/src/base/unit.cpp new file mode 100644 index 00000000..a42f342a --- /dev/null +++ b/src/base/unit.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "unit.h" + +namespace Mayo { + +#if 0 +static const char* BaseUnit_symbol(BaseUnit baseUnit) +{ + switch (baseUnit) { + case BaseUnit::Length: return "m"; + case BaseUnit::Mass: return "kg"; + case BaseUnit::Time: return "s"; + case BaseUnit::ElectricCurrent: return "A"; + case BaseUnit::ThermodynamicTemperature: return "K"; + case BaseUnit::AmountOfSubstance: return "mol"; + case BaseUnit::LuminousIntensity: return "cd"; + case BaseUnit::Angle: return "°"; + } + return ""; +} + +static constexpr size_t Unit_powIndex(BaseUnit baseUnit) { + return static_cast(baseUnit); +} + +Unit operator*(const Unit& unit, BaseUnit baseUnit) +{ + Unit out = unit.m_powBaseUnit; + ++out.m_powBaseUnit.at(Unit_powIndex(baseUnit)); + out.buildSymbol(); + return out; +} + +Unit operator*(const Unit& lhs, const Unit& rhs) +{ + Unit out = lhs.m_powBaseUnit; + for (size_t i = 0; i < lhs.m_powBaseUnit.size(); ++i) + out.m_powBaseUnit.at(i) += rhs.m_powBaseUnit.at(i); + out.buildSymbol(); + return out; +} + +Unit operator/(const Unit& unit, BaseUnit baseUnit) +{ + Unit out = unit.m_powBaseUnit; + --out.m_powBaseUnit.at(Unit_powIndex(baseUnit)); + out.buildSymbol(); + return out; +} + +Unit operator/(const Unit& lhs, const Unit& rhs) +{ + Unit out = lhs.m_powBaseUnit; + for (size_t i = 0; i < lhs.m_powBaseUnit.size(); ++i) + out.m_powBaseUnit.at(i) -= rhs.m_powBaseUnit.at(i); + out.buildSymbol(); + return out; +} + +const Unit Unit::None; + +const Unit Unit::Length = BaseUnit::Length; +const Unit Unit::Mass = BaseUnit::Mass; +const Unit Unit::Angle = BaseUnit::Angle; +const Unit Unit::Time = BaseUnit::Time; +const Unit Unit::Area = Unit::Length * Unit::Length; +const Unit Unit::Volume = Unit::Area * Unit::Length; +const Unit Unit::Velocity = Unit::Length / BaseUnit::Time; +const Unit Unit::Acceleration = Unit::Length / (Unit::Time * Unit::Time); +const Unit Unit::Density = Unit::Mass / Unit::Volume; +const Unit Unit::Pressure = Unit::Mass / (Unit::Length * Unit::Time * Unit::Time); + +const std::string &Unit::symbol() const +{ + return m_symbol; +} + +Unit::Unit(BaseUnit base) +{ + m_powBaseUnit.at(Unit_powIndex(base)) = 1; + this->buildSymbol(); +} + +Unit::Unit(const Unit::ArrayPowBaseUnit &arrayPow) + : m_powBaseUnit(arrayPow) +{ +} + +Unit &Unit::operator=(BaseUnit base) +{ + m_powBaseUnit.at(Unit_powIndex(base)) = 1; + this->buildSymbol(); + return *this; +} + +void Unit::buildSymbol() +{ + m_symbol.clear(); + int numCount = 0; + int divCount = 0; + std::stringstream numStream; + std::stringstream divStream; + for (size_t i = 0; i < m_powBaseUnit.size(); ++i) { + const int8_t powBaseUnit = m_powBaseUnit.at(i); + if (powBaseUnit != 0) { + const int8_t absPowBaseUnit = std::abs(powBaseUnit); + std::stringstream& refStream = powBaseUnit > 0 ? numStream : divStream; + int& refCount = powBaseUnit > 0 ? numCount : divCount; + if (refCount != 0) + refStream << '.'; + refStream << BaseUnit_symbol(static_cast(i)); + if (absPowBaseUnit == 2) + refStream << "\xc2\xb2"; + else if (absPowBaseUnit == 3) + refStream << "\xc2\xb3"; + else if (absPowBaseUnit != 1) + refStream << '^' << powBaseUnit; + ++refCount; + } + } + if (numCount > 0) { + m_symbol = numStream.str(); + if (divCount > 0) + m_symbol += "/" + divStream.str(); + } +} +#endif + +} // namespace Mayo diff --git a/src/base/unit.h b/src/base/unit.h new file mode 100644 index 00000000..dee8ef12 --- /dev/null +++ b/src/base/unit.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +namespace Mayo { + +enum class Unit { + None, + + // Base + Length, // Meter(m) + Mass, // Kilogram(kg) + Time, // Second(s) + ElectricCurrent, // Ampere(A) + ThermodynamicTemperature, // Kelvin(K) + AmountOfSubstance, // Mole(mol) + LuminousIntensity, // Candela(cd) + Angle, // Radian(rad) + + // Derived + Area, // m² + Volume, // m^3 + Velocity, // m/s + Acceleration, // m/s² + Density, // kg/m^3 + Pressure // kg/m.s² (or N/m²) +}; + +#if 0 +enum class BaseUnit { + Length = 0, // Meter(m) + Mass, // Kilogram(kg) + Time, // Second(s) + ElectricCurrent, // Ampere(A) + ThermodynamicTemperature, // Kelvin(K) + AmountOfSubstance, // Mole(mol) + LuminousIntensity, // Candela(cd) + Angle // Degree(°) +}; + +class Unit { +public: + static const Unit None; + + static const Unit Length; + static const Unit Mass; + static const Unit Time; + static const Unit Angle; + + static const Unit Area; + static const Unit Volume; + + static const Unit Velocity; + static const Unit Acceleration; + + static const Unit Density; + static const Unit Pressure; + + const std::string& symbol() const; + +private: + using ArrayPowBaseUnit = std::array; + + Unit() = default; + Unit(BaseUnit base); + Unit(const ArrayPowBaseUnit& arrayPow); + Unit& operator=(BaseUnit base); + Unit& operator=(const Unit& unit) = delete; + + void buildSymbol(); + + friend Unit operator*(const Unit& unit, BaseUnit baseUnit); + friend Unit operator*(const Unit& lhs, const Unit& rhs); + friend Unit operator/(const Unit& unit, BaseUnit baseUnit); + friend Unit operator/(const Unit& lhs, const Unit& rhs); + + ArrayPowBaseUnit m_powBaseUnit = {}; + std::string m_symbol; +}; +#endif + +} // namespace Mayo diff --git a/src/base/unit_system.cpp b/src/base/unit_system.cpp new file mode 100644 index 00000000..ae4da9a5 --- /dev/null +++ b/src/base/unit_system.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "unit_system.h" + +#include +#include +#include +#include + +#define MAYO_CUBIC_SYMBOL "\xc2\xb3" + +namespace Mayo { + +namespace Internal { + +static const char* symbol(Unit unit) +{ + switch (unit) { + case Unit::None: return ""; + // Base + case Unit::Length: return "m"; + case Unit::Mass: return "kg"; + case Unit::Time: return "s"; + case Unit::ElectricCurrent: return "A"; + case Unit::ThermodynamicTemperature: return "K"; + case Unit::AmountOfSubstance: return "mol"; + case Unit::LuminousIntensity: return "cd"; + case Unit::Angle: return "rad"; + // Derived + case Unit::Area: return "m²"; + case Unit::Volume: return "m" MAYO_CUBIC_SYMBOL; + case Unit::Velocity: return "m/s"; + case Unit::Acceleration: return "m/s²"; + case Unit::Density: return "kg/m" MAYO_CUBIC_SYMBOL; + case Unit::Pressure: return "kg/m.s²"; + } + + return "?"; +} + +struct Threshold_UnitInfo { + double threshold; + const char* str; + double factor; +}; + +template UnitSystem::TranslateResult translate( + double value, const Threshold_UnitInfo (&array)[N]) +{ + for (const Threshold_UnitInfo& t : array) { + if (value < t.threshold) + return { value / t.factor, t.str, t.factor }; + } + + return { value, nullptr, 1. }; +} + +static UnitSystem::TranslateResult translateSI(double value, Unit unit) +{ + if (unit == Unit::Length) + return { value, "mm", 1. }; + else if (unit == Unit::Area) + return { value, "mm²", 1. }; + else if (unit == Unit::Volume) + return { value, "mm" MAYO_CUBIC_SYMBOL, 1. }; + else if (unit == Unit::Velocity) + return { value, "mm/s", 1. }; + else if (unit == Unit::Density) + return { value, "kg/mm" MAYO_CUBIC_SYMBOL, 1. }; + else if (unit == Unit::Pressure) + return { value, "kPa", 1. }; + + return { value, symbol(unit), 1. }; +} + +static UnitSystem::TranslateResult translateImperialUK(double value, Unit unit) +{ + if (unit == Unit::Length) + return { value / 25.4, "in", 25.4 }; + else if (unit == Unit::Area) + return { value / 645.16, "in²", 654.16 }; + else if (unit == Unit::Volume) + return { value / 16387.064, "in" MAYO_CUBIC_SYMBOL, 16387.064 }; + else if (unit == Unit::Velocity) + return { value / (25.4 / 60.), "in/min", 25.4 / 60. }; + + return { value, symbol(unit), 1. }; +} + +static UnitSystem::TranslateResult translateSI_ranged(double value, Unit unit) +{ + if (unit == Unit::Length) { + static const Internal::Threshold_UnitInfo array[] = { + { 1e-9, "m", 1000. }, // < 0.001nm + { 0.001, "nm", 1e-6 }, // < 1µm + { 0.1, "µm", 0.001 }, // < 0.1mm + { 100., "mm", 1. }, // < 10cm + { 1e7, "m", 1000. }, // < 10km + { 1e11, "km", 1e6 }, // < 100000km + { DBL_MAX, "m", 1000. } + }; + return Internal::translate(value, array); + } + else if (unit == Unit::Area) { + static const Internal::Threshold_UnitInfo array[] = { + { 100., "mm²", 1. }, // < 1cm² + { 1e12, "m²", 1e6 }, // < 1km² + { DBL_MAX, "km²", 1e12 } // > 1km² + }; + return Internal::translate(value, array); + } + else if (unit == Unit::Volume) { + static const Internal::Threshold_UnitInfo array[] = { + { 1e4, "mm^3", 1. }, // < 10cm^3 + { 1e18, "m^3", 1e9 }, // < 1km^3 + { DBL_MAX, "km^3", 1e18 } // > 1km^3 + }; + return Internal::translate(value, array); + } + else if (unit == Unit::Density) { + static const Internal::Threshold_UnitInfo array[] = { + { 1e-4, "kg/m^3", 1e-9 }, + { 1., "kg/cm^3", 0.001 }, + { DBL_MAX, "kg/mm^3", 1. } + }; + return Internal::translate(value, array); + } + else if (unit == Unit::Pressure) { + static const Internal::Threshold_UnitInfo array[] = { + { 10, "Pa", 0.001 }, + { 10000, "kPa", 1. }, + { 1e7, "MPa", 1000. }, + { 1e10, "GPa", 1e6 }, + { DBL_MAX, "Pa", 0.001 } // > 1000Gpa + }; + return Internal::translate(value, array); + } + else { + // TODO + } + + return { value, symbol(unit), 1. }; +} + +static UnitSystem::TranslateResult translateImperialUK_ranged(double value, Unit unit) +{ + if (unit == Unit::Length) { + static const Internal::Threshold_UnitInfo array[] = { + { 0.00000254, "in", 25.4 }, // < 0.001 thou + { 2.54, "thou", 0.0254 }, // < 0.1 in + { 304.8, "\"", 25.4 }, + { 914.4, "'", 304.8 }, + { 1609344., "yd", 914.4 }, + { 1609344000, "mi", 1609344 }, + { DBL_MAX, "in", 25.4 } // > 1000 mi + }; + + return Internal::translate(value, array); + } + + return translateImperialUK(value, unit); +} + +static std::string toLocaleString( + const QLocale& locale, double value, const char* strUnit) +{ + return QCoreApplication::translate("Mayo::UnitSystem", "%1%2") + .arg(locale.toString(value), QString::fromUtf8(strUnit)) + .toStdString(); +} + +} // namespace Internal + +std::string UnitSystem::toSystemLocaleString(double value, const char* strUnit) +{ + return Internal::toLocaleString(QLocale::system(), value, strUnit); +} + +std::string UnitSystem::toCLocaleString(double value, const char* strUnit) +{ + return Internal::toLocaleString(QLocale::c(), value, strUnit); +} + +UnitSystem::TranslateResult UnitSystem::translate( + Schema schema, double value, Unit unit) +{ + switch (schema) { + case Schema::SI: + return Internal::translateSI(value, unit); + case Schema::ImperialUK: + return Internal::translateImperialUK(value, unit); + } + + Q_UNREACHABLE(); + return {}; +} + +UnitSystem::TranslateResult UnitSystem::radians(QuantityAngle angle) +{ + return { angle.value(), "rad", 1. }; +} + +UnitSystem::TranslateResult UnitSystem::degrees(QuantityAngle angle) +{ + constexpr double factor = Quantity_Degree.value(); + const double rad = angle.value(); + return { rad / factor, "°", factor }; +} + +UnitSystem::TranslateResult UnitSystem::millimeters(QuantityLength length) +{ + return { length.value(), "mm", 1. }; +} + +UnitSystem::TranslateResult UnitSystem::cubicMillimeters(QuantityVolume volume) +{ + return { volume.value(), "mm" MAYO_CUBIC_SYMBOL, 1. }; +} + +UnitSystem::TranslateResult UnitSystem::millimetersPerSecond(QuantityVelocity speed) +{ + return { speed.value(), "mm/s", 1. }; +} + +UnitSystem::TranslateResult UnitSystem::seconds(QuantityTime duration) +{ + return { duration.value(), "s", 1. }; +} + +} // namespace Mayo diff --git a/src/base/unit_system.h b/src/base/unit_system.h new file mode 100644 index 00000000..b9faaf91 --- /dev/null +++ b/src/base/unit_system.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "quantity.h" +#include + +namespace Mayo { + +class UnitSystem { +public: + enum Schema { + SI, + ImperialUK + }; + + struct TranslateResult { + double value; + const char* strUnit; // UTF8 + double factor; + constexpr operator double() const { return this->value; } + }; + + template + static TranslateResult translate(Schema schema, Quantity qty) { + return UnitSystem::translate(schema, qty.value(), UNIT); + } + static TranslateResult translate(Schema schema, double value, Unit unit); + + static TranslateResult radians(QuantityAngle angle); + static TranslateResult degrees(QuantityAngle angle); + static TranslateResult millimeters(QuantityLength length); + static TranslateResult cubicMillimeters(QuantityVolume volume); + static TranslateResult millimetersPerSecond(QuantityVelocity speed); + static TranslateResult seconds(QuantityTime duration); + + static std::string toSystemLocaleString(double value, const char* strUnit); + static std::string toCLocaleString(double value, const char* strUnit); + +private: + UnitSystem() = default; +}; + +} // namespace Mayo diff --git a/src/base/xde_document_item.cpp b/src/base/xde_document_item.cpp new file mode 100644 index 00000000..7e42d819 --- /dev/null +++ b/src/base/xde_document_item.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "xde_document_item.h" +#include "xde_shape_property_owner.h" +#include "caf_utils.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +XdeDocumentItem::XdeDocumentItem(const Handle_TDocStd_Document &doc) + : m_cafDoc(doc), + m_shapeTool(XCAFDoc_DocumentTool::ShapeTool(doc->Main())), + m_colorTool(XCAFDoc_DocumentTool::ColorTool(doc->Main())) +{ + this->rebuildAssemblyTree(); +} + +const Handle_TDocStd_Document& XdeDocumentItem::cafDoc() const +{ + return m_cafDoc; +} + +const Handle_XCAFDoc_ShapeTool& XdeDocumentItem::shapeTool() const +{ + return m_shapeTool; +} + +const Handle_XCAFDoc_ColorTool& XdeDocumentItem::colorTool() const +{ + return m_colorTool; +} + +void XdeDocumentItem::rebuildAssemblyTree() +{ + m_asmTree.clear(); + for (const TDF_Label& rootLabel : this->topLevelFreeShapes()) + this->deepBuildAssemblyTree(0, rootLabel); +} + +const Tree& XdeDocumentItem::assemblyTree() const +{ + return m_asmTree; +} + +TDF_LabelSequence XdeDocumentItem::topLevelFreeShapes() const +{ + TDF_LabelSequence seq; + m_shapeTool->GetFreeShapes(seq); + return seq; +} + +TDF_LabelSequence XdeDocumentItem::shapeComponents(const TDF_Label& lbl) +{ + TDF_LabelSequence seq; + XCAFDoc_ShapeTool::GetComponents(lbl, seq); + return seq; +} + +TDF_LabelSequence XdeDocumentItem::shapeSubs(const TDF_Label& lbl) +{ + TDF_LabelSequence seq; + XCAFDoc_ShapeTool::GetSubShapes(lbl, seq); + return seq; +} + +bool XdeDocumentItem::isShape(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsShape(lbl); +} + +bool XdeDocumentItem::isShapeFree(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsFree(lbl); +} + +TopoDS_Shape XdeDocumentItem::shape(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::GetShape(lbl); +} + +QString XdeDocumentItem::findLabelName(const TDF_Label& lbl) +{ + QString name = CafUtils::labelAttrStdName(lbl); + if (name.isEmpty()) { + if (XdeDocumentItem::isShape(lbl)) { + const TopoDS_Shape shape = XdeDocumentItem::shape(lbl); + switch (shape.ShapeType()) { + case TopAbs_COMPOUND: name = "Compound"; break; + case TopAbs_COMPSOLID: name = "CompSolid"; break; + case TopAbs_SOLID: name = "Solid"; break; + case TopAbs_SHELL: name = "Shell"; break; + case TopAbs_FACE: name = "Face"; break; + case TopAbs_WIRE: name = "Wire"; break; + case TopAbs_EDGE: name = "Edge"; break; + case TopAbs_VERTEX: name = "Vertex"; break; + case TopAbs_SHAPE: name = "Shape"; break; + } + name = QString("%1 %2").arg(name).arg(lbl.Tag()); + } + else { + name = QString("[[%1]]").arg(CafUtils::labelTag(lbl)); + } + } + + return name; +} + +QString XdeDocumentItem::findLabelName(TreeNodeId nodeId) const +{ + return XdeDocumentItem::findLabelName(m_asmTree.nodeData(nodeId)); +} + +void XdeDocumentItem::setLabelName(const TDF_Label& lbl, const QString& name) +{ + TDataStd_Name::Set(lbl, occ::QtUtils::toOccExtendedString(name)); +} + +void XdeDocumentItem::setLabelName(TreeNodeId nodeId, const QString& name) +{ + XdeDocumentItem::setLabelName(m_asmTree.nodeData(nodeId), name); +} + +bool XdeDocumentItem::isShapeAssembly(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsAssembly(lbl); +} + +bool XdeDocumentItem::isShapeReference(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsReference(lbl); +} + +bool XdeDocumentItem::isShapeSimple(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsSimpleShape(lbl); +} + +bool XdeDocumentItem::isShapeComponent(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsComponent(lbl); +} + +bool XdeDocumentItem::isShapeCompound(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsCompound(lbl); +} + +bool XdeDocumentItem::isShapeSub(const TDF_Label& lbl) +{ + return XCAFDoc_ShapeTool::IsSubShape(lbl); +} + +bool XdeDocumentItem::hasShapeColor(const TDF_Label &lbl) const +{ + return m_colorTool->IsSet(lbl, XCAFDoc_ColorGen) + || m_colorTool->IsSet(lbl, XCAFDoc_ColorSurf) + || m_colorTool->IsSet(lbl, XCAFDoc_ColorCurv); +} + +Quantity_Color XdeDocumentItem::shapeColor(const TDF_Label &lbl) const +{ + Quantity_Color color; + if (m_colorTool->GetColor(lbl, XCAFDoc_ColorGen, color)) + return color; + + if (m_colorTool->GetColor(lbl, XCAFDoc_ColorSurf, color)) + return color; + + if (m_colorTool->GetColor(lbl, XCAFDoc_ColorCurv, color)) + return color; + + return color; +} + +TopLoc_Location XdeDocumentItem::shapeReferenceLocation(const TDF_Label &lbl) +{ + return XCAFDoc_ShapeTool::GetLocation(lbl); +} + +TDF_Label XdeDocumentItem::shapeReferred(const TDF_Label &lbl) +{ + TDF_Label referred; + XCAFDoc_ShapeTool::GetReferredShape(lbl, referred); + return referred; +} + +TopLoc_Location XdeDocumentItem::shapeAbsoluteLocation(TreeNodeId nodeId) const +{ + TopLoc_Location absoluteLoc; + TreeNodeId it = nodeId; + while (it != 0) { + const TDF_Label& nodeLabel = m_asmTree.nodeData(it); + const TopLoc_Location nodeLoc = XdeDocumentItem::shapeReferenceLocation(nodeLabel); + absoluteLoc = nodeLoc * absoluteLoc; + it = m_asmTree.nodeParent(it); + } + + return absoluteLoc; +} + +XdeDocumentItem::ValidationProperties XdeDocumentItem::validationProperties( + const TDF_Label& lbl) +{ + ValidationProperties props = {}; + for (TDF_AttributeIterator it(lbl); it.More(); it.Next()) { + const Handle_TDF_Attribute ptrAttr = it.Value(); + const Standard_GUID& attrId = ptrAttr->ID(); + if (&attrId == &XCAFDoc_Centroid::GetID()) { + const auto& centroid = static_cast(*ptrAttr); + props.hasCentroid = true; + props.centroid = centroid.Get(); + } + else if (&attrId == &XCAFDoc_Area::GetID()) { + const auto& area = static_cast(*ptrAttr); + props.hasArea = true; + props.area = area.Get() * Quantity_SquaredMillimeter; + } + else if (&attrId == &XCAFDoc_Volume::GetID()) { + const auto& volume = static_cast(*ptrAttr); + props.hasVolume = true; + props.volume = volume.Get() * Quantity_CubicMillimeter; + } + + if (props.hasCentroid && props.hasArea && props.hasVolume) + break; + } + + return props; +} + +const char XdeDocumentItem::TypeName[] = "2a3efb26-cd32-432d-b95c-cdc64c3cf7d9"; +const char *XdeDocumentItem::dynTypeName() const +{ + return XdeDocumentItem::TypeName; +} + +TDF_Label XdeDocumentItem::label(const DocumentItemNode& docItemNode) +{ + if (!docItemNode.isValid()) + return TDF_Label(); + + if (!sameType(docItemNode.documentItem)) + return TDF_Label(); + + auto xdeDocItem = static_cast(docItemNode.documentItem); + return xdeDocItem->label(docItemNode.id); +} + +TDF_Label XdeDocumentItem::label(TreeNodeId nodeId) const +{ + return this->assemblyTree().nodeData(nodeId); +} + +void XdeDocumentItem::deepBuildAssemblyTree( + TreeNodeId parentNode, const TDF_Label &label) +{ + const TreeNodeId node = m_asmTree.appendChild(parentNode, label); + if (XdeDocumentItem::isShapeAssembly(label)) { + for (const TDF_Label& child : XdeDocumentItem::shapeComponents(label)) + this->deepBuildAssemblyTree(node, child); + } + else if (XdeDocumentItem::isShapeSimple(label)) { + for (const TDF_Label& child : XdeDocumentItem::shapeSubs(label)) + this->deepBuildAssemblyTree(node, child); + } + else if (XdeDocumentItem::isShapeReference(label)) { + const TDF_Label referred = XdeDocumentItem::shapeReferred(label); + this->deepBuildAssemblyTree(node, referred); + } +} + +std::unique_ptr XdeDocumentItem::shapeProperties(const TDF_Label& label) const +{ + auto owner = new XdeShapePropertyOwner(this, label); + std::unique_ptr ptr(owner); + return ptr; +} + +std::unique_ptr XdeDocumentItem::propertiesAtNode(TreeNodeId nodeId) const +{ + std::unique_ptr ptr( + new XdeShapePropertyOwner(this, this->label(nodeId))); + return ptr; +} + +} // namespace Mayo diff --git a/src/base/xde_document_item.h b/src/base/xde_document_item.h new file mode 100644 index 00000000..a2e52e76 --- /dev/null +++ b/src/base/xde_document_item.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "document_item.h" +#include "libtree.h" +#include "quantity.h" +#include +#include +#include +#include +#include + +#include +#include + +namespace Mayo { + +class XdeShapePropertyOwner; + +class XdeDocumentItem : public PartItem { + Q_DECLARE_TR_FUNCTIONS(XdeDocumentItem) +public: + struct ValidationProperties { + bool hasCentroid; + bool hasArea; + bool hasVolume; + gp_Pnt centroid; + QuantityArea area; + QuantityVolume volume; + }; + + XdeDocumentItem(const Handle_TDocStd_Document& doc); + + const Handle_TDocStd_Document& cafDoc() const; + const Handle_XCAFDoc_ShapeTool& shapeTool() const; + const Handle_XCAFDoc_ColorTool& colorTool() const; + + void rebuildAssemblyTree(); + const Tree& assemblyTree() const; + + TDF_LabelSequence topLevelFreeShapes() const; + static TDF_LabelSequence shapeComponents(const TDF_Label& lbl); + static TDF_LabelSequence shapeSubs(const TDF_Label& lbl); + + static QString findLabelName(const TDF_Label& lbl); + QString findLabelName(TreeNodeId nodeId) const; + static void setLabelName(const TDF_Label& lbl, const QString& name); + void setLabelName(TreeNodeId nodeId, const QString& name); + + static TopoDS_Shape shape(const TDF_Label& lbl); + static bool isShape(const TDF_Label& lbl); + static bool isShapeFree(const TDF_Label& lbl); + static bool isShapeAssembly(const TDF_Label& lbl); + static bool isShapeReference(const TDF_Label& lbl); + static bool isShapeSimple(const TDF_Label& lbl); + static bool isShapeComponent(const TDF_Label& lbl); + static bool isShapeCompound(const TDF_Label& lbl); + static bool isShapeSub(const TDF_Label& lbl); + + bool hasShapeColor(const TDF_Label& lbl) const; + Quantity_Color shapeColor(const TDF_Label& lbl) const; + + TopLoc_Location shapeAbsoluteLocation(TreeNodeId nodeId) const; + static TopLoc_Location shapeReferenceLocation(const TDF_Label& lbl); + static TDF_Label shapeReferred(const TDF_Label& lbl); + + static ValidationProperties validationProperties(const TDF_Label& lbl); + + std::unique_ptr shapeProperties(const TDF_Label& label) const; + std::unique_ptr propertiesAtNode(TreeNodeId nodeId) const override; + + static const char TypeName[]; + const char* dynTypeName() const override; + + static TDF_Label label(const DocumentItemNode& docItemNode); + TDF_Label label(TreeNodeId nodeId) const; + +private: + void deepBuildAssemblyTree(TreeNodeId parentNode, const TDF_Label& label); + + Handle_TDocStd_Document m_cafDoc; + Handle_XCAFDoc_ShapeTool m_shapeTool; + Handle_XCAFDoc_ColorTool m_colorTool; + Tree m_asmTree; +}; + +} // namespace Mayo diff --git a/src/base/xde_shape_property_owner.cpp b/src/base/xde_shape_property_owner.cpp new file mode 100644 index 00000000..738182ec --- /dev/null +++ b/src/base/xde_shape_property_owner.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "xde_shape_property_owner.h" +#include "string_utils.h" + +namespace Mayo { + +XdeShapePropertyOwner::XdeShapePropertyOwner( + const XdeDocumentItem* docItem, const TDF_Label& label) + : m_propertyName(this, tr("Name")), + m_propertyShapeType(this, tr("Shape")), + m_propertyXdeShapeKind(this, tr("XDE shape")), + m_propertyColor(this, tr("Color")), + m_propertyReferenceLocation(this, tr("Location")), + m_propertyValidationCentroid(this, tr("Centroid")), + m_propertyValidationArea(this, tr("Area")), + m_propertyValidationVolume(this, tr("Volume")), + m_propertyReferredName(this, tr("[Referred]Name")), + m_propertyReferredColor(this, tr("[Referred]Color")), + m_propertyReferredValidationCentroid(this, tr("[Referred]Centroid")), + m_propertyReferredValidationArea(this, tr("[Referred]Area")), + m_propertyReferredValidationVolume(this, tr("[Referred]Volume")), + m_docItem(docItem), + m_label(label) +{ + // Name + m_propertyName.setValue(XdeDocumentItem::findLabelName(label)); + + // Shape type + const TopAbs_ShapeEnum shapeType = XCAFDoc_ShapeTool::GetShape(label).ShapeType(); + m_propertyShapeType.setValue( + QString(StringUtils::rawText(shapeType)).remove("TopAbs_")); + + // XDE shape kind + QStringList listXdeShapeKind; + if (XdeDocumentItem::isShapeAssembly(label)) + listXdeShapeKind.push_back(tr("Assembly")); + + if (XdeDocumentItem::isShapeReference(label)) + listXdeShapeKind.push_back(tr("Reference")); + + if (XdeDocumentItem::isShapeComponent(label)) + listXdeShapeKind.push_back(tr("Component")); + + if (XdeDocumentItem::isShapeCompound(label)) + listXdeShapeKind.push_back(tr("Compound")); + + if (XdeDocumentItem::isShapeSimple(label)) + listXdeShapeKind.push_back(tr("Simple")); + + if (XdeDocumentItem::isShapeSub(label)) + listXdeShapeKind.push_back(tr("Sub")); + + m_propertyXdeShapeKind.setValue(listXdeShapeKind.join('+')); + + // Reference location + if (XdeDocumentItem::isShapeReference(label)) { + const TopLoc_Location loc = XdeDocumentItem::shapeReferenceLocation(label); + m_propertyReferenceLocation.setValue(loc.Transformation()); + } + else { + this->removeProperty(&m_propertyReferenceLocation); + } + + // Color + if (docItem->hasShapeColor(label)) + m_propertyColor.setValue(docItem->shapeColor(label)); + else + this->removeProperty(&m_propertyColor); + + // Validation properties + { + const XdeDocumentItem::ValidationProperties validProps = + XdeDocumentItem::validationProperties(label); + m_propertyValidationCentroid.setValue(validProps.centroid); + if (!validProps.hasCentroid) + this->removeProperty(&m_propertyValidationCentroid); + m_propertyValidationArea.setQuantity(validProps.area); + if (!validProps.hasArea) + this->removeProperty(&m_propertyValidationArea); + m_propertyValidationVolume.setQuantity(validProps.volume); + if (!validProps.hasVolume) + this->removeProperty(&m_propertyValidationVolume); + } + + // Referred entity's properties + if (XdeDocumentItem::isShapeReference(label)) { + m_labelReferred = XdeDocumentItem::shapeReferred(label); + m_propertyReferredName.setValue(XdeDocumentItem::findLabelName(m_labelReferred)); + const XdeDocumentItem::ValidationProperties validProps = + XdeDocumentItem::validationProperties(m_labelReferred); + m_propertyReferredValidationCentroid.setValue(validProps.centroid); + if (!validProps.hasCentroid) + this->removeProperty(&m_propertyReferredValidationCentroid); + + m_propertyReferredValidationArea.setQuantity(validProps.area); + if (!validProps.hasArea) + this->removeProperty(&m_propertyReferredValidationArea); + + m_propertyReferredValidationVolume.setQuantity(validProps.volume); + if (!validProps.hasVolume) + this->removeProperty(&m_propertyReferredValidationVolume); + + if (docItem->hasShapeColor(m_labelReferred)) + m_propertyReferredColor.setValue(docItem->shapeColor(m_labelReferred)); + else + this->removeProperty(&m_propertyReferredColor); + } + else { + this->removeProperty(&m_propertyReferredName); + this->removeProperty(&m_propertyReferredValidationCentroid); + this->removeProperty(&m_propertyReferredValidationArea); + this->removeProperty(&m_propertyReferredValidationVolume); + this->removeProperty(&m_propertyReferredColor); + } + + for (Property* prop : this->properties()) + prop->setUserReadOnly(true); + + m_propertyName.setUserReadOnly(false); + m_propertyReferredName.setUserReadOnly(false); +} + +const XdeDocumentItem* XdeShapePropertyOwner::xdeDocumentItem() const +{ + return m_docItem; +} + +const TDF_Label& XdeShapePropertyOwner::label() const +{ + return m_label; +} + +const TDF_Label& XdeShapePropertyOwner::referredLabel() const +{ + return m_labelReferred; +} + +void XdeShapePropertyOwner::onPropertyChanged(Property* prop) +{ + if (prop == &m_propertyName) { + XdeDocumentItem::setLabelName(m_label, m_propertyName.value()); + emit nameChanged(); + } + else if (prop == &m_propertyReferredName) { + XdeDocumentItem::setLabelName(m_labelReferred, m_propertyReferredName.value()); + emit referredNameChanged(); + } + + PropertyOwnerSignals::onPropertyChanged(prop); +} + +} // namespace Mayo diff --git a/src/base/xde_shape_property_owner.h b/src/base/xde_shape_property_owner.h new file mode 100644 index 00000000..b4d17bcd --- /dev/null +++ b/src/base/xde_shape_property_owner.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "property.h" +#include "property_builtins.h" +#include "xde_document_item.h" + +namespace Mayo { + +class XdeShapePropertyOwner : public PropertyOwnerSignals { + Q_OBJECT +public: + const XdeDocumentItem* xdeDocumentItem() const; + const TDF_Label& label() const; + const TDF_Label& referredLabel() const; + +signals: + void nameChanged(); + void referredNameChanged(); + +protected: + void onPropertyChanged(Property* prop) override; + +private: + XdeShapePropertyOwner(const XdeDocumentItem* docItem, const TDF_Label& label); + + friend class XdeDocumentItem; + + PropertyQString m_propertyName; + PropertyQString m_propertyShapeType; + PropertyQString m_propertyXdeShapeKind; + PropertyOccColor m_propertyColor; + PropertyOccTrsf m_propertyReferenceLocation; + PropertyOccPnt m_propertyValidationCentroid; + PropertyArea m_propertyValidationArea; + PropertyVolume m_propertyValidationVolume; + + PropertyQString m_propertyReferredName; + PropertyOccColor m_propertyReferredColor; + PropertyOccPnt m_propertyReferredValidationCentroid; + PropertyArea m_propertyReferredValidationArea; + PropertyVolume m_propertyReferredValidationVolume; + + const XdeDocumentItem* m_docItem = nullptr; + TDF_Label m_label; + TDF_Label m_labelReferred; +}; + +} // namespace Mayo diff --git a/src/brep_shape_item.cpp b/src/brep_shape_item.cpp deleted file mode 100644 index 8620d16d..00000000 --- a/src/brep_shape_item.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "brep_shape_item.h" - -namespace Mayo { - -const TopoDS_Shape &BRepShapeItem::brepShape() const -{ - return m_brepShape; -} - -void BRepShapeItem::setBRepShape(const TopoDS_Shape &shape) -{ - m_brepShape = shape; -} - -bool BRepShapeItem::isNull() const -{ - return m_brepShape.IsNull(); -} - -const char* BRepShapeItem::type = "8095882e-8b1f-4b19-a0dd-f74f27748169"; -const char* BRepShapeItem::dynType() const { return BRepShapeItem::type; } - -} // namespace Mayo diff --git a/src/brep_shape_item.h b/src/brep_shape_item.h deleted file mode 100644 index 073b2a19..00000000 --- a/src/brep_shape_item.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "document_item.h" -#include - -namespace Mayo { - -class BRepShapeItem : public PartItem -{ -public: - const TopoDS_Shape& brepShape() const; - void setBRepShape(const TopoDS_Shape& shape); - - bool isNull() const override; - - static const char* type; - const char* dynType() const override; - -private: - TopoDS_Shape m_brepShape; -}; - -} // namespace Mayo diff --git a/src/dialog_about.cpp b/src/dialog_about.cpp deleted file mode 100644 index bfa1f3d1..00000000 --- a/src/dialog_about.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "dialog_about.h" - -#include "ui_dialog_about.h" -#include -#include - -namespace Mayo { - -DialogAbout::DialogAbout(QWidget *parent) - : QDialog(parent), - m_ui(new Ui_DialogAbout) -{ - m_ui->setupUi(this); - - m_ui->label_Version->setText( - m_ui->label_Version->text().arg("0.1-dev").arg(QT_POINTER_SIZE * 8)); - m_ui->label_BuildDateTime->setText( - m_ui->label_BuildDateTime->text().arg(__DATE__).arg(__TIME__)); - m_ui->label_Qt->setText(m_ui->label_Qt->text().arg(QT_VERSION_STR)); - m_ui->label_Occ->setText(m_ui->label_Occ->text().arg(OCC_VERSION_COMPLETE)); - m_ui->label_Gmio->setText(m_ui->label_Gmio->text().arg(GMIO_VERSION_STR)); -} - -DialogAbout::~DialogAbout() -{ - delete m_ui; -} - -} // namespace Mayo diff --git a/src/dialog_about.h b/src/dialog_about.h deleted file mode 100644 index 093010d2..00000000 --- a/src/dialog_about.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include - -namespace Mayo { - -class DialogAbout : public QDialog -{ - Q_OBJECT - -public: - DialogAbout(QWidget *parent = nullptr); - ~DialogAbout(); - -private: - class Ui_DialogAbout* m_ui = nullptr; -}; - -} // namespace Mayo diff --git a/src/dialog_export_options.h b/src/dialog_export_options.h deleted file mode 100644 index ad0149c0..00000000 --- a/src/dialog_export_options.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "application.h" - -#include - -namespace Mayo { - -class DialogExportOptions : public QDialog -{ - Q_OBJECT - -public: - DialogExportOptions(QWidget *parent = nullptr); - ~DialogExportOptions(); - - Application::PartFormat partFormat() const; - void setPartFormat(Application::PartFormat format); - - Application::ExportOptions currentExportOptions() const; - - void accept() override; - -private: - Application::PartFormat m_partFormat = Application::PartFormat::Unknown; - class Ui_DialogExportOptions* m_ui = nullptr; -}; - -} // namespace Mayo diff --git a/src/dialog_options.cpp b/src/dialog_options.cpp deleted file mode 100644 index 167b4a31..00000000 --- a/src/dialog_options.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "dialog_options.h" - -#include "options.h" -#include "property_enumeration.h" -#include "ui_dialog_options.h" -#include "fougtools/qttools/gui/qwidget_utils.h" -#include "fougtools/occtools/qt_utils.h" - -#include -#include - -namespace Mayo { - -namespace Internal { - -static QPixmap colorPixmap(const QColor& color) -{ - QPixmap pix(16, 16); - pix.fill(color); - return pix; -} - -} // namespace Internal - -DialogOptions::DialogOptions(QWidget *parent) - : QDialog(parent), - m_ui(new Ui_DialogOptions) -{ - m_ui->setupUi(this); - - const Options* opts = Options::instance(); - const auto& vecGpxMaterialMapping = - Mayo::enum_Graphic3dNameOfMaterial().mappings(); - - // STL import/export - auto btnGrp_stlIoLib = new QButtonGroup(this); - btnGrp_stlIoLib->addButton(m_ui->radioBtn_UseGmio); - btnGrp_stlIoLib->addButton(m_ui->radioBtn_UseOcc); - QObject::connect( - m_ui->radioBtn_UseGmio, &QAbstractButton::toggled, - m_ui->widget_gmioStlImport, &QWidget::setEnabled); - - const Options::StlIoLibrary lib = opts->stlIoLibrary(); - m_ui->radioBtn_UseGmio->setChecked(lib == Options::StlIoLibrary::Gmio); - m_ui->radioBtn_UseOcc->setChecked(lib == Options::StlIoLibrary::OpenCascade); - - const Options::GmioStlImportType impType = opts->gmioStlImportType(); - m_ui->radioBtn_GmioImportStlMesh->setChecked( - impType == Options::GmioStlImportType::OccStlMesh); - m_ui->radioBtn_GmioImportPolyTriShape->setChecked( - impType == Options::GmioStlImportType::OccPolyTriShape); - - // BRep shape defaults - m_ui->toolBtn_BRepShapeDefaultColor->setIcon( - Internal::colorPixmap(opts->brepShapeDefaultColor())); - m_brepShapeDefaultColor = opts->brepShapeDefaultColor(); - QObject::connect( - m_ui->toolBtn_BRepShapeDefaultColor, &QAbstractButton::clicked, - [=] { - this->chooseColor(opts->brepShapeDefaultColor(), - m_ui->toolBtn_BRepShapeDefaultColor, - &m_brepShapeDefaultColor); - } ); - for (const Enumeration::Mapping& m : vecGpxMaterialMapping) - m_ui->comboBox_BRepShapeDefaultMaterial->addItem(m.string, m.value); - m_ui->comboBox_BRepShapeDefaultMaterial->setCurrentIndex( - m_ui->comboBox_BRepShapeDefaultMaterial->findData( - static_cast(opts->brepShapeDefaultMaterial()))); - - // Mesh defaults - m_ui->toolBtn_MeshDefaultColor->setIcon( - Internal::colorPixmap(opts->meshDefaultColor())); - m_meshDefaultColor = opts->meshDefaultColor(); - QObject::connect( - m_ui->toolBtn_MeshDefaultColor, &QAbstractButton::clicked, - [=] { - this->chooseColor(opts->meshDefaultColor(), - m_ui->toolBtn_MeshDefaultColor, - &m_meshDefaultColor); - } ); - for (const Enumeration::Mapping& m : vecGpxMaterialMapping) - m_ui->comboBox_MeshDefaultMaterial->addItem(m.string, m.value); - m_ui->comboBox_MeshDefaultMaterial->setCurrentIndex( - m_ui->comboBox_MeshDefaultMaterial->findData( - static_cast(opts->meshDefaultMaterial()))); - m_ui->checkBox_MeshShowEdges->setChecked(opts->meshDefaultShowEdges()); - m_ui->checkBox_MeshShowNodes->setChecked(opts->meshDefaultShowNodes()); -} - -DialogOptions::~DialogOptions() -{ - delete m_ui; -} - -void DialogOptions::accept() -{ - Options* opts = Options::instance(); - - // STL import/export - if (m_ui->radioBtn_UseGmio->isChecked()) - opts->setStlIoLibrary(Options::StlIoLibrary::Gmio); - else if (m_ui->radioBtn_UseOcc->isChecked()) - opts->setStlIoLibrary(Options::StlIoLibrary::OpenCascade); - - if (opts->stlIoLibrary() == Options::StlIoLibrary::Gmio) { - if (m_ui->radioBtn_GmioImportStlMesh->isChecked()) - opts->setGmioStlImportType(Options::GmioStlImportType::OccStlMesh); - else if (m_ui->radioBtn_GmioImportPolyTriShape->isChecked()) - opts->setGmioStlImportType(Options::GmioStlImportType::OccPolyTriShape); - } - - // BRep shape defaults - opts->setBrepShapeDefaultColor(m_brepShapeDefaultColor); - opts->setBrepShapeDefaultMaterial( - static_cast( - m_ui->comboBox_BRepShapeDefaultMaterial->currentData().toInt())); - - // Mesh defaults - opts->setMeshDefaultColor(m_meshDefaultColor); - opts->setMeshDefaultMaterial( - static_cast( - m_ui->comboBox_MeshDefaultMaterial->currentData().toInt())); - opts->setMeshDefaultShowEdges(m_ui->checkBox_MeshShowEdges->isChecked()); - opts->setMeshDefaultShowNodes(m_ui->checkBox_MeshShowNodes->isChecked()); - - QDialog::accept(); -} - -void DialogOptions::chooseColor( - const QColor& currentColor, QToolButton* targetBtn, QColor* targetColor) -{ - auto dlg = new QColorDialog(this); - dlg->setCurrentColor(currentColor); - QObject::connect( - dlg, &QDialog::finished, - [=](int result) { - if (result == QDialog::Accepted) { - targetBtn->setIcon(Internal::colorPixmap(dlg->selectedColor())); - *targetColor = dlg->selectedColor(); - } - } ); - qtgui::QWidgetUtils::asyncDialogExec(dlg); -} - -} // namespace Mayo diff --git a/src/dialog_options.h b/src/dialog_options.h deleted file mode 100644 index 88f0769b..00000000 --- a/src/dialog_options.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -class QToolButton; - -namespace Mayo { - -class DialogOptions : public QDialog -{ - Q_OBJECT - -public: - DialogOptions(QWidget *parent = nullptr); - ~DialogOptions(); - - void accept() override; - -private: - void chooseColor( - const QColor& currentColor, - QToolButton* targetBtn, - QColor* targetColor); - - class Ui_DialogOptions* m_ui = nullptr; - QColor m_brepShapeDefaultColor; - QColor m_meshDefaultColor; -}; - -} // namespace Mayo diff --git a/src/dialog_save_image_view.h b/src/dialog_save_image_view.h deleted file mode 100644 index 878bc598..00000000 --- a/src/dialog_save_image_view.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include - -class Image_PixMap; - -namespace Mayo { - -class WidgetOccView; - -class DialogSaveImageView : public QDialog -{ - Q_OBJECT - -public: - DialogSaveImageView(const WidgetOccView* view, QWidget *parent = nullptr); - ~DialogSaveImageView(); - -private: - void saveFile(); - void clipboardCopy(); - void preview(); - - bool createImageView(Image_PixMap* img) const; - - class Ui_DialogSaveImageView* m_ui = nullptr; - const WidgetOccView* m_view = nullptr; -}; - -} // namespace Mayo diff --git a/src/dialog_task_manager.h b/src/dialog_task_manager.h deleted file mode 100644 index 20202362..00000000 --- a/src/dialog_task_manager.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include - -namespace Mayo { - -namespace Internal { class TaskWidget; } - -class DialogTaskManager : public QDialog -{ - Q_OBJECT - -public: - DialogTaskManager(QWidget *parent = nullptr); - ~DialogTaskManager(); - - bool isRunning() const; - void execWithTask(quint64 taskId); - -private: - void onTaskStarted(quint64 taskId, const QString& title); - void onTaskEnded(quint64 taskId); - void onTaskProgress(quint64 taskId, int percent); - void onTaskProgressStep(quint64 taskId, const QString& name); - void interruptTask(); - - Internal::TaskWidget* taskWidget(quint64 taskId); - - class Ui_DialogTaskManager* m_ui = nullptr; - QHash m_taskIdToWidget; - bool m_isRunning = false; - unsigned m_taskCount = 0; -}; - -} // namespace Mayo diff --git a/src/document.cpp b/src/document.cpp deleted file mode 100644 index bb424c5a..00000000 --- a/src/document.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "document.h" - -#include "application.h" -#include "document_item.h" - -namespace Mayo { - -Document::Document(Application *app) - : QObject(app), - m_app(app) -{ -} - -Document::~Document() -{ - for (DocumentItem* item : m_rootItems) - delete item; -} - -const Application *Document::application() const -{ - return m_app; -} - -Application *Document::application() -{ - return m_app; -} - -const QString &Document::label() const -{ - return m_label; -} - -void Document::setLabel(const QString &v) -{ - m_label = v; -} - -bool Document::eraseRootItem(DocumentItem *docItem) -{ - auto itFound = std::find(m_rootItems.cbegin(), m_rootItems.cend(), docItem); - if (itFound != m_rootItems.cend()) { - m_rootItems.erase(itFound); - delete docItem; - emit itemErased(docItem); - return true; - } - return false; -} - -const std::vector &Document::rootItems() const -{ - return m_rootItems; -} - -bool Document::isEmpty() const -{ - return m_rootItems.empty(); -} - -void Document::addItem(DocumentItem* item) -{ - item->setDocument(this); - m_rootItems.push_back(item); - emit itemAdded(item); -} - -} // namespace Mayo diff --git a/src/document.h b/src/document.h deleted file mode 100644 index 7130d182..00000000 --- a/src/document.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include - -namespace Mayo { - -class Application; -class DocumentItem; -class PartItem; -class Property; - -class Document : public QObject -{ - Q_OBJECT - -public: - const Application* application() const; - Application* application(); - - const QString& label() const; - void setLabel(const QString& v); - - bool eraseRootItem(DocumentItem* docItem); - - const std::vector& rootItems() const; - bool isEmpty() const; - -signals: - void itemAdded(DocumentItem* docItem); - void itemErased(const DocumentItem* docItem); - void itemPropertyChanged(const DocumentItem* docItem, const Property* prop); - -private: - friend class Application; - friend class DocumentItem; - Document(Application* app); - ~Document(); - - void addItem(DocumentItem* item); - - Application* m_app = nullptr; - std::vector m_rootItems; - QString m_label; -}; - -} // namespace Mayo diff --git a/src/document_item.cpp b/src/document_item.cpp deleted file mode 100644 index 5cee6a3f..00000000 --- a/src/document_item.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "document_item.h" - -#include "document.h" -#include - -namespace Mayo { - -DocumentItem::DocumentItem() - : propertyLabel( - this, QCoreApplication::translate("Mayo::DocumentItem", "label")) -{ -} - -Document *DocumentItem::document() -{ - return m_document; -} - -const Document *DocumentItem::document() const -{ - return m_document; -} - -void DocumentItem::setDocument(Document *doc) -{ - m_document = doc; -} - -const std::vector& DocumentItem::outItems() const -{ - return m_outItems; -} - -void DocumentItem::onPropertyChanged(Property *prop) -{ - if (m_document != nullptr) - emit m_document->itemPropertyChanged(this, prop); -} - -const QString& PartItem::filePath() const -{ - return m_filePath; -} - -void PartItem::setFilePath(const QString &v) -{ - m_filePath = v; -} - -bool PartItem::isNull() const -{ - return false; -} - -const char* PartItem::type = "247d246a-6316-4a99-b68e-bdcf565fa8aa"; -const char* PartItem::dynType() const { return PartItem::type; } - -bool sameType(const DocumentItem *lhs, const DocumentItem *rhs) -{ - if (lhs != nullptr && rhs != nullptr) - return std::strcmp(lhs->dynType(), rhs->dynType()) == 0; - return false; -} - -} // namespace Mayo diff --git a/src/document_item.h b/src/document_item.h deleted file mode 100644 index 81c070a5..00000000 --- a/src/document_item.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "property_builtins.h" -#include -#include - -namespace Mayo { - -class Document; - -class DocumentItem : public PropertyOwner -{ -public: - DocumentItem(); - - Document* document(); - const Document* document() const; - void setDocument(Document* doc); - - PropertyQString propertyLabel; - - const std::vector& outItems() const; // For future use - - virtual const char* dynType() const = 0; - -protected: - void onPropertyChanged(Property* prop) override; - -private: - Document* m_document = nullptr; - std::vector m_outItems; -}; - -class PartItem : public DocumentItem -{ -public: - const QString& filePath() const; - void setFilePath(const QString& v); - - virtual bool isNull() const; - - static const char* type; - const char* dynType() const override; - -private: - QString m_filePath; -}; - -bool sameType(const DocumentItem* lhs, const DocumentItem* rhs); - -template -bool sameType(const DocumentItem* item) -{ - return item != nullptr ? - std::strcmp(item->dynType(), T::type) == 0 : - false; -} - -} // namespace Mayo diff --git a/src/gpx/ais_text.cpp b/src/gpx/ais_text.cpp new file mode 100644 index 00000000..37145f48 --- /dev/null +++ b/src/gpx/ais_text.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "ais_text.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Mayo { + +AIS_Text::AIS_Text(const TCollection_ExtendedString &text, const gp_Pnt& pos) +{ + TextProperties defaultProps; + m_textProps.push_back(defaultProps); + this->setText(text); + this->setPosition(pos); +} + +Handle_Prs3d_TextAspect AIS_Text::presentationTextAspect(unsigned i) const +{ + if (this->isValidTextIndex(i)) + return m_textProps.at(i).m_aspect; + return Handle_Prs3d_TextAspect(); +} + +Handle_Graphic3d_AspectText3d AIS_Text::graphicTextAspect(unsigned i) const +{ + if (this->isValidTextIndex(i)) + return m_textProps.at(i).m_aspect->Aspect(); + return Handle_Graphic3d_AspectText3d(); +} + +gp_Pnt AIS_Text::position(unsigned i) const +{ + return this->isValidTextIndex(i) ? + m_textProps.at(i).m_position : gp_Pnt(); +} + +TCollection_ExtendedString AIS_Text::text(unsigned i) const +{ + return this->isValidTextIndex(i) ? + m_textProps.at(i).m_text : TCollection_ExtendedString(); +} + +bool AIS_Text::isValidTextIndex(unsigned i) const +{ + return i < this->textCount(); +} + +unsigned AIS_Text::textCount() const +{ + return static_cast(m_textProps.size()); +} + +void AIS_Text::addText(const TCollection_ExtendedString &text, const gp_Pnt& pos) +{ + TextProperties newProps; + m_textProps.push_back(newProps); + const unsigned i = this->textCount() - 1; + + this->presentationTextAspect(i)->SetColor(m_defaultColor); + this->presentationTextAspect(i)->SetFont(m_defaultFont); + + this->setPosition(pos, i); + this->setText(text, i); + this->setTextDisplayMode(m_defaultTextDisplayMode, i); + this->setTextStyle(m_defaultTextStyle, i); + this->setTextBackgroundColor(m_defaultTextBackgroundColor, i); +} + +void AIS_Text::setPosition(const gp_Pnt& pos, unsigned i) +{ + if (this->isValidTextIndex(i)) + m_textProps.at(i).m_position = pos; +} + +void AIS_Text::setText(const TCollection_ExtendedString &v, unsigned i) +{ + if (this->isValidTextIndex(i)) + m_textProps.at(i).m_text = v; +} + +//! Only works when the i-th text display mode is set to Aspect_TODT_SUBTITLE +void AIS_Text::setTextBackgroundColor(const Quantity_Color& color, unsigned i) +{ + if (this->isValidTextIndex(i)) + this->graphicTextAspect(i)->SetColorSubTitle(color); +} + +void AIS_Text::setTextDisplayMode(Aspect_TypeOfDisplayText mode, unsigned i) +{ + if (this->isValidTextIndex(i)) + this->graphicTextAspect(i)->SetDisplayType(mode); +} + +void AIS_Text::setTextStyle(Aspect_TypeOfStyleText style, unsigned i) +{ + if (this->isValidTextIndex(i)) + this->graphicTextAspect(i)->SetStyle(style); +} + +void AIS_Text::setDefaultColor(const Quantity_Color &c) +{ + m_defaultColor = c; +} + +void AIS_Text::setDefaultFont(const char *fontName) +{ + m_defaultFont = fontName; +} + +void AIS_Text::setDefaultTextBackgroundColor(const Quantity_Color& c) +{ + m_defaultTextBackgroundColor = c; +} + +void AIS_Text::setDefaultTextDisplayMode(Aspect_TypeOfDisplayText mode) +{ + m_defaultTextDisplayMode = mode; +} + +void AIS_Text::setDefaultTextStyle(Aspect_TypeOfStyleText style) +{ + m_defaultTextStyle = style; +} + +void AIS_Text::Compute( + const opencascade::handle&, + const opencascade::handle& pres, + const int) +{ + for (unsigned i = 0; i < this->textCount(); ++i) { + Prs3d_Text::Draw( + pres, + this->presentationTextAspect(i), + this->text(i), + this->position(i)); + } +} + +void AIS_Text::Compute( + const opencascade::handle&, + const opencascade::handle&) +{ +} + +void AIS_Text::ComputeSelection( + const opencascade::handle&, const int) +{ +} + +AIS_Text::TextProperties::TextProperties() + : m_aspect(new Prs3d_TextAspect) +{ +} + +bool AIS_Text::TextProperties::operator==(const AIS_Text::TextProperties& other) const +{ + return m_font == other.m_font + && m_position.SquareDistance(other.m_position) < Precision::Confusion() + && m_text == other.m_text + && m_aspect == other.m_aspect; +} + +} // namespace Mayo diff --git a/src/gpx/ais_text.h b/src/gpx/ais_text.h new file mode 100644 index 00000000..93d24519 --- /dev/null +++ b/src/gpx/ais_text.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +class AIS_Text : public AIS_InteractiveObject { +public: + AIS_Text() = default; + AIS_Text(const TCollection_ExtendedString& text, const gp_Pnt& pos); + + Handle_Prs3d_TextAspect presentationTextAspect(unsigned i = 0) const; + Handle_Graphic3d_AspectText3d graphicTextAspect(unsigned i = 0) const; + + void setDefaultColor(const Quantity_Color& c); + void setDefaultFont(const char* fontName); + void setDefaultTextBackgroundColor(const Quantity_Color& c); + void setDefaultTextDisplayMode(Aspect_TypeOfDisplayText mode); + void setDefaultTextStyle(Aspect_TypeOfStyleText style); + + gp_Pnt position(unsigned i = 0) const; + void setPosition(const gp_Pnt& pos, unsigned i = 0); + + TCollection_ExtendedString text(unsigned i = 0) const; + void setText(const TCollection_ExtendedString& v, unsigned i = 0); + bool isValidTextIndex(unsigned i) const; + + void setTextBackgroundColor(const Quantity_Color& color, unsigned i = 0); + void setTextDisplayMode(Aspect_TypeOfDisplayText mode, unsigned i = 0); + void setTextStyle(Aspect_TypeOfStyleText style, unsigned i = 0); + + unsigned textCount() const; + void addText(const TCollection_ExtendedString& text, const gp_Pnt& pos); + + void ComputeSelection( + const opencascade::handle& sel, + const int mode) override; + +protected: + void Compute( + const opencascade::handle& pm, + const opencascade::handle& pres, + const int mode) override; + void Compute( + const opencascade::handle& proj, + const opencascade::handle& pres) override; + +private: + struct TextProperties { + TextProperties(); + bool operator==(const TextProperties& other) const; + const char* m_font = nullptr; + gp_Pnt m_position; + TCollection_ExtendedString m_text; + Handle_Prs3d_TextAspect m_aspect; + }; + + const char* m_defaultFont = "Courrier"; + Quantity_Color m_defaultColor = Quantity_NOC_YELLOW; + Quantity_Color m_defaultTextBackgroundColor = Quantity_NOC_GREEN; + Aspect_TypeOfDisplayText m_defaultTextDisplayMode = Aspect_TODT_NORMAL; + Aspect_TypeOfStyleText m_defaultTextStyle = Aspect_TOST_NORMAL; + std::vector m_textProps; +}; + +} // namespace Mayo diff --git a/src/gpx_document_item.cpp b/src/gpx/gpx_document_item.cpp similarity index 64% rename from src/gpx_document_item.cpp rename to src/gpx/gpx_document_item.cpp index 7dd6a029..bb1cf84a 100644 --- a/src/gpx_document_item.cpp +++ b/src/gpx/gpx_document_item.cpp @@ -28,31 +28,56 @@ ****************************************************************************/ #include "gpx_document_item.h" +#include "../base/occt_enums.h" #include #include -#include namespace Mayo { GpxDocumentItem::GpxDocumentItem() : propertyIsVisible(this, tr("Visible")), - propertyMaterial(this, tr("Material"), &enum_Graphic3dNameOfMaterial()), + propertyMaterial(this, tr("Material"), &OcctEnums::Graphic3d_NameOfMaterial()), propertyColor(this, tr("Color")) { Mayo_PropertyChangedBlocker(this); this->propertyIsVisible.setValue(true); } +void GpxDocumentItem::setVisible(bool on) +{ + Mayo_PropertyChangedBlocker(this); + this->propertyIsVisible.setValue(on); +} + +void GpxDocumentItem::activateSelection(int /*mode*/) +{ +} + +std::vector GpxDocumentItem::entityOwners(int /*mode*/) const +{ + return std::vector(); +} + void GpxDocumentItem::onPropertyChanged(Property *prop) { if (prop == &this->propertyIsVisible) { - Handle_AIS_InteractiveContext cxt = this->handleGpxObject()->GetContext(); - if (this->propertyIsVisible.value()) - cxt->Display(this->handleGpxObject()); - else - cxt->Erase(this->handleGpxObject()); + this->setVisible(this->propertyIsVisible.value()); + this->context()->UpdateCurrentViewer(); } } +void GpxDocumentItem::getEntityOwners( + const Handle_AIS_InteractiveContext& ctx, + const Handle_AIS_InteractiveObject& obj, + int mode, + std::vector* vec) +{ + opencascade::handle mapEntityOwner; + ctx->EntityOwners(mapEntityOwner, obj, mode); + vec->reserve(vec->capacity() + mapEntityOwner->Extent()); + for (auto it = mapEntityOwner->cbegin(); it != mapEntityOwner->cend(); ++it) + vec->push_back(std::move(*it)); +} + } // namespace Mayo diff --git a/src/gpx/gpx_document_item.h b/src/gpx/gpx_document_item.h new file mode 100644 index 00000000..b561f39c --- /dev/null +++ b/src/gpx/gpx_document_item.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/property_builtins.h" +#include "../base/property_enumeration.h" + +#include +#include +#include + +namespace Mayo { + +class DocumentItem; + +class GpxDocumentItem : public PropertyOwner { + Q_DECLARE_TR_FUNCTIONS(Mayo::GpxDocumentItem) +public: + GpxDocumentItem(); + virtual ~GpxDocumentItem() = default; + + virtual DocumentItem* documentItem() const = 0; + + const Handle_AIS_InteractiveContext& context() const { return m_ctx; } + void setContext(const Handle_AIS_InteractiveContext& ctx) { m_ctx = ctx; } + + virtual void setVisible(bool on); + virtual void activateSelection(int mode); + virtual std::vector entityOwners(int mode) const; + virtual Bnd_Box boundingBox() const = 0; + + PropertyBool propertyIsVisible; + PropertyEnumeration propertyMaterial; + PropertyOccColor propertyColor; + +protected: + void onPropertyChanged(Property* prop) override; + static void getEntityOwners( + const Handle_AIS_InteractiveContext& ctx, + const Handle_AIS_InteractiveObject& obj, + int mode, + std::vector* vec); + +private: + Handle_AIS_InteractiveContext m_ctx; +}; + +} // namespace Mayo diff --git a/src/gpx/gpx_document_item_factory.cpp b/src/gpx/gpx_document_item_factory.cpp new file mode 100644 index 00000000..993219c0 --- /dev/null +++ b/src/gpx/gpx_document_item_factory.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gpx_document_item_factory.h" +#include "../base/document_item.h" + +#include + +namespace Mayo { + +GpxDocumentItemFactory *GpxDocumentItemFactory::instance() +{ + static GpxDocumentItemFactory global; + return &global; +} + +GpxDocumentItem* GpxDocumentItemFactory::create(DocumentItem* docItem) +{ + const char* strDocItemTypeName = docItem->dynTypeName(); + for (const CreatorData& creatorData : m_vecCreatorData) { + if (creatorData.strDocumentItemTypeName == strDocItemTypeName) + return creatorData.func(docItem); + } + return nullptr; +} + +void GpxDocumentItemFactory::registerCreatorFunction( + const char* strDocumentItemTypeName, const CreatorFunction& func) +{ + auto itFound = std::find_if( + m_vecCreatorData.cbegin(), + m_vecCreatorData.cend(), + [=](const CreatorData& candidate) { + return candidate.strDocumentItemTypeName == strDocumentItemTypeName; + }); + if (itFound == m_vecCreatorData.cend()) + m_vecCreatorData.push_back({ strDocumentItemTypeName, func }); +} + +} // namespace Mayo diff --git a/src/gpx/gpx_document_item_factory.h b/src/gpx/gpx_document_item_factory.h new file mode 100644 index 00000000..161cfe9f --- /dev/null +++ b/src/gpx/gpx_document_item_factory.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include +#include + +namespace Mayo { + +class DocumentItem; +class GpxDocumentItem; + +// Singleton providing creation of GpxDocumentItem objects suited to display +// input DocumentItem objects +class GpxDocumentItemFactory { +public: + static GpxDocumentItemFactory* instance(); + + GpxDocumentItem* create(DocumentItem* docItem); + + using CreatorFunction = std::function; + void registerCreatorFunction( + const char* strDocumentItemTypeName, const CreatorFunction& func); + + // Helper for GpxDocumentItem creator function + template + static GPX_DOC_ITEM* createGpx(DocumentItem* docItem) { + return new GPX_DOC_ITEM(dynamic_cast(docItem)); + } + +private: + GpxDocumentItemFactory() = default; + + struct CreatorData { + const char* strDocumentItemTypeName; + CreatorFunction func; + }; + + std::vector m_vecCreatorData; +}; + +} // namespace Mayo diff --git a/src/gpx/gpx_mesh_item.cpp b/src/gpx/gpx_mesh_item.cpp new file mode 100644 index 00000000..d3c93383 --- /dev/null +++ b/src/gpx/gpx_mesh_item.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gpx_mesh_item.h" +#include "gpx_utils.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +Q_GLOBAL_STATIC(GpxMeshItem::DefaultValues, defaultValues) + +static void redisplayAndUpdateViewer(const Handle_AIS_InteractiveObject& gpx) +{ + gpx->Redisplay(true); // All modes + gpx->GetContext()->UpdateCurrentViewer(); +} + +} // namespace Internal + +GpxMeshItem::GpxMeshItem(MeshItem *item) + : propertyDisplayMode(this, tr("Display mode"), &enum_DisplayMode()), + propertyShowEdges(this, tr("Show edges")), + propertyShowNodes(this, tr("Show nodes")), + m_meshItem(item) +{ + // Create the MeshVS_Mesh object + Handle_XSDRAWSTLVRML_DataSource dataSource = + new XSDRAWSTLVRML_DataSource(item->triangulation()); + Handle_MeshVS_Mesh meshVisu = new MeshVS_Mesh; + meshVisu->SetDataSource(dataSource); + // meshVisu->AddBuilder(..., false); -> No selection + meshVisu->AddBuilder(new MeshVS_MeshPrsBuilder(meshVisu), true); + // -- MeshVS_DrawerAttribute + meshVisu->GetDrawer()->SetBoolean( + MeshVS_DA_ShowEdges, GpxMeshItem::defaultValues().showEdges); + meshVisu->GetDrawer()->SetBoolean( + MeshVS_DA_DisplayNodes, GpxMeshItem::defaultValues().showNodes); + meshVisu->GetDrawer()->SetMaterial( + MeshVS_DA_FrontMaterial, + Graphic3d_MaterialAspect(GpxMeshItem::defaultValues().material)); + meshVisu->GetDrawer()->SetColor( + MeshVS_DA_InteriorColor, + occ::QtUtils::toOccColor(GpxMeshItem::defaultValues().color)); + meshVisu->SetDisplayMode(MeshVS_DMF_Shading); + // -- Wireframe as default highlight mode + meshVisu->SetHilightMode(MeshVS_DMF_WireFrame); + meshVisu->SetMeshSelMethod(MeshVS_MSM_PRECISE); + + m_meshVisu = meshVisu; + + // Init properties + Mayo_PropertyChangedBlocker(this); + // -- Material + Graphic3d_MaterialAspect materialAspect; + meshVisu->GetDrawer()->GetMaterial(MeshVS_DA_FrontMaterial, materialAspect); + this->propertyMaterial.setValue(materialAspect.Name()); + // -- Color + Quantity_Color color; + meshVisu->GetDrawer()->GetColor(MeshVS_DA_InteriorColor, color); + this->propertyColor.setValue(color); + // -- Display mode + this->propertyDisplayMode.setValue(meshVisu->DisplayMode()); + // -- Show edges + bool boolVal; + meshVisu->GetDrawer()->GetBoolean(MeshVS_DA_ShowEdges, boolVal); + this->propertyShowEdges.setValue(boolVal); + // -- Show nodes + meshVisu->GetDrawer()->GetBoolean(MeshVS_DA_DisplayNodes, boolVal); + this->propertyShowNodes.setValue(boolVal); +} + +GpxMeshItem::~GpxMeshItem() +{ + GpxUtils::AisContext_eraseObject(this->context(), m_meshVisu); +} + +MeshItem *GpxMeshItem::documentItem() const +{ + return m_meshItem; +} + +void GpxMeshItem::setVisible(bool on) +{ + GpxDocumentItem::setVisible(on); + GpxUtils::AisContext_setObjectVisible(this->context(), m_meshVisu, on); +} + +void GpxMeshItem::activateSelection(int mode) +{ + this->context()->Activate(m_meshVisu, mode); +} + +std::vector GpxMeshItem::entityOwners(int mode) const +{ + std::vector vec; + GpxDocumentItem::getEntityOwners(this->context(), m_meshVisu, mode, &vec); + return vec; +} + +Bnd_Box GpxMeshItem::boundingBox() const +{ + return GpxUtils::AisObject_boundingBox(m_meshVisu); +} + +const GpxMeshItem::DefaultValues& GpxMeshItem::defaultValues() +{ + return *Internal::defaultValues; +} + +void GpxMeshItem::setDefaultValues(const DefaultValues& values) +{ + *Internal::defaultValues = values; +} + +void GpxMeshItem::onPropertyChanged(Property* prop) +{ + if (prop == &this->propertyMaterial) { + const Graphic3d_NameOfMaterial mat = + this->propertyMaterial.valueAs(); + m_meshVisu->GetDrawer()->SetMaterial( + MeshVS_DA_FrontMaterial, Graphic3d_MaterialAspect(mat)); + Internal::redisplayAndUpdateViewer(m_meshVisu); + } + else if (prop == &this->propertyColor) { + m_meshVisu->GetDrawer()->SetColor( + MeshVS_DA_InteriorColor, this->propertyColor.value()); + Internal::redisplayAndUpdateViewer(m_meshVisu); + } + else if (prop == &this->propertyDisplayMode) { + this->context()->SetDisplayMode( + m_meshVisu, this->propertyDisplayMode.value(), true); + //ptrGpx->SetDisplayMode(this->propertyDisplayMode.value()); + } + else if (prop == &this->propertyShowEdges) { + m_meshVisu->GetDrawer()->SetBoolean( + MeshVS_DA_ShowEdges, this->propertyShowEdges.value()); + Internal::redisplayAndUpdateViewer(m_meshVisu); + } + else if (prop == &this->propertyShowNodes) { + m_meshVisu->GetDrawer()->SetBoolean( + MeshVS_DA_DisplayNodes, this->propertyShowNodes.value()); + Internal::redisplayAndUpdateViewer(m_meshVisu); + } + + GpxDocumentItem::onPropertyChanged(prop); +} + +const Enumeration &GpxMeshItem::enum_DisplayMode() +{ + static Enumeration enumeration; + if (enumeration.size() == 0) { + enumeration.addItem(MeshVS_DMF_WireFrame, tr("Wireframe")); + enumeration.addItem(MeshVS_DMF_Shading, tr("Shaded")); + enumeration.addItem(MeshVS_DMF_Shrink, tr("Shrink")); + } + + return enumeration; +} + +} // namespace Mayo diff --git a/src/gpx/gpx_mesh_item.h b/src/gpx/gpx_mesh_item.h new file mode 100644 index 00000000..32c1a4d2 --- /dev/null +++ b/src/gpx/gpx_mesh_item.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "gpx_document_item.h" +#include "../base/mesh_item.h" +#include +#include + +namespace Mayo { + +class GpxMeshItem : public GpxDocumentItem { + Q_DECLARE_TR_FUNCTIONS(Mayo::GpxMeshItem) +public: + GpxMeshItem(MeshItem* item); + ~GpxMeshItem(); + + MeshItem* documentItem() const override; + + void setVisible(bool on) override; + void activateSelection(int mode) override; + std::vector entityOwners(int mode) const override; + Bnd_Box boundingBox() const override; + + PropertyEnumeration propertyDisplayMode; + PropertyBool propertyShowEdges; + PropertyBool propertyShowNodes; + + struct DefaultValues { + bool showEdges = false; + bool showNodes = false; + Graphic3d_NameOfMaterial material = Graphic3d_NOM_PLASTIC; + QColor color = Qt::gray; + }; + + static const DefaultValues& defaultValues(); + static void setDefaultValues(const DefaultValues& values); + +protected: + void onPropertyChanged(Property* prop) override; + +private: + static const Enumeration& enum_DisplayMode(); + MeshItem* m_meshItem = nullptr; + Handle_MeshVS_Mesh m_meshVisu; +}; + +} // namespace Mayo diff --git a/src/gpx/gpx_utils.cpp b/src/gpx/gpx_utils.cpp new file mode 100644 index 00000000..d1d18675 --- /dev/null +++ b/src/gpx/gpx_utils.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gpx_utils.h" +#include "../base/bnd_utils.h" +#include "../base/math_utils.h" + +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +void GpxUtils::V3dView_fitAll(const Handle_V3d_View& view) +{ + view->ZFitAll(); + view->FitAll(0.01, false); +} + +bool GpxUtils::V3dView_hasClipPlane( + const Handle_V3d_View &view, const Handle_Graphic3d_ClipPlane& plane) +{ + const Handle_Graphic3d_SequenceOfHClipPlane& seqClipPlane = view->ClipPlanes(); + if (seqClipPlane.IsNull() || seqClipPlane->Size() == 0) + return false; + + for (Graphic3d_SequenceOfHClipPlane::Iterator it(*seqClipPlane); it.More(); it.Next()) { + const Handle_Graphic3d_ClipPlane& candidate = it.Value(); + if (candidate.operator->() == plane.operator->()) + return true; + } + + return false; +} + +gp_Pnt GpxUtils::V3dView_to3dPosition( + const Handle_V3d_View& view, double x, double y) +{ + double xEye, yEye, zEye, xAt, yAt, zAt; + view->Eye(xEye, yEye, zEye); + view->At(xAt, yAt, zAt); + const gp_Pnt pntEye(xEye, yEye, zEye); + const gp_Pnt pntAt(xAt, yAt, zAt); + + const gp_Vec vecEye(pntEye, pntAt); + const gp_Dir dirEye(vecEye); + + const gp_Pln planeView(pntAt, dirEye); + double px, py, pz; + const int ix = static_cast(std::round(x)); + const int iy = static_cast(std::round(y)); + view->Convert(ix, iy, px, py, pz); + const gp_Pnt pntConverted(px, py, pz); + const gp_Pnt2d pntConvertedOnPlane = ProjLib::Project(planeView, pntConverted); + const gp_Pnt pntResult = + ElSLib::Value( + pntConvertedOnPlane.X(), + pntConvertedOnPlane.Y(), + planeView); + return pntResult; +} + +void GpxUtils::AisContext_eraseObject( + const Handle_AIS_InteractiveContext& context, + const Handle_AIS_InteractiveObject& object) +{ + if (!object.IsNull() && !context.IsNull()) { + context->Erase(object, false); + context->Remove(object, false); + context->ClearPrs(object, 0, false); + context->SelectionManager()->Remove(object); + Handle_AIS_InteractiveObject objectHCopy = object; + while (!objectHCopy.IsNull()) + objectHCopy.Nullify(); + } +} + +void GpxUtils::AisContext_setObjectVisible( + const Handle_AIS_InteractiveContext& context, + const Handle_AIS_InteractiveObject& object, + bool on) +{ + if (!context.IsNull() && !object.IsNull()) { + if (on) + context->Display(object, false); + else + context->Erase(object, false); + } +} + +Bnd_Box GpxUtils::AisObject_boundingBox(const Handle_AIS_InteractiveObject& object) +{ + Bnd_Box box; + if (object.IsNull()) + return box; + + // Ensure bounding box is calculated +#if OCC_VERSION_HEX >= 0x070400 + for (Handle_PrsMgr_Presentation prs : object->Presentations()) { + if (prs->Mode() == object->DisplayMode() && !prs->CStructure()->BoundingBox().IsValid()) + prs->CalculateBoundBox(); + } +#else + for (PrsMgr_ModedPresentation& pres : object->Presentations()) { + if (pres.Mode() == object->DisplayMode()) { + const Handle_Prs3d_Presentation& pres3d = pres.Presentation()->Presentation(); + if (!pres3d->CStructure()->BoundingBox().IsValid()) + pres3d->CalculateBoundBox(); + } + } +#endif + + object->BoundingBox(box); + return box; +} + +int GpxUtils::AspectWindow_width(const Handle_Aspect_Window& wnd) +{ + if (wnd.IsNull()) + return 0; + + int w, h; + wnd->Size(w, h); + return w; +} + +int GpxUtils::AspectWindow_height(const Handle_Aspect_Window& wnd) +{ + if (wnd.IsNull()) + return 0; + + int w, h; + wnd->Size(w, h); + return h; +} + +void GpxUtils::Gpx3dClipPlane_setCappingHatch( + const Handle_Graphic3d_ClipPlane& plane, Aspect_HatchStyle hatch) +{ + if (hatch == Aspect_HS_SOLID) + plane->SetCappingHatchOff(); + else + plane->SetCappingHatchOn(); + + plane->SetCappingHatch(hatch); +} + +void GpxUtils::Gpx3dClipPlane_setNormal( + const Handle_Graphic3d_ClipPlane& plane, const gp_Dir &n) +{ + const double planePos = MathUtils::planePosition(plane->ToPlane()); + const gp_Vec placement(planePos * gp_Vec(n)); + plane->SetEquation(gp_Pln(placement.XYZ(), n)); +} + +void GpxUtils::Gpx3dClipPlane_setPosition( + const Handle_Graphic3d_ClipPlane& plane, double pos) +{ + const gp_Dir& n = plane->ToPlane().Axis().Direction(); + if (MathUtils::isReversedStandardDir(n)) + pos = -pos; + + const gp_Vec placement(pos * gp_Vec(n)); + plane->SetEquation(gp_Pln(placement.XYZ(), n)); +} + +} // namespace Mayo diff --git a/src/gpx/gpx_utils.h b/src/gpx/gpx_utils.h new file mode 100644 index 00000000..d9e42875 --- /dev/null +++ b/src/gpx/gpx_utils.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +namespace Mayo { + +struct GpxUtils { + static void V3dView_fitAll(const Handle_V3d_View& view); + static bool V3dView_hasClipPlane( + const Handle_V3d_View& view, + const Handle_Graphic3d_ClipPlane& plane); + static gp_Pnt V3dView_to3dPosition( + const Handle_V3d_View& view, double x, double y); + + static void AisContext_eraseObject( + const Handle_AIS_InteractiveContext& context, + const Handle_AIS_InteractiveObject& object); + static void AisContext_setObjectVisible( + const Handle_AIS_InteractiveContext& context, + const Handle_AIS_InteractiveObject& object, + bool on); + static Bnd_Box AisObject_boundingBox(const Handle_AIS_InteractiveObject& object); + + static int AspectWindow_width(const Handle_Aspect_Window& wnd); + static int AspectWindow_height(const Handle_Aspect_Window& wnd); + + static void Gpx3dClipPlane_setCappingHatch( + const Handle_Graphic3d_ClipPlane& plane, Aspect_HatchStyle hatch); + static void Gpx3dClipPlane_setNormal( + const Handle_Graphic3d_ClipPlane& plane, const gp_Dir& n); + static void Gpx3dClipPlane_setPosition( + const Handle_Graphic3d_ClipPlane& plane, double pos); +}; + +} // namespace Mayo diff --git a/src/gpx/gpx_xde_document_item.cpp b/src/gpx/gpx_xde_document_item.cpp new file mode 100644 index 00000000..b3006747 --- /dev/null +++ b/src/gpx/gpx_xde_document_item.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gpx_xde_document_item.h" + +#include "../base/span.h" +#include "gpx_utils.h" + +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +Q_GLOBAL_STATIC(GpxXdeDocumentItem::DefaultValues, defaultValues) + +} // namespace Internal + +GpxXdeDocumentItem::GpxXdeDocumentItem(XdeDocumentItem* item) + : propertyTransparency(this, tr("Transparency"), 0, 100, 5), + propertyDisplayMode(this, tr("Display mode"), &enumDisplayMode()), + m_xdeDocItem(item) +{ + // XCAFPrs_AISObject requires a root label containing a TopoDS_Shape + // If the XDE document as many free top-level shapes then there is a problem + // Doesn't work : + // XCAFDoc_DocumentTool::ShapesLabel() + // XCAFDoc_ShapeTool::BaseLabel() + // The only viable solution(instead of creating a root shape label containing + // the free top-level shapes) is to have an AIS object per free top-level + // shape. + const TDF_LabelSequence seqFreeShape = item->topLevelFreeShapes(); + if (!seqFreeShape.IsEmpty()) { + m_vecXdeGpx.reserve(seqFreeShape.Size()); + Mayo_PropertyChangedBlocker(this); + for (const TDF_Label& label : seqFreeShape) { + Handle_XCAFPrs_AISObject gpx = new XCAFPrs_AISObject(label); + gpx->SetMaterial(GpxXdeDocumentItem::defaultValues().material); + gpx->SetDisplayMode(AIS_Shaded); + gpx->SetColor(occ::QtUtils::toOccColor(GpxXdeDocumentItem::defaultValues().color)); + gpx->Attributes()->SetFaceBoundaryDraw(true); + gpx->Attributes()->SetIsoOnTriangulation(true); + this->propertyMaterial.setValue(GpxXdeDocumentItem::defaultValues().material); + Quantity_Color color; + gpx->Color(color); + this->propertyColor.setValue(color); + this->propertyDisplayMode.setValue(DisplayMode_ShadedWithFaceBoundary); + this->propertyTransparency.setValue(static_cast(gpx->Transparency() * 100)); + m_vecXdeGpx.push_back(gpx); + } + } + else { // Dummy + Handle_XCAFPrs_AISObject gpx = new XCAFPrs_AISObject(item->cafDoc()->Main()); + m_vecXdeGpx.push_back(gpx); + } +} + +GpxXdeDocumentItem::~GpxXdeDocumentItem() +{ + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + GpxUtils::AisContext_eraseObject(this->context(), obj); +} + +XdeDocumentItem *GpxXdeDocumentItem::documentItem() const +{ + return m_xdeDocItem; +} + +void GpxXdeDocumentItem::setVisible(bool on) +{ + Mayo::GpxDocumentItem::setVisible(on); + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + GpxUtils::AisContext_setObjectVisible(this->context(), obj, on); + + if (on && !m_selectionActivated) { + m_selectionActivated = true; + for (SelectionMode mode : m_setActivatedSelectionMode) + this->activateSelection(mode); + } + + if (!on) + m_selectionActivated = false; +} + +static int toAisShapeSelectionMode(GpxXdeDocumentItem::SelectionMode mode) +{ + using Gpx = GpxXdeDocumentItem; + switch (mode) { + case Gpx::SelectVertex: return AIS_Shape::SelectionMode(TopAbs_VERTEX); + case Gpx::SelectEdge: return AIS_Shape::SelectionMode(TopAbs_EDGE); + case Gpx::SelectWire: return AIS_Shape::SelectionMode(TopAbs_WIRE); + case Gpx::SelectFace: return AIS_Shape::SelectionMode(TopAbs_FACE); + case Gpx::SelectShell: return AIS_Shape::SelectionMode(TopAbs_SHELL); + case Gpx::SelectSolid: return AIS_Shape::SelectionMode(TopAbs_SOLID); + } + + return AIS_Shape::SelectionMode(TopAbs_SHAPE); +} + +void GpxXdeDocumentItem::activateSelection(int mode) +{ + const auto typedMode = static_cast(mode); + if (this->propertyIsVisible.value()) { + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + this->context()->Activate(obj, toAisShapeSelectionMode(typedMode)); + } + + m_selectionActivated = this->propertyIsVisible.value(); + m_setActivatedSelectionMode.insert(typedMode); +} + +std::vector GpxXdeDocumentItem::entityOwners(int mode) const +{ + const auto typedMode = static_cast(mode); + const int aisMode = toAisShapeSelectionMode(typedMode); + std::vector vecOwner; + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + GpxDocumentItem::getEntityOwners(this->context(), obj, aisMode, &vecOwner); + + return vecOwner; +} + +Bnd_Box GpxXdeDocumentItem::boundingBox() const +{ + Bnd_Box bndBox; + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + bndBox.Add(GpxUtils::AisObject_boundingBox(obj)); + + return bndBox; +} + +void GpxXdeDocumentItem::onPropertyChanged(Property* prop) +{ + if (prop == &this->propertyMaterial) { + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + obj->SetMaterial(this->propertyMaterial.valueAs()); + + this->context()->UpdateCurrentViewer(); + } + else if (prop == &this->propertyColor) { + auto dispMode = static_cast(this->propertyDisplayMode.value()); + const bool showFaceBounds = dispMode == DisplayMode_ShadedWithFaceBoundary; + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) { + obj->SetColor(this->propertyColor.value()); + if (showFaceBounds) + obj->Redisplay(true); // All modes + } + + this->context()->UpdateCurrentViewer(); + } + if (prop == &this->propertyTransparency) { + const double factor = this->propertyTransparency.value() / 100.; + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) + this->context()->SetTransparency(obj, factor, false); + + this->context()->UpdateCurrentViewer(); + } + else if (prop == &this->propertyDisplayMode) { + auto dispMode = static_cast(this->propertyDisplayMode.value()); + const AIS_DisplayMode aisDispMode = + dispMode == DisplayMode_Wireframe ? AIS_WireFrame : AIS_Shaded; + const bool showFaceBounds = dispMode == DisplayMode_ShadedWithFaceBoundary; + for (const Handle_XCAFPrs_AISObject& obj : m_vecXdeGpx) { + if (obj->DisplayMode() != aisDispMode) + this->context()->SetDisplayMode(obj, aisDispMode, false); + + if (obj->Attributes()->FaceBoundaryDraw() != showFaceBounds) { + obj->Attributes()->SetFaceBoundaryDraw(showFaceBounds); + obj->Redisplay(true); + } + } + + this->context()->UpdateCurrentViewer(); + } + + GpxDocumentItem::onPropertyChanged(prop); +} + +const Enumeration& GpxXdeDocumentItem::enumDisplayMode() +{ + static Enumeration enumeration; + if (enumeration.size() == 0) { + enumeration.addItem(DisplayMode_Wireframe, tr("Wireframe")); + enumeration.addItem(DisplayMode_Shaded, tr("Shaded")); + enumeration.addItem(DisplayMode_ShadedWithFaceBoundary, tr("Shaded with face boundaries")); + } + + return enumeration; +} + +const GpxXdeDocumentItem::DefaultValues& GpxXdeDocumentItem::defaultValues() +{ + return *Internal::defaultValues; +} + +void GpxXdeDocumentItem::setDefaultValues(const DefaultValues& values) +{ + *Internal::defaultValues = values; +} + +} // namespace Mayo diff --git a/src/gpx/gpx_xde_document_item.h b/src/gpx/gpx_xde_document_item.h new file mode 100644 index 00000000..8b570647 --- /dev/null +++ b/src/gpx/gpx_xde_document_item.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "gpx_document_item.h" +#include "../base/xde_document_item.h" +#include +#include +#include + +namespace Mayo { + +class GpxXdeDocumentItem : public GpxDocumentItem { + Q_DECLARE_TR_FUNCTIONS(Mayo::GpxXdeDocumentItem) +public: + enum SelectionMode { + SelectVertex, + SelectEdge, + SelectWire, + SelectFace, + SelectShell, + SelectSolid + }; + + GpxXdeDocumentItem(XdeDocumentItem* item); + ~GpxXdeDocumentItem(); + + XdeDocumentItem* documentItem() const override; + + void setVisible(bool on) override; + void activateSelection(int mode) override; + std::vector entityOwners(int mode) const override; + Bnd_Box boundingBox() const override; + + PropertyInt propertyTransparency; + PropertyEnumeration propertyDisplayMode; + + enum DisplayMode { + DisplayMode_Wireframe, + DisplayMode_Shaded, + DisplayMode_ShadedWithFaceBoundary + }; + static const Enumeration& enumDisplayMode(); + + struct DefaultValues { + Graphic3d_NameOfMaterial material = Graphic3d_NOM_PLASTIC; + QColor color = Qt::gray; + }; + + static const DefaultValues& defaultValues(); + static void setDefaultValues(const DefaultValues& values); + +protected: + void onPropertyChanged(Property* prop) override; + +private: + XdeDocumentItem* m_xdeDocItem = nullptr; + std::vector m_vecXdeGpx; + bool m_selectionActivated = false; + std::unordered_set m_setActivatedSelectionMode; +}; + +} // namespace Mayo diff --git a/src/gpx/v3d_view_camera_animation.cpp b/src/gpx/v3d_view_camera_animation.cpp new file mode 100644 index 00000000..90548e90 --- /dev/null +++ b/src/gpx/v3d_view_camera_animation.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "v3d_view_camera_animation.h" + +namespace Mayo { + +V3dViewCameraAnimation::V3dViewCameraAnimation(const Handle_V3d_View& view, QObject* parent) + : QAbstractAnimation(parent), + m_view(view), + m_cameraStart(new Graphic3d_Camera), + m_cameraEnd(new Graphic3d_Camera) +{ +} + +int V3dViewCameraAnimation::duration() const +{ + return m_duration_ms; +} + +void V3dViewCameraAnimation::setDuration(int msecs) +{ + m_duration_ms = msecs; +} + +void V3dViewCameraAnimation::setCameraStart(const Handle_Graphic3d_Camera& camera) +{ + m_cameraStart->Copy(camera); +} + +void V3dViewCameraAnimation::setCameraEnd(const Handle_Graphic3d_Camera& camera) +{ + m_cameraEnd->Copy(camera); +} + +const QEasingCurve& V3dViewCameraAnimation::easingCurve() const +{ + return m_easingCurve; +} + +void V3dViewCameraAnimation::setEasingCurve(const QEasingCurve& easingCurve) +{ + m_easingCurve = easingCurve; +} + +void V3dViewCameraAnimation::configure(const std::function& fnViewChange) +{ + if (this->state() == QAbstractAnimation::Running) + this->stop(); + + const bool wasImmediateUpdateOn = m_view->SetImmediateUpdate(false); + m_cameraStart->Copy(m_view->Camera()); + fnViewChange(m_view); + m_cameraEnd->Copy(m_view->Camera()); + m_view->Camera()->Copy(m_cameraStart); // Restore + m_view->SetImmediateUpdate(wasImmediateUpdateOn); +} + +void V3dViewCameraAnimation::updateCurrentTime(int currentTime) +{ + const double t = m_easingCurve.valueForProgress(currentTime / double(m_duration_ms)); + const bool prevImmediateUpdate = m_view->SetImmediateUpdate(false); + const Graphic3d_CameraLerp cameraLerp(m_cameraStart, m_cameraEnd); + Handle_Graphic3d_Camera camera = m_view->Camera(); + cameraLerp.Interpolate(t, camera); + m_view->SetCamera(camera); + m_view->ZFitAll(); + m_view->SetImmediateUpdate(prevImmediateUpdate); + m_view->Update(); +} + +} // namespace Mayo diff --git a/src/gpx/v3d_view_camera_animation.h b/src/gpx/v3d_view_camera_animation.h new file mode 100644 index 00000000..dac634f9 --- /dev/null +++ b/src/gpx/v3d_view_camera_animation.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include +#include +#include +#include + +namespace Mayo { + +class V3dViewCameraAnimation : public QAbstractAnimation { +public: + V3dViewCameraAnimation(const Handle_V3d_View& view, QObject* parent = nullptr); + + int duration() const override; + void setDuration(int msecs); + + void setCameraStart(const Handle_Graphic3d_Camera& camera); + void setCameraEnd(const Handle_Graphic3d_Camera& camera); + + const QEasingCurve& easingCurve() const; + void setEasingCurve(const QEasingCurve& easingCurve); + + void configure(const std::function& fnViewChange); + +protected: + void updateCurrentTime(int currentTime) override; + +private: + Handle_V3d_View m_view; + Handle_Graphic3d_Camera m_cameraStart; + Handle_Graphic3d_Camera m_cameraEnd; + QEasingCurve m_easingCurve; // Linear by default + int m_duration_ms = 1000; +}; + +} // namespace Mayo diff --git a/src/gpx/v3d_view_controller.cpp b/src/gpx/v3d_view_controller.cpp new file mode 100644 index 00000000..4941841f --- /dev/null +++ b/src/gpx/v3d_view_controller.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "v3d_view_controller.h" + +#include +#include +#include + +namespace Mayo { + +V3dViewController::V3dViewController(const Handle_V3d_View& view, QObject* parent) + : QObject(parent), + m_view(view) +{ +} + +V3dViewController::~V3dViewController() +{ + delete m_rubberBand; +} + +void V3dViewController::zoomIn() +{ + m_view->SetScale(m_view->Scale() * 1.1); // +10% + emit viewScaled(); +} + +void V3dViewController::zoomOut() +{ + m_view->SetScale(m_view->Scale() / 1.1); // -10% + emit viewScaled(); +} + +void V3dViewController::startDynamicAction(DynamicAction dynAction) +{ + if (dynAction == DynamicAction::None) + return; + + if (m_dynamicAction != DynamicAction::None) + return; + + m_dynamicAction = dynAction; + emit dynamicActionStarted(dynAction); +} + +void V3dViewController::stopDynamicAction() +{ + if (m_dynamicAction != DynamicAction::None) { + emit dynamicActionEnded(m_dynamicAction); + m_dynamicAction = DynamicAction::None; + } +} + +bool V3dViewController::isRotationStarted() const +{ + return m_dynamicAction == DynamicAction::Rotation; +} + +bool V3dViewController::isPanningStarted() const +{ + return m_dynamicAction == DynamicAction::Panning; +} + +bool V3dViewController::isWindowZoomingStarted() const +{ + return m_dynamicAction == DynamicAction::WindowZoom; +} + +void V3dViewController::drawRubberBand(const QPoint& posMin, const QPoint& posMax) +{ + if (!m_rubberBand) + m_rubberBand = this->createRubberBand(); + + QRect rect; + rect.setX(std::min(posMin.x(), posMax.x())); + rect.setY(std::min(posMin.y(), posMax.y())); + rect.setWidth(std::abs(posMax.x() - posMin.x())); + rect.setHeight(std::abs(posMax.y() - posMin.y())); + m_rubberBand->updateGeometry(rect); + m_rubberBand->setVisible(true); +} + +void V3dViewController::hideRubberBand() +{ + if (m_rubberBand) + m_rubberBand->setVisible(false); +} + +void V3dViewController::windowFitAll(const QPoint& posMin, const QPoint& posMax) +{ + if (std::abs(posMin.x() - posMax.x()) > 1 || std::abs(posMin.y() - posMax.y()) > 1) + m_view->WindowFitAll(posMin.x(), posMin.y(), posMax.x(), posMax.y()); +} + +V3dViewController::DynamicAction V3dViewController::currentDynamicAction() const +{ + return m_dynamicAction; +} + +bool V3dViewController::hasCurrentDynamicAction() const +{ + return m_dynamicAction != DynamicAction::None; +} + +} // namespace Mayo diff --git a/src/gpx/v3d_view_controller.h b/src/gpx/v3d_view_controller.h new file mode 100644 index 00000000..5222716b --- /dev/null +++ b/src/gpx/v3d_view_controller.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace Mayo { + +class V3dViewController : public QObject { + Q_OBJECT +public: + enum class DynamicAction { + None, + Panning, + Rotation, + WindowZoom, + InstantZoom + }; + + struct AbstractRubberBand { + virtual ~AbstractRubberBand() {} + virtual void updateGeometry(const QRect& rect) = 0; + virtual void setVisible(bool on) = 0; + }; + + V3dViewController(const Handle_V3d_View& view, QObject* parent = nullptr); + virtual ~V3dViewController(); + + DynamicAction currentDynamicAction() const; + bool hasCurrentDynamicAction() const; + + void zoomIn(); + void zoomOut(); + +signals: + void dynamicActionStarted(DynamicAction dynAction); + void dynamicActionEnded(DynamicAction dynAction); + void viewScaled(); + + void mouseMoved(const QPoint& posMouseInView); + void mouseClicked(Qt::MouseButton btn); + +protected: + void startDynamicAction(DynamicAction dynAction); + void stopDynamicAction(); + + bool isRotationStarted() const; + bool isPanningStarted() const; + bool isWindowZoomingStarted() const; + + void windowFitAll(const QPoint& posMin, const QPoint& posMax); + + virtual AbstractRubberBand* createRubberBand() = 0; + void drawRubberBand(const QPoint& posMin, const QPoint& posMax); + void hideRubberBand(); + +private: + Handle_V3d_View m_view; + DynamicAction m_dynamicAction = DynamicAction::None; + AbstractRubberBand* m_rubberBand = nullptr; +}; + +} // namespace Mayo diff --git a/src/gpx_brep_shape_item.cpp b/src/gpx_brep_shape_item.cpp deleted file mode 100644 index 3c85f07e..00000000 --- a/src/gpx_brep_shape_item.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "gpx_brep_shape_item.h" - -#include "options.h" -#include "fougtools/occtools/qt_utils.h" - -#include - -namespace Mayo { - -GpxBRepShapeItem::GpxBRepShapeItem(BRepShapeItem *item) - : GpxCovariantDocumentItem(item), - propertyTransparency(this, tr("Transparency"), 0, 100, 5), - propertyDisplayMode(this, tr("Display mode"), &enum_DisplayMode()), - propertyShowFaceBoundary(this, tr("Show face boundary")) -{ - const Options* opts = Options::instance(); - - // Create the AIS_Shape object - Handle_AIS_Shape aisShape = new AIS_Shape(item->brepShape()); - aisShape->SetMaterial(opts->brepShapeDefaultMaterial()); - aisShape->SetDisplayMode(AIS_Shaded); - aisShape->SetColor(occ::QtUtils::toOccColor(opts->brepShapeDefaultColor())); - aisShape->Attributes()->SetFaceBoundaryDraw(Standard_True); - aisShape->Attributes()->SetIsoOnTriangulation(Standard_True); - - m_hndGpxObject = aisShape; - - // Init properties - Mayo_PropertyChangedBlocker(this); - this->propertyMaterial.setValue(opts->brepShapeDefaultMaterial()); - this->propertyColor.setValue(m_hndGpxObject->Color()); - this->propertyTransparency.setValue( - static_cast(m_hndGpxObject->Transparency() * 100)); - this->propertyDisplayMode.setValue(m_hndGpxObject->DisplayMode()); - this->propertyShowFaceBoundary.setValue( - m_hndGpxObject->Attributes()->FaceBoundaryDraw() == Standard_True); -} - -void GpxBRepShapeItem::onPropertyChanged(Property *prop) -{ - Handle_AIS_InteractiveContext cxt = this->gpxObject()->GetContext(); - const Handle_AIS_InteractiveObject& hndGpx = this->handleGpxObject(); - AIS_Shape* ptrGpx = this->gpxObject(); - if (prop == &this->propertyMaterial) { - ptrGpx->SetMaterial( - this->propertyMaterial.valueAs()); - cxt->UpdateCurrentViewer(); - } - else if (prop == &this->propertyColor) { - ptrGpx->SetColor(this->propertyColor.value()); - if (this->propertyShowFaceBoundary.value()) { - ptrGpx->Redisplay(Standard_True); // All modes - cxt->UpdateCurrentViewer(); - } - } - else if (prop == &this->propertyTransparency) { - cxt->SetTransparency(hndGpx, this->propertyTransparency.value() / 100.); - } - else if (prop == &this->propertyDisplayMode) { - cxt->SetDisplayMode(hndGpx, this->propertyDisplayMode.value()); - } - else if (prop == &this->propertyShowFaceBoundary) { - ptrGpx->Attributes()->SetFaceBoundaryDraw( - this->propertyShowFaceBoundary.value()); - ptrGpx->Redisplay(Standard_True); // All modes - cxt->UpdateCurrentViewer(); - } - GpxDocumentItem::onPropertyChanged(prop); -} - -const Enumeration &GpxBRepShapeItem::enum_DisplayMode() -{ - static Enumeration enumeration; - if (enumeration.size() == 0) { - enumeration.map(AIS_Shaded, tr("Shaded")); - enumeration.map(AIS_WireFrame, tr("Wireframe")); - } - return enumeration; -} - -} // namespace Mayo diff --git a/src/gpx_brep_shape_item.h b/src/gpx_brep_shape_item.h deleted file mode 100644 index d26fbc94..00000000 --- a/src/gpx_brep_shape_item.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "brep_shape_item.h" -#include "gpx_document_item.h" -#include - -namespace Mayo { - -class GpxBRepShapeItem : - public GpxCovariantDocumentItem -{ - Q_DECLARE_TR_FUNCTIONS(Mayo::GpxBRepShapeItem) - -public: - GpxBRepShapeItem(BRepShapeItem* item); - - PropertyInt propertyTransparency; - PropertyEnumeration propertyDisplayMode; - PropertyBool propertyShowFaceBoundary; - -protected: - void onPropertyChanged(Property* prop) override; - -private: - static const Enumeration& enum_DisplayMode(); -}; - -} // namespace Mayo diff --git a/src/gpx_document_item.h b/src/gpx_document_item.h deleted file mode 100644 index 14ea894d..00000000 --- a/src/gpx_document_item.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "property_builtins.h" -#include "property_enumeration.h" - -#include -#include -#include - -namespace Mayo { - -class DocumentItem; - -class GpxDocumentItem : public PropertyOwner -{ - Q_DECLARE_TR_FUNCTIONS(Mayo::GpxDocumentItem) - -public: - GpxDocumentItem(); - - virtual DocumentItem* documentItem() const = 0; - virtual const Handle_AIS_InteractiveObject& handleGpxObject() const = 0; - virtual AIS_InteractiveObject* gpxObject() const = 0; - - PropertyBool propertyIsVisible; - PropertyEnumeration propertyMaterial; - PropertyOccColor propertyColor; - -protected: - void onPropertyChanged(Property* prop) override; -}; - -template -class GpxCovariantDocumentItem : public GpxDocumentItem -{ -public: - GpxCovariantDocumentItem(DOC_ITEM* item); - - DOC_ITEM* documentItem() const override; - const Handle_AIS_InteractiveObject& handleGpxObject() const override; - GPX_OBJECT* gpxObject() const override; - -protected: - DOC_ITEM* m_docItem = nullptr; - HND_GPX_OBJECT m_hndGpxObject; -}; - - - -// -- -// -- Implementation -// -- - -template -GpxCovariantDocumentItem:: -GpxCovariantDocumentItem(DOC_ITEM* item) - : m_docItem(item) -{ } - -template -DOC_ITEM* GpxCovariantDocumentItem::documentItem() const -{ return m_docItem; } - -template -const Handle_AIS_InteractiveObject& -GpxCovariantDocumentItem::handleGpxObject() const -{ return m_hndGpxObject; } - -template -GPX_OBJECT* GpxCovariantDocumentItem::gpxObject() const -{ return m_hndGpxObject.operator->(); } - -} // namespace Mayo diff --git a/src/gpx_stl_mesh_item.cpp b/src/gpx_stl_mesh_item.cpp deleted file mode 100644 index 813405a9..00000000 --- a/src/gpx_stl_mesh_item.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "gpx_stl_mesh_item.h" - -#include "options.h" -#include "fougtools/occtools/qt_utils.h" - -#include -#include -#include -#include -#include -#include - -namespace Mayo { - -namespace Internal { - -static void redisplayAndUpdateViewer(AIS_InteractiveObject* ptrGpx) -{ - ptrGpx->Redisplay(Standard_True); // All modes - ptrGpx->GetContext()->UpdateCurrentViewer(); -} - -} // namespace Internal - -GpxStlMeshItem::GpxStlMeshItem(StlMeshItem *item) - : GpxCovariantDocumentItem(item), - propertyDisplayMode(this, tr("Display mode"), &enum_DisplayMode()), - propertyShowEdges(this, tr("Show edges")), - propertyShowNodes(this, tr("Show nodes")) -{ - // Create the MeshVS_Mesh object - const Options* opts = Options::instance(); - Handle_XSDRAWSTLVRML_DataSource dataSource = - new XSDRAWSTLVRML_DataSource(item->stlMesh()); - Handle_MeshVS_Mesh meshVisu = new MeshVS_Mesh; - meshVisu->SetDataSource(dataSource); - // meshVisu->AddBuilder(..., Standard_False); -> No selection - meshVisu->AddBuilder(new MeshVS_MeshPrsBuilder(meshVisu), Standard_True); - // -- MeshVS_DrawerAttribute - meshVisu->GetDrawer()->SetBoolean( - MeshVS_DA_ShowEdges, opts->meshDefaultShowEdges()); - meshVisu->GetDrawer()->SetBoolean( - MeshVS_DA_DisplayNodes, opts->meshDefaultShowNodes()); - meshVisu->GetDrawer()->SetMaterial( - MeshVS_DA_FrontMaterial, - Graphic3d_MaterialAspect(opts->meshDefaultMaterial())); - meshVisu->GetDrawer()->SetColor( - MeshVS_DA_InteriorColor, - occ::QtUtils::toOccColor(opts->meshDefaultColor())); - meshVisu->SetDisplayMode(MeshVS_DMF_Shading); - // -- Wireframe as default hilight mode - meshVisu->SetHilightMode(MeshVS_DMF_WireFrame); - meshVisu->SetMeshSelMethod(MeshVS_MSM_PRECISE); - - m_hndGpxObject = meshVisu; - - // Init properties - Mayo_PropertyChangedBlocker(this); - // -- Material - Graphic3d_MaterialAspect materialAspect; - meshVisu->GetDrawer()->GetMaterial( - MeshVS_DA_FrontMaterial, materialAspect); - this->propertyMaterial.setValue(materialAspect.Name()); - // -- Color - Quantity_Color color; - meshVisu->GetDrawer()->GetColor(MeshVS_DA_InteriorColor, color); - this->propertyColor.setValue(color); - // -- Display mode - this->propertyDisplayMode.setValue(meshVisu->DisplayMode()); - // -- Show edges - Standard_Boolean boolVal; - meshVisu->GetDrawer()->GetBoolean(MeshVS_DA_ShowEdges, boolVal); - this->propertyShowEdges.setValue(boolVal == Standard_True); - // -- Show nodes - meshVisu->GetDrawer()->GetBoolean(MeshVS_DA_DisplayNodes, boolVal); - this->propertyShowNodes.setValue(boolVal == Standard_True); -} - -void GpxStlMeshItem::onPropertyChanged(Property *prop) -{ - Handle_AIS_InteractiveContext cxt = this->gpxObject()->GetContext(); - const Handle_AIS_InteractiveObject& hndGpx = this->handleGpxObject(); - MeshVS_Mesh* ptrGpx = this->gpxObject(); - if (prop == &this->propertyMaterial) { - const Graphic3d_NameOfMaterial mat = - this->propertyMaterial.valueAs(); - ptrGpx->GetDrawer()->SetMaterial( - MeshVS_DA_FrontMaterial, Graphic3d_MaterialAspect(mat)); - Internal::redisplayAndUpdateViewer(ptrGpx); - } - else if (prop == &this->propertyColor) { - ptrGpx->GetDrawer()->SetColor( - MeshVS_DA_InteriorColor, this->propertyColor.value()); - Internal::redisplayAndUpdateViewer(ptrGpx); - } - else if (prop == &this->propertyDisplayMode) { - cxt->SetDisplayMode(hndGpx, this->propertyDisplayMode.value()); - //ptrGpx->SetDisplayMode(this->propertyDisplayMode.value()); - } - else if (prop == &this->propertyShowEdges) { - ptrGpx->GetDrawer()->SetBoolean( - MeshVS_DA_ShowEdges, this->propertyShowEdges.value()); - Internal::redisplayAndUpdateViewer(ptrGpx); - } - else if (prop == &this->propertyShowNodes) { - ptrGpx->GetDrawer()->SetBoolean( - MeshVS_DA_DisplayNodes, this->propertyShowNodes.value()); - Internal::redisplayAndUpdateViewer(ptrGpx); - } - GpxDocumentItem::onPropertyChanged(prop); -} - -const Enumeration &GpxStlMeshItem::enum_DisplayMode() -{ - static Enumeration enumeration; - if (enumeration.size() == 0) { - enumeration.map(MeshVS_DMF_WireFrame, tr("Wireframe")); - enumeration.map(MeshVS_DMF_Shading, tr("Shaded")); - enumeration.map(MeshVS_DMF_Shrink, tr("Shrink")); - } - return enumeration; -} - -} // namespace Mayo diff --git a/src/gpx_stl_mesh_item.h b/src/gpx_stl_mesh_item.h deleted file mode 100644 index 931fabb0..00000000 --- a/src/gpx_stl_mesh_item.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "gpx_document_item.h" -#include "stl_mesh_item.h" -#include - -namespace Mayo { - -class GpxStlMeshItem : - public GpxCovariantDocumentItem -{ - Q_DECLARE_TR_FUNCTIONS(Mayo::GpxStlMeshItem) - -public: - GpxStlMeshItem(StlMeshItem* item); - - PropertyEnumeration propertyDisplayMode; - PropertyBool propertyShowEdges; - PropertyBool propertyShowNodes; - -protected: - void onPropertyChanged(Property* prop) override; - -private: - static const Enumeration& enum_DisplayMode(); -}; - -} // namespace Mayo diff --git a/src/gui/gui_application.cpp b/src/gui/gui_application.cpp new file mode 100644 index 00000000..acaf40ea --- /dev/null +++ b/src/gui/gui_application.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gui_application.h" + +#include "../base/application.h" +#include "../base/application_item_selection_model.h" +#include "../base/document.h" +#include "gui_document.h" + +#include + +namespace Mayo { + +GuiApplication::GuiApplication(QObject *parent) + : QObject(parent) +{ + m_selectionModel = new ApplicationItemSelectionModel(this); + + auto app = Application::instance(); + QObject::connect( + app, &Application::documentAdded, + this, &GuiApplication::onDocumentAdded); + QObject::connect( + app, &Application::documentErased, + this, &GuiApplication::onDocumentErased); + + QObject::connect( + m_selectionModel, &ApplicationItemSelectionModel::changed, + this, &GuiApplication::onApplicationItemSelectionChanged); + QObject::connect( + m_selectionModel, &ApplicationItemSelectionModel::cleared, + this, &GuiApplication::onApplicationItemSelectionCleared); +} + +GuiApplication *GuiApplication::instance() +{ + static GuiApplication app; + return &app; +} + +GuiApplication::~GuiApplication() +{ + for (Doc_GuiDoc& pair : m_vecDocGuiDoc) { + delete pair.guiDoc; + pair.guiDoc = nullptr; + } +} + +GuiDocument *GuiApplication::findGuiDocument(const Document *doc) const +{ + for (const Doc_GuiDoc& pair : m_vecDocGuiDoc) { + if (pair.doc == doc) + return pair.guiDoc; + } + return nullptr; +} + +std::vector GuiApplication::guiDocuments() const +{ + std::vector vecGuiDoc; + vecGuiDoc.reserve(m_vecDocGuiDoc.size()); + for (const Doc_GuiDoc& pair : m_vecDocGuiDoc) + vecGuiDoc.push_back(pair.guiDoc); + return vecGuiDoc; +} + +ApplicationItemSelectionModel* GuiApplication::selectionModel() const +{ + return m_selectionModel; +} + +void GuiApplication::onDocumentAdded(Document *doc) +{ + const Doc_GuiDoc pair = { doc, new GuiDocument(doc) }; // TODO: set container widget + m_vecDocGuiDoc.emplace_back(std::move(pair)); + emit guiDocumentAdded(pair.guiDoc); +} + +void GuiApplication::onDocumentErased(const Document *doc) +{ + auto itFound = std::find_if( + m_vecDocGuiDoc.begin(), + m_vecDocGuiDoc.end(), + [=](const Doc_GuiDoc& pair) { return pair.doc == doc; }); + if (itFound != m_vecDocGuiDoc.end()) { + const GuiDocument* guiDoc = itFound->guiDoc; + delete guiDoc; + m_vecDocGuiDoc.erase(itFound); + emit guiDocumentErased(guiDoc); + } +} + +void GuiApplication::onApplicationItemSelectionCleared() +{ + for (Doc_GuiDoc pair : m_vecDocGuiDoc) { + pair.guiDoc->clearItemSelection(); + pair.guiDoc->updateV3dViewer(); + } +} + +void GuiApplication::onApplicationItemSelectionChanged( + Span selected, Span deselected) +{ + std::unordered_set setGuiDocDirty; + auto funcToggleItemSelected = [&](const ApplicationItem& item) { + GuiDocument* guiDoc = this->findGuiDocument(item.document()); + if (guiDoc != nullptr) { + guiDoc->toggleItemSelected(item); + setGuiDocDirty.insert(guiDoc); + } + }; + for (const ApplicationItem& item : selected) + funcToggleItemSelected(item); + for (const ApplicationItem& item : deselected) + funcToggleItemSelected(item); + for (GuiDocument* guiDoc : setGuiDocDirty) + guiDoc->updateV3dViewer(); +} + +} // namespace Mayo diff --git a/src/gui/gui_application.h b/src/gui/gui_application.h new file mode 100644 index 00000000..5e8387ab --- /dev/null +++ b/src/gui/gui_application.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../base/application_item_selection_model.h" +#include +#include + +namespace Mayo { + +class Document; +class DocumentItem; +class GuiDocument; + +class GuiApplication : public QObject { + Q_OBJECT +public: + static GuiApplication* instance(); + ~GuiApplication(); + + std::vector guiDocuments() const; + GuiDocument* findGuiDocument(const Document* doc) const; + + ApplicationItemSelectionModel* selectionModel() const; + +signals: + void guiDocumentAdded(GuiDocument* guiDoc); + void guiDocumentErased(const GuiDocument* guiDoc); + +protected: + void onDocumentAdded(Document* doc); + void onDocumentErased(const Document* doc); + +private: + void onApplicationItemSelectionCleared(); + void onApplicationItemSelectionChanged( + Span selected, Span deselected); + + GuiApplication(QObject* parent = nullptr); + + struct Doc_GuiDoc { + Document* doc; + GuiDocument* guiDoc; + }; + + std::vector m_vecDocGuiDoc; + ApplicationItemSelectionModel* m_selectionModel = nullptr; +}; + +} // namespace Mayo diff --git a/src/gui/gui_document.cpp b/src/gui/gui_document.cpp new file mode 100644 index 00000000..99656c72 --- /dev/null +++ b/src/gui/gui_document.cpp @@ -0,0 +1,280 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gui_document.h" + +#include "../app/theme.h" // TODO Remove this dependency +#include "../base/application_item.h" +#include "../base/bnd_utils.h" +#include "../base/brep_utils.h" +#include "../base/document.h" +#include "../base/document_item.h" +#include "../base/xde_document_item.h" +#include "../gpx/gpx_document_item_factory.h" +#include "../gpx/gpx_utils.h" +#include "../gpx/gpx_xde_document_item.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Mayo { + +namespace Internal { + +static Handle_V3d_Viewer createOccViewer() +{ + Handle_Aspect_DisplayConnection dispConnection; +#if (!defined(Q_OS_WIN32) && (!defined(Q_OS_MAC) || defined(MACOSX_USE_GLX))) + dispConnection = new Aspect_DisplayConnection(std::getenv("DISPLAY")); +#endif + Handle_Graphic3d_GraphicDriver gpxDriver = new OpenGl_GraphicDriver(dispConnection); + Handle_V3d_Viewer viewer = new V3d_Viewer(gpxDriver); + viewer->SetDefaultViewSize(1000.); + viewer->SetDefaultViewProj(V3d_XposYnegZpos); + viewer->SetComputedMode(Standard_True); + viewer->SetDefaultComputedMode(Standard_True); +// viewer->SetDefaultVisualization(V3d_ZBUFFER); +// viewer->SetDefaultShadingModel(V3d_GOURAUD); + viewer->SetDefaultLights(); + viewer->SetLightOn(); + + return viewer; +} + +static Handle_AIS_Trihedron createOriginTrihedron() +{ + Handle_Geom_Axis2Placement axis = new Geom_Axis2Placement(gp::XOY()); + Handle_AIS_Trihedron aisTrihedron = new AIS_Trihedron(axis); + aisTrihedron->SetDatumDisplayMode(Prs3d_DM_Shaded); + aisTrihedron->SetDatumPartColor(Prs3d_DP_XArrow, Quantity_NOC_RED2); + aisTrihedron->SetDatumPartColor(Prs3d_DP_YArrow, Quantity_NOC_GREEN2); + aisTrihedron->SetDatumPartColor(Prs3d_DP_ZArrow, Quantity_NOC_BLUE2); + aisTrihedron->SetDatumPartColor(Prs3d_DP_XAxis, Quantity_NOC_RED2); + aisTrihedron->SetDatumPartColor(Prs3d_DP_YAxis, Quantity_NOC_GREEN2); + aisTrihedron->SetDatumPartColor(Prs3d_DP_ZAxis, Quantity_NOC_BLUE2); + aisTrihedron->SetLabel(Prs3d_DP_XAxis, ""); + aisTrihedron->SetLabel(Prs3d_DP_YAxis, ""); + aisTrihedron->SetLabel(Prs3d_DP_ZAxis, ""); + //aisTrihedron->SetTextColor(Quantity_NOC_GRAY40); + aisTrihedron->SetSize(60); + Handle_Graphic3d_TransformPers trsf = + new Graphic3d_TransformPers(Graphic3d_TMF_ZoomPers, axis->Ax2().Location()); + aisTrihedron->SetTransformPersistence(trsf); + aisTrihedron->SetInfiniteState(true); + return aisTrihedron; +} + +} // namespace Internal + +GuiDocument::GuiDocument(Document* doc) + : m_document(doc), + m_v3dViewer(Internal::createOccViewer()), + m_v3dView(m_v3dViewer->CreateView()), + m_aisContext(new AIS_InteractiveContext(m_v3dViewer)), + m_aisOriginTrihedron(Internal::createOriginTrihedron()) +{ + Q_ASSERT(doc != nullptr); + + //m_v3dView->SetShadingModel(V3d_PHONG); + // 3D view - Enable anti-aliasing with MSAA + m_v3dView->ChangeRenderingParams().IsAntialiasingEnabled = true; + m_v3dView->ChangeRenderingParams().NbMsaaSamples = 4; + // 3D view - Set gradient background + m_v3dView->SetBgGradientColors( + occ::QtUtils::toOccColor( + mayoTheme()->color(Theme::Color::View3d_BackgroundGradientStart)), + occ::QtUtils::toOccColor( + mayoTheme()->color(Theme::Color::View3d_BackgroundGradientEnd)), + Aspect_GFM_VER); + // 3D view - Add shaded trihedron located in the bottom-left corner + m_v3dView->TriedronDisplay( + Aspect_TOTP_LEFT_LOWER, + Quantity_NOC_GRAY50, + 0.075, + V3d_ZBUFFER); + + for (DocumentItem* docItem : doc->rootItems()) + this->mapGpxItem(docItem); + + QObject::connect(doc, &Document::itemAdded, this, &GuiDocument::onItemAdded); + QObject::connect(doc, &Document::itemErased, this, &GuiDocument::onItemErased); +} + +Document* GuiDocument::document() const +{ + return m_document; +} + +const Handle_V3d_View& GuiDocument::v3dView() const +{ + return m_v3dView; +} + +const Handle_AIS_InteractiveContext& GuiDocument::aisInteractiveContext() const +{ + return m_aisContext; +} + +GpxDocumentItem* GuiDocument::findItemGpx(const DocumentItem* item) const +{ + const GuiDocumentItem* guiDocItem = this->findGuiDocumentItem(item); + return guiDocItem ? guiDocItem->gpxDocItem.get() : nullptr; +} + +const Bnd_Box& GuiDocument::gpxBoundingBox() const +{ + return m_gpxBoundingBox; +} + +void GuiDocument::toggleItemSelected(const ApplicationItem& appItem) +{ + if (appItem.document() != this->document()) + return; + + if (appItem.isDocumentItemNode()) { + const GuiDocumentItem* guiItem = this->findGuiDocumentItem(appItem.documentItem()); + if (guiItem && sameType(appItem.documentItem())) { + auto xdeItem = static_cast(appItem.documentItem()); + const DocumentItemNode& docItemNode = appItem.documentItemNode(); + const TopLoc_Location shapeLoc = xdeItem->shapeAbsoluteLocation(docItemNode.id); + const TDF_Label labelNode = XdeDocumentItem::label(docItemNode); + const TopoDS_Shape shape = XdeDocumentItem::shape(labelNode).Located(shapeLoc); + std::vector vecFace; + if (BRepUtils::moreComplex(shape.ShapeType(), TopAbs_FACE)) { + BRepUtils::forEachSubFace(shape, [&](const TopoDS_Face& face) { + vecFace.push_back(face); + }); + } + else if (shape.ShapeType() == TopAbs_FACE) { + vecFace.push_back(TopoDS::Face(shape)); + } + + for (const TopoDS_Face& face : vecFace) { + auto brepOwner = guiItem->findBrepOwner(face); + if (!brepOwner.IsNull()) + m_aisContext->AddOrRemoveSelected(brepOwner, false); + } + } + } +} + +void GuiDocument::clearItemSelection() +{ + m_aisContext->ClearSelected(false); +} + +bool GuiDocument::isOriginTrihedronVisible() const +{ + return m_aisContext->IsDisplayed(m_aisOriginTrihedron); +} + +void GuiDocument::toggleOriginTrihedronVisibility() +{ + if (this->isOriginTrihedronVisible()) + m_aisContext->Erase(m_aisOriginTrihedron, false); + else + m_aisContext->Display(m_aisOriginTrihedron, false); +} + +void GuiDocument::updateV3dViewer() +{ + m_aisContext->UpdateCurrentViewer(); +} + +std::vector GuiDocument::selectedEntityOwners() const +{ + std::vector vecOwner; + m_aisContext->InitSelected(); + while (m_aisContext->MoreSelected()) { + vecOwner.push_back(m_aisContext->SelectedOwner()); + m_aisContext->NextSelected(); + } + return vecOwner; +} + +void GuiDocument::onItemAdded(DocumentItem* item) +{ + this->mapGpxItem(item); + emit gpxBoundingBoxChanged(m_gpxBoundingBox); +} + +void GuiDocument::onItemErased(const DocumentItem* item) +{ + auto itFound = std::find_if( + m_vecGuiDocumentItem.begin(), + m_vecGuiDocumentItem.end(), + [=](const GuiDocumentItem& guiItem) { return guiItem.docItem == item; }); + if (itFound != m_vecGuiDocumentItem.end()) { + // Delete gpx item + m_vecGuiDocumentItem.erase(itFound); + this->updateV3dViewer(); + + // Recompute bounding box + m_gpxBoundingBox.SetVoid(); + for (const GuiDocumentItem& guiItem : m_vecGuiDocumentItem) { + const Bnd_Box otherBox = guiItem.gpxDocItem->boundingBox(); + BndUtils::add(&m_gpxBoundingBox, otherBox); + } + emit gpxBoundingBoxChanged(m_gpxBoundingBox); + } +} + +void GuiDocument::mapGpxItem(DocumentItem* item) +{ + GpxDocumentItem* gpxItem = GpxDocumentItemFactory::instance()->create(item); + GuiDocumentItem guiItem(item, gpxItem); + gpxItem->setContext(m_aisContext); + gpxItem->setVisible(true); + m_aisContext->UpdateCurrentViewer(); + if (sameType(item)) { + gpxItem->activateSelection(GpxXdeDocumentItem::SelectVertex); + gpxItem->activateSelection(GpxXdeDocumentItem::SelectEdge); + gpxItem->activateSelection(GpxXdeDocumentItem::SelectWire); + gpxItem->activateSelection(GpxXdeDocumentItem::SelectFace); + gpxItem->activateSelection(GpxXdeDocumentItem::SelectShell); + gpxItem->activateSelection(GpxXdeDocumentItem::SelectSolid); + guiItem.vecGpxEntityOwner = gpxItem->entityOwners(GpxXdeDocumentItem::SelectFace); + } + + GpxUtils::V3dView_fitAll(m_v3dView); + BndUtils::add(&m_gpxBoundingBox, gpxItem->boundingBox()); + m_vecGuiDocumentItem.emplace_back(std::move(guiItem)); +} + +const GuiDocument::GuiDocumentItem* +GuiDocument::findGuiDocumentItem(const DocumentItem* item) const +{ + for (const GuiDocumentItem& guiItem : m_vecGuiDocumentItem) { + if (guiItem.docItem == item) + return &guiItem; + } + return nullptr; +} + +GuiDocument::GuiDocumentItem::GuiDocumentItem(DocumentItem* item, GpxDocumentItem* gpx) + : docItem(item), gpxDocItem(gpx) +{ +} + +Handle_SelectMgr_EntityOwner +GuiDocument::GuiDocumentItem::findBrepOwner(const TopoDS_Face& face) const +{ + for (const Handle_SelectMgr_EntityOwner& owner : vecGpxEntityOwner) { + auto brepOwner = Handle_StdSelect_BRepOwner::DownCast(owner); + if (!brepOwner.IsNull() && brepOwner->Shape() == face) + return owner; + } + return Handle_SelectMgr_EntityOwner(); +} + +} // namespace Mayo diff --git a/src/gui/gui_document.h b/src/gui/gui_document.h new file mode 100644 index 00000000..79452cde --- /dev/null +++ b/src/gui/gui_document.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include "../gpx/gpx_document_item.h" + +#include +#include +#include +#include +#include +#include +#include +class TopoDS_Face; + +namespace Mayo { + +class ApplicationItem; +class Document; +class DocumentItem; + +class GuiDocument : public QObject { + Q_OBJECT +public: + GuiDocument(Document* doc); + + Document* document() const; + const Handle_V3d_View& v3dView() const; + const Handle_AIS_InteractiveContext& aisInteractiveContext() const; + GpxDocumentItem* findItemGpx(const DocumentItem* item) const; + + const Bnd_Box& gpxBoundingBox() const; + + std::vector selectedEntityOwners() const; + void toggleItemSelected(const ApplicationItem& appItem); + void clearItemSelection(); + + bool isOriginTrihedronVisible() const; + void toggleOriginTrihedronVisibility(); + + void updateV3dViewer(); + +signals: + void gpxBoundingBoxChanged(const Bnd_Box& bndBox); + +private: + void onItemAdded(DocumentItem* item); + void onItemErased(const DocumentItem* item); + + void mapGpxItem(DocumentItem* item); + + using ArrayGpxEntityOwner = std::vector; + struct GuiDocumentItem { + GuiDocumentItem() = default; + GuiDocumentItem(DocumentItem* item, GpxDocumentItem* gpx); + DocumentItem* docItem; + std::unique_ptr gpxDocItem; + ArrayGpxEntityOwner vecGpxEntityOwner; + Handle_SelectMgr_EntityOwner findBrepOwner(const TopoDS_Face& face) const; + }; + const GuiDocumentItem* findGuiDocumentItem(const DocumentItem* item) const; + + Document* m_document = nullptr; + Handle_V3d_Viewer m_v3dViewer; + Handle_V3d_View m_v3dView; + Handle_AIS_InteractiveContext m_aisContext; + Handle_AIS_InteractiveObject m_aisOriginTrihedron; + std::vector m_vecGuiDocumentItem; + Bnd_Box m_gpxBoundingBox; +}; + +} // namespace Mayo diff --git a/src/gui/gui_document_list_model.cpp b/src/gui/gui_document_list_model.cpp new file mode 100644 index 00000000..a5ceb4ec --- /dev/null +++ b/src/gui/gui_document_list_model.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "gui_document_list_model.h" + +#include "../base/document.h" +#include "gui_application.h" +#include "gui_document.h" + +namespace Mayo { + +GuiDocumentListModel::GuiDocumentListModel(GuiApplication* app) + : QStringListModel(app) +{ + for (const GuiDocument* doc : app->guiDocuments()) + this->appendGuiDocument(doc); + QObject::connect( + app, &GuiApplication::guiDocumentAdded, + this, &GuiDocumentListModel::appendGuiDocument); + QObject::connect( + app, &GuiApplication::guiDocumentErased, + this, &GuiDocumentListModel::removeGuiDocument); +} + +QVariant GuiDocumentListModel::data(const QModelIndex& index, int role) const +{ + if (index.isValid() && role == Qt::ToolTipRole) + return m_vecGuiDocument.at(index.row())->document()->filePath(); + return QStringListModel::data(index, role); +} + +void GuiDocumentListModel::appendGuiDocument(const GuiDocument* guiDoc) +{ + const int rowId = this->rowCount(); + this->insertRow(rowId); + const QModelIndex indexRow = this->index(rowId); + this->setData(indexRow, guiDoc->document()->label()); + m_vecGuiDocument.emplace_back(guiDoc); +} + +void GuiDocumentListModel::removeGuiDocument(const GuiDocument* guiDoc) +{ + auto itFound = std::find(m_vecGuiDocument.begin(), m_vecGuiDocument.end(), guiDoc); + if (itFound != m_vecGuiDocument.end()) { + this->removeRow(itFound - m_vecGuiDocument.begin()); + m_vecGuiDocument.erase(itFound); + } +} + +} // namespace Mayo diff --git a/src/gui/gui_document_list_model.h b/src/gui/gui_document_list_model.h new file mode 100644 index 00000000..c22aae60 --- /dev/null +++ b/src/gui/gui_document_list_model.h @@ -0,0 +1,30 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +class GuiApplication; +class GuiDocument; + +class GuiDocumentListModel : public QStringListModel { +public: + GuiDocumentListModel(GuiApplication* app); + + QVariant data(const QModelIndex& index, int role) const override; + +private: + void appendGuiDocument(const GuiDocument* guiDoc); + void removeGuiDocument(const GuiDocument* guiDoc); + + std::vector m_vecGuiDocument; +}; + +} // namespace Mayo diff --git a/src/gui/qtgui_utils.cpp b/src/gui/qtgui_utils.cpp new file mode 100644 index 00000000..598e7b9a --- /dev/null +++ b/src/gui/qtgui_utils.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "qtgui_utils.h" +#include "../base/math_utils.h" +#include "../3rdparty/gsl/gsl_assert" +#include + +namespace Mayo { + +namespace { + +constexpr bool isLessOrEqual(double lhs, double rhs) { + return lhs < rhs || qFuzzyCompare(lhs, rhs); +} + +// Is 'v' inside ['start', 'end'] ? +constexpr bool isInRange(double v, double start, double end) { + return isLessOrEqual(start, v) && isLessOrEqual(v, end); +} + +} // namespace + +QColor QtGuiUtils::lerp(const QColor& a, const QColor& b, double t) +{ + Expects(isInRange(t, 0, 1)); + return QColor( + MathUtils::lerp(a.red(), b.red(), t), + MathUtils::lerp(a.green(), b.green(), t), + MathUtils::lerp(a.blue(), b.blue(), t), + MathUtils::lerp(a.alpha(), b.alpha(), t)); +} + +QColor QtGuiUtils::linearColorAt(const QGradient& gradient, double t) +{ + Expects(gradient.type() == QGradient::LinearGradient); + Expects(isInRange(t, 0, 1)); + const QGradientStops stops = gradient.stops(); + if (qFuzzyIsNull(t)) + return stops.front().second; + + auto itLower = + std::lower_bound( + stops.cbegin(), + stops.cend(), + QGradientStop(t, QColor()), + [](const QGradientStop& lhs, const QGradientStop& rhs) { + return lhs.first < rhs.first; + }); + if (itLower != stops.cbegin() && itLower != stops.cend()) { + const int i = (itLower - stops.cbegin()) - 1; + const double tMapped = + MathUtils::mappedValue( + t, stops.at(i).first, stops.at(i + 1).first, 0, 1); + return lerp(stops.at(i).second, stops.at(i + 1).second, tMapped); + } + + return !stops.empty() ? stops.back().second : QColor(); +} + +QGradient QtGuiUtils::gradientEndsAdded(const QGradient& gradient) +{ + QGradient newGradient = gradient; + const QGradientStops stops = gradient.stops(); + if (!qFuzzyIsNull(stops.front().first)) + newGradient.setColorAt(0., stops.front().second); + + if (!qFuzzyCompare(stops.back().first, 1.)) + newGradient.setColorAt(1., stops.back().second); + + return newGradient; +} + +QGradient QtGuiUtils::subGradient(const QGradient& gradient, double t1, double t2) +{ + if (qFuzzyCompare(t1, 0) && qFuzzyCompare(t2, 1)) + return gradient; + + Expects(isLessOrEqual(t1, t2)); + Expects(gradient.type() == QGradient::LinearGradient); + QGradientStops subStops; + subStops.push_back({ 0., linearColorAt(gradient, t1) }); + const QGradientStops stops = gradient.stops(); + for (const QGradientStop& stop : stops) { + const double t = stop.first; + const QColor& color = stop.second; + if (t < t1) + continue; + + if (t > t2) + break; + + const double tMapped = MathUtils::mappedValue(t, t1, t2, 0, 1); + subStops.push_back({ tMapped, color }); + } + + subStops.push_back({ 1., linearColorAt(gradient, t2) }); + QLinearGradient subGradient(0, 0, 1, 0); + subGradient.setStops(subStops); + return subGradient; +} + +} // namespace Mayo diff --git a/src/gui/qtgui_utils.h b/src/gui/qtgui_utils.h new file mode 100644 index 00000000..4e063a73 --- /dev/null +++ b/src/gui/qtgui_utils.h @@ -0,0 +1,29 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +class QtGuiUtils { +public: + // Returns linear interpolated color between 'a' and 'b' at parameter 't' + static QColor lerp(const QColor& a, const QColor& b, double t); + + // Returns color at normalized pos 't' from linear gradient + // Note: assumes that gradient stops array contains keys 0 and 1 + static QColor linearColorAt(const QGradient& gradient, double t); + + // Returns version of 'gradient' having stop keys 0 and 1 + static QGradient gradientEndsAdded(const QGradient& gradient); + + static QGradient subGradient(const QGradient& gradient, double t1, double t2); +}; + +} // namespace Mayo diff --git a/src/gui_application.cpp b/src/gui_application.cpp deleted file mode 100644 index 4f9df6d6..00000000 --- a/src/gui_application.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "gui_application.h" - -#include "application.h" -#include "document.h" -#include "gui_document.h" - -namespace Mayo { - -GuiApplication::GuiApplication(QObject *parent) - : QObject(parent) -{ - auto app = Application::instance(); - QObject::connect( - app, &Application::documentAdded, - this, &GuiApplication::onDocumentAdded); - QObject::connect( - app, &Application::documentErased, - this, &GuiApplication::onDocumentErased); -} - -GuiDocument *GuiApplication::findGuiDocument(const Document *doc) const -{ - auto itFound = std::find_if( - m_vecDocGuiDoc.cbegin(), - m_vecDocGuiDoc.cend(), - [=](const Doc_GuiDoc& pair) { return pair.doc == doc; }); - return itFound != m_vecDocGuiDoc.cend() ? itFound->guiDoc : nullptr; -} - -void GuiApplication::onDocumentAdded(Document *doc) -{ - const Doc_GuiDoc pair = { doc, new GuiDocument(doc) }; // TODO: set container widget - m_vecDocGuiDoc.emplace_back(std::move(pair)); - emit guiDocumentAdded(pair.guiDoc); -} - -void GuiApplication::onDocumentErased(const Document *doc) -{ - auto itFound = std::find_if( - m_vecDocGuiDoc.begin(), - m_vecDocGuiDoc.end(), - [=](const Doc_GuiDoc& pair) { return pair.doc == doc; }); - if (itFound != m_vecDocGuiDoc.end()) { - const GuiDocument* guiDoc = itFound->guiDoc; - delete guiDoc; - m_vecDocGuiDoc.erase(itFound); - emit guiDocumentErased(guiDoc); - } -} - -} // namespace Mayo diff --git a/src/gui_application.h b/src/gui_application.h deleted file mode 100644 index 539bc171..00000000 --- a/src/gui_application.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include - -namespace Mayo { - -class Document; -class DocumentItem; -class GuiDocument; - -class GuiApplication : public QObject -{ - Q_OBJECT - -public: - GuiApplication(QObject* parent = nullptr); - - GuiDocument* findGuiDocument(const Document* doc) const; - -signals: - void guiDocumentAdded(GuiDocument* guiDoc); - void guiDocumentErased(const GuiDocument* guiDoc); - -protected: - void onDocumentAdded(Document* doc); - void onDocumentErased(const Document* doc); - -private: - struct Doc_GuiDoc { - Document* doc; - GuiDocument* guiDoc; - }; - - std::vector m_vecDocGuiDoc; -}; - -} // namespace Mayo diff --git a/src/gui_document.cpp b/src/gui_document.cpp deleted file mode 100644 index b158a4ed..00000000 --- a/src/gui_document.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "gui_document.h" - -#include "document.h" -#include "document_item.h" -#include "gpx_document_item.h" -#include "widget_gui_document_view3d.h" -#include "widget_occ_view.h" - -#include "gpx_brep_shape_item.h" -#include "gpx_stl_mesh_item.h" -#include "brep_shape_item.h" -#include "stl_mesh_item.h" - -#include -#include -#include -#if OCC_VERSION_HEX <= 0x60701 -# include -#else -# include -#endif -#include -#include -#include - -#include - -namespace Mayo { - -namespace Internal { - -template struct ItemTraits { }; -template<> struct ItemTraits { typedef GpxBRepShapeItem GpxType; }; -template<> struct ItemTraits { typedef GpxStlMeshItem GpxType; }; - -template -bool createGpxIfItemOfType(GpxDocumentItem** gpx, DocumentItem* item) -{ - if (*gpx == nullptr && sameType(item)) { - typedef typename ItemTraits::GpxType GpxType; - *gpx = new GpxType(static_cast(item)); - return true; - } - return false; -} - -static GpxDocumentItem* createGpxForItem(DocumentItem* item) -{ - GpxDocumentItem* gpx = nullptr; - createGpxIfItemOfType(&gpx, item); - createGpxIfItemOfType(&gpx, item); - return gpx; -} - -static Handle_V3d_Viewer createOccViewer() -{ - // Create the graphic driver - Handle_Graphic3d_GraphicDriver gpxDriver; - - Handle_Aspect_DisplayConnection dispConnection; -#if (!defined(Q_OS_WIN32) && (!defined(Q_OS_MAC) || defined(MACOSX_USE_GLX))) - dispConnection = new Aspect_DisplayConnection(std::getenv("DISPLAY")); -#endif - -#if OCC_VERSION_HEX >= 0x060800 - if (dispConnection.IsNull()) - dispConnection = new Aspect_DisplayConnection; - gpxDriver = new OpenGl_GraphicDriver(dispConnection); -#else - gpxDriver = Graphic3d::InitGraphicDriver(dispConnection); -#endif - - // Create the named OCC 3d viewer - Handle_V3d_Viewer viewer = new V3d_Viewer( - gpxDriver, reinterpret_cast("Viewer3d")); - - // Configure the OCC 3d viewer - viewer->SetDefaultViewSize(1000.); - viewer->SetDefaultViewProj(V3d_XposYnegZpos); - viewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK); - viewer->SetDefaultVisualization(V3d_ZBUFFER); - viewer->SetDefaultShadingModel(V3d_GOURAUD); - viewer->SetUpdateMode(V3d_WAIT); - viewer->SetDefaultSurfaceDetail(V3d_TEX_NONE); - - // Initialize the OCC 3d viewer -#if OCC_VERSION_HEX < 0x60700 - viewer->Init(); -#endif - viewer->SetDefaultLights(); - viewer->SetLightOn(); - - return viewer; -} - -void eraseGpxObjectFromContext( - const Handle_AIS_InteractiveObject &object, - const Handle_AIS_InteractiveContext &context) -{ - if (!object.IsNull()) { - context->Erase(object, Standard_False); - context->Remove(object, Standard_False); -#if OCC_VERSION_HEX < 0x060900 - context->Clear(object, Standard_False); // Note: Remove() can be used too -#else - context->ClearPrs(object, 0, Standard_False); -#endif - context->SelectionManager()->Remove(object); - - Handle_AIS_InteractiveObject objectHCopy = object; - while (!objectHCopy.IsNull()) - objectHCopy.Nullify(); - } -} - -} // namespace Internal - -GuiDocument::GuiDocument(Document *doc) - : m_document(doc), - m_v3dViewer(Internal::createOccViewer()), - m_aisContext(new AIS_InteractiveContext(m_v3dViewer)), - m_guiDocView3d(new WidgetGuiDocumentView3d(this)) -{ - assert(doc != nullptr); - - m_guiDocView3d->widgetOccView()->setOccV3dViewer(m_v3dViewer); - - QObject::connect( - doc, &Document::itemAdded, this, &GuiDocument::onItemAdded); - QObject::connect( - doc, &Document::itemErased, this, &GuiDocument::onItemErased); -} - -Document *GuiDocument::document() const -{ - return m_document; -} - -WidgetGuiDocumentView3d *GuiDocument::widgetView3d() const -{ - return m_guiDocView3d; -} - -GpxDocumentItem *GuiDocument::findItemGpx(const DocumentItem *item) const -{ - auto itFound = std::find_if( - m_vecDocItemGpx.cbegin(), - m_vecDocItemGpx.cend(), - [=](const DocumentItem_Gpx& pair) { return pair.item == item; }); - return itFound != m_vecDocItemGpx.cend() ? itFound->gpx : nullptr; -} - -void GuiDocument::onItemAdded(DocumentItem *item) -{ - const DocumentItem_Gpx pair = { item, Internal::createGpxForItem(item) }; - m_vecDocItemGpx.emplace_back(std::move(pair)); - m_aisContext->Display(pair.gpx->handleGpxObject()); - m_guiDocView3d->widgetOccView()->fitAll(); -} - -void GuiDocument::onItemErased(const DocumentItem *item) -{ - auto itFound = std::find_if( - m_vecDocItemGpx.begin(), - m_vecDocItemGpx.end(), - [=](const DocumentItem_Gpx& pair) { return pair.item == item; }); - if (itFound != m_vecDocItemGpx.end()) { - Internal::eraseGpxObjectFromContext( - itFound->gpx->handleGpxObject(), m_aisContext); - delete itFound->gpx; - m_vecDocItemGpx.erase(itFound); - } -} - -} // namespace Mayo diff --git a/src/gui_document.h b/src/gui_document.h deleted file mode 100644 index 13f1e5eb..00000000 --- a/src/gui_document.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -namespace Mayo { - -class Document; -class DocumentItem; -class GpxDocumentItem; -class WidgetGuiDocumentView3d; - -class GuiDocument : public QObject -{ -public: - GuiDocument(Document* doc); - - Document* document() const; - WidgetGuiDocumentView3d* widgetView3d() const; - GpxDocumentItem* findItemGpx(const DocumentItem* item) const; - -private: - void onItemAdded(DocumentItem* item); - void onItemErased(const DocumentItem* item); - - struct DocumentItem_Gpx { - DocumentItem* item; - GpxDocumentItem* gpx; - }; - - Document* m_document = nullptr; - Handle_V3d_Viewer m_v3dViewer; - Handle_AIS_InteractiveContext m_aisContext; - WidgetGuiDocumentView3d* m_guiDocView3d = nullptr; - std::vector m_vecDocItemGpx; -}; - -} // namespace Mayo diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index f7b84702..00000000 --- a/src/main.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "gui_application.h" -#include "mainwindow.h" -#include - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - QApplication::setOrganizationName("Fougue"); - QApplication::setOrganizationDomain("www.fougue.pro"); - QApplication::setApplicationName("Mayo"); - QApplication::setApplicationVersion("0.1"); - - Mayo::GuiApplication guiApp; - Mayo::MainWindow w(&guiApp); - w.show(); - - return app.exec(); -} diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp deleted file mode 100644 index c9a3fee9..00000000 --- a/src/mainwindow.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "mainwindow.h" -#include "ui_mainwindow.h" - -#include "application.h" -#include "dialog_about.h" -#include "dialog_export_options.h" -#include "dialog_options.h" -#include "dialog_save_image_view.h" -#include "dialog_task_manager.h" -#include "document.h" -#include "gui_application.h" -#include "gui_document.h" -#include "widget_gui_document_view3d.h" -#include "widget_message_indicator.h" -#include "fougtools/qttools/gui/qwidget_utils.h" -#include "fougtools/qttools/task/manager.h" -#include "fougtools/qttools/task/runner_qthreadpool.h" - -#include -#include -#include -#include -#include - -namespace Mayo { - -namespace Internal { - -static const QLatin1String keyLastOpenDir("GUI/MainWindow_lastOpenDir"); -static const QLatin1String keyLastSelectedFilter("GUI/MainWindow_lastSelectedFilter"); - -static Application::PartFormat partFormatFromFilter(const QString& filter) -{ - const auto itFormatFound = - std::find_if(Application::partFormats().cbegin(), - Application::partFormats().cend(), - [=](Application::PartFormat format) { - return filter == Application::partFormatFilter(format); - } ); - return itFormatFound != Application::partFormats().cend() ? - *itFormatFound : - Application::PartFormat::Unknown; -} - -struct ImportExportSettings -{ - QString openDir; - QString selectedFilter; - - static ImportExportSettings load() - { - QSettings settings; - return { settings.value(keyLastOpenDir, QString()).toString(), - settings.value(keyLastSelectedFilter, QString()).toString() }; - } - - static void save(const ImportExportSettings& sets) - { - QSettings settings; - settings.setValue(keyLastOpenDir, sets.openDir); - settings.setValue(keyLastSelectedFilter, sets.selectedFilter); - } -}; - -struct OpenFileNames { - QStringList listFilepath; - ImportExportSettings lastIoSettings; - Application::PartFormat selectedFormat; - - static OpenFileNames get(QWidget* parentWidget) - { - OpenFileNames result; - result.selectedFormat = Application::PartFormat::Unknown; - result.lastIoSettings = ImportExportSettings::load(); - QStringList listPartFormatFilter = Application::partFormatFilters(); - const QString allFilesFilter = Application::tr("All files(*.*)"); - listPartFormatFilter.append(allFilesFilter); - result.listFilepath = - QFileDialog::getOpenFileNames( - parentWidget, - Application::tr("Select Part File"), - result.lastIoSettings.openDir, - listPartFormatFilter.join(QLatin1String(";;")), - &result.lastIoSettings.selectedFilter); - if (!result.listFilepath.isEmpty()) { - result.lastIoSettings.openDir = - QFileInfo(result.listFilepath.front()).canonicalPath(); - result.selectedFormat = - result.lastIoSettings.selectedFilter != allFilesFilter ? - partFormatFromFilter(result.lastIoSettings.selectedFilter) : - Application::PartFormat::Unknown; - } - return result; - } -}; - -} // namespace Internal - - -MainWindow::MainWindow(GuiApplication *guiApp, QWidget *parent) - : QMainWindow(parent), - m_guiApp(guiApp), - m_ui(new Ui_MainWindow) -{ - m_ui->setupUi(this); - m_ui->widget_DocumentProps->setGuiApplication(guiApp); - m_ui->widget_DocumentProps->editDocumentItems(std::vector()); - - new DialogTaskManager(this); - - QObject::connect( - m_ui->actionNewDoc, &QAction::triggered, - this, &MainWindow::newDoc); - QObject::connect( - m_ui->actionOpen, &QAction::triggered, - this, &MainWindow::openPartInNewDoc); - QObject::connect( - m_ui->actionImport, &QAction::triggered, - this, &MainWindow::importInCurrentDoc); - QObject::connect( - m_ui->actionExportSelectedItems, &QAction::triggered, - this, &MainWindow::exportSelectedItems); - QObject::connect( - m_ui->actionQuit, &QAction::triggered, - this, &MainWindow::quitApp); - QObject::connect( - m_ui->actionSaveImageView, &QAction::triggered, - this, &MainWindow::saveImageView); - QObject::connect( - m_ui->actionOptions, &QAction::triggered, - this, &MainWindow::editOptions); - QObject::connect( - m_ui->actionReportBug, &QAction::triggered, - this, &MainWindow::reportbug); - QObject::connect( - m_ui->actionAboutMayo, &QAction::triggered, - this, &MainWindow::aboutMayo); - QObject::connect( - m_ui->tab_GuiDocuments, &QTabWidget::tabCloseRequested, - this, &MainWindow::onTabCloseRequested); - QObject::connect( - this, &MainWindow::operationFinished, - this, &MainWindow::onOperationFinished); - - QObject::connect( - guiApp, &GuiApplication::guiDocumentAdded, - this, &MainWindow::onGuiDocumentAdded); - QObject::connect( - m_ui->widget_ApplicationTree, - &WidgetApplicationTree::selectionChanged, - this, - &MainWindow::onApplicationTreeWidgetSelectionChanged); - - this->updateControlsActivation(); -} - -MainWindow::~MainWindow() -{ - delete m_ui; -} - -void MainWindow::newDoc() -{ - Application::instance()->addDocument(); -} - -void MainWindow::openPartInNewDoc() -{ - this->foreachOpenFileName( - [=](Application::PartFormat format, QString filepath) { - Document* doc = Application::instance()->addDocument( - QFileInfo(filepath).fileName()); - this->runImportTask(doc, format, filepath); - }); -} - -void MainWindow::importInCurrentDoc() -{ - auto docView3d = - qobject_cast( - m_ui->tab_GuiDocuments->currentWidget()); - if (docView3d != nullptr) { - Document* doc = docView3d->guiDocument()->document(); - this->foreachOpenFileName( - [=](Application::PartFormat format, QString filepath) { - this->runImportTask(doc, format, filepath); - }); - } -} - -void MainWindow::runImportTask( - Document* doc, Application::PartFormat format, const QString& filepath) -{ - qttask::BaseRunner* task = - qttask::Manager::globalInstance()->newTask(); - task->run([=]{ - QTime chrono; - chrono.start(); - const Application::IoResult result = - Application::instance()->importInDocument( - doc, format, filepath, &task->progress()); - QString msg; - if (result.ok) { - msg = tr("Import time '%1': %2ms") - .arg(QFileInfo(filepath).fileName()) - .arg(chrono.elapsed()); - } else { - msg = tr("Failed to import part:\n %1\nError: %2") - .arg(filepath).arg(result.errorText); - } - emit operationFinished(result.ok, msg); - }); -} - -void MainWindow::exportSelectedItems() -{ - auto lastSettings = Internal::ImportExportSettings::load(); - const QString filepath = - QFileDialog::getSaveFileName( - this, - tr("Select Output File"), - lastSettings.openDir, - Application::partFormatFilters().join(QLatin1String(";;")), - &lastSettings.selectedFilter); - if (!filepath.isEmpty()) { - lastSettings.openDir = QFileInfo(filepath).canonicalPath(); - const Application::PartFormat format = - Internal::partFormatFromFilter(lastSettings.selectedFilter); - const std::vector vecDocItem = - m_ui->widget_ApplicationTree->selectedDocumentItems(); - if (Application::hasExportOptionsForFormat(format)) { - auto dlg = new DialogExportOptions(this); - dlg->setPartFormat(format); - QObject::connect( - dlg, &QDialog::accepted, - [=]{ - this->runExportTask( - vecDocItem, format, dlg->currentExportOptions(), filepath); - Internal::ImportExportSettings::save(lastSettings); - }); - qtgui::QWidgetUtils::asyncDialogExec(dlg); - } - else { - this->runExportTask( - vecDocItem, format, Application::ExportOptions(), filepath); - Internal::ImportExportSettings::save(lastSettings); - } - } -} - -void MainWindow::quitApp() -{ - QApplication::quit(); -} - -void MainWindow::editOptions() -{ - auto dlg = new DialogOptions(this); - qtgui::QWidgetUtils::asyncDialogExec(dlg); -} - -void MainWindow::saveImageView() -{ - auto docView3d = - qobject_cast( - m_ui->tab_GuiDocuments->currentWidget()); - auto dlg = new DialogSaveImageView(docView3d->widgetOccView()); - qtgui::QWidgetUtils::asyncDialogExec(dlg); -} - -void MainWindow::aboutMayo() -{ - auto dlg = new DialogAbout(this); - qtgui::QWidgetUtils::asyncDialogExec(dlg); -} - -void MainWindow::reportbug() -{ - QDesktopServices::openUrl( - QUrl(QStringLiteral("https://github.com/fougue/mayo/issues"))); -} - -void MainWindow::onGuiDocumentAdded(GuiDocument *guiDoc) -{ - m_ui->tab_GuiDocuments->addTab( - guiDoc->widgetView3d(), guiDoc->document()->label()); - m_ui->tab_GuiDocuments->setCurrentWidget(guiDoc->widgetView3d()); - this->updateControlsActivation(); -} - -void MainWindow::onApplicationTreeWidgetSelectionChanged() -{ - m_ui->widget_DocumentProps->editDocumentItems( - m_ui->widget_ApplicationTree->selectedDocumentItems()); -} - -void MainWindow::onOperationFinished(bool ok, const QString &msg) -{ - if (ok) - WidgetMessageIndicator::showMessage(msg, this); - else - qtgui::QWidgetUtils::asyncMsgBoxCritical(this, tr("Error"), msg); -} - -void MainWindow::onTabCloseRequested(int tabIndex) -{ - QWidget* tab = m_ui->tab_GuiDocuments->widget(tabIndex); - auto docView3d = qobject_cast(tab); - Application::instance()->eraseDocument(docView3d->guiDocument()->document()); - m_ui->tab_GuiDocuments->removeTab(tabIndex); - this->updateControlsActivation(); -} - -void MainWindow::foreachOpenFileName( - std::function&& func) -{ - const auto resFileNames = Internal::OpenFileNames::get(this); - if (!resFileNames.listFilepath.isEmpty()) { - for (const QString& filepath : resFileNames.listFilepath) { - const Application::PartFormat fileFormat = - resFileNames.selectedFormat != Application::PartFormat::Unknown ? - resFileNames.selectedFormat : - Application::findPartFormat(filepath); - if (fileFormat != Application::PartFormat::Unknown) { - func(fileFormat, filepath); - } - else { - qtgui::QWidgetUtils::asyncMsgBoxCritical( - this, - tr("Error"), - tr("'%1'\nUnknown file format").arg(filepath)); - } - } - Internal::ImportExportSettings::save(resFileNames.lastIoSettings); - } -} - -void MainWindow::runExportTask( - const std::vector& docItems, - Application::PartFormat format, - const Application::ExportOptions& opts, - const QString& filepath) -{ - qttask::BaseRunner* task = - qttask::Manager::globalInstance()->newTask(); - task->run([=]{ - QTime chrono; - chrono.start(); - const Application::IoResult result = - Application::instance()->exportDocumentItems( - docItems, format, opts, filepath, &task->progress()); - QString msg; - if (result.ok) { - msg = tr("Export time '%1': %2ms") - .arg(QFileInfo(filepath).fileName()) - .arg(chrono.elapsed()); - } else { - msg = tr("Failed to export part:\n %1\nError: %2") - .arg(filepath).arg(result.errorText); - } - emit operationFinished(result.ok, msg); - }); -} - -void MainWindow::updateControlsActivation() -{ - const bool appDocumentsEmpty = Application::instance()->documents().empty(); - m_ui->actionImport->setEnabled(!appDocumentsEmpty); - m_ui->actionSaveImageView->setEnabled(!appDocumentsEmpty); -} - -} // namespace Mayo diff --git a/src/mainwindow.h b/src/mainwindow.h deleted file mode 100644 index 6ca20f97..00000000 --- a/src/mainwindow.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "application.h" -#include -#include - -namespace Mayo { - -class Document; -class GuiApplication; -class GuiDocument; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(GuiApplication* guiApp, QWidget* parent = nullptr); - ~MainWindow(); - -signals: - void operationFinished(bool ok, const QString& msg); - -private: - void newDoc(); - void openPartInNewDoc(); - void importInCurrentDoc(); - void exportSelectedItems(); - void quitApp(); - void editOptions(); - void saveImageView(); - void aboutMayo(); - void reportbug(); - - void onGuiDocumentAdded(GuiDocument* guiDoc); - void onApplicationTreeWidgetSelectionChanged(); - void onOperationFinished(bool ok, const QString& msg); - void onTabCloseRequested(int tabIndex); - - void foreachOpenFileName( - std::function&& func); - void runImportTask( - Document *doc, - Application::PartFormat format, - const QString &filepath); - void runExportTask( - const std::vector& docItems, - Application::PartFormat format, - const Application::ExportOptions& opts, - const QString& filepath); - void updateControlsActivation(); - - GuiApplication* m_guiApp = nullptr; - class Ui_MainWindow* m_ui = nullptr; -}; - -} // namespace Mayo diff --git a/src/mainwindow.ui b/src/mainwindow.ui deleted file mode 100644 index 93c05799..00000000 --- a/src/mainwindow.ui +++ /dev/null @@ -1,177 +0,0 @@ - - - Mayo::MainWindow - - - - 0 - 0 - 707 - 649 - - - - Mayo - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Horizontal - - - - Qt::Vertical - - - - - - - - 2 - 0 - - - - -1 - - - true - - - - - - - - - - 0 - 0 - 707 - 21 - - - - - &File - - - - - - - - - - - - &Help - - - - - - - - &Tools - - - - - - - - - - - - - New - - - Ctrl+N - - - - - Import - - - - - Quit - - - - - Open - - - Ctrl+O - - - - - About Mayo - - - - - Report Bug - - - - - Options - - - - - - :/images/camera_photo.png:/images/camera_photo.png - - - Save View to Image - - - - - Export selected items - - - - - - - WidgetApplicationTree - QWidget -
widget_application_tree.h
- 1 -
- - WidgetDocumentItemProps - QWidget -
widget_document_item_props.h
- 1 -
-
- - - - -
diff --git a/src/options.cpp b/src/options.cpp deleted file mode 100644 index 2109d519..00000000 --- a/src/options.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "options.h" - -namespace Mayo { - -static const char keyStlIoLibrary[] = "Core/stlIoLibrary"; -static const char keyGmioStlImportType[] = "Core/gmioStlImportType"; -static const char keyBrepShapeDefaultColor[] = "BRepShapeGpx/defaultColor"; -static const char keyBrepShapeDefaultMaterial[] = "BRepShapeGpx/defaultMaterial"; -static const char keyMeshDefaultColor[] = "MeshGpx/defaultColor"; -static const char keyMeshDefaultMaterial[] = "MeshGpx/defaultMaterial"; -static const char keyMeshDefaultShowEdges[] = "MeshGpx/defaultShowEdges"; -static const char keyMeshDefaultShowNodes[] = "MeshGpx/defaultShowNodes"; - -Options *Options::instance() -{ - static Options opts; - return &opts; -} - -Options::StlIoLibrary Options::stlIoLibrary() const -{ - static const int defaultVal = static_cast(StlIoLibrary::Gmio); - const int stlIoLib = m_settings.value(keyStlIoLibrary, defaultVal).toInt(); - return static_cast(stlIoLib); -} - -void Options::setStlIoLibrary(Options::StlIoLibrary lib) -{ - m_settings.setValue(keyStlIoLibrary, static_cast(lib)); -} - -Options::GmioStlImportType Options::gmioStlImportType() const -{ - static const int defaultVal = - static_cast(GmioStlImportType::OccStlMesh); - const int gmioStlImpType = - m_settings.value(keyGmioStlImportType, defaultVal).toInt(); - return static_cast(gmioStlImpType); -} - -void Options::setGmioStlImportType(Options::GmioStlImportType imp) -{ - m_settings.setValue(keyGmioStlImportType, static_cast(imp)); -} - -QColor Options::brepShapeDefaultColor() const -{ - static const QColor defaultColor(Qt::gray); - return m_settings.value( - keyBrepShapeDefaultColor, defaultColor).value(); -} - -void Options::setBrepShapeDefaultColor(const QColor &color) -{ - m_settings.setValue(keyBrepShapeDefaultColor, color); -} - -Graphic3d_NameOfMaterial Options::brepShapeDefaultMaterial() const -{ - static const int defaultMat = Graphic3d_NOM_PLASTIC; - const int mat = - m_settings.value(keyBrepShapeDefaultMaterial, defaultMat).toInt(); - return static_cast(mat); -} - -void Options::setBrepShapeDefaultMaterial(Graphic3d_NameOfMaterial material) -{ - m_settings.setValue(keyBrepShapeDefaultMaterial, static_cast(material)); -} - -QColor Options::meshDefaultColor() const -{ - static const QColor defaultColor(Qt::gray); - return m_settings.value(keyMeshDefaultColor, defaultColor).value(); -} - -void Options::setMeshDefaultColor(const QColor &color) -{ - m_settings.setValue(keyMeshDefaultColor, color); -} - -Graphic3d_NameOfMaterial Options::meshDefaultMaterial() const -{ - static const int defaultMat = Graphic3d_NOM_PLASTIC; - const int mat = - m_settings.value(keyMeshDefaultMaterial, defaultMat).toInt(); - return static_cast(mat); -} - -void Options::setMeshDefaultMaterial(Graphic3d_NameOfMaterial material) -{ - m_settings.setValue(keyMeshDefaultMaterial, static_cast(material)); -} - -bool Options::meshDefaultShowEdges() const -{ - return m_settings.value(keyMeshDefaultShowEdges, false).toBool(); -} - -void Options::setMeshDefaultShowEdges(bool on) -{ - m_settings.setValue(keyMeshDefaultShowEdges, on); -} - -bool Options::meshDefaultShowNodes() const -{ - return m_settings.value(keyMeshDefaultShowNodes, false).toBool(); -} - -void Options::setMeshDefaultShowNodes(bool on) -{ - m_settings.setValue(keyMeshDefaultShowNodes, on); -} - -} // namespace Mayo diff --git a/src/options.h b/src/options.h deleted file mode 100644 index c67ca309..00000000 --- a/src/options.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include -#include - -namespace Mayo { - -class Options -{ -public: - enum class StlIoLibrary { - Gmio, - OpenCascade - }; - enum class GmioStlImportType { - OccStlMesh, - OccPolyTriShape - }; - - static Options* instance(); - - StlIoLibrary stlIoLibrary() const; - void setStlIoLibrary(StlIoLibrary lib); - - GmioStlImportType gmioStlImportType() const; - void setGmioStlImportType(GmioStlImportType imp); - - // BRep shape graphics - - QColor brepShapeDefaultColor() const; - void setBrepShapeDefaultColor(const QColor& color); - - Graphic3d_NameOfMaterial brepShapeDefaultMaterial() const; - void setBrepShapeDefaultMaterial(Graphic3d_NameOfMaterial material); - - // Mesh graphics - - QColor meshDefaultColor() const; - void setMeshDefaultColor(const QColor& color); - - Graphic3d_NameOfMaterial meshDefaultMaterial() const; - void setMeshDefaultMaterial(Graphic3d_NameOfMaterial material); - - bool meshDefaultShowEdges() const; - void setMeshDefaultShowEdges(bool on); - - bool meshDefaultShowNodes() const; - void setMeshDefaultShowNodes(bool on); - -private: - QSettings m_settings; -}; - -} // namespace Mayo diff --git a/src/property.cpp b/src/property.cpp deleted file mode 100644 index 62761efa..00000000 --- a/src/property.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "property.h" - -#include "property_enumeration.h" -#include - -namespace Mayo { - -const std::vector& PropertyOwner::properties() const -{ - return m_properties; -} - -void PropertyOwner::onPropertyChanged(Property* /*prop*/) -{ } - -void PropertyOwner::blockPropertyChanged(bool on) -{ - m_propertyChangedBlocked = on; -} - -bool PropertyOwner::isPropertyChangedBlocked() const -{ - return m_propertyChangedBlocked; -} - -void PropertyOwner::addProperty(Property* prop) -{ - m_properties.emplace_back(prop); -} - -const QString &Property::label() const -{ - return m_label; -} - -Property::Property(PropertyOwner *owner, const QString &label) - : m_owner(owner), - m_label(label) -{ - m_owner->addProperty(this); -} - -void Property::notifyChanged() -{ - if (!m_owner->isPropertyChangedBlocked()) - m_owner->onPropertyChanged(this); -} - -const char Property::BoolTypeName[] = "Mayo::PropertyBool"; -const char Property::IntTypeName[] = "Mayo::PropertyInt"; -const char Property::DoubleTypeName[] = "Mayo::PropertyDouble"; -const char Property::QByteArrayTypeName[] = "Mayo::PropertyQByteArray"; -const char Property::QStringTypeName[] = "Mayo::PropertyQString"; -const char Property::QDateTimeTypeName[] = "Mayo::PropertyQDateTime"; -const char Property::EnumerationTypeName[] = "Mayo::PropertyEnumeration"; -const char Property::OccColorTypeName[] = "Mayo::PropertyOccColor"; - -PropertyOwner::PropertyChangedBlocker::PropertyChangedBlocker(PropertyOwner *owner) - : m_owner(owner) -{ - m_owner->blockPropertyChanged(true); -} - -PropertyOwner::PropertyChangedBlocker::~PropertyChangedBlocker() -{ - m_owner->blockPropertyChanged(false); -} - -} // namespace Mayo diff --git a/src/property.h b/src/property.h deleted file mode 100644 index 47a1e860..00000000 --- a/src/property.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include - -namespace Mayo { - -class Property; -class PropertyEnumeration; - -class PropertyOwner -{ -public: - const std::vector& properties() const; - -protected: - virtual void onPropertyChanged(Property* prop); - void blockPropertyChanged(bool on); - bool isPropertyChangedBlocked() const; - - void addProperty(Property* prop); - - struct PropertyChangedBlocker { - PropertyChangedBlocker(PropertyOwner* owner); - ~PropertyChangedBlocker(); - PropertyOwner* const m_owner; - }; - -private: - friend class Property; - friend struct PropertyChangedBlocker; - std::vector m_properties; - bool m_propertyChangedBlocked = false; -}; - -#define Mayo_PropertyChangedBlocker(owner) \ - PropertyChangedBlocker __Mayo_PropertyChangedBlocker(owner); \ - Q_UNUSED(__Mayo_PropertyChangedBlocker); - -class Property -{ -public: - Property(PropertyOwner* owner, const QString& label); - Property() = delete; - Property(const Property&) = delete; - Property(Property&&) = delete; - Property& operator=(const Property&) = delete; - Property& operator=(Property&&) = delete; - - const QString& label() const; - - virtual const char* dynTypeName() const = 0; - - static const char BoolTypeName[]; - static const char IntTypeName[]; - static const char DoubleTypeName[]; - static const char QByteArrayTypeName[]; - static const char QStringTypeName[]; - static const char QDateTimeTypeName[]; - static const char EnumerationTypeName[]; - static const char OccColorTypeName[]; - -protected: - void notifyChanged(); - -private: - PropertyOwner* const m_owner = nullptr; - const QString m_label; -}; - -} // namespace Mayo diff --git a/src/property_builtins.h b/src/property_builtins.h deleted file mode 100644 index 09f08be5..00000000 --- a/src/property_builtins.h +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "property.h" -#include -#include -#include - -namespace Mayo { - -template struct PropertyDefault -{ static T initValue() { return T(); } }; - -template<> struct PropertyDefault -{ static bool initValue() { return false; } }; - -template<> struct PropertyDefault -{ static int initValue() { return 0; } }; - -template<> struct PropertyDefault -{ static double initValue() { return 0.; } }; - -template -class GenericProperty : public Property -{ -public: - GenericProperty(PropertyOwner* owner, const QString& label); - - const T& value() const; - void setValue(const T& val); - - const char* dynTypeName() const override; - -protected: - T m_value = PropertyDefault::initValue(); -}; - -template -class PropertyScalarConstraints -{ - static_assert(std::is_scalar::value, "Requires scalar type"); - -public: - PropertyScalarConstraints() = default; - PropertyScalarConstraints(T minimum, T maximum, T singleStep); - - bool constraintsEnabled() const; - void setConstraintsEnabled(bool on); - - T minimum() const; - void setMinimum(T val); - - T maximum() const; - void setMaximum(T val); - - void setRange(T minVal, T maxVal); - - T singleStep() const; - void setSingleStep(T step); - -private: - T m_minimum; - T m_maximum; - T m_singleStep; - bool m_constraintsEnabled = false; -}; - -template -class GenericScalarProperty : - public GenericProperty, - public PropertyScalarConstraints -{ -public: - GenericScalarProperty(PropertyOwner* owner, const QString& label); - GenericScalarProperty( - PropertyOwner* owner, const QString& label, - T minimum, T maximum, T singleStep); -}; - -typedef GenericProperty PropertyBool; -typedef GenericScalarProperty PropertyInt; -typedef GenericScalarProperty PropertyDouble; -typedef GenericProperty PropertyQByteArray; -typedef GenericProperty PropertyQString; -typedef GenericProperty PropertyQDateTime; -typedef GenericProperty PropertyOccColor; - - - -// -- -// -- Implementation -// -- - -template -GenericProperty::GenericProperty( - PropertyOwner* owner, const QString& label) - : Property(owner, label) -{ } - -template -const T& GenericProperty::value() const -{ return m_value; } - -template -void GenericProperty::setValue(const T& val) -{ - m_value = val; - this->notifyChanged(); -} - -template -const char* GenericProperty::dynTypeName() const -{ return TYPENAME_STR; } - -template -PropertyScalarConstraints::PropertyScalarConstraints( - T minimum, T maximum, T singleStep) - : m_minimum(minimum), - m_maximum(maximum), - m_singleStep(singleStep), - m_constraintsEnabled(true) -{ } - -template bool PropertyScalarConstraints::constraintsEnabled() const -{ return m_constraintsEnabled; } - -template void PropertyScalarConstraints::setConstraintsEnabled(bool on) -{ m_constraintsEnabled = on; } - -template T PropertyScalarConstraints::minimum() const -{ return m_minimum; } - -template void PropertyScalarConstraints::setMinimum(T val) -{ m_minimum = val; } - -template T PropertyScalarConstraints::maximum() const -{ return m_maximum; } - -template void PropertyScalarConstraints::setMaximum(T val) -{ m_maximum = val; } - -template -void PropertyScalarConstraints::setRange(T minVal, T maxVal) -{ - this->setMinimum(minVal); - this->setMaximum(maxVal); -} - -template T PropertyScalarConstraints::singleStep() const -{ return m_singleStep; } - -template void PropertyScalarConstraints::setSingleStep(T step) -{ m_singleStep = step; } - -template -GenericScalarProperty::GenericScalarProperty( - PropertyOwner* owner, const QString& label) - : GenericProperty(owner, label) -{ } - -template -GenericScalarProperty::GenericScalarProperty( - PropertyOwner* owner, const QString& label, - T minimum, T maximum, T singleStep) - : GenericProperty(owner, label), - PropertyScalarConstraints(minimum, maximum, singleStep) -{ } - -} // namespace Mayo diff --git a/src/property_enumeration.cpp b/src/property_enumeration.cpp deleted file mode 100644 index df9518b5..00000000 --- a/src/property_enumeration.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "property_enumeration.h" - -#include "options.h" - -#include -#include - -namespace Mayo { - -void Enumeration::map(Value eval, const QString& str) -{ - const Mapping mapping = { eval, str }; - m_vecMapping.emplace_back(std::move(mapping)); -} - -std::size_t Enumeration::size() const -{ - return m_vecMapping.size(); -} - -std::size_t Enumeration::index(Value eval) const -{ - return this->findCppSql(eval) - m_vecMapping.cbegin(); -} - -Enumeration::Value Enumeration::valueAt(std::size_t i) const -{ - return m_vecMapping.at(i).value; -} - -Enumeration::Value Enumeration::value(const QString& str) const -{ - auto it = std::find_if( - m_vecMapping.cbegin(), - m_vecMapping.cend(), - [&](const Mapping& mapping) { return mapping.string == str; }); - assert(it != m_vecMapping.cend()); - return it->value; -} - -const QString& Enumeration::string(Value eval) const -{ - auto it = this->findCppSql(eval); - assert(it != m_vecMapping.cend()); - return it->string; -} - -Enumeration::Mapping Enumeration::mapping(std::size_t i) const -{ - assert(i < m_vecMapping.size()); - return m_vecMapping.at(i); -} - -const std::vector &Enumeration::mappings() const -{ - return m_vecMapping; -} - -std::vector::const_iterator -Enumeration::findCppSql(Value eval) const -{ - auto it = std::find_if( - m_vecMapping.cbegin(), - m_vecMapping.cend(), - [=] (const Mapping& map) { return map.value == eval; } ); - assert(it != m_vecMapping.cend()); - return it; -} - -PropertyEnumeration::PropertyEnumeration( - PropertyOwner* owner, - const QString& label, - const Enumeration* enumeration) - : Property(owner, label), - m_enumeration(enumeration) -{ - assert(m_enumeration != nullptr); - assert(m_enumeration->size() > 0); - m_value = m_enumeration->valueAt(0); -} - -const Enumeration& PropertyEnumeration::enumeration() const -{ - return *m_enumeration; -} - -const QString& PropertyEnumeration::string() const -{ - return m_enumeration->string(m_value); -} - -Enumeration::Value PropertyEnumeration::value() const -{ - return m_value; -} - -void PropertyEnumeration::setValue(Enumeration::Value v) -{ - // TODO: check v is an enumerated value of m_enumeration - m_value = v; - this->notifyChanged(); -} - -const char* PropertyEnumeration::dynTypeName() const -{ - return Property::EnumerationTypeName; -} - -const Enumeration &enum_Graphic3dNameOfMaterial() -{ - static Enumeration enumeration; - if (enumeration.size() == 0) { - enumeration.map( - Graphic3d_NOM_BRASS, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Brass")); - enumeration.map( - Graphic3d_NOM_BRONZE, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Bronze")); - enumeration.map( - Graphic3d_NOM_COPPER, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Copper")); - enumeration.map( - Graphic3d_NOM_GOLD, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Gold")); - enumeration.map( - Graphic3d_NOM_PEWTER, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Pewter")); - enumeration.map( - Graphic3d_NOM_PLASTER, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Plaster")); - enumeration.map( - Graphic3d_NOM_PLASTIC, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Plastic")); - enumeration.map( - Graphic3d_NOM_SILVER, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Silver")); - enumeration.map( - Graphic3d_NOM_STEEL, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Steel")); - enumeration.map( - Graphic3d_NOM_STONE, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Stone")); - enumeration.map( - Graphic3d_NOM_SHINY_PLASTIC, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Shiny plastic")); - enumeration.map( - Graphic3d_NOM_SATIN, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Satin")); - enumeration.map( - Graphic3d_NOM_METALIZED, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Metalized")); - enumeration.map( - Graphic3d_NOM_NEON_GNC, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Neon gnc")); - enumeration.map( - Graphic3d_NOM_CHROME, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Chrome")); - enumeration.map( - Graphic3d_NOM_ALUMINIUM, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Aluminium")); - enumeration.map( - Graphic3d_NOM_OBSIDIAN, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Obsidian")); - enumeration.map( - Graphic3d_NOM_NEON_PHC, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Neon phc")); - enumeration.map( - Graphic3d_NOM_JADE, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Jade")); - enumeration.map( - Graphic3d_NOM_DEFAULT, - QCoreApplication::translate("Mayo::EnumGpxMaterial", "Default")); - } - return enumeration; -} - -} // namespace Mayo diff --git a/src/property_enumeration.h b/src/property_enumeration.h deleted file mode 100644 index db9553d2..00000000 --- a/src/property_enumeration.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "property.h" -#include -#include - -namespace Mayo { - -class Enumeration -{ -public: - typedef int Value; - struct Mapping { - Value value; - QString string; - }; - - Enumeration() = default; - - void map(int eval, const QString& str); - - std::size_t size() const; - std::size_t index(int eval) const; - - Value valueAt(std::size_t i) const; - Value value(const QString& str) const; - const QString& string(Value eval) const; - - Mapping mapping(std::size_t i) const; - const std::vector& mappings() const; - -private: - std::vector::const_iterator findCppSql(Value eval) const; - - std::vector m_vecMapping; -}; - -class PropertyEnumeration : public Property -{ -public: - PropertyEnumeration( - PropertyOwner* owner, - const QString& label, - const Enumeration* enumeration); - - const Enumeration& enumeration() const; - - const QString& string() const; - Enumeration::Value value() const; - template T valueAs() const; - void setValue(Enumeration::Value v); - - const char* dynTypeName() const override; - -private: - Enumeration::Value m_value; - const Enumeration* m_enumeration; -}; - -const Enumeration& enum_Graphic3dNameOfMaterial(); - - - -// -- Implementation - -template T PropertyEnumeration::valueAs() const -{ return static_cast(m_value); } - -} // namespace Mayo diff --git a/src/qt-solutions/qtpropertybrowser/INSTALL.TXT b/src/qt-solutions/qtpropertybrowser/INSTALL.TXT deleted file mode 100644 index bbb74a9d..00000000 --- a/src/qt-solutions/qtpropertybrowser/INSTALL.TXT +++ /dev/null @@ -1,254 +0,0 @@ -INSTALLATION INSTRUCTIONS - -These instructions refer to the package you are installing as -some-package.tar.gz or some-package.zip. The .zip file is intended for use -on Windows. - -The directory you choose for the installation will be referred to as -your-install-dir. - -Note to Qt Visual Studio Integration users: In the instructions below, -instead of building from command line with nmake, you can use the menu -command 'Qt->Open Solution from .pro file' on the .pro files in the -example and plugin directories, and then build from within Visual -Studio. - -Unpacking and installation --------------------------- - -1. Unpacking the archive (if you have not done so already). - - On Unix and Mac OS X (in a terminal window): - - cd your-install-dir - gunzip some-package.tar.gz - tar xvf some-package.tar - - This creates the subdirectory some-package containing the files. - - On Windows: - - Unpack the .zip archive by right-clicking it in explorer and - choosing "Extract All...". If your version of Windows does not - have zip support, you can use the infozip tools available - from www.info-zip.org. - - If you are using the infozip tools (in a command prompt window): - cd your-install-dir - unzip some-package.zip - -2. Configuring the package. - - The configure script is called "configure" on unix/mac and - "configure.bat" on Windows. It should be run from a command line - after cd'ing to the package directory. - - You can choose whether you want to use the component by including - its source code directly into your project, or build the component - as a dynamic shared library (DLL) that is loaded into the - application at run-time. The latter may be preferable for - technical or licensing (LGPL) reasons. If you want to build a DLL, - run the configure script with the argument "-library". Also see - the note about usage below. - - (Components that are Qt plugins, e.g. styles and image formats, - are by default built as a plugin DLL.) - - The configure script will prompt you in some cases for further - information. Answer these questions and carefully read the license text - before accepting the license conditions. The package cannot be used if - you do not accept the license conditions. - -3. Building the component and examples (when required). - - If a DLL is to be built, or if you would like to build the - examples, next give the commands - - qmake - make [or nmake if your are using Microsoft Visual C++] - - The example program(s) can be found in the directory called - "examples" or "example". - - Components that are Qt plugins, e.g. styles and image formats, are - ready to be used as soon as they are built, so the rest of this - installation instruction can be skipped. - -4. Building the Qt Designer plugin (optional). - - Some of the widget components are provided with plugins for Qt - Designer. To build and install the plugin, cd into the - some-package/plugin directory and give the commands - - qmake - make [or nmake if your are using Microsoft Visual C++] - - Restart Qt Designer to make it load the new widget plugin. - - Note: If you are using the built-in Qt Designer from the Qt Visual - Studio Integration, you will need to manually copy the plugin DLL - file, i.e. copy - %QTDIR%\plugins\designer\some-component.dll - to the Qt Visual Studio Integration plugin path, typically: - C:\Program Files\Trolltech\Qt VS Integration\plugins - - Note: If you for some reason are using a Qt Designer that is built - in debug mode, you will need to build the plugin in debug mode - also. Edit the file plugin.pro in the plugin directory, changing - 'release' to 'debug' in the CONFIG line, before running qmake. - - - -Solutions components are intended to be used directly from the package -directory during development, so there is no 'make install' procedure. - - -Using a component in your project ---------------------------------- - -To use this component in your project, add the following line to the -project's .pro file (or do the equivalent in your IDE): - - include(your-install-dir/some-package/src/some-package.pri) - -This adds the package's sources and headers to the SOURCES and HEADERS -project variables respectively (or, if the component has been -configured as a DLL, it adds that library to the LIBS variable), and -updates INCLUDEPATH to contain the package's src -directory. Additionally, the .pri file may include some dependencies -needed by the package. - -To include a header file from the package in your sources, you can now -simply use: - - #include - -or alternatively, in pre-Qt 4 style: - - #include - -Refer to the documentation to see the classes and headers this -components provides. - - - -Install documentation (optional) --------------------------------- - -The HTML documentation for the package's classes is located in the -your-install-dir/some-package/doc/html/index.html. You can open this -file and read the documentation with any web browser. - -To install the documentation into Qt Assistant (for Qt version 4.4 and -later): - -1. In Assistant, open the Edit->Preferences dialog and choose the - Documentation tab. Click the Add... button and select the file - your-install-dir/some-package/doc/html/some-package.qch - -For Qt versions prior to 4.4, do instead the following: - -1. The directory your-install-dir/some-package/doc/html contains a - file called some-package.dcf. Execute the following commands in a - shell, command prompt or terminal window: - - cd your-install-dir/some-package/doc/html/ - assistant -addContentFile some-package.dcf - -The next time you start Qt Assistant, you can access the package's -documentation. - - -Removing the documentation from assistant ------------------------------------------ - -If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later: - -1. In Assistant, open the Edit->Preferences dialog and choose the - Documentation tab. In the list of Registered Documentation, select - the item com.nokia.qtsolutions.some-package_version, and click - the Remove button. - -For Qt versions prior to 4.4, do instead the following: - -1. The directory your-install-dir/some-package/doc/html contains a - file called some-package.dcf. Execute the following commands in a - shell, command prompt or terminal window: - - cd your-install-dir/some-package/doc/html/ - assistant -removeContentFile some-package.dcf - - - -Using the component as a DLL ----------------------------- - -1. Normal components - - The shared library (DLL) is built and placed in the - some-package/lib directory. It is intended to be used directly - from there during development. When appropriate, both debug and - release versions are built, since the run-time linker will in some - cases refuse to load a debug-built DLL into a release-built - application or vice versa. - - The following steps are taken by default to help the dynamic - linker to locate the DLL at run-time (during development): - - Unix: The some-package.pri file will add linker instructions to - add the some-package/lib directory to the rpath of the - executable. (When distributing, or if your system does not support - rpath, you can copy the shared library to another place that is - searched by the dynamic linker, e.g. the "lib" directory of your - Qt installation.) - - Mac: The full path to the library is hardcoded into the library - itself, from where it is copied into the executable at link time, - and ready by the dynamic linker at run-time. (When distributing, - you will want to edit these hardcoded paths in the same way as for - the Qt DLLs. Refer to the document "Deploying an Application on - Mac OS X" in the Qt Reference Documentation.) - - Windows: the .dll file(s) are copied into the "bin" directory of - your Qt installation. The Qt installation will already have set up - that directory to be searched by the dynamic linker. - - -2. Plugins - - For Qt Solutions plugins (e.g. image formats), both debug and - release versions of the plugin are built by default when - appropriate, since in some cases the release Qt library will not - load a debug plugin, and vice versa. The plugins are automatically - copied into the plugins directory of your Qt installation when - built, so no further setup is required. - - Plugins may also be built statically, i.e. as a library that will be - linked into your application executable, and so will not need to - be redistributed as a separate plugin DLL to end users. Static - building is required if Qt itself is built statically. To do it, - just add "static" to the CONFIG variable in the plugin/plugin.pro - file before building. Refer to the "Static Plugins" section in the - chapter "How to Create Qt Plugins" for explanation of how to use a - static plugin in your application. The source code of the example - program(s) will also typically contain the relevant instructions - as comments. - - - -Uninstalling ------------- - - The following command will remove any fils that have been - automatically placed outside the package directory itself during - installation and building - - make distclean [or nmake if your are using Microsoft Visual C++] - - If Qt Assistant documentation or Qt Designer plugins have been - installed, they can be uninstalled manually, ref. above. - - -Enjoy! :) - -- The Qt Solutions Team. diff --git a/src/qt-solutions/qtpropertybrowser/README.TXT b/src/qt-solutions/qtpropertybrowser/README.TXT deleted file mode 100644 index 148c47b4..00000000 --- a/src/qt-solutions/qtpropertybrowser/README.TXT +++ /dev/null @@ -1,93 +0,0 @@ -Qt Solutions Component: Property Browser - -A property browser framework enabling the user to edit a set of -properties. - -The framework provides a browser widget that displays the given -properties with labels and corresponding editing widgets (e.g. -line edits or comboboxes). The various types of editing widgets -are provided by the framework's editor factories: For each -property type, the framework provides a property manager (e.g. -QtIntPropertyManager and QtStringPropertyManager) which can be -associated with the preferred editor factory (e.g. -QtSpinBoxFactory and QtLineEditFactory). The framework also -provides a variant based property type with corresponding variant -manager and factory. Finally, the framework provides three -ready-made implementations of the browser widget: -QtTreePropertyBrowser, QtButtonPropertyBrowser and -QtGroupBoxPropertyBrowser. - -Version history: - -2.1: - QtTreePropertyBrowser - tooltip of property applied to - first column, while second column shows the value text of property - in its tooltip - - QtAbstractPropertyManager - initializeProperty() and - uninitializeProperty() without const modifier now - - QtTreePropertyBrowser and QtGroupBoxPropertyBrowser - internal - margin set to 0 - - QtProperty - setEnabled() and isEnabled() methods added - - QtTreePropertyBrowser - "rootIsDecorated", "indentation" and - "headerVisible" properties added - - QtProperty - hasValue() method added, useful for group - properties - -2.2: - FocusOut event now filtered out in case of - Qt::ActiveWindowFocusReason reason. In that case editor is not - closed when its sub dialog is executed - - Removed bug in color icon generation - - Decimals attribute added to "double" property type - - PointF, SizeF and RectF types supported - - Proper translation calls for tree property browser - - QtProperty - ensure inserted subproperty is different from - "this" property - - QtBrowserItem class introduced, useful for identifying browser's - gui elements - - Possibility to control expanded state of QtTreePropertyBrowser's - items from code - - QtTreePropertyBrowser - "resizeMode" and "splitterPosition" - properties added - - QtGroupBoxPropertyBrowser - fixed crash in case of deleting the - editor factory and then deleting the manager - - "Decoration" example added - it shows how to add new - responsibilities to the existing managers and editor factories - -2.3: - Various bugfixes and improvements - - QtProperty - setModified() and isModified() methods added - - QtTreePropertyBrowser - disabling an item closes its editor - - KeySequence, Char, Locale and Cursor types supported - - Support for icons in enum type added - - Kerning subproperty exposed in Font type - - New property browser class added - QtButtonPropertyBrowser with - drop down button as a grouping element - -2.4: - Fixed memory leak of QtProperty - - QtTreePropertyBrowser - group items are rendered better - - QtTreePropertyBrowser - propertiesWithoutValueMarked and - alternatingRowColors features added - - QtTreePropertyBrowser - possibility of coloring properties added - - QtTreePropertyBrowser - keyboard navigation improved - - New factories providing popup dialogs added: - QtColorEditorFactory and QtFontEditorFactory - - Single step attribute added to: QtIntPropertyManager and - QtDoublePropertyManager - -2.5: - "Object Controller" example added. It implements a similar - widget to the property editor in QDesigner - - Compile with QT_NO_CURSOR - - Expand root item with single click on the '+' icon - - QtRectPropertyManager and QtRectFPropertyManager - by default - constraint is null rect meaning no constraint is applied - -2.6: - QtGroupPropertyBrowser - don't force the layout to show the - whole labels' contents for read only properties, show tooltips for - them in addition. - - QtTreePropertyBrowser - fixed painting of the editor for color - property type when style sheet is used (QTSOLBUG-64). - - Make it possible to change the style of the checkboxes with a - stylesheet (QTSOLBUG-61). - - Change the minimum size of a combobox so that it can show at - least one character and an icon. - - Make it possible to properly style custom embedded editors (e.g. - the color editor provided with the solution). - diff --git a/src/qt-solutions/qtpropertybrowser/buildlib/buildlib.pro b/src/qt-solutions/qtpropertybrowser/buildlib/buildlib.pro deleted file mode 100644 index 8da3de25..00000000 --- a/src/qt-solutions/qtpropertybrowser/buildlib/buildlib.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE=lib -CONFIG += qt dll qtpropertybrowser-buildlib -mac:CONFIG += absolute_library_soname -win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all -include(../src/qtpropertybrowser.pri) -TARGET = $$QTPROPERTYBROWSER_LIBNAME -DESTDIR = $$QTPROPERTYBROWSER_LIBDIR -win32 { - DLLDESTDIR = $$[QT_INSTALL_BINS] - QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTPROPERTYBROWSER_LIBNAME}.dll -} -target.path = $$DESTDIR -INSTALLS += target diff --git a/src/qt-solutions/qtpropertybrowser/common.pri b/src/qt-solutions/qtpropertybrowser/common.pri deleted file mode 100644 index 8b977f12..00000000 --- a/src/qt-solutions/qtpropertybrowser/common.pri +++ /dev/null @@ -1,6 +0,0 @@ -exists(config.pri):infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtpropertybrowser-uselib -TEMPLATE += fakelib -QTPROPERTYBROWSER_LIBNAME = $$qtLibraryTarget(QtSolutions_PropertyBrowser-head) -TEMPLATE -= fakelib -QTPROPERTYBROWSER_LIBDIR = $$PWD/lib -unix:qtpropertybrowser-uselib:!qtpropertybrowser-buildlib:QMAKE_RPATHDIR += $$QTPROPERTYBROWSER_LIBDIR diff --git a/src/qt-solutions/qtpropertybrowser/configure b/src/qt-solutions/qtpropertybrowser/configure deleted file mode 100644 index 3c4edfff..00000000 --- a/src/qt-solutions/qtpropertybrowser/configure +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -if [ "x$1" != "x" -a "x$1" != "x-library" ]; then - echo "Usage: $0 [-library]" - echo - echo "-library: Build the component as a dynamic library (DLL). Default is to" - echo " include the component source code directly in the application." - echo - exit 0 -fi - -rm -f config.pri -if [ "x$1" = "x-library" ]; then - echo "Configuring to build this component as a dynamic library." - echo "SOLUTIONS_LIBRARY = yes" > config.pri -fi - -echo -echo "This component is now configured." -echo -echo "To build the component library (if requested) and example(s)," -echo "run qmake and your make command." -echo -echo "To remove or reconfigure, run make distclean." -echo diff --git a/src/qt-solutions/qtpropertybrowser/configure.bat b/src/qt-solutions/qtpropertybrowser/configure.bat deleted file mode 100644 index 9bf19870..00000000 --- a/src/qt-solutions/qtpropertybrowser/configure.bat +++ /dev/null @@ -1,80 +0,0 @@ -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:: -:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -:: Contact: http://www.qt-project.org/legal -:: -:: This file is part of the Qt Solutions component. -:: -:: $QT_BEGIN_LICENSE:BSD$ -:: You may use this file under the terms of the BSD license as follows: -:: -:: "Redistribution and use in source and binary forms, with or without -:: modification, are permitted provided that the following conditions are -:: met: -:: * Redistributions of source code must retain the above copyright -:: notice, this list of conditions and the following disclaimer. -:: * Redistributions in binary form must reproduce the above copyright -:: notice, this list of conditions and the following disclaimer in -:: the documentation and/or other materials provided with the -:: distribution. -:: * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -:: of its contributors may be used to endorse or promote products derived -:: from this software without specific prior written permission. -:: -:: -:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -:: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -:: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -:: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -:: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -:: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -:: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -:: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -:: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -:: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -:: -:: $QT_END_LICENSE$ -:: -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - -@echo off - -rem -rem "Main" -rem - -if not "%1"=="" ( - if not "%1"=="-library" ( - call :PrintUsage - goto EOF - ) -) - -if exist config.pri. del config.pri -if "%1"=="-library" ( - echo Configuring to build this component as a dynamic library. - echo SOLUTIONS_LIBRARY = yes > config.pri -) - -echo . -echo This component is now configured. -echo . -echo To build the component library (if requested) and example(s), -echo run qmake and your make or nmake command. -echo . -echo To remove or reconfigure, run make (nmake) distclean. -echo . -goto EOF - -:PrintUsage -echo Usage: configure.bat [-library] -echo . -echo -library: Build the component as a dynamic library (DLL). Default is to -echo include the component source directly in the application. -echo A DLL may be preferable for technical or licensing (LGPL) reasons. -echo . -goto EOF - - -:EOF diff --git a/src/qt-solutions/qtpropertybrowser/qtpropertybrowser.pro b/src/qt-solutions/qtpropertybrowser/qtpropertybrowser.pro deleted file mode 100644 index 2c8a3170..00000000 --- a/src/qt-solutions/qtpropertybrowser/qtpropertybrowser.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE=subdirs -CONFIG += ordered -include(common.pri) -qtpropertybrowser-uselib:SUBDIRS=buildlib -SUBDIRS+=examples diff --git a/src/qt-solutions/qtpropertybrowser/src/QtAbstractEditorFactoryBase b/src/qt-solutions/qtpropertybrowser/src/QtAbstractEditorFactoryBase deleted file mode 100644 index ab4e7104..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtAbstractEditorFactoryBase +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtAbstractPropertyBrowser b/src/qt-solutions/qtpropertybrowser/src/QtAbstractPropertyBrowser deleted file mode 100644 index ab4e7104..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtAbstractPropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtAbstractPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtAbstractPropertyManager deleted file mode 100644 index ab4e7104..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtAbstractPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtBoolPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtBoolPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtBoolPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtBrowserItem b/src/qt-solutions/qtpropertybrowser/src/QtBrowserItem deleted file mode 100644 index ab4e7104..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtBrowserItem +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtButtonPropertyBrowser b/src/qt-solutions/qtpropertybrowser/src/QtButtonPropertyBrowser deleted file mode 100644 index 56e08970..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtButtonPropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qtbuttonpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtCharEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtCharEditorFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtCharEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtCharPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtCharPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtCharPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtCheckBoxFactory b/src/qt-solutions/qtpropertybrowser/src/QtCheckBoxFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtCheckBoxFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtColorEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtColorEditorFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtColorEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtColorPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtColorPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtColorPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtCursorEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtCursorEditorFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtCursorEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtCursorPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtCursorPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtCursorPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtDateEditFactory b/src/qt-solutions/qtpropertybrowser/src/QtDateEditFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtDateEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtDatePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtDatePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtDatePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtDateTimeEditFactory b/src/qt-solutions/qtpropertybrowser/src/QtDateTimeEditFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtDateTimeEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtDateTimePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtDateTimePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtDateTimePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtDoublePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtDoublePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtDoublePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtDoubleSpinBoxFactory b/src/qt-solutions/qtpropertybrowser/src/QtDoubleSpinBoxFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtDoubleSpinBoxFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtEnumEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtEnumEditorFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtEnumEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtEnumPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtEnumPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtEnumPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtFlagPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtFlagPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtFlagPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtFontEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtFontEditorFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtFontEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtFontPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtFontPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtFontPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtGroupBoxPropertyBrowser b/src/qt-solutions/qtpropertybrowser/src/QtGroupBoxPropertyBrowser deleted file mode 100644 index 27964c08..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtGroupBoxPropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qtgroupboxpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtGroupPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtGroupPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtGroupPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtIntPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtIntPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtIntPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtKeySequenceEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtKeySequenceEditorFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtKeySequenceEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtKeySequencePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtKeySequencePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtKeySequencePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtLineEditFactory b/src/qt-solutions/qtpropertybrowser/src/QtLineEditFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtLineEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtLocalePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtLocalePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtLocalePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtPointFPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtPointFPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtPointFPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtPointPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtPointPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtPointPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtProperty b/src/qt-solutions/qtpropertybrowser/src/QtProperty deleted file mode 100644 index ab4e7104..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtProperty +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtRectFPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtRectFPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtRectFPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtRectPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtRectPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtRectPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtScrollBarFactory b/src/qt-solutions/qtpropertybrowser/src/QtScrollBarFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtScrollBarFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtSizeFPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtSizeFPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtSizeFPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtSizePolicyPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtSizePolicyPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtSizePolicyPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtSizePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtSizePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtSizePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtSliderFactory b/src/qt-solutions/qtpropertybrowser/src/QtSliderFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtSliderFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtSpinBoxFactory b/src/qt-solutions/qtpropertybrowser/src/QtSpinBoxFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtSpinBoxFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtStringPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtStringPropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtStringPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtTimeEditFactory b/src/qt-solutions/qtpropertybrowser/src/QtTimeEditFactory deleted file mode 100644 index 75f35ada..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtTimeEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtTimePropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtTimePropertyManager deleted file mode 100644 index 1842e431..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtTimePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtTreePropertyBrowser b/src/qt-solutions/qtpropertybrowser/src/QtTreePropertyBrowser deleted file mode 100644 index aab106c7..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtTreePropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qttreepropertybrowser.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtVariantEditorFactory b/src/qt-solutions/qtpropertybrowser/src/QtVariantEditorFactory deleted file mode 100644 index 8118190d..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtVariantEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qtvariantproperty.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtVariantProperty b/src/qt-solutions/qtpropertybrowser/src/QtVariantProperty deleted file mode 100644 index 8118190d..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtVariantProperty +++ /dev/null @@ -1 +0,0 @@ -#include "qtvariantproperty.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/QtVariantPropertyManager b/src/qt-solutions/qtpropertybrowser/src/QtVariantPropertyManager deleted file mode 100644 index 8118190d..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/QtVariantPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtvariantproperty.h" diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-arrow.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-arrow.png deleted file mode 100644 index a69ef4eb..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-arrow.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-busy.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-busy.png deleted file mode 100644 index 53717e49..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-busy.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-closedhand.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-closedhand.png deleted file mode 100644 index b78dd1da..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-closedhand.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-cross.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-cross.png deleted file mode 100644 index fe38e744..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-cross.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-forbidden.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-forbidden.png deleted file mode 100644 index 2b08c4e2..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-forbidden.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-hand.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-hand.png deleted file mode 100644 index d2004aef..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-hand.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-hsplit.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-hsplit.png deleted file mode 100644 index a5667e3f..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-hsplit.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-ibeam.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-ibeam.png deleted file mode 100644 index 097fc5fa..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-ibeam.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-openhand.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-openhand.png deleted file mode 100644 index 9181c859..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-openhand.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeall.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeall.png deleted file mode 100644 index 69f13eb3..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeall.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeb.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeb.png deleted file mode 100644 index f37d7b91..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeb.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizef.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizef.png deleted file mode 100644 index 3b127a05..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizef.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeh.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeh.png deleted file mode 100644 index a9f40cbc..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizeh.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizev.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizev.png deleted file mode 100644 index 1edbab27..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-sizev.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-uparrow.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-uparrow.png deleted file mode 100644 index d3e70ef4..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-uparrow.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-vsplit.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-vsplit.png deleted file mode 100644 index 1beda257..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-vsplit.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-wait.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-wait.png deleted file mode 100644 index 69056c47..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-wait.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/images/cursor-whatsthis.png b/src/qt-solutions/qtpropertybrowser/src/images/cursor-whatsthis.png deleted file mode 100644 index b47601c3..00000000 Binary files a/src/qt-solutions/qtpropertybrowser/src/images/cursor-whatsthis.png and /dev/null differ diff --git a/src/qt-solutions/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp b/src/qt-solutions/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp deleted file mode 100644 index 293fbf6b..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtbuttonpropertybrowser.h" -#include -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtButtonPropertyBrowserPrivate -{ - QtButtonPropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtButtonPropertyBrowser) -public: - - void init(QWidget *parent); - - void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); - void propertyRemoved(QtBrowserItem *index); - void propertyChanged(QtBrowserItem *index); - QWidget *createEditor(QtProperty *property, QWidget *parent) const - { return q_ptr->createEditor(property, parent); } - - void slotEditorDestroyed(); - void slotUpdate(); - void slotToggled(bool checked); - - struct WidgetItem - { - WidgetItem() : widget(0), label(0), widgetLabel(0), - button(0), container(0), layout(0), /*line(0), */parent(0), expanded(false) { } - QWidget *widget; // can be null - QLabel *label; // main label with property name - QLabel *widgetLabel; // label substitute showing the current value if there is no widget - QToolButton *button; // expandable button for items with children - QWidget *container; // container which is expanded when the button is clicked - QGridLayout *layout; // layout in container - WidgetItem *parent; - QList children; - bool expanded; - }; -private: - void updateLater(); - void updateItem(WidgetItem *item); - void insertRow(QGridLayout *layout, int row) const; - void removeRow(QGridLayout *layout, int row) const; - int gridRow(WidgetItem *item) const; - int gridSpan(WidgetItem *item) const; - void setExpanded(WidgetItem *item, bool expanded); - QToolButton *createButton(QWidget *panret = 0) const; - - QMap m_indexToItem; - QMap m_itemToIndex; - QMap m_widgetToItem; - QMap m_buttonToItem; - QGridLayout *m_mainLayout; - QList m_children; - QList m_recreateQueue; -}; - -QToolButton *QtButtonPropertyBrowserPrivate::createButton(QWidget *parent) const -{ - QToolButton *button = new QToolButton(parent); - button->setCheckable(true); - button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); - button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - button->setArrowType(Qt::DownArrow); - button->setIconSize(QSize(3, 16)); - /* - QIcon icon; - icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowDown), QIcon::Normal, QIcon::Off); - icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowUp), QIcon::Normal, QIcon::On); - button->setIcon(icon); - */ - return button; -} - -int QtButtonPropertyBrowserPrivate::gridRow(WidgetItem *item) const -{ - QList siblings; - if (item->parent) - siblings = item->parent->children; - else - siblings = m_children; - - int row = 0; - QListIterator it(siblings); - while (it.hasNext()) { - WidgetItem *sibling = it.next(); - if (sibling == item) - return row; - row += gridSpan(sibling); - } - return -1; -} - -int QtButtonPropertyBrowserPrivate::gridSpan(WidgetItem *item) const -{ - if (item->container && item->expanded) - return 2; - return 1; -} - -void QtButtonPropertyBrowserPrivate::init(QWidget *parent) -{ - m_mainLayout = new QGridLayout(); - parent->setLayout(m_mainLayout); - QLayoutItem *item = new QSpacerItem(0, 0, - QSizePolicy::Fixed, QSizePolicy::Expanding); - m_mainLayout->addItem(item, 0, 0); -} - -void QtButtonPropertyBrowserPrivate::slotEditorDestroyed() -{ - QWidget *editor = qobject_cast(q_ptr->sender()); - if (!editor) - return; - if (!m_widgetToItem.contains(editor)) - return; - m_widgetToItem[editor]->widget = 0; - m_widgetToItem.remove(editor); -} - -void QtButtonPropertyBrowserPrivate::slotUpdate() -{ - QListIterator itItem(m_recreateQueue); - while (itItem.hasNext()) { - WidgetItem *item = itItem.next(); - - WidgetItem *parent = item->parent; - QWidget *w = 0; - QGridLayout *l = 0; - const int oldRow = gridRow(item); - if (parent) { - w = parent->container; - l = parent->layout; - } else { - w = q_ptr; - l = m_mainLayout; - } - - int span = 1; - if (!item->widget && !item->widgetLabel) - span = 2; - item->label = new QLabel(w); - item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - l->addWidget(item->label, oldRow, 0, 1, span); - - updateItem(item); - } - m_recreateQueue.clear(); -} - -void QtButtonPropertyBrowserPrivate::setExpanded(WidgetItem *item, bool expanded) -{ - if (item->expanded == expanded) - return; - - if (!item->container) - return; - - item->expanded = expanded; - const int row = gridRow(item); - WidgetItem *parent = item->parent; - QGridLayout *l = 0; - if (parent) - l = parent->layout; - else - l = m_mainLayout; - - if (expanded) { - insertRow(l, row + 1); - l->addWidget(item->container, row + 1, 0, 1, 2); - item->container->show(); - } else { - l->removeWidget(item->container); - item->container->hide(); - removeRow(l, row + 1); - } - - item->button->setChecked(expanded); - item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow); -} - -void QtButtonPropertyBrowserPrivate::slotToggled(bool checked) -{ - WidgetItem *item = m_buttonToItem.value(q_ptr->sender()); - if (!item) - return; - - setExpanded(item, checked); - - if (checked) - emit q_ptr->expanded(m_itemToIndex.value(item)); - else - emit q_ptr->collapsed(m_itemToIndex.value(item)); -} - -void QtButtonPropertyBrowserPrivate::updateLater() -{ - QTimer::singleShot(0, q_ptr, SLOT(slotUpdate())); -} - -void QtButtonPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) -{ - WidgetItem *afterItem = m_indexToItem.value(afterIndex); - WidgetItem *parentItem = m_indexToItem.value(index->parent()); - - WidgetItem *newItem = new WidgetItem(); - newItem->parent = parentItem; - - QGridLayout *layout = 0; - QWidget *parentWidget = 0; - int row = -1; - if (!afterItem) { - row = 0; - if (parentItem) - parentItem->children.insert(0, newItem); - else - m_children.insert(0, newItem); - } else { - row = gridRow(afterItem) + gridSpan(afterItem); - if (parentItem) - parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem); - else - m_children.insert(m_children.indexOf(afterItem) + 1, newItem); - } - - if (!parentItem) { - layout = m_mainLayout; - parentWidget = q_ptr; - } else { - if (!parentItem->container) { - m_recreateQueue.removeAll(parentItem); - WidgetItem *grandParent = parentItem->parent; - QGridLayout *l = 0; - const int oldRow = gridRow(parentItem); - if (grandParent) { - l = grandParent->layout; - } else { - l = m_mainLayout; - } - QFrame *container = new QFrame(); - container->setFrameShape(QFrame::Panel); - container->setFrameShadow(QFrame::Raised); - parentItem->container = container; - parentItem->button = createButton(); - m_buttonToItem[parentItem->button] = parentItem; - q_ptr->connect(parentItem->button, SIGNAL(toggled(bool)), q_ptr, SLOT(slotToggled(bool))); - parentItem->layout = new QGridLayout(); - container->setLayout(parentItem->layout); - if (parentItem->label) { - l->removeWidget(parentItem->label); - delete parentItem->label; - parentItem->label = 0; - } - int span = 1; - if (!parentItem->widget && !parentItem->widgetLabel) - span = 2; - l->addWidget(parentItem->button, oldRow, 0, 1, span); - updateItem(parentItem); - } - layout = parentItem->layout; - parentWidget = parentItem->container; - } - - newItem->label = new QLabel(parentWidget); - newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - newItem->widget = createEditor(index->property(), parentWidget); - if (newItem->widget) { - QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed())); - m_widgetToItem[newItem->widget] = newItem; - } else if (index->property()->hasValue()) { - newItem->widgetLabel = new QLabel(parentWidget); - newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); - } - - insertRow(layout, row); - int span = 1; - if (newItem->widget) - layout->addWidget(newItem->widget, row, 1); - else if (newItem->widgetLabel) - layout->addWidget(newItem->widgetLabel, row, 1); - else - span = 2; - layout->addWidget(newItem->label, row, 0, span, 1); - - m_itemToIndex[newItem] = index; - m_indexToItem[index] = newItem; - - updateItem(newItem); -} - -void QtButtonPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - m_indexToItem.remove(index); - m_itemToIndex.remove(item); - - WidgetItem *parentItem = item->parent; - - const int row = gridRow(item); - - if (parentItem) - parentItem->children.removeAt(parentItem->children.indexOf(item)); - else - m_children.removeAt(m_children.indexOf(item)); - - const int colSpan = gridSpan(item); - - m_buttonToItem.remove(item->button); - - if (item->widget) - delete item->widget; - if (item->label) - delete item->label; - if (item->widgetLabel) - delete item->widgetLabel; - if (item->button) - delete item->button; - if (item->container) - delete item->container; - - if (!parentItem) { - removeRow(m_mainLayout, row); - if (colSpan > 1) - removeRow(m_mainLayout, row); - } else if (parentItem->children.count() != 0) { - removeRow(parentItem->layout, row); - if (colSpan > 1) - removeRow(parentItem->layout, row); - } else { - const WidgetItem *grandParent = parentItem->parent; - QGridLayout *l = 0; - if (grandParent) { - l = grandParent->layout; - } else { - l = m_mainLayout; - } - - const int parentRow = gridRow(parentItem); - const int parentSpan = gridSpan(parentItem); - - l->removeWidget(parentItem->button); - l->removeWidget(parentItem->container); - delete parentItem->button; - delete parentItem->container; - parentItem->button = 0; - parentItem->container = 0; - parentItem->layout = 0; - if (!m_recreateQueue.contains(parentItem)) - m_recreateQueue.append(parentItem); - if (parentSpan > 1) - removeRow(l, parentRow + 1); - - updateLater(); - } - m_recreateQueue.removeAll(item); - - delete item; -} - -void QtButtonPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r >= row) { - itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for(QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -void QtButtonPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r > row) { - itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for(QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -void QtButtonPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - updateItem(item); -} - -void QtButtonPropertyBrowserPrivate::updateItem(WidgetItem *item) -{ - QtProperty *property = m_itemToIndex[item]->property(); - if (item->button) { - QFont font = item->button->font(); - font.setUnderline(property->isModified()); - item->button->setFont(font); - item->button->setText(property->propertyName()); - item->button->setToolTip(property->toolTip()); - item->button->setStatusTip(property->statusTip()); - item->button->setWhatsThis(property->whatsThis()); - item->button->setEnabled(property->isEnabled()); - } - if (item->label) { - QFont font = item->label->font(); - font.setUnderline(property->isModified()); - item->label->setFont(font); - item->label->setText(property->propertyName()); - item->label->setToolTip(property->toolTip()); - item->label->setStatusTip(property->statusTip()); - item->label->setWhatsThis(property->whatsThis()); - item->label->setEnabled(property->isEnabled()); - } - if (item->widgetLabel) { - QFont font = item->widgetLabel->font(); - font.setUnderline(false); - item->widgetLabel->setFont(font); - item->widgetLabel->setText(property->valueText()); - item->widgetLabel->setToolTip(property->valueText()); - item->widgetLabel->setEnabled(property->isEnabled()); - } - if (item->widget) { - QFont font = item->widget->font(); - font.setUnderline(false); - item->widget->setFont(font); - item->widget->setEnabled(property->isEnabled()); - item->widget->setToolTip(property->valueText()); - } -} - - - -/*! - \class QtButtonPropertyBrowser - - \brief The QtButtonPropertyBrowser class provides a drop down QToolButton - based property browser. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - QtButtonPropertyBrowser provides drop down button for all nested - properties, i.e. subproperties are enclosed by a container associated with - the drop down button. The parent property's name is displayed as button text. For example: - - \image qtbuttonpropertybrowser.png - - Use the QtAbstractPropertyBrowser API to add, insert and remove - properties from an instance of the QtButtonPropertyBrowser - class. The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. - - \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser -*/ - -/*! - \fn void QtButtonPropertyBrowser::collapsed(QtBrowserItem *item) - - This signal is emitted when the \a item is collapsed. - - \sa expanded(), setExpanded() -*/ - -/*! - \fn void QtButtonPropertyBrowser::expanded(QtBrowserItem *item) - - This signal is emitted when the \a item is expanded. - - \sa collapsed(), setExpanded() -*/ - -/*! - Creates a property browser with the given \a parent. -*/ -QtButtonPropertyBrowser::QtButtonPropertyBrowser(QWidget *parent) - : QtAbstractPropertyBrowser(parent) -{ - d_ptr = new QtButtonPropertyBrowserPrivate; - d_ptr->q_ptr = this; - - d_ptr->init(this); -} - -/*! - Destroys this property browser. - - Note that the properties that were inserted into this browser are - \e not destroyed since they may still be used in other - browsers. The properties are owned by the manager that created - them. - - \sa QtProperty, QtAbstractPropertyManager -*/ -QtButtonPropertyBrowser::~QtButtonPropertyBrowser() -{ - const QMap::ConstIterator icend = d_ptr->m_itemToIndex.constEnd(); - for (QMap::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it) - delete it.key(); - delete d_ptr; -} - -/*! - \reimp -*/ -void QtButtonPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) -{ - d_ptr->propertyInserted(item, afterItem); -} - -/*! - \reimp -*/ -void QtButtonPropertyBrowser::itemRemoved(QtBrowserItem *item) -{ - d_ptr->propertyRemoved(item); -} - -/*! - \reimp -*/ -void QtButtonPropertyBrowser::itemChanged(QtBrowserItem *item) -{ - d_ptr->propertyChanged(item); -} - -/*! - Sets the \a item to either collapse or expanded, depending on the value of \a expanded. - - \sa isExpanded(), expanded(), collapsed() -*/ - -void QtButtonPropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded) -{ - QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item); - if (itm) - d_ptr->setExpanded(itm, expanded); -} - -/*! - Returns true if the \a item is expanded; otherwise returns false. - - \sa setExpanded() -*/ - -bool QtButtonPropertyBrowser::isExpanded(QtBrowserItem *item) const -{ - QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item); - if (itm) - return itm->expanded; - return false; -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtbuttonpropertybrowser.cpp" diff --git a/src/qt-solutions/qtpropertybrowser/src/qtbuttonpropertybrowser.h b/src/qt-solutions/qtpropertybrowser/src/qtbuttonpropertybrowser.h deleted file mode 100644 index bdab1485..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtbuttonpropertybrowser.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTBUTTONPROPERTYBROWSER_H -#define QTBUTTONPROPERTYBROWSER_H - -#include "qtpropertybrowser.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtButtonPropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtButtonPropertyBrowser : public QtAbstractPropertyBrowser -{ - Q_OBJECT -public: - - QtButtonPropertyBrowser(QWidget *parent = 0); - ~QtButtonPropertyBrowser(); - - void setExpanded(QtBrowserItem *item, bool expanded); - bool isExpanded(QtBrowserItem *item) const; - -Q_SIGNALS: - - void collapsed(QtBrowserItem *item); - void expanded(QtBrowserItem *item); - -protected: - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); - virtual void itemRemoved(QtBrowserItem *item); - virtual void itemChanged(QtBrowserItem *item); - -private: - - QtButtonPropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtButtonPropertyBrowser) - Q_DISABLE_COPY(QtButtonPropertyBrowser) - Q_PRIVATE_SLOT(d_func(), void slotUpdate()) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) - Q_PRIVATE_SLOT(d_func(), void slotToggled(bool)) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qteditorfactory.cpp b/src/qt-solutions/qtpropertybrowser/src/qteditorfactory.cpp deleted file mode 100644 index c9a371da..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qteditorfactory.cpp +++ /dev/null @@ -1,2704 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qteditorfactory.h" -#include "qtpropertybrowserutils_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -// Set a hard coded left margin to account for the indentation -// of the tree view icon when switching to an editor - -static inline void setupTreeViewEditorMargin(QLayout *lt) -{ - enum { DecorationMargin = 4 }; - if (QApplication::layoutDirection() == Qt::LeftToRight) - lt->setContentsMargins(DecorationMargin, 0, 0, 0); - else - lt->setContentsMargins(0, 0, DecorationMargin, 0); -} - -// ---------- EditorFactoryPrivate : -// Base class for editor factory private classes. Manages mapping of properties to editors and vice versa. - -template -class EditorFactoryPrivate -{ -public: - - typedef QList EditorList; - typedef QMap PropertyToEditorListMap; - typedef QMap EditorToPropertyMap; - - Editor *createEditor(QtProperty *property, QWidget *parent); - void initializeEditor(QtProperty *property, Editor *e); - void slotEditorDestroyed(QObject *object); - - PropertyToEditorListMap m_createdEditors; - EditorToPropertyMap m_editorToProperty; -}; - -template -Editor *EditorFactoryPrivate::createEditor(QtProperty *property, QWidget *parent) -{ - Editor *editor = new Editor(parent); - initializeEditor(property, editor); - return editor; -} - -template -void EditorFactoryPrivate::initializeEditor(QtProperty *property, Editor *editor) -{ - typename PropertyToEditorListMap::iterator it = m_createdEditors.find(property); - if (it == m_createdEditors.end()) - it = m_createdEditors.insert(property, EditorList()); - it.value().append(editor); - m_editorToProperty.insert(editor, property); -} - -template -void EditorFactoryPrivate::slotEditorDestroyed(QObject *object) -{ - const typename EditorToPropertyMap::iterator ecend = m_editorToProperty.end(); - for (typename EditorToPropertyMap::iterator itEditor = m_editorToProperty.begin(); itEditor != ecend; ++itEditor) { - if (itEditor.key() == object) { - Editor *editor = itEditor.key(); - QtProperty *property = itEditor.value(); - const typename PropertyToEditorListMap::iterator pit = m_createdEditors.find(property); - if (pit != m_createdEditors.end()) { - pit.value().removeAll(editor); - if (pit.value().empty()) - m_createdEditors.erase(pit); - } - m_editorToProperty.erase(itEditor); - return; - } - } -} - -// ------------ QtSpinBoxFactory - -class QtSpinBoxFactoryPrivate : public EditorFactoryPrivate -{ - QtSpinBoxFactory *q_ptr; - Q_DECLARE_PUBLIC(QtSpinBoxFactory) -public: - - void slotPropertyChanged(QtProperty *property, int value); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotReadOnlyChanged(QtProperty *property, bool readOnly); - void slotSetValue(int value); -}; - -void QtSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - if (editor->value() != value) { - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } - } -} - -void QtSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtSpinBoxFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setReadOnly(readOnly); - editor->blockSignals(false); - } -} - -void QtSpinBoxFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) { - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } - } -} - -/*! - \class QtSpinBoxFactory - - \brief The QtSpinBoxFactory class provides QSpinBox widgets for - properties created by QtIntPropertyManager objects. - - \sa QtAbstractEditorFactory, QtIntPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtSpinBoxFactory::QtSpinBoxFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtSpinBoxFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtSpinBoxFactory::~QtSpinBoxFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSpinBoxFactory::connectPropertyManager(QtIntPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); - connect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtSpinBoxFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QSpinBox *editor = d_ptr->createEditor(property, parent); - editor->setSingleStep(manager->singleStep(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - editor->setKeyboardTracking(false); - editor->setReadOnly(manager->isReadOnly(property)); - - connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSpinBoxFactory::disconnectPropertyManager(QtIntPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -// QtSliderFactory - -class QtSliderFactoryPrivate : public EditorFactoryPrivate -{ - QtSliderFactory *q_ptr; - Q_DECLARE_PUBLIC(QtSliderFactory) -public: - void slotPropertyChanged(QtProperty *property, int value); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotSetValue(int value); -}; - -void QtSliderFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSlider *editor = itEditor.next(); - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } -} - -void QtSliderFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSlider *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtSliderFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSlider *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtSliderFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor ) { - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } - } -} - -/*! - \class QtSliderFactory - - \brief The QtSliderFactory class provides QSlider widgets for - properties created by QtIntPropertyManager objects. - - \sa QtAbstractEditorFactory, QtIntPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtSliderFactory::QtSliderFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtSliderFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtSliderFactory::~QtSliderFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSliderFactory::connectPropertyManager(QtIntPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtSliderFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QSlider *editor = new QSlider(Qt::Horizontal, parent); - d_ptr->initializeEditor(property, editor); - editor->setSingleStep(manager->singleStep(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - - connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSliderFactory::disconnectPropertyManager(QtIntPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -// QtSliderFactory - -class QtScrollBarFactoryPrivate : public EditorFactoryPrivate -{ - QtScrollBarFactory *q_ptr; - Q_DECLARE_PUBLIC(QtScrollBarFactory) -public: - void slotPropertyChanged(QtProperty *property, int value); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotSetValue(int value); -}; - -void QtScrollBarFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor( m_createdEditors[property]); - while (itEditor.hasNext()) { - QScrollBar *editor = itEditor.next(); - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } -} - -void QtScrollBarFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor( m_createdEditors[property]); - while (itEditor.hasNext()) { - QScrollBar *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtScrollBarFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QScrollBar *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtScrollBarFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtScrollBarFactory - - \brief The QtScrollBarFactory class provides QScrollBar widgets for - properties created by QtIntPropertyManager objects. - - \sa QtAbstractEditorFactory, QtIntPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtScrollBarFactory::QtScrollBarFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtScrollBarFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtScrollBarFactory::~QtScrollBarFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtScrollBarFactory::connectPropertyManager(QtIntPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtScrollBarFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QScrollBar *editor = new QScrollBar(Qt::Horizontal, parent); - d_ptr->initializeEditor(property, editor); - editor->setSingleStep(manager->singleStep(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtScrollBarFactory::disconnectPropertyManager(QtIntPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -// QtCheckBoxFactory - -class QtCheckBoxFactoryPrivate : public EditorFactoryPrivate -{ - QtCheckBoxFactory *q_ptr; - Q_DECLARE_PUBLIC(QtCheckBoxFactory) -public: - void slotPropertyChanged(QtProperty *property, bool value); - void slotTextVisibleChanged(QtProperty *property, bool textVisible); - void slotSetValue(bool value); -}; - -void QtCheckBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, bool value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtBoolEdit *editor = itEditor.next(); - editor->blockCheckBoxSignals(true); - editor->setChecked(value); - editor->blockCheckBoxSignals(false); - } -} - -void QtCheckBoxFactoryPrivate::slotTextVisibleChanged(QtProperty *property, bool textVisible) -{ - if (!m_createdEditors.contains(property)) - return; - - QtBoolPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtBoolEdit *editor = itEditor.next(); - editor->setTextVisible(textVisible); - } -} - -void QtCheckBoxFactoryPrivate::slotSetValue(bool value) -{ - QObject *object = q_ptr->sender(); - - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtBoolPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtCheckBoxFactory - - \brief The QtCheckBoxFactory class provides QCheckBox widgets for - properties created by QtBoolPropertyManager objects. - - \sa QtAbstractEditorFactory, QtBoolPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtCheckBoxFactory::QtCheckBoxFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtCheckBoxFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtCheckBoxFactory::~QtCheckBoxFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCheckBoxFactory::connectPropertyManager(QtBoolPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotPropertyChanged(QtProperty *, bool))); - connect(manager, SIGNAL(textVisibleChanged(QtProperty *, bool)), - this, SLOT(slotTextVisibleChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtCheckBoxFactory::createEditor(QtBoolPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QtBoolEdit *editor = d_ptr->createEditor(property, parent); - editor->setChecked(manager->value(property)); - editor->setTextVisible(manager->textVisible(property)); - - connect(editor, SIGNAL(toggled(bool)), this, SLOT(slotSetValue(bool))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCheckBoxFactory::disconnectPropertyManager(QtBoolPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotPropertyChanged(QtProperty *, bool))); - disconnect(manager, SIGNAL(textVisibleChanged(QtProperty *, bool)), - this, SLOT(slotTextVisibleChanged(QtProperty *, bool))); -} - -// QtDoubleSpinBoxFactory - -class QtDoubleSpinBoxFactoryPrivate : public EditorFactoryPrivate -{ - QtDoubleSpinBoxFactory *q_ptr; - Q_DECLARE_PUBLIC(QtDoubleSpinBoxFactory) -public: - - void slotPropertyChanged(QtProperty *property, double value); - void slotRangeChanged(QtProperty *property, double min, double max); - void slotSingleStepChanged(QtProperty *property, double step); - void slotDecimalsChanged(QtProperty *property, int prec); - void slotReadOnlyChanged(QtProperty *property, bool readOnly); - void slotSetValue(double value); -}; - -void QtDoubleSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, double value) -{ - QList editors = m_createdEditors[property]; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDoubleSpinBox *editor = itEditor.next(); - if (editor->value() != value) { - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, - double min, double max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QList editors = m_createdEditors[property]; - QListIterator itEditor(editors); - while (itEditor.hasNext()) { - QDoubleSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, double step) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QList editors = m_createdEditors[property]; - QListIterator itEditor(editors); - while (itEditor.hasNext()) { - QDoubleSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDoubleSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setReadOnly(readOnly); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotDecimalsChanged(QtProperty *property, int prec) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QList editors = m_createdEditors[property]; - QListIterator itEditor(editors); - while (itEditor.hasNext()) { - QDoubleSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDecimals(prec); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotSetValue(double value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator itcend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != itcend; ++itEditor) { - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } - } -} - -/*! \class QtDoubleSpinBoxFactory - - \brief The QtDoubleSpinBoxFactory class provides QDoubleSpinBox - widgets for properties created by QtDoublePropertyManager objects. - - \sa QtAbstractEditorFactory, QtDoublePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtDoubleSpinBoxFactory::QtDoubleSpinBoxFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtDoubleSpinBoxFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtDoubleSpinBoxFactory::~QtDoubleSpinBoxFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDoubleSpinBoxFactory::connectPropertyManager(QtDoublePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotPropertyChanged(QtProperty *, double))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, double)), - this, SLOT(slotSingleStepChanged(QtProperty *, double))); - connect(manager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtDoubleSpinBoxFactory::createEditor(QtDoublePropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QDoubleSpinBox *editor = d_ptr->createEditor(property, parent); - editor->setSingleStep(manager->singleStep(property)); - editor->setDecimals(manager->decimals(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - editor->setKeyboardTracking(false); - editor->setReadOnly(manager->isReadOnly(property)); - - connect(editor, SIGNAL(valueChanged(double)), this, SLOT(slotSetValue(double))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDoubleSpinBoxFactory::disconnectPropertyManager(QtDoublePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotPropertyChanged(QtProperty *, double))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, double)), - this, SLOT(slotSingleStepChanged(QtProperty *, double))); - disconnect(manager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -// QtLineEditFactory - -class QtLineEditFactoryPrivate : public EditorFactoryPrivate -{ - QtLineEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtLineEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QString &value); - void slotRegExpChanged(QtProperty *property, const QRegExp ®Exp); - void slotSetValue(const QString &value); - void slotEchoModeChanged(QtProperty *, int); - void slotReadOnlyChanged(QtProperty *, bool); -}; - -void QtLineEditFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QString &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor( m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - if (editor->text() != value) { - editor->blockSignals(true); - editor->setText(value); - editor->blockSignals(false); - } - } -} - -void QtLineEditFactoryPrivate::slotRegExpChanged(QtProperty *property, - const QRegExp ®Exp) -{ - if (!m_createdEditors.contains(property)) - return; - - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - editor->blockSignals(true); - const QValidator *oldValidator = editor->validator(); - QValidator *newValidator = 0; - if (regExp.isValid()) { - newValidator = new QRegExpValidator(regExp, editor); - } - editor->setValidator(newValidator); - if (oldValidator) - delete oldValidator; - editor->blockSignals(false); - } -} - -void QtLineEditFactoryPrivate::slotEchoModeChanged(QtProperty *property, int echoMode) -{ - if (!m_createdEditors.contains(property)) - return; - - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setEchoMode((EchoMode)echoMode); - editor->blockSignals(false); - } -} - -void QtLineEditFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) -{ - if (!m_createdEditors.contains(property)) - return; - - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setReadOnly(readOnly); - editor->blockSignals(false); - } -} - -void QtLineEditFactoryPrivate::slotSetValue(const QString &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - - - -/*! - \class QtLineEditFactory - - \brief The QtLineEditFactory class provides QLineEdit widgets for - properties created by QtStringPropertyManager objects. - - \sa QtAbstractEditorFactory, QtStringPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtLineEditFactory::QtLineEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtLineEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtLineEditFactory::~QtLineEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtLineEditFactory::connectPropertyManager(QtStringPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QString &))); - connect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)), - this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &))); - connect(manager, SIGNAL(echoModeChanged(QtProperty*, int)), - this, SLOT(slotEchoModeChanged(QtProperty *, int))); - connect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtLineEditFactory::createEditor(QtStringPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - - QLineEdit *editor = d_ptr->createEditor(property, parent); - editor->setEchoMode((EchoMode)manager->echoMode(property)); - editor->setReadOnly(manager->isReadOnly(property)); - QRegExp regExp = manager->regExp(property); - if (regExp.isValid()) { - QValidator *validator = new QRegExpValidator(regExp, editor); - editor->setValidator(validator); - } - editor->setText(manager->value(property)); - - connect(editor, SIGNAL(textChanged(const QString &)), - this, SLOT(slotSetValue(const QString &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtLineEditFactory::disconnectPropertyManager(QtStringPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QString &))); - disconnect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)), - this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &))); - disconnect(manager, SIGNAL(echoModeChanged(QtProperty*,int)), - this, SLOT(slotEchoModeChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); - -} - -// QtDateEditFactory - -class QtDateEditFactoryPrivate : public EditorFactoryPrivate -{ - QtDateEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtDateEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QDate &value); - void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max); - void slotSetValue(const QDate &value); -}; - -void QtDateEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QDate &value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDateEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDate(value); - editor->blockSignals(false); - } -} - -void QtDateEditFactoryPrivate::slotRangeChanged(QtProperty *property, - const QDate &min, const QDate &max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDatePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDateEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDateRange(min, max); - editor->setDate(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtDateEditFactoryPrivate::slotSetValue(const QDate &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtDatePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtDateEditFactory - - \brief The QtDateEditFactory class provides QDateEdit widgets for - properties created by QtDatePropertyManager objects. - - \sa QtAbstractEditorFactory, QtDatePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtDateEditFactory::QtDateEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtDateEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtDateEditFactory::~QtDateEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateEditFactory::connectPropertyManager(QtDatePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDate &))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), - this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtDateEditFactory::createEditor(QtDatePropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QDateEdit *editor = d_ptr->createEditor(property, parent); - editor->setCalendarPopup(true); - editor->setDateRange(manager->minimum(property), manager->maximum(property)); - editor->setDate(manager->value(property)); - - connect(editor, SIGNAL(dateChanged(const QDate &)), - this, SLOT(slotSetValue(const QDate &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateEditFactory::disconnectPropertyManager(QtDatePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDate &))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), - this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); -} - -// QtTimeEditFactory - -class QtTimeEditFactoryPrivate : public EditorFactoryPrivate -{ - QtTimeEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtTimeEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QTime &value); - void slotSetValue(const QTime &value); -}; - -void QtTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QTime &value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QTimeEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setTime(value); - editor->blockSignals(false); - } -} - -void QtTimeEditFactoryPrivate::slotSetValue(const QTime &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtTimePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtTimeEditFactory - - \brief The QtTimeEditFactory class provides QTimeEdit widgets for - properties created by QtTimePropertyManager objects. - - \sa QtAbstractEditorFactory, QtTimePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtTimeEditFactory::QtTimeEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtTimeEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtTimeEditFactory::~QtTimeEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtTimeEditFactory::connectPropertyManager(QtTimePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QTime &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtTimeEditFactory::createEditor(QtTimePropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QTimeEdit *editor = d_ptr->createEditor(property, parent); - editor->setTime(manager->value(property)); - - connect(editor, SIGNAL(timeChanged(const QTime &)), - this, SLOT(slotSetValue(const QTime &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtTimeEditFactory::disconnectPropertyManager(QtTimePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QTime &))); -} - -// QtDateTimeEditFactory - -class QtDateTimeEditFactoryPrivate : public EditorFactoryPrivate -{ - QtDateTimeEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtDateTimeEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QDateTime &value); - void slotSetValue(const QDateTime &value); - -}; - -void QtDateTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QDateTime &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDateTimeEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDateTime(value); - editor->blockSignals(false); - } -} - -void QtDateTimeEditFactoryPrivate::slotSetValue(const QDateTime &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtDateTimePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtDateTimeEditFactory - - \brief The QtDateTimeEditFactory class provides QDateTimeEdit - widgets for properties created by QtDateTimePropertyManager objects. - - \sa QtAbstractEditorFactory, QtDateTimePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtDateTimeEditFactory::QtDateTimeEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtDateTimeEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtDateTimeEditFactory::~QtDateTimeEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateTimeEditFactory::connectPropertyManager(QtDateTimePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtDateTimeEditFactory::createEditor(QtDateTimePropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QDateTimeEdit *editor = d_ptr->createEditor(property, parent); - editor->setDateTime(manager->value(property)); - - connect(editor, SIGNAL(dateTimeChanged(const QDateTime &)), - this, SLOT(slotSetValue(const QDateTime &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateTimeEditFactory::disconnectPropertyManager(QtDateTimePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &))); -} - -// QtKeySequenceEditorFactory - -class QtKeySequenceEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtKeySequenceEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtKeySequenceEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QKeySequence &value); - void slotSetValue(const QKeySequence &value); -}; - -void QtKeySequenceEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QKeySequence &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtKeySequenceEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setKeySequence(value); - editor->blockSignals(false); - } -} - -void QtKeySequenceEditorFactoryPrivate::slotSetValue(const QKeySequence &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtKeySequencePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtKeySequenceEditorFactory - - \brief The QtKeySequenceEditorFactory class provides editor - widgets for properties created by QtKeySequencePropertyManager objects. - - \sa QtAbstractEditorFactory -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtKeySequenceEditorFactory::QtKeySequenceEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtKeySequenceEditorFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtKeySequenceEditorFactory::~QtKeySequenceEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtKeySequenceEditorFactory::connectPropertyManager(QtKeySequencePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtKeySequenceEditorFactory::createEditor(QtKeySequencePropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtKeySequenceEdit *editor = d_ptr->createEditor(property, parent); - editor->setKeySequence(manager->value(property)); - - connect(editor, SIGNAL(keySequenceChanged(const QKeySequence &)), - this, SLOT(slotSetValue(const QKeySequence &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtKeySequenceEditorFactory::disconnectPropertyManager(QtKeySequencePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &))); -} - -// QtCharEdit - -class QtCharEdit : public QWidget -{ - Q_OBJECT -public: - QtCharEdit(QWidget *parent = 0); - - QChar value() const; - bool eventFilter(QObject *o, QEvent *e); -public Q_SLOTS: - void setValue(const QChar &value); -Q_SIGNALS: - void valueChanged(const QChar &value); -protected: - void focusInEvent(QFocusEvent *e); - void focusOutEvent(QFocusEvent *e); - void keyPressEvent(QKeyEvent *e); - void keyReleaseEvent(QKeyEvent *e); - void paintEvent(QPaintEvent *); - bool event(QEvent *e); -private slots: - void slotClearChar(); -private: - void handleKeyEvent(QKeyEvent *e); - - QChar m_value; - QLineEdit *m_lineEdit; -}; - -QtCharEdit::QtCharEdit(QWidget *parent) - : QWidget(parent), m_lineEdit(new QLineEdit(this)) -{ - QHBoxLayout *layout = new QHBoxLayout(this); - layout->addWidget(m_lineEdit); - layout->setMargin(0); - m_lineEdit->installEventFilter(this); - m_lineEdit->setReadOnly(true); - m_lineEdit->setFocusProxy(this); - setFocusPolicy(m_lineEdit->focusPolicy()); - setAttribute(Qt::WA_InputMethodEnabled); -} - -bool QtCharEdit::eventFilter(QObject *o, QEvent *e) -{ - if (o == m_lineEdit && e->type() == QEvent::ContextMenu) { - QContextMenuEvent *c = static_cast(e); - QMenu *menu = m_lineEdit->createStandardContextMenu(); - QList actions = menu->actions(); - QListIterator itAction(actions); - while (itAction.hasNext()) { - QAction *action = itAction.next(); - action->setShortcut(QKeySequence()); - QString actionString = action->text(); - const int pos = actionString.lastIndexOf(QLatin1Char('\t')); - if (pos > 0) - actionString = actionString.remove(pos, actionString.length() - pos); - action->setText(actionString); - } - QAction *actionBefore = 0; - if (actions.count() > 0) - actionBefore = actions[0]; - QAction *clearAction = new QAction(tr("Clear Char"), menu); - menu->insertAction(actionBefore, clearAction); - menu->insertSeparator(actionBefore); - clearAction->setEnabled(!m_value.isNull()); - connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearChar())); - menu->exec(c->globalPos()); - delete menu; - e->accept(); - return true; - } - - return QWidget::eventFilter(o, e); -} - -void QtCharEdit::slotClearChar() -{ - if (m_value.isNull()) - return; - setValue(QChar()); - emit valueChanged(m_value); -} - -void QtCharEdit::handleKeyEvent(QKeyEvent *e) -{ - const int key = e->key(); - switch (key) { - case Qt::Key_Control: - case Qt::Key_Shift: - case Qt::Key_Meta: - case Qt::Key_Alt: - case Qt::Key_Super_L: - case Qt::Key_Return: - return; - default: - break; - } - - const QString text = e->text(); - if (text.count() != 1) - return; - - const QChar c = text.at(0); - if (!c.isPrint()) - return; - - if (m_value == c) - return; - - m_value = c; - const QString str = m_value.isNull() ? QString() : QString(m_value); - m_lineEdit->setText(str); - e->accept(); - emit valueChanged(m_value); -} - -void QtCharEdit::setValue(const QChar &value) -{ - if (value == m_value) - return; - - m_value = value; - QString str = value.isNull() ? QString() : QString(value); - m_lineEdit->setText(str); -} - -QChar QtCharEdit::value() const -{ - return m_value; -} - -void QtCharEdit::focusInEvent(QFocusEvent *e) -{ - m_lineEdit->event(e); - m_lineEdit->selectAll(); - QWidget::focusInEvent(e); -} - -void QtCharEdit::focusOutEvent(QFocusEvent *e) -{ - m_lineEdit->event(e); - QWidget::focusOutEvent(e); -} - -void QtCharEdit::keyPressEvent(QKeyEvent *e) -{ - handleKeyEvent(e); - e->accept(); -} - -void QtCharEdit::keyReleaseEvent(QKeyEvent *e) -{ - m_lineEdit->event(e); -} - -void QtCharEdit::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -bool QtCharEdit::event(QEvent *e) -{ - switch(e->type()) { - case QEvent::Shortcut: - case QEvent::ShortcutOverride: - case QEvent::KeyRelease: - e->accept(); - return true; - default: - break; - } - return QWidget::event(e); -} - -// QtCharEditorFactory - -class QtCharEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtCharEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtCharEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QChar &value); - void slotSetValue(const QChar &value); - -}; - -void QtCharEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QChar &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtCharEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } -} - -void QtCharEditorFactoryPrivate::slotSetValue(const QChar &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtCharPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtCharEditorFactory - - \brief The QtCharEditorFactory class provides editor - widgets for properties created by QtCharPropertyManager objects. - - \sa QtAbstractEditorFactory -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtCharEditorFactory::QtCharEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtCharEditorFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtCharEditorFactory::~QtCharEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCharEditorFactory::connectPropertyManager(QtCharPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QChar &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtCharEditorFactory::createEditor(QtCharPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtCharEdit *editor = d_ptr->createEditor(property, parent); - editor->setValue(manager->value(property)); - - connect(editor, SIGNAL(valueChanged(const QChar &)), - this, SLOT(slotSetValue(const QChar &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCharEditorFactory::disconnectPropertyManager(QtCharPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QChar &))); -} - -// QtEnumEditorFactory - -class QtEnumEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtEnumEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtEnumEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, int value); - void slotEnumNamesChanged(QtProperty *property, const QStringList &); - void slotEnumIconsChanged(QtProperty *property, const QMap &); - void slotSetValue(int value); -}; - -void QtEnumEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QComboBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setCurrentIndex(value); - editor->blockSignals(false); - } -} - -void QtEnumEditorFactoryPrivate::slotEnumNamesChanged(QtProperty *property, - const QStringList &enumNames) -{ - if (!m_createdEditors.contains(property)) - return; - - QtEnumPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QMap enumIcons = manager->enumIcons(property); - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QComboBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->clear(); - editor->addItems(enumNames); - const int nameCount = enumNames.count(); - for (int i = 0; i < nameCount; i++) - editor->setItemIcon(i, enumIcons.value(i)); - editor->setCurrentIndex(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtEnumEditorFactoryPrivate::slotEnumIconsChanged(QtProperty *property, - const QMap &enumIcons) -{ - if (!m_createdEditors.contains(property)) - return; - - QtEnumPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - const QStringList enumNames = manager->enumNames(property); - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QComboBox *editor = itEditor.next(); - editor->blockSignals(true); - const int nameCount = enumNames.count(); - for (int i = 0; i < nameCount; i++) - editor->setItemIcon(i, enumIcons.value(i)); - editor->setCurrentIndex(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtEnumEditorFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtEnumPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtEnumEditorFactory - - \brief The QtEnumEditorFactory class provides QComboBox widgets for - properties created by QtEnumPropertyManager objects. - - \sa QtAbstractEditorFactory, QtEnumPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtEnumEditorFactory::QtEnumEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtEnumEditorFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtEnumEditorFactory::~QtEnumEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtEnumEditorFactory::connectPropertyManager(QtEnumPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtEnumEditorFactory::createEditor(QtEnumPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QComboBox *editor = d_ptr->createEditor(property, parent); - editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); - editor->setMinimumContentsLength(1); - editor->view()->setTextElideMode(Qt::ElideRight); - QStringList enumNames = manager->enumNames(property); - editor->addItems(enumNames); - QMap enumIcons = manager->enumIcons(property); - const int enumNamesCount = enumNames.count(); - for (int i = 0; i < enumNamesCount; i++) - editor->setItemIcon(i, enumIcons.value(i)); - editor->setCurrentIndex(manager->value(property)); - - connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtEnumEditorFactory::disconnectPropertyManager(QtEnumPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); -} - -// QtCursorEditorFactory - -Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase) - -class QtCursorEditorFactoryPrivate -{ - QtCursorEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtCursorEditorFactory) -public: - QtCursorEditorFactoryPrivate(); - - void slotPropertyChanged(QtProperty *property, const QCursor &cursor); - void slotEnumChanged(QtProperty *property, int value); - void slotEditorDestroyed(QObject *object); - - QtEnumEditorFactory *m_enumEditorFactory; - QtEnumPropertyManager *m_enumPropertyManager; - - QMap m_propertyToEnum; - QMap m_enumToProperty; - QMap > m_enumToEditors; - QMap m_editorToEnum; - bool m_updatingEnum; -}; - -QtCursorEditorFactoryPrivate::QtCursorEditorFactoryPrivate() - : m_updatingEnum(false) -{ - -} - -void QtCursorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QCursor &cursor) -{ - // update enum property - QtProperty *enumProp = m_propertyToEnum.value(property); - if (!enumProp) - return; - - m_updatingEnum = true; - m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(cursor)); - m_updatingEnum = false; -} - -void QtCursorEditorFactoryPrivate::slotEnumChanged(QtProperty *property, int value) -{ - if (m_updatingEnum) - return; - // update cursor property - QtProperty *prop = m_enumToProperty.value(property); - if (!prop) - return; - QtCursorPropertyManager *cursorManager = q_ptr->propertyManager(prop); - if (!cursorManager) - return; -#ifndef QT_NO_CURSOR - cursorManager->setValue(prop, QCursor(cursorDatabase()->valueToCursor(value))); -#endif -} - -void QtCursorEditorFactoryPrivate::slotEditorDestroyed(QObject *object) -{ - // remove from m_editorToEnum map; - // remove from m_enumToEditors map; - // if m_enumToEditors doesn't contains more editors delete enum property; - const QMap::ConstIterator ecend = m_editorToEnum.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToEnum.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QWidget *editor = itEditor.key(); - QtProperty *enumProp = itEditor.value(); - m_editorToEnum.remove(editor); - m_enumToEditors[enumProp].removeAll(editor); - if (m_enumToEditors[enumProp].isEmpty()) { - m_enumToEditors.remove(enumProp); - QtProperty *property = m_enumToProperty.value(enumProp); - m_enumToProperty.remove(enumProp); - m_propertyToEnum.remove(property); - delete enumProp; - } - return; - } -} - -/*! - \class QtCursorEditorFactory - - \brief The QtCursorEditorFactory class provides QComboBox widgets for - properties created by QtCursorPropertyManager objects. - - \sa QtAbstractEditorFactory, QtCursorPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtCursorEditorFactory::QtCursorEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtCursorEditorFactoryPrivate(); - d_ptr->q_ptr = this; - - d_ptr->m_enumEditorFactory = new QtEnumEditorFactory(this); - d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); - connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotEnumChanged(QtProperty *, int))); - d_ptr->m_enumEditorFactory->addPropertyManager(d_ptr->m_enumPropertyManager); -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtCursorEditorFactory::~QtCursorEditorFactory() -{ - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCursorEditorFactory::connectPropertyManager(QtCursorPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtCursorEditorFactory::createEditor(QtCursorPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QtProperty *enumProp = 0; - if (d_ptr->m_propertyToEnum.contains(property)) { - enumProp = d_ptr->m_propertyToEnum[property]; - } else { - enumProp = d_ptr->m_enumPropertyManager->addProperty(property->propertyName()); - d_ptr->m_enumPropertyManager->setEnumNames(enumProp, cursorDatabase()->cursorShapeNames()); - d_ptr->m_enumPropertyManager->setEnumIcons(enumProp, cursorDatabase()->cursorShapeIcons()); -#ifndef QT_NO_CURSOR - d_ptr->m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(manager->value(property))); -#endif - d_ptr->m_propertyToEnum[property] = enumProp; - d_ptr->m_enumToProperty[enumProp] = property; - } - QtAbstractEditorFactoryBase *af = d_ptr->m_enumEditorFactory; - QWidget *editor = af->createEditor(enumProp, parent); - d_ptr->m_enumToEditors[enumProp].append(editor); - d_ptr->m_editorToEnum[editor] = enumProp; - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCursorEditorFactory::disconnectPropertyManager(QtCursorPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &))); -} - -// QtColorEditWidget - -class QtColorEditWidget : public QWidget { - Q_OBJECT - -public: - QtColorEditWidget(QWidget *parent); - - bool eventFilter(QObject *obj, QEvent *ev); - -public Q_SLOTS: - void setValue(const QColor &value); - -Q_SIGNALS: - void valueChanged(const QColor &value); - -protected: - void paintEvent(QPaintEvent *); - -private Q_SLOTS: - void buttonClicked(); - -private: - QColor m_color; - QLabel *m_pixmapLabel; - QLabel *m_label; - QToolButton *m_button; -}; - -QtColorEditWidget::QtColorEditWidget(QWidget *parent) : - QWidget(parent), - m_pixmapLabel(new QLabel), - m_label(new QLabel), - m_button(new QToolButton) -{ - QHBoxLayout *lt = new QHBoxLayout(this); - setupTreeViewEditorMargin(lt); - lt->setSpacing(0); - lt->addWidget(m_pixmapLabel); - lt->addWidget(m_label); - lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); - - m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); - m_button->setFixedWidth(20); - setFocusProxy(m_button); - setFocusPolicy(m_button->focusPolicy()); - m_button->setText(tr("...")); - m_button->installEventFilter(this); - connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); - lt->addWidget(m_button); - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(m_color))); - m_label->setText(QtPropertyBrowserUtils::colorValueText(m_color)); -} - -void QtColorEditWidget::setValue(const QColor &c) -{ - if (m_color != c) { - m_color = c; - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(c))); - m_label->setText(QtPropertyBrowserUtils::colorValueText(c)); - } -} - -void QtColorEditWidget::buttonClicked() -{ - bool ok = false; - QRgb oldRgba = m_color.rgba(); - QRgb newRgba = QColorDialog::getRgba(oldRgba, &ok, this); - if (ok && newRgba != oldRgba) { - setValue(QColor::fromRgba(newRgba)); - emit valueChanged(m_color); - } -} - -bool QtColorEditWidget::eventFilter(QObject *obj, QEvent *ev) -{ - if (obj == m_button) { - switch (ev->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate - switch (static_cast(ev)->key()) { - case Qt::Key_Escape: - case Qt::Key_Enter: - case Qt::Key_Return: - ev->ignore(); - return true; - default: - break; - } - } - break; - default: - break; - } - } - return QWidget::eventFilter(obj, ev); -} - -void QtColorEditWidget::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -// QtColorEditorFactoryPrivate - -class QtColorEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtColorEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtColorEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QColor &value); - void slotSetValue(const QColor &value); -}; - -void QtColorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QColor &value) -{ - const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); - if (it == m_createdEditors.end()) - return; - QListIterator itEditor(it.value()); - - while (itEditor.hasNext()) - itEditor.next()->setValue(value); -} - -void QtColorEditorFactoryPrivate::slotSetValue(const QColor &value) -{ - QObject *object = q_ptr->sender(); - const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtColorPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtColorEditorFactory - - \brief The QtColorEditorFactory class provides color editing for - properties created by QtColorPropertyManager objects. - - \sa QtAbstractEditorFactory, QtColorPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtColorEditorFactory::QtColorEditorFactory(QObject *parent) : - QtAbstractEditorFactory(parent), - d_ptr(new QtColorEditorFactoryPrivate()) -{ - d_ptr->q_ptr = this; -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtColorEditorFactory::~QtColorEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtColorEditorFactory::connectPropertyManager(QtColorPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), - this, SLOT(slotPropertyChanged(QtProperty*,QColor))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtColorEditorFactory::createEditor(QtColorPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtColorEditWidget *editor = d_ptr->createEditor(property, parent); - editor->setValue(manager->value(property)); - connect(editor, SIGNAL(valueChanged(QColor)), this, SLOT(slotSetValue(QColor))); - connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtColorEditorFactory::disconnectPropertyManager(QtColorPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), this, SLOT(slotPropertyChanged(QtProperty*,QColor))); -} - -// QtFontEditWidget - -class QtFontEditWidget : public QWidget { - Q_OBJECT - -public: - QtFontEditWidget(QWidget *parent); - - bool eventFilter(QObject *obj, QEvent *ev); - -public Q_SLOTS: - void setValue(const QFont &value); - -Q_SIGNALS: - void valueChanged(const QFont &value); - -protected: - void paintEvent(QPaintEvent *); - -private Q_SLOTS: - void buttonClicked(); - -private: - QFont m_font; - QLabel *m_pixmapLabel; - QLabel *m_label; - QToolButton *m_button; -}; - -QtFontEditWidget::QtFontEditWidget(QWidget *parent) : - QWidget(parent), - m_pixmapLabel(new QLabel), - m_label(new QLabel), - m_button(new QToolButton) -{ - QHBoxLayout *lt = new QHBoxLayout(this); - setupTreeViewEditorMargin(lt); - lt->setSpacing(0); - lt->addWidget(m_pixmapLabel); - lt->addWidget(m_label); - lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); - - m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); - m_button->setFixedWidth(20); - setFocusProxy(m_button); - setFocusPolicy(m_button->focusPolicy()); - m_button->setText(tr("...")); - m_button->installEventFilter(this); - connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); - lt->addWidget(m_button); - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(m_font)); - m_label->setText(QtPropertyBrowserUtils::fontValueText(m_font)); -} - -void QtFontEditWidget::setValue(const QFont &f) -{ - if (m_font != f) { - m_font = f; - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(f)); - m_label->setText(QtPropertyBrowserUtils::fontValueText(f)); - } -} - -void QtFontEditWidget::buttonClicked() -{ - bool ok = false; - QFont newFont = QFontDialog::getFont(&ok, m_font, this, tr("Select Font")); - if (ok && newFont != m_font) { - QFont f = m_font; - // prevent mask for unchanged attributes, don't change other attributes (like kerning, etc...) - if (m_font.family() != newFont.family()) - f.setFamily(newFont.family()); - if (m_font.pointSize() != newFont.pointSize()) - f.setPointSize(newFont.pointSize()); - if (m_font.bold() != newFont.bold()) - f.setBold(newFont.bold()); - if (m_font.italic() != newFont.italic()) - f.setItalic(newFont.italic()); - if (m_font.underline() != newFont.underline()) - f.setUnderline(newFont.underline()); - if (m_font.strikeOut() != newFont.strikeOut()) - f.setStrikeOut(newFont.strikeOut()); - setValue(f); - emit valueChanged(m_font); - } -} - -bool QtFontEditWidget::eventFilter(QObject *obj, QEvent *ev) -{ - if (obj == m_button) { - switch (ev->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate - switch (static_cast(ev)->key()) { - case Qt::Key_Escape: - case Qt::Key_Enter: - case Qt::Key_Return: - ev->ignore(); - return true; - default: - break; - } - } - break; - default: - break; - } - } - return QWidget::eventFilter(obj, ev); -} - -void QtFontEditWidget::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -// QtFontEditorFactoryPrivate - -class QtFontEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtFontEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtFontEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QFont &value); - void slotSetValue(const QFont &value); -}; - -void QtFontEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QFont &value) -{ - const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); - if (it == m_createdEditors.end()) - return; - QListIterator itEditor(it.value()); - - while (itEditor.hasNext()) - itEditor.next()->setValue(value); -} - -void QtFontEditorFactoryPrivate::slotSetValue(const QFont &value) -{ - QObject *object = q_ptr->sender(); - const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtFontPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtFontEditorFactory - - \brief The QtFontEditorFactory class provides font editing for - properties created by QtFontPropertyManager objects. - - \sa QtAbstractEditorFactory, QtFontPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtFontEditorFactory::QtFontEditorFactory(QObject *parent) : - QtAbstractEditorFactory(parent), - d_ptr(new QtFontEditorFactoryPrivate()) -{ - d_ptr->q_ptr = this; -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtFontEditorFactory::~QtFontEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtFontEditorFactory::connectPropertyManager(QtFontPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), - this, SLOT(slotPropertyChanged(QtProperty*,QFont))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtFontEditorFactory::createEditor(QtFontPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtFontEditWidget *editor = d_ptr->createEditor(property, parent); - editor->setValue(manager->value(property)); - connect(editor, SIGNAL(valueChanged(QFont)), this, SLOT(slotSetValue(QFont))); - connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtFontEditorFactory::disconnectPropertyManager(QtFontPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), this, SLOT(slotPropertyChanged(QtProperty*,QFont))); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qteditorfactory.cpp" -#include "qteditorfactory.moc" diff --git a/src/qt-solutions/qtpropertybrowser/src/qteditorfactory.h b/src/qt-solutions/qtpropertybrowser/src/qteditorfactory.h deleted file mode 100644 index cbb2077d..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qteditorfactory.h +++ /dev/null @@ -1,406 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTEDITORFACTORY_H -#define QTEDITORFACTORY_H - -#include "qtpropertymanager.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtSpinBoxFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSpinBoxFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtSpinBoxFactory(QObject *parent = 0); - ~QtSpinBoxFactory(); -protected: - void connectPropertyManager(QtIntPropertyManager *manager); - QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtIntPropertyManager *manager); -private: - QtSpinBoxFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSpinBoxFactory) - Q_DISABLE_COPY(QtSpinBoxFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtSliderFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSliderFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtSliderFactory(QObject *parent = 0); - ~QtSliderFactory(); -protected: - void connectPropertyManager(QtIntPropertyManager *manager); - QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtIntPropertyManager *manager); -private: - QtSliderFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSliderFactory) - Q_DISABLE_COPY(QtSliderFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtScrollBarFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtScrollBarFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtScrollBarFactory(QObject *parent = 0); - ~QtScrollBarFactory(); -protected: - void connectPropertyManager(QtIntPropertyManager *manager); - QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtIntPropertyManager *manager); -private: - QtScrollBarFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtScrollBarFactory) - Q_DISABLE_COPY(QtScrollBarFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtCheckBoxFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCheckBoxFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtCheckBoxFactory(QObject *parent = 0); - ~QtCheckBoxFactory(); -protected: - void connectPropertyManager(QtBoolPropertyManager *manager); - QWidget *createEditor(QtBoolPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtBoolPropertyManager *manager); -private: - QtCheckBoxFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCheckBoxFactory) - Q_DISABLE_COPY(QtCheckBoxFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotTextVisibleChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(bool)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtDoubleSpinBoxFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDoubleSpinBoxFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtDoubleSpinBoxFactory(QObject *parent = 0); - ~QtDoubleSpinBoxFactory(); -protected: - void connectPropertyManager(QtDoublePropertyManager *manager); - QWidget *createEditor(QtDoublePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDoublePropertyManager *manager); -private: - QtDoubleSpinBoxFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDoubleSpinBoxFactory) - Q_DISABLE_COPY(QtDoubleSpinBoxFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(double)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtLineEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtLineEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtLineEditFactory(QObject *parent = 0); - ~QtLineEditFactory(); -protected: - void connectPropertyManager(QtStringPropertyManager *manager); - QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtStringPropertyManager *manager); -private: - QtLineEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtLineEditFactory) - Q_DISABLE_COPY(QtLineEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QString &)) - Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &)) - Q_PRIVATE_SLOT(d_func(), void slotEchoModeChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QString &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtDateEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDateEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtDateEditFactory(QObject *parent = 0); - ~QtDateEditFactory(); -protected: - void connectPropertyManager(QtDatePropertyManager *manager); - QWidget *createEditor(QtDatePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDatePropertyManager *manager); -private: - QtDateEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDateEditFactory) - Q_DISABLE_COPY(QtDateEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, - const QDate &, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtTimeEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtTimeEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtTimeEditFactory(QObject *parent = 0); - ~QtTimeEditFactory(); -protected: - void connectPropertyManager(QtTimePropertyManager *manager); - QWidget *createEditor(QtTimePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtTimePropertyManager *manager); -private: - QtTimeEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtTimeEditFactory) - Q_DISABLE_COPY(QtTimeEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QTime &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QTime &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtDateTimeEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDateTimeEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtDateTimeEditFactory(QObject *parent = 0); - ~QtDateTimeEditFactory(); -protected: - void connectPropertyManager(QtDateTimePropertyManager *manager); - QWidget *createEditor(QtDateTimePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDateTimePropertyManager *manager); -private: - QtDateTimeEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDateTimeEditFactory) - Q_DISABLE_COPY(QtDateTimeEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDateTime &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDateTime &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtKeySequenceEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtKeySequenceEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtKeySequenceEditorFactory(QObject *parent = 0); - ~QtKeySequenceEditorFactory(); -protected: - void connectPropertyManager(QtKeySequencePropertyManager *manager); - QWidget *createEditor(QtKeySequencePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtKeySequencePropertyManager *manager); -private: - QtKeySequenceEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtKeySequenceEditorFactory) - Q_DISABLE_COPY(QtKeySequenceEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QKeySequence &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QKeySequence &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtCharEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCharEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtCharEditorFactory(QObject *parent = 0); - ~QtCharEditorFactory(); -protected: - void connectPropertyManager(QtCharPropertyManager *manager); - QWidget *createEditor(QtCharPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtCharPropertyManager *manager); -private: - QtCharEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCharEditorFactory) - Q_DISABLE_COPY(QtCharEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QChar &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QChar &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtEnumEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtEnumEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtEnumEditorFactory(QObject *parent = 0); - ~QtEnumEditorFactory(); -protected: - void connectPropertyManager(QtEnumPropertyManager *manager); - QWidget *createEditor(QtEnumPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtEnumPropertyManager *manager); -private: - QtEnumEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtEnumEditorFactory) - Q_DISABLE_COPY(QtEnumEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, - const QStringList &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, - const QMap &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtCursorEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCursorEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtCursorEditorFactory(QObject *parent = 0); - ~QtCursorEditorFactory(); -protected: - void connectPropertyManager(QtCursorPropertyManager *manager); - QWidget *createEditor(QtCursorPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtCursorPropertyManager *manager); -private: - QtCursorEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCursorEditorFactory) - Q_DISABLE_COPY(QtCursorEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QCursor &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtColorEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtColorEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtColorEditorFactory(QObject *parent = 0); - ~QtColorEditorFactory(); -protected: - void connectPropertyManager(QtColorPropertyManager *manager); - QWidget *createEditor(QtColorPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtColorPropertyManager *manager); -private: - QtColorEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtColorEditorFactory) - Q_DISABLE_COPY(QtColorEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QColor &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QColor &)) -}; - -class QtFontEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtFontEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtFontEditorFactory(QObject *parent = 0); - ~QtFontEditorFactory(); -protected: - void connectPropertyManager(QtFontPropertyManager *manager); - QWidget *createEditor(QtFontPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtFontPropertyManager *manager); -private: - QtFontEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtFontEditorFactory) - Q_DISABLE_COPY(QtFontEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QFont &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QFont &)) -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp b/src/qt-solutions/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp deleted file mode 100644 index b2c4989d..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtgroupboxpropertybrowser.h" -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtGroupBoxPropertyBrowserPrivate -{ - QtGroupBoxPropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtGroupBoxPropertyBrowser) -public: - - void init(QWidget *parent); - - void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); - void propertyRemoved(QtBrowserItem *index); - void propertyChanged(QtBrowserItem *index); - QWidget *createEditor(QtProperty *property, QWidget *parent) const - { return q_ptr->createEditor(property, parent); } - - void slotEditorDestroyed(); - void slotUpdate(); - - struct WidgetItem - { - WidgetItem() : widget(0), label(0), widgetLabel(0), - groupBox(0), layout(0), line(0), parent(0) { } - QWidget *widget; // can be null - QLabel *label; - QLabel *widgetLabel; - QGroupBox *groupBox; - QGridLayout *layout; - QFrame *line; - WidgetItem *parent; - QList children; - }; -private: - void updateLater(); - void updateItem(WidgetItem *item); - void insertRow(QGridLayout *layout, int row) const; - void removeRow(QGridLayout *layout, int row) const; - - bool hasHeader(WidgetItem *item) const; - - QMap m_indexToItem; - QMap m_itemToIndex; - QMap m_widgetToItem; - QGridLayout *m_mainLayout; - QList m_children; - QList m_recreateQueue; -}; - -void QtGroupBoxPropertyBrowserPrivate::init(QWidget *parent) -{ - m_mainLayout = new QGridLayout(); - parent->setLayout(m_mainLayout); - QLayoutItem *item = new QSpacerItem(0, 0, - QSizePolicy::Fixed, QSizePolicy::Expanding); - m_mainLayout->addItem(item, 0, 0); -} - -void QtGroupBoxPropertyBrowserPrivate::slotEditorDestroyed() -{ - QWidget *editor = qobject_cast(q_ptr->sender()); - if (!editor) - return; - if (!m_widgetToItem.contains(editor)) - return; - m_widgetToItem[editor]->widget = 0; - m_widgetToItem.remove(editor); -} - -void QtGroupBoxPropertyBrowserPrivate::slotUpdate() -{ - QListIterator itItem(m_recreateQueue); - while (itItem.hasNext()) { - WidgetItem *item = itItem.next(); - - WidgetItem *par = item->parent; - QWidget *w = 0; - QGridLayout *l = 0; - int oldRow = -1; - if (!par) { - w = q_ptr; - l = m_mainLayout; - oldRow = m_children.indexOf(item); - } else { - w = par->groupBox; - l = par->layout; - oldRow = par->children.indexOf(item); - if (hasHeader(par)) - oldRow += 2; - } - - if (item->widget) { - item->widget->setParent(w); - } else if (item->widgetLabel) { - item->widgetLabel->setParent(w); - } else { - item->widgetLabel = new QLabel(w); - item->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); - item->widgetLabel->setTextFormat(Qt::PlainText); - } - int span = 1; - if (item->widget) - l->addWidget(item->widget, oldRow, 1, 1, 1); - else if (item->widgetLabel) - l->addWidget(item->widgetLabel, oldRow, 1, 1, 1); - else - span = 2; - item->label = new QLabel(w); - item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - l->addWidget(item->label, oldRow, 0, 1, span); - - updateItem(item); - } - m_recreateQueue.clear(); -} - -void QtGroupBoxPropertyBrowserPrivate::updateLater() -{ - QTimer::singleShot(0, q_ptr, SLOT(slotUpdate())); -} - -void QtGroupBoxPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) -{ - WidgetItem *afterItem = m_indexToItem.value(afterIndex); - WidgetItem *parentItem = m_indexToItem.value(index->parent()); - - WidgetItem *newItem = new WidgetItem(); - newItem->parent = parentItem; - - QGridLayout *layout = 0; - QWidget *parentWidget = 0; - int row = -1; - if (!afterItem) { - row = 0; - if (parentItem) - parentItem->children.insert(0, newItem); - else - m_children.insert(0, newItem); - } else { - if (parentItem) { - row = parentItem->children.indexOf(afterItem) + 1; - parentItem->children.insert(row, newItem); - } else { - row = m_children.indexOf(afterItem) + 1; - m_children.insert(row, newItem); - } - } - if (parentItem && hasHeader(parentItem)) - row += 2; - - if (!parentItem) { - layout = m_mainLayout; - parentWidget = q_ptr;; - } else { - if (!parentItem->groupBox) { - m_recreateQueue.removeAll(parentItem); - WidgetItem *par = parentItem->parent; - QWidget *w = 0; - QGridLayout *l = 0; - int oldRow = -1; - if (!par) { - w = q_ptr; - l = m_mainLayout; - oldRow = m_children.indexOf(parentItem); - } else { - w = par->groupBox; - l = par->layout; - oldRow = par->children.indexOf(parentItem); - if (hasHeader(par)) - oldRow += 2; - } - parentItem->groupBox = new QGroupBox(w); - parentItem->layout = new QGridLayout(); - parentItem->groupBox->setLayout(parentItem->layout); - if (parentItem->label) { - l->removeWidget(parentItem->label); - delete parentItem->label; - parentItem->label = 0; - } - if (parentItem->widget) { - l->removeWidget(parentItem->widget); - parentItem->widget->setParent(parentItem->groupBox); - parentItem->layout->addWidget(parentItem->widget, 0, 0, 1, 2); - parentItem->line = new QFrame(parentItem->groupBox); - } else if (parentItem->widgetLabel) { - l->removeWidget(parentItem->widgetLabel); - delete parentItem->widgetLabel; - parentItem->widgetLabel = 0; - } - if (parentItem->line) { - parentItem->line->setFrameShape(QFrame::HLine); - parentItem->line->setFrameShadow(QFrame::Sunken); - parentItem->layout->addWidget(parentItem->line, 1, 0, 1, 2); - } - l->addWidget(parentItem->groupBox, oldRow, 0, 1, 2); - updateItem(parentItem); - } - layout = parentItem->layout; - parentWidget = parentItem->groupBox; - } - - newItem->label = new QLabel(parentWidget); - newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - newItem->widget = createEditor(index->property(), parentWidget); - if (!newItem->widget) { - newItem->widgetLabel = new QLabel(parentWidget); - newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); - newItem->widgetLabel->setTextFormat(Qt::PlainText); - } else { - QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed())); - m_widgetToItem[newItem->widget] = newItem; - } - - insertRow(layout, row); - int span = 1; - if (newItem->widget) - layout->addWidget(newItem->widget, row, 1); - else if (newItem->widgetLabel) - layout->addWidget(newItem->widgetLabel, row, 1); - else - span = 2; - layout->addWidget(newItem->label, row, 0, 1, span); - - m_itemToIndex[newItem] = index; - m_indexToItem[index] = newItem; - - updateItem(newItem); -} - -void QtGroupBoxPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - m_indexToItem.remove(index); - m_itemToIndex.remove(item); - - WidgetItem *parentItem = item->parent; - - int row = -1; - - if (parentItem) { - row = parentItem->children.indexOf(item); - parentItem->children.removeAt(row); - if (hasHeader(parentItem)) - row += 2; - } else { - row = m_children.indexOf(item); - m_children.removeAt(row); - } - - if (item->widget) - delete item->widget; - if (item->label) - delete item->label; - if (item->widgetLabel) - delete item->widgetLabel; - if (item->groupBox) - delete item->groupBox; - - if (!parentItem) { - removeRow(m_mainLayout, row); - } else if (parentItem->children.count() != 0) { - removeRow(parentItem->layout, row); - } else { - WidgetItem *par = parentItem->parent; - QGridLayout *l = 0; - int oldRow = -1; - if (!par) { - l = m_mainLayout; - oldRow = m_children.indexOf(parentItem); - } else { - l = par->layout; - oldRow = par->children.indexOf(parentItem); - if (hasHeader(par)) - oldRow += 2; - } - - if (parentItem->widget) { - parentItem->widget->hide(); - parentItem->widget->setParent(0); - } else if (parentItem->widgetLabel) { - parentItem->widgetLabel->hide(); - parentItem->widgetLabel->setParent(0); - } else { - //parentItem->widgetLabel = new QLabel(w); - } - l->removeWidget(parentItem->groupBox); - delete parentItem->groupBox; - parentItem->groupBox = 0; - parentItem->line = 0; - parentItem->layout = 0; - if (!m_recreateQueue.contains(parentItem)) - m_recreateQueue.append(parentItem); - updateLater(); - } - m_recreateQueue.removeAll(item); - - delete item; -} - -void QtGroupBoxPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r >= row) { - itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for (QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -void QtGroupBoxPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r > row) { - itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for (QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -bool QtGroupBoxPropertyBrowserPrivate::hasHeader(WidgetItem *item) const -{ - if (item->widget) - return true; - return false; -} - -void QtGroupBoxPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - updateItem(item); -} - -void QtGroupBoxPropertyBrowserPrivate::updateItem(WidgetItem *item) -{ - QtProperty *property = m_itemToIndex[item]->property(); - if (item->groupBox) { - QFont font = item->groupBox->font(); - font.setUnderline(property->isModified()); - item->groupBox->setFont(font); - item->groupBox->setTitle(property->propertyName()); - item->groupBox->setToolTip(property->toolTip()); - item->groupBox->setStatusTip(property->statusTip()); - item->groupBox->setWhatsThis(property->whatsThis()); - item->groupBox->setEnabled(property->isEnabled()); - } - if (item->label) { - QFont font = item->label->font(); - font.setUnderline(property->isModified()); - item->label->setFont(font); - item->label->setText(property->propertyName()); - item->label->setToolTip(property->toolTip()); - item->label->setStatusTip(property->statusTip()); - item->label->setWhatsThis(property->whatsThis()); - item->label->setEnabled(property->isEnabled()); - } - if (item->widgetLabel) { - QFont font = item->widgetLabel->font(); - font.setUnderline(false); - item->widgetLabel->setFont(font); - item->widgetLabel->setText(property->valueText()); - item->widgetLabel->setToolTip(property->valueText()); - item->widgetLabel->setEnabled(property->isEnabled()); - } - if (item->widget) { - QFont font = item->widget->font(); - font.setUnderline(false); - item->widget->setFont(font); - item->widget->setEnabled(property->isEnabled()); - item->widget->setToolTip(property->valueText()); - } - //item->setIcon(1, property->valueIcon()); -} - - - -/*! - \class QtGroupBoxPropertyBrowser - - \brief The QtGroupBoxPropertyBrowser class provides a QGroupBox - based property browser. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - QtGroupBoxPropertyBrowser provides group boxes for all nested - properties, i.e. subproperties are enclosed by a group box with - the parent property's name as its title. For example: - - \image qtgroupboxpropertybrowser.png - - Use the QtAbstractPropertyBrowser API to add, insert and remove - properties from an instance of the QtGroupBoxPropertyBrowser - class. The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. - - \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser -*/ - -/*! - Creates a property browser with the given \a parent. -*/ -QtGroupBoxPropertyBrowser::QtGroupBoxPropertyBrowser(QWidget *parent) - : QtAbstractPropertyBrowser(parent) -{ - d_ptr = new QtGroupBoxPropertyBrowserPrivate; - d_ptr->q_ptr = this; - - d_ptr->init(this); -} - -/*! - Destroys this property browser. - - Note that the properties that were inserted into this browser are - \e not destroyed since they may still be used in other - browsers. The properties are owned by the manager that created - them. - - \sa QtProperty, QtAbstractPropertyManager -*/ -QtGroupBoxPropertyBrowser::~QtGroupBoxPropertyBrowser() -{ - const QMap::ConstIterator icend = d_ptr->m_itemToIndex.constEnd(); - for (QMap::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it) - delete it.key(); - delete d_ptr; -} - -/*! - \reimp -*/ -void QtGroupBoxPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) -{ - d_ptr->propertyInserted(item, afterItem); -} - -/*! - \reimp -*/ -void QtGroupBoxPropertyBrowser::itemRemoved(QtBrowserItem *item) -{ - d_ptr->propertyRemoved(item); -} - -/*! - \reimp -*/ -void QtGroupBoxPropertyBrowser::itemChanged(QtBrowserItem *item) -{ - d_ptr->propertyChanged(item); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtgroupboxpropertybrowser.cpp" diff --git a/src/qt-solutions/qtpropertybrowser/src/qtgroupboxpropertybrowser.h b/src/qt-solutions/qtpropertybrowser/src/qtgroupboxpropertybrowser.h deleted file mode 100644 index 78b4a9b1..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtgroupboxpropertybrowser.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTGROUPBOXPROPERTYBROWSER_H -#define QTGROUPBOXPROPERTYBROWSER_H - -#include "qtpropertybrowser.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtGroupBoxPropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtGroupBoxPropertyBrowser : public QtAbstractPropertyBrowser -{ - Q_OBJECT -public: - - QtGroupBoxPropertyBrowser(QWidget *parent = 0); - ~QtGroupBoxPropertyBrowser(); - -protected: - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); - virtual void itemRemoved(QtBrowserItem *item); - virtual void itemChanged(QtBrowserItem *item); - -private: - - QtGroupBoxPropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtGroupBoxPropertyBrowser) - Q_DISABLE_COPY(QtGroupBoxPropertyBrowser) - Q_PRIVATE_SLOT(d_func(), void slotUpdate()) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.cpp b/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.cpp deleted file mode 100644 index 738bfbf1..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.cpp +++ /dev/null @@ -1,2026 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtpropertybrowser.h" -#include -#include -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtPropertyPrivate -{ -public: - QtPropertyPrivate(QtAbstractPropertyManager *manager) - : m_enabled(true), - m_modified(false), - m_manager(manager) {} - QtProperty *q_ptr; - - QSet m_parentItems; - QList m_subItems; - - QString m_toolTip; - QString m_statusTip; - QString m_whatsThis; - QString m_name; - bool m_enabled; - bool m_modified; - - QtAbstractPropertyManager * const m_manager; -}; - -class QtAbstractPropertyManagerPrivate -{ - QtAbstractPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtAbstractPropertyManager) -public: - void propertyDestroyed(QtProperty *property); - void propertyChanged(QtProperty *property) const; - void propertyRemoved(QtProperty *property, - QtProperty *parentProperty) const; - void propertyInserted(QtProperty *property, QtProperty *parentProperty, - QtProperty *afterProperty) const; - - QSet m_properties; -}; - -/*! - \class QtProperty - - \brief The QtProperty class encapsulates an instance of a property. - - Properties are created by objects of QtAbstractPropertyManager - subclasses; a manager can create properties of a given type, and - is used in conjunction with the QtAbstractPropertyBrowser class. A - property is always owned by the manager that created it, which can - be retrieved using the propertyManager() function. - - QtProperty contains the most common property attributes, and - provides functions for retrieving as well as setting their values: - - \table - \header \o Getter \o Setter - \row - \o propertyName() \o setPropertyName() - \row - \o statusTip() \o setStatusTip() - \row - \o toolTip() \o setToolTip() - \row - \o whatsThis() \o setWhatsThis() - \row - \o isEnabled() \o setEnabled() - \row - \o isModified() \o setModified() - \row - \o valueText() \o Nop - \row - \o valueIcon() \o Nop - \endtable - - It is also possible to nest properties: QtProperty provides the - addSubProperty(), insertSubProperty() and removeSubProperty() functions to - manipulate the set of subproperties. Use the subProperties() - function to retrieve a property's current set of subproperties. - Note that nested properties are not owned by the parent property, - i.e. each subproperty is owned by the manager that created it. - - \sa QtAbstractPropertyManager, QtBrowserItem -*/ - -/*! - Creates a property with the given \a manager. - - This constructor is only useful when creating a custom QtProperty - subclass (e.g. QtVariantProperty). To create a regular QtProperty - object, use the QtAbstractPropertyManager::addProperty() - function instead. - - \sa QtAbstractPropertyManager::addProperty() -*/ -QtProperty::QtProperty(QtAbstractPropertyManager *manager) -{ - d_ptr = new QtPropertyPrivate(manager); - d_ptr->q_ptr = this; -} - -/*! - Destroys this property. - - Note that subproperties are detached but not destroyed, i.e. they - can still be used in another context. - - \sa QtAbstractPropertyManager::clear() - -*/ -QtProperty::~QtProperty() -{ - QSetIterator itParent(d_ptr->m_parentItems); - while (itParent.hasNext()) { - QtProperty *property = itParent.next(); - property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property); - } - - d_ptr->m_manager->d_ptr->propertyDestroyed(this); - - QListIterator itChild(d_ptr->m_subItems); - while (itChild.hasNext()) { - QtProperty *property = itChild.next(); - property->d_ptr->m_parentItems.remove(this); - } - - itParent.toFront(); - while (itParent.hasNext()) { - QtProperty *property = itParent.next(); - property->d_ptr->m_subItems.removeAll(this); - } - delete d_ptr; -} - -/*! - Returns the set of subproperties. - - Note that subproperties are not owned by \e this property, but by - the manager that created them. - - \sa insertSubProperty(), removeSubProperty() -*/ -QList QtProperty::subProperties() const -{ - return d_ptr->m_subItems; -} - -/*! - Returns a pointer to the manager that owns this property. -*/ -QtAbstractPropertyManager *QtProperty::propertyManager() const -{ - return d_ptr->m_manager; -} - -/*! - Returns the property's tool tip. - - \sa setToolTip() -*/ -QString QtProperty::toolTip() const -{ - return d_ptr->m_toolTip; -} - -/*! - Returns the property's status tip. - - \sa setStatusTip() -*/ -QString QtProperty::statusTip() const -{ - return d_ptr->m_statusTip; -} - -/*! - Returns the property's "What's This" help text. - - \sa setWhatsThis() -*/ -QString QtProperty::whatsThis() const -{ - return d_ptr->m_whatsThis; -} - -/*! - Returns the property's name. - - \sa setPropertyName() -*/ -QString QtProperty::propertyName() const -{ - return d_ptr->m_name; -} - -/*! - Returns whether the property is enabled. - - \sa setEnabled() -*/ -bool QtProperty::isEnabled() const -{ - return d_ptr->m_enabled; -} - -/*! - Returns whether the property is modified. - - \sa setModified() -*/ -bool QtProperty::isModified() const -{ - return d_ptr->m_modified; -} - -/*! - Returns whether the property has a value. - - \sa QtAbstractPropertyManager::hasValue() -*/ -bool QtProperty::hasValue() const -{ - return d_ptr->m_manager->hasValue(this); -} - -/*! - Returns an icon representing the current state of this property. - - If the given property type can not generate such an icon, this - function returns an invalid icon. - - \sa QtAbstractPropertyManager::valueIcon() -*/ -QIcon QtProperty::valueIcon() const -{ - return d_ptr->m_manager->valueIcon(this); -} - -/*! - Returns a string representing the current state of this property. - - If the given property type can not generate such a string, this - function returns an empty string. - - \sa QtAbstractPropertyManager::valueText() -*/ -QString QtProperty::valueText() const -{ - return d_ptr->m_manager->valueText(this); -} - -/*! - Returns the display text according to the echo-mode set on the editor. - - When the editor is a QLineEdit, this will return a string equal to what - is displayed. - - \sa QtAbstractPropertyManager::valueText() -*/ -QString QtProperty::displayText() const -{ - return d_ptr->m_manager->displayText(this); -} - -/*! - Sets the property's tool tip to the given \a text. - - \sa toolTip() -*/ -void QtProperty::setToolTip(const QString &text) -{ - if (d_ptr->m_toolTip == text) - return; - - d_ptr->m_toolTip = text; - propertyChanged(); -} - -/*! - Sets the property's status tip to the given \a text. - - \sa statusTip() -*/ -void QtProperty::setStatusTip(const QString &text) -{ - if (d_ptr->m_statusTip == text) - return; - - d_ptr->m_statusTip = text; - propertyChanged(); -} - -/*! - Sets the property's "What's This" help text to the given \a text. - - \sa whatsThis() -*/ -void QtProperty::setWhatsThis(const QString &text) -{ - if (d_ptr->m_whatsThis == text) - return; - - d_ptr->m_whatsThis = text; - propertyChanged(); -} - -/*! - \fn void QtProperty::setPropertyName(const QString &name) - - Sets the property's name to the given \a name. - - \sa propertyName() -*/ -void QtProperty::setPropertyName(const QString &text) -{ - if (d_ptr->m_name == text) - return; - - d_ptr->m_name = text; - propertyChanged(); -} - -/*! - Enables or disables the property according to the passed \a enable value. - - \sa isEnabled() -*/ -void QtProperty::setEnabled(bool enable) -{ - if (d_ptr->m_enabled == enable) - return; - - d_ptr->m_enabled = enable; - propertyChanged(); -} - -/*! - Sets the property's modified state according to the passed \a modified value. - - \sa isModified() -*/ -void QtProperty::setModified(bool modified) -{ - if (d_ptr->m_modified == modified) - return; - - d_ptr->m_modified = modified; - propertyChanged(); -} - -/*! - Appends the given \a property to this property's subproperties. - - If the given \a property already is added, this function does - nothing. - - \sa insertSubProperty(), removeSubProperty() -*/ -void QtProperty::addSubProperty(QtProperty *property) -{ - QtProperty *after = 0; - if (d_ptr->m_subItems.count() > 0) - after = d_ptr->m_subItems.last(); - insertSubProperty(property, after); -} - -/*! - \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty) - - Inserts the given \a property after the specified \a - precedingProperty into this property's list of subproperties. If - \a precedingProperty is 0, the specified \a property is inserted - at the beginning of the list. - - If the given \a property already is inserted, this function does - nothing. - - \sa addSubProperty(), removeSubProperty() -*/ -void QtProperty::insertSubProperty(QtProperty *property, - QtProperty *afterProperty) -{ - if (!property) - return; - - if (property == this) - return; - - // traverse all children of item. if this item is a child of item then cannot add. - QList pendingList = property->subProperties(); - QMap visited; - while (!pendingList.isEmpty()) { - QtProperty *i = pendingList.first(); - if (i == this) - return; - pendingList.removeFirst(); - if (visited.contains(i)) - continue; - visited[i] = true; - pendingList += i->subProperties(); - } - - pendingList = subProperties(); - int pos = 0; - int newPos = 0; - QtProperty *properAfterProperty = 0; - while (pos < pendingList.count()) { - QtProperty *i = pendingList.at(pos); - if (i == property) - return; // if item is already inserted in this item then cannot add. - if (i == afterProperty) { - newPos = pos + 1; - properAfterProperty = afterProperty; - } - pos++; - } - - d_ptr->m_subItems.insert(newPos, property); - property->d_ptr->m_parentItems.insert(this); - - d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty); -} - -/*! - Removes the given \a property from the list of subproperties - without deleting it. - - \sa addSubProperty(), insertSubProperty() -*/ -void QtProperty::removeSubProperty(QtProperty *property) -{ - if (!property) - return; - - d_ptr->m_manager->d_ptr->propertyRemoved(property, this); - - QList pendingList = subProperties(); - int pos = 0; - while (pos < pendingList.count()) { - if (pendingList.at(pos) == property) { - d_ptr->m_subItems.removeAt(pos); - property->d_ptr->m_parentItems.remove(this); - - return; - } - pos++; - } -} - -/*! - \internal -*/ -void QtProperty::propertyChanged() -{ - d_ptr->m_manager->d_ptr->propertyChanged(this); -} - -//////////////////////////////// - -void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property) -{ - if (m_properties.contains(property)) { - emit q_ptr->propertyDestroyed(property); - q_ptr->uninitializeProperty(property); - m_properties.remove(property); - } -} - -void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const -{ - emit q_ptr->propertyChanged(property); -} - -void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property, - QtProperty *parentProperty) const -{ - emit q_ptr->propertyRemoved(property, parentProperty); -} - -void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property, - QtProperty *parentProperty, QtProperty *afterProperty) const -{ - emit q_ptr->propertyInserted(property, parentProperty, afterProperty); -} - -/*! - \class QtAbstractPropertyManager - - \brief The QtAbstractPropertyManager provides an interface for - property managers. - - A manager can create and manage properties of a given type, and is - used in conjunction with the QtAbstractPropertyBrowser class. - - When using a property browser widget, the properties are created - and managed by implementations of the QtAbstractPropertyManager - class. To ensure that the properties' values will be displayed - using suitable editing widgets, the managers are associated with - objects of QtAbstractEditorFactory subclasses. The property browser - will use these associations to determine which factories it should - use to create the preferred editing widgets. - - The QtAbstractPropertyManager class provides common functionality - like creating a property using the addProperty() function, and - retrieving the properties created by the manager using the - properties() function. The class also provides signals that are - emitted when the manager's properties change: propertyInserted(), - propertyRemoved(), propertyChanged() and propertyDestroyed(). - - QtAbstractPropertyManager subclasses are supposed to provide their - own type specific API. Note that several ready-made - implementations are available: - - \list - \o QtBoolPropertyManager - \o QtColorPropertyManager - \o QtDatePropertyManager - \o QtDateTimePropertyManager - \o QtDoublePropertyManager - \o QtEnumPropertyManager - \o QtFlagPropertyManager - \o QtFontPropertyManager - \o QtGroupPropertyManager - \o QtIntPropertyManager - \o QtPointPropertyManager - \o QtRectPropertyManager - \o QtSizePropertyManager - \o QtSizePolicyPropertyManager - \o QtStringPropertyManager - \o QtTimePropertyManager - \o QtVariantPropertyManager - \endlist - - \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty, - QtProperty *parentProperty, QtProperty *precedingProperty) - - This signal is emitted when a new subproperty is inserted into an - existing property, passing pointers to the \a newProperty, \a - parentProperty and \a precedingProperty as parameters. - - If \a precedingProperty is 0, the \a newProperty was inserted at - the beginning of the \a parentProperty's subproperties list. - - Note that signal is emitted only if the \a parentProperty is created - by this manager. - - \sa QtAbstractPropertyBrowser::itemInserted() -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property) - - This signal is emitted whenever a property's data changes, passing - a pointer to the \a property as parameter. - - Note that signal is only emitted for properties that are created by - this manager. - - \sa QtAbstractPropertyBrowser::itemChanged() -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent) - - This signal is emitted when a subproperty is removed, passing - pointers to the removed \a property and the \a parent property as - parameters. - - Note that signal is emitted only when the \a parent property is - created by this manager. - - \sa QtAbstractPropertyBrowser::itemRemoved() -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property) - - This signal is emitted when the specified \a property is about to - be destroyed. - - Note that signal is only emitted for properties that are created - by this manager. - - \sa clear(), uninitializeProperty() -*/ - -/*! - \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current) - - This signal is emitted when the current item changes. The current item is specified by \a current. - - \sa QtAbstractPropertyBrowser::setCurrentItem() -*/ - -/*! - Creates an abstract property manager with the given \a parent. -*/ -QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent) - : QObject(parent) -{ - d_ptr = new QtAbstractPropertyManagerPrivate; - d_ptr->q_ptr = this; - -} - -/*! - Destroys the manager. All properties created by the manager are - destroyed. -*/ -QtAbstractPropertyManager::~QtAbstractPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Destroys all the properties that this manager has created. - - \sa propertyDestroyed(), uninitializeProperty() -*/ -void QtAbstractPropertyManager::clear() const -{ - while (!properties().isEmpty()) { - QSetIterator itProperty(properties()); - QtProperty *prop = itProperty.next(); - delete prop; - } -} - -/*! - Returns the set of properties created by this manager. - - \sa addProperty() -*/ -QSet QtAbstractPropertyManager::properties() const -{ - return d_ptr->m_properties; -} - -/*! - Returns whether the given \a property has a value. - - The default implementation of this function returns true. - - \sa QtProperty::hasValue() -*/ -bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const -{ - Q_UNUSED(property) - return true; -} - -/*! - Returns an icon representing the current state of the given \a - property. - - The default implementation of this function returns an invalid - icon. - - \sa QtProperty::valueIcon() -*/ -QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const -{ - Q_UNUSED(property) - return QIcon(); -} - -/*! - Returns a string representing the current state of the given \a - property. - - The default implementation of this function returns an empty - string. - - \sa QtProperty::valueText() -*/ -QString QtAbstractPropertyManager::valueText(const QtProperty *property) const -{ - Q_UNUSED(property) - return QString(); -} - -/*! - Returns a string representing the current state of the given \a - property. - - The default implementation of this function returns an empty - string. - - \sa QtProperty::valueText() -*/ -QString QtAbstractPropertyManager::displayText(const QtProperty *property) const -{ - Q_UNUSED(property) - return QString(); -} - -/*! - Returns the echo mode representing the current state of the given \a - property. - - The default implementation of this function returns QLineEdit::Normal. - - \sa QtProperty::valueText() -*/ -EchoMode QtAbstractPropertyManager::echoMode(const QtProperty *property) const -{ - Q_UNUSED(property) - return QLineEdit::Normal; -} - -/*! - Creates a property with the given \a name which then is owned by this manager. - - Internally, this function calls the createProperty() and - initializeProperty() functions. - - \sa initializeProperty(), properties() -*/ -QtProperty *QtAbstractPropertyManager::addProperty(const QString &name) -{ - QtProperty *property = createProperty(); - if (property) { - property->setPropertyName(name); - d_ptr->m_properties.insert(property); - initializeProperty(property); - } - return property; -} - -/*! - Creates a property. - - The base implementation produce QtProperty instances; Reimplement - this function to make this manager produce objects of a QtProperty - subclass. - - \sa addProperty(), initializeProperty() -*/ -QtProperty *QtAbstractPropertyManager::createProperty() -{ - return new QtProperty(this); -} - -/*! - \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0 - - This function is called whenever a new valid property pointer has - been created, passing the pointer as parameter. - - The purpose is to let the manager know that the \a property has - been created so that it can provide additional attributes for the - new property, e.g. QtIntPropertyManager adds \l - {QtIntPropertyManager::value()}{value}, \l - {QtIntPropertyManager::minimum()}{minimum} and \l - {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager - subclass adds type specific attributes, this function is pure - virtual and must be reimplemented when deriving from the - QtAbstractPropertyManager class. - - \sa addProperty(), createProperty() -*/ - -/*! - This function is called just before the specified \a property is destroyed. - - The purpose is to let the property manager know that the \a - property is being destroyed so that it can remove the property's - additional attributes. - - \sa clear(), propertyDestroyed() -*/ -void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property) -{ - Q_UNUSED(property) -} - -//////////////////////////////////// - -/*! - \class QtAbstractEditorFactoryBase - - \brief The QtAbstractEditorFactoryBase provides an interface for - editor factories. - - An editor factory is a class that is able to create an editing - widget of a specified type (e.g. line edits or comboboxes) for a - given QtProperty object, and it is used in conjunction with the - QtAbstractPropertyManager and QtAbstractPropertyBrowser classes. - - When using a property browser widget, the properties are created - and managed by implementations of the QtAbstractPropertyManager - class. To ensure that the properties' values will be displayed - using suitable editing widgets, the managers are associated with - objects of QtAbstractEditorFactory subclasses. The property browser - will use these associations to determine which factories it should - use to create the preferred editing widgets. - - Typically, an editor factory is created by subclassing the - QtAbstractEditorFactory template class which inherits - QtAbstractEditorFactoryBase. But note that several ready-made - implementations are available: - - \list - \o QtCheckBoxFactory - \o QtDateEditFactory - \o QtDateTimeEditFactory - \o QtDoubleSpinBoxFactory - \o QtEnumEditorFactory - \o QtLineEditFactory - \o QtScrollBarFactory - \o QtSliderFactory - \o QtSpinBoxFactory - \o QtTimeEditFactory - \o QtVariantEditorFactory - \endlist - - \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser -*/ - -/*! - \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property, - QWidget *parent) = 0 - - Creates an editing widget (with the given \a parent) for the given - \a property. - - This function is reimplemented in QtAbstractEditorFactory template class - which also provides a pure virtual convenience overload of this - function enabling access to the property's manager. - - \sa QtAbstractEditorFactory::createEditor() -*/ - -/*! - \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0) - - Creates an abstract editor factory with the given \a parent. -*/ - -/*! - \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0 - - \internal - - Detaches property manager from factory. - This method is reimplemented in QtAbstractEditorFactory template subclass. - You don't need to reimplement it in your subclasses. Instead implement more convenient - QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass. -*/ - -/*! - \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0 - - \internal - - This method is called when property manager is being destroyed. - Basically it notifies factory not to produce editors for properties owned by \a manager. - You don't need to reimplement it in your subclass. This method is implemented in - QtAbstractEditorFactory template subclass. -*/ - -/*! - \class QtAbstractEditorFactory - - \brief The QtAbstractEditorFactory is the base template class for editor - factories. - - An editor factory is a class that is able to create an editing - widget of a specified type (e.g. line edits or comboboxes) for a - given QtProperty object, and it is used in conjunction with the - QtAbstractPropertyManager and QtAbstractPropertyBrowser classes. - - Note that the QtAbstractEditorFactory functions are using the - PropertyManager template argument class which can be any - QtAbstractPropertyManager subclass. For example: - - \code - QtSpinBoxFactory *factory; - QSet managers = factory->propertyManagers(); - \endcode - - Note that QtSpinBoxFactory by definition creates editing widgets - \e only for properties created by QtIntPropertyManager. - - When using a property browser widget, the properties are created - and managed by implementations of the QtAbstractPropertyManager - class. To ensure that the properties' values will be displayed - using suitable editing widgets, the managers are associated with - objects of QtAbstractEditorFactory subclasses. The property browser will - use these associations to determine which factories it should use - to create the preferred editing widgets. - - A QtAbstractEditorFactory object is capable of producing editors for - several property managers at the same time. To create an - association between this factory and a given manager, use the - addPropertyManager() function. Use the removePropertyManager() function to make - this factory stop producing editors for a given property - manager. Use the propertyManagers() function to retrieve the set of - managers currently associated with this factory. - - Several ready-made implementations of the QtAbstractEditorFactory class - are available: - - \list - \o QtCheckBoxFactory - \o QtDateEditFactory - \o QtDateTimeEditFactory - \o QtDoubleSpinBoxFactory - \o QtEnumEditorFactory - \o QtLineEditFactory - \o QtScrollBarFactory - \o QtSliderFactory - \o QtSpinBoxFactory - \o QtTimeEditFactory - \o QtVariantEditorFactory - \endlist - - When deriving from the QtAbstractEditorFactory class, several pure virtual - functions must be implemented: the connectPropertyManager() function is - used by the factory to connect to the given manager's signals, the - createEditor() function is supposed to create an editor for the - given property controlled by the given manager, and finally the - disconnectPropertyManager() function is used by the factory to disconnect - from the specified manager's signals. - - \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager -*/ - -/*! - \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0) - - Creates an editor factory with the given \a parent. - - \sa addPropertyManager() -*/ - -/*! - \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent) - - Creates an editing widget (with the given \a parent) for the given - \a property. -*/ - -/*! - \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager) - - Adds the given \a manager to this factory's set of managers, - making this factory produce editing widgets for properties created - by the given manager. - - The PropertyManager type is a template argument class, and represents the chosen - QtAbstractPropertyManager subclass. - - \sa propertyManagers(), removePropertyManager() -*/ - -/*! - \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager) - - Removes the given \a manager from this factory's set of - managers. The PropertyManager type is a template argument class, and may be - any QtAbstractPropertyManager subclass. - - \sa propertyManagers(), addPropertyManager() -*/ - -/*! - \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0 - - Connects this factory to the given \a manager's signals. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - This function is used internally by the addPropertyManager() function, and - makes it possible to update an editing widget when the associated - property's data changes. This is typically done in custom slots - responding to the signals emitted by the property's manager, - e.g. QtIntPropertyManager::valueChanged() and - QtIntPropertyManager::rangeChanged(). - - \sa propertyManagers(), disconnectPropertyManager() -*/ - -/*! - \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property, - QWidget *parent) = 0 - - Creates an editing widget with the given \a parent for the - specified \a property created by the given \a manager. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - This function must be implemented in derived classes: It is - recommended to store a pointer to the widget and map it to the - given \a property, since the widget must be updated whenever the - associated property's data changes. This is typically done in - custom slots responding to the signals emitted by the property's - manager, e.g. QtIntPropertyManager::valueChanged() and - QtIntPropertyManager::rangeChanged(). - - \sa connectPropertyManager() -*/ - -/*! - \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0 - - Disconnects this factory from the given \a manager's signals. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - This function is used internally by the removePropertyManager() function. - - \sa propertyManagers(), connectPropertyManager() -*/ - -/*! - \fn QSet QtAbstractEditorFactory::propertyManagers() const - - Returns the factory's set of associated managers. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - \sa addPropertyManager(), removePropertyManager() -*/ - -/*! - \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const - - Returns the property manager for the given \a property, or 0 if - the given \a property doesn't belong to any of this factory's - registered managers. - - The PropertyManager type is a template argument class, and represents the chosen - QtAbstractPropertyManager subclass. - - \sa propertyManagers() -*/ - -/*! - \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager) - - \internal - \reimp -*/ - -//////////////////////////////////// -class QtBrowserItemPrivate -{ -public: - QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent) - : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {} - - void addChild(QtBrowserItem *index, QtBrowserItem *after); - void removeChild(QtBrowserItem *index); - - QtAbstractPropertyBrowser * const m_browser; - QtProperty *m_property; - QtBrowserItem *m_parent; - - QtBrowserItem *q_ptr; - - QList m_children; - -}; - -void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after) -{ - if (m_children.contains(index)) - return; - int idx = m_children.indexOf(after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0; - m_children.insert(idx, index); -} - -void QtBrowserItemPrivate::removeChild(QtBrowserItem *index) -{ - m_children.removeAll(index); -} - - -/*! - \class QtBrowserItem - - \brief The QtBrowserItem class represents a property in - a property browser instance. - - Browser items are created whenever a QtProperty is inserted to the - property browser. A QtBrowserItem uniquely identifies a - browser's item. Thus, if the same QtProperty is inserted multiple - times, each occurrence gets its own unique QtBrowserItem. The - items are owned by QtAbstractPropertyBrowser and automatically - deleted when they are removed from the browser. - - You can traverse a browser's properties by calling parent() and - children(). The property and the browser associated with an item - are available as property() and browser(). - - \sa QtAbstractPropertyBrowser, QtProperty -*/ - -/*! - Returns the property which is accosiated with this item. Note that - several items can be associated with the same property instance in - the same property browser. - - \sa QtAbstractPropertyBrowser::items() -*/ - -QtProperty *QtBrowserItem::property() const -{ - return d_ptr->m_property; -} - -/*! - Returns the parent item of \e this item. Returns 0 if \e this item - is associated with top-level property in item's property browser. - - \sa children() -*/ - -QtBrowserItem *QtBrowserItem::parent() const -{ - return d_ptr->m_parent; -} - -/*! - Returns the children items of \e this item. The properties - reproduced from children items are always the same as - reproduced from associated property' children, for example: - - \code - QtBrowserItem *item; - QList childrenItems = item->children(); - - QList childrenProperties = item->property()->subProperties(); - \endcode - - The \e childrenItems list represents the same list as \e childrenProperties. -*/ - -QList QtBrowserItem::children() const -{ - return d_ptr->m_children; -} - -/*! - Returns the property browser which owns \e this item. -*/ - -QtAbstractPropertyBrowser *QtBrowserItem::browser() const -{ - return d_ptr->m_browser; -} - -QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent) -{ - d_ptr = new QtBrowserItemPrivate(browser, property, parent); - d_ptr->q_ptr = this; -} - -QtBrowserItem::~QtBrowserItem() -{ - delete d_ptr; -} - - -//////////////////////////////////// - -typedef QMap > Map1; -typedef QMap > > Map2; -Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory) -Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews) - -class QtAbstractPropertyBrowserPrivate -{ - QtAbstractPropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser) -public: - QtAbstractPropertyBrowserPrivate(); - - void insertSubTree(QtProperty *property, - QtProperty *parentProperty); - void removeSubTree(QtProperty *property, - QtProperty *parentProperty); - void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty); - void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty); - QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex); - void removeBrowserIndex(QtBrowserItem *index); - void clearIndex(QtBrowserItem *index); - - void slotPropertyInserted(QtProperty *property, - QtProperty *parentProperty, QtProperty *afterProperty); - void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty); - void slotPropertyDestroyed(QtProperty *property); - void slotPropertyDataChanged(QtProperty *property); - - QList m_subItems; - QMap > m_managerToProperties; - QMap > m_propertyToParents; - - QMap m_topLevelPropertyToIndex; - QList m_topLevelIndexes; - QMap > m_propertyToIndexes; - - QtBrowserItem *m_currentItem; -}; - -QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() : - m_currentItem(0) -{ -} - -void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property, - QtProperty *parentProperty) -{ - if (m_propertyToParents.contains(property)) { - // property was already inserted, so its manager is connected - // and all its children are inserted and theirs managers are connected - // we just register new parent (parent has to be new). - m_propertyToParents[property].append(parentProperty); - // don't need to update m_managerToProperties map since - // m_managerToProperties[manager] already contains property. - return; - } - QtAbstractPropertyManager *manager = property->propertyManager(); - if (m_managerToProperties[manager].isEmpty()) { - // connect manager's signals - q_ptr->connect(manager, SIGNAL(propertyInserted(QtProperty *, - QtProperty *, QtProperty *)), - q_ptr, SLOT(slotPropertyInserted(QtProperty *, - QtProperty *, QtProperty *))); - q_ptr->connect(manager, SIGNAL(propertyRemoved(QtProperty *, - QtProperty *)), - q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - q_ptr->connect(manager, SIGNAL(propertyDestroyed(QtProperty *)), - q_ptr, SLOT(slotPropertyDestroyed(QtProperty *))); - q_ptr->connect(manager, SIGNAL(propertyChanged(QtProperty *)), - q_ptr, SLOT(slotPropertyDataChanged(QtProperty *))); - } - m_managerToProperties[manager].append(property); - m_propertyToParents[property].append(parentProperty); - - QList subList = property->subProperties(); - QListIterator itSub(subList); - while (itSub.hasNext()) { - QtProperty *subProperty = itSub.next(); - insertSubTree(subProperty, property); - } -} - -void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property, - QtProperty *parentProperty) -{ - if (!m_propertyToParents.contains(property)) { - // ASSERT - return; - } - - m_propertyToParents[property].removeAll(parentProperty); - if (!m_propertyToParents[property].isEmpty()) - return; - - m_propertyToParents.remove(property); - QtAbstractPropertyManager *manager = property->propertyManager(); - m_managerToProperties[manager].removeAll(property); - if (m_managerToProperties[manager].isEmpty()) { - // disconnect manager's signals - q_ptr->disconnect(manager, SIGNAL(propertyInserted(QtProperty *, - QtProperty *, QtProperty *)), - q_ptr, SLOT(slotPropertyInserted(QtProperty *, - QtProperty *, QtProperty *))); - q_ptr->disconnect(manager, SIGNAL(propertyRemoved(QtProperty *, - QtProperty *)), - q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - q_ptr->disconnect(manager, SIGNAL(propertyDestroyed(QtProperty *)), - q_ptr, SLOT(slotPropertyDestroyed(QtProperty *))); - q_ptr->disconnect(manager, SIGNAL(propertyChanged(QtProperty *)), - q_ptr, SLOT(slotPropertyDataChanged(QtProperty *))); - - m_managerToProperties.remove(manager); - } - - QList subList = property->subProperties(); - QListIterator itSub(subList); - while (itSub.hasNext()) { - QtProperty *subProperty = itSub.next(); - removeSubTree(subProperty, property); - } -} - -void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) -{ - QMap parentToAfter; - if (afterProperty) { - QMap >::ConstIterator it = - m_propertyToIndexes.find(afterProperty); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - QtBrowserItem *parentIdx = idx->parent(); - if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx)) - parentToAfter[idx->parent()] = idx; - } - } else if (parentProperty) { - QMap >::ConstIterator it = - m_propertyToIndexes.find(parentProperty); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - parentToAfter[idx] = 0; - } - } else { - parentToAfter[0] = 0; - } - - const QMap::ConstIterator pcend = parentToAfter.constEnd(); - for (QMap::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it) - createBrowserIndex(property, it.key(), it.value()); -} - -QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property, - QtBrowserItem *parentIndex, QtBrowserItem *afterIndex) -{ - QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex); - if (parentIndex) { - parentIndex->d_ptr->addChild(newIndex, afterIndex); - } else { - m_topLevelPropertyToIndex[property] = newIndex; - m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex); - } - m_propertyToIndexes[property].append(newIndex); - - q_ptr->itemInserted(newIndex, afterIndex); - - QList subItems = property->subProperties(); - QListIterator itChild(subItems); - QtBrowserItem *afterChild = 0; - while (itChild.hasNext()) { - QtProperty *child = itChild.next(); - afterChild = createBrowserIndex(child, newIndex, afterChild); - } - return newIndex; -} - -void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty) -{ - QList toRemove; - QMap >::ConstIterator it = - m_propertyToIndexes.find(property); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - QtBrowserItem *parentIdx = idx->parent(); - if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx)) - toRemove.append(idx); - } - - QListIterator itRemove(toRemove); - while (itRemove.hasNext()) { - QtBrowserItem *index = itRemove.next(); - removeBrowserIndex(index); - } -} - -void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index) -{ - QList children = index->children(); - for (int i = children.count(); i > 0; i--) { - removeBrowserIndex(children.at(i - 1)); - } - - q_ptr->itemRemoved(index); - - if (index->parent()) { - index->parent()->d_ptr->removeChild(index); - } else { - m_topLevelPropertyToIndex.remove(index->property()); - m_topLevelIndexes.removeAll(index); - } - - QtProperty *property = index->property(); - - m_propertyToIndexes[property].removeAll(index); - if (m_propertyToIndexes[property].isEmpty()) - m_propertyToIndexes.remove(property); - - delete index; -} - -void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index) -{ - QList children = index->children(); - QListIterator itChild(children); - while (itChild.hasNext()) { - clearIndex(itChild.next()); - } - delete index; -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property, - QtProperty *parentProperty, QtProperty *afterProperty) -{ - if (!m_propertyToParents.contains(parentProperty)) - return; - createBrowserIndexes(property, parentProperty, afterProperty); - insertSubTree(property, parentProperty); - //q_ptr->propertyInserted(property, parentProperty, afterProperty); -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property, - QtProperty *parentProperty) -{ - if (!m_propertyToParents.contains(parentProperty)) - return; - removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call - //q_ptr->propertyRemoved(property, parentProperty); - removeBrowserIndexes(property, parentProperty); -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (!m_subItems.contains(property)) - return; - q_ptr->removeProperty(property); -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property) -{ - if (!m_propertyToParents.contains(property)) - return; - - QMap >::ConstIterator it = - m_propertyToIndexes.find(property); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - q_ptr->itemChanged(idx); - } - //q_ptr->propertyChanged(property); -} - -/*! - \class QtAbstractPropertyBrowser - - \brief QtAbstractPropertyBrowser provides a base class for - implementing property browsers. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - \image qtpropertybrowser.png - - The top level properties can be retrieved using the - properties() function. To traverse each property's - subproperties, use the QtProperty::subProperties() function. In - addition, the set of top level properties can be manipulated using - the addProperty(), insertProperty() and removeProperty() - functions. Note that the QtProperty class provides a corresponding - set of functions making it possible to manipulate the set of - subproperties as well. - - To remove all the properties from the property browser widget, use - the clear() function. This function will clear the editor, but it - will not delete the properties since they can still be used in - other editors. - - The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. A manager - can handle (i.e. create and manage) properties of a given type. In - the property browser the managers are associated with - implementations of the QtAbstractEditorFactory: A factory is a - class able to create an editing widget of a specified type. - - When using a property browser widget, managers must be created for - each of the required property types before the properties - themselves can be created. To ensure that the properties' values - will be displayed using suitable editing widgets, the managers - must be associated with objects of the preferred factory - implementations using the setFactoryForManager() function. The - property browser will use these associations to determine which - factory it should use to create the preferred editing widget. - - Note that a factory can be associated with many managers, but a - manager can only be associated with one single factory within the - context of a single property browser. The associations between - managers and factories can at any time be removed using the - unsetFactoryForManager() function. - - Whenever the property data changes or a property is inserted or - removed, the itemChanged(), itemInserted() or - itemRemoved() functions are called, respectively. These - functions must be reimplemented in derived classes in order to - update the property browser widget. Be aware that some property - instances can appear several times in an abstract tree - structure. For example: - - \table 100% - \row - \o - \code - QtProperty *property1, *property2, *property3; - - property2->addSubProperty(property1); - property3->addSubProperty(property2); - - QtAbstractPropertyBrowser *editor; - - editor->addProperty(property1); - editor->addProperty(property2); - editor->addProperty(property3); - \endcode - \o \image qtpropertybrowser-duplicate.png - \endtable - - The addProperty() function returns a QtBrowserItem that uniquely - identifies the created item. - - To make a property editable in the property browser, the - createEditor() function must be called to provide the - property with a suitable editing widget. - - Note that there are two ready-made property browser - implementations: - - \list - \o QtGroupBoxPropertyBrowser - \o QtTreePropertyBrowser - \endlist - - \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase -*/ - -/*! - \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager, - QtAbstractEditorFactory *factory) - - Connects the given \a manager to the given \a factory, ensuring - that properties of the \a manager's type will be displayed with an - editing widget suitable for their value. - - For example: - - \code - QtIntPropertyManager *intManager; - QtDoublePropertyManager *doubleManager; - - QtProperty *myInteger = intManager->addProperty(); - QtProperty *myDouble = doubleManager->addProperty(); - - QtSpinBoxFactory *spinBoxFactory; - QtDoubleSpinBoxFactory *doubleSpinBoxFactory; - - QtAbstractPropertyBrowser *editor; - editor->setFactoryForManager(intManager, spinBoxFactory); - editor->setFactoryForManager(doubleManager, doubleSpinBoxFactory); - - editor->addProperty(myInteger); - editor->addProperty(myDouble); - \endcode - - In this example the \c myInteger property's value is displayed - with a QSpinBox widget, while the \c myDouble property's value is - displayed with a QDoubleSpinBox widget. - - Note that a factory can be associated with many managers, but a - manager can only be associated with one single factory. If the - given \a manager already is associated with another factory, the - old association is broken before the new one established. - - This function ensures that the given \a manager and the given \a - factory are compatible, and it automatically calls the - QtAbstractEditorFactory::addPropertyManager() function if necessary. - - \sa unsetFactoryForManager() -*/ - -/*! - \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem, - QtBrowserItem *precedingItem) = 0 - - This function is called to update the widget whenever a property - is inserted or added to the property browser, passing pointers to - the \a insertedItem of property and the specified - \a precedingItem as parameters. - - If \a precedingItem is 0, the \a insertedItem was put at - the beginning of its parent item's list of subproperties. If - the parent of \a insertedItem is 0, the \a insertedItem was added as a top - level property of \e this property browser. - - This function must be reimplemented in derived classes. Note that - if the \a insertedItem's property has subproperties, this - method will be called for those properties as soon as the current call is finished. - - \sa insertProperty(), addProperty() -*/ - -/*! - \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0 - - This function is called to update the widget whenever a property - is removed from the property browser, passing the pointer to the - \a item of the property as parameters. The passed \a item is - deleted just after this call is finished. - - If the the parent of \a item is 0, the removed \a item was a - top level property in this editor. - - This function must be reimplemented in derived classes. Note that - if the removed \a item's property has subproperties, this - method will be called for those properties just before the current call is started. - - \sa removeProperty() -*/ - -/*! - \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0 - - This function is called whenever a property's data changes, - passing a pointer to the \a item of property as parameter. - - This function must be reimplemented in derived classes in order to - update the property browser widget whenever a property's name, - tool tip, status tip, "what's this" text, value text or value icon - changes. - - Note that if the property browser contains several occurrences of - the same property, this method will be called once for each - occurrence (with a different item each time). - - \sa QtProperty, items() -*/ - -/*! - Creates an abstract property browser with the given \a parent. -*/ -QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent) - : QWidget(parent) -{ - d_ptr = new QtAbstractPropertyBrowserPrivate; - d_ptr->q_ptr = this; - -} - -/*! - Destroys the property browser, and destroys all the items that were - created by this property browser. - - Note that the properties that were displayed in the editor are not - deleted since they still can be used in other editors. Neither - does the destructor delete the property managers and editor - factories that were used by this property browser widget unless - this widget was their parent. - - \sa QtAbstractPropertyManager::~QtAbstractPropertyManager() -*/ -QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser() -{ - QList indexes = topLevelItems(); - QListIterator itItem(indexes); - while (itItem.hasNext()) - d_ptr->clearIndex(itItem.next()); - delete d_ptr; -} - -/*! - Returns the property browser's list of top level properties. - - To traverse the subproperties, use the QtProperty::subProperties() - function. - - \sa addProperty(), insertProperty(), removeProperty() -*/ -QList QtAbstractPropertyBrowser::properties() const -{ - return d_ptr->m_subItems; -} - -/*! - Returns the property browser's list of all items associated - with the given \a property. - - There is one item per instance of the property in the browser. - - \sa topLevelItem() -*/ - -QList QtAbstractPropertyBrowser::items(QtProperty *property) const -{ - return d_ptr->m_propertyToIndexes.value(property); -} - -/*! - Returns the top-level items associated with the given \a property. - - Returns 0 if \a property wasn't inserted into this property - browser or isn't a top-level one. - - \sa topLevelItems(), items() -*/ - -QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const -{ - return d_ptr->m_topLevelPropertyToIndex.value(property); -} - -/*! - Returns the list of top-level items. - - \sa topLevelItem() -*/ - -QList QtAbstractPropertyBrowser::topLevelItems() const -{ - return d_ptr->m_topLevelIndexes; -} - -/*! - Removes all the properties from the editor, but does not delete - them since they can still be used in other editors. - - \sa removeProperty(), QtAbstractPropertyManager::clear() -*/ -void QtAbstractPropertyBrowser::clear() -{ - QList subList = properties(); - QListIterator itSub(subList); - itSub.toBack(); - while (itSub.hasPrevious()) { - QtProperty *property = itSub.previous(); - removeProperty(property); - } -} - -/*! - Appends the given \a property (and its subproperties) to the - property browser's list of top level properties. Returns the item - created by property browser which is associated with the \a property. - In order to get all children items created by the property - browser in this call, the returned item should be traversed. - - If the specified \a property is already added, this function does - nothing and returns 0. - - \sa insertProperty(), QtProperty::addSubProperty(), properties() -*/ -QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property) -{ - QtProperty *afterProperty = 0; - if (d_ptr->m_subItems.count() > 0) - afterProperty = d_ptr->m_subItems.last(); - return insertProperty(property, afterProperty); -} - -/*! - \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property, - QtProperty *afterProperty) - - Inserts the given \a property (and its subproperties) after - the specified \a afterProperty in the browser's list of top - level properties. Returns item created by property browser which - is associated with the \a property. In order to get all children items - created by the property browser in this call returned item should be traversed. - - If the specified \a afterProperty is 0, the given \a property is - inserted at the beginning of the list. If \a property is - already inserted, this function does nothing and returns 0. - - \sa addProperty(), QtProperty::insertSubProperty(), properties() -*/ -QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property, - QtProperty *afterProperty) -{ - if (!property) - return 0; - - // if item is already inserted in this item then cannot add. - QList pendingList = properties(); - int pos = 0; - int newPos = 0; - while (pos < pendingList.count()) { - QtProperty *prop = pendingList.at(pos); - if (prop == property) - return 0; - if (prop == afterProperty) { - newPos = pos + 1; - } - pos++; - } - d_ptr->createBrowserIndexes(property, 0, afterProperty); - - // traverse inserted subtree and connect to manager's signals - d_ptr->insertSubTree(property, 0); - - d_ptr->m_subItems.insert(newPos, property); - //propertyInserted(property, 0, properAfterProperty); - return topLevelItem(property); -} - -/*! - Removes the specified \a property (and its subproperties) from the - property browser's list of top level properties. All items - that were associated with the given \a property and its children - are deleted. - - Note that the properties are \e not deleted since they can still - be used in other editors. - - \sa clear(), QtProperty::removeSubProperty(), properties() -*/ -void QtAbstractPropertyBrowser::removeProperty(QtProperty *property) -{ - if (!property) - return; - - QList pendingList = properties(); - int pos = 0; - while (pos < pendingList.count()) { - if (pendingList.at(pos) == property) { - d_ptr->m_subItems.removeAt(pos); //perhaps this two lines - d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call. - //propertyRemoved(property, 0); - - d_ptr->removeBrowserIndexes(property, 0); - - // when item is deleted, item will call removeItem for top level items, - // and itemRemoved for nested items. - - return; - } - pos++; - } -} - -/*! - Creates an editing widget (with the given \a parent) for the given - \a property according to the previously established associations - between property managers and editor factories. - - If the property is created by a property manager which was not - associated with any of the existing factories in \e this property - editor, the function returns 0. - - To make a property editable in the property browser, the - createEditor() function must be called to provide the - property with a suitable editing widget. - - Reimplement this function to provide additional decoration for the - editing widgets created by the installed factories. - - \sa setFactoryForManager() -*/ -QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property, - QWidget *parent) -{ - QtAbstractEditorFactoryBase *factory = 0; - QtAbstractPropertyManager *manager = property->propertyManager(); - - if (m_viewToManagerToFactory()->contains(this) && - (*m_viewToManagerToFactory())[this].contains(manager)) { - factory = (*m_viewToManagerToFactory())[this][manager]; - } - - if (!factory) - return 0; - return factory->createEditor(property, parent); -} - -bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager, - QtAbstractEditorFactoryBase *abstractFactory) -{ - bool connectNeeded = false; - if (!m_managerToFactoryToViews()->contains(abstractManager) || - !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory)) { - connectNeeded = true; - } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory] - .contains(this)) { - return connectNeeded; - } - - if (m_viewToManagerToFactory()->contains(this) && - (*m_viewToManagerToFactory())[this].contains(abstractManager)) { - unsetFactoryForManager(abstractManager); - } - - (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this); - (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory; - - return connectNeeded; -} - -/*! - Removes the association between the given \a manager and the - factory bound to it, automatically calling the - QtAbstractEditorFactory::removePropertyManager() function if necessary. - - \sa setFactoryForManager() -*/ -void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager) -{ - if (!m_viewToManagerToFactory()->contains(this) || - !(*m_viewToManagerToFactory())[this].contains(manager)) { - return; - } - - QtAbstractEditorFactoryBase *abstractFactory = - (*m_viewToManagerToFactory())[this][manager]; - (*m_viewToManagerToFactory())[this].remove(manager); - if ((*m_viewToManagerToFactory())[this].isEmpty()) { - (*m_viewToManagerToFactory()).remove(this); - } - - (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this); - if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) { - (*m_managerToFactoryToViews())[manager].remove(abstractFactory); - abstractFactory->breakConnection(manager); - if ((*m_managerToFactoryToViews())[manager].isEmpty()) { - (*m_managerToFactoryToViews()).remove(manager); - } - } -} - -/*! - Returns the current item in the property browser. - - \sa setCurrentItem() -*/ -QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const -{ - return d_ptr->m_currentItem; -} - -/*! - Sets the current item in the property browser to \a item. - - \sa currentItem(), currentItemChanged() -*/ -void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item) -{ - QtBrowserItem *oldItem = d_ptr->m_currentItem; - d_ptr->m_currentItem = item; - if (oldItem != item) - emit currentItemChanged(item); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtpropertybrowser.cpp" diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.h b/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.h deleted file mode 100644 index 6b734f0c..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.h +++ /dev/null @@ -1,335 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTPROPERTYBROWSER_H -#define QTPROPERTYBROWSER_H - -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -#if defined(Q_OS_WIN) -# if !defined(QT_QTPROPERTYBROWSER_EXPORT) && !defined(QT_QTPROPERTYBROWSER_IMPORT) -# define QT_QTPROPERTYBROWSER_EXPORT -# elif defined(QT_QTPROPERTYBROWSER_IMPORT) -# if defined(QT_QTPROPERTYBROWSER_EXPORT) -# undef QT_QTPROPERTYBROWSER_EXPORT -# endif -# define QT_QTPROPERTYBROWSER_EXPORT __declspec(dllimport) -# elif defined(QT_QTPROPERTYBROWSER_EXPORT) -# undef QT_QTPROPERTYBROWSER_EXPORT -# define QT_QTPROPERTYBROWSER_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTPROPERTYBROWSER_EXPORT -#endif - -typedef QLineEdit::EchoMode EchoMode; - -class QtAbstractPropertyManager; -class QtPropertyPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtProperty -{ -public: - virtual ~QtProperty(); - - QList subProperties() const; - - QtAbstractPropertyManager *propertyManager() const; - - QString toolTip() const; - QString statusTip() const; - QString whatsThis() const; - QString propertyName() const; - bool isEnabled() const; - bool isModified() const; - - bool hasValue() const; - QIcon valueIcon() const; - QString valueText() const; - QString displayText() const; - - void setToolTip(const QString &text); - void setStatusTip(const QString &text); - void setWhatsThis(const QString &text); - void setPropertyName(const QString &text); - void setEnabled(bool enable); - void setModified(bool modified); - - void addSubProperty(QtProperty *property); - void insertSubProperty(QtProperty *property, QtProperty *afterProperty); - void removeSubProperty(QtProperty *property); -protected: - explicit QtProperty(QtAbstractPropertyManager *manager); - void propertyChanged(); -private: - friend class QtAbstractPropertyManager; - QtPropertyPrivate *d_ptr; -}; - -class QtAbstractPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtAbstractPropertyManager : public QObject -{ - Q_OBJECT -public: - - explicit QtAbstractPropertyManager(QObject *parent = 0); - ~QtAbstractPropertyManager(); - - QSet properties() const; - void clear() const; - - QtProperty *addProperty(const QString &name = QString()); -Q_SIGNALS: - - void propertyInserted(QtProperty *property, - QtProperty *parent, QtProperty *after); - void propertyChanged(QtProperty *property); - void propertyRemoved(QtProperty *property, QtProperty *parent); - void propertyDestroyed(QtProperty *property); -protected: - virtual bool hasValue(const QtProperty *property) const; - virtual QIcon valueIcon(const QtProperty *property) const; - virtual QString valueText(const QtProperty *property) const; - virtual QString displayText(const QtProperty *property) const; - virtual EchoMode echoMode(const QtProperty *) const; - virtual void initializeProperty(QtProperty *property) = 0; - virtual void uninitializeProperty(QtProperty *property); - virtual QtProperty *createProperty(); -private: - friend class QtProperty; - QtAbstractPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtAbstractPropertyManager) - Q_DISABLE_COPY(QtAbstractPropertyManager) -}; - -class QT_QTPROPERTYBROWSER_EXPORT QtAbstractEditorFactoryBase : public QObject -{ - Q_OBJECT -public: - virtual QWidget *createEditor(QtProperty *property, QWidget *parent) = 0; -protected: - explicit QtAbstractEditorFactoryBase(QObject *parent = 0) - : QObject(parent) {} - - virtual void breakConnection(QtAbstractPropertyManager *manager) = 0; -protected Q_SLOTS: - virtual void managerDestroyed(QObject *manager) = 0; - - friend class QtAbstractPropertyBrowser; -}; - -template -class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase -{ -public: - explicit QtAbstractEditorFactory(QObject *parent) : QtAbstractEditorFactoryBase(parent) {} - QWidget *createEditor(QtProperty *property, QWidget *parent) - { - QSetIterator it(m_managers); - while (it.hasNext()) { - PropertyManager *manager = it.next(); - if (manager == property->propertyManager()) { - return createEditor(manager, property, parent); - } - } - return 0; - } - void addPropertyManager(PropertyManager *manager) - { - if (m_managers.contains(manager)) - return; - m_managers.insert(manager); - connectPropertyManager(manager); - connect(manager, SIGNAL(destroyed(QObject *)), - this, SLOT(managerDestroyed(QObject *))); - } - void removePropertyManager(PropertyManager *manager) - { - if (!m_managers.contains(manager)) - return; - disconnect(manager, SIGNAL(destroyed(QObject *)), - this, SLOT(managerDestroyed(QObject *))); - disconnectPropertyManager(manager); - m_managers.remove(manager); - } - QSet propertyManagers() const - { - return m_managers; - } - PropertyManager *propertyManager(QtProperty *property) const - { - QtAbstractPropertyManager *manager = property->propertyManager(); - QSetIterator itManager(m_managers); - while (itManager.hasNext()) { - PropertyManager *m = itManager.next(); - if (m == manager) { - return m; - } - } - return 0; - } -protected: - virtual void connectPropertyManager(PropertyManager *manager) = 0; - virtual QWidget *createEditor(PropertyManager *manager, QtProperty *property, - QWidget *parent) = 0; - virtual void disconnectPropertyManager(PropertyManager *manager) = 0; - void managerDestroyed(QObject *manager) - { - QSetIterator it(m_managers); - while (it.hasNext()) { - PropertyManager *m = it.next(); - if (m == manager) { - m_managers.remove(m); - return; - } - } - } -private: - void breakConnection(QtAbstractPropertyManager *manager) - { - QSetIterator it(m_managers); - while (it.hasNext()) { - PropertyManager *m = it.next(); - if (m == manager) { - removePropertyManager(m); - return; - } - } - } -private: - QSet m_managers; - friend class QtAbstractPropertyEditor; -}; - -class QtAbstractPropertyBrowser; -class QtBrowserItemPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtBrowserItem -{ -public: - QtProperty *property() const; - QtBrowserItem *parent() const; - QList children() const; - QtAbstractPropertyBrowser *browser() const; -private: - explicit QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent); - ~QtBrowserItem(); - QtBrowserItemPrivate *d_ptr; - friend class QtAbstractPropertyBrowserPrivate; -}; - -class QtAbstractPropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtAbstractPropertyBrowser : public QWidget -{ - Q_OBJECT -public: - - explicit QtAbstractPropertyBrowser(QWidget *parent = 0); - ~QtAbstractPropertyBrowser(); - - QList properties() const; - QList items(QtProperty *property) const; - QtBrowserItem *topLevelItem(QtProperty *property) const; - QList topLevelItems() const; - void clear(); - - template - void setFactoryForManager(PropertyManager *manager, - QtAbstractEditorFactory *factory) { - QtAbstractPropertyManager *abstractManager = manager; - QtAbstractEditorFactoryBase *abstractFactory = factory; - - if (addFactory(abstractManager, abstractFactory)) - factory->addPropertyManager(manager); - } - - void unsetFactoryForManager(QtAbstractPropertyManager *manager); - - QtBrowserItem *currentItem() const; - void setCurrentItem(QtBrowserItem *); - -Q_SIGNALS: - void currentItemChanged(QtBrowserItem *); - -public Q_SLOTS: - - QtBrowserItem *addProperty(QtProperty *property); - QtBrowserItem *insertProperty(QtProperty *property, QtProperty *afterProperty); - void removeProperty(QtProperty *property); - -protected: - - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) = 0; - virtual void itemRemoved(QtBrowserItem *item) = 0; - // can be tooltip, statustip, whatsthis, name, icon, text. - virtual void itemChanged(QtBrowserItem *item) = 0; - - virtual QWidget *createEditor(QtProperty *property, QWidget *parent); -private: - - bool addFactory(QtAbstractPropertyManager *abstractManager, - QtAbstractEditorFactoryBase *abstractFactory); - - QtAbstractPropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtAbstractPropertyBrowser) - Q_DISABLE_COPY(QtAbstractPropertyBrowser) - Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, - QtProperty *, QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, - QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDataChanged(QtProperty *)) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif // QTPROPERTYBROWSER_H diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.pri b/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.pri deleted file mode 100644 index 27978278..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.pri +++ /dev/null @@ -1,32 +0,0 @@ -include(../common.pri) -greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - -qtpropertybrowser-uselib:!qtpropertybrowser-buildlib { - LIBS += -L$$QTPROPERTYBROWSER_LIBDIR -l$$QTPROPERTYBROWSER_LIBNAME -} else { - DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 - SOURCES += $$PWD/qtpropertybrowser.cpp \ - $$PWD/qtpropertymanager.cpp \ - $$PWD/qteditorfactory.cpp \ - $$PWD/qtvariantproperty.cpp \ - $$PWD/qttreepropertybrowser.cpp \ - $$PWD/qtbuttonpropertybrowser.cpp \ - $$PWD/qtgroupboxpropertybrowser.cpp \ - $$PWD/qtpropertybrowserutils.cpp - HEADERS += $$PWD/qtpropertybrowser.h \ - $$PWD/qtpropertymanager.h \ - $$PWD/qteditorfactory.h \ - $$PWD/qtvariantproperty.h \ - $$PWD/qttreepropertybrowser.h \ - $$PWD/qtbuttonpropertybrowser.h \ - $$PWD/qtgroupboxpropertybrowser.h \ - $$PWD/qtpropertybrowserutils_p.h - RESOURCES += $$PWD/qtpropertybrowser.qrc -} - -win32 { - contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTPROPERTYBROWSER_EXPORT - else:qtpropertybrowser-uselib:DEFINES += QT_QTPROPERTYBROWSER_IMPORT -} diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.qrc b/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.qrc deleted file mode 100644 index 03e9c561..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowser.qrc +++ /dev/null @@ -1,23 +0,0 @@ - - - images/cursor-arrow.png - images/cursor-busy.png - images/cursor-closedhand.png - images/cursor-cross.png - images/cursor-forbidden.png - images/cursor-hand.png - images/cursor-hsplit.png - images/cursor-ibeam.png - images/cursor-openhand.png - images/cursor-sizeall.png - images/cursor-sizeb.png - images/cursor-sizef.png - images/cursor-sizeh.png - images/cursor-sizev.png - images/cursor-uparrow.png - images/cursor-vsplit.png - images/cursor-wait.png - images/cursor-whatsthis.png - - - diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowserutils.cpp b/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowserutils.cpp deleted file mode 100644 index f1cd6129..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowserutils.cpp +++ /dev/null @@ -1,456 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtpropertybrowserutils_p.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -QtCursorDatabase::QtCursorDatabase() -{ - appendCursor(Qt::ArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Arrow"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-arrow.png"))); - appendCursor(Qt::UpArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Up Arrow"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-uparrow.png"))); - appendCursor(Qt::CrossCursor, QCoreApplication::translate("QtCursorDatabase", "Cross"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-cross.png"))); - appendCursor(Qt::WaitCursor, QCoreApplication::translate("QtCursorDatabase", "Wait"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-wait.png"))); - appendCursor(Qt::IBeamCursor, QCoreApplication::translate("QtCursorDatabase", "IBeam"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-ibeam.png"))); - appendCursor(Qt::SizeVerCursor, QCoreApplication::translate("QtCursorDatabase", "Size Vertical"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizev.png"))); - appendCursor(Qt::SizeHorCursor, QCoreApplication::translate("QtCursorDatabase", "Size Horizontal"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeh.png"))); - appendCursor(Qt::SizeFDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Backslash"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizef.png"))); - appendCursor(Qt::SizeBDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Slash"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeb.png"))); - appendCursor(Qt::SizeAllCursor, QCoreApplication::translate("QtCursorDatabase", "Size All"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeall.png"))); - appendCursor(Qt::BlankCursor, QCoreApplication::translate("QtCursorDatabase", "Blank"), - QIcon()); - appendCursor(Qt::SplitVCursor, QCoreApplication::translate("QtCursorDatabase", "Split Vertical"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-vsplit.png"))); - appendCursor(Qt::SplitHCursor, QCoreApplication::translate("QtCursorDatabase", "Split Horizontal"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hsplit.png"))); - appendCursor(Qt::PointingHandCursor, QCoreApplication::translate("QtCursorDatabase", "Pointing Hand"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hand.png"))); - appendCursor(Qt::ForbiddenCursor, QCoreApplication::translate("QtCursorDatabase", "Forbidden"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-forbidden.png"))); - appendCursor(Qt::OpenHandCursor, QCoreApplication::translate("QtCursorDatabase", "Open Hand"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-openhand.png"))); - appendCursor(Qt::ClosedHandCursor, QCoreApplication::translate("QtCursorDatabase", "Closed Hand"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-closedhand.png"))); - appendCursor(Qt::WhatsThisCursor, QCoreApplication::translate("QtCursorDatabase", "What's This"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-whatsthis.png"))); - appendCursor(Qt::BusyCursor, QCoreApplication::translate("QtCursorDatabase", "Busy"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-busy.png"))); -} - -void QtCursorDatabase::clear() -{ - m_cursorNames.clear(); - m_cursorIcons.clear(); - m_valueToCursorShape.clear(); - m_cursorShapeToValue.clear(); -} - -void QtCursorDatabase::appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon) -{ - if (m_cursorShapeToValue.contains(shape)) - return; - const int value = m_cursorNames.count(); - m_cursorNames.append(name); - m_cursorIcons.insert(value, icon); - m_valueToCursorShape.insert(value, shape); - m_cursorShapeToValue.insert(shape, value); -} - -QStringList QtCursorDatabase::cursorShapeNames() const -{ - return m_cursorNames; -} - -QMap QtCursorDatabase::cursorShapeIcons() const -{ - return m_cursorIcons; -} - -QString QtCursorDatabase::cursorToShapeName(const QCursor &cursor) const -{ - int val = cursorToValue(cursor); - if (val >= 0) - return m_cursorNames.at(val); - return QString(); -} - -QIcon QtCursorDatabase::cursorToShapeIcon(const QCursor &cursor) const -{ - int val = cursorToValue(cursor); - return m_cursorIcons.value(val); -} - -int QtCursorDatabase::cursorToValue(const QCursor &cursor) const -{ -#ifndef QT_NO_CURSOR - Qt::CursorShape shape = cursor.shape(); - if (m_cursorShapeToValue.contains(shape)) - return m_cursorShapeToValue[shape]; -#endif - return -1; -} - -#ifndef QT_NO_CURSOR -QCursor QtCursorDatabase::valueToCursor(int value) const -{ - if (m_valueToCursorShape.contains(value)) - return QCursor(m_valueToCursorShape[value]); - return QCursor(); -} -#endif - -QPixmap QtPropertyBrowserUtils::brushValuePixmap(const QBrush &b) -{ - QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - - QPainter painter(&img); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(0, 0, img.width(), img.height(), b); - QColor color = b.color(); - if (color.alpha() != 255) { // indicate alpha by an inset - QBrush opaqueBrush = b; - color.setAlpha(255); - opaqueBrush.setColor(color); - painter.fillRect(img.width() / 4, img.height() / 4, - img.width() / 2, img.height() / 2, opaqueBrush); - } - painter.end(); - return QPixmap::fromImage(img); -} - -QIcon QtPropertyBrowserUtils::brushValueIcon(const QBrush &b) -{ - return QIcon(brushValuePixmap(b)); -} - -QString QtPropertyBrowserUtils::colorValueText(const QColor &c) -{ - return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2, %3] (%4)") - .arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha()); -} - -QPixmap QtPropertyBrowserUtils::fontValuePixmap(const QFont &font) -{ - QFont f = font; - QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - QPainter p(&img); - p.setRenderHint(QPainter::TextAntialiasing, true); - p.setRenderHint(QPainter::Antialiasing, true); - f.setPointSize(13); - p.setFont(f); - QTextOption t; - t.setAlignment(Qt::AlignCenter); - p.drawText(QRect(0, 0, 16, 16), QString(QLatin1Char('A')), t); - return QPixmap::fromImage(img); -} - -QIcon QtPropertyBrowserUtils::fontValueIcon(const QFont &f) -{ - return QIcon(fontValuePixmap(f)); -} - -QString QtPropertyBrowserUtils::fontValueText(const QFont &f) -{ - return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2]") - .arg(f.family()).arg(f.pointSize()); -} - - -QtBoolEdit::QtBoolEdit(QWidget *parent) : - QWidget(parent), - m_checkBox(new QCheckBox(this)), - m_textVisible(true) -{ - QHBoxLayout *lt = new QHBoxLayout; - if (QApplication::layoutDirection() == Qt::LeftToRight) - lt->setContentsMargins(4, 0, 0, 0); - else - lt->setContentsMargins(0, 0, 4, 0); - lt->addWidget(m_checkBox); - setLayout(lt); - connect(m_checkBox, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool))); - setFocusProxy(m_checkBox); - m_checkBox->setText(tr("True")); -} - -void QtBoolEdit::setTextVisible(bool textVisible) -{ - if (m_textVisible == textVisible) - return; - - m_textVisible = textVisible; - if (m_textVisible) - m_checkBox->setText(isChecked() ? tr("True") : tr("False")); - else - m_checkBox->setText(QString()); -} - -Qt::CheckState QtBoolEdit::checkState() const -{ - return m_checkBox->checkState(); -} - -void QtBoolEdit::setCheckState(Qt::CheckState state) -{ - m_checkBox->setCheckState(state); -} - -bool QtBoolEdit::isChecked() const -{ - return m_checkBox->isChecked(); -} - -void QtBoolEdit::setChecked(bool c) -{ - m_checkBox->setChecked(c); - if (!m_textVisible) - return; - m_checkBox->setText(isChecked() ? tr("True") : tr("False")); -} - -bool QtBoolEdit::blockCheckBoxSignals(bool block) -{ - return m_checkBox->blockSignals(block); -} - -void QtBoolEdit::mousePressEvent(QMouseEvent *event) -{ - if (event->buttons() == Qt::LeftButton) { - m_checkBox->click(); - event->accept(); - } else { - QWidget::mousePressEvent(event); - } -} - -void QtBoolEdit::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - - - -QtKeySequenceEdit::QtKeySequenceEdit(QWidget *parent) - : QWidget(parent), m_num(0), m_lineEdit(new QLineEdit(this)) -{ - QHBoxLayout *layout = new QHBoxLayout(this); - layout->addWidget(m_lineEdit); - layout->setMargin(0); - m_lineEdit->installEventFilter(this); - m_lineEdit->setReadOnly(true); - m_lineEdit->setFocusProxy(this); - setFocusPolicy(m_lineEdit->focusPolicy()); - setAttribute(Qt::WA_InputMethodEnabled); -} - -bool QtKeySequenceEdit::eventFilter(QObject *o, QEvent *e) -{ - if (o == m_lineEdit && e->type() == QEvent::ContextMenu) { - QContextMenuEvent *c = static_cast(e); - QMenu *menu = m_lineEdit->createStandardContextMenu(); - const QList actions = menu->actions(); - QListIterator itAction(actions); - while (itAction.hasNext()) { - QAction *action = itAction.next(); - action->setShortcut(QKeySequence()); - QString actionString = action->text(); - const int pos = actionString.lastIndexOf(QLatin1Char('\t')); - if (pos > 0) - actionString.remove(pos, actionString.length() - pos); - action->setText(actionString); - } - QAction *actionBefore = 0; - if (actions.count() > 0) - actionBefore = actions[0]; - QAction *clearAction = new QAction(tr("Clear Shortcut"), menu); - menu->insertAction(actionBefore, clearAction); - menu->insertSeparator(actionBefore); - clearAction->setEnabled(!m_keySequence.isEmpty()); - connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearShortcut())); - menu->exec(c->globalPos()); - delete menu; - e->accept(); - return true; - } - - return QWidget::eventFilter(o, e); -} - -void QtKeySequenceEdit::slotClearShortcut() -{ - if (m_keySequence.isEmpty()) - return; - setKeySequence(QKeySequence()); - emit keySequenceChanged(m_keySequence); -} - -void QtKeySequenceEdit::handleKeyEvent(QKeyEvent *e) -{ - int nextKey = e->key(); - if (nextKey == Qt::Key_Control || nextKey == Qt::Key_Shift || - nextKey == Qt::Key_Meta || nextKey == Qt::Key_Alt || - nextKey == Qt::Key_Super_L || nextKey == Qt::Key_AltGr) - return; - - nextKey |= translateModifiers(e->modifiers(), e->text()); - int k0 = m_keySequence[0]; - int k1 = m_keySequence[1]; - int k2 = m_keySequence[2]; - int k3 = m_keySequence[3]; - switch (m_num) { - case 0: k0 = nextKey; k1 = 0; k2 = 0; k3 = 0; break; - case 1: k1 = nextKey; k2 = 0; k3 = 0; break; - case 2: k2 = nextKey; k3 = 0; break; - case 3: k3 = nextKey; break; - default: break; - } - ++m_num; - if (m_num > 3) - m_num = 0; - m_keySequence = QKeySequence(k0, k1, k2, k3); - m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText)); - e->accept(); - emit keySequenceChanged(m_keySequence); -} - -void QtKeySequenceEdit::setKeySequence(const QKeySequence &sequence) -{ - if (sequence == m_keySequence) - return; - m_num = 0; - m_keySequence = sequence; - m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText)); -} - -QKeySequence QtKeySequenceEdit::keySequence() const -{ - return m_keySequence; -} - -int QtKeySequenceEdit::translateModifiers(Qt::KeyboardModifiers state, const QString &text) const -{ - int result = 0; - if ((state & Qt::ShiftModifier) && (text.size() == 0 || !text.at(0).isPrint() || text.at(0).isLetter() || text.at(0).isSpace())) - result |= Qt::SHIFT; - if (state & Qt::ControlModifier) - result |= Qt::CTRL; - if (state & Qt::MetaModifier) - result |= Qt::META; - if (state & Qt::AltModifier) - result |= Qt::ALT; - return result; -} - -void QtKeySequenceEdit::focusInEvent(QFocusEvent *e) -{ - m_lineEdit->event(e); - m_lineEdit->selectAll(); - QWidget::focusInEvent(e); -} - -void QtKeySequenceEdit::focusOutEvent(QFocusEvent *e) -{ - m_num = 0; - m_lineEdit->event(e); - QWidget::focusOutEvent(e); -} - -void QtKeySequenceEdit::keyPressEvent(QKeyEvent *e) -{ - handleKeyEvent(e); - e->accept(); -} - -void QtKeySequenceEdit::keyReleaseEvent(QKeyEvent *e) -{ - m_lineEdit->event(e); -} - -void QtKeySequenceEdit::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -bool QtKeySequenceEdit::event(QEvent *e) -{ - if (e->type() == QEvent::Shortcut || - e->type() == QEvent::ShortcutOverride || - e->type() == QEvent::KeyRelease) { - e->accept(); - return true; - } - return QWidget::event(e); -} - - - - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowserutils_p.h b/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowserutils_p.h deleted file mode 100644 index 5a826d2b..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertybrowserutils_p.h +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of Qt Designer. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QTPROPERTYBROWSERUTILS_H -#define QTPROPERTYBROWSERUTILS_H - -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QMouseEvent; -class QCheckBox; -class QLineEdit; - -class QtCursorDatabase -{ -public: - QtCursorDatabase(); - void clear(); - - QStringList cursorShapeNames() const; - QMap cursorShapeIcons() const; - QString cursorToShapeName(const QCursor &cursor) const; - QIcon cursorToShapeIcon(const QCursor &cursor) const; - int cursorToValue(const QCursor &cursor) const; -#ifndef QT_NO_CURSOR - QCursor valueToCursor(int value) const; -#endif -private: - void appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon); - QStringList m_cursorNames; - QMap m_cursorIcons; - QMap m_valueToCursorShape; - QMap m_cursorShapeToValue; -}; - -class QtPropertyBrowserUtils -{ -public: - static QPixmap brushValuePixmap(const QBrush &b); - static QIcon brushValueIcon(const QBrush &b); - static QString colorValueText(const QColor &c); - static QPixmap fontValuePixmap(const QFont &f); - static QIcon fontValueIcon(const QFont &f); - static QString fontValueText(const QFont &f); -}; - -class QtBoolEdit : public QWidget { - Q_OBJECT -public: - QtBoolEdit(QWidget *parent = 0); - - bool textVisible() const { return m_textVisible; } - void setTextVisible(bool textVisible); - - Qt::CheckState checkState() const; - void setCheckState(Qt::CheckState state); - - bool isChecked() const; - void setChecked(bool c); - - bool blockCheckBoxSignals(bool block); - -Q_SIGNALS: - void toggled(bool); - -protected: - void mousePressEvent(QMouseEvent * event); - void paintEvent(QPaintEvent *); - -private: - QCheckBox *m_checkBox; - bool m_textVisible; -}; - -class QtKeySequenceEdit : public QWidget -{ - Q_OBJECT -public: - QtKeySequenceEdit(QWidget *parent = 0); - - QKeySequence keySequence() const; - bool eventFilter(QObject *o, QEvent *e); -public Q_SLOTS: - void setKeySequence(const QKeySequence &sequence); -Q_SIGNALS: - void keySequenceChanged(const QKeySequence &sequence); -protected: - void focusInEvent(QFocusEvent *e); - void focusOutEvent(QFocusEvent *e); - void keyPressEvent(QKeyEvent *e); - void keyReleaseEvent(QKeyEvent *e); - void paintEvent(QPaintEvent *); - bool event(QEvent *e); -private slots: - void slotClearShortcut(); -private: - void handleKeyEvent(QKeyEvent *e); - int translateModifiers(Qt::KeyboardModifiers state, const QString &text) const; - - int m_num; - QKeySequence m_keySequence; - QLineEdit *m_lineEdit; -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertymanager.cpp b/src/qt-solutions/qtpropertybrowser/src/qtpropertymanager.cpp deleted file mode 100644 index a3bc78c4..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertymanager.cpp +++ /dev/null @@ -1,6648 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtpropertymanager.h" -#include "qtpropertybrowserutils_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -template -static void setSimpleMinimumData(PrivateData *data, const Value &minVal) -{ - data->minVal = minVal; - if (data->maxVal < data->minVal) - data->maxVal = data->minVal; - - if (data->val < data->minVal) - data->val = data->minVal; -} - -template -static void setSimpleMaximumData(PrivateData *data, const Value &maxVal) -{ - data->maxVal = maxVal; - if (data->minVal > data->maxVal) - data->minVal = data->maxVal; - - if (data->val > data->maxVal) - data->val = data->maxVal; -} - -template -static void setSizeMinimumData(PrivateData *data, const Value &newMinVal) -{ - data->minVal = newMinVal; - if (data->maxVal.width() < data->minVal.width()) - data->maxVal.setWidth(data->minVal.width()); - if (data->maxVal.height() < data->minVal.height()) - data->maxVal.setHeight(data->minVal.height()); - - if (data->val.width() < data->minVal.width()) - data->val.setWidth(data->minVal.width()); - if (data->val.height() < data->minVal.height()) - data->val.setHeight(data->minVal.height()); -} - -template -static void setSizeMaximumData(PrivateData *data, const Value &newMaxVal) -{ - data->maxVal = newMaxVal; - if (data->minVal.width() > data->maxVal.width()) - data->minVal.setWidth(data->maxVal.width()); - if (data->minVal.height() > data->maxVal.height()) - data->minVal.setHeight(data->maxVal.height()); - - if (data->val.width() > data->maxVal.width()) - data->val.setWidth(data->maxVal.width()); - if (data->val.height() > data->maxVal.height()) - data->val.setHeight(data->maxVal.height()); -} - -template -static SizeValue qBoundSize(const SizeValue &minVal, const SizeValue &val, const SizeValue &maxVal) -{ - SizeValue croppedVal = val; - if (minVal.width() > val.width()) - croppedVal.setWidth(minVal.width()); - else if (maxVal.width() < val.width()) - croppedVal.setWidth(maxVal.width()); - - if (minVal.height() > val.height()) - croppedVal.setHeight(minVal.height()); - else if (maxVal.height() < val.height()) - croppedVal.setHeight(maxVal.height()); - - return croppedVal; -} - -// Match the exact signature of qBound for VS 6. -QSize qBound(QSize minVal, QSize val, QSize maxVal) -{ - return qBoundSize(minVal, val, maxVal); -} - -QSizeF qBound(QSizeF minVal, QSizeF val, QSizeF maxVal) -{ - return qBoundSize(minVal, val, maxVal); -} - -namespace { - -namespace { -template -void orderBorders(Value &minVal, Value &maxVal) -{ - if (minVal > maxVal) - qSwap(minVal, maxVal); -} - -template -static void orderSizeBorders(Value &minVal, Value &maxVal) -{ - Value fromSize = minVal; - Value toSize = maxVal; - if (fromSize.width() > toSize.width()) { - fromSize.setWidth(maxVal.width()); - toSize.setWidth(minVal.width()); - } - if (fromSize.height() > toSize.height()) { - fromSize.setHeight(maxVal.height()); - toSize.setHeight(minVal.height()); - } - minVal = fromSize; - maxVal = toSize; -} - -void orderBorders(QSize &minVal, QSize &maxVal) -{ - orderSizeBorders(minVal, maxVal); -} - -void orderBorders(QSizeF &minVal, QSizeF &maxVal) -{ - orderSizeBorders(minVal, maxVal); -} - -} -} -//////// - -template -static Value getData(const QMap &propertyMap, - Value PrivateData::*data, - const QtProperty *property, const Value &defaultValue = Value()) -{ - typedef QMap PropertyToData; - typedef typename PropertyToData::const_iterator PropertyToDataConstIterator; - const PropertyToDataConstIterator it = propertyMap.constFind(property); - if (it == propertyMap.constEnd()) - return defaultValue; - return it.value().*data; -} - -template -static Value getValue(const QMap &propertyMap, - const QtProperty *property, const Value &defaultValue = Value()) -{ - return getData(propertyMap, &PrivateData::val, property, defaultValue); -} - -template -static Value getMinimum(const QMap &propertyMap, - const QtProperty *property, const Value &defaultValue = Value()) -{ - return getData(propertyMap, &PrivateData::minVal, property, defaultValue); -} - -template -static Value getMaximum(const QMap &propertyMap, - const QtProperty *property, const Value &defaultValue = Value()) -{ - return getData(propertyMap, &PrivateData::maxVal, property, defaultValue); -} - -template -static void setSimpleValue(QMap &propertyMap, - PropertyManager *manager, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - QtProperty *property, const Value &val) -{ - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = propertyMap.find(property); - if (it == propertyMap.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, val); -} - -template -static void setValueInRange(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - QtProperty *property, const Value &val, - void (PropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, ValueChangeParameter)) -{ - typedef typename PropertyManagerPrivate::Data PrivateData; - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = managerPrivate->m_values.find(property); - if (it == managerPrivate->m_values.end()) - return; - - PrivateData &data = it.value(); - - if (data.val == val) - return; - - const Value oldVal = data.val; - - data.val = qBound(data.minVal, val, data.maxVal); - - if (data.val == oldVal) - return; - - if (setSubPropertyValue) - (managerPrivate->*setSubPropertyValue)(property, data.val); - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, data.val); -} - -template -static void setBorderValues(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, const Value &minVal, const Value &maxVal, - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter)) -{ - typedef typename PropertyManagerPrivate::Data PrivateData; - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = managerPrivate->m_values.find(property); - if (it == managerPrivate->m_values.end()) - return; - - Value fromVal = minVal; - Value toVal = maxVal; - orderBorders(fromVal, toVal); - - PrivateData &data = it.value(); - - if (data.minVal == fromVal && data.maxVal == toVal) - return; - - const Value oldVal = data.val; - - data.setMinimumValue(fromVal); - data.setMaximumValue(toVal); - - emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal); - - if (setSubPropertyRange) - (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val); - - if (data.val == oldVal) - return; - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, data.val); -} - -template -static void setBorderValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, - Value (PrivateData::*getRangeVal)() const, - void (PrivateData::*setRangeVal)(ValueChangeParameter), const Value &borderVal, - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter)) -{ - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = managerPrivate->m_values.find(property); - if (it == managerPrivate->m_values.end()) - return; - - PrivateData &data = it.value(); - - if ((data.*getRangeVal)() == borderVal) - return; - - const Value oldVal = data.val; - - (data.*setRangeVal)(borderVal); - - emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal); - - if (setSubPropertyRange) - (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val); - - if (data.val == oldVal) - return; - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, data.val); -} - -template -static void setMinimumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, const Value &minVal) -{ - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0; - setBorderValue(manager, managerPrivate, - propertyChangedSignal, valueChangedSignal, rangeChangedSignal, - property, &PropertyManagerPrivate::Data::minimumValue, &PropertyManagerPrivate::Data::setMinimumValue, minVal, setSubPropertyRange); -} - -template -static void setMaximumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, const Value &maxVal) -{ - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0; - setBorderValue(manager, managerPrivate, - propertyChangedSignal, valueChangedSignal, rangeChangedSignal, - property, &PropertyManagerPrivate::Data::maximumValue, &PropertyManagerPrivate::Data::setMaximumValue, maxVal, setSubPropertyRange); -} - -class QtMetaEnumWrapper : public QObject -{ - Q_OBJECT - Q_PROPERTY(QSizePolicy::Policy policy READ policy) -public: - QSizePolicy::Policy policy() const { return QSizePolicy::Ignored; } -private: - QtMetaEnumWrapper(QObject *parent) : QObject(parent) {} -}; - -class QtMetaEnumProvider -{ -public: - QtMetaEnumProvider(); - - QStringList policyEnumNames() const { return m_policyEnumNames; } - QStringList languageEnumNames() const { return m_languageEnumNames; } - QStringList countryEnumNames(QLocale::Language language) const { return m_countryEnumNames.value(language); } - - QSizePolicy::Policy indexToSizePolicy(int index) const; - int sizePolicyToIndex(QSizePolicy::Policy policy) const; - - void indexToLocale(int languageIndex, int countryIndex, QLocale::Language *language, QLocale::Country *country) const; - void localeToIndex(QLocale::Language language, QLocale::Country country, int *languageIndex, int *countryIndex) const; - -private: - void initLocale(); - - QStringList m_policyEnumNames; - QStringList m_languageEnumNames; - QMap m_countryEnumNames; - QMap m_indexToLanguage; - QMap m_languageToIndex; - QMap > m_indexToCountry; - QMap > m_countryToIndex; - QMetaEnum m_policyEnum; -}; - -#if QT_VERSION < 0x040300 - -static QList countriesForLanguage(QLocale::Language language) -{ - QList countries; - QLocale::Country country = QLocale::AnyCountry; - while (country <= QLocale::LastCountry) { - QLocale locale(language, country); - if (locale.language() == language && !countries.contains(locale.country())) - countries << locale.country(); - country = (QLocale::Country)((uint)country + 1); // ++country - } - return countries; -} - -#endif - -static QList sortCountries(const QList &countries) -{ - QMultiMap nameToCountry; - QListIterator itCountry(countries); - while (itCountry.hasNext()) { - QLocale::Country country = itCountry.next(); - nameToCountry.insert(QLocale::countryToString(country), country); - } - return nameToCountry.values(); -} - -void QtMetaEnumProvider::initLocale() -{ - QMultiMap nameToLanguage; - QLocale::Language language = QLocale::C; - while (language <= QLocale::LastLanguage) { - QLocale locale(language); - if (locale.language() == language) - nameToLanguage.insert(QLocale::languageToString(language), language); - language = (QLocale::Language)((uint)language + 1); // ++language - } - - const QLocale system = QLocale::system(); - if (!nameToLanguage.contains(QLocale::languageToString(system.language()))) - nameToLanguage.insert(QLocale::languageToString(system.language()), system.language()); - - QList languages = nameToLanguage.values(); - QListIterator itLang(languages); - while (itLang.hasNext()) { - QLocale::Language language = itLang.next(); - QList countries; -#if QT_VERSION < 0x040300 - countries = countriesForLanguage(language); -#else - countries = QLocale::countriesForLanguage(language); -#endif - if (countries.isEmpty() && language == system.language()) - countries << system.country(); - - if (!countries.isEmpty() && !m_languageToIndex.contains(language)) { - countries = sortCountries(countries); - int langIdx = m_languageEnumNames.count(); - m_indexToLanguage[langIdx] = language; - m_languageToIndex[language] = langIdx; - QStringList countryNames; - QListIterator it(countries); - int countryIdx = 0; - while (it.hasNext()) { - QLocale::Country country = it.next(); - countryNames << QLocale::countryToString(country); - m_indexToCountry[langIdx][countryIdx] = country; - m_countryToIndex[language][country] = countryIdx; - ++countryIdx; - } - m_languageEnumNames << QLocale::languageToString(language); - m_countryEnumNames[language] = countryNames; - } - } -} - -QtMetaEnumProvider::QtMetaEnumProvider() -{ - QMetaProperty p; - - p = QtMetaEnumWrapper::staticMetaObject.property( - QtMetaEnumWrapper::staticMetaObject.propertyOffset() + 0); - m_policyEnum = p.enumerator(); - const int keyCount = m_policyEnum.keyCount(); - for (int i = 0; i < keyCount; i++) - m_policyEnumNames << QLatin1String(m_policyEnum.key(i)); - - initLocale(); -} - -QSizePolicy::Policy QtMetaEnumProvider::indexToSizePolicy(int index) const -{ - return static_cast(m_policyEnum.value(index)); -} - -int QtMetaEnumProvider::sizePolicyToIndex(QSizePolicy::Policy policy) const -{ - const int keyCount = m_policyEnum.keyCount(); - for (int i = 0; i < keyCount; i++) - if (indexToSizePolicy(i) == policy) - return i; - return -1; -} - -void QtMetaEnumProvider::indexToLocale(int languageIndex, int countryIndex, QLocale::Language *language, QLocale::Country *country) const -{ - QLocale::Language l = QLocale::C; - QLocale::Country c = QLocale::AnyCountry; - if (m_indexToLanguage.contains(languageIndex)) { - l = m_indexToLanguage[languageIndex]; - if (m_indexToCountry.contains(languageIndex) && m_indexToCountry[languageIndex].contains(countryIndex)) - c = m_indexToCountry[languageIndex][countryIndex]; - } - if (language) - *language = l; - if (country) - *country = c; -} - -void QtMetaEnumProvider::localeToIndex(QLocale::Language language, QLocale::Country country, int *languageIndex, int *countryIndex) const -{ - int l = -1; - int c = -1; - if (m_languageToIndex.contains(language)) { - l = m_languageToIndex[language]; - if (m_countryToIndex.contains(language) && m_countryToIndex[language].contains(country)) - c = m_countryToIndex[language][country]; - } - - if (languageIndex) - *languageIndex = l; - if (countryIndex) - *countryIndex = c; -} - -Q_GLOBAL_STATIC(QtMetaEnumProvider, metaEnumProvider) - -// QtGroupPropertyManager - -/*! - \class QtGroupPropertyManager - - \brief The QtGroupPropertyManager provides and manages group properties. - - This class is intended to provide a grouping element without any value. - - \sa QtAbstractPropertyManager -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtGroupPropertyManager::QtGroupPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtGroupPropertyManager::~QtGroupPropertyManager() -{ - -} - -/*! - \reimp -*/ -bool QtGroupPropertyManager::hasValue(const QtProperty *property) const -{ - Q_UNUSED(property) - return false; -} - -/*! - \reimp -*/ -void QtGroupPropertyManager::initializeProperty(QtProperty *property) -{ - Q_UNUSED(property) -} - -/*! - \reimp -*/ -void QtGroupPropertyManager::uninitializeProperty(QtProperty *property) -{ - Q_UNUSED(property) -} - -// QtIntPropertyManager - -class QtIntPropertyManagerPrivate -{ - QtIntPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtIntPropertyManager) -public: - - struct Data - { - Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), readOnly(false) {} - int val; - int minVal; - int maxVal; - int singleStep; - bool readOnly; - int minimumValue() const { return minVal; } - int maximumValue() const { return maxVal; } - void setMinimumValue(int newMinVal) { setSimpleMinimumData(this, newMinVal); } - void setMaximumValue(int newMaxVal) { setSimpleMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtIntPropertyManager - - \brief The QtIntPropertyManager provides and manages int properties. - - An int property has a current value, and a range specifying the - valid values. The range is defined by a minimum and a maximum - value. - - The property's value and range can be retrieved using the value(), - minimum() and maximum() functions, and can be set using the - setValue(), setMinimum() and setMaximum() slots. Alternatively, - the range can be defined in one go using the setRange() slot. - - In addition, QtIntPropertyManager provides the valueChanged() signal which - is emitted whenever a property created by this manager changes, - and the rangeChanged() signal which is emitted whenever such a - property changes its range of valid values. - - \sa QtAbstractPropertyManager, QtSpinBoxFactory, QtSliderFactory, QtScrollBarFactory -*/ - -/*! - \fn void QtIntPropertyManager::valueChanged(QtProperty *property, int value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtIntPropertyManager::rangeChanged(QtProperty *property, int minimum, int maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid values, passing a pointer to the - \a property and the new \a minimum and \a maximum values. - - \sa setRange() -*/ - -/*! - \fn void QtIntPropertyManager::singleStepChanged(QtProperty *property, int step) - - This signal is emitted whenever a property created by this manager - changes its single step property, passing a pointer to the - \a property and the new \a step value - - \sa setSingleStep() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtIntPropertyManager::QtIntPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtIntPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtIntPropertyManager::~QtIntPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns 0. - - \sa setValue() -*/ -int QtIntPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's minimum value. - - \sa setMinimum(), maximum(), setRange() -*/ -int QtIntPropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's maximum value. - - \sa setMaximum(), minimum(), setRange() -*/ -int QtIntPropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's step value. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa setSingleStep() -*/ -int QtIntPropertyManager::singleStep(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::singleStep, property, 0); -} - -/*! - Returns read-only status of the property. - - When property is read-only it's value can be selected and copied from editor but not modified. - - \sa QtIntPropertyManager::setReadOnly -*/ -bool QtIntPropertyManager::isReadOnly(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::readOnly, property, false); -} - -/*! - \reimp -*/ -QString QtIntPropertyManager::valueText(const QtProperty *property) const -{ - const QtIntPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return QString::number(it.value().val); -} - -/*! - \fn void QtIntPropertyManager::setValue(QtProperty *property, int value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given \a - property's range, the \a value is adjusted to the nearest valid - value within the range. - - \sa value(), setRange(), valueChanged() -*/ -void QtIntPropertyManager::setValue(QtProperty *property, int val) -{ - void (QtIntPropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, int) = 0; - setValueInRange(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - property, val, setSubPropertyValue); -} - -/*! - Sets the minimum value for the given \a property to \a minVal. - - When setting the minimum value, the maximum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtIntPropertyManager::setMinimum(QtProperty *property, int minVal) -{ - setMinimumValue(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - &QtIntPropertyManager::rangeChanged, - property, minVal); -} - -/*! - Sets the maximum value for the given \a property to \a maxVal. - - When setting maximum value, the minimum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtIntPropertyManager::setMaximum(QtProperty *property, int maxVal) -{ - setMaximumValue(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - &QtIntPropertyManager::rangeChanged, - property, maxVal); -} - -/*! - \fn void QtIntPropertyManager::setRange(QtProperty *property, int minimum, int maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtIntPropertyManager::setRange(QtProperty *property, int minVal, int maxVal) -{ - void (QtIntPropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, int, int, int) = 0; - setBorderValues(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - &QtIntPropertyManager::rangeChanged, - property, minVal, maxVal, setSubPropertyRange); -} - -/*! - Sets the step value for the given \a property to \a step. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa singleStep() -*/ -void QtIntPropertyManager::setSingleStep(QtProperty *property, int step) -{ - const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtIntPropertyManagerPrivate::Data data = it.value(); - - if (step < 0) - step = 0; - - if (data.singleStep == step) - return; - - data.singleStep = step; - - it.value() = data; - - emit singleStepChanged(property, data.singleStep); -} - -/*! - Sets read-only status of the property. - - \sa QtIntPropertyManager::setReadOnly -*/ -void QtIntPropertyManager::setReadOnly(QtProperty *property, bool readOnly) -{ - const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtIntPropertyManagerPrivate::Data data = it.value(); - - if (data.readOnly == readOnly) - return; - - data.readOnly = readOnly; - it.value() = data; - - emit propertyChanged(property); - emit readOnlyChanged(property, data.readOnly); -} - -/*! - \reimp -*/ -void QtIntPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtIntPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtIntPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtDoublePropertyManager - -class QtDoublePropertyManagerPrivate -{ - QtDoublePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtDoublePropertyManager) -public: - - struct Data - { - Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), decimals(2), readOnly(false) {} - double val; - double minVal; - double maxVal; - double singleStep; - int decimals; - bool readOnly; - double minimumValue() const { return minVal; } - double maximumValue() const { return maxVal; } - void setMinimumValue(double newMinVal) { setSimpleMinimumData(this, newMinVal); } - void setMaximumValue(double newMaxVal) { setSimpleMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtDoublePropertyManager - - \brief The QtDoublePropertyManager provides and manages double properties. - - A double property has a current value, and a range specifying the - valid values. The range is defined by a minimum and a maximum - value. - - The property's value and range can be retrieved using the value(), - minimum() and maximum() functions, and can be set using the - setValue(), setMinimum() and setMaximum() slots. - Alternatively, the range can be defined in one go using the - setRange() slot. - - In addition, QtDoublePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid values. - - \sa QtAbstractPropertyManager, QtDoubleSpinBoxFactory -*/ - -/*! - \fn void QtDoublePropertyManager::valueChanged(QtProperty *property, double value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtDoublePropertyManager::rangeChanged(QtProperty *property, double minimum, double maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid values, passing a pointer to the - \a property and the new \a minimum and \a maximum values - - \sa setRange() -*/ - -/*! - \fn void QtDoublePropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - \fn void QtDoublePropertyManager::singleStepChanged(QtProperty *property, double step) - - This signal is emitted whenever a property created by this manager - changes its single step property, passing a pointer to the - \a property and the new \a step value - - \sa setSingleStep() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtDoublePropertyManager::QtDoublePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtDoublePropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtDoublePropertyManager::~QtDoublePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns 0. - - \sa setValue() -*/ -double QtDoublePropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, 0.0); -} - -/*! - Returns the given \a property's minimum value. - - \sa maximum(), setRange() -*/ -double QtDoublePropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property, 0.0); -} - -/*! - Returns the given \a property's maximum value. - - \sa minimum(), setRange() -*/ -double QtDoublePropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property, 0.0); -} - -/*! - Returns the given \a property's step value. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa setSingleStep() -*/ -double QtDoublePropertyManager::singleStep(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::singleStep, property, 0); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtDoublePropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - Returns read-only status of the property. - - When property is read-only it's value can be selected and copied from editor but not modified. - - \sa QtDoublePropertyManager::setReadOnly -*/ -bool QtDoublePropertyManager::isReadOnly(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::readOnly, property, false); -} - -/*! - \reimp -*/ -QString QtDoublePropertyManager::valueText(const QtProperty *property) const -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return QLocale::system().toString(it.value().val, 'f', it.value().decimals); -} - -/*! - \fn void QtDoublePropertyManager::setValue(QtProperty *property, double value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given - \a property's range, the \a value is adjusted to the nearest valid value - within the range. - - \sa value(), setRange(), valueChanged() -*/ -void QtDoublePropertyManager::setValue(QtProperty *property, double val) -{ - void (QtDoublePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, double) = 0; - setValueInRange(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - property, val, setSubPropertyValue); -} - -/*! - Sets the step value for the given \a property to \a step. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa singleStep() -*/ -void QtDoublePropertyManager::setSingleStep(QtProperty *property, double step) -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtDoublePropertyManagerPrivate::Data data = it.value(); - - if (step < 0) - step = 0; - - if (data.singleStep == step) - return; - - data.singleStep = step; - - it.value() = data; - - emit singleStepChanged(property, data.singleStep); -} - -/*! - Sets read-only status of the property. - - \sa QtDoublePropertyManager::setReadOnly -*/ -void QtDoublePropertyManager::setReadOnly(QtProperty *property, bool readOnly) -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtDoublePropertyManagerPrivate::Data data = it.value(); - - if (data.readOnly == readOnly) - return; - - data.readOnly = readOnly; - it.value() = data; - - emit propertyChanged(property); - emit readOnlyChanged(property, data.readOnly); -} - -/*! - \fn void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtDoublePropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - Sets the minimum value for the given \a property to \a minVal. - - When setting the minimum value, the maximum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within in the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtDoublePropertyManager::setMinimum(QtProperty *property, double minVal) -{ - setMinimumValue(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - &QtDoublePropertyManager::rangeChanged, - property, minVal); -} - -/*! - Sets the maximum value for the given \a property to \a maxVal. - - When setting the maximum value, the minimum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within in the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtDoublePropertyManager::setMaximum(QtProperty *property, double maxVal) -{ - setMaximumValue(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - &QtDoublePropertyManager::rangeChanged, - property, maxVal); -} - -/*! - \fn void QtDoublePropertyManager::setRange(QtProperty *property, double minimum, double maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtDoublePropertyManager::setRange(QtProperty *property, double minVal, double maxVal) -{ - void (QtDoublePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, double, double, double) = 0; - setBorderValues(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - &QtDoublePropertyManager::rangeChanged, - property, minVal, maxVal, setSubPropertyRange); -} - -/*! - \reimp -*/ -void QtDoublePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtDoublePropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtDoublePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtStringPropertyManager - -class QtStringPropertyManagerPrivate -{ - QtStringPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtStringPropertyManager) -public: - - struct Data - { - Data() : regExp(QString(QLatin1Char('*')), Qt::CaseSensitive, QRegExp::Wildcard), - echoMode(QLineEdit::Normal), readOnly(false) - { - } - QString val; - QRegExp regExp; - int echoMode; - bool readOnly; - }; - - typedef QMap PropertyValueMap; - QMap m_values; -}; - -/*! - \class QtStringPropertyManager - - \brief The QtStringPropertyManager provides and manages QString properties. - - A string property's value can be retrieved using the value() - function, and set using the setValue() slot. - - The current value can be checked against a regular expression. To - set the regular expression use the setRegExp() slot, use the - regExp() function to retrieve the currently set expression. - - In addition, QtStringPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the regExpChanged() signal which is emitted whenever - such a property changes its currently set regular expression. - - \sa QtAbstractPropertyManager, QtLineEditFactory -*/ - -/*! - \fn void QtStringPropertyManager::valueChanged(QtProperty *property, const QString &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtStringPropertyManager::regExpChanged(QtProperty *property, const QRegExp ®Exp) - - This signal is emitted whenever a property created by this manager - changes its currenlty set regular expression, passing a pointer to - the \a property and the new \a regExp as parameters. - - \sa setRegExp() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtStringPropertyManager::QtStringPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtStringPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtStringPropertyManager::~QtStringPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns an empty string. - - \sa setValue() -*/ -QString QtStringPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's currently set regular expression. - - If the given \a property is not managed by this manager, this - function returns an empty expression. - - \sa setRegExp() -*/ -QRegExp QtStringPropertyManager::regExp(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::regExp, property, QRegExp()); -} - -/*! - \reimp -*/ -EchoMode QtStringPropertyManager::echoMode(const QtProperty *property) const -{ - return (EchoMode)getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::echoMode, property, 0); -} - -/*! - Returns read-only status of the property. - - When property is read-only it's value can be selected and copied from editor but not modified. - - \sa QtStringPropertyManager::setReadOnly -*/ -bool QtStringPropertyManager::isReadOnly(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::readOnly, property, false); -} - -/*! - \reimp -*/ -QString QtStringPropertyManager::valueText(const QtProperty *property) const -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return it.value().val; -} - -/*! - \reimp -*/ -QString QtStringPropertyManager::displayText(const QtProperty *property) const -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - QLineEdit edit; - edit.setEchoMode((EchoMode)it.value().echoMode); - edit.setText(it.value().val); - return edit.displayText(); -} - -/*! - \fn void QtStringPropertyManager::setValue(QtProperty *property, const QString &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value doesn't match the given \a property's - regular expression, this function does nothing. - - \sa value(), setRegExp(), valueChanged() -*/ -void QtStringPropertyManager::setValue(QtProperty *property, const QString &val) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value(); - - if (data.val == val) - return; - - if (data.regExp.isValid() && !data.regExp.exactMatch(val)) - return; - - data.val = val; - - it.value() = data; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the regular expression of the given \a property to \a regExp. - - \sa regExp(), setValue(), regExpChanged() -*/ -void QtStringPropertyManager::setRegExp(QtProperty *property, const QRegExp ®Exp) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value() ; - - if (data.regExp == regExp) - return; - - data.regExp = regExp; - - it.value() = data; - - emit regExpChanged(property, data.regExp); -} - - -void QtStringPropertyManager::setEchoMode(QtProperty *property, EchoMode echoMode) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value(); - - if (data.echoMode == echoMode) - return; - - data.echoMode = echoMode; - it.value() = data; - - emit propertyChanged(property); - emit echoModeChanged(property, data.echoMode); -} - -/*! - Sets read-only status of the property. - - \sa QtStringPropertyManager::setReadOnly -*/ -void QtStringPropertyManager::setReadOnly(QtProperty *property, bool readOnly) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value(); - - if (data.readOnly == readOnly) - return; - - data.readOnly = readOnly; - it.value() = data; - - emit propertyChanged(property); - emit readOnlyChanged(property, data.readOnly); -} - -/*! - \reimp -*/ -void QtStringPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtStringPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtStringPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtBoolPropertyManager -// Return an icon containing a check box indicator -static QIcon drawCheckBox(bool value) -{ - QStyleOptionButton opt; - opt.state |= value ? QStyle::State_On : QStyle::State_Off; - opt.state |= QStyle::State_Enabled; - const QStyle *style = QApplication::style(); - // Figure out size of an indicator and make sure it is not scaled down in a list view item - // by making the pixmap as big as a list view icon and centering the indicator in it. - // (if it is smaller, it can't be helped) - const int indicatorWidth = style->pixelMetric(QStyle::PM_IndicatorWidth, &opt); - const int indicatorHeight = style->pixelMetric(QStyle::PM_IndicatorHeight, &opt); - const int listViewIconSize = indicatorWidth; - const int pixmapWidth = indicatorWidth; - const int pixmapHeight = qMax(indicatorHeight, listViewIconSize); - - opt.rect = QRect(0, 0, indicatorWidth, indicatorHeight); - QPixmap pixmap = QPixmap(pixmapWidth, pixmapHeight); - pixmap.fill(Qt::transparent); - { - // Center? - const int xoff = (pixmapWidth > indicatorWidth) ? (pixmapWidth - indicatorWidth) / 2 : 0; - const int yoff = (pixmapHeight > indicatorHeight) ? (pixmapHeight - indicatorHeight) / 2 : 0; - QPainter painter(&pixmap); - painter.translate(xoff, yoff); - style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, &painter); - } - return QIcon(pixmap); -} - -class QtBoolPropertyManagerPrivate -{ - QtBoolPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtBoolPropertyManager) -public: - QtBoolPropertyManagerPrivate(); - - struct Data - { - Data() : val(false), textVisible(true) {} - bool val; - bool textVisible; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - const QIcon m_checkedIcon; - const QIcon m_uncheckedIcon; -}; - -QtBoolPropertyManagerPrivate::QtBoolPropertyManagerPrivate() : - m_checkedIcon(drawCheckBox(true)), - m_uncheckedIcon(drawCheckBox(false)) -{ -} - -/*! - \class QtBoolPropertyManager - - \brief The QtBoolPropertyManager class provides and manages boolean properties. - - The property's value can be retrieved using the value() function, - and set using the setValue() slot. - - In addition, QtBoolPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtCheckBoxFactory -*/ - -/*! - \fn void QtBoolPropertyManager::valueChanged(QtProperty *property, bool value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtBoolPropertyManager::QtBoolPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtBoolPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtBoolPropertyManager::~QtBoolPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by \e this manager, this - function returns false. - - \sa setValue() -*/ -bool QtBoolPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, false); -} - -bool QtBoolPropertyManager::textVisible(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtBoolPropertyManagerPrivate::Data::textVisible, property, false); -} - -/*! - \reimp -*/ -QString QtBoolPropertyManager::valueText(const QtProperty *property) const -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QtBoolPropertyManagerPrivate::Data &data = it.value(); - if (!data.textVisible) - return QString(); - - static const QString trueText = tr("True"); - static const QString falseText = tr("False"); - return data.val ? trueText : falseText; -} - -/*! - \reimp -*/ -QIcon QtBoolPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - return it.value().val ? d_ptr->m_checkedIcon : d_ptr->m_uncheckedIcon; -} - -/*! - \fn void QtBoolPropertyManager::setValue(QtProperty *property, bool value) - - Sets the value of the given \a property to \a value. - - \sa value() -*/ -void QtBoolPropertyManager::setValue(QtProperty *property, bool val) -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtBoolPropertyManagerPrivate::Data data = it.value(); - - if (data.val == val) - return; - - data.val = val; - it.value() = data; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -void QtBoolPropertyManager::setTextVisible(QtProperty *property, bool textVisible) -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtBoolPropertyManagerPrivate::Data data = it.value(); - - if (data.textVisible == textVisible) - return; - - data.textVisible = textVisible; - it.value() = data; - - emit propertyChanged(property); - emit textVisibleChanged(property, data.textVisible); -} - -/*! - \reimp -*/ -void QtBoolPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtBoolPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtBoolPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtDatePropertyManager - -class QtDatePropertyManagerPrivate -{ - QtDatePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtDatePropertyManager) -public: - - struct Data - { - Data() : val(QDate::currentDate()), minVal(QDate(1752, 9, 14)), - maxVal(QDate(7999, 12, 31)) {} - QDate val; - QDate minVal; - QDate maxVal; - QDate minimumValue() const { return minVal; } - QDate maximumValue() const { return maxVal; } - void setMinimumValue(const QDate &newMinVal) { setSimpleMinimumData(this, newMinVal); } - void setMaximumValue(const QDate &newMaxVal) { setSimpleMaximumData(this, newMaxVal); } - }; - - QString m_format; - - typedef QMap PropertyValueMap; - QMap m_values; -}; - -/*! - \class QtDatePropertyManager - - \brief The QtDatePropertyManager provides and manages QDate properties. - - A date property has a current value, and a range specifying the - valid dates. The range is defined by a minimum and a maximum - value. - - The property's values can be retrieved using the minimum(), - maximum() and value() functions, and can be set using the - setMinimum(), setMaximum() and setValue() slots. Alternatively, - the range can be defined in one go using the setRange() slot. - - In addition, QtDatePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid dates. - - \sa QtAbstractPropertyManager, QtDateEditFactory, QtDateTimePropertyManager -*/ - -/*! - \fn void QtDatePropertyManager::valueChanged(QtProperty *property, const QDate &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtDatePropertyManager::rangeChanged(QtProperty *property, const QDate &minimum, const QDate &maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid dates, passing a pointer to the \a - property and the new \a minimum and \a maximum dates. - - \sa setRange() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtDatePropertyManager::QtDatePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtDatePropertyManagerPrivate; - d_ptr->q_ptr = this; - - QLocale loc; - d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtDatePropertyManager::~QtDatePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by \e this manager, this - function returns an invalid date. - - \sa setValue() -*/ -QDate QtDatePropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's minimum date. - - \sa maximum(), setRange() -*/ -QDate QtDatePropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's maximum date. - - \sa minimum(), setRange() -*/ -QDate QtDatePropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property); -} - -/*! - \reimp -*/ -QString QtDatePropertyManager::valueText(const QtProperty *property) const -{ - const QtDatePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().val.toString(d_ptr->m_format); -} - -/*! - \fn void QtDatePropertyManager::setValue(QtProperty *property, const QDate &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not a valid date according to the - given \a property's range, the value is adjusted to the nearest - valid value within the range. - - \sa value(), setRange(), valueChanged() -*/ -void QtDatePropertyManager::setValue(QtProperty *property, const QDate &val) -{ - void (QtDatePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, const QDate &) = 0; - setValueInRange(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - property, val, setSubPropertyValue); -} - -/*! - Sets the minimum value for the given \a property to \a minVal. - - When setting the minimum value, the maximum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within in the range). - - \sa minimum(), setRange() -*/ -void QtDatePropertyManager::setMinimum(QtProperty *property, const QDate &minVal) -{ - setMinimumValue(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - &QtDatePropertyManager::rangeChanged, - property, minVal); -} - -/*! - Sets the maximum value for the given \a property to \a maxVal. - - When setting the maximum value, the minimum and current - values are adjusted if necessary (ensuring that the range remains - valid and that the current value is within in the range). - - \sa maximum(), setRange() -*/ -void QtDatePropertyManager::setMaximum(QtProperty *property, const QDate &maxVal) -{ - setMaximumValue(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - &QtDatePropertyManager::rangeChanged, - property, maxVal); -} - -/*! - \fn void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minimum, const QDate &maximum) - - Sets the range of valid dates. - - This is a convenience function defining the range of valid dates - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new date range, the current value is adjusted if - necessary (ensuring that the value remains in date range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal) -{ - void (QtDatePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, const QDate &, - const QDate &, const QDate &) = 0; - setBorderValues(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - &QtDatePropertyManager::rangeChanged, - property, minVal, maxVal, setSubPropertyRange); -} - -/*! - \reimp -*/ -void QtDatePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtDatePropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtDatePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtTimePropertyManager - -class QtTimePropertyManagerPrivate -{ - QtTimePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtTimePropertyManager) -public: - - QString m_format; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtTimePropertyManager - - \brief The QtTimePropertyManager provides and manages QTime properties. - - A time property's value can be retrieved using the value() - function, and set using the setValue() slot. - - In addition, QtTimePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtTimeEditFactory -*/ - -/*! - \fn void QtTimePropertyManager::valueChanged(QtProperty *property, const QTime &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtTimePropertyManager::QtTimePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtTimePropertyManagerPrivate; - d_ptr->q_ptr = this; - - QLocale loc; - d_ptr->m_format = loc.timeFormat(QLocale::ShortFormat); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtTimePropertyManager::~QtTimePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns an invalid time object. - - \sa setValue() -*/ -QTime QtTimePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QTime()); -} - -/*! - \reimp -*/ -QString QtTimePropertyManager::valueText(const QtProperty *property) const -{ - const QtTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().toString(d_ptr->m_format); -} - -/*! - \fn void QtTimePropertyManager::setValue(QtProperty *property, const QTime &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtTimePropertyManager::setValue(QtProperty *property, const QTime &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtTimePropertyManager::propertyChanged, - &QtTimePropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtTimePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QTime::currentTime(); -} - -/*! - \reimp -*/ -void QtTimePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtDateTimePropertyManager - -class QtDateTimePropertyManagerPrivate -{ - QtDateTimePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtDateTimePropertyManager) -public: - - QString m_format; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! \class QtDateTimePropertyManager - - \brief The QtDateTimePropertyManager provides and manages QDateTime properties. - - A date and time property has a current value which can be - retrieved using the value() function, and set using the setValue() - slot. In addition, QtDateTimePropertyManager provides the - valueChanged() signal which is emitted whenever a property created - by this manager changes. - - \sa QtAbstractPropertyManager, QtDateTimeEditFactory, QtDatePropertyManager -*/ - -/*! - \fn void QtDateTimePropertyManager::valueChanged(QtProperty *property, const QDateTime &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtDateTimePropertyManager::QtDateTimePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtDateTimePropertyManagerPrivate; - d_ptr->q_ptr = this; - - QLocale loc; - d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat); - d_ptr->m_format += QLatin1Char(' '); - d_ptr->m_format += loc.timeFormat(QLocale::ShortFormat); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtDateTimePropertyManager::~QtDateTimePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid QDateTime object. - - \sa setValue() -*/ -QDateTime QtDateTimePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QDateTime()); -} - -/*! - \reimp -*/ -QString QtDateTimePropertyManager::valueText(const QtProperty *property) const -{ - const QtDateTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().toString(d_ptr->m_format); -} - -/*! - \fn void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtDateTimePropertyManager::propertyChanged, - &QtDateTimePropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtDateTimePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QDateTime::currentDateTime(); -} - -/*! - \reimp -*/ -void QtDateTimePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtKeySequencePropertyManager - -class QtKeySequencePropertyManagerPrivate -{ - QtKeySequencePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtKeySequencePropertyManager) -public: - - QString m_format; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! \class QtKeySequencePropertyManager - - \brief The QtKeySequencePropertyManager provides and manages QKeySequence properties. - - A key sequence's value can be retrieved using the value() - function, and set using the setValue() slot. - - In addition, QtKeySequencePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager -*/ - -/*! - \fn void QtKeySequencePropertyManager::valueChanged(QtProperty *property, const QKeySequence &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtKeySequencePropertyManager::QtKeySequencePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtKeySequencePropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtKeySequencePropertyManager::~QtKeySequencePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an empty QKeySequence object. - - \sa setValue() -*/ -QKeySequence QtKeySequencePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QKeySequence()); -} - -/*! - \reimp -*/ -QString QtKeySequencePropertyManager::valueText(const QtProperty *property) const -{ - const QtKeySequencePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().toString(QKeySequence::NativeText); -} - -/*! - \fn void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtKeySequencePropertyManager::propertyChanged, - &QtKeySequencePropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtKeySequencePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QKeySequence(); -} - -/*! - \reimp -*/ -void QtKeySequencePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtCharPropertyManager - -class QtCharPropertyManagerPrivate -{ - QtCharPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtCharPropertyManager) -public: - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! \class QtCharPropertyManager - - \brief The QtCharPropertyManager provides and manages QChar properties. - - A char's value can be retrieved using the value() - function, and set using the setValue() slot. - - In addition, QtCharPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager -*/ - -/*! - \fn void QtCharPropertyManager::valueChanged(QtProperty *property, const QChar &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtCharPropertyManager::QtCharPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtCharPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtCharPropertyManager::~QtCharPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an null QChar object. - - \sa setValue() -*/ -QChar QtCharPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QChar()); -} - -/*! - \reimp -*/ -QString QtCharPropertyManager::valueText(const QtProperty *property) const -{ - const QtCharPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QChar c = it.value(); - return c.isNull() ? QString() : QString(c); -} - -/*! - \fn void QtCharPropertyManager::setValue(QtProperty *property, const QChar &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtCharPropertyManager::setValue(QtProperty *property, const QChar &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtCharPropertyManager::propertyChanged, - &QtCharPropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtCharPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QChar(); -} - -/*! - \reimp -*/ -void QtCharPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtLocalePropertyManager - -class QtLocalePropertyManagerPrivate -{ - QtLocalePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtLocalePropertyManager) -public: - - QtLocalePropertyManagerPrivate(); - - void slotEnumChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtEnumPropertyManager *m_enumPropertyManager; - - QMap m_propertyToLanguage; - QMap m_propertyToCountry; - - QMap m_languageToProperty; - QMap m_countryToProperty; -}; - -QtLocalePropertyManagerPrivate::QtLocalePropertyManagerPrivate() -{ -} - -void QtLocalePropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_languageToProperty.value(property, 0)) { - const QLocale loc = m_values[prop]; - QLocale::Language newLanguage = loc.language(); - QLocale::Country newCountry = loc.country(); - metaEnumProvider()->indexToLocale(value, 0, &newLanguage, 0); - QLocale newLoc(newLanguage, newCountry); - q_ptr->setValue(prop, newLoc); - } else if (QtProperty *prop = m_countryToProperty.value(property, 0)) { - const QLocale loc = m_values[prop]; - QLocale::Language newLanguage = loc.language(); - QLocale::Country newCountry = loc.country(); - metaEnumProvider()->indexToLocale(m_enumPropertyManager->value(m_propertyToLanguage.value(prop)), value, &newLanguage, &newCountry); - QLocale newLoc(newLanguage, newCountry); - q_ptr->setValue(prop, newLoc); - } -} - -void QtLocalePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *subProp = m_languageToProperty.value(property, 0)) { - m_propertyToLanguage[subProp] = 0; - m_languageToProperty.remove(property); - } else if (QtProperty *subProp = m_countryToProperty.value(property, 0)) { - m_propertyToCountry[subProp] = 0; - m_countryToProperty.remove(property); - } -} - -/*! - \class QtLocalePropertyManager - - \brief The QtLocalePropertyManager provides and manages QLocale properties. - - A locale property has nested \e language and \e country - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by QtEnumPropertyManager object. - These submanager can be retrieved using the subEnumPropertyManager() - function. In order to provide editing widgets for the subproperties - in a property browser widget, this manager must be associated with editor factory. - - In addition, QtLocalePropertyManager provides the valueChanged() - signal which is emitted whenever a property created by this - manager changes. - - \sa QtAbstractPropertyManager, QtEnumPropertyManager -*/ - -/*! - \fn void QtLocalePropertyManager::valueChanged(QtProperty *property, const QLocale &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtLocalePropertyManager::QtLocalePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtLocalePropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); - connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotEnumChanged(QtProperty *, int))); - - connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtLocalePropertyManager::~QtLocalePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e language - and \e country subproperties. - - In order to provide editing widgets for the mentioned subproperties - in a property browser widget, this manager must be associated with - an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtEnumPropertyManager *QtLocalePropertyManager::subEnumPropertyManager() const -{ - return d_ptr->m_enumPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns the default locale. - - \sa setValue() -*/ -QLocale QtLocalePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QLocale()); -} - -/*! - \reimp -*/ -QString QtLocalePropertyManager::valueText(const QtProperty *property) const -{ - const QtLocalePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - QLocale loc = it.value(); - - int langIdx = 0; - int countryIdx = 0; - metaEnumProvider()->localeToIndex(loc.language(), loc.country(), &langIdx, &countryIdx); - QString str = tr("%1, %2") - .arg(metaEnumProvider()->languageEnumNames().at(langIdx)) - .arg(metaEnumProvider()->countryEnumNames(loc.language()).at(countryIdx)); - return str; -} - -/*! - \fn void QtLocalePropertyManager::setValue(QtProperty *property, const QLocale &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtLocalePropertyManager::setValue(QtProperty *property, const QLocale &val) -{ - const QtLocalePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - const QLocale loc = it.value(); - if (loc == val) - return; - - it.value() = val; - - int langIdx = 0; - int countryIdx = 0; - metaEnumProvider()->localeToIndex(val.language(), val.country(), &langIdx, &countryIdx); - if (loc.language() != val.language()) { - d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToLanguage.value(property), langIdx); - d_ptr->m_enumPropertyManager->setEnumNames(d_ptr->m_propertyToCountry.value(property), - metaEnumProvider()->countryEnumNames(val.language())); - } - d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToCountry.value(property), countryIdx); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtLocalePropertyManager::initializeProperty(QtProperty *property) -{ - QLocale val; - d_ptr->m_values[property] = val; - - int langIdx = 0; - int countryIdx = 0; - metaEnumProvider()->localeToIndex(val.language(), val.country(), &langIdx, &countryIdx); - - QtProperty *languageProp = d_ptr->m_enumPropertyManager->addProperty(); - languageProp->setPropertyName(tr("Language")); - d_ptr->m_enumPropertyManager->setEnumNames(languageProp, metaEnumProvider()->languageEnumNames()); - d_ptr->m_enumPropertyManager->setValue(languageProp, langIdx); - d_ptr->m_propertyToLanguage[property] = languageProp; - d_ptr->m_languageToProperty[languageProp] = property; - property->addSubProperty(languageProp); - - QtProperty *countryProp = d_ptr->m_enumPropertyManager->addProperty(); - countryProp->setPropertyName(tr("Country")); - d_ptr->m_enumPropertyManager->setEnumNames(countryProp, metaEnumProvider()->countryEnumNames(val.language())); - d_ptr->m_enumPropertyManager->setValue(countryProp, countryIdx); - d_ptr->m_propertyToCountry[property] = countryProp; - d_ptr->m_countryToProperty[countryProp] = property; - property->addSubProperty(countryProp); -} - -/*! - \reimp -*/ -void QtLocalePropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *languageProp = d_ptr->m_propertyToLanguage[property]; - if (languageProp) { - d_ptr->m_languageToProperty.remove(languageProp); - delete languageProp; - } - d_ptr->m_propertyToLanguage.remove(property); - - QtProperty *countryProp = d_ptr->m_propertyToCountry[property]; - if (countryProp) { - d_ptr->m_countryToProperty.remove(countryProp); - delete countryProp; - } - d_ptr->m_propertyToCountry.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtPointPropertyManager - -class QtPointPropertyManagerPrivate -{ - QtPointPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtPointPropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - - QMap m_xToProperty; - QMap m_yToProperty; -}; - -void QtPointPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *xprop = m_xToProperty.value(property, 0)) { - QPoint p = m_values[xprop]; - p.setX(value); - q_ptr->setValue(xprop, p); - } else if (QtProperty *yprop = m_yToProperty.value(property, 0)) { - QPoint p = m_values[yprop]; - p.setY(value); - q_ptr->setValue(yprop, p); - } -} - -void QtPointPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } -} - -/*! \class QtPointPropertyManager - - \brief The QtPointPropertyManager provides and manages QPoint properties. - - A point property has nested \e x and \e y subproperties. The - top-level property's value can be retrieved using the value() - function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtPointPropertyManager provides the valueChanged() signal which - is emitted whenever a property created by this manager changes. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtPointFPropertyManager -*/ - -/*! - \fn void QtPointPropertyManager::valueChanged(QtProperty *property, const QPoint &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtPointPropertyManager::QtPointPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtPointPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtPointPropertyManager::~QtPointPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x and \e y - subproperties. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtPointPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns a point with coordinates (0, 0). - - \sa setValue() -*/ -QPoint QtPointPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QPoint()); -} - -/*! - \reimp -*/ -QString QtPointPropertyManager::valueText(const QtProperty *property) const -{ - const QtPointPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QPoint v = it.value(); - return QString(tr("(%1, %2)").arg(QString::number(v.x())) - .arg(QString::number(v.y()))); -} - -/*! - \fn void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &val) -{ - const QtPointPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], val.x()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], val.y()); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtPointPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QPoint(0, 0); - - QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_intPropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_intPropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); -} - -/*! - \reimp -*/ -void QtPointPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtPointFPropertyManager - -class QtPointFPropertyManagerPrivate -{ - QtPointFPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtPointFPropertyManager) -public: - - struct Data - { - Data() : decimals(2) {} - QPointF val; - int decimals; - }; - - void slotDoubleChanged(QtProperty *property, double value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtDoublePropertyManager *m_doublePropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - - QMap m_xToProperty; - QMap m_yToProperty; -}; - -void QtPointFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) -{ - if (QtProperty *prop = m_xToProperty.value(property, 0)) { - QPointF p = m_values[prop].val; - p.setX(value); - q_ptr->setValue(prop, p); - } else if (QtProperty *prop = m_yToProperty.value(property, 0)) { - QPointF p = m_values[prop].val; - p.setY(value); - q_ptr->setValue(prop, p); - } -} - -void QtPointFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } -} - -/*! \class QtPointFPropertyManager - - \brief The QtPointFPropertyManager provides and manages QPointF properties. - - A point property has nested \e x and \e y subproperties. The - top-level property's value can be retrieved using the value() - function, and set using the setValue() slot. - - The subproperties are created by a QtDoublePropertyManager object. This - manager can be retrieved using the subDoublePropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtPointFPropertyManager provides the valueChanged() signal which - is emitted whenever a property created by this manager changes. - - \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtPointPropertyManager -*/ - -/*! - \fn void QtPointFPropertyManager::valueChanged(QtProperty *property, const QPointF &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtPointFPropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtPointFPropertyManager::QtPointFPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtPointFPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); - connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotDoubleChanged(QtProperty *, double))); - connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtPointFPropertyManager::~QtPointFPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x and \e y - subproperties. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtDoublePropertyManager *QtPointFPropertyManager::subDoublePropertyManager() const -{ - return d_ptr->m_doublePropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns a point with coordinates (0, 0). - - \sa setValue() -*/ -QPointF QtPointFPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtPointFPropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtPointFPropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - \reimp -*/ -QString QtPointFPropertyManager::valueText(const QtProperty *property) const -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QPointF v = it.value().val; - const int dec = it.value().decimals; - return QString(tr("(%1, %2)").arg(QString::number(v.x(), 'f', dec)) - .arg(QString::number(v.y(), 'f', dec))); -} - -/*! - \fn void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &val) -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value().val == val) - return; - - it.value().val = val; - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], val.x()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], val.y()); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \fn void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtPointFPropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec); - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - \reimp -*/ -void QtPointFPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtPointFPropertyManagerPrivate::Data(); - - QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); -} - -/*! - \reimp -*/ -void QtPointFPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtSizePropertyManager - -class QtSizePropertyManagerPrivate -{ - QtSizePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtSizePropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - void setValue(QtProperty *property, const QSize &val); - void setRange(QtProperty *property, - const QSize &minVal, const QSize &maxVal, const QSize &val); - - struct Data - { - Data() : val(QSize(0, 0)), minVal(QSize(0, 0)), maxVal(QSize(INT_MAX, INT_MAX)) {} - QSize val; - QSize minVal; - QSize maxVal; - QSize minimumValue() const { return minVal; } - QSize maximumValue() const { return maxVal; } - void setMinimumValue(const QSize &newMinVal) { setSizeMinimumData(this, newMinVal); } - void setMaximumValue(const QSize &newMaxVal) { setSizeMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtSizePropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_wToProperty.value(property, 0)) { - QSize s = m_values[prop].val; - s.setWidth(value); - q_ptr->setValue(prop, s); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - QSize s = m_values[prop].val; - s.setHeight(value); - q_ptr->setValue(prop, s); - } -} - -void QtSizePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtSizePropertyManagerPrivate::setValue(QtProperty *property, const QSize &val) -{ - m_intPropertyManager->setValue(m_propertyToW.value(property), val.width()); - m_intPropertyManager->setValue(m_propertyToH.value(property), val.height()); -} - -void QtSizePropertyManagerPrivate::setRange(QtProperty *property, - const QSize &minVal, const QSize &maxVal, const QSize &val) -{ - QtProperty *wProperty = m_propertyToW.value(property); - QtProperty *hProperty = m_propertyToH.value(property); - m_intPropertyManager->setRange(wProperty, minVal.width(), maxVal.width()); - m_intPropertyManager->setValue(wProperty, val.width()); - m_intPropertyManager->setRange(hProperty, minVal.height(), maxVal.height()); - m_intPropertyManager->setValue(hProperty, val.height()); -} - -/*! - \class QtSizePropertyManager - - \brief The QtSizePropertyManager provides and manages QSize properties. - - A size property has nested \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A size property also has a range of valid values defined by a - minimum size and a maximum size. These sizes can be retrieved - using the minimum() and the maximum() functions, and set using the - setMinimum() and setMaximum() slots. Alternatively, the range can - be defined in one go using the setRange() slot. - - In addition, QtSizePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid sizes. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtSizeFPropertyManager -*/ - -/*! - \fn void QtSizePropertyManager::valueChanged(QtProperty *property, const QSize &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtSizePropertyManager::rangeChanged(QtProperty *property, const QSize &minimum, const QSize &maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid sizes, passing a pointer to the \a - property and the new \a minimum and \a maximum sizes. - - \sa setRange() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtSizePropertyManager::QtSizePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtSizePropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtSizePropertyManager::~QtSizePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e width and \e height - subproperties. - - In order to provide editing widgets for the \e width and \e height - properties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtSizePropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid size - - \sa setValue() -*/ -QSize QtSizePropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's minimum size value. - - \sa setMinimum(), maximum(), setRange() -*/ -QSize QtSizePropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's maximum size value. - - \sa setMaximum(), minimum(), setRange() -*/ -QSize QtSizePropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property); -} - -/*! - \reimp -*/ -QString QtSizePropertyManager::valueText(const QtProperty *property) const -{ - const QtSizePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QSize v = it.value().val; - return QString(tr("%1 x %2").arg(QString::number(v.width())) - .arg(QString::number(v.height()))); -} - -/*! - \fn void QtSizePropertyManager::setValue(QtProperty *property, const QSize &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given \a - property's size range, the \a value is adjusted to the nearest - valid value within the size range. - - \sa value(), setRange(), valueChanged() -*/ -void QtSizePropertyManager::setValue(QtProperty *property, const QSize &val) -{ - setValueInRange(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - property, val, &QtSizePropertyManagerPrivate::setValue); -} - -/*! - Sets the minimum size value for the given \a property to \a minVal. - - When setting the minimum size value, the maximum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtSizePropertyManager::setMinimum(QtProperty *property, const QSize &minVal) -{ - setBorderValue(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - &QtSizePropertyManager::rangeChanged, - property, - &QtSizePropertyManagerPrivate::Data::minimumValue, - &QtSizePropertyManagerPrivate::Data::setMinimumValue, - minVal, &QtSizePropertyManagerPrivate::setRange); -} - -/*! - Sets the maximum size value for the given \a property to \a maxVal. - - When setting the maximum size value, the minimum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtSizePropertyManager::setMaximum(QtProperty *property, const QSize &maxVal) -{ - setBorderValue(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - &QtSizePropertyManager::rangeChanged, - property, - &QtSizePropertyManagerPrivate::Data::maximumValue, - &QtSizePropertyManagerPrivate::Data::setMaximumValue, - maxVal, &QtSizePropertyManagerPrivate::setRange); -} - -/*! - \fn void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minimum, const QSize &maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within the range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal) -{ - setBorderValues(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - &QtSizePropertyManager::rangeChanged, - property, minVal, maxVal, &QtSizePropertyManagerPrivate::setRange); -} - -/*! - \reimp -*/ -void QtSizePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtSizePropertyManagerPrivate::Data(); - - QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_intPropertyManager->setValue(wProp, 0); - d_ptr->m_intPropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_intPropertyManager->setValue(hProp, 0); - d_ptr->m_intPropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtSizePropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtSizeFPropertyManager - -class QtSizeFPropertyManagerPrivate -{ - QtSizeFPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtSizeFPropertyManager) -public: - - void slotDoubleChanged(QtProperty *property, double value); - void slotPropertyDestroyed(QtProperty *property); - void setValue(QtProperty *property, const QSizeF &val); - void setRange(QtProperty *property, - const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val); - - struct Data - { - Data() : val(QSizeF(0, 0)), minVal(QSizeF(0, 0)), maxVal(QSizeF(INT_MAX, INT_MAX)), decimals(2) {} - QSizeF val; - QSizeF minVal; - QSizeF maxVal; - int decimals; - QSizeF minimumValue() const { return minVal; } - QSizeF maximumValue() const { return maxVal; } - void setMinimumValue(const QSizeF &newMinVal) { setSizeMinimumData(this, newMinVal); } - void setMaximumValue(const QSizeF &newMaxVal) { setSizeMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtDoublePropertyManager *m_doublePropertyManager; - - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtSizeFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) -{ - if (QtProperty *prop = m_wToProperty.value(property, 0)) { - QSizeF s = m_values[prop].val; - s.setWidth(value); - q_ptr->setValue(prop, s); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - QSizeF s = m_values[prop].val; - s.setHeight(value); - q_ptr->setValue(prop, s); - } -} - -void QtSizeFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtSizeFPropertyManagerPrivate::setValue(QtProperty *property, const QSizeF &val) -{ - m_doublePropertyManager->setValue(m_propertyToW.value(property), val.width()); - m_doublePropertyManager->setValue(m_propertyToH.value(property), val.height()); -} - -void QtSizeFPropertyManagerPrivate::setRange(QtProperty *property, - const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val) -{ - m_doublePropertyManager->setRange(m_propertyToW[property], minVal.width(), maxVal.width()); - m_doublePropertyManager->setValue(m_propertyToW[property], val.width()); - m_doublePropertyManager->setRange(m_propertyToH[property], minVal.height(), maxVal.height()); - m_doublePropertyManager->setValue(m_propertyToH[property], val.height()); -} - -/*! - \class QtSizeFPropertyManager - - \brief The QtSizeFPropertyManager provides and manages QSizeF properties. - - A size property has nested \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtDoublePropertyManager object. This - manager can be retrieved using the subDoublePropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A size property also has a range of valid values defined by a - minimum size and a maximum size. These sizes can be retrieved - using the minimum() and the maximum() functions, and set using the - setMinimum() and setMaximum() slots. Alternatively, the range can - be defined in one go using the setRange() slot. - - In addition, QtSizeFPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid sizes. - - \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtSizePropertyManager -*/ - -/*! - \fn void QtSizeFPropertyManager::valueChanged(QtProperty *property, const QSizeF &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtSizeFPropertyManager::rangeChanged(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid sizes, passing a pointer to the \a - property and the new \a minimum and \a maximum sizes. - - \sa setRange() -*/ - -/*! - \fn void QtSizeFPropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtSizeFPropertyManager::QtSizeFPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtSizeFPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); - connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotDoubleChanged(QtProperty *, double))); - connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtSizeFPropertyManager::~QtSizeFPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e width and \e height - subproperties. - - In order to provide editing widgets for the \e width and \e height - properties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtDoublePropertyManager *QtSizeFPropertyManager::subDoublePropertyManager() const -{ - return d_ptr->m_doublePropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid size - - \sa setValue() -*/ -QSizeF QtSizeFPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtSizeFPropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtSizeFPropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - Returns the given \a property's minimum size value. - - \sa setMinimum(), maximum(), setRange() -*/ -QSizeF QtSizeFPropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's maximum size value. - - \sa setMaximum(), minimum(), setRange() -*/ -QSizeF QtSizeFPropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property); -} - -/*! - \reimp -*/ -QString QtSizeFPropertyManager::valueText(const QtProperty *property) const -{ - const QtSizeFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QSizeF v = it.value().val; - const int dec = it.value().decimals; - return QString(tr("%1 x %2").arg(QString::number(v.width(), 'f', dec)) - .arg(QString::number(v.height(), 'f', dec))); -} - -/*! - \fn void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given \a - property's size range, the \a value is adjusted to the nearest - valid value within the size range. - - \sa value(), setRange(), valueChanged() -*/ -void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &val) -{ - setValueInRange(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - property, val, &QtSizeFPropertyManagerPrivate::setValue); -} - -/*! - \fn void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtSizeFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtSizeFPropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec); - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - Sets the minimum size value for the given \a property to \a minVal. - - When setting the minimum size value, the maximum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtSizeFPropertyManager::setMinimum(QtProperty *property, const QSizeF &minVal) -{ - setBorderValue(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - &QtSizeFPropertyManager::rangeChanged, - property, - &QtSizeFPropertyManagerPrivate::Data::minimumValue, - &QtSizeFPropertyManagerPrivate::Data::setMinimumValue, - minVal, &QtSizeFPropertyManagerPrivate::setRange); -} - -/*! - Sets the maximum size value for the given \a property to \a maxVal. - - When setting the maximum size value, the minimum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtSizeFPropertyManager::setMaximum(QtProperty *property, const QSizeF &maxVal) -{ - setBorderValue(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - &QtSizeFPropertyManager::rangeChanged, - property, - &QtSizeFPropertyManagerPrivate::Data::maximumValue, - &QtSizeFPropertyManagerPrivate::Data::setMaximumValue, - maxVal, &QtSizeFPropertyManagerPrivate::setRange); -} - -/*! - \fn void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within the range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal) -{ - setBorderValues(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - &QtSizeFPropertyManager::rangeChanged, - property, minVal, maxVal, &QtSizeFPropertyManagerPrivate::setRange); -} - -/*! - \reimp -*/ -void QtSizeFPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtSizeFPropertyManagerPrivate::Data(); - - QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(wProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(hProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtSizeFPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtRectPropertyManager - -class QtRectPropertyManagerPrivate -{ - QtRectPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtRectPropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - void setConstraint(QtProperty *property, const QRect &constraint, const QRect &val); - - struct Data - { - Data() : val(0, 0, 0, 0) {} - QRect val; - QRect constraint; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_xToProperty; - QMap m_yToProperty; - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtRectPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_xToProperty.value(property, 0)) { - QRect r = m_values[prop].val; - r.moveLeft(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_yToProperty.value(property)) { - QRect r = m_values[prop].val; - r.moveTop(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_wToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRect r = data.val; - r.setWidth(value); - if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) { - r.moveLeft(data.constraint.left() + data.constraint.width() - r.width()); - } - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRect r = data.val; - r.setHeight(value); - if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) { - r.moveTop(data.constraint.top() + data.constraint.height() - r.height()); - } - q_ptr->setValue(prop, r); - } -} - -void QtRectPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtRectPropertyManagerPrivate::setConstraint(QtProperty *property, - const QRect &constraint, const QRect &val) -{ - const bool isNull = constraint.isNull(); - const int left = isNull ? INT_MIN : constraint.left(); - const int right = isNull ? INT_MAX : constraint.left() + constraint.width(); - const int top = isNull ? INT_MIN : constraint.top(); - const int bottom = isNull ? INT_MAX : constraint.top() + constraint.height(); - const int width = isNull ? INT_MAX : constraint.width(); - const int height = isNull ? INT_MAX : constraint.height(); - - m_intPropertyManager->setRange(m_propertyToX[property], left, right); - m_intPropertyManager->setRange(m_propertyToY[property], top, bottom); - m_intPropertyManager->setRange(m_propertyToW[property], 0, width); - m_intPropertyManager->setRange(m_propertyToH[property], 0, height); - - m_intPropertyManager->setValue(m_propertyToX[property], val.x()); - m_intPropertyManager->setValue(m_propertyToY[property], val.y()); - m_intPropertyManager->setValue(m_propertyToW[property], val.width()); - m_intPropertyManager->setValue(m_propertyToH[property], val.height()); -} - -/*! - \class QtRectPropertyManager - - \brief The QtRectPropertyManager provides and manages QRect properties. - - A rectangle property has nested \e x, \e y, \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A rectangle property also has a constraint rectangle which can be - retrieved using the constraint() function, and set using the - setConstraint() slot. - - In addition, QtRectPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the constraintChanged() signal which is emitted - whenever such a property changes its constraint rectangle. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtRectFPropertyManager -*/ - -/*! - \fn void QtRectPropertyManager::valueChanged(QtProperty *property, const QRect &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtRectPropertyManager::constraintChanged(QtProperty *property, const QRect &constraint) - - This signal is emitted whenever property changes its constraint - rectangle, passing a pointer to the \a property and the new \a - constraint rectangle as parameters. - - \sa setConstraint() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtRectPropertyManager::QtRectPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtRectPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtRectPropertyManager::~QtRectPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x, \e y, \e width - and \e height subproperties. - - In order to provide editing widgets for the mentioned - subproperties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtRectPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid rectangle. - - \sa setValue(), constraint() -*/ -QRect QtRectPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's constraining rectangle. If returned value is null QRect it means there is no constraint applied. - - \sa value(), setConstraint() -*/ -QRect QtRectPropertyManager::constraint(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtRectPropertyManagerPrivate::Data::constraint, property, QRect()); -} - -/*! - \reimp -*/ -QString QtRectPropertyManager::valueText(const QtProperty *property) const -{ - const QtRectPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QRect v = it.value().val; - return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x())) - .arg(QString::number(v.y())) - .arg(QString::number(v.width())) - .arg(QString::number(v.height()))); -} - -/*! - \fn void QtRectPropertyManager::setValue(QtProperty *property, const QRect &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - If the specified \a value is not inside the given \a property's - constraining rectangle, the value is adjusted accordingly to fit - within the constraint. - - \sa value(), setConstraint(), valueChanged() -*/ -void QtRectPropertyManager::setValue(QtProperty *property, const QRect &val) -{ - const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectPropertyManagerPrivate::Data data = it.value(); - - QRect newRect = val.normalized(); - if (!data.constraint.isNull() && !data.constraint.contains(newRect)) { - const QRect r1 = data.constraint; - const QRect r2 = newRect; - newRect.setLeft(qMax(r1.left(), r2.left())); - newRect.setRight(qMin(r1.right(), r2.right())); - newRect.setTop(qMax(r1.top(), r2.top())); - newRect.setBottom(qMin(r1.bottom(), r2.bottom())); - if (newRect.width() < 0 || newRect.height() < 0) - return; - } - - if (data.val == newRect) - return; - - data.val = newRect; - - it.value() = data; - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height()); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's constraining rectangle to \a - constraint. - - When setting the constraint, the current value is adjusted if - necessary (ensuring that the current rectangle value is inside the - constraint). In order to reset the constraint pass a null QRect value. - - \sa setValue(), constraint(), constraintChanged() -*/ -void QtRectPropertyManager::setConstraint(QtProperty *property, const QRect &constraint) -{ - const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectPropertyManagerPrivate::Data data = it.value(); - - QRect newConstraint = constraint.normalized(); - if (data.constraint == newConstraint) - return; - - const QRect oldVal = data.val; - - data.constraint = newConstraint; - - if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) { - QRect r1 = data.constraint; - QRect r2 = data.val; - - if (r2.width() > r1.width()) - r2.setWidth(r1.width()); - if (r2.height() > r1.height()) - r2.setHeight(r1.height()); - if (r2.left() < r1.left()) - r2.moveLeft(r1.left()); - else if (r2.right() > r1.right()) - r2.moveRight(r1.right()); - if (r2.top() < r1.top()) - r2.moveTop(r1.top()); - else if (r2.bottom() > r1.bottom()) - r2.moveBottom(r1.bottom()); - - data.val = r2; - } - - it.value() = data; - - emit constraintChanged(property, data.constraint); - - d_ptr->setConstraint(property, data.constraint, data.val); - - if (data.val == oldVal) - return; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - \reimp -*/ -void QtRectPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtRectPropertyManagerPrivate::Data(); - - QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_intPropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_intPropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); - - QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_intPropertyManager->setValue(wProp, 0); - d_ptr->m_intPropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_intPropertyManager->setValue(hProp, 0); - d_ptr->m_intPropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtRectPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtRectFPropertyManager - -class QtRectFPropertyManagerPrivate -{ - QtRectFPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtRectFPropertyManager) -public: - - void slotDoubleChanged(QtProperty *property, double value); - void slotPropertyDestroyed(QtProperty *property); - void setConstraint(QtProperty *property, const QRectF &constraint, const QRectF &val); - - struct Data - { - Data() : val(0, 0, 0, 0), decimals(2) {} - QRectF val; - QRectF constraint; - int decimals; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtDoublePropertyManager *m_doublePropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_xToProperty; - QMap m_yToProperty; - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtRectFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) -{ - if (QtProperty *prop = m_xToProperty.value(property, 0)) { - QRectF r = m_values[prop].val; - r.moveLeft(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_yToProperty.value(property, 0)) { - QRectF r = m_values[prop].val; - r.moveTop(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_wToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRectF r = data.val; - r.setWidth(value); - if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) { - r.moveLeft(data.constraint.left() + data.constraint.width() - r.width()); - } - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRectF r = data.val; - r.setHeight(value); - if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) { - r.moveTop(data.constraint.top() + data.constraint.height() - r.height()); - } - q_ptr->setValue(prop, r); - } -} - -void QtRectFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtRectFPropertyManagerPrivate::setConstraint(QtProperty *property, - const QRectF &constraint, const QRectF &val) -{ - const bool isNull = constraint.isNull(); - const float left = isNull ? FLT_MIN : constraint.left(); - const float right = isNull ? FLT_MAX : constraint.left() + constraint.width(); - const float top = isNull ? FLT_MIN : constraint.top(); - const float bottom = isNull ? FLT_MAX : constraint.top() + constraint.height(); - const float width = isNull ? FLT_MAX : constraint.width(); - const float height = isNull ? FLT_MAX : constraint.height(); - - m_doublePropertyManager->setRange(m_propertyToX[property], left, right); - m_doublePropertyManager->setRange(m_propertyToY[property], top, bottom); - m_doublePropertyManager->setRange(m_propertyToW[property], 0, width); - m_doublePropertyManager->setRange(m_propertyToH[property], 0, height); - - m_doublePropertyManager->setValue(m_propertyToX[property], val.x()); - m_doublePropertyManager->setValue(m_propertyToY[property], val.y()); - m_doublePropertyManager->setValue(m_propertyToW[property], val.width()); - m_doublePropertyManager->setValue(m_propertyToH[property], val.height()); -} - -/*! - \class QtRectFPropertyManager - - \brief The QtRectFPropertyManager provides and manages QRectF properties. - - A rectangle property has nested \e x, \e y, \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtDoublePropertyManager object. This - manager can be retrieved using the subDoublePropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A rectangle property also has a constraint rectangle which can be - retrieved using the constraint() function, and set using the - setConstraint() slot. - - In addition, QtRectFPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the constraintChanged() signal which is emitted - whenever such a property changes its constraint rectangle. - - \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtRectPropertyManager -*/ - -/*! - \fn void QtRectFPropertyManager::valueChanged(QtProperty *property, const QRectF &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtRectFPropertyManager::constraintChanged(QtProperty *property, const QRectF &constraint) - - This signal is emitted whenever property changes its constraint - rectangle, passing a pointer to the \a property and the new \a - constraint rectangle as parameters. - - \sa setConstraint() -*/ - -/*! - \fn void QtRectFPropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtRectFPropertyManager::QtRectFPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtRectFPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); - connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotDoubleChanged(QtProperty *, double))); - connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtRectFPropertyManager::~QtRectFPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x, \e y, \e width - and \e height subproperties. - - In order to provide editing widgets for the mentioned - subproperties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtDoublePropertyManager *QtRectFPropertyManager::subDoublePropertyManager() const -{ - return d_ptr->m_doublePropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid rectangle. - - \sa setValue(), constraint() -*/ -QRectF QtRectFPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtRectFPropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - Returns the given \a property's constraining rectangle. If returned value is null QRectF it means there is no constraint applied. - - \sa value(), setConstraint() -*/ -QRectF QtRectFPropertyManager::constraint(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::constraint, property, QRect()); -} - -/*! - \reimp -*/ -QString QtRectFPropertyManager::valueText(const QtProperty *property) const -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QRectF v = it.value().val; - const int dec = it.value().decimals; - return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x(), 'f', dec)) - .arg(QString::number(v.y(), 'f', dec)) - .arg(QString::number(v.width(), 'f', dec)) - .arg(QString::number(v.height(), 'f', dec))); -} - -/*! - \fn void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - If the specified \a value is not inside the given \a property's - constraining rectangle, the value is adjusted accordingly to fit - within the constraint. - - \sa value(), setConstraint(), valueChanged() -*/ -void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &val) -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectFPropertyManagerPrivate::Data data = it.value(); - - QRectF newRect = val.normalized(); - if (!data.constraint.isNull() && !data.constraint.contains(newRect)) { - const QRectF r1 = data.constraint; - const QRectF r2 = newRect; - newRect.setLeft(qMax(r1.left(), r2.left())); - newRect.setRight(qMin(r1.right(), r2.right())); - newRect.setTop(qMax(r1.top(), r2.top())); - newRect.setBottom(qMin(r1.bottom(), r2.bottom())); - if (newRect.width() < 0 || newRect.height() < 0) - return; - } - - if (data.val == newRect) - return; - - data.val = newRect; - - it.value() = data; - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height()); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's constraining rectangle to \a - constraint. - - When setting the constraint, the current value is adjusted if - necessary (ensuring that the current rectangle value is inside the - constraint). In order to reset the constraint pass a null QRectF value. - - \sa setValue(), constraint(), constraintChanged() -*/ -void QtRectFPropertyManager::setConstraint(QtProperty *property, const QRectF &constraint) -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectFPropertyManagerPrivate::Data data = it.value(); - - QRectF newConstraint = constraint.normalized(); - if (data.constraint == newConstraint) - return; - - const QRectF oldVal = data.val; - - data.constraint = newConstraint; - - if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) { - QRectF r1 = data.constraint; - QRectF r2 = data.val; - - if (r2.width() > r1.width()) - r2.setWidth(r1.width()); - if (r2.height() > r1.height()) - r2.setHeight(r1.height()); - if (r2.left() < r1.left()) - r2.moveLeft(r1.left()); - else if (r2.right() > r1.right()) - r2.moveRight(r1.right()); - if (r2.top() < r1.top()) - r2.moveTop(r1.top()); - else if (r2.bottom() > r1.bottom()) - r2.moveBottom(r1.bottom()); - - data.val = r2; - } - - it.value() = data; - - emit constraintChanged(property, data.constraint); - - d_ptr->setConstraint(property, data.constraint, data.val); - - if (data.val == oldVal) - return; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - \fn void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectFPropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec); - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - \reimp -*/ -void QtRectFPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtRectFPropertyManagerPrivate::Data(); - - QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); - - QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(wProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(hProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtRectFPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtEnumPropertyManager - -class QtEnumPropertyManagerPrivate -{ - QtEnumPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtEnumPropertyManager) -public: - - struct Data - { - Data() : val(-1) {} - int val; - QStringList enumNames; - QMap enumIcons; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtEnumPropertyManager - - \brief The QtEnumPropertyManager provides and manages enum properties. - - Each enum property has an associated list of enum names which can - be retrieved using the enumNames() function, and set using the - corresponding setEnumNames() function. An enum property's value is - represented by an index in this list, and can be retrieved and set - using the value() and setValue() slots respectively. - - Each enum value can also have an associated icon. The mapping from - values to icons can be set using the setEnumIcons() function and - queried with the enumIcons() function. - - In addition, QtEnumPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. The enumNamesChanged() or enumIconsChanged() signal is emitted - whenever the list of enum names or icons is altered. - - \sa QtAbstractPropertyManager, QtEnumEditorFactory -*/ - -/*! - \fn void QtEnumPropertyManager::valueChanged(QtProperty *property, int value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtEnumPropertyManager::enumNamesChanged(QtProperty *property, const QStringList &names) - - This signal is emitted whenever a property created by this manager - changes its enum names, passing a pointer to the \a property and - the new \a names as parameters. - - \sa setEnumNames() -*/ - -/*! - \fn void QtEnumPropertyManager::enumIconsChanged(QtProperty *property, const QMap &icons) - - This signal is emitted whenever a property created by this manager - changes its enum icons, passing a pointer to the \a property and - the new mapping of values to \a icons as parameters. - - \sa setEnumIcons() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtEnumPropertyManager::QtEnumPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtEnumPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtEnumPropertyManager::~QtEnumPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value which is an index in the - list returned by enumNames() - - If the given property is not managed by this manager, this - function returns -1. - - \sa enumNames(), setValue() -*/ -int QtEnumPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, -1); -} - -/*! - Returns the given \a property's list of enum names. - - \sa value(), setEnumNames() -*/ -QStringList QtEnumPropertyManager::enumNames(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumNames, property, QStringList()); -} - -/*! - Returns the given \a property's map of enum values to their icons. - - \sa value(), setEnumIcons() -*/ -QMap QtEnumPropertyManager::enumIcons(const QtProperty *property) const -{ - return getData >(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumIcons, property, QMap()); -} - -/*! - \reimp -*/ -QString QtEnumPropertyManager::valueText(const QtProperty *property) const -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QtEnumPropertyManagerPrivate::Data &data = it.value(); - - const int v = data.val; - if (v >= 0 && v < data.enumNames.count()) - return data.enumNames.at(v); - return QString(); -} - -/*! - \reimp -*/ -QIcon QtEnumPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - const QtEnumPropertyManagerPrivate::Data &data = it.value(); - - const int v = data.val; - return data.enumIcons.value(v); -} - -/*! - \fn void QtEnumPropertyManager::setValue(QtProperty *property, int value) - - Sets the value of the given \a property to \a value. - - The specified \a value must be less than the size of the given \a - property's enumNames() list, and larger than (or equal to) 0. - - \sa value(), valueChanged() -*/ -void QtEnumPropertyManager::setValue(QtProperty *property, int val) -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtEnumPropertyManagerPrivate::Data data = it.value(); - - if (val >= data.enumNames.count()) - return; - - if (val < 0 && data.enumNames.count() > 0) - return; - - if (val < 0) - val = -1; - - if (data.val == val) - return; - - data.val = val; - - it.value() = data; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's list of enum names to \a - enumNames. The \a property's current value is reset to 0 - indicating the first item of the list. - - If the specified \a enumNames list is empty, the \a property's - current value is set to -1. - - \sa enumNames(), enumNamesChanged() -*/ -void QtEnumPropertyManager::setEnumNames(QtProperty *property, const QStringList &enumNames) -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtEnumPropertyManagerPrivate::Data data = it.value(); - - if (data.enumNames == enumNames) - return; - - data.enumNames = enumNames; - - data.val = -1; - - if (enumNames.count() > 0) - data.val = 0; - - it.value() = data; - - emit enumNamesChanged(property, data.enumNames); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's map of enum values to their icons to \a - enumIcons. - - Each enum value can have associated icon. This association is represented with passed \a enumIcons map. - - \sa enumNames(), enumNamesChanged() -*/ -void QtEnumPropertyManager::setEnumIcons(QtProperty *property, const QMap &enumIcons) -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - it.value().enumIcons = enumIcons; - - emit enumIconsChanged(property, it.value().enumIcons); - - emit propertyChanged(property); -} - -/*! - \reimp -*/ -void QtEnumPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtEnumPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtEnumPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtFlagPropertyManager - -class QtFlagPropertyManagerPrivate -{ - QtFlagPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtFlagPropertyManager) -public: - - void slotBoolChanged(QtProperty *property, bool value); - void slotPropertyDestroyed(QtProperty *property); - - struct Data - { - Data() : val(-1) {} - int val; - QStringList flagNames; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtBoolPropertyManager *m_boolPropertyManager; - - QMap > m_propertyToFlags; - - QMap m_flagToProperty; -}; - -void QtFlagPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value) -{ - QtProperty *prop = m_flagToProperty.value(property, 0); - if (prop == 0) - return; - - QListIterator itProp(m_propertyToFlags[prop]); - int level = 0; - while (itProp.hasNext()) { - QtProperty *p = itProp.next(); - if (p == property) { - int v = m_values[prop].val; - if (value) { - v |= (1 << level); - } else { - v &= ~(1 << level); - } - q_ptr->setValue(prop, v); - return; - } - level++; - } -} - -void QtFlagPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - QtProperty *flagProperty = m_flagToProperty.value(property, 0); - if (flagProperty == 0) - return; - - m_propertyToFlags[flagProperty].replace(m_propertyToFlags[flagProperty].indexOf(property), 0); - m_flagToProperty.remove(property); -} - -/*! - \class QtFlagPropertyManager - - \brief The QtFlagPropertyManager provides and manages flag properties. - - Each flag property has an associated list of flag names which can - be retrieved using the flagNames() function, and set using the - corresponding setFlagNames() function. - - The flag manager provides properties with nested boolean - subproperties representing each flag, i.e. a flag property's value - is the binary combination of the subproperties' values. A - property's value can be retrieved and set using the value() and - setValue() slots respectively. The combination of flags is represented - by single int value - that's why it's possible to store up to - 32 independent flags in one flag property. - - The subproperties are created by a QtBoolPropertyManager object. This - manager can be retrieved using the subBoolPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtFlagPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the flagNamesChanged() signal which is emitted - whenever the list of flag names is altered. - - \sa QtAbstractPropertyManager, QtBoolPropertyManager -*/ - -/*! - \fn void QtFlagPropertyManager::valueChanged(QtProperty *property, int value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtFlagPropertyManager::flagNamesChanged(QtProperty *property, const QStringList &names) - - This signal is emitted whenever a property created by this manager - changes its flag names, passing a pointer to the \a property and the - new \a names as parameters. - - \sa setFlagNames() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtFlagPropertyManager::QtFlagPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtFlagPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this); - connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotBoolChanged(QtProperty *, bool))); - connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtFlagPropertyManager::~QtFlagPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that produces the nested boolean subproperties - representing each flag. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtBoolPropertyManager *QtFlagPropertyManager::subBoolPropertyManager() const -{ - return d_ptr->m_boolPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns 0. - - \sa flagNames(), setValue() -*/ -int QtFlagPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's list of flag names. - - \sa value(), setFlagNames() -*/ -QStringList QtFlagPropertyManager::flagNames(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtFlagPropertyManagerPrivate::Data::flagNames, property, QStringList()); -} - -/*! - \reimp -*/ -QString QtFlagPropertyManager::valueText(const QtProperty *property) const -{ - const QtFlagPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QtFlagPropertyManagerPrivate::Data &data = it.value(); - - QString str; - int level = 0; - const QChar bar = QLatin1Char('|'); - const QStringList::const_iterator fncend = data.flagNames.constEnd(); - for (QStringList::const_iterator it = data.flagNames.constBegin(); it != fncend; ++it) { - if (data.val & (1 << level)) { - if (!str.isEmpty()) - str += bar; - str += *it; - } - - level++; - } - return str; -} - -/*! - \fn void QtFlagPropertyManager::setValue(QtProperty *property, int value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - The specified \a value must be less than the binary combination of - the property's flagNames() list size (i.e. less than 2\sup n, - where \c n is the size of the list) and larger than (or equal to) - 0. - - \sa value(), valueChanged() -*/ -void QtFlagPropertyManager::setValue(QtProperty *property, int val) -{ - const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtFlagPropertyManagerPrivate::Data data = it.value(); - - if (data.val == val) - return; - - if (val > (1 << data.flagNames.count()) - 1) - return; - - if (val < 0) - return; - - data.val = val; - - it.value() = data; - - QListIterator itProp(d_ptr->m_propertyToFlags[property]); - int level = 0; - while (itProp.hasNext()) { - QtProperty *prop = itProp.next(); - if (prop) - d_ptr->m_boolPropertyManager->setValue(prop, val & (1 << level)); - level++; - } - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's list of flag names to \a flagNames. The - property's current value is reset to 0 indicating the first item - of the list. - - \sa flagNames(), flagNamesChanged() -*/ -void QtFlagPropertyManager::setFlagNames(QtProperty *property, const QStringList &flagNames) -{ - const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtFlagPropertyManagerPrivate::Data data = it.value(); - - if (data.flagNames == flagNames) - return; - - data.flagNames = flagNames; - data.val = 0; - - it.value() = data; - - QListIterator itProp(d_ptr->m_propertyToFlags[property]); - while (itProp.hasNext()) { - QtProperty *prop = itProp.next(); - if (prop) { - delete prop; - d_ptr->m_flagToProperty.remove(prop); - } - } - d_ptr->m_propertyToFlags[property].clear(); - - QStringListIterator itFlag(flagNames); - while (itFlag.hasNext()) { - const QString flagName = itFlag.next(); - QtProperty *prop = d_ptr->m_boolPropertyManager->addProperty(); - prop->setPropertyName(flagName); - property->addSubProperty(prop); - d_ptr->m_propertyToFlags[property].append(prop); - d_ptr->m_flagToProperty[prop] = property; - } - - emit flagNamesChanged(property, data.flagNames); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - \reimp -*/ -void QtFlagPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtFlagPropertyManagerPrivate::Data(); - - d_ptr->m_propertyToFlags[property] = QList(); -} - -/*! - \reimp -*/ -void QtFlagPropertyManager::uninitializeProperty(QtProperty *property) -{ - QListIterator itProp(d_ptr->m_propertyToFlags[property]); - while (itProp.hasNext()) { - QtProperty *prop = itProp.next(); - if (prop) { - delete prop; - d_ptr->m_flagToProperty.remove(prop); - } - } - d_ptr->m_propertyToFlags.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtSizePolicyPropertyManager - -class QtSizePolicyPropertyManagerPrivate -{ - QtSizePolicyPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtSizePolicyPropertyManager) -public: - - QtSizePolicyPropertyManagerPrivate(); - - void slotIntChanged(QtProperty *property, int value); - void slotEnumChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - QtEnumPropertyManager *m_enumPropertyManager; - - QMap m_propertyToHPolicy; - QMap m_propertyToVPolicy; - QMap m_propertyToHStretch; - QMap m_propertyToVStretch; - - QMap m_hPolicyToProperty; - QMap m_vPolicyToProperty; - QMap m_hStretchToProperty; - QMap m_vStretchToProperty; -}; - -QtSizePolicyPropertyManagerPrivate::QtSizePolicyPropertyManagerPrivate() -{ -} - -void QtSizePolicyPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_hStretchToProperty.value(property, 0)) { - QSizePolicy sp = m_values[prop]; - sp.setHorizontalStretch(value); - q_ptr->setValue(prop, sp); - } else if (QtProperty *prop = m_vStretchToProperty.value(property, 0)) { - QSizePolicy sp = m_values[prop]; - sp.setVerticalStretch(value); - q_ptr->setValue(prop, sp); - } -} - -void QtSizePolicyPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_hPolicyToProperty.value(property, 0)) { - QSizePolicy sp = m_values[prop]; - sp.setHorizontalPolicy(metaEnumProvider()->indexToSizePolicy(value)); - q_ptr->setValue(prop, sp); - } else if (QtProperty *prop = m_vPolicyToProperty.value(property, 0)) { - QSizePolicy sp = m_values[prop]; - sp.setVerticalPolicy(metaEnumProvider()->indexToSizePolicy(value)); - q_ptr->setValue(prop, sp); - } -} - -void QtSizePolicyPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_hStretchToProperty.value(property, 0)) { - m_propertyToHStretch[pointProp] = 0; - m_hStretchToProperty.remove(property); - } else if (QtProperty *pointProp = m_vStretchToProperty.value(property, 0)) { - m_propertyToVStretch[pointProp] = 0; - m_vStretchToProperty.remove(property); - } else if (QtProperty *pointProp = m_hPolicyToProperty.value(property, 0)) { - m_propertyToHPolicy[pointProp] = 0; - m_hPolicyToProperty.remove(property); - } else if (QtProperty *pointProp = m_vPolicyToProperty.value(property, 0)) { - m_propertyToVPolicy[pointProp] = 0; - m_vPolicyToProperty.remove(property); - } -} - -/*! - \class QtSizePolicyPropertyManager - - \brief The QtSizePolicyPropertyManager provides and manages QSizePolicy properties. - - A size policy property has nested \e horizontalPolicy, \e - verticalPolicy, \e horizontalStretch and \e verticalStretch - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by QtIntPropertyManager and QtEnumPropertyManager - objects. These managers can be retrieved using the subIntPropertyManager() - and subEnumPropertyManager() functions respectively. In order to provide - editing widgets for the subproperties in a property browser widget, - these managers must be associated with editor factories. - - In addition, QtSizePolicyPropertyManager provides the valueChanged() - signal which is emitted whenever a property created by this - manager changes. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtEnumPropertyManager -*/ - -/*! - \fn void QtSizePolicyPropertyManager::valueChanged(QtProperty *property, const QSizePolicy &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtSizePolicyPropertyManager::QtSizePolicyPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtSizePolicyPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); - connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotEnumChanged(QtProperty *, int))); - - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); - connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtSizePolicyPropertyManager::~QtSizePolicyPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e horizontalStretch - and \e verticalStretch subproperties. - - In order to provide editing widgets for the mentioned subproperties - in a property browser widget, this manager must be associated with - an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtSizePolicyPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the manager that creates the nested \e horizontalPolicy - and \e verticalPolicy subproperties. - - In order to provide editing widgets for the mentioned subproperties - in a property browser widget, this manager must be associated with - an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtEnumPropertyManager *QtSizePolicyPropertyManager::subEnumPropertyManager() const -{ - return d_ptr->m_enumPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns the default size policy. - - \sa setValue() -*/ -QSizePolicy QtSizePolicyPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QSizePolicy()); -} - -/*! - \reimp -*/ -QString QtSizePolicyPropertyManager::valueText(const QtProperty *property) const -{ - const QtSizePolicyPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QSizePolicy sp = it.value(); - const QtMetaEnumProvider *mep = metaEnumProvider(); - const int hIndex = mep->sizePolicyToIndex(sp.horizontalPolicy()); - const int vIndex = mep->sizePolicyToIndex(sp.verticalPolicy()); - //! Unknown size policy on reading invalid uic3 files - const QString hPolicy = hIndex != -1 ? mep->policyEnumNames().at(hIndex) : tr(""); - const QString vPolicy = vIndex != -1 ? mep->policyEnumNames().at(vIndex) : tr(""); - const QString str = tr("[%1, %2, %3, %4]").arg(hPolicy, vPolicy).arg(sp.horizontalStretch()).arg(sp.verticalStretch()); - return str; -} - -/*! - \fn void QtSizePolicyPropertyManager::setValue(QtProperty *property, const QSizePolicy &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtSizePolicyPropertyManager::setValue(QtProperty *property, const QSizePolicy &val) -{ - const QtSizePolicyPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - - d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToHPolicy[property], - metaEnumProvider()->sizePolicyToIndex(val.horizontalPolicy())); - d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToVPolicy[property], - metaEnumProvider()->sizePolicyToIndex(val.verticalPolicy())); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToHStretch[property], - val.horizontalStretch()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToVStretch[property], - val.verticalStretch()); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtSizePolicyPropertyManager::initializeProperty(QtProperty *property) -{ - QSizePolicy val; - d_ptr->m_values[property] = val; - - QtProperty *hPolicyProp = d_ptr->m_enumPropertyManager->addProperty(); - hPolicyProp->setPropertyName(tr("Horizontal Policy")); - d_ptr->m_enumPropertyManager->setEnumNames(hPolicyProp, metaEnumProvider()->policyEnumNames()); - d_ptr->m_enumPropertyManager->setValue(hPolicyProp, - metaEnumProvider()->sizePolicyToIndex(val.horizontalPolicy())); - d_ptr->m_propertyToHPolicy[property] = hPolicyProp; - d_ptr->m_hPolicyToProperty[hPolicyProp] = property; - property->addSubProperty(hPolicyProp); - - QtProperty *vPolicyProp = d_ptr->m_enumPropertyManager->addProperty(); - vPolicyProp->setPropertyName(tr("Vertical Policy")); - d_ptr->m_enumPropertyManager->setEnumNames(vPolicyProp, metaEnumProvider()->policyEnumNames()); - d_ptr->m_enumPropertyManager->setValue(vPolicyProp, - metaEnumProvider()->sizePolicyToIndex(val.verticalPolicy())); - d_ptr->m_propertyToVPolicy[property] = vPolicyProp; - d_ptr->m_vPolicyToProperty[vPolicyProp] = property; - property->addSubProperty(vPolicyProp); - - QtProperty *hStretchProp = d_ptr->m_intPropertyManager->addProperty(); - hStretchProp->setPropertyName(tr("Horizontal Stretch")); - d_ptr->m_intPropertyManager->setValue(hStretchProp, val.horizontalStretch()); - d_ptr->m_intPropertyManager->setRange(hStretchProp, 0, 0xff); - d_ptr->m_propertyToHStretch[property] = hStretchProp; - d_ptr->m_hStretchToProperty[hStretchProp] = property; - property->addSubProperty(hStretchProp); - - QtProperty *vStretchProp = d_ptr->m_intPropertyManager->addProperty(); - vStretchProp->setPropertyName(tr("Vertical Stretch")); - d_ptr->m_intPropertyManager->setValue(vStretchProp, val.verticalStretch()); - d_ptr->m_intPropertyManager->setRange(vStretchProp, 0, 0xff); - d_ptr->m_propertyToVStretch[property] = vStretchProp; - d_ptr->m_vStretchToProperty[vStretchProp] = property; - property->addSubProperty(vStretchProp); - -} - -/*! - \reimp -*/ -void QtSizePolicyPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *hPolicyProp = d_ptr->m_propertyToHPolicy[property]; - if (hPolicyProp) { - d_ptr->m_hPolicyToProperty.remove(hPolicyProp); - delete hPolicyProp; - } - d_ptr->m_propertyToHPolicy.remove(property); - - QtProperty *vPolicyProp = d_ptr->m_propertyToVPolicy[property]; - if (vPolicyProp) { - d_ptr->m_vPolicyToProperty.remove(vPolicyProp); - delete vPolicyProp; - } - d_ptr->m_propertyToVPolicy.remove(property); - - QtProperty *hStretchProp = d_ptr->m_propertyToHStretch[property]; - if (hStretchProp) { - d_ptr->m_hStretchToProperty.remove(hStretchProp); - delete hStretchProp; - } - d_ptr->m_propertyToHStretch.remove(property); - - QtProperty *vStretchProp = d_ptr->m_propertyToVStretch[property]; - if (vStretchProp) { - d_ptr->m_vStretchToProperty.remove(vStretchProp); - delete vStretchProp; - } - d_ptr->m_propertyToVStretch.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtFontPropertyManager: -// QtFontPropertyManagerPrivate has a mechanism for reacting -// to QApplication::fontDatabaseChanged() [4.5], which is emitted -// when someone loads an application font. The signals are compressed -// using a timer with interval 0, which then causes the family -// enumeration manager to re-set its strings and index values -// for each property. - -Q_GLOBAL_STATIC(QFontDatabase, fontDatabase) - -class QtFontPropertyManagerPrivate -{ - QtFontPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtFontPropertyManager) -public: - - QtFontPropertyManagerPrivate(); - - void slotIntChanged(QtProperty *property, int value); - void slotEnumChanged(QtProperty *property, int value); - void slotBoolChanged(QtProperty *property, bool value); - void slotPropertyDestroyed(QtProperty *property); - void slotFontDatabaseChanged(); - void slotFontDatabaseDelayedChange(); - - QStringList m_familyNames; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - QtEnumPropertyManager *m_enumPropertyManager; - QtBoolPropertyManager *m_boolPropertyManager; - - QMap m_propertyToFamily; - QMap m_propertyToPointSize; - QMap m_propertyToBold; - QMap m_propertyToItalic; - QMap m_propertyToUnderline; - QMap m_propertyToStrikeOut; - QMap m_propertyToKerning; - - QMap m_familyToProperty; - QMap m_pointSizeToProperty; - QMap m_boldToProperty; - QMap m_italicToProperty; - QMap m_underlineToProperty; - QMap m_strikeOutToProperty; - QMap m_kerningToProperty; - - bool m_settingValue; - QTimer *m_fontDatabaseChangeTimer; -}; - -QtFontPropertyManagerPrivate::QtFontPropertyManagerPrivate() : - m_settingValue(false), - m_fontDatabaseChangeTimer(0) -{ -} - -void QtFontPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (m_settingValue) - return; - if (QtProperty *prop = m_pointSizeToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setPointSize(value); - q_ptr->setValue(prop, f); - } -} - -void QtFontPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) -{ - if (m_settingValue) - return; - if (QtProperty *prop = m_familyToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setFamily(m_familyNames.at(value)); - q_ptr->setValue(prop, f); - } -} - -void QtFontPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value) -{ - if (m_settingValue) - return; - if (QtProperty *prop = m_boldToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setBold(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_italicToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setItalic(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_underlineToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setUnderline(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_strikeOutToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setStrikeOut(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_kerningToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setKerning(value); - q_ptr->setValue(prop, f); - } -} - -void QtFontPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_pointSizeToProperty.value(property, 0)) { - m_propertyToPointSize[pointProp] = 0; - m_pointSizeToProperty.remove(property); - } else if (QtProperty *pointProp = m_familyToProperty.value(property, 0)) { - m_propertyToFamily[pointProp] = 0; - m_familyToProperty.remove(property); - } else if (QtProperty *pointProp = m_boldToProperty.value(property, 0)) { - m_propertyToBold[pointProp] = 0; - m_boldToProperty.remove(property); - } else if (QtProperty *pointProp = m_italicToProperty.value(property, 0)) { - m_propertyToItalic[pointProp] = 0; - m_italicToProperty.remove(property); - } else if (QtProperty *pointProp = m_underlineToProperty.value(property, 0)) { - m_propertyToUnderline[pointProp] = 0; - m_underlineToProperty.remove(property); - } else if (QtProperty *pointProp = m_strikeOutToProperty.value(property, 0)) { - m_propertyToStrikeOut[pointProp] = 0; - m_strikeOutToProperty.remove(property); - } else if (QtProperty *pointProp = m_kerningToProperty.value(property, 0)) { - m_propertyToKerning[pointProp] = 0; - m_kerningToProperty.remove(property); - } -} - -void QtFontPropertyManagerPrivate::slotFontDatabaseChanged() -{ - if (!m_fontDatabaseChangeTimer) { - m_fontDatabaseChangeTimer = new QTimer(q_ptr); - m_fontDatabaseChangeTimer->setInterval(0); - m_fontDatabaseChangeTimer->setSingleShot(true); - QObject::connect(m_fontDatabaseChangeTimer, SIGNAL(timeout()), q_ptr, SLOT(slotFontDatabaseDelayedChange())); - } - if (!m_fontDatabaseChangeTimer->isActive()) - m_fontDatabaseChangeTimer->start(); -} - -void QtFontPropertyManagerPrivate::slotFontDatabaseDelayedChange() -{ - typedef QMap PropertyPropertyMap; - // rescan available font names - const QStringList oldFamilies = m_familyNames; - m_familyNames = fontDatabase()->families(); - - // Adapt all existing properties - if (!m_propertyToFamily.empty()) { - PropertyPropertyMap::const_iterator cend = m_propertyToFamily.constEnd(); - for (PropertyPropertyMap::const_iterator it = m_propertyToFamily.constBegin(); it != cend; ++it) { - QtProperty *familyProp = it.value(); - const int oldIdx = m_enumPropertyManager->value(familyProp); - int newIdx = m_familyNames.indexOf(oldFamilies.at(oldIdx)); - if (newIdx < 0) - newIdx = 0; - m_enumPropertyManager->setEnumNames(familyProp, m_familyNames); - m_enumPropertyManager->setValue(familyProp, newIdx); - } - } -} - -/*! - \class QtFontPropertyManager - - \brief The QtFontPropertyManager provides and manages QFont properties. - - A font property has nested \e family, \e pointSize, \e bold, \e - italic, \e underline, \e strikeOut and \e kerning subproperties. The top-level - property's value can be retrieved using the value() function, and - set using the setValue() slot. - - The subproperties are created by QtIntPropertyManager, QtEnumPropertyManager and - QtBoolPropertyManager objects. These managers can be retrieved using the - corresponding subIntPropertyManager(), subEnumPropertyManager() and - subBoolPropertyManager() functions. In order to provide editing widgets - for the subproperties in a property browser widget, these managers - must be associated with editor factories. - - In addition, QtFontPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtEnumPropertyManager, QtIntPropertyManager, QtBoolPropertyManager -*/ - -/*! - \fn void QtFontPropertyManager::valueChanged(QtProperty *property, const QFont &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtFontPropertyManager::QtFontPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtFontPropertyManagerPrivate; - d_ptr->q_ptr = this; -#if QT_VERSION >= 0x040500 - QObject::connect(qApp, SIGNAL(fontDatabaseChanged()), this, SLOT(slotFontDatabaseChanged())); -#endif - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); - connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotEnumChanged(QtProperty *, int))); - d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this); - connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotBoolChanged(QtProperty *, bool))); - - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); - connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); - connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtFontPropertyManager::~QtFontPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the \e pointSize subproperty. - - In order to provide editing widgets for the \e pointSize property - in a property browser widget, this manager must be associated - with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtFontPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the manager that create the \e family subproperty. - - In order to provide editing widgets for the \e family property - in a property browser widget, this manager must be associated - with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtEnumPropertyManager *QtFontPropertyManager::subEnumPropertyManager() const -{ - return d_ptr->m_enumPropertyManager; -} - -/*! - Returns the manager that creates the \e bold, \e italic, \e underline, - \e strikeOut and \e kerning subproperties. - - In order to provide editing widgets for the mentioned properties - in a property browser widget, this manager must be associated with - an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtBoolPropertyManager *QtFontPropertyManager::subBoolPropertyManager() const -{ - return d_ptr->m_boolPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns a font object that uses the application's default - font. - - \sa setValue() -*/ -QFont QtFontPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QFont()); -} - -/*! - \reimp -*/ -QString QtFontPropertyManager::valueText(const QtProperty *property) const -{ - const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return QtPropertyBrowserUtils::fontValueText(it.value()); -} - -/*! - \reimp -*/ -QIcon QtFontPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - return QtPropertyBrowserUtils::fontValueIcon(it.value()); -} - -/*! - \fn void QtFontPropertyManager::setValue(QtProperty *property, const QFont &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtFontPropertyManager::setValue(QtProperty *property, const QFont &val) -{ - const QtFontPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - const QFont oldVal = it.value(); - if (oldVal == val && oldVal.resolve() == val.resolve()) - return; - - it.value() = val; - - int idx = d_ptr->m_familyNames.indexOf(val.family()); - if (idx == -1) - idx = 0; - bool settingValue = d_ptr->m_settingValue; - d_ptr->m_settingValue = true; - d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToFamily[property], idx); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToPointSize[property], val.pointSize()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToBold[property], val.bold()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToItalic[property], val.italic()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToUnderline[property], val.underline()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToStrikeOut[property], val.strikeOut()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToKerning[property], val.kerning()); - d_ptr->m_settingValue = settingValue; - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtFontPropertyManager::initializeProperty(QtProperty *property) -{ - QFont val; - d_ptr->m_values[property] = val; - - QtProperty *familyProp = d_ptr->m_enumPropertyManager->addProperty(); - familyProp->setPropertyName(tr("Family")); - if (d_ptr->m_familyNames.empty()) - d_ptr->m_familyNames = fontDatabase()->families(); - d_ptr->m_enumPropertyManager->setEnumNames(familyProp, d_ptr->m_familyNames); - int idx = d_ptr->m_familyNames.indexOf(val.family()); - if (idx == -1) - idx = 0; - d_ptr->m_enumPropertyManager->setValue(familyProp, idx); - d_ptr->m_propertyToFamily[property] = familyProp; - d_ptr->m_familyToProperty[familyProp] = property; - property->addSubProperty(familyProp); - - QtProperty *pointSizeProp = d_ptr->m_intPropertyManager->addProperty(); - pointSizeProp->setPropertyName(tr("Point Size")); - d_ptr->m_intPropertyManager->setValue(pointSizeProp, val.pointSize()); - d_ptr->m_intPropertyManager->setMinimum(pointSizeProp, 1); - d_ptr->m_propertyToPointSize[property] = pointSizeProp; - d_ptr->m_pointSizeToProperty[pointSizeProp] = property; - property->addSubProperty(pointSizeProp); - - QtProperty *boldProp = d_ptr->m_boolPropertyManager->addProperty(); - boldProp->setPropertyName(tr("Bold")); - d_ptr->m_boolPropertyManager->setValue(boldProp, val.bold()); - d_ptr->m_propertyToBold[property] = boldProp; - d_ptr->m_boldToProperty[boldProp] = property; - property->addSubProperty(boldProp); - - QtProperty *italicProp = d_ptr->m_boolPropertyManager->addProperty(); - italicProp->setPropertyName(tr("Italic")); - d_ptr->m_boolPropertyManager->setValue(italicProp, val.italic()); - d_ptr->m_propertyToItalic[property] = italicProp; - d_ptr->m_italicToProperty[italicProp] = property; - property->addSubProperty(italicProp); - - QtProperty *underlineProp = d_ptr->m_boolPropertyManager->addProperty(); - underlineProp->setPropertyName(tr("Underline")); - d_ptr->m_boolPropertyManager->setValue(underlineProp, val.underline()); - d_ptr->m_propertyToUnderline[property] = underlineProp; - d_ptr->m_underlineToProperty[underlineProp] = property; - property->addSubProperty(underlineProp); - - QtProperty *strikeOutProp = d_ptr->m_boolPropertyManager->addProperty(); - strikeOutProp->setPropertyName(tr("Strikeout")); - d_ptr->m_boolPropertyManager->setValue(strikeOutProp, val.strikeOut()); - d_ptr->m_propertyToStrikeOut[property] = strikeOutProp; - d_ptr->m_strikeOutToProperty[strikeOutProp] = property; - property->addSubProperty(strikeOutProp); - - QtProperty *kerningProp = d_ptr->m_boolPropertyManager->addProperty(); - kerningProp->setPropertyName(tr("Kerning")); - d_ptr->m_boolPropertyManager->setValue(kerningProp, val.kerning()); - d_ptr->m_propertyToKerning[property] = kerningProp; - d_ptr->m_kerningToProperty[kerningProp] = property; - property->addSubProperty(kerningProp); -} - -/*! - \reimp -*/ -void QtFontPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *familyProp = d_ptr->m_propertyToFamily[property]; - if (familyProp) { - d_ptr->m_familyToProperty.remove(familyProp); - delete familyProp; - } - d_ptr->m_propertyToFamily.remove(property); - - QtProperty *pointSizeProp = d_ptr->m_propertyToPointSize[property]; - if (pointSizeProp) { - d_ptr->m_pointSizeToProperty.remove(pointSizeProp); - delete pointSizeProp; - } - d_ptr->m_propertyToPointSize.remove(property); - - QtProperty *boldProp = d_ptr->m_propertyToBold[property]; - if (boldProp) { - d_ptr->m_boldToProperty.remove(boldProp); - delete boldProp; - } - d_ptr->m_propertyToBold.remove(property); - - QtProperty *italicProp = d_ptr->m_propertyToItalic[property]; - if (italicProp) { - d_ptr->m_italicToProperty.remove(italicProp); - delete italicProp; - } - d_ptr->m_propertyToItalic.remove(property); - - QtProperty *underlineProp = d_ptr->m_propertyToUnderline[property]; - if (underlineProp) { - d_ptr->m_underlineToProperty.remove(underlineProp); - delete underlineProp; - } - d_ptr->m_propertyToUnderline.remove(property); - - QtProperty *strikeOutProp = d_ptr->m_propertyToStrikeOut[property]; - if (strikeOutProp) { - d_ptr->m_strikeOutToProperty.remove(strikeOutProp); - delete strikeOutProp; - } - d_ptr->m_propertyToStrikeOut.remove(property); - - QtProperty *kerningProp = d_ptr->m_propertyToKerning[property]; - if (kerningProp) { - d_ptr->m_kerningToProperty.remove(kerningProp); - delete kerningProp; - } - d_ptr->m_propertyToKerning.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtColorPropertyManager - -class QtColorPropertyManagerPrivate -{ - QtColorPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtColorPropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToR; - QMap m_propertyToG; - QMap m_propertyToB; - QMap m_propertyToA; - - QMap m_rToProperty; - QMap m_gToProperty; - QMap m_bToProperty; - QMap m_aToProperty; -}; - -void QtColorPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_rToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setRed(value); - q_ptr->setValue(prop, c); - } else if (QtProperty *prop = m_gToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setGreen(value); - q_ptr->setValue(prop, c); - } else if (QtProperty *prop = m_bToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setBlue(value); - q_ptr->setValue(prop, c); - } else if (QtProperty *prop = m_aToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setAlpha(value); - q_ptr->setValue(prop, c); - } -} - -void QtColorPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_rToProperty.value(property, 0)) { - m_propertyToR[pointProp] = 0; - m_rToProperty.remove(property); - } else if (QtProperty *pointProp = m_gToProperty.value(property, 0)) { - m_propertyToG[pointProp] = 0; - m_gToProperty.remove(property); - } else if (QtProperty *pointProp = m_bToProperty.value(property, 0)) { - m_propertyToB[pointProp] = 0; - m_bToProperty.remove(property); - } else if (QtProperty *pointProp = m_aToProperty.value(property, 0)) { - m_propertyToA[pointProp] = 0; - m_aToProperty.remove(property); - } -} - -/*! - \class QtColorPropertyManager - - \brief The QtColorPropertyManager provides and manages QColor properties. - - A color property has nested \e red, \e green and \e blue - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtColorPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser, QtIntPropertyManager -*/ - -/*! - \fn void QtColorPropertyManager::valueChanged(QtProperty *property, const QColor &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtColorPropertyManager::QtColorPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtColorPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtColorPropertyManager::~QtColorPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that produces the nested \e red, \e green and - \e blue subproperties. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtColorPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by \e this manager, this - function returns an invalid color. - - \sa setValue() -*/ -QColor QtColorPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QColor()); -} - -/*! - \reimp -*/ - -QString QtColorPropertyManager::valueText(const QtProperty *property) const -{ - const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return QtPropertyBrowserUtils::colorValueText(it.value()); -} - -/*! - \reimp -*/ - -QIcon QtColorPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - return QtPropertyBrowserUtils::brushValueIcon(QBrush(it.value())); -} - -/*! - \fn void QtColorPropertyManager::setValue(QtProperty *property, const QColor &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtColorPropertyManager::setValue(QtProperty *property, const QColor &val) -{ - const QtColorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToR[property], val.red()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToG[property], val.green()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToB[property], val.blue()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToA[property], val.alpha()); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtColorPropertyManager::initializeProperty(QtProperty *property) -{ - QColor val; - d_ptr->m_values[property] = val; - - QtProperty *rProp = d_ptr->m_intPropertyManager->addProperty(); - rProp->setPropertyName(tr("Red")); - d_ptr->m_intPropertyManager->setValue(rProp, val.red()); - d_ptr->m_intPropertyManager->setRange(rProp, 0, 0xFF); - d_ptr->m_propertyToR[property] = rProp; - d_ptr->m_rToProperty[rProp] = property; - property->addSubProperty(rProp); - - QtProperty *gProp = d_ptr->m_intPropertyManager->addProperty(); - gProp->setPropertyName(tr("Green")); - d_ptr->m_intPropertyManager->setValue(gProp, val.green()); - d_ptr->m_intPropertyManager->setRange(gProp, 0, 0xFF); - d_ptr->m_propertyToG[property] = gProp; - d_ptr->m_gToProperty[gProp] = property; - property->addSubProperty(gProp); - - QtProperty *bProp = d_ptr->m_intPropertyManager->addProperty(); - bProp->setPropertyName(tr("Blue")); - d_ptr->m_intPropertyManager->setValue(bProp, val.blue()); - d_ptr->m_intPropertyManager->setRange(bProp, 0, 0xFF); - d_ptr->m_propertyToB[property] = bProp; - d_ptr->m_bToProperty[bProp] = property; - property->addSubProperty(bProp); - - QtProperty *aProp = d_ptr->m_intPropertyManager->addProperty(); - aProp->setPropertyName(tr("Alpha")); - d_ptr->m_intPropertyManager->setValue(aProp, val.alpha()); - d_ptr->m_intPropertyManager->setRange(aProp, 0, 0xFF); - d_ptr->m_propertyToA[property] = aProp; - d_ptr->m_aToProperty[aProp] = property; - property->addSubProperty(aProp); -} - -/*! - \reimp -*/ -void QtColorPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *rProp = d_ptr->m_propertyToR[property]; - if (rProp) { - d_ptr->m_rToProperty.remove(rProp); - delete rProp; - } - d_ptr->m_propertyToR.remove(property); - - QtProperty *gProp = d_ptr->m_propertyToG[property]; - if (gProp) { - d_ptr->m_gToProperty.remove(gProp); - delete gProp; - } - d_ptr->m_propertyToG.remove(property); - - QtProperty *bProp = d_ptr->m_propertyToB[property]; - if (bProp) { - d_ptr->m_bToProperty.remove(bProp); - delete bProp; - } - d_ptr->m_propertyToB.remove(property); - - QtProperty *aProp = d_ptr->m_propertyToA[property]; - if (aProp) { - d_ptr->m_aToProperty.remove(aProp); - delete aProp; - } - d_ptr->m_propertyToA.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtCursorPropertyManager - -// Make sure icons are removed as soon as QApplication is destroyed, otherwise, -// handles are leaked on X11. -static void clearCursorDatabase(); -namespace { -struct CursorDatabase : public QtCursorDatabase -{ - CursorDatabase() - { - qAddPostRoutine(clearCursorDatabase); - } -}; -} -Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase) - -static void clearCursorDatabase() -{ - cursorDatabase()->clear(); -} - -class QtCursorPropertyManagerPrivate -{ - QtCursorPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtCursorPropertyManager) -public: - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtCursorPropertyManager - - \brief The QtCursorPropertyManager provides and manages QCursor properties. - - A cursor property has a current value which can be - retrieved using the value() function, and set using the setValue() - slot. In addition, QtCursorPropertyManager provides the - valueChanged() signal which is emitted whenever a property created - by this manager changes. - - \sa QtAbstractPropertyManager -*/ - -/*! - \fn void QtCursorPropertyManager::valueChanged(QtProperty *property, const QCursor &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtCursorPropertyManager::QtCursorPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtCursorPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtCursorPropertyManager::~QtCursorPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns a default QCursor object. - - \sa setValue() -*/ -#ifndef QT_NO_CURSOR -QCursor QtCursorPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QCursor()); -} -#endif - -/*! - \reimp -*/ -QString QtCursorPropertyManager::valueText(const QtProperty *property) const -{ - const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return cursorDatabase()->cursorToShapeName(it.value()); -} - -/*! - \reimp -*/ -QIcon QtCursorPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - return cursorDatabase()->cursorToShapeIcon(it.value()); -} - -/*! - \fn void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value) -{ -#ifndef QT_NO_CURSOR - const QtCursorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value().shape() == value.shape() && value.shape() != Qt::BitmapCursor) - return; - - it.value() = value; - - emit propertyChanged(property); - emit valueChanged(property, value); -#endif -} - -/*! - \reimp -*/ -void QtCursorPropertyManager::initializeProperty(QtProperty *property) -{ -#ifndef QT_NO_CURSOR - d_ptr->m_values[property] = QCursor(); -#endif -} - -/*! - \reimp -*/ -void QtCursorPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtpropertymanager.cpp" -#include "qtpropertymanager.moc" diff --git a/src/qt-solutions/qtpropertybrowser/src/qtpropertymanager.h b/src/qt-solutions/qtpropertybrowser/src/qtpropertymanager.h deleted file mode 100644 index d6b94ccf..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtpropertymanager.h +++ /dev/null @@ -1,769 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTPROPERTYMANAGER_H -#define QTPROPERTYMANAGER_H - -#include "qtpropertybrowser.h" -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QDate; -class QTime; -class QDateTime; -class QLocale; - -class QT_QTPROPERTYBROWSER_EXPORT QtGroupPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtGroupPropertyManager(QObject *parent = 0); - ~QtGroupPropertyManager(); - -protected: - virtual bool hasValue(const QtProperty *property) const; - - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -}; - -class QtIntPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtIntPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtIntPropertyManager(QObject *parent = 0); - ~QtIntPropertyManager(); - - int value(const QtProperty *property) const; - int minimum(const QtProperty *property) const; - int maximum(const QtProperty *property) const; - int singleStep(const QtProperty *property) const; - bool isReadOnly(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, int val); - void setMinimum(QtProperty *property, int minVal); - void setMaximum(QtProperty *property, int maxVal); - void setRange(QtProperty *property, int minVal, int maxVal); - void setSingleStep(QtProperty *property, int step); - void setReadOnly(QtProperty *property, bool readOnly); -Q_SIGNALS: - void valueChanged(QtProperty *property, int val); - void rangeChanged(QtProperty *property, int minVal, int maxVal); - void singleStepChanged(QtProperty *property, int step); - void readOnlyChanged(QtProperty *property, bool readOnly); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtIntPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtIntPropertyManager) - Q_DISABLE_COPY(QtIntPropertyManager) -}; - -class QtBoolPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtBoolPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtBoolPropertyManager(QObject *parent = 0); - ~QtBoolPropertyManager(); - - bool value(const QtProperty *property) const; - bool textVisible(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, bool val); - void setTextVisible(QtProperty *property, bool textVisible); -Q_SIGNALS: - void valueChanged(QtProperty *property, bool val); - void textVisibleChanged(QtProperty *property, bool); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtBoolPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtBoolPropertyManager) - Q_DISABLE_COPY(QtBoolPropertyManager) -}; - -class QtDoublePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDoublePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtDoublePropertyManager(QObject *parent = 0); - ~QtDoublePropertyManager(); - - double value(const QtProperty *property) const; - double minimum(const QtProperty *property) const; - double maximum(const QtProperty *property) const; - double singleStep(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - bool isReadOnly(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, double val); - void setMinimum(QtProperty *property, double minVal); - void setMaximum(QtProperty *property, double maxVal); - void setRange(QtProperty *property, double minVal, double maxVal); - void setSingleStep(QtProperty *property, double step); - void setDecimals(QtProperty *property, int prec); - void setReadOnly(QtProperty *property, bool readOnly); -Q_SIGNALS: - void valueChanged(QtProperty *property, double val); - void rangeChanged(QtProperty *property, double minVal, double maxVal); - void singleStepChanged(QtProperty *property, double step); - void decimalsChanged(QtProperty *property, int prec); - void readOnlyChanged(QtProperty *property, bool readOnly); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtDoublePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDoublePropertyManager) - Q_DISABLE_COPY(QtDoublePropertyManager) -}; - -class QtStringPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtStringPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtStringPropertyManager(QObject *parent = 0); - ~QtStringPropertyManager(); - - QString value(const QtProperty *property) const; - QRegExp regExp(const QtProperty *property) const; - EchoMode echoMode(const QtProperty *property) const; - bool isReadOnly(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QString &val); - void setRegExp(QtProperty *property, const QRegExp ®Exp); - void setEchoMode(QtProperty *property, EchoMode echoMode); - void setReadOnly(QtProperty *property, bool readOnly); - -Q_SIGNALS: - void valueChanged(QtProperty *property, const QString &val); - void regExpChanged(QtProperty *property, const QRegExp ®Exp); - void echoModeChanged(QtProperty *property, const int); - void readOnlyChanged(QtProperty *property, bool); - -protected: - QString valueText(const QtProperty *property) const; - QString displayText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtStringPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtStringPropertyManager) - Q_DISABLE_COPY(QtStringPropertyManager) -}; - -class QtDatePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDatePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtDatePropertyManager(QObject *parent = 0); - ~QtDatePropertyManager(); - - QDate value(const QtProperty *property) const; - QDate minimum(const QtProperty *property) const; - QDate maximum(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QDate &val); - void setMinimum(QtProperty *property, const QDate &minVal); - void setMaximum(QtProperty *property, const QDate &maxVal); - void setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QDate &val); - void rangeChanged(QtProperty *property, const QDate &minVal, const QDate &maxVal); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtDatePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDatePropertyManager) - Q_DISABLE_COPY(QtDatePropertyManager) -}; - -class QtTimePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtTimePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtTimePropertyManager(QObject *parent = 0); - ~QtTimePropertyManager(); - - QTime value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QTime &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QTime &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtTimePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtTimePropertyManager) - Q_DISABLE_COPY(QtTimePropertyManager) -}; - -class QtDateTimePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDateTimePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtDateTimePropertyManager(QObject *parent = 0); - ~QtDateTimePropertyManager(); - - QDateTime value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QDateTime &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QDateTime &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtDateTimePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDateTimePropertyManager) - Q_DISABLE_COPY(QtDateTimePropertyManager) -}; - -class QtKeySequencePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtKeySequencePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtKeySequencePropertyManager(QObject *parent = 0); - ~QtKeySequencePropertyManager(); - - QKeySequence value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QKeySequence &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QKeySequence &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtKeySequencePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtKeySequencePropertyManager) - Q_DISABLE_COPY(QtKeySequencePropertyManager) -}; - -class QtCharPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCharPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtCharPropertyManager(QObject *parent = 0); - ~QtCharPropertyManager(); - - QChar value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QChar &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QChar &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtCharPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCharPropertyManager) - Q_DISABLE_COPY(QtCharPropertyManager) -}; - -class QtEnumPropertyManager; -class QtLocalePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtLocalePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtLocalePropertyManager(QObject *parent = 0); - ~QtLocalePropertyManager(); - - QtEnumPropertyManager *subEnumPropertyManager() const; - - QLocale value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QLocale &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QLocale &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtLocalePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtLocalePropertyManager) - Q_DISABLE_COPY(QtLocalePropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtPointPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtPointPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtPointPropertyManager(QObject *parent = 0); - ~QtPointPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QPoint value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QPoint &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QPoint &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtPointPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtPointPropertyManager) - Q_DISABLE_COPY(QtPointPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtPointFPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtPointFPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtPointFPropertyManager(QObject *parent = 0); - ~QtPointFPropertyManager(); - - QtDoublePropertyManager *subDoublePropertyManager() const; - - QPointF value(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QPointF &val); - void setDecimals(QtProperty *property, int prec); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QPointF &val); - void decimalsChanged(QtProperty *property, int prec); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtPointFPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtPointFPropertyManager) - Q_DISABLE_COPY(QtPointFPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtSizePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSizePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtSizePropertyManager(QObject *parent = 0); - ~QtSizePropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QSize value(const QtProperty *property) const; - QSize minimum(const QtProperty *property) const; - QSize maximum(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QSize &val); - void setMinimum(QtProperty *property, const QSize &minVal); - void setMaximum(QtProperty *property, const QSize &maxVal); - void setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QSize &val); - void rangeChanged(QtProperty *property, const QSize &minVal, const QSize &maxVal); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtSizePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSizePropertyManager) - Q_DISABLE_COPY(QtSizePropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtSizeFPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSizeFPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtSizeFPropertyManager(QObject *parent = 0); - ~QtSizeFPropertyManager(); - - QtDoublePropertyManager *subDoublePropertyManager() const; - - QSizeF value(const QtProperty *property) const; - QSizeF minimum(const QtProperty *property) const; - QSizeF maximum(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QSizeF &val); - void setMinimum(QtProperty *property, const QSizeF &minVal); - void setMaximum(QtProperty *property, const QSizeF &maxVal); - void setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal); - void setDecimals(QtProperty *property, int prec); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QSizeF &val); - void rangeChanged(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal); - void decimalsChanged(QtProperty *property, int prec); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtSizeFPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSizeFPropertyManager) - Q_DISABLE_COPY(QtSizeFPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtRectPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtRectPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtRectPropertyManager(QObject *parent = 0); - ~QtRectPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QRect value(const QtProperty *property) const; - QRect constraint(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QRect &val); - void setConstraint(QtProperty *property, const QRect &constraint); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QRect &val); - void constraintChanged(QtProperty *property, const QRect &constraint); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtRectPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtRectPropertyManager) - Q_DISABLE_COPY(QtRectPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtRectFPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtRectFPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtRectFPropertyManager(QObject *parent = 0); - ~QtRectFPropertyManager(); - - QtDoublePropertyManager *subDoublePropertyManager() const; - - QRectF value(const QtProperty *property) const; - QRectF constraint(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QRectF &val); - void setConstraint(QtProperty *property, const QRectF &constraint); - void setDecimals(QtProperty *property, int prec); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QRectF &val); - void constraintChanged(QtProperty *property, const QRectF &constraint); - void decimalsChanged(QtProperty *property, int prec); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtRectFPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtRectFPropertyManager) - Q_DISABLE_COPY(QtRectFPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtEnumPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtEnumPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtEnumPropertyManager(QObject *parent = 0); - ~QtEnumPropertyManager(); - - int value(const QtProperty *property) const; - QStringList enumNames(const QtProperty *property) const; - QMap enumIcons(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, int val); - void setEnumNames(QtProperty *property, const QStringList &names); - void setEnumIcons(QtProperty *property, const QMap &icons); -Q_SIGNALS: - void valueChanged(QtProperty *property, int val); - void enumNamesChanged(QtProperty *property, const QStringList &names); - void enumIconsChanged(QtProperty *property, const QMap &icons); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtEnumPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtEnumPropertyManager) - Q_DISABLE_COPY(QtEnumPropertyManager) -}; - -class QtFlagPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtFlagPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtFlagPropertyManager(QObject *parent = 0); - ~QtFlagPropertyManager(); - - QtBoolPropertyManager *subBoolPropertyManager() const; - - int value(const QtProperty *property) const; - QStringList flagNames(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, int val); - void setFlagNames(QtProperty *property, const QStringList &names); -Q_SIGNALS: - void valueChanged(QtProperty *property, int val); - void flagNamesChanged(QtProperty *property, const QStringList &names); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtFlagPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtFlagPropertyManager) - Q_DISABLE_COPY(QtFlagPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtSizePolicyPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSizePolicyPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtSizePolicyPropertyManager(QObject *parent = 0); - ~QtSizePolicyPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - QtEnumPropertyManager *subEnumPropertyManager() const; - - QSizePolicy value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QSizePolicy &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QSizePolicy &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtSizePolicyPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSizePolicyPropertyManager) - Q_DISABLE_COPY(QtSizePolicyPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtFontPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtFontPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtFontPropertyManager(QObject *parent = 0); - ~QtFontPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - QtEnumPropertyManager *subEnumPropertyManager() const; - QtBoolPropertyManager *subBoolPropertyManager() const; - - QFont value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QFont &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QFont &val); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtFontPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtFontPropertyManager) - Q_DISABLE_COPY(QtFontPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseChanged()) - Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseDelayedChange()) -}; - -class QtColorPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtColorPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtColorPropertyManager(QObject *parent = 0); - ~QtColorPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QColor value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QColor &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QColor &val); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtColorPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtColorPropertyManager) - Q_DISABLE_COPY(QtColorPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtCursorPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCursorPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtCursorPropertyManager(QObject *parent = 0); - ~QtCursorPropertyManager(); - -#ifndef QT_NO_CURSOR - QCursor value(const QtProperty *property) const; -#endif - -public Q_SLOTS: - void setValue(QtProperty *property, const QCursor &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QCursor &val); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtCursorPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCursorPropertyManager) - Q_DISABLE_COPY(QtCursorPropertyManager) -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qttreepropertybrowser.cpp b/src/qt-solutions/qtpropertybrowser/src/qttreepropertybrowser.cpp deleted file mode 100644 index 97818e1c..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qttreepropertybrowser.cpp +++ /dev/null @@ -1,1079 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qttreepropertybrowser.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtPropertyEditorView; - -class QtTreePropertyBrowserPrivate -{ - QtTreePropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtTreePropertyBrowser) - -public: - QtTreePropertyBrowserPrivate(); - void init(QWidget *parent); - - void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); - void propertyRemoved(QtBrowserItem *index); - void propertyChanged(QtBrowserItem *index); - QWidget *createEditor(QtProperty *property, QWidget *parent) const - { return q_ptr->createEditor(property, parent); } - QtProperty *indexToProperty(const QModelIndex &index) const; - QTreeWidgetItem *indexToItem(const QModelIndex &index) const; - QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const; - bool lastColumn(int column) const; - void disableItem(QTreeWidgetItem *item) const; - void enableItem(QTreeWidgetItem *item) const; - bool hasValue(QTreeWidgetItem *item) const; - - void slotCollapsed(const QModelIndex &index); - void slotExpanded(const QModelIndex &index); - - QColor calculatedBackgroundColor(QtBrowserItem *item) const; - - QtPropertyEditorView *treeWidget() const { return m_treeWidget; } - bool markPropertiesWithoutValue() const { return m_markPropertiesWithoutValue; } - - QtBrowserItem *currentItem() const; - void setCurrentItem(QtBrowserItem *browserItem, bool block); - void editItem(QtBrowserItem *browserItem); - - void slotCurrentBrowserItemChanged(QtBrowserItem *item); - void slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *); - - QTreeWidgetItem *editedItem() const; - -private: - void updateItem(QTreeWidgetItem *item); - - QMap m_indexToItem; - QMap m_itemToIndex; - - QMap m_indexToBackgroundColor; - - QtPropertyEditorView *m_treeWidget; - - bool m_headerVisible; - QtTreePropertyBrowser::ResizeMode m_resizeMode; - class QtPropertyEditorDelegate *m_delegate; - bool m_markPropertiesWithoutValue; - bool m_browserChangedBlocked; - QIcon m_expandIcon; -}; - -// ------------ QtPropertyEditorView -class QtPropertyEditorView : public QTreeWidget -{ - Q_OBJECT -public: - QtPropertyEditorView(QWidget *parent = 0); - - void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate) - { m_editorPrivate = editorPrivate; } - - QTreeWidgetItem *indexToItem(const QModelIndex &index) const - { return itemFromIndex(index); } - -protected: - void keyPressEvent(QKeyEvent *event); - void mousePressEvent(QMouseEvent *event); - void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; - -private: - QtTreePropertyBrowserPrivate *m_editorPrivate; -}; - -QtPropertyEditorView::QtPropertyEditorView(QWidget *parent) : - QTreeWidget(parent), - m_editorPrivate(0) -{ - connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int))); -} - -void QtPropertyEditorView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - QStyleOptionViewItemV3 opt = option; - bool hasValue = true; - if (m_editorPrivate) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - if (property) - hasValue = property->hasValue(); - } - if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) { - const QColor c = option.palette.color(QPalette::Dark); - painter->fillRect(option.rect, c); - opt.palette.setColor(QPalette::AlternateBase, c); - } else { - const QColor c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index)); - if (c.isValid()) { - painter->fillRect(option.rect, c); - opt.palette.setColor(QPalette::AlternateBase, c.lighter(112)); - } - } - QTreeWidget::drawRow(painter, opt, index); - QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); - painter->save(); - painter->setPen(QPen(color)); - painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); - painter->restore(); -} - -void QtPropertyEditorView::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Space: // Trigger Edit - if (!m_editorPrivate->editedItem()) - if (const QTreeWidgetItem *item = currentItem()) - if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) { - event->accept(); - // If the current position is at column 0, move to 1. - QModelIndex index = currentIndex(); - if (index.column() == 0) { - index = index.sibling(index.row(), 1); - setCurrentIndex(index); - } - edit(index); - return; - } - break; - default: - break; - } - QTreeWidget::keyPressEvent(event); -} - -void QtPropertyEditorView::mousePressEvent(QMouseEvent *event) -{ - QTreeWidget::mousePressEvent(event); - QTreeWidgetItem *item = itemAt(event->pos()); - - if (item) { - if ((item != m_editorPrivate->editedItem()) && (event->button() == Qt::LeftButton) - && (header()->logicalIndexAt(event->pos().x()) == 1) - && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) { - editItem(item, 1); - } else if (!m_editorPrivate->hasValue(item) && m_editorPrivate->markPropertiesWithoutValue() && !rootIsDecorated()) { - if (event->pos().x() + header()->offset() < 20) - item->setExpanded(!item->isExpanded()); - } - } -} - -// ------------ QtPropertyEditorDelegate -class QtPropertyEditorDelegate : public QItemDelegate -{ - Q_OBJECT -public: - QtPropertyEditorDelegate(QObject *parent = 0) - : QItemDelegate(parent), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0), m_disablePainting(false) - {} - - void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate) - { m_editorPrivate = editorPrivate; } - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; - - void setModelData(QWidget *, QAbstractItemModel *, - const QModelIndex &) const {} - - void setEditorData(QWidget *, const QModelIndex &) const {} - - bool eventFilter(QObject *object, QEvent *event); - void closeEditor(QtProperty *property); - - QTreeWidgetItem *editedItem() const { return m_editedItem; } - -protected: - - void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QPixmap &pixmap) const; - void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QString &text) const; - -private slots: - void slotEditorDestroyed(QObject *object); - -private: - int indentation(const QModelIndex &index) const; - - typedef QMap EditorToPropertyMap; - mutable EditorToPropertyMap m_editorToProperty; - - typedef QMap PropertyToEditorMap; - mutable PropertyToEditorMap m_propertyToEditor; - QtTreePropertyBrowserPrivate *m_editorPrivate; - mutable QTreeWidgetItem *m_editedItem; - mutable QWidget *m_editedWidget; - mutable bool m_disablePainting; -}; - -int QtPropertyEditorDelegate::indentation(const QModelIndex &index) const -{ - if (!m_editorPrivate) - return 0; - - QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); - int indent = 0; - while (item->parent()) { - item = item->parent(); - ++indent; - } - if (m_editorPrivate->treeWidget()->rootIsDecorated()) - ++indent; - return indent * m_editorPrivate->treeWidget()->indentation(); -} - -void QtPropertyEditorDelegate::slotEditorDestroyed(QObject *object) -{ - if (QWidget *w = qobject_cast(object)) { - const EditorToPropertyMap::iterator it = m_editorToProperty.find(w); - if (it != m_editorToProperty.end()) { - m_propertyToEditor.remove(it.value()); - m_editorToProperty.erase(it); - } - if (m_editedWidget == w) { - m_editedWidget = 0; - m_editedItem = 0; - } - } -} - -void QtPropertyEditorDelegate::closeEditor(QtProperty *property) -{ - if (QWidget *w = m_propertyToEditor.value(property, 0)) - w->deleteLater(); -} - -QWidget *QtPropertyEditorDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &, const QModelIndex &index) const -{ - if (index.column() == 1 && m_editorPrivate) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); - if (property && item && (item->flags() & Qt::ItemIsEnabled)) { - QWidget *editor = m_editorPrivate->createEditor(property, parent); - if (editor) { - editor->setAutoFillBackground(true); - editor->installEventFilter(const_cast(this)); - connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); - m_propertyToEditor[property] = editor; - m_editorToProperty[editor] = property; - m_editedItem = item; - m_editedWidget = editor; - } - return editor; - } - } - return 0; -} - -void QtPropertyEditorDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - Q_UNUSED(index) - editor->setGeometry(option.rect.adjusted(0, 0, 0, -1)); -} - -void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - bool hasValue = true; - if (m_editorPrivate) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - if (property) - hasValue = property->hasValue(); - } - QStyleOptionViewItemV3 opt = option; - if ((m_editorPrivate && index.column() == 0) || !hasValue) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - if (property && property->isModified()) { - opt.font.setBold(true); - opt.fontMetrics = QFontMetrics(opt.font); - } - } - QColor c; - if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) { - c = opt.palette.color(QPalette::Dark); - opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText)); - } else { - c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index)); - if (c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate)) - c = c.lighter(112); - } - if (c.isValid()) - painter->fillRect(option.rect, c); - opt.state &= ~QStyle::State_HasFocus; - if (index.column() == 1) { - QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); - if (m_editedItem && m_editedItem == item) - m_disablePainting = true; - } - QItemDelegate::paint(painter, opt, index); - if (option.type) - m_disablePainting = false; - - opt.palette.setCurrentColorGroup(QPalette::Active); - QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); - painter->save(); - painter->setPen(QPen(color)); - if (!m_editorPrivate || (!m_editorPrivate->lastColumn(index.column()) && hasValue)) { - int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left(); - painter->drawLine(right, option.rect.y(), right, option.rect.bottom()); - } - painter->restore(); -} - -void QtPropertyEditorDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QPixmap &pixmap) const -{ - if (m_disablePainting) - return; - - QItemDelegate::drawDecoration(painter, option, rect, pixmap); -} - -void QtPropertyEditorDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QString &text) const -{ - if (m_disablePainting) - return; - - QItemDelegate::drawDisplay(painter, option, rect, text); -} - -QSize QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - return QItemDelegate::sizeHint(option, index) + QSize(3, 4); -} - -bool QtPropertyEditorDelegate::eventFilter(QObject *object, QEvent *event) -{ - if (event->type() == QEvent::FocusOut) { - QFocusEvent *fe = static_cast(event); - if (fe->reason() == Qt::ActiveWindowFocusReason) - return false; - } - return QItemDelegate::eventFilter(object, event); -} - -// -------- QtTreePropertyBrowserPrivate implementation -QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() : - m_treeWidget(0), - m_headerVisible(true), - m_resizeMode(QtTreePropertyBrowser::Stretch), - m_delegate(0), - m_markPropertiesWithoutValue(false), - m_browserChangedBlocked(false) -{ -} - -// Draw an icon indicating opened/closing branches -static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style) -{ - QPixmap pix(14, 14); - pix.fill(Qt::transparent); - QStyleOption branchOption; - QRect r(QPoint(0, 0), pix.size()); - branchOption.rect = QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp - branchOption.palette = palette; - branchOption.state = QStyle::State_Children; - - QPainter p; - // Draw closed state - p.begin(&pix); - style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); - p.end(); - QIcon rc = pix; - rc.addPixmap(pix, QIcon::Selected, QIcon::Off); - // Draw opened state - branchOption.state |= QStyle::State_Open; - pix.fill(Qt::transparent); - p.begin(&pix); - style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); - p.end(); - - rc.addPixmap(pix, QIcon::Normal, QIcon::On); - rc.addPixmap(pix, QIcon::Selected, QIcon::On); - return rc; -} - -void QtTreePropertyBrowserPrivate::init(QWidget *parent) -{ - QHBoxLayout *layout = new QHBoxLayout(parent); - layout->setMargin(0); - m_treeWidget = new QtPropertyEditorView(parent); - m_treeWidget->setEditorPrivate(this); - m_treeWidget->setIconSize(QSize(18, 18)); - layout->addWidget(m_treeWidget); - parent->setFocusProxy(m_treeWidget); - - m_treeWidget->setColumnCount(2); - QStringList labels; - labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Property")); - labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Value")); - m_treeWidget->setHeaderLabels(labels); - m_treeWidget->setAlternatingRowColors(true); - m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed); - m_delegate = new QtPropertyEditorDelegate(parent); - m_delegate->setEditorPrivate(this); - m_treeWidget->setItemDelegate(m_delegate); - m_treeWidget->header()->setMovable(false); - m_treeWidget->header()->setResizeMode(QHeaderView::Stretch); - - m_expandIcon = drawIndicatorIcon(q_ptr->palette(), q_ptr->style()); - - QObject::connect(m_treeWidget, SIGNAL(collapsed(const QModelIndex &)), q_ptr, SLOT(slotCollapsed(const QModelIndex &))); - QObject::connect(m_treeWidget, SIGNAL(expanded(const QModelIndex &)), q_ptr, SLOT(slotExpanded(const QModelIndex &))); - QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), q_ptr, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); -} - -QtBrowserItem *QtTreePropertyBrowserPrivate::currentItem() const -{ - if (QTreeWidgetItem *treeItem = m_treeWidget->currentItem()) - return m_itemToIndex.value(treeItem); - return 0; -} - -void QtTreePropertyBrowserPrivate::setCurrentItem(QtBrowserItem *browserItem, bool block) -{ - const bool blocked = block ? m_treeWidget->blockSignals(true) : false; - if (browserItem == 0) - m_treeWidget->setCurrentItem(0); - else - m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem)); - if (block) - m_treeWidget->blockSignals(blocked); -} - -QtProperty *QtTreePropertyBrowserPrivate::indexToProperty(const QModelIndex &index) const -{ - QTreeWidgetItem *item = m_treeWidget->indexToItem(index); - QtBrowserItem *idx = m_itemToIndex.value(item); - if (idx) - return idx->property(); - return 0; -} - -QtBrowserItem *QtTreePropertyBrowserPrivate::indexToBrowserItem(const QModelIndex &index) const -{ - QTreeWidgetItem *item = m_treeWidget->indexToItem(index); - return m_itemToIndex.value(item); -} - -QTreeWidgetItem *QtTreePropertyBrowserPrivate::indexToItem(const QModelIndex &index) const -{ - return m_treeWidget->indexToItem(index); -} - -bool QtTreePropertyBrowserPrivate::lastColumn(int column) const -{ - return m_treeWidget->header()->visualIndex(column) == m_treeWidget->columnCount() - 1; -} - -void QtTreePropertyBrowserPrivate::disableItem(QTreeWidgetItem *item) const -{ - Qt::ItemFlags flags = item->flags(); - if (flags & Qt::ItemIsEnabled) { - flags &= ~Qt::ItemIsEnabled; - item->setFlags(flags); - m_delegate->closeEditor(m_itemToIndex[item]->property()); - const int childCount = item->childCount(); - for (int i = 0; i < childCount; i++) { - QTreeWidgetItem *child = item->child(i); - disableItem(child); - } - } -} - -void QtTreePropertyBrowserPrivate::enableItem(QTreeWidgetItem *item) const -{ - Qt::ItemFlags flags = item->flags(); - flags |= Qt::ItemIsEnabled; - item->setFlags(flags); - const int childCount = item->childCount(); - for (int i = 0; i < childCount; i++) { - QTreeWidgetItem *child = item->child(i); - QtProperty *property = m_itemToIndex[child]->property(); - if (property->isEnabled()) { - enableItem(child); - } - } -} - -bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem *item) const -{ - QtBrowserItem *browserItem = m_itemToIndex.value(item); - if (browserItem) - return browserItem->property()->hasValue(); - return false; -} - -void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) -{ - QTreeWidgetItem *afterItem = m_indexToItem.value(afterIndex); - QTreeWidgetItem *parentItem = m_indexToItem.value(index->parent()); - - QTreeWidgetItem *newItem = 0; - if (parentItem) { - newItem = new QTreeWidgetItem(parentItem, afterItem); - } else { - newItem = new QTreeWidgetItem(m_treeWidget, afterItem); - } - m_itemToIndex[newItem] = index; - m_indexToItem[index] = newItem; - - newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); - m_treeWidget->setItemExpanded(newItem, true); - - updateItem(newItem); -} - -void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) -{ - QTreeWidgetItem *item = m_indexToItem.value(index); - - if (m_treeWidget->currentItem() == item) { - m_treeWidget->setCurrentItem(0); - } - - delete item; - - m_indexToItem.remove(index); - m_itemToIndex.remove(item); - m_indexToBackgroundColor.remove(index); -} - -void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) -{ - QTreeWidgetItem *item = m_indexToItem.value(index); - - updateItem(item); -} - -void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item) -{ - QtProperty *property = m_itemToIndex[item]->property(); - QIcon expandIcon; - if (property->hasValue()) { - QString toolTip = property->toolTip(); - if (toolTip.isEmpty()) - toolTip = property->displayText(); - item->setToolTip(1, toolTip); - item->setIcon(1, property->valueIcon()); - property->displayText().isEmpty() ? item->setText(1, property->valueText()) : item->setText(1, property->displayText()); - } else if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) { - expandIcon = m_expandIcon; - } - item->setIcon(0, expandIcon); - item->setFirstColumnSpanned(!property->hasValue()); - item->setToolTip(0, property->propertyName()); - item->setStatusTip(0, property->statusTip()); - item->setWhatsThis(0, property->whatsThis()); - item->setText(0, property->propertyName()); - bool wasEnabled = item->flags() & Qt::ItemIsEnabled; - bool isEnabled = wasEnabled; - if (property->isEnabled()) { - QTreeWidgetItem *parent = item->parent(); - if (!parent || (parent->flags() & Qt::ItemIsEnabled)) - isEnabled = true; - else - isEnabled = false; - } else { - isEnabled = false; - } - if (wasEnabled != isEnabled) { - if (isEnabled) - enableItem(item); - else - disableItem(item); - } - m_treeWidget->viewport()->update(); -} - -QColor QtTreePropertyBrowserPrivate::calculatedBackgroundColor(QtBrowserItem *item) const -{ - QtBrowserItem *i = item; - const QMap::const_iterator itEnd = m_indexToBackgroundColor.constEnd(); - while (i) { - QMap::const_iterator it = m_indexToBackgroundColor.constFind(i); - if (it != itEnd) - return it.value(); - i = i->parent(); - } - return QColor(); -} - -void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex &index) -{ - QTreeWidgetItem *item = indexToItem(index); - QtBrowserItem *idx = m_itemToIndex.value(item); - if (item) - emit q_ptr->collapsed(idx); -} - -void QtTreePropertyBrowserPrivate::slotExpanded(const QModelIndex &index) -{ - QTreeWidgetItem *item = indexToItem(index); - QtBrowserItem *idx = m_itemToIndex.value(item); - if (item) - emit q_ptr->expanded(idx); -} - -void QtTreePropertyBrowserPrivate::slotCurrentBrowserItemChanged(QtBrowserItem *item) -{ - if (!m_browserChangedBlocked && item != currentItem()) - setCurrentItem(item, true); -} - -void QtTreePropertyBrowserPrivate::slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *) -{ - QtBrowserItem *browserItem = newItem ? m_itemToIndex.value(newItem) : 0; - m_browserChangedBlocked = true; - q_ptr->setCurrentItem(browserItem); - m_browserChangedBlocked = false; -} - -QTreeWidgetItem *QtTreePropertyBrowserPrivate::editedItem() const -{ - return m_delegate->editedItem(); -} - -void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem *browserItem) -{ - if (QTreeWidgetItem *treeItem = m_indexToItem.value(browserItem, 0)) { - m_treeWidget->setCurrentItem (treeItem, 1); - m_treeWidget->editItem(treeItem, 1); - } -} - -/*! - \class QtTreePropertyBrowser - - \brief The QtTreePropertyBrowser class provides QTreeWidget based - property browser. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - QtTreePropertyBrowser provides a tree based view for all nested - properties, i.e. properties that have subproperties can be in an - expanded (subproperties are visible) or collapsed (subproperties - are hidden) state. For example: - - \image qttreepropertybrowser.png - - Use the QtAbstractPropertyBrowser API to add, insert and remove - properties from an instance of the QtTreePropertyBrowser class. - The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. - - \sa QtGroupBoxPropertyBrowser, QtAbstractPropertyBrowser -*/ - -/*! - \fn void QtTreePropertyBrowser::collapsed(QtBrowserItem *item) - - This signal is emitted when the \a item is collapsed. - - \sa expanded(), setExpanded() -*/ - -/*! - \fn void QtTreePropertyBrowser::expanded(QtBrowserItem *item) - - This signal is emitted when the \a item is expanded. - - \sa collapsed(), setExpanded() -*/ - -/*! - Creates a property browser with the given \a parent. -*/ -QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent) - : QtAbstractPropertyBrowser(parent) -{ - d_ptr = new QtTreePropertyBrowserPrivate; - d_ptr->q_ptr = this; - - d_ptr->init(this); - connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*))); -} - -/*! - Destroys this property browser. - - Note that the properties that were inserted into this browser are - \e not destroyed since they may still be used in other - browsers. The properties are owned by the manager that created - them. - - \sa QtProperty, QtAbstractPropertyManager -*/ -QtTreePropertyBrowser::~QtTreePropertyBrowser() -{ - delete d_ptr; -} - -/*! - \property QtTreePropertyBrowser::indentation - \brief indentation of the items in the tree view. -*/ -int QtTreePropertyBrowser::indentation() const -{ - return d_ptr->m_treeWidget->indentation(); -} - -void QtTreePropertyBrowser::setIndentation(int i) -{ - d_ptr->m_treeWidget->setIndentation(i); -} - -/*! - \property QtTreePropertyBrowser::rootIsDecorated - \brief whether to show controls for expanding and collapsing root items. -*/ -bool QtTreePropertyBrowser::rootIsDecorated() const -{ - return d_ptr->m_treeWidget->rootIsDecorated(); -} - -void QtTreePropertyBrowser::setRootIsDecorated(bool show) -{ - d_ptr->m_treeWidget->setRootIsDecorated(show); - QMapIterator it(d_ptr->m_itemToIndex); - while (it.hasNext()) { - QtProperty *property = it.next().value()->property(); - if (!property->hasValue()) - d_ptr->updateItem(it.key()); - } -} - -/*! - \property QtTreePropertyBrowser::alternatingRowColors - \brief whether to draw the background using alternating colors. - By default this property is set to true. -*/ -bool QtTreePropertyBrowser::alternatingRowColors() const -{ - return d_ptr->m_treeWidget->alternatingRowColors(); -} - -void QtTreePropertyBrowser::setAlternatingRowColors(bool enable) -{ - d_ptr->m_treeWidget->setAlternatingRowColors(enable); - QMapIterator it(d_ptr->m_itemToIndex); -} - -/*! - \property QtTreePropertyBrowser::headerVisible - \brief whether to show the header. -*/ -bool QtTreePropertyBrowser::isHeaderVisible() const -{ - return d_ptr->m_headerVisible; -} - -void QtTreePropertyBrowser::setHeaderVisible(bool visible) -{ - if (d_ptr->m_headerVisible == visible) - return; - - d_ptr->m_headerVisible = visible; - d_ptr->m_treeWidget->header()->setVisible(visible); -} - -/*! - \enum QtTreePropertyBrowser::ResizeMode - - The resize mode specifies the behavior of the header sections. - - \value Interactive The user can resize the sections. - The sections can also be resized programmatically using setSplitterPosition(). - - \value Fixed The user cannot resize the section. - The section can only be resized programmatically using setSplitterPosition(). - - \value Stretch QHeaderView will automatically resize the section to fill the available space. - The size cannot be changed by the user or programmatically. - - \value ResizeToContents QHeaderView will automatically resize the section to its optimal - size based on the contents of the entire column. - The size cannot be changed by the user or programmatically. - - \sa setResizeMode() -*/ - -/*! - \property QtTreePropertyBrowser::resizeMode - \brief the resize mode of setions in the header. -*/ - -QtTreePropertyBrowser::ResizeMode QtTreePropertyBrowser::resizeMode() const -{ - return d_ptr->m_resizeMode; -} - -void QtTreePropertyBrowser::setResizeMode(QtTreePropertyBrowser::ResizeMode mode) -{ - if (d_ptr->m_resizeMode == mode) - return; - - d_ptr->m_resizeMode = mode; - QHeaderView::ResizeMode m = QHeaderView::Stretch; - switch (mode) { - case QtTreePropertyBrowser::Interactive: m = QHeaderView::Interactive; break; - case QtTreePropertyBrowser::Fixed: m = QHeaderView::Fixed; break; - case QtTreePropertyBrowser::ResizeToContents: m = QHeaderView::ResizeToContents; break; - case QtTreePropertyBrowser::Stretch: - default: m = QHeaderView::Stretch; break; - } - d_ptr->m_treeWidget->header()->setResizeMode(m); -} - -/*! - \property QtTreePropertyBrowser::splitterPosition - \brief the position of the splitter between the colunms. -*/ - -int QtTreePropertyBrowser::splitterPosition() const -{ - return d_ptr->m_treeWidget->header()->sectionSize(0); -} - -void QtTreePropertyBrowser::setSplitterPosition(int position) -{ - d_ptr->m_treeWidget->header()->resizeSection(0, position); -} - -/*! - Sets the \a item to either collapse or expanded, depending on the value of \a expanded. - - \sa isExpanded(), expanded(), collapsed() -*/ - -void QtTreePropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded) -{ - QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item); - if (treeItem) - treeItem->setExpanded(expanded); -} - -/*! - Returns true if the \a item is expanded; otherwise returns false. - - \sa setExpanded() -*/ - -bool QtTreePropertyBrowser::isExpanded(QtBrowserItem *item) const -{ - QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item); - if (treeItem) - return treeItem->isExpanded(); - return false; -} - -/*! - Returns true if the \a item is visible; otherwise returns false. - - \sa setItemVisible() - \since 4.5 -*/ - -bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem *item) const -{ - if (const QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item)) - return !treeItem->isHidden(); - return false; -} - -/*! - Sets the \a item to be visible, depending on the value of \a visible. - - \sa isItemVisible() - \since 4.5 -*/ - -void QtTreePropertyBrowser::setItemVisible(QtBrowserItem *item, bool visible) -{ - if (QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item)) - treeItem->setHidden(!visible); -} - -/*! - Sets the \a item's background color to \a color. Note that while item's background - is rendered every second row is being drawn with alternate color (which is a bit lighter than items \a color) - - \sa backgroundColor(), calculatedBackgroundColor() -*/ - -void QtTreePropertyBrowser::setBackgroundColor(QtBrowserItem *item, const QColor &color) -{ - if (!d_ptr->m_indexToItem.contains(item)) - return; - if (color.isValid()) - d_ptr->m_indexToBackgroundColor[item] = color; - else - d_ptr->m_indexToBackgroundColor.remove(item); - d_ptr->m_treeWidget->viewport()->update(); -} - -/*! - Returns the \a item's color. If there is no color set for item it returns invalid color. - - \sa calculatedBackgroundColor(), setBackgroundColor() -*/ - -QColor QtTreePropertyBrowser::backgroundColor(QtBrowserItem *item) const -{ - return d_ptr->m_indexToBackgroundColor.value(item); -} - -/*! - Returns the \a item's color. If there is no color set for item it returns parent \a item's - color (if there is no color set for parent it returns grandparent's color and so on). In case - the color is not set for \a item and it's top level item it returns invalid color. - - \sa backgroundColor(), setBackgroundColor() -*/ - -QColor QtTreePropertyBrowser::calculatedBackgroundColor(QtBrowserItem *item) const -{ - return d_ptr->calculatedBackgroundColor(item); -} - -/*! - \property QtTreePropertyBrowser::propertiesWithoutValueMarked - \brief whether to enable or disable marking properties without value. - - When marking is enabled the item's background is rendered in dark color and item's - foreground is rendered with light color. - - \sa propertiesWithoutValueMarked() -*/ -void QtTreePropertyBrowser::setPropertiesWithoutValueMarked(bool mark) -{ - if (d_ptr->m_markPropertiesWithoutValue == mark) - return; - - d_ptr->m_markPropertiesWithoutValue = mark; - QMapIterator it(d_ptr->m_itemToIndex); - while (it.hasNext()) { - QtProperty *property = it.next().value()->property(); - if (!property->hasValue()) - d_ptr->updateItem(it.key()); - } - d_ptr->m_treeWidget->viewport()->update(); -} - -bool QtTreePropertyBrowser::propertiesWithoutValueMarked() const -{ - return d_ptr->m_markPropertiesWithoutValue; -} - -/*! - \reimp -*/ -void QtTreePropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) -{ - d_ptr->propertyInserted(item, afterItem); -} - -/*! - \reimp -*/ -void QtTreePropertyBrowser::itemRemoved(QtBrowserItem *item) -{ - d_ptr->propertyRemoved(item); -} - -/*! - \reimp -*/ -void QtTreePropertyBrowser::itemChanged(QtBrowserItem *item) -{ - d_ptr->propertyChanged(item); -} - -/*! - Sets the current item to \a item and opens the relevant editor for it. -*/ -void QtTreePropertyBrowser::editItem(QtBrowserItem *item) -{ - d_ptr->editItem(item); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qttreepropertybrowser.cpp" -#include "qttreepropertybrowser.moc" diff --git a/src/qt-solutions/qtpropertybrowser/src/qttreepropertybrowser.h b/src/qt-solutions/qtpropertybrowser/src/qttreepropertybrowser.h deleted file mode 100644 index 7a3057f7..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qttreepropertybrowser.h +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTTREEPROPERTYBROWSER_H -#define QTTREEPROPERTYBROWSER_H - -#include "qtpropertybrowser.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QTreeWidgetItem; -class QtTreePropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtTreePropertyBrowser : public QtAbstractPropertyBrowser -{ - Q_OBJECT - Q_ENUMS(ResizeMode) - Q_PROPERTY(int indentation READ indentation WRITE setIndentation) - Q_PROPERTY(bool rootIsDecorated READ rootIsDecorated WRITE setRootIsDecorated) - Q_PROPERTY(bool alternatingRowColors READ alternatingRowColors WRITE setAlternatingRowColors) - Q_PROPERTY(bool headerVisible READ isHeaderVisible WRITE setHeaderVisible) - Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode) - Q_PROPERTY(int splitterPosition READ splitterPosition WRITE setSplitterPosition) - Q_PROPERTY(bool propertiesWithoutValueMarked READ propertiesWithoutValueMarked WRITE setPropertiesWithoutValueMarked) -public: - - enum ResizeMode - { - Interactive, - Stretch, - Fixed, - ResizeToContents - }; - - QtTreePropertyBrowser(QWidget *parent = 0); - ~QtTreePropertyBrowser(); - - int indentation() const; - void setIndentation(int i); - - bool rootIsDecorated() const; - void setRootIsDecorated(bool show); - - bool alternatingRowColors() const; - void setAlternatingRowColors(bool enable); - - bool isHeaderVisible() const; - void setHeaderVisible(bool visible); - - ResizeMode resizeMode() const; - void setResizeMode(ResizeMode mode); - - int splitterPosition() const; - void setSplitterPosition(int position); - - void setExpanded(QtBrowserItem *item, bool expanded); - bool isExpanded(QtBrowserItem *item) const; - - bool isItemVisible(QtBrowserItem *item) const; - void setItemVisible(QtBrowserItem *item, bool visible); - - void setBackgroundColor(QtBrowserItem *item, const QColor &color); - QColor backgroundColor(QtBrowserItem *item) const; - QColor calculatedBackgroundColor(QtBrowserItem *item) const; - - void setPropertiesWithoutValueMarked(bool mark); - bool propertiesWithoutValueMarked() const; - - void editItem(QtBrowserItem *item); - -Q_SIGNALS: - - void collapsed(QtBrowserItem *item); - void expanded(QtBrowserItem *item); - -protected: - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); - virtual void itemRemoved(QtBrowserItem *item); - virtual void itemChanged(QtBrowserItem *item); - -private: - - QtTreePropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtTreePropertyBrowser) - Q_DISABLE_COPY(QtTreePropertyBrowser) - - Q_PRIVATE_SLOT(d_func(), void slotCollapsed(const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void slotExpanded(const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void slotCurrentBrowserItemChanged(QtBrowserItem *)) - Q_PRIVATE_SLOT(d_func(), void slotCurrentTreeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qt-solutions/qtpropertybrowser/src/qtvariantproperty.cpp b/src/qt-solutions/qtpropertybrowser/src/qtvariantproperty.cpp deleted file mode 100644 index d7fe1119..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtvariantproperty.cpp +++ /dev/null @@ -1,2362 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtvariantproperty.h" -#include "qtpropertymanager.h" -#include "qteditorfactory.h" -#include -#include -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtEnumPropertyType -{ -}; - - -class QtFlagPropertyType -{ -}; - - -class QtGroupPropertyType -{ -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -Q_DECLARE_METATYPE(QtEnumPropertyType) -Q_DECLARE_METATYPE(QtFlagPropertyType) -Q_DECLARE_METATYPE(QtGroupPropertyType) - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -/*! - Returns the type id for an enum property. - - Note that the property's value type can be retrieved using the - valueType() function (which is QVariant::Int for the enum property - type). - - \sa propertyType(), valueType() -*/ -int QtVariantPropertyManager::enumTypeId() -{ - return qMetaTypeId(); -} - -/*! - Returns the type id for a flag property. - - Note that the property's value type can be retrieved using the - valueType() function (which is QVariant::Int for the flag property - type). - - \sa propertyType(), valueType() -*/ -int QtVariantPropertyManager::flagTypeId() -{ - return qMetaTypeId(); -} - -/*! - Returns the type id for a group property. - - Note that the property's value type can be retrieved using the - valueType() function (which is QVariant::Invalid for the group - property type, since it doesn't provide any value). - - \sa propertyType(), valueType() -*/ -int QtVariantPropertyManager::groupTypeId() -{ - return qMetaTypeId(); -} - -/*! - Returns the type id for a icon map attribute. - - Note that the property's attribute type can be retrieved using the - attributeType() function. - - \sa attributeType(), QtEnumPropertyManager::enumIcons() -*/ -int QtVariantPropertyManager::iconMapTypeId() -{ - return qMetaTypeId(); -} - -typedef QMap PropertyMap; -Q_GLOBAL_STATIC(PropertyMap, propertyToWrappedProperty) - -static QtProperty *wrappedProperty(QtProperty *property) -{ - return propertyToWrappedProperty()->value(property, 0); -} - -class QtVariantPropertyPrivate -{ - QtVariantProperty *q_ptr; -public: - QtVariantPropertyPrivate(QtVariantPropertyManager *m) : manager(m) {} - - QtVariantPropertyManager *manager; -}; - -/*! - \class QtVariantProperty - - \brief The QtVariantProperty class is a convenience class handling - QVariant based properties. - - QtVariantProperty provides additional API: A property's type, - value type, attribute values and current value can easily be - retrieved using the propertyType(), valueType(), attributeValue() - and value() functions respectively. In addition, the attribute - values and the current value can be set using the corresponding - setValue() and setAttribute() functions. - - For example, instead of writing: - - \code - QtVariantPropertyManager *variantPropertyManager; - QtProperty *property; - - variantPropertyManager->setValue(property, 10); - \endcode - - you can write: - - \code - QtVariantPropertyManager *variantPropertyManager; - QtVariantProperty *property; - - property->setValue(10); - \endcode - - QtVariantProperty instances can only be created by the - QtVariantPropertyManager class. - - \sa QtProperty, QtVariantPropertyManager, QtVariantEditorFactory -*/ - -/*! - Creates a variant property using the given \a manager. - - Do not use this constructor to create variant property instances; - use the QtVariantPropertyManager::addProperty() function - instead. This constructor is used internally by the - QtVariantPropertyManager::createProperty() function. - - \sa QtVariantPropertyManager -*/ -QtVariantProperty::QtVariantProperty(QtVariantPropertyManager *manager) - : QtProperty(manager), d_ptr(new QtVariantPropertyPrivate(manager)) -{ - -} - -/*! - Destroys this property. - - \sa QtProperty::~QtProperty() -*/ -QtVariantProperty::~QtVariantProperty() -{ - delete d_ptr; -} - -/*! - Returns the property's current value. - - \sa valueType(), setValue() -*/ -QVariant QtVariantProperty::value() const -{ - return d_ptr->manager->value(this); -} - -/*! - Returns this property's value for the specified \a attribute. - - QtVariantPropertyManager provides a couple of related functions: - \l{QtVariantPropertyManager::attributes()}{attributes()} and - \l{QtVariantPropertyManager::attributeType()}{attributeType()}. - - \sa setAttribute() -*/ -QVariant QtVariantProperty::attributeValue(const QString &attribute) const -{ - return d_ptr->manager->attributeValue(this, attribute); -} - -/*! - Returns the type of this property's value. - - \sa propertyType() -*/ -int QtVariantProperty::valueType() const -{ - return d_ptr->manager->valueType(this); -} - -/*! - Returns this property's type. - - QtVariantPropertyManager provides several related functions: - \l{QtVariantPropertyManager::enumTypeId()}{enumTypeId()}, - \l{QtVariantPropertyManager::flagTypeId()}{flagTypeId()} and - \l{QtVariantPropertyManager::groupTypeId()}{groupTypeId()}. - - \sa valueType() -*/ -int QtVariantProperty::propertyType() const -{ - return d_ptr->manager->propertyType(this); -} - -/*! - Sets the value of this property to \a value. - - The specified \a value must be of the type returned by - valueType(), or of a type that can be converted to valueType() - using the QVariant::canConvert() function; otherwise this function - does nothing. - - \sa value() -*/ -void QtVariantProperty::setValue(const QVariant &value) -{ - d_ptr->manager->setValue(this, value); -} - -/*! - Sets the \a attribute of property to \a value. - - QtVariantPropertyManager provides the related - \l{QtVariantPropertyManager::setAttribute()}{setAttribute()} - function. - - \sa attributeValue() -*/ -void QtVariantProperty::setAttribute(const QString &attribute, const QVariant &value) -{ - d_ptr->manager->setAttribute(this, attribute, value); -} - -class QtVariantPropertyManagerPrivate -{ - QtVariantPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtVariantPropertyManager) -public: - QtVariantPropertyManagerPrivate(); - - bool m_creatingProperty; - bool m_creatingSubProperties; - bool m_destroyingSubProperties; - int m_propertyType; - - void slotValueChanged(QtProperty *property, int val); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotValueChanged(QtProperty *property, double val); - void slotRangeChanged(QtProperty *property, double min, double max); - void slotSingleStepChanged(QtProperty *property, double step); - void slotDecimalsChanged(QtProperty *property, int prec); - void slotValueChanged(QtProperty *property, bool val); - void slotValueChanged(QtProperty *property, const QString &val); - void slotRegExpChanged(QtProperty *property, const QRegExp ®Exp); - void slotEchoModeChanged(QtProperty *property, int); - void slotValueChanged(QtProperty *property, const QDate &val); - void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max); - void slotValueChanged(QtProperty *property, const QTime &val); - void slotValueChanged(QtProperty *property, const QDateTime &val); - void slotValueChanged(QtProperty *property, const QKeySequence &val); - void slotValueChanged(QtProperty *property, const QChar &val); - void slotValueChanged(QtProperty *property, const QLocale &val); - void slotValueChanged(QtProperty *property, const QPoint &val); - void slotValueChanged(QtProperty *property, const QPointF &val); - void slotValueChanged(QtProperty *property, const QSize &val); - void slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max); - void slotValueChanged(QtProperty *property, const QSizeF &val); - void slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max); - void slotValueChanged(QtProperty *property, const QRect &val); - void slotConstraintChanged(QtProperty *property, const QRect &val); - void slotValueChanged(QtProperty *property, const QRectF &val); - void slotConstraintChanged(QtProperty *property, const QRectF &val); - void slotValueChanged(QtProperty *property, const QColor &val); - void slotEnumChanged(QtProperty *property, int val); - void slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames); - void slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons); - void slotValueChanged(QtProperty *property, const QSizePolicy &val); - void slotValueChanged(QtProperty *property, const QFont &val); - void slotValueChanged(QtProperty *property, const QCursor &val); - void slotFlagChanged(QtProperty *property, int val); - void slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames); - void slotReadOnlyChanged(QtProperty *property, bool readOnly); - void slotTextVisibleChanged(QtProperty *property, bool textVisible); - void slotPropertyInserted(QtProperty *property, QtProperty *parent, QtProperty *after); - void slotPropertyRemoved(QtProperty *property, QtProperty *parent); - - void valueChanged(QtProperty *property, const QVariant &val); - - int internalPropertyToType(QtProperty *property) const; - QtVariantProperty *createSubProperty(QtVariantProperty *parent, QtVariantProperty *after, - QtProperty *internal); - void removeSubProperty(QtVariantProperty *property); - - QMap m_typeToPropertyManager; - QMap > m_typeToAttributeToAttributeType; - - QMap > m_propertyToType; - - QMap m_typeToValueType; - - - QMap m_internalToProperty; - - const QString m_constraintAttribute; - const QString m_singleStepAttribute; - const QString m_decimalsAttribute; - const QString m_enumIconsAttribute; - const QString m_enumNamesAttribute; - const QString m_flagNamesAttribute; - const QString m_maximumAttribute; - const QString m_minimumAttribute; - const QString m_regExpAttribute; - const QString m_echoModeAttribute; - const QString m_readOnlyAttribute; - const QString m_textVisibleAttribute; -}; - -QtVariantPropertyManagerPrivate::QtVariantPropertyManagerPrivate() : - m_constraintAttribute(QLatin1String("constraint")), - m_singleStepAttribute(QLatin1String("singleStep")), - m_decimalsAttribute(QLatin1String("decimals")), - m_enumIconsAttribute(QLatin1String("enumIcons")), - m_enumNamesAttribute(QLatin1String("enumNames")), - m_flagNamesAttribute(QLatin1String("flagNames")), - m_maximumAttribute(QLatin1String("maximum")), - m_minimumAttribute(QLatin1String("minimum")), - m_regExpAttribute(QLatin1String("regExp")), - m_echoModeAttribute(QLatin1String("echoMode")), - m_readOnlyAttribute(QLatin1String("readOnly")), - m_textVisibleAttribute(QLatin1String("textVisible")) -{ -} - -int QtVariantPropertyManagerPrivate::internalPropertyToType(QtProperty *property) const -{ - int type = 0; - QtAbstractPropertyManager *internPropertyManager = property->propertyManager(); - if (qobject_cast(internPropertyManager)) - type = QVariant::Int; - else if (qobject_cast(internPropertyManager)) - type = QtVariantPropertyManager::enumTypeId(); - else if (qobject_cast(internPropertyManager)) - type = QVariant::Bool; - else if (qobject_cast(internPropertyManager)) - type = QVariant::Double; - return type; -} - -QtVariantProperty *QtVariantPropertyManagerPrivate::createSubProperty(QtVariantProperty *parent, - QtVariantProperty *after, QtProperty *internal) -{ - int type = internalPropertyToType(internal); - if (!type) - return 0; - - bool wasCreatingSubProperties = m_creatingSubProperties; - m_creatingSubProperties = true; - - QtVariantProperty *varChild = q_ptr->addProperty(type, internal->propertyName()); - - m_creatingSubProperties = wasCreatingSubProperties; - - varChild->setPropertyName(internal->propertyName()); - varChild->setToolTip(internal->toolTip()); - varChild->setStatusTip(internal->statusTip()); - varChild->setWhatsThis(internal->whatsThis()); - - parent->insertSubProperty(varChild, after); - - m_internalToProperty[internal] = varChild; - propertyToWrappedProperty()->insert(varChild, internal); - return varChild; -} - -void QtVariantPropertyManagerPrivate::removeSubProperty(QtVariantProperty *property) -{ - QtProperty *internChild = wrappedProperty(property); - bool wasDestroyingSubProperties = m_destroyingSubProperties; - m_destroyingSubProperties = true; - delete property; - m_destroyingSubProperties = wasDestroyingSubProperties; - m_internalToProperty.remove(internChild); - propertyToWrappedProperty()->remove(property); -} - -void QtVariantPropertyManagerPrivate::slotPropertyInserted(QtProperty *property, - QtProperty *parent, QtProperty *after) -{ - if (m_creatingProperty) - return; - - QtVariantProperty *varParent = m_internalToProperty.value(parent, 0); - if (!varParent) - return; - - QtVariantProperty *varAfter = 0; - if (after) { - varAfter = m_internalToProperty.value(after, 0); - if (!varAfter) - return; - } - - createSubProperty(varParent, varAfter, property); -} - -void QtVariantPropertyManagerPrivate::slotPropertyRemoved(QtProperty *property, QtProperty *parent) -{ - Q_UNUSED(parent) - - QtVariantProperty *varProperty = m_internalToProperty.value(property, 0); - if (!varProperty) - return; - - removeSubProperty(varProperty); -} - -void QtVariantPropertyManagerPrivate::valueChanged(QtProperty *property, const QVariant &val) -{ - QtVariantProperty *varProp = m_internalToProperty.value(property, 0); - if (!varProp) - return; - emit q_ptr->valueChanged(varProp, val); - emit q_ptr->propertyChanged(varProp); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, int val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, double val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, double min, double max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, double step) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step)); -} - -void QtVariantPropertyManagerPrivate::slotDecimalsChanged(QtProperty *property, int prec) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_decimalsAttribute, QVariant(prec)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, bool val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QString &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRegExpChanged(QtProperty *property, const QRegExp ®Exp) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_regExpAttribute, QVariant(regExp)); -} - -void QtVariantPropertyManagerPrivate::slotEchoModeChanged(QtProperty *property, int mode) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_echoModeAttribute, QVariant(mode)); -} - -void QtVariantPropertyManagerPrivate::slotReadOnlyChanged(QtProperty *property, bool readOnly) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_readOnlyAttribute, QVariant(readOnly)); -} - -void QtVariantPropertyManagerPrivate::slotTextVisibleChanged(QtProperty *property, bool textVisible) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_textVisibleAttribute, QVariant(textVisible)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDate &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QTime &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDateTime &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val) -{ - QVariant v; - qVariantSetValue(v, val); - valueChanged(property, v); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QChar &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QLocale &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPoint &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPointF &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSize &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizeF &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRect &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRect &constraint) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRectF &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRectF &constraint) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QColor &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_enumNamesAttribute, QVariant(enumNames)); -} - -void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - QVariant v; - qVariantSetValue(v, enumIcons); - emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizePolicy &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QFont &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QCursor &val) -{ -#ifndef QT_NO_CURSOR - valueChanged(property, QVariant(val)); -#endif -} - -void QtVariantPropertyManagerPrivate::slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_flagNamesAttribute, QVariant(flagNames)); -} - -/*! - \class QtVariantPropertyManager - - \brief The QtVariantPropertyManager class provides and manages QVariant based properties. - - QtVariantPropertyManager provides the addProperty() function which - creates QtVariantProperty objects. The QtVariantProperty class is - a convenience class handling QVariant based properties inheriting - QtProperty. A QtProperty object created by a - QtVariantPropertyManager instance can be converted into a - QtVariantProperty object using the variantProperty() function. - - The property's value can be retrieved using the value(), and set - using the setValue() slot. In addition the property's type, and - the type of its value, can be retrieved using the propertyType() - and valueType() functions respectively. - - A property's type is a QVariant::Type enumerator value, and - usually a property's type is the same as its value type. But for - some properties the types differ, for example for enums, flags and - group types in which case QtVariantPropertyManager provides the - enumTypeId(), flagTypeId() and groupTypeId() functions, - respectively, to identify their property type (the value types are - QVariant::Int for the enum and flag types, and QVariant::Invalid - for the group type). - - Use the isPropertyTypeSupported() function to check if a particular - property type is supported. The currently supported property types - are: - - \table - \header - \o Property Type - \o Property Type Id - \row - \o int - \o QVariant::Int - \row - \o double - \o QVariant::Double - \row - \o bool - \o QVariant::Bool - \row - \o QString - \o QVariant::String - \row - \o QDate - \o QVariant::Date - \row - \o QTime - \o QVariant::Time - \row - \o QDateTime - \o QVariant::DateTime - \row - \o QKeySequence - \o QVariant::KeySequence - \row - \o QChar - \o QVariant::Char - \row - \o QLocale - \o QVariant::Locale - \row - \o QPoint - \o QVariant::Point - \row - \o QPointF - \o QVariant::PointF - \row - \o QSize - \o QVariant::Size - \row - \o QSizeF - \o QVariant::SizeF - \row - \o QRect - \o QVariant::Rect - \row - \o QRectF - \o QVariant::RectF - \row - \o QColor - \o QVariant::Color - \row - \o QSizePolicy - \o QVariant::SizePolicy - \row - \o QFont - \o QVariant::Font - \row - \o QCursor - \o QVariant::Cursor - \row - \o enum - \o enumTypeId() - \row - \o flag - \o flagTypeId() - \row - \o group - \o groupTypeId() - \endtable - - Each property type can provide additional attributes, - e.g. QVariant::Int and QVariant::Double provides minimum and - maximum values. The currently supported attributes are: - - \table - \header - \o Property Type - \o Attribute Name - \o Attribute Type - \row - \o \c int - \o minimum - \o QVariant::Int - \row - \o - \o maximum - \o QVariant::Int - \row - \o - \o singleStep - \o QVariant::Int - \row - \o \c double - \o minimum - \o QVariant::Double - \row - \o - \o maximum - \o QVariant::Double - \row - \o - \o singleStep - \o QVariant::Double - \row - \o - \o decimals - \o QVariant::Int - \row - \o \c bool - \o textVisible - \o QVariant::Bool - \row - \o QString - \o regExp - \o QVariant::RegExp - \row - \o - \o echoMode - \o QVariant::Int - \row - \o QDate - \o minimum - \o QVariant::Date - \row - \o - \o maximum - \o QVariant::Date - \row - \o QPointF - \o decimals - \o QVariant::Int - \row - \o QSize - \o minimum - \o QVariant::Size - \row - \o - \o maximum - \o QVariant::Size - \row - \o QSizeF - \o minimum - \o QVariant::SizeF - \row - \o - \o maximum - \o QVariant::SizeF - \row - \o - \o decimals - \o QVariant::Int - \row - \o QRect - \o constraint - \o QVariant::Rect - \row - \o QRectF - \o constraint - \o QVariant::RectF - \row - \o - \o decimals - \o QVariant::Int - \row - \o \c enum - \o enumNames - \o QVariant::StringList - \row - \o - \o enumIcons - \o iconMapTypeId() - \row - \o \c flag - \o flagNames - \o QVariant::StringList - \endtable - - The attributes for a given property type can be retrieved using - the attributes() function. Each attribute has a value type which - can be retrieved using the attributeType() function, and a value - accessible through the attributeValue() function. In addition, the - value can be set using the setAttribute() slot. - - QtVariantManager also provides the valueChanged() signal which is - emitted whenever a property created by this manager change, and - the attributeChanged() signal which is emitted whenever an - attribute of such a property changes. - - \sa QtVariantProperty, QtVariantEditorFactory -*/ - -/*! - \fn void QtVariantPropertyManager::valueChanged(QtProperty *property, const QVariant &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtVariantPropertyManager::attributeChanged(QtProperty *property, - const QString &attribute, const QVariant &value) - - This signal is emitted whenever an attribute of a property created - by this manager changes its value, passing a pointer to the \a - property, the \a attribute and the new \a value as parameters. - - \sa setAttribute() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtVariantPropertyManager::QtVariantPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtVariantPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_creatingProperty = false; - d_ptr->m_creatingSubProperties = false; - d_ptr->m_destroyingSubProperties = false; - d_ptr->m_propertyType = 0; - - // IntPropertyManager - QtIntPropertyManager *intPropertyManager = new QtIntPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Int] = intPropertyManager; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_minimumAttribute] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_maximumAttribute] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_singleStepAttribute] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_readOnlyAttribute] = QVariant::Bool; - d_ptr->m_typeToValueType[QVariant::Int] = QVariant::Int; - connect(intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(intPropertyManager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(intPropertyManager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); - // DoublePropertyManager - QtDoublePropertyManager *doublePropertyManager = new QtDoublePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Double] = doublePropertyManager; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_minimumAttribute] = - QVariant::Double; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_maximumAttribute] = - QVariant::Double; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_singleStepAttribute] = - QVariant::Double; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_decimalsAttribute] = - QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_readOnlyAttribute] = - QVariant::Bool; - d_ptr->m_typeToValueType[QVariant::Double] = QVariant::Double; - connect(doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(doublePropertyManager, SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(doublePropertyManager, SIGNAL(singleStepChanged(QtProperty *, double)), - this, SLOT(slotSingleStepChanged(QtProperty *, double))); - connect(doublePropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - // BoolPropertyManager - QtBoolPropertyManager *boolPropertyManager = new QtBoolPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Bool] = boolPropertyManager; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Bool][d_ptr->m_textVisibleAttribute] = QVariant::Bool; - d_ptr->m_typeToValueType[QVariant::Bool] = QVariant::Bool; - connect(boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotValueChanged(QtProperty *, bool))); - connect(boolPropertyManager, SIGNAL(textVisibleChanged(QtProperty*, bool)), - this, SLOT(slotTextVisibleChanged(QtProperty*, bool))); - // StringPropertyManager - QtStringPropertyManager *stringPropertyManager = new QtStringPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::String] = stringPropertyManager; - d_ptr->m_typeToValueType[QVariant::String] = QVariant::String; - d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_regExpAttribute] = - QVariant::RegExp; - d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_echoModeAttribute] = - QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_readOnlyAttribute] = - QVariant::Bool; - - connect(stringPropertyManager, SIGNAL(valueChanged(QtProperty *, const QString &)), - this, SLOT(slotValueChanged(QtProperty *, const QString &))); - connect(stringPropertyManager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)), - this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &))); - connect(stringPropertyManager, SIGNAL(echoModeChanged(QtProperty*,int)), - this, SLOT(slotEchoModeChanged(QtProperty*, int))); - connect(stringPropertyManager, SIGNAL(readOnlyChanged(QtProperty*, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty*, bool))); - - // DatePropertyManager - QtDatePropertyManager *datePropertyManager = new QtDatePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Date] = datePropertyManager; - d_ptr->m_typeToValueType[QVariant::Date] = QVariant::Date; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_minimumAttribute] = - QVariant::Date; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_maximumAttribute] = - QVariant::Date; - connect(datePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDate &)), - this, SLOT(slotValueChanged(QtProperty *, const QDate &))); - connect(datePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), - this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); - // TimePropertyManager - QtTimePropertyManager *timePropertyManager = new QtTimePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Time] = timePropertyManager; - d_ptr->m_typeToValueType[QVariant::Time] = QVariant::Time; - connect(timePropertyManager, SIGNAL(valueChanged(QtProperty *, const QTime &)), - this, SLOT(slotValueChanged(QtProperty *, const QTime &))); - // DateTimePropertyManager - QtDateTimePropertyManager *dateTimePropertyManager = new QtDateTimePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::DateTime] = dateTimePropertyManager; - d_ptr->m_typeToValueType[QVariant::DateTime] = QVariant::DateTime; - connect(dateTimePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), - this, SLOT(slotValueChanged(QtProperty *, const QDateTime &))); - // KeySequencePropertyManager - QtKeySequencePropertyManager *keySequencePropertyManager = new QtKeySequencePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::KeySequence] = keySequencePropertyManager; - d_ptr->m_typeToValueType[QVariant::KeySequence] = QVariant::KeySequence; - connect(keySequencePropertyManager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), - this, SLOT(slotValueChanged(QtProperty *, const QKeySequence &))); - // CharPropertyManager - QtCharPropertyManager *charPropertyManager = new QtCharPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Char] = charPropertyManager; - d_ptr->m_typeToValueType[QVariant::Char] = QVariant::Char; - connect(charPropertyManager, SIGNAL(valueChanged(QtProperty *, const QChar &)), - this, SLOT(slotValueChanged(QtProperty *, const QChar &))); - // LocalePropertyManager - QtLocalePropertyManager *localePropertyManager = new QtLocalePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Locale] = localePropertyManager; - d_ptr->m_typeToValueType[QVariant::Locale] = QVariant::Locale; - connect(localePropertyManager, SIGNAL(valueChanged(QtProperty *, const QLocale &)), - this, SLOT(slotValueChanged(QtProperty *, const QLocale &))); - connect(localePropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(localePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(localePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // PointPropertyManager - QtPointPropertyManager *pointPropertyManager = new QtPointPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Point] = pointPropertyManager; - d_ptr->m_typeToValueType[QVariant::Point] = QVariant::Point; - connect(pointPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPoint &)), - this, SLOT(slotValueChanged(QtProperty *, const QPoint &))); - connect(pointPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(pointPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(pointPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // PointFPropertyManager - QtPointFPropertyManager *pointFPropertyManager = new QtPointFPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::PointF] = pointFPropertyManager; - d_ptr->m_typeToValueType[QVariant::PointF] = QVariant::PointF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::PointF][d_ptr->m_decimalsAttribute] = - QVariant::Int; - connect(pointFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPointF &)), - this, SLOT(slotValueChanged(QtProperty *, const QPointF &))); - connect(pointFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(pointFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(pointFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(pointFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // SizePropertyManager - QtSizePropertyManager *sizePropertyManager = new QtSizePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Size] = sizePropertyManager; - d_ptr->m_typeToValueType[QVariant::Size] = QVariant::Size; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_minimumAttribute] = - QVariant::Size; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_maximumAttribute] = - QVariant::Size; - connect(sizePropertyManager, SIGNAL(valueChanged(QtProperty *, const QSize &)), - this, SLOT(slotValueChanged(QtProperty *, const QSize &))); - connect(sizePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSize &, const QSize &)), - this, SLOT(slotRangeChanged(QtProperty *, const QSize &, const QSize &))); - connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(sizePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(sizePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // SizeFPropertyManager - QtSizeFPropertyManager *sizeFPropertyManager = new QtSizeFPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::SizeF] = sizeFPropertyManager; - d_ptr->m_typeToValueType[QVariant::SizeF] = QVariant::SizeF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_minimumAttribute] = - QVariant::SizeF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_maximumAttribute] = - QVariant::SizeF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_decimalsAttribute] = - QVariant::Int; - connect(sizeFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizeF &)), - this, SLOT(slotValueChanged(QtProperty *, const QSizeF &))); - connect(sizeFPropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSizeF &, const QSizeF &)), - this, SLOT(slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &))); - connect(sizeFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(sizeFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(sizeFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // RectPropertyManager - QtRectPropertyManager *rectPropertyManager = new QtRectPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Rect] = rectPropertyManager; - d_ptr->m_typeToValueType[QVariant::Rect] = QVariant::Rect; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Rect][d_ptr->m_constraintAttribute] = - QVariant::Rect; - connect(rectPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRect &)), - this, SLOT(slotValueChanged(QtProperty *, const QRect &))); - connect(rectPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRect &)), - this, SLOT(slotConstraintChanged(QtProperty *, const QRect &))); - connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(rectPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(rectPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // RectFPropertyManager - QtRectFPropertyManager *rectFPropertyManager = new QtRectFPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::RectF] = rectFPropertyManager; - d_ptr->m_typeToValueType[QVariant::RectF] = QVariant::RectF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_constraintAttribute] = - QVariant::RectF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_decimalsAttribute] = - QVariant::Int; - connect(rectFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRectF &)), - this, SLOT(slotValueChanged(QtProperty *, const QRectF &))); - connect(rectFPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRectF &)), - this, SLOT(slotConstraintChanged(QtProperty *, const QRectF &))); - connect(rectFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(rectFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(rectFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // ColorPropertyManager - QtColorPropertyManager *colorPropertyManager = new QtColorPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Color] = colorPropertyManager; - d_ptr->m_typeToValueType[QVariant::Color] = QVariant::Color; - connect(colorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QColor &)), - this, SLOT(slotValueChanged(QtProperty *, const QColor &))); - connect(colorPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(colorPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(colorPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // EnumPropertyManager - int enumId = enumTypeId(); - QtEnumPropertyManager *enumPropertyManager = new QtEnumPropertyManager(this); - d_ptr->m_typeToPropertyManager[enumId] = enumPropertyManager; - d_ptr->m_typeToValueType[enumId] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumNamesAttribute] = - QVariant::StringList; - d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumIconsAttribute] = - iconMapTypeId(); - connect(enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(enumPropertyManager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); - connect(enumPropertyManager, SIGNAL(enumIconsChanged(QtProperty *, const QMap &)), - this, SLOT(slotEnumIconsChanged(QtProperty *, const QMap &))); - // SizePolicyPropertyManager - QtSizePolicyPropertyManager *sizePolicyPropertyManager = new QtSizePolicyPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::SizePolicy] = sizePolicyPropertyManager; - d_ptr->m_typeToValueType[QVariant::SizePolicy] = QVariant::SizePolicy; - connect(sizePolicyPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizePolicy &)), - this, SLOT(slotValueChanged(QtProperty *, const QSizePolicy &))); - connect(sizePolicyPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(sizePolicyPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(sizePolicyPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(sizePolicyPropertyManager->subEnumPropertyManager(), - SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); - connect(sizePolicyPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(sizePolicyPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // FontPropertyManager - QtFontPropertyManager *fontPropertyManager = new QtFontPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Font] = fontPropertyManager; - d_ptr->m_typeToValueType[QVariant::Font] = QVariant::Font; - connect(fontPropertyManager, SIGNAL(valueChanged(QtProperty *, const QFont &)), - this, SLOT(slotValueChanged(QtProperty *, const QFont &))); - connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(fontPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(fontPropertyManager->subEnumPropertyManager(), - SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); - connect(fontPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotValueChanged(QtProperty *, bool))); - connect(fontPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(fontPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // CursorPropertyManager - QtCursorPropertyManager *cursorPropertyManager = new QtCursorPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Cursor] = cursorPropertyManager; - d_ptr->m_typeToValueType[QVariant::Cursor] = QVariant::Cursor; - connect(cursorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), - this, SLOT(slotValueChanged(QtProperty *, const QCursor &))); - // FlagPropertyManager - int flagId = flagTypeId(); - QtFlagPropertyManager *flagPropertyManager = new QtFlagPropertyManager(this); - d_ptr->m_typeToPropertyManager[flagId] = flagPropertyManager; - d_ptr->m_typeToValueType[flagId] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[flagId][d_ptr->m_flagNamesAttribute] = - QVariant::StringList; - connect(flagPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(flagPropertyManager, SIGNAL(flagNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotFlagNamesChanged(QtProperty *, const QStringList &))); - connect(flagPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotValueChanged(QtProperty *, bool))); - connect(flagPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(flagPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // FlagPropertyManager - int groupId = groupTypeId(); - QtGroupPropertyManager *groupPropertyManager = new QtGroupPropertyManager(this); - d_ptr->m_typeToPropertyManager[groupId] = groupPropertyManager; - d_ptr->m_typeToValueType[groupId] = QVariant::Invalid; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtVariantPropertyManager::~QtVariantPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property converted into a QtVariantProperty. - - If the \a property was not created by this variant manager, the - function returns 0. - - \sa createProperty() -*/ -QtVariantProperty *QtVariantPropertyManager::variantProperty(const QtProperty *property) const -{ - const QMap >::const_iterator it = d_ptr->m_propertyToType.constFind(property); - if (it == d_ptr->m_propertyToType.constEnd()) - return 0; - return it.value().first; -} - -/*! - Returns true if the given \a propertyType is supported by this - variant manager; otherwise false. - - \sa propertyType() -*/ -bool QtVariantPropertyManager::isPropertyTypeSupported(int propertyType) const -{ - if (d_ptr->m_typeToValueType.contains(propertyType)) - return true; - return false; -} - -/*! - Creates and returns a variant property of the given \a propertyType - with the given \a name. - - If the specified \a propertyType is not supported by this variant - manager, this function returns 0. - - Do not use the inherited - QtAbstractPropertyManager::addProperty() function to create a - variant property (that function will always return 0 since it will - not be clear what type the property should have). - - \sa isPropertyTypeSupported() -*/ -QtVariantProperty *QtVariantPropertyManager::addProperty(int propertyType, const QString &name) -{ - if (!isPropertyTypeSupported(propertyType)) - return 0; - - bool wasCreating = d_ptr->m_creatingProperty; - d_ptr->m_creatingProperty = true; - d_ptr->m_propertyType = propertyType; - QtProperty *property = QtAbstractPropertyManager::addProperty(name); - d_ptr->m_creatingProperty = wasCreating; - d_ptr->m_propertyType = 0; - - if (!property) - return 0; - - return variantProperty(property); -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid variant. - - \sa setValue() -*/ -QVariant QtVariantPropertyManager::value(const QtProperty *property) const -{ - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return QVariant(); - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - return intManager->value(internProp); - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - return doubleManager->value(internProp); - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - return boolManager->value(internProp); - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - return stringManager->value(internProp); - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - return dateManager->value(internProp); - } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { - return timeManager->value(internProp); - } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { - return dateTimeManager->value(internProp); - } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { -#if QT_VERSION < 0x050000 - return keySequenceManager->value(internProp); -#else - return QVariant::fromValue(keySequenceManager->value(internProp)); -#endif - } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { - return charManager->value(internProp); - } else if (QtLocalePropertyManager *localeManager = qobject_cast(manager)) { - return localeManager->value(internProp); - } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { - return pointManager->value(internProp); - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - return pointFManager->value(internProp); - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - return sizeManager->value(internProp); - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - return sizeFManager->value(internProp); - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - return rectManager->value(internProp); - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - return rectFManager->value(internProp); - } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { - return colorManager->value(internProp); - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - return enumManager->value(internProp); - } else if (QtSizePolicyPropertyManager *sizePolicyManager = - qobject_cast(manager)) { - return sizePolicyManager->value(internProp); - } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { - return fontManager->value(internProp); -#ifndef QT_NO_CURSOR - } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { - return cursorManager->value(internProp); -#endif - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - return flagManager->value(internProp); - } - return QVariant(); -} - -/*! - Returns the given \a property's value type. - - \sa propertyType() -*/ -int QtVariantPropertyManager::valueType(const QtProperty *property) const -{ - int propType = propertyType(property); - return valueType(propType); -} - -/*! - \overload - - Returns the value type associated with the given \a propertyType. -*/ -int QtVariantPropertyManager::valueType(int propertyType) const -{ - if (d_ptr->m_typeToValueType.contains(propertyType)) - return d_ptr->m_typeToValueType[propertyType]; - return 0; -} - -/*! - Returns the given \a property's type. - - \sa valueType() -*/ -int QtVariantPropertyManager::propertyType(const QtProperty *property) const -{ - const QMap >::const_iterator it = d_ptr->m_propertyToType.constFind(property); - if (it == d_ptr->m_propertyToType.constEnd()) - return 0; - return it.value().second; -} - -/*! - Returns the given \a property's value for the specified \a - attribute - - If the given \a property was not created by \e this manager, or if - the specified \a attribute does not exist, this function returns - an invalid variant. - - \sa attributes(), attributeType(), setAttribute() -*/ -QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const -{ - int propType = propertyType(property); - if (!propType) - return QVariant(); - - QMap >::ConstIterator it = - d_ptr->m_typeToAttributeToAttributeType.find(propType); - if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) - return QVariant(); - - QMap attributes = it.value(); - QMap::ConstIterator itAttr = attributes.find(attribute); - if (itAttr == attributes.constEnd()) - return QVariant(); - - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return QVariant(); - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return intManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return intManager->minimum(internProp); - if (attribute == d_ptr->m_singleStepAttribute) - return intManager->singleStep(internProp); - if (attribute == d_ptr->m_readOnlyAttribute) - return intManager->isReadOnly(internProp); - return QVariant(); - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return doubleManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return doubleManager->minimum(internProp); - if (attribute == d_ptr->m_singleStepAttribute) - return doubleManager->singleStep(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return doubleManager->decimals(internProp); - if (attribute == d_ptr->m_readOnlyAttribute) - return doubleManager->isReadOnly(internProp); - return QVariant(); - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_textVisibleAttribute) - return boolManager->textVisible(internProp); - return QVariant(); - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_regExpAttribute) - return stringManager->regExp(internProp); - if (attribute == d_ptr->m_echoModeAttribute) - return stringManager->echoMode(internProp); - if (attribute == d_ptr->m_readOnlyAttribute) - return stringManager->isReadOnly(internProp); - return QVariant(); - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return dateManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return dateManager->minimum(internProp); - return QVariant(); - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_decimalsAttribute) - return pointFManager->decimals(internProp); - return QVariant(); - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return sizeManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return sizeManager->minimum(internProp); - return QVariant(); - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return sizeFManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return sizeFManager->minimum(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return sizeFManager->decimals(internProp); - return QVariant(); - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - return rectManager->constraint(internProp); - return QVariant(); - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - return rectFManager->constraint(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return rectFManager->decimals(internProp); - return QVariant(); - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_enumNamesAttribute) - return enumManager->enumNames(internProp); - if (attribute == d_ptr->m_enumIconsAttribute) { - QVariant v; - qVariantSetValue(v, enumManager->enumIcons(internProp)); - return v; - } - return QVariant(); - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_flagNamesAttribute) - return flagManager->flagNames(internProp); - return QVariant(); - } - return QVariant(); -} - -/*! - Returns a list of the given \a propertyType 's attributes. - - \sa attributeValue(), attributeType() -*/ -QStringList QtVariantPropertyManager::attributes(int propertyType) const -{ - QMap >::ConstIterator it = - d_ptr->m_typeToAttributeToAttributeType.find(propertyType); - if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) - return QStringList(); - return it.value().keys(); -} - -/*! - Returns the type of the specified \a attribute of the given \a - propertyType. - - If the given \a propertyType is not supported by \e this manager, - or if the given \a propertyType does not possess the specified \a - attribute, this function returns QVariant::Invalid. - - \sa attributes(), valueType() -*/ -int QtVariantPropertyManager::attributeType(int propertyType, const QString &attribute) const -{ - QMap >::ConstIterator it = - d_ptr->m_typeToAttributeToAttributeType.find(propertyType); - if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) - return 0; - - QMap attributes = it.value(); - QMap::ConstIterator itAttr = attributes.find(attribute); - if (itAttr == attributes.constEnd()) - return 0; - return itAttr.value(); -} - -/*! - \fn void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &value) - - Sets the value of the given \a property to \a value. - - The specified \a value must be of a type returned by valueType(), - or of type that can be converted to valueType() using the - QVariant::canConvert() function, otherwise this function does - nothing. - - \sa value(), QtVariantProperty::setValue(), valueChanged() -*/ -void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &val) -{ - int propType = val.userType(); - if (!propType) - return; - - int valType = valueType(property); - - if (propType != valType && !val.canConvert(static_cast(valType))) - return; - - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return; - - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - intManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - doubleManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - boolManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - stringManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - dateManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { - timeManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { - dateTimeManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { - keySequenceManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { - charManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtLocalePropertyManager *localeManager = qobject_cast(manager)) { - localeManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { - pointManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - pointFManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - sizeManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - sizeFManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - rectManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - rectFManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { - colorManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - enumManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtSizePolicyPropertyManager *sizePolicyManager = - qobject_cast(manager)) { - sizePolicyManager->setValue(internProp, qVariantValue(val)); - return; - } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { - fontManager->setValue(internProp, qVariantValue(val)); - return; -#ifndef QT_NO_CURSOR - } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { - cursorManager->setValue(internProp, qVariantValue(val)); - return; -#endif - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - flagManager->setValue(internProp, qVariantValue(val)); - return; - } -} - -/*! - Sets the value of the specified \a attribute of the given \a - property, to \a value. - - The new \a value's type must be of the type returned by - attributeType(), or of a type that can be converted to - attributeType() using the QVariant::canConvert() function, - otherwise this function does nothing. - - \sa attributeValue(), QtVariantProperty::setAttribute(), attributeChanged() -*/ -void QtVariantPropertyManager::setAttribute(QtProperty *property, - const QString &attribute, const QVariant &value) -{ - QVariant oldAttr = attributeValue(property, attribute); - if (!oldAttr.isValid()) - return; - - int attrType = value.userType(); - if (!attrType) - return; - - if (attrType != attributeType(propertyType(property), attribute) && - !value.canConvert((QVariant::Type)attrType)) - return; - - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return; - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - intManager->setMaximum(internProp, qVariantValue(value)); - else if (attribute == d_ptr->m_minimumAttribute) - intManager->setMinimum(internProp, qVariantValue(value)); - else if (attribute == d_ptr->m_singleStepAttribute) - intManager->setSingleStep(internProp, qVariantValue(value)); - else if (attribute == d_ptr->m_readOnlyAttribute) - intManager->setReadOnly(internProp, qVariantValue(value)); - return; - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - doubleManager->setMaximum(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_minimumAttribute) - doubleManager->setMinimum(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_singleStepAttribute) - doubleManager->setSingleStep(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_decimalsAttribute) - doubleManager->setDecimals(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_readOnlyAttribute) - doubleManager->setReadOnly(internProp, qVariantValue(value)); - return; - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_textVisibleAttribute) - boolManager->setTextVisible(internProp, qVariantValue(value)); - return; - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_regExpAttribute) - stringManager->setRegExp(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_echoModeAttribute) - stringManager->setEchoMode(internProp, (EchoMode)qVariantValue(value)); - if (attribute == d_ptr->m_readOnlyAttribute) - stringManager->setReadOnly(internProp, (EchoMode)qVariantValue(value)); - return; - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - dateManager->setMaximum(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_minimumAttribute) - dateManager->setMinimum(internProp, qVariantValue(value)); - return; - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_decimalsAttribute) - pointFManager->setDecimals(internProp, qVariantValue(value)); - return; - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - sizeManager->setMaximum(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_minimumAttribute) - sizeManager->setMinimum(internProp, qVariantValue(value)); - return; - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - sizeFManager->setMaximum(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_minimumAttribute) - sizeFManager->setMinimum(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_decimalsAttribute) - sizeFManager->setDecimals(internProp, qVariantValue(value)); - return; - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - rectManager->setConstraint(internProp, qVariantValue(value)); - return; - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - rectFManager->setConstraint(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_decimalsAttribute) - rectFManager->setDecimals(internProp, qVariantValue(value)); - return; - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_enumNamesAttribute) - enumManager->setEnumNames(internProp, qVariantValue(value)); - if (attribute == d_ptr->m_enumIconsAttribute) - enumManager->setEnumIcons(internProp, qVariantValue(value)); - return; - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_flagNamesAttribute) - flagManager->setFlagNames(internProp, qVariantValue(value)); - return; - } -} - -/*! - \reimp -*/ -bool QtVariantPropertyManager::hasValue(const QtProperty *property) const -{ - if (propertyType(property) == groupTypeId()) - return false; - return true; -} - -/*! - \reimp -*/ -QString QtVariantPropertyManager::valueText(const QtProperty *property) const -{ - const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - return internProp ? !internProp->displayText().isEmpty() ? internProp->displayText() : internProp->valueText() : QString(); -} - -/*! - \reimp -*/ -QIcon QtVariantPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - return internProp ? internProp->valueIcon() : QIcon(); -} - -/*! - \reimp -*/ -void QtVariantPropertyManager::initializeProperty(QtProperty *property) -{ - QtVariantProperty *varProp = variantProperty(property); - if (!varProp) - return; - - QMap::ConstIterator it = - d_ptr->m_typeToPropertyManager.find(d_ptr->m_propertyType); - if (it != d_ptr->m_typeToPropertyManager.constEnd()) { - QtProperty *internProp = 0; - if (!d_ptr->m_creatingSubProperties) { - QtAbstractPropertyManager *manager = it.value(); - internProp = manager->addProperty(); - d_ptr->m_internalToProperty[internProp] = varProp; - } - propertyToWrappedProperty()->insert(varProp, internProp); - if (internProp) { - QList children = internProp->subProperties(); - QListIterator itChild(children); - QtVariantProperty *lastProperty = 0; - while (itChild.hasNext()) { - QtVariantProperty *prop = d_ptr->createSubProperty(varProp, lastProperty, itChild.next()); - lastProperty = prop ? prop : lastProperty; - } - } - } -} - -/*! - \reimp -*/ -void QtVariantPropertyManager::uninitializeProperty(QtProperty *property) -{ - const QMap >::iterator type_it = d_ptr->m_propertyToType.find(property); - if (type_it == d_ptr->m_propertyToType.end()) - return; - - PropertyMap::iterator it = propertyToWrappedProperty()->find(property); - if (it != propertyToWrappedProperty()->end()) { - QtProperty *internProp = it.value(); - if (internProp) { - d_ptr->m_internalToProperty.remove(internProp); - if (!d_ptr->m_destroyingSubProperties) { - delete internProp; - } - } - propertyToWrappedProperty()->erase(it); - } - d_ptr->m_propertyToType.erase(type_it); -} - -/*! - \reimp -*/ -QtProperty *QtVariantPropertyManager::createProperty() -{ - if (!d_ptr->m_creatingProperty) - return 0; - - QtVariantProperty *property = new QtVariantProperty(this); - d_ptr->m_propertyToType.insert(property, qMakePair(property, d_ptr->m_propertyType)); - - return property; -} - -///////////////////////////// - -class QtVariantEditorFactoryPrivate -{ - QtVariantEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtVariantEditorFactory) -public: - - QtSpinBoxFactory *m_spinBoxFactory; - QtDoubleSpinBoxFactory *m_doubleSpinBoxFactory; - QtCheckBoxFactory *m_checkBoxFactory; - QtLineEditFactory *m_lineEditFactory; - QtDateEditFactory *m_dateEditFactory; - QtTimeEditFactory *m_timeEditFactory; - QtDateTimeEditFactory *m_dateTimeEditFactory; - QtKeySequenceEditorFactory *m_keySequenceEditorFactory; - QtCharEditorFactory *m_charEditorFactory; - QtEnumEditorFactory *m_comboBoxFactory; - QtCursorEditorFactory *m_cursorEditorFactory; - QtColorEditorFactory *m_colorEditorFactory; - QtFontEditorFactory *m_fontEditorFactory; - - QMap m_factoryToType; - QMap m_typeToFactory; -}; - -/*! - \class QtVariantEditorFactory - - \brief The QtVariantEditorFactory class provides widgets for properties - created by QtVariantPropertyManager objects. - - The variant factory provides the following widgets for the - specified property types: - - \table - \header - \o Property Type - \o Widget - \row - \o \c int - \o QSpinBox - \row - \o \c double - \o QDoubleSpinBox - \row - \o \c bool - \o QCheckBox - \row - \o QString - \o QLineEdit - \row - \o QDate - \o QDateEdit - \row - \o QTime - \o QTimeEdit - \row - \o QDateTime - \o QDateTimeEdit - \row - \o QKeySequence - \o customized editor - \row - \o QChar - \o customized editor - \row - \o \c enum - \o QComboBox - \row - \o QCursor - \o QComboBox - \endtable - - Note that QtVariantPropertyManager supports several additional property - types for which the QtVariantEditorFactory class does not provide - editing widgets, e.g. QPoint and QSize. To provide widgets for other - types using the variant approach, derive from the QtVariantEditorFactory - class. - - \sa QtAbstractEditorFactory, QtVariantPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtVariantEditorFactory::QtVariantEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtVariantEditorFactoryPrivate(); - d_ptr->q_ptr = this; - - d_ptr->m_spinBoxFactory = new QtSpinBoxFactory(this); - d_ptr->m_factoryToType[d_ptr->m_spinBoxFactory] = QVariant::Int; - d_ptr->m_typeToFactory[QVariant::Int] = d_ptr->m_spinBoxFactory; - - d_ptr->m_doubleSpinBoxFactory = new QtDoubleSpinBoxFactory(this); - d_ptr->m_factoryToType[d_ptr->m_doubleSpinBoxFactory] = QVariant::Double; - d_ptr->m_typeToFactory[QVariant::Double] = d_ptr->m_doubleSpinBoxFactory; - - d_ptr->m_checkBoxFactory = new QtCheckBoxFactory(this); - d_ptr->m_factoryToType[d_ptr->m_checkBoxFactory] = QVariant::Bool; - d_ptr->m_typeToFactory[QVariant::Bool] = d_ptr->m_checkBoxFactory; - - d_ptr->m_lineEditFactory = new QtLineEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_lineEditFactory] = QVariant::String; - d_ptr->m_typeToFactory[QVariant::String] = d_ptr->m_lineEditFactory; - - d_ptr->m_dateEditFactory = new QtDateEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_dateEditFactory] = QVariant::Date; - d_ptr->m_typeToFactory[QVariant::Date] = d_ptr->m_dateEditFactory; - - d_ptr->m_timeEditFactory = new QtTimeEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_timeEditFactory] = QVariant::Time; - d_ptr->m_typeToFactory[QVariant::Time] = d_ptr->m_timeEditFactory; - - d_ptr->m_dateTimeEditFactory = new QtDateTimeEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_dateTimeEditFactory] = QVariant::DateTime; - d_ptr->m_typeToFactory[QVariant::DateTime] = d_ptr->m_dateTimeEditFactory; - - d_ptr->m_keySequenceEditorFactory = new QtKeySequenceEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_keySequenceEditorFactory] = QVariant::KeySequence; - d_ptr->m_typeToFactory[QVariant::KeySequence] = d_ptr->m_keySequenceEditorFactory; - - d_ptr->m_charEditorFactory = new QtCharEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_charEditorFactory] = QVariant::Char; - d_ptr->m_typeToFactory[QVariant::Char] = d_ptr->m_charEditorFactory; - - d_ptr->m_cursorEditorFactory = new QtCursorEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_cursorEditorFactory] = QVariant::Cursor; - d_ptr->m_typeToFactory[QVariant::Cursor] = d_ptr->m_cursorEditorFactory; - - d_ptr->m_colorEditorFactory = new QtColorEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_colorEditorFactory] = QVariant::Color; - d_ptr->m_typeToFactory[QVariant::Color] = d_ptr->m_colorEditorFactory; - - d_ptr->m_fontEditorFactory = new QtFontEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_fontEditorFactory] = QVariant::Font; - d_ptr->m_typeToFactory[QVariant::Font] = d_ptr->m_fontEditorFactory; - - d_ptr->m_comboBoxFactory = new QtEnumEditorFactory(this); - const int enumId = QtVariantPropertyManager::enumTypeId(); - d_ptr->m_factoryToType[d_ptr->m_comboBoxFactory] = enumId; - d_ptr->m_typeToFactory[enumId] = d_ptr->m_comboBoxFactory; -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtVariantEditorFactory::~QtVariantEditorFactory() -{ - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) -{ - QList intPropertyManagers = qFindChildren(manager); - QListIterator itInt(intPropertyManagers); - while (itInt.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next()); - - QList doublePropertyManagers = qFindChildren(manager); - QListIterator itDouble(doublePropertyManagers); - while (itDouble.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next()); - - QList boolPropertyManagers = qFindChildren(manager); - QListIterator itBool(boolPropertyManagers); - while (itBool.hasNext()) - d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next()); - - QList stringPropertyManagers = qFindChildren(manager); - QListIterator itString(stringPropertyManagers); - while (itString.hasNext()) - d_ptr->m_lineEditFactory->addPropertyManager(itString.next()); - - QList datePropertyManagers = qFindChildren(manager); - QListIterator itDate(datePropertyManagers); - while (itDate.hasNext()) - d_ptr->m_dateEditFactory->addPropertyManager(itDate.next()); - - QList timePropertyManagers = qFindChildren(manager); - QListIterator itTime(timePropertyManagers); - while (itTime.hasNext()) - d_ptr->m_timeEditFactory->addPropertyManager(itTime.next()); - - QList dateTimePropertyManagers = qFindChildren(manager); - QListIterator itDateTime(dateTimePropertyManagers); - while (itDateTime.hasNext()) - d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next()); - - QList keySequencePropertyManagers = qFindChildren(manager); - QListIterator itKeySequence(keySequencePropertyManagers); - while (itKeySequence.hasNext()) - d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next()); - - QList charPropertyManagers = qFindChildren(manager); - QListIterator itChar(charPropertyManagers); - while (itChar.hasNext()) - d_ptr->m_charEditorFactory->addPropertyManager(itChar.next()); - - QList localePropertyManagers = qFindChildren(manager); - QListIterator itLocale(localePropertyManagers); - while (itLocale.hasNext()) - d_ptr->m_comboBoxFactory->addPropertyManager(itLocale.next()->subEnumPropertyManager()); - - QList pointPropertyManagers = qFindChildren(manager); - QListIterator itPoint(pointPropertyManagers); - while (itPoint.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager()); - - QList pointFPropertyManagers = qFindChildren(manager); - QListIterator itPointF(pointFPropertyManagers); - while (itPointF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager()); - - QList sizePropertyManagers = qFindChildren(manager); - QListIterator itSize(sizePropertyManagers); - while (itSize.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager()); - - QList sizeFPropertyManagers = qFindChildren(manager); - QListIterator itSizeF(sizeFPropertyManagers); - while (itSizeF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager()); - - QList rectPropertyManagers = qFindChildren(manager); - QListIterator itRect(rectPropertyManagers); - while (itRect.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager()); - - QList rectFPropertyManagers = qFindChildren(manager); - QListIterator itRectF(rectFPropertyManagers); - while (itRectF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager()); - - QList colorPropertyManagers = qFindChildren(manager); - QListIterator itColor(colorPropertyManagers); - while (itColor.hasNext()) { - QtColorPropertyManager *manager = itColor.next(); - d_ptr->m_colorEditorFactory->addPropertyManager(manager); - d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); - } - - QList enumPropertyManagers = qFindChildren(manager); - QListIterator itEnum(enumPropertyManagers); - while (itEnum.hasNext()) - d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next()); - - QList sizePolicyPropertyManagers = qFindChildren(manager); - QListIterator itSizePolicy(sizePolicyPropertyManagers); - while (itSizePolicy.hasNext()) { - QtSizePolicyPropertyManager *manager = itSizePolicy.next(); - d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); - d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); - } - - QList fontPropertyManagers = qFindChildren(manager); - QListIterator itFont(fontPropertyManagers); - while (itFont.hasNext()) { - QtFontPropertyManager *manager = itFont.next(); - d_ptr->m_fontEditorFactory->addPropertyManager(manager); - d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); - d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); - d_ptr->m_checkBoxFactory->addPropertyManager(manager->subBoolPropertyManager()); - } - - QList cursorPropertyManagers = qFindChildren(manager); - QListIterator itCursor(cursorPropertyManagers); - while (itCursor.hasNext()) - d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next()); - - QList flagPropertyManagers = qFindChildren(manager); - QListIterator itFlag(flagPropertyManagers); - while (itFlag.hasNext()) - d_ptr->m_checkBoxFactory->addPropertyManager(itFlag.next()->subBoolPropertyManager()); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtVariantEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - const int propType = manager->propertyType(property); - QtAbstractEditorFactoryBase *factory = d_ptr->m_typeToFactory.value(propType, 0); - if (!factory) - return 0; - return factory->createEditor(wrappedProperty(property), parent); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) -{ - QList intPropertyManagers = qFindChildren(manager); - QListIterator itInt(intPropertyManagers); - while (itInt.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next()); - - QList doublePropertyManagers = qFindChildren(manager); - QListIterator itDouble(doublePropertyManagers); - while (itDouble.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next()); - - QList boolPropertyManagers = qFindChildren(manager); - QListIterator itBool(boolPropertyManagers); - while (itBool.hasNext()) - d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next()); - - QList stringPropertyManagers = qFindChildren(manager); - QListIterator itString(stringPropertyManagers); - while (itString.hasNext()) - d_ptr->m_lineEditFactory->removePropertyManager(itString.next()); - - QList datePropertyManagers = qFindChildren(manager); - QListIterator itDate(datePropertyManagers); - while (itDate.hasNext()) - d_ptr->m_dateEditFactory->removePropertyManager(itDate.next()); - - QList timePropertyManagers = qFindChildren(manager); - QListIterator itTime(timePropertyManagers); - while (itTime.hasNext()) - d_ptr->m_timeEditFactory->removePropertyManager(itTime.next()); - - QList dateTimePropertyManagers = qFindChildren(manager); - QListIterator itDateTime(dateTimePropertyManagers); - while (itDateTime.hasNext()) - d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next()); - - QList keySequencePropertyManagers = qFindChildren(manager); - QListIterator itKeySequence(keySequencePropertyManagers); - while (itKeySequence.hasNext()) - d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next()); - - QList charPropertyManagers = qFindChildren(manager); - QListIterator itChar(charPropertyManagers); - while (itChar.hasNext()) - d_ptr->m_charEditorFactory->removePropertyManager(itChar.next()); - - QList localePropertyManagers = qFindChildren(manager); - QListIterator itLocale(localePropertyManagers); - while (itLocale.hasNext()) - d_ptr->m_comboBoxFactory->removePropertyManager(itLocale.next()->subEnumPropertyManager()); - - QList pointPropertyManagers = qFindChildren(manager); - QListIterator itPoint(pointPropertyManagers); - while (itPoint.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager()); - - QList pointFPropertyManagers = qFindChildren(manager); - QListIterator itPointF(pointFPropertyManagers); - while (itPointF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager()); - - QList sizePropertyManagers = qFindChildren(manager); - QListIterator itSize(sizePropertyManagers); - while (itSize.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager()); - - QList sizeFPropertyManagers = qFindChildren(manager); - QListIterator itSizeF(sizeFPropertyManagers); - while (itSizeF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager()); - - QList rectPropertyManagers = qFindChildren(manager); - QListIterator itRect(rectPropertyManagers); - while (itRect.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager()); - - QList rectFPropertyManagers = qFindChildren(manager); - QListIterator itRectF(rectFPropertyManagers); - while (itRectF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager()); - - QList colorPropertyManagers = qFindChildren(manager); - QListIterator itColor(colorPropertyManagers); - while (itColor.hasNext()) { - QtColorPropertyManager *manager = itColor.next(); - d_ptr->m_colorEditorFactory->removePropertyManager(manager); - d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); - } - - QList enumPropertyManagers = qFindChildren(manager); - QListIterator itEnum(enumPropertyManagers); - while (itEnum.hasNext()) - d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next()); - - QList sizePolicyPropertyManagers = qFindChildren(manager); - QListIterator itSizePolicy(sizePolicyPropertyManagers); - while (itSizePolicy.hasNext()) { - QtSizePolicyPropertyManager *manager = itSizePolicy.next(); - d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); - d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); - } - - QList fontPropertyManagers = qFindChildren(manager); - QListIterator itFont(fontPropertyManagers); - while (itFont.hasNext()) { - QtFontPropertyManager *manager = itFont.next(); - d_ptr->m_fontEditorFactory->removePropertyManager(manager); - d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); - d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); - d_ptr->m_checkBoxFactory->removePropertyManager(manager->subBoolPropertyManager()); - } - - QList cursorPropertyManagers = qFindChildren(manager); - QListIterator itCursor(cursorPropertyManagers); - while (itCursor.hasNext()) - d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next()); - - QList flagPropertyManagers = qFindChildren(manager); - QListIterator itFlag(flagPropertyManagers); - while (itFlag.hasNext()) - d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager()); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtvariantproperty.cpp" diff --git a/src/qt-solutions/qtpropertybrowser/src/qtvariantproperty.h b/src/qt-solutions/qtpropertybrowser/src/qtvariantproperty.h deleted file mode 100644 index 2c09fe9e..00000000 --- a/src/qt-solutions/qtpropertybrowser/src/qtvariantproperty.h +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTVARIANTPROPERTY_H -#define QTVARIANTPROPERTY_H - -#include "qtpropertybrowser.h" -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -typedef QMap QtIconMap; - -class QtVariantPropertyManager; -class QtVariantPropertyPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtVariantProperty : public QtProperty -{ -public: - ~QtVariantProperty(); - QVariant value() const; - QVariant attributeValue(const QString &attribute) const; - int valueType() const; - int propertyType() const; - - void setValue(const QVariant &value); - void setAttribute(const QString &attribute, const QVariant &value); -protected: - QtVariantProperty(QtVariantPropertyManager *manager); -private: - friend class QtVariantPropertyManager; - QtVariantPropertyPrivate *d_ptr; -}; - -class QtVariantPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtVariantPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtVariantPropertyManager(QObject *parent = 0); - ~QtVariantPropertyManager(); - - virtual QtVariantProperty *addProperty(int propertyType, const QString &name = QString()); - - int propertyType(const QtProperty *property) const; - int valueType(const QtProperty *property) const; - QtVariantProperty *variantProperty(const QtProperty *property) const; - - virtual bool isPropertyTypeSupported(int propertyType) const; - virtual int valueType(int propertyType) const; - virtual QStringList attributes(int propertyType) const; - virtual int attributeType(int propertyType, const QString &attribute) const; - - virtual QVariant value(const QtProperty *property) const; - virtual QVariant attributeValue(const QtProperty *property, const QString &attribute) const; - - static int enumTypeId(); - static int flagTypeId(); - static int groupTypeId(); - static int iconMapTypeId(); -public Q_SLOTS: - virtual void setValue(QtProperty *property, const QVariant &val); - virtual void setAttribute(QtProperty *property, - const QString &attribute, const QVariant &value); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QVariant &val); - void attributeChanged(QtProperty *property, - const QString &attribute, const QVariant &val); -protected: - virtual bool hasValue(const QtProperty *property) const; - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); - virtual QtProperty *createProperty(); -private: - QtVariantPropertyManagerPrivate *d_ptr; - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QString &)) - Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &)) - Q_PRIVATE_SLOT(d_func(), void slotEchoModeChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QDate &, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QTime &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDateTime &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QKeySequence &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QChar &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QLocale &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPoint &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPointF &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSize &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSize &, const QSize &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizeF &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRect &)) - Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRect &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRectF &)) - Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRectF &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QColor &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, const QStringList &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, const QMap &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizePolicy &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QFont &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QCursor &)) - Q_PRIVATE_SLOT(d_func(), void slotFlagNamesChanged(QtProperty *, const QStringList &)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotTextVisibleChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, QtProperty *)) - Q_DECLARE_PRIVATE(QtVariantPropertyManager) - Q_DISABLE_COPY(QtVariantPropertyManager) -}; - -class QtVariantEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtVariantEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtVariantEditorFactory(QObject *parent = 0); - ~QtVariantEditorFactory(); -protected: - void connectPropertyManager(QtVariantPropertyManager *manager); - QWidget *createEditor(QtVariantPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtVariantPropertyManager *manager); -private: - QtVariantEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtVariantEditorFactory) - Q_DISABLE_COPY(QtVariantEditorFactory) -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -Q_DECLARE_METATYPE(QIcon) -Q_DECLARE_METATYPE(QtIconMap) -#endif diff --git a/src/qt_occ_view_controller.cpp b/src/qt_occ_view_controller.cpp deleted file mode 100644 index 52507fd9..00000000 --- a/src/qt_occ_view_controller.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "qt_occ_view_controller.h" - -#include "widget_occ_view.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace Mayo { - -namespace Internal { - -static const QCursor& rotateCursor() -{ - static QCursor cursor; - if (cursor.bitmap() == nullptr) { - const int rotateCursorWidth = 16; - const int rotateCursorHeight = 16; - const int rotateCursorByteCount = - ((rotateCursorWidth + 7) / 8) * rotateCursorHeight; - const int rotateCursorHotX = 6; - const int rotateCursorHotY = 8; - - static unsigned char rotateCursorBitmap[rotateCursorByteCount] = { - 0xf0, 0xef, 0x18, 0xb8, 0x0c, 0x90, 0xe4, 0x83, - 0x34, 0x86, 0x1c, 0x83, 0x00, 0x81, 0x00, 0xff, - 0xff, 0x00, 0x81, 0x00, 0xc1, 0x38, 0x61, 0x2c, - 0xc1, 0x27, 0x09, 0x30, 0x1d, 0x18, 0xf7, 0x0f - }; - - static unsigned char rotateCursorMaskBitmap[rotateCursorByteCount] = { - 0xf0,0xef,0xf8,0xff,0xfc,0xff,0xfc,0xff,0x3c,0xfe,0x1c,0xff,0x00,0xff,0x00, - 0xff,0xff,0x00,0xff,0x00,0xff,0x38,0x7f,0x3c,0xff,0x3f,0xff,0x3f,0xff,0x1f, - 0xf7,0x0f - }; - - const QBitmap cursorBmp = QBitmap::fromData( - QSize(rotateCursorWidth, rotateCursorHeight), - rotateCursorBitmap); - const QBitmap maskBmp = QBitmap::fromData( - QSize(rotateCursorWidth, rotateCursorHeight), - rotateCursorMaskBitmap); - const QCursor tempCursor( - cursorBmp, maskBmp, rotateCursorHotX, rotateCursorHotY); - cursor = std::move(tempCursor); - } - return cursor; -} - -} // namespace Internal - -QtOccViewController::QtOccViewController(WidgetOccView* view) - : QObject(view), - m_view(view) -{ - if (view != nullptr) - view->installEventFilter(this); -} - -bool QtOccViewController::eventFilter(QObject* watched, QEvent* event) -{ - auto view = qobject_cast(watched); - if (view != m_view) - return QObject::eventFilter(watched, event); - Handle_V3d_View occView = view->occV3dView(); - - //const Qt::KeyboardModifiers keybMods = QApplication::queryKeyboardModifiers(); - - switch (event->type()) { - case QEvent::MouseButtonPress: { - const QMouseEvent* mouseEvent = static_cast(event); - const QPoint currPos = view->mapFromGlobal(mouseEvent->globalPos()); - m_prevPos = currPos; - if (mouseEvent->button() == Qt::LeftButton) { - occView->StartRotation(currPos.x(), currPos.y()); - return true; - } - break; - } - case QEvent::MouseMove: { - const QMouseEvent* mouseEvent = static_cast(event); - const QPoint currPos = view->mapFromGlobal(mouseEvent->globalPos()); - const QPoint prevPos = m_prevPos; - m_prevPos = currPos; - - if (QApplication::mouseButtons() == Qt::LeftButton) { - this->setViewCursor(Internal::rotateCursor()); - occView->Rotation(currPos.x(), currPos.y()); - return true; - } - else if (QApplication::mouseButtons() == Qt::RightButton) { - this->setViewCursor(Qt::SizeAllCursor); - occView->Pan(currPos.x() - prevPos.x(), prevPos.y() - currPos.y()); - return true; - } - break; - } - case QEvent::MouseButtonRelease: { - this->setViewCursor(Qt::ArrowCursor); - return true; - } - case QEvent::Wheel: { - const QWheelEvent* wheelEvent = static_cast(event); - Standard_Real currentScale = occView->Scale(); - if (wheelEvent->delta() > 0) - currentScale *= 1.1; // +10% - else - currentScale /= 1.1; // -10% - occView->SetScale(currentScale); - return true; - } - default: return false; - } // end switch - - return false; -} - -void QtOccViewController::setViewCursor(const QCursor &cursor) -{ - if (m_view != nullptr) - m_view->setCursor(cursor); -} - -} // namespace Mayo diff --git a/src/qt_occ_view_controller.h b/src/qt_occ_view_controller.h deleted file mode 100644 index 17056a7f..00000000 --- a/src/qt_occ_view_controller.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include -class QCursor; - -namespace Mayo { - -class WidgetOccView; - -class QtOccViewController : public QObject -{ - Q_OBJECT - -public: - QtOccViewController(WidgetOccView* view = nullptr); - - bool eventFilter(QObject* watched, QEvent* event) override; - -private: - void setViewCursor(const QCursor& cursor); - -private: - QPoint m_prevPos; - class WidgetOccView* m_view = nullptr; -}; - -} // namespace Mayo diff --git a/src/stl_mesh_item.cpp b/src/stl_mesh_item.cpp deleted file mode 100644 index 92d76ead..00000000 --- a/src/stl_mesh_item.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "stl_mesh_item.h" - -#include - -namespace Mayo { - -StlMeshItem::StlMeshItem() - : propertyNodeCount( - this, QCoreApplication::translate("Mayo::StlMeshItem", "Node count")), - propertyTriangleCount( - this, QCoreApplication::translate("Mayo::StlMeshItem", "Triangle count")) -{ -} - -const Handle_StlMesh_Mesh &StlMeshItem::stlMesh() const -{ - return m_stlMesh; -} - -void StlMeshItem::setStlMesh(const Handle_StlMesh_Mesh &mesh) -{ - m_stlMesh = mesh; -} - -bool StlMeshItem::isNull() const -{ - return m_stlMesh.IsNull(); -} - -const char* StlMeshItem::type = "2d441323-48db-4222-91b4-bdb7b5460c3f"; -const char* StlMeshItem::dynType() const { return StlMeshItem::type; } - -} // namespace Mayo diff --git a/src/stl_mesh_item.h b/src/stl_mesh_item.h deleted file mode 100644 index 7a9d95fd..00000000 --- a/src/stl_mesh_item.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include "document_item.h" -#include - -namespace Mayo { - -class StlMeshItem : public PartItem -{ -public: - StlMeshItem(); - - const Handle_StlMesh_Mesh& stlMesh() const; - void setStlMesh(const Handle_StlMesh_Mesh& mesh); - - bool isNull() const override; - - static const char* type; - const char* dynType() const override; - - PropertyInt propertyNodeCount; // Read-only - PropertyInt propertyTriangleCount; // Read-only - -private: - Handle_StlMesh_Mesh m_stlMesh; -}; - -} // namespace Mayo diff --git a/src/widget_application_tree.cpp b/src/widget_application_tree.cpp deleted file mode 100644 index d849a62f..00000000 --- a/src/widget_application_tree.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "widget_application_tree.h" - -#include "application.h" -#include "document.h" -#include "document_item.h" -#include "ui_widget_application_tree.h" - -namespace Mayo { - -namespace Internal { - -static QString documentItemLabel(const DocumentItem* docItem) -{ - const QString docItemLabel = docItem->propertyLabel.value(); - return !docItemLabel.isEmpty() ? - docItemLabel : - WidgetApplicationTree::tr(""); -} - -} // namespace Internal - -WidgetApplicationTree::WidgetApplicationTree(QWidget *widget) - : QWidget(widget), - m_ui(new Ui_WidgetApplicationTree) -{ - m_ui->setupUi(this); - - auto app = Application::instance(); - QObject::connect( - app, &Application::documentAdded, - this, &WidgetApplicationTree::onDocumentAdded); - QObject::connect( - app, &Application::documentErased, - this, &WidgetApplicationTree::onDocumentErased); - QObject::connect( - app, &Application::documentItemAdded, - this, &WidgetApplicationTree::onDocumentItemAdded); - QObject::connect( - app, &Application::documentItemPropertyChanged, - this, &WidgetApplicationTree::onDocumentItemPropertyChanged); - QObject::connect( - m_ui->treeWidget_App->selectionModel(), - &QItemSelectionModel::selectionChanged, - this, - &WidgetApplicationTree::onTreeWidgetDocumentSelectionChanged); -} - -WidgetApplicationTree::~WidgetApplicationTree() -{ - delete m_ui; -} - -std::vector WidgetApplicationTree::selectedDocumentItems() const -{ - const QList listTreeItem = - m_ui->treeWidget_App->selectedItems(); - std::vector vecDocItem; - vecDocItem.reserve(listTreeItem.size()); - for (QTreeWidgetItem* treeItem : listTreeItem) { - auto itFound = std::find_if( - m_vecTreeItemDocItem.cbegin(), - m_vecTreeItemDocItem.cend(), - [=](const TreeWidgetItem_DocumentItem& pair) { - return pair.treeItem == treeItem; - }); - if (itFound != m_vecTreeItemDocItem.cend()) - vecDocItem.push_back(itFound->docItem); - } - return vecDocItem; -} - -void WidgetApplicationTree::onDocumentAdded(Document *doc) -{ - auto treeItem = new QTreeWidgetItem; - const QString docLabel = - !doc->label().isEmpty() ? doc->label() : tr(""); - treeItem->setText(0, docLabel); - treeItem->setIcon(0, QPixmap(":/images/document.png")); - const TreeWidgetItem_Document pair = { treeItem, doc }; - m_vecTreeItemDoc.emplace_back(std::move(pair)); - m_ui->treeWidget_App->addTopLevelItem(treeItem); -} - -void WidgetApplicationTree::onDocumentErased(const Document *doc) -{ - auto itFound = this->findTreeItemDocument(doc); - if (itFound != m_vecTreeItemDoc.end()) { - delete itFound->treeItem; - m_vecTreeItemDoc.erase(itFound); - } -} - -void WidgetApplicationTree::onDocumentItemAdded(DocumentItem *docItem) -{ - auto treeItem = new QTreeWidgetItem; - const QString docItemLabel = Internal::documentItemLabel(docItem); - treeItem->setText(0, docItemLabel); - //treeItem->setIcon(0, QPixmap(":/images/document.png")); - const TreeWidgetItem_DocumentItem pair = { treeItem, docItem }; - m_vecTreeItemDocItem.emplace_back(std::move(pair)); - auto itFound = this->findTreeItemDocument(docItem->document()); - if (itFound != m_vecTreeItemDoc.end()) { - itFound->treeItem->addChild(treeItem); - itFound->treeItem->setExpanded(true); - } -} - -void WidgetApplicationTree::onDocumentItemPropertyChanged( - const DocumentItem *docItem, const Property *prop) -{ - auto itFound = this->findTreeItemDocumentItem(docItem); - if (itFound != m_vecTreeItemDocItem.end()) { - TreeWidgetItem_DocumentItem pair = *itFound; - if (prop == &docItem->propertyLabel) - pair.treeItem->setText(0, Internal::documentItemLabel(docItem)); - } -} - -void WidgetApplicationTree::onTreeWidgetDocumentSelectionChanged() -{ - emit selectionChanged(); -} - -std::vector::iterator -WidgetApplicationTree::findTreeItemDocument(const Document* doc) -{ - auto itFound = std::find_if( - m_vecTreeItemDoc.begin(), - m_vecTreeItemDoc.end(), - [=](const TreeWidgetItem_Document& pair) - { return pair.doc == doc; }); - return itFound; -} - -std::vector::iterator -WidgetApplicationTree::findTreeItemDocumentItem(const DocumentItem *docItem) -{ - auto itFound = std::find_if( - m_vecTreeItemDocItem.begin(), - m_vecTreeItemDocItem.end(), - [=](const TreeWidgetItem_DocumentItem& pair) - { return pair.docItem == docItem; }); - return itFound; -} - -} // namespace Mayo diff --git a/src/widget_application_tree.h b/src/widget_application_tree.h deleted file mode 100644 index 164df927..00000000 --- a/src/widget_application_tree.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include -class QTreeWidgetItem; - -namespace Mayo { - -class Document; -class DocumentItem; -class Property; - -class WidgetApplicationTree : public QWidget -{ - Q_OBJECT - -public: - WidgetApplicationTree(QWidget* widget = nullptr); - ~WidgetApplicationTree(); - - std::vector selectedDocumentItems() const; - -signals: - void selectionChanged(); - -private: - void onDocumentAdded(Document* doc); - void onDocumentErased(const Document* doc); - void onDocumentItemAdded(DocumentItem* docItem); - void onDocumentItemPropertyChanged( - const DocumentItem* docItem, const Property* prop); - - void onTreeWidgetDocumentSelectionChanged(); - - struct TreeWidgetItem_Document { - QTreeWidgetItem* treeItem; - Document* doc; - }; - struct TreeWidgetItem_DocumentItem { - QTreeWidgetItem* treeItem; - DocumentItem* docItem; - }; - std::vector::iterator - findTreeItemDocument(const Document* doc); - std::vector::iterator - findTreeItemDocumentItem(const DocumentItem* docItem); - - class Ui_WidgetApplicationTree* m_ui = nullptr; - std::vector m_vecTreeItemDoc; - std::vector m_vecTreeItemDocItem; -}; - -} // namespace Mayo diff --git a/src/widget_document_item_props.cpp b/src/widget_document_item_props.cpp deleted file mode 100644 index 02623c27..00000000 --- a/src/widget_document_item_props.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "widget_document_item_props.h" - -#include "document_item.h" -#include "gui_application.h" -#include "gui_document.h" -#include "gpx_document_item.h" -#include "options.h" -#include "ui_widget_document_item_props.h" -#include "fougtools/occtools/qt_utils.h" - -#include -#include - -namespace Mayo { - -namespace Internal { - -struct EnumTag {}; - -// -- -// -- PropTraits<> -// -- -template struct PropTraits {}; - -template<> struct PropTraits { - static int qVariantTypeId() { return QVariant::Bool; } - typedef bool QVariantType; - typedef PropertyBool PropertyType; -}; - -template<> struct PropTraits { - static int qVariantTypeId() { return QVariant::Int; } - typedef int QVariantType; - typedef PropertyInt PropertyType; -}; - -template<> struct PropTraits { - static int qVariantTypeId() { return QVariant::Double; } - typedef double QVariantType; - typedef PropertyDouble PropertyType; -}; - -template<> struct PropTraits { - static int qVariantTypeId() { return QVariant::Color; } - typedef QColor QVariantType; - typedef PropertyOccColor PropertyType; -}; - -template<> struct PropTraits { - static int qVariantTypeId() { return QVariant::String; } - typedef QString QVariantType; - typedef PropertyQString PropertyType; -}; - -template<> struct PropTraits { - static int qVariantTypeId() { return QtVariantPropertyManager::enumTypeId(); } - typedef int QVariantType; - typedef PropertyEnumeration PropertyType; -}; - -// -- -// -- PropertyQVariantCast<> -// -- -template struct PropertyQVariantCast { - typedef typename PropTraits::QVariantType QVariantType; - typedef typename PropTraits::PropertyType PropertyType; - - static QVariantType toQVariantValue(const PropertyType* prop) - { return qvariant_cast(prop->value()); } - - static T toPropertyValue(const QVariant& value, const PropertyType*) - { return qvariant_cast(value); } -}; - -template<> struct PropertyQVariantCast { - static QColor toQVariantValue(const PropertyOccColor* prop) - { return occ::QtUtils::toQColor(prop->value()); } - - static Quantity_Color toPropertyValue( - const QVariant& value, const PropertyOccColor*) - { return occ::QtUtils::toOccColor(qvariant_cast(value)); } -}; - -template<> struct PropertyQVariantCast { - static int toQVariantValue(const PropertyEnumeration* prop) - { - const auto& enumMappings = prop->enumeration().mappings(); - auto itEnum = - std::find_if( - enumMappings.cbegin(), - enumMappings.cend(), - [=](const Enumeration::Mapping& mapping) { - return mapping.value == prop->value(); - } ); - if (itEnum != enumMappings.cend()) - return itEnum - enumMappings.cbegin(); - return -1; - } - - static Enumeration::Value toPropertyValue( - const QVariant& value, const PropertyEnumeration* prop) - { - const int enumValueId = value.toInt(); - return prop->enumeration().mapping(enumValueId).value; - } -}; - -// -- -// -- QtPropertyInit<> -// -- - -template struct QtPropertyInit { - static void func(QtVariantProperty*, const Property*) {} -}; - -template struct QtPropertyInitConstraints { - static void func( - QtVariantProperty* qtProp, const PropertyScalarConstraints* cnts) - { - if (cnts->constraintsEnabled()) { - qtProp->setAttribute(QLatin1String("minimum"), cnts->minimum()); - qtProp->setAttribute(QLatin1String("maximum"), cnts->maximum()); - qtProp->setAttribute(QLatin1String("singleStep"), cnts->singleStep()); - } - } -}; -template<> struct QtPropertyInit : public QtPropertyInitConstraints {}; -template<> struct QtPropertyInit : public QtPropertyInitConstraints {}; - -template<> struct QtPropertyInit { - static void func(QtVariantProperty* qtProp, const PropertyEnumeration* prop) - { - QStringList enumNames; - const auto& enumMappings = prop->enumeration().mappings(); - for (const Enumeration::Mapping& mapping : enumMappings) - enumNames.push_back(mapping.string); - qtProp->setAttribute(QLatin1String("enumNames"), enumNames); - } -}; - -// -- -// -- Generic API -// -- - - -template -static QtVariantProperty* createQtProperty( - const Property* prop, QtVariantPropertyManager* varPropMgr) -{ - typedef typename PropTraits::PropertyType PropertyType; - auto castedProp = static_cast(prop); - QtVariantProperty* qtProp = - varPropMgr->addProperty( - PropTraits::qVariantTypeId(), prop->label()); - QtPropertyInit::func(qtProp, castedProp); - qtProp->setValue(PropertyQVariantCast::toQVariantValue(castedProp)); - return qtProp; -} - -template void setPropertyValue(Property* prop, const QVariant& value) -{ - typedef typename PropTraits::PropertyType PropertyType; - auto castedProp = static_cast(prop); - castedProp->setValue( - PropertyQVariantCast::toPropertyValue(value, castedProp)); -} - -} // namespace Internal - -WidgetDocumentItemProps::WidgetDocumentItemProps(QWidget *parent) - : QWidget(parent), - m_ui(new Ui_WidgetDocumentItemProps), - m_varPropMgr(new QtVariantPropertyManager(this)) -{ - m_ui->setupUi(this); - auto variantEditorFactory = new QtVariantEditorFactory(this); - m_ui->propsBrowser_DocumentItem->setFactoryForManager( - m_varPropMgr, variantEditorFactory); -} - -WidgetDocumentItemProps::~WidgetDocumentItemProps() -{ - delete m_ui; -} - -void WidgetDocumentItemProps::setGuiApplication(GuiApplication *guiApp) -{ - m_guiApp = guiApp; -} - -void WidgetDocumentItemProps::editDocumentItems( - const std::vector& vecDocItem) -{ - this->connectPropertyValueChangeSignals(false); - if (vecDocItem.size() == 1) { - m_ui->stack_Browser->setCurrentWidget(m_ui->page_BrowserDetails); - m_varPropMgr->clear(); - m_ui->propsBrowser_DocumentItem->clear(); - m_vecQtPropProp.clear(); - - // Data - m_currentDocItem = vecDocItem.front(); - if (m_currentDocItem != nullptr) { - QtProperty* propGroupData = - m_varPropMgr->addProperty( - QtVariantPropertyManager::groupTypeId(), tr("Data")); - m_ui->propsBrowser_DocumentItem->addProperty(propGroupData); - this->createQtProperties(m_currentDocItem->properties(), propGroupData); - } - - // Graphics - const GuiDocument* guiDoc = - m_guiApp->findGuiDocument(m_currentDocItem->document()); - m_currentGpxDocItem = guiDoc->findItemGpx(m_currentDocItem); - if (m_currentGpxDocItem != nullptr) { - QtProperty* propGroupGpx = - m_varPropMgr->addProperty( - QtVariantPropertyManager::groupTypeId(), tr("Graphics")); - m_ui->propsBrowser_DocumentItem->addProperty(propGroupGpx); - const GpxDocumentItem* gpxItem = m_currentGpxDocItem; - this->createQtProperties(gpxItem->properties(), propGroupGpx); - } - this->connectPropertyValueChangeSignals(true); - } - else { - m_ui->stack_Browser->setCurrentWidget(m_ui->page_BrowserEmpty); - m_currentDocItem = nullptr; - m_currentGpxDocItem = nullptr; - } -} - -void WidgetDocumentItemProps::connectPropertyValueChangeSignals(bool on) -{ - if (on) { - QObject::connect( - m_varPropMgr, &QtVariantPropertyManager::valueChanged, - this, &WidgetDocumentItemProps::onQVariantPropertyValueChanged, - Qt::UniqueConnection); - } - else { - QObject::disconnect( - m_varPropMgr, &QtVariantPropertyManager::valueChanged, - this, &WidgetDocumentItemProps::onQVariantPropertyValueChanged); - } -} - -void WidgetDocumentItemProps::onQVariantPropertyValueChanged( - QtProperty *qtProp, const QVariant &value) -{ - if (m_currentDocItem != nullptr || m_currentGpxDocItem != nullptr) { - auto itFound = std::find_if( - m_vecQtPropProp.cbegin(), - m_vecQtPropProp.cend(), - [=](const QtProp_Prop& pair) { return pair.qtProp == qtProp; }); - if (itFound != m_vecQtPropProp.cend()) { - Property* prop = itFound->prop; - const char* strPropType = prop->dynTypeName(); - typedef void (*FuncSetPropertyValue)(Property*, const QVariant&); - typedef std::pair - PropType_FuncSetPropertyValue; - static const PropType_FuncSetPropertyValue arrayPair[] = { - { Property::OccColorTypeName, &Internal::setPropertyValue}, - { Property::EnumerationTypeName, &Internal::setPropertyValue }, - { Property::BoolTypeName, &Internal::setPropertyValue }, - { Property::IntTypeName, &Internal::setPropertyValue }, - { Property::DoubleTypeName, &Internal::setPropertyValue }, - { Property::QStringTypeName, &Internal::setPropertyValue } - }; - for (const PropType_FuncSetPropertyValue& pair : arrayPair) { - const char* propDynTypeName = pair.first; - const FuncSetPropertyValue funcSetPropValue = pair.second; - if (std::strcmp(strPropType, propDynTypeName) == 0) { - funcSetPropValue(prop, value); - break; - } - } - } - } -} - -void WidgetDocumentItemProps::createQtProperties( - const std::vector& properties, QtProperty *parentProp) -{ - typedef QtVariantProperty* (*FuncCreateQtProperty)( - const Property*, QtVariantPropertyManager*); - typedef std::pair - PropType_FuncCreateQtProp; - static const PropType_FuncCreateQtProp arrayPair[] = { - { Property::OccColorTypeName, &Internal::createQtProperty}, - { Property::EnumerationTypeName, &Internal::createQtProperty }, - { Property::BoolTypeName, &Internal::createQtProperty }, - { Property::IntTypeName, &Internal::createQtProperty }, - { Property::DoubleTypeName, &Internal::createQtProperty }, - { Property::QStringTypeName, &Internal::createQtProperty } - }; - for (Property* prop : properties) { - QtVariantProperty* qtProp = nullptr; - const char* strPropType = prop->dynTypeName(); - for (const PropType_FuncCreateQtProp& pair : arrayPair) { - const char* propDynTypeName = pair.first; - const FuncCreateQtProperty funcCreateQtProp = pair.second; - if (std::strcmp(strPropType, propDynTypeName) == 0) { - qtProp = funcCreateQtProp(prop, m_varPropMgr); - break; - } - } - if (qtProp != nullptr) { - parentProp->addSubProperty(qtProp); - foreach (QtBrowserItem* item, m_ui->propsBrowser_DocumentItem->items(qtProp)) - m_ui->propsBrowser_DocumentItem->setExpanded(item, false); - this->mapProperty(qtProp, prop); - } - } -} - -void WidgetDocumentItemProps::mapProperty( - QtVariantProperty *qtProp, Property *prop) -{ - const QtProp_Prop pair = { qtProp, prop }; - m_vecQtPropProp.emplace_back(std::move(pair)); -} - -} // namespace Mayo diff --git a/src/widget_document_item_props.h b/src/widget_document_item_props.h deleted file mode 100644 index f9b1a9cc..00000000 --- a/src/widget_document_item_props.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include - -class QtProperty; -class QtVariantPropertyManager; -class QtVariantProperty; - -namespace Mayo { - -class DocumentItem; -class GuiApplication; -class GpxDocumentItem; -class Property; - -class WidgetDocumentItemProps : public QWidget -{ -public: - WidgetDocumentItemProps(QWidget* parent = nullptr); - ~WidgetDocumentItemProps(); - - void setGuiApplication(GuiApplication* guiApp); - - void editDocumentItems(const std::vector& vecDocItem); - -private: - void connectPropertyValueChangeSignals(bool on); - void onQVariantPropertyValueChanged( - QtProperty *qtProp, const QVariant &value); - - void createQtProperties( - const std::vector& properties, QtProperty* parentProp); - void mapProperty(QtVariantProperty* qtProp, Property* prop); - - struct QtProp_Prop { - QtVariantProperty* qtProp; - Property* prop; - }; - - GuiApplication* m_guiApp = nullptr; - class Ui_WidgetDocumentItemProps* m_ui = nullptr; - DocumentItem* m_currentDocItem = nullptr; - GpxDocumentItem* m_currentGpxDocItem = nullptr; - - QtVariantPropertyManager* m_varPropMgr = nullptr; - std::vector m_vecQtPropProp; -}; - -} // namespace Mayo diff --git a/src/widget_gui_document_view3d.cpp b/src/widget_gui_document_view3d.cpp deleted file mode 100644 index 0d8d546c..00000000 --- a/src/widget_gui_document_view3d.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "widget_gui_document_view3d.h" - -#include "gui_document.h" -#include "widget_occ_view.h" -#include "qt_occ_view_controller.h" -#include "fougtools/qttools/gui/qwidget_utils.h" - -#include -#include - -#include - -namespace Mayo { - -namespace Internal { - -static QToolButton* createViewBtn( - QWidget* parent, const QString& imageFile, const QString& tooltip) -{ - auto btn = new QToolButton(parent); - btn->setIcon(QIcon(QString(":/images/%1.png").arg(imageFile))); - btn->setIconSize(QSize(16, 16)); - btn->setFixedSize(24, 24); - btn->setToolTip(tooltip); - return btn; -} - -static void connectViewProjBtn( - QToolButton* btn, WidgetOccView* view, V3d_TypeOfOrientation proj) -{ - QObject::connect( - btn, &QAbstractButton::clicked, - [=]{ view->occV3dView()->SetProj(proj); }); -} - -} // namespace Internal - -WidgetGuiDocumentView3d::WidgetGuiDocumentView3d(GuiDocument* guiDoc, QWidget *parent) - : QWidget(parent), - m_guiDoc(guiDoc), - m_qtOccView(new WidgetOccView(this)) -{ - new QtOccViewController(m_qtOccView); - - auto layout = new QVBoxLayout; - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(m_qtOccView); - this->setLayout(layout); - - auto btnFitAll = Internal::createViewBtn(this, "fit_all", tr("Fit All")); - auto btnViewIso = Internal::createViewBtn(this, "view_axo", tr("Isometric")); - auto btnViewBack = Internal::createViewBtn(this, "view_back", tr("Back")); - auto btnViewFront = Internal::createViewBtn(this, "view_front", tr("Front")); - auto btnViewLeft = Internal::createViewBtn(this, "view_left", tr("Left")); - auto btnViewRight = Internal::createViewBtn(this, "view_right", tr("Right")); - auto btnViewTop = Internal::createViewBtn(this, "view_top", tr("Top")); - auto btnViewBottom = Internal::createViewBtn(this, "view_bottom", tr("Bottom")); - btnFitAll->move(0, 0); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewIso, btnFitAll); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewBack, btnViewIso); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewFront, btnViewBack); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewLeft, btnViewFront); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewRight, btnViewLeft); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewTop, btnViewRight); - qtgui::QWidgetUtils::moveWidgetRightTo(btnViewBottom, btnViewTop); - - Internal::connectViewProjBtn(btnViewIso, m_qtOccView, V3d_XposYnegZpos); - Internal::connectViewProjBtn(btnViewBack, m_qtOccView, V3d_Xneg); - Internal::connectViewProjBtn(btnViewFront, m_qtOccView, V3d_Xpos); - Internal::connectViewProjBtn(btnViewLeft, m_qtOccView, V3d_Ypos); - Internal::connectViewProjBtn(btnViewRight, m_qtOccView, V3d_Yneg); - Internal::connectViewProjBtn(btnViewTop, m_qtOccView, V3d_Zpos); - Internal::connectViewProjBtn(btnViewBottom, m_qtOccView, V3d_Zneg); - QObject::connect( - btnFitAll, &QAbstractButton::clicked, - m_qtOccView, &WidgetOccView::fitAll); -} - -GuiDocument *WidgetGuiDocumentView3d::guiDocument() const -{ - return m_guiDoc; -} - -WidgetOccView *WidgetGuiDocumentView3d::widgetOccView() const -{ - return m_qtOccView; -} - -} // namespace Mayo diff --git a/src/widget_gui_document_view3d.h b/src/widget_gui_document_view3d.h deleted file mode 100644 index 121a21f9..00000000 --- a/src/widget_gui_document_view3d.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include - -namespace Mayo { - -class GuiDocument; -class WidgetOccView; - -class WidgetGuiDocumentView3d : public QWidget -{ - Q_OBJECT - -public: - WidgetGuiDocumentView3d(GuiDocument* guiDoc, QWidget* parent = nullptr); - - GuiDocument* guiDocument() const; - WidgetOccView* widgetOccView() const; - -private: - GuiDocument* m_guiDoc = nullptr; - WidgetOccView* m_qtOccView = nullptr; -}; - -} // namespace Mayo diff --git a/src/widget_message_indicator.h b/src/widget_message_indicator.h deleted file mode 100644 index cfa8e29c..00000000 --- a/src/widget_message_indicator.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include - -namespace Mayo { - -/*! Provides an auto-shading application message - * - * Use directly MessageIndicator::showMessage() instead of manually creating - * MessageIndicator.\n - * Messages are displayed at widget's bottom-left corner and during a time - * proportional to the length of the message. - */ -class WidgetMessageIndicator : public QWidget -{ - Q_OBJECT - Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity USER true) - -public: - WidgetMessageIndicator(const QString& msg, QWidget* parent = nullptr); - - qreal opacity() const; - void setOpacity(qreal value); - - void run(); - - static void showMessage(const QString& msg, QWidget* parent); - -protected: - void paintEvent(QPaintEvent*) override; - -private: - void runInternal(); - - const QString m_message; - QRectF m_messageRect; - qreal m_opacity = 1.; -}; - -} // namespace Mayo diff --git a/src/widget_occ_view.cpp b/src/widget_occ_view.cpp deleted file mode 100644 index ebad7b57..00000000 --- a/src/widget_occ_view.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#include "widget_occ_view.h" - -#include "occt_window.h" - -#if defined(Q_OS_WIN32) -# include -#endif - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#if defined(Q_OS_WIN32) -# include -#elif defined(Q_OS_MAC) && !defined(MACOSX_USE_GLX) -# include -#else -# include -# include // OpenCascade -# include -#endif - -namespace Mayo { - -WidgetOccView::WidgetOccView(QWidget *parent) - : QWidget(parent) -{ } - -WidgetOccView::WidgetOccView(const Handle_V3d_Viewer& viewer, QWidget* parent) - : QWidget(parent), - m_viewer(viewer) -{ } - -const Handle_V3d_Viewer &WidgetOccView::occV3dViewer() const -{ - return m_viewer; -} - -void WidgetOccView::setOccV3dViewer(const Handle_V3d_Viewer &viewer) -{ - Q_ASSERT(m_viewer.IsNull()); - m_viewer = viewer; -} - -const Handle_V3d_View& WidgetOccView::occV3dView() const -{ - return m_view; -} - -//! Hack for Qt 4.5.x -QPaintEngine* WidgetOccView::paintEngine() const -{ - return nullptr; -} - -//! Force a redraw of the view -void WidgetOccView::redraw() -{ - if (!m_view.IsNull()) { - if (m_needsResize) - m_view->MustBeResized(); - else - m_view->Redraw(); - } - m_needsResize = false; -} - -void WidgetOccView::fitAll() -{ - if (!m_view.IsNull()) { - m_view->ZFitAll(); - m_view->FitAll(); - } -} - -//! Reimplemented from QWidget::paintEvent() -void WidgetOccView::paintEvent(QPaintEvent* /*event*/) -{ - initialize(); - if (!m_viewer.IsNull()) - this->redraw(); -} - -/*! Reimplemented from QWidget::resizeEvent() - * - * Called when the widget needs to resize itself, but seeing as a paint event - * always follows a resize event, we'll move the work into the paint event - */ -void WidgetOccView::resizeEvent(QResizeEvent* /*event*/) -{ - m_needsResize = true; -} - -void WidgetOccView::initialize() -{ - if (!m_isInitialized) { - this->setMouseTracking(true); - - // Avoid Qt background clears to improve resizing speed - this->setAutoFillBackground(false); - this->setAttribute(Qt::WA_NoSystemBackground); - this->setAttribute(Qt::WA_PaintOnScreen); - this->setAttribute(Qt::WA_OpaquePaintEvent); - this->setAttribute(Qt::WA_NativeWindow); - - m_view = m_viewer->CreateView(); - - Handle_OcctWindow hWnd = new OcctWindow(this); - m_view->SetWindow(hWnd); - if (!hWnd->IsMapped()) - hWnd->Map(); - - m_view->SetBgGradientColors( - Quantity_Color(0.5, 0.58, 1., Quantity_TOC_RGB), - Quantity_NOC_WHITE, - Aspect_GFM_VER); - - m_view->TriedronDisplay( - Aspect_TOTP_LEFT_LOWER, - Quantity_NOC_GRAY50, - 0.075, - V3d_ZBUFFER); - - m_view->MustBeResized(); - m_isInitialized = true; - m_needsResize = true; - } -} - -} // namespace Mayo diff --git a/src/widget_occ_view.h b/src/widget_occ_view.h deleted file mode 100644 index fe879d24..00000000 --- a/src/widget_occ_view.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** Copyright (c) 2016, Fougue Ltd. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** -** 2. Redistributions in binary form must reproduce the above -** copyright notice, this list of conditions and the following -** disclaimer in the documentation and/or other materials provided -** with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -namespace Mayo { - -/*! Qt wrapper around the V3d_View class - * - * WidgetOccView does not handle input devices interaction like keyboard and mouse. - */ -class WidgetOccView : public QWidget -{ - Q_OBJECT - -public: - WidgetOccView(QWidget* parent = nullptr); - WidgetOccView(const Handle_V3d_Viewer& viewer, QWidget* parent = nullptr); - - const Handle_V3d_Viewer& occV3dViewer() const; - void setOccV3dViewer(const Handle_V3d_Viewer& viewer); - - const Handle_V3d_View& occV3dView() const; - - QPaintEngine* paintEngine() const override; - - void redraw(); - void fitAll(); - -protected: - void paintEvent(QPaintEvent* event) override; - void resizeEvent(QResizeEvent* event) override; - -private: - void initialize(); - - Handle_V3d_Viewer m_viewer; - Handle_V3d_View m_view; - bool m_isInitialized = false; - bool m_needsResize = false; -}; - -} // namespace Mayo diff --git a/tests/inputs/cube.brep b/tests/inputs/cube.brep new file mode 100644 index 00000000..f2eddd01 --- /dev/null +++ b/tests/inputs/cube.brep @@ -0,0 +1,401 @@ +DBRep_DrawableShape + +CASCADE Topology V1, (c) Matra-Datavision +Locations 1 +1 + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 +Curve2ds 36 +1 0 0 1 0 +1 0 0 1 0 +1 0 0 -1 0 +1 0 0 -1 0 +1 10 0 0 -1 +1 0 0 0 1 +1 -10 0 -0 -1 +1 0 -10 1 0 +1 0 0 1 0 +1 0 -10 -1 0 +1 0 0 0 -1 +1 0 0 0 1 +1 0 0 -0 -1 +1 0 0 -0 1 +1 0 0 1 0 +1 0 10 1 0 +1 0 10 -1 0 +1 10 0 0 -1 +1 10 0 0 1 +1 0 -10 1 0 +1 0 10 1 0 +1 0 0 0 -1 +1 10 0 0 1 +1 -10 0 -0 1 +1 0 0 0 1 +1 0 0 1 0 +1 0 0 -0 1 +1 0 0 -1 0 +1 10 0 0 1 +1 0 0 1 0 +1 -10 0 -0 1 +1 0 0 0 1 +1 0 10 1 0 +1 0 10 -1 0 +1 10 0 0 1 +1 0 10 1 0 +Curves 12 +1 0 0 0 0 0 1 +1 0 0 10 -0 1 0 +1 0 10 0 0 0 1 +1 0 0 0 -0 1 0 +1 10 0 0 0 0 1 +1 10 0 10 -0 1 0 +1 10 10 0 0 0 1 +1 10 0 0 -0 1 0 +1 0 0 0 1 0 -0 +1 0 0 10 1 0 -0 +1 0 10 0 1 0 -0 +1 0 10 10 1 0 -0 +Polygon3D 0 +PolygonOnTriangulations 24 +2 1 2 +p 0.05 1 0 10 +2 1 4 +p 0.05 1 0 10 +2 2 3 +p 0.05 1 0 10 +2 1 2 +p 0.05 1 0 10 +2 4 3 +p 0.05 1 0 10 +2 1 4 +p 0.05 1 0 10 +2 1 4 +p 0.05 1 0 10 +2 1 2 +p 0.05 1 0 10 +2 1 2 +p 0.05 1 0 10 +2 2 3 +p 0.05 1 0 10 +2 2 3 +p 0.05 1 0 10 +2 4 3 +p 0.05 1 0 10 +2 4 3 +p 0.05 1 0 10 +2 2 3 +p 0.05 1 0 10 +2 1 4 +p 0.05 1 0 10 +2 4 3 +p 0.05 1 0 10 +2 1 2 +p 0.05 1 0 10 +2 1 4 +p 0.05 1 0 10 +2 4 3 +p 0.05 1 0 10 +2 1 4 +p 0.05 1 0 10 +2 1 2 +p 0.05 1 0 10 +2 2 3 +p 0.05 1 0 10 +2 4 3 +p 0.05 1 0 10 +2 2 3 +p 0.05 1 0 10 +Surfaces 9 +1 0 0 0 1 0 -0 0 0 1 0 -1 0 +1 0 0 0 -0 1 0 0 0 1 1 0 -0 +1 0 0 0 1 0 -0 -0 -0 -1 0 -1 0 +1 0 0 0 -0 1 0 -0 -0 -1 1 0 -0 +1 0 0 10 0 0 1 1 0 -0 -0 1 0 +1 0 10 0 -0 1 0 0 0 1 1 0 -0 +1 0 0 0 0 0 1 1 0 -0 -0 1 0 +1 0 0 0 0 0 1 -1 -0 0 -0 1 0 +1 10 0 0 1 0 -0 0 0 1 0 -1 0 +Triangulations 6 +4 2 1 0 +0 0 0 0 0 10 0 10 10 0 10 0 0 0 10 0 10 -10 0 -10 2 4 3 2 1 4 +4 2 1 0 +0 0 0 10 0 0 10 0 10 0 0 10 0 0 0 10 10 10 10 0 3 2 1 3 1 4 +4 2 1 0 +0 0 10 0 10 10 10 10 10 10 0 10 0 0 0 10 10 10 10 0 3 2 1 3 1 4 +4 2 1 0 +0 10 0 10 10 0 10 10 10 0 10 10 0 0 0 10 10 10 10 0 3 2 1 3 1 4 +4 2 1 0 +0 0 0 0 10 0 10 10 0 10 0 0 0 0 0 10 10 10 10 0 3 2 1 3 1 4 +4 2 1 0 +10 0 0 10 0 10 10 10 10 10 10 0 0 0 10 0 10 -10 0 -10 2 4 3 2 1 4 + +TShapes 35 +Ve +1e-07 +0 0 10 +0 0 + +0101101 +* +Ve +1e-07 +0 0 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 1 0 0 10 +2 1 1 0 0 10 +2 2 2 0 0 10 +6 1 1 0 +6 2 2 0 +2 3 3 0 0 10 +2 4 4 0 0 10 +0 + +0101000 +-35 0 +34 0 * +Ve +1e-07 +0 10 10 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 2 0 0 10 +2 5 1 0 0 10 +2 6 5 0 0 10 +6 3 1 0 +6 4 3 0 +2 7 3 0 0 10 +0 + +0101000 +-32 0 +35 0 * +Ve +1e-07 +0 10 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 3 0 0 10 +2 8 1 0 0 10 +2 9 6 0 0 10 +6 5 1 0 +6 6 4 0 +2 10 3 0 0 10 +0 + +0101000 +-32 0 +30 0 * +Ed + 1e-07 1 1 0 +1 4 0 0 10 +2 11 1 0 0 10 +2 12 7 0 0 10 +6 7 1 0 +6 8 5 0 +2 13 3 0 0 10 +2 14 8 0 0 10 +0 + +0101000 +-30 0 +34 0 * +Wi + +0101100 +-33 0 -31 0 +29 0 +28 0 * +Fa +0 1e-07 1 0 +2 1 +0101000 ++27 0 * +Ve +1e-07 +10 0 10 +0 0 + +0101101 +* +Ve +1e-07 +10 0 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 5 0 0 10 +2 15 9 0 0 10 +2 16 2 0 0 10 +6 9 6 0 +6 10 2 0 +2 17 4 0 0 10 +0 + +0101000 +-25 0 +24 0 * +Ve +1e-07 +10 10 10 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 6 0 0 10 +2 18 9 0 0 10 +2 19 5 0 0 10 +6 11 6 0 +6 12 3 0 +0 + +0101000 +-22 0 +25 0 * +Ve +1e-07 +10 10 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 7 0 0 10 +2 20 9 0 0 10 +2 21 6 0 0 10 +6 13 6 0 +6 14 4 0 +0 + +0101000 +-22 0 +20 0 * +Ed + 1e-07 1 1 0 +1 8 0 0 10 +2 22 9 0 0 10 +2 23 7 0 0 10 +6 15 6 0 +6 16 5 0 +2 24 8 0 0 10 +0 + +0101000 +-20 0 +24 0 * +Wi + +0101100 +-23 0 -21 0 +19 0 +18 0 * +Fa +0 1e-07 9 0 +2 6 +0101000 ++17 0 * +Ed + 1e-07 1 1 0 +1 9 0 0 10 +2 25 2 0 0 10 +2 26 7 0 0 10 +6 17 2 0 +6 18 5 0 +2 27 4 0 0 10 +2 28 8 0 0 10 +0 + +0101000 +-24 0 +34 0 * +Ed + 1e-07 1 1 0 +1 10 0 0 10 +2 29 2 0 0 10 +2 30 5 0 0 10 +6 19 2 0 +6 20 3 0 +2 31 4 0 0 10 +0 + +0101000 +-25 0 +35 0 * +Wi + +0101100 +-15 0 -23 0 +14 0 +33 0 * +Fa +0 1e-07 2 0 +2 2 +0101000 ++13 0 * +Ed + 1e-07 1 1 0 +1 11 0 0 10 +2 32 6 0 0 10 +2 33 7 0 0 10 +6 21 4 0 +6 22 5 0 +2 34 8 0 0 10 +0 + +0101000 +-20 0 +30 0 * +Ed + 1e-07 1 1 0 +1 12 0 0 10 +2 35 6 0 0 10 +2 36 5 0 0 10 +6 23 4 0 +6 24 3 0 +0 + +0101000 +-22 0 +32 0 * +Wi + +0101100 +-11 0 -19 0 +10 0 +29 0 * +Fa +0 1e-07 6 0 +2 4 +0101000 ++9 0 * +Wi + +0101100 +-28 0 -11 0 +18 0 +15 0 * +Fa +0 1e-07 7 0 +2 5 +0101000 ++7 0 * +Wi + +0101100 +-31 0 -10 0 +21 0 +14 0 * +Fa +0 1e-07 5 0 +2 3 +0101000 ++5 0 * +Sh + +0101100 +-26 0 +16 0 -12 0 +8 0 -6 0 +4 0 * +So + +0100000 ++3 0 * +Co + +1100000 ++2 1 * + ++1 0 \ No newline at end of file diff --git a/tests/inputs/cube.iges b/tests/inputs/cube.iges new file mode 100644 index 00000000..11cb4b77 --- /dev/null +++ b/tests/inputs/cube.iges @@ -0,0 +1,153 @@ + S0000001 +,,31HOpen CASCADE IGES processor 7.3,13HFilename.iges, G0000001 +16HOpen CASCADE 7.3,31HOpen CASCADE IGES processor 7.3,32,308,15,308,15,G0000002 +,1.,2,2HMM,1,0.01,15H20200305.175218,1E-07,10.,,,11,0, G0000003 +15H20200305.175218,; G0000004 + 402 1 0 0 0 0 0 000000000D0000001 + 402 0 0 1 1 0D0000002 + 144 2 0 0 0 0 0 000020000D0000003 + 144 0 0 1 0 0D0000004 + 108 3 0 0 0 0 0 000010000D0000005 + 108 0 0 1 0 0D0000006 + 142 4 0 0 0 0 0 000010500D0000007 + 142 0 0 1 0 0D0000008 + 102 5 0 0 0 0 0 000010000D0000009 + 102 0 0 1 0 0D0000010 + 110 6 0 0 0 0 0 000010000D0000011 + 110 0 0 1 0 0D0000012 + 110 7 0 0 0 0 0 000010000D0000013 + 110 0 0 1 0 0D0000014 + 110 8 0 0 0 0 0 000010000D0000015 + 110 0 0 1 0 0D0000016 + 110 9 0 0 0 0 0 000010000D0000017 + 110 0 0 1 0 0D0000018 + 144 10 0 0 0 0 0 000020000D0000019 + 144 0 0 1 0 0D0000020 + 108 11 0 0 0 0 0 000010000D0000021 + 108 0 0 1 0 0D0000022 + 142 12 0 0 0 0 0 000010500D0000023 + 142 0 0 1 0 0D0000024 + 102 13 0 0 0 0 0 000010000D0000025 + 102 0 0 1 0 0D0000026 + 110 14 0 0 0 0 0 000010000D0000027 + 110 0 0 1 0 0D0000028 + 110 15 0 0 0 0 0 000010000D0000029 + 110 0 0 1 0 0D0000030 + 110 16 0 0 0 0 0 000010000D0000031 + 110 0 0 1 0 0D0000032 + 110 17 0 0 0 0 0 000010000D0000033 + 110 0 0 1 0 0D0000034 + 144 18 0 0 0 0 0 000020000D0000035 + 144 0 0 1 0 0D0000036 + 108 19 0 0 0 0 0 000010000D0000037 + 108 0 0 1 0 0D0000038 + 142 20 0 0 0 0 0 000010500D0000039 + 142 0 0 1 0 0D0000040 + 102 21 0 0 0 0 0 000010000D0000041 + 102 0 0 1 0 0D0000042 + 110 22 0 0 0 0 0 000010000D0000043 + 110 0 0 1 0 0D0000044 + 110 23 0 0 0 0 0 000010000D0000045 + 110 0 0 1 0 0D0000046 + 110 24 0 0 0 0 0 000010000D0000047 + 110 0 0 1 0 0D0000048 + 110 25 0 0 0 0 0 000010000D0000049 + 110 0 0 1 0 0D0000050 + 144 26 0 0 0 0 0 000020000D0000051 + 144 0 0 1 0 0D0000052 + 108 27 0 0 0 0 0 000010000D0000053 + 108 0 0 1 0 0D0000054 + 142 28 0 0 0 0 0 000010500D0000055 + 142 0 0 1 0 0D0000056 + 102 29 0 0 0 0 0 000010000D0000057 + 102 0 0 1 0 0D0000058 + 110 30 0 0 0 0 0 000010000D0000059 + 110 0 0 1 0 0D0000060 + 110 31 0 0 0 0 0 000010000D0000061 + 110 0 0 1 0 0D0000062 + 110 32 0 0 0 0 0 000010000D0000063 + 110 0 0 1 0 0D0000064 + 110 33 0 0 0 0 0 000010000D0000065 + 110 0 0 1 0 0D0000066 + 144 34 0 0 0 0 0 000020000D0000067 + 144 0 0 1 0 0D0000068 + 108 35 0 0 0 0 0 000010000D0000069 + 108 0 0 1 0 0D0000070 + 142 36 0 0 0 0 0 000010500D0000071 + 142 0 0 1 0 0D0000072 + 102 37 0 0 0 0 0 000010000D0000073 + 102 0 0 1 0 0D0000074 + 110 38 0 0 0 0 0 000010000D0000075 + 110 0 0 1 0 0D0000076 + 110 39 0 0 0 0 0 000010000D0000077 + 110 0 0 1 0 0D0000078 + 110 40 0 0 0 0 0 000010000D0000079 + 110 0 0 1 0 0D0000080 + 110 41 0 0 0 0 0 000010000D0000081 + 110 0 0 1 0 0D0000082 + 144 42 0 0 0 0 0 000020000D0000083 + 144 0 0 1 0 0D0000084 + 108 43 0 0 0 0 0 000010000D0000085 + 108 0 0 1 0 0D0000086 + 142 44 0 0 0 0 0 000010500D0000087 + 142 0 0 1 0 0D0000088 + 102 45 0 0 0 0 0 000010000D0000089 + 102 0 0 1 0 0D0000090 + 110 46 0 0 0 0 0 000010000D0000091 + 110 0 0 1 0 0D0000092 + 110 47 0 0 0 0 0 000010000D0000093 + 110 0 0 1 0 0D0000094 + 110 48 0 0 0 0 0 000010000D0000095 + 110 0 0 1 0 0D0000096 + 110 49 0 0 0 0 0 000010000D0000097 + 110 0 0 1 0 0D0000098 +402,6,3,19,35,51,67,83; 0000001P0000001 +144,5,1,0,7; 0000003P0000002 +108,-1.,-0.,-0.,-0.,0,0.,0.,0.,0.; 0000005P0000003 +142,0,5,0,9,2; 0000007P0000004 +102,4,11,13,15,17; 0000009P0000005 +110,0.,10.,0.,0.,0.,0.; 0000011P0000006 +110,0.,0.,0.,0.,0.,10.; 0000013P0000007 +110,0.,0.,10.,0.,10.,10.; 0000015P0000008 +110,0.,10.,10.,0.,10.,0.; 0000017P0000009 +144,21,1,0,23; 0000019P0000010 +108,1.,0.,0.,10.,0,10.,0.,0.,0.; 0000021P0000011 +142,0,21,0,25,2; 0000023P0000012 +102,4,27,29,31,33; 0000025P0000013 +110,10.,0.,10.,10.,0.,0.; 0000027P0000014 +110,10.,0.,0.,10.,10.,0.; 0000029P0000015 +110,10.,10.,0.,10.,10.,10.; 0000031P0000016 +110,10.,10.,10.,10.,0.,10.; 0000033P0000017 +144,37,1,0,39; 0000035P0000018 +108,-0.,-1.,-0.,-0.,0,0.,0.,0.,0.; 0000037P0000019 +142,0,37,0,41,2; 0000039P0000020 +102,4,43,45,47,49; 0000041P0000021 +110,0.,0.,10.,0.,0.,0.; 0000043P0000022 +110,0.,0.,0.,10.,0.,0.; 0000045P0000023 +110,10.,0.,0.,10.,0.,10.; 0000047P0000024 +110,10.,0.,10.,0.,0.,10.; 0000049P0000025 +144,53,1,0,55; 0000051P0000026 +108,0.,1.,0.,10.,0,0.,10.,0.,0.; 0000053P0000027 +142,0,53,0,57,2; 0000055P0000028 +102,4,59,61,63,65; 0000057P0000029 +110,10.,10.,0.,0.,10.,0.; 0000059P0000030 +110,0.,10.,0.,0.,10.,10.; 0000061P0000031 +110,0.,10.,10.,10.,10.,10.; 0000063P0000032 +110,10.,10.,10.,10.,10.,0.; 0000065P0000033 +144,69,1,0,71; 0000067P0000034 +108,-0.,-0.,-1.,-0.,0,0.,0.,0.,0.; 0000069P0000035 +142,0,69,0,73,2; 0000071P0000036 +102,4,75,77,79,81; 0000073P0000037 +110,10.,0.,0.,0.,0.,0.; 0000075P0000038 +110,0.,0.,0.,0.,10.,0.; 0000077P0000039 +110,0.,10.,0.,10.,10.,0.; 0000079P0000040 +110,10.,10.,0.,10.,0.,0.; 0000081P0000041 +144,85,1,0,87; 0000083P0000042 +108,0.,0.,1.,10.,0,0.,0.,10.,0.; 0000085P0000043 +142,0,85,0,89,2; 0000087P0000044 +102,4,91,93,95,97; 0000089P0000045 +110,0.,10.,10.,0.,0.,10.; 0000091P0000046 +110,0.,0.,10.,10.,0.,10.; 0000093P0000047 +110,10.,0.,10.,10.,10.,10.; 0000095P0000048 +110,10.,10.,10.,0.,10.,10.; 0000097P0000049 +S 1G 4D 98P 49 T0000001 diff --git a/tests/inputs/cube.step b/tests/inputs/cube.step new file mode 100644 index 00000000..2d3c033d --- /dev/null +++ b/tests/inputs/cube.step @@ -0,0 +1,427 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('FreeCAD Model'),'2;1'); +FILE_NAME('D:/dev/projects/fougue/mayo/tests/inputs/cube.step', + '2020-03-05T17:54:24',('Author'),(''), + 'Open CASCADE STEP processor 7.3','FreeCAD','Unknown'); +FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }')); +ENDSEC; +DATA; +#1 = APPLICATION_PROTOCOL_DEFINITION('international standard', + 'automotive_design',2000,#2); +#2 = APPLICATION_CONTEXT( + 'core data for automotive mechanical design processes'); +#3 = SHAPE_DEFINITION_REPRESENTATION(#4,#10); +#4 = PRODUCT_DEFINITION_SHAPE('','',#5); +#5 = PRODUCT_DEFINITION('design','',#6,#9); +#6 = PRODUCT_DEFINITION_FORMATION('','',#7); +#7 = PRODUCT('Cube','Cube','',(#8)); +#8 = PRODUCT_CONTEXT('',#2,'mechanical'); +#9 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design'); +#10 = ADVANCED_BREP_SHAPE_REPRESENTATION('',(#11,#15),#345); +#11 = AXIS2_PLACEMENT_3D('',#12,#13,#14); +#12 = CARTESIAN_POINT('',(0.,0.,0.)); +#13 = DIRECTION('',(0.,0.,1.)); +#14 = DIRECTION('',(1.,0.,-0.)); +#15 = MANIFOLD_SOLID_BREP('',#16); +#16 = CLOSED_SHELL('',(#17,#137,#237,#284,#331,#338)); +#17 = ADVANCED_FACE('',(#18),#32,.F.); +#18 = FACE_BOUND('',#19,.F.); +#19 = EDGE_LOOP('',(#20,#55,#83,#111)); +#20 = ORIENTED_EDGE('',*,*,#21,.F.); +#21 = EDGE_CURVE('',#22,#24,#26,.T.); +#22 = VERTEX_POINT('',#23); +#23 = CARTESIAN_POINT('',(0.,0.,0.)); +#24 = VERTEX_POINT('',#25); +#25 = CARTESIAN_POINT('',(0.,0.,10.)); +#26 = SURFACE_CURVE('',#27,(#31,#43),.PCURVE_S1.); +#27 = LINE('',#28,#29); +#28 = CARTESIAN_POINT('',(0.,0.,0.)); +#29 = VECTOR('',#30,1.); +#30 = DIRECTION('',(0.,0.,1.)); +#31 = PCURVE('',#32,#37); +#32 = PLANE('',#33); +#33 = AXIS2_PLACEMENT_3D('',#34,#35,#36); +#34 = CARTESIAN_POINT('',(0.,0.,0.)); +#35 = DIRECTION('',(1.,0.,0.)); +#36 = DIRECTION('',(0.,0.,1.)); +#37 = DEFINITIONAL_REPRESENTATION('',(#38),#42); +#38 = LINE('',#39,#40); +#39 = CARTESIAN_POINT('',(0.,0.)); +#40 = VECTOR('',#41,1.); +#41 = DIRECTION('',(1.,0.)); +#42 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#43 = PCURVE('',#44,#49); +#44 = PLANE('',#45); +#45 = AXIS2_PLACEMENT_3D('',#46,#47,#48); +#46 = CARTESIAN_POINT('',(0.,0.,0.)); +#47 = DIRECTION('',(0.,1.,0.)); +#48 = DIRECTION('',(0.,0.,1.)); +#49 = DEFINITIONAL_REPRESENTATION('',(#50),#54); +#50 = LINE('',#51,#52); +#51 = CARTESIAN_POINT('',(0.,0.)); +#52 = VECTOR('',#53,1.); +#53 = DIRECTION('',(1.,0.)); +#54 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#55 = ORIENTED_EDGE('',*,*,#56,.T.); +#56 = EDGE_CURVE('',#22,#57,#59,.T.); +#57 = VERTEX_POINT('',#58); +#58 = CARTESIAN_POINT('',(0.,10.,0.)); +#59 = SURFACE_CURVE('',#60,(#64,#71),.PCURVE_S1.); +#60 = LINE('',#61,#62); +#61 = CARTESIAN_POINT('',(0.,0.,0.)); +#62 = VECTOR('',#63,1.); +#63 = DIRECTION('',(0.,1.,0.)); +#64 = PCURVE('',#32,#65); +#65 = DEFINITIONAL_REPRESENTATION('',(#66),#70); +#66 = LINE('',#67,#68); +#67 = CARTESIAN_POINT('',(0.,0.)); +#68 = VECTOR('',#69,1.); +#69 = DIRECTION('',(0.,-1.)); +#70 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#71 = PCURVE('',#72,#77); +#72 = PLANE('',#73); +#73 = AXIS2_PLACEMENT_3D('',#74,#75,#76); +#74 = CARTESIAN_POINT('',(0.,0.,0.)); +#75 = DIRECTION('',(0.,0.,1.)); +#76 = DIRECTION('',(1.,0.,0.)); +#77 = DEFINITIONAL_REPRESENTATION('',(#78),#82); +#78 = LINE('',#79,#80); +#79 = CARTESIAN_POINT('',(0.,0.)); +#80 = VECTOR('',#81,1.); +#81 = DIRECTION('',(0.,1.)); +#82 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#83 = ORIENTED_EDGE('',*,*,#84,.T.); +#84 = EDGE_CURVE('',#57,#85,#87,.T.); +#85 = VERTEX_POINT('',#86); +#86 = CARTESIAN_POINT('',(0.,10.,10.)); +#87 = SURFACE_CURVE('',#88,(#92,#99),.PCURVE_S1.); +#88 = LINE('',#89,#90); +#89 = CARTESIAN_POINT('',(0.,10.,0.)); +#90 = VECTOR('',#91,1.); +#91 = DIRECTION('',(0.,0.,1.)); +#92 = PCURVE('',#32,#93); +#93 = DEFINITIONAL_REPRESENTATION('',(#94),#98); +#94 = LINE('',#95,#96); +#95 = CARTESIAN_POINT('',(0.,-10.)); +#96 = VECTOR('',#97,1.); +#97 = DIRECTION('',(1.,0.)); +#98 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#99 = PCURVE('',#100,#105); +#100 = PLANE('',#101); +#101 = AXIS2_PLACEMENT_3D('',#102,#103,#104); +#102 = CARTESIAN_POINT('',(0.,10.,0.)); +#103 = DIRECTION('',(0.,1.,0.)); +#104 = DIRECTION('',(0.,0.,1.)); +#105 = DEFINITIONAL_REPRESENTATION('',(#106),#110); +#106 = LINE('',#107,#108); +#107 = CARTESIAN_POINT('',(0.,0.)); +#108 = VECTOR('',#109,1.); +#109 = DIRECTION('',(1.,0.)); +#110 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#111 = ORIENTED_EDGE('',*,*,#112,.F.); +#112 = EDGE_CURVE('',#24,#85,#113,.T.); +#113 = SURFACE_CURVE('',#114,(#118,#125),.PCURVE_S1.); +#114 = LINE('',#115,#116); +#115 = CARTESIAN_POINT('',(0.,0.,10.)); +#116 = VECTOR('',#117,1.); +#117 = DIRECTION('',(0.,1.,0.)); +#118 = PCURVE('',#32,#119); +#119 = DEFINITIONAL_REPRESENTATION('',(#120),#124); +#120 = LINE('',#121,#122); +#121 = CARTESIAN_POINT('',(10.,0.)); +#122 = VECTOR('',#123,1.); +#123 = DIRECTION('',(0.,-1.)); +#124 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#125 = PCURVE('',#126,#131); +#126 = PLANE('',#127); +#127 = AXIS2_PLACEMENT_3D('',#128,#129,#130); +#128 = CARTESIAN_POINT('',(0.,0.,10.)); +#129 = DIRECTION('',(0.,0.,1.)); +#130 = DIRECTION('',(1.,0.,0.)); +#131 = DEFINITIONAL_REPRESENTATION('',(#132),#136); +#132 = LINE('',#133,#134); +#133 = CARTESIAN_POINT('',(0.,0.)); +#134 = VECTOR('',#135,1.); +#135 = DIRECTION('',(0.,1.)); +#136 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#137 = ADVANCED_FACE('',(#138),#152,.T.); +#138 = FACE_BOUND('',#139,.T.); +#139 = EDGE_LOOP('',(#140,#170,#193,#216)); +#140 = ORIENTED_EDGE('',*,*,#141,.F.); +#141 = EDGE_CURVE('',#142,#144,#146,.T.); +#142 = VERTEX_POINT('',#143); +#143 = CARTESIAN_POINT('',(10.,0.,0.)); +#144 = VERTEX_POINT('',#145); +#145 = CARTESIAN_POINT('',(10.,0.,10.)); +#146 = SURFACE_CURVE('',#147,(#151,#163),.PCURVE_S1.); +#147 = LINE('',#148,#149); +#148 = CARTESIAN_POINT('',(10.,0.,0.)); +#149 = VECTOR('',#150,1.); +#150 = DIRECTION('',(0.,0.,1.)); +#151 = PCURVE('',#152,#157); +#152 = PLANE('',#153); +#153 = AXIS2_PLACEMENT_3D('',#154,#155,#156); +#154 = CARTESIAN_POINT('',(10.,0.,0.)); +#155 = DIRECTION('',(1.,0.,0.)); +#156 = DIRECTION('',(0.,0.,1.)); +#157 = DEFINITIONAL_REPRESENTATION('',(#158),#162); +#158 = LINE('',#159,#160); +#159 = CARTESIAN_POINT('',(0.,0.)); +#160 = VECTOR('',#161,1.); +#161 = DIRECTION('',(1.,0.)); +#162 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#163 = PCURVE('',#44,#164); +#164 = DEFINITIONAL_REPRESENTATION('',(#165),#169); +#165 = LINE('',#166,#167); +#166 = CARTESIAN_POINT('',(0.,10.)); +#167 = VECTOR('',#168,1.); +#168 = DIRECTION('',(1.,0.)); +#169 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#170 = ORIENTED_EDGE('',*,*,#171,.T.); +#171 = EDGE_CURVE('',#142,#172,#174,.T.); +#172 = VERTEX_POINT('',#173); +#173 = CARTESIAN_POINT('',(10.,10.,0.)); +#174 = SURFACE_CURVE('',#175,(#179,#186),.PCURVE_S1.); +#175 = LINE('',#176,#177); +#176 = CARTESIAN_POINT('',(10.,0.,0.)); +#177 = VECTOR('',#178,1.); +#178 = DIRECTION('',(0.,1.,0.)); +#179 = PCURVE('',#152,#180); +#180 = DEFINITIONAL_REPRESENTATION('',(#181),#185); +#181 = LINE('',#182,#183); +#182 = CARTESIAN_POINT('',(0.,0.)); +#183 = VECTOR('',#184,1.); +#184 = DIRECTION('',(0.,-1.)); +#185 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#186 = PCURVE('',#72,#187); +#187 = DEFINITIONAL_REPRESENTATION('',(#188),#192); +#188 = LINE('',#189,#190); +#189 = CARTESIAN_POINT('',(10.,0.)); +#190 = VECTOR('',#191,1.); +#191 = DIRECTION('',(0.,1.)); +#192 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#193 = ORIENTED_EDGE('',*,*,#194,.T.); +#194 = EDGE_CURVE('',#172,#195,#197,.T.); +#195 = VERTEX_POINT('',#196); +#196 = CARTESIAN_POINT('',(10.,10.,10.)); +#197 = SURFACE_CURVE('',#198,(#202,#209),.PCURVE_S1.); +#198 = LINE('',#199,#200); +#199 = CARTESIAN_POINT('',(10.,10.,0.)); +#200 = VECTOR('',#201,1.); +#201 = DIRECTION('',(0.,0.,1.)); +#202 = PCURVE('',#152,#203); +#203 = DEFINITIONAL_REPRESENTATION('',(#204),#208); +#204 = LINE('',#205,#206); +#205 = CARTESIAN_POINT('',(0.,-10.)); +#206 = VECTOR('',#207,1.); +#207 = DIRECTION('',(1.,0.)); +#208 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#209 = PCURVE('',#100,#210); +#210 = DEFINITIONAL_REPRESENTATION('',(#211),#215); +#211 = LINE('',#212,#213); +#212 = CARTESIAN_POINT('',(0.,10.)); +#213 = VECTOR('',#214,1.); +#214 = DIRECTION('',(1.,0.)); +#215 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#216 = ORIENTED_EDGE('',*,*,#217,.F.); +#217 = EDGE_CURVE('',#144,#195,#218,.T.); +#218 = SURFACE_CURVE('',#219,(#223,#230),.PCURVE_S1.); +#219 = LINE('',#220,#221); +#220 = CARTESIAN_POINT('',(10.,0.,10.)); +#221 = VECTOR('',#222,1.); +#222 = DIRECTION('',(0.,1.,0.)); +#223 = PCURVE('',#152,#224); +#224 = DEFINITIONAL_REPRESENTATION('',(#225),#229); +#225 = LINE('',#226,#227); +#226 = CARTESIAN_POINT('',(10.,0.)); +#227 = VECTOR('',#228,1.); +#228 = DIRECTION('',(0.,-1.)); +#229 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#230 = PCURVE('',#126,#231); +#231 = DEFINITIONAL_REPRESENTATION('',(#232),#236); +#232 = LINE('',#233,#234); +#233 = CARTESIAN_POINT('',(10.,0.)); +#234 = VECTOR('',#235,1.); +#235 = DIRECTION('',(0.,1.)); +#236 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#237 = ADVANCED_FACE('',(#238),#44,.F.); +#238 = FACE_BOUND('',#239,.F.); +#239 = EDGE_LOOP('',(#240,#261,#262,#283)); +#240 = ORIENTED_EDGE('',*,*,#241,.F.); +#241 = EDGE_CURVE('',#22,#142,#242,.T.); +#242 = SURFACE_CURVE('',#243,(#247,#254),.PCURVE_S1.); +#243 = LINE('',#244,#245); +#244 = CARTESIAN_POINT('',(0.,0.,0.)); +#245 = VECTOR('',#246,1.); +#246 = DIRECTION('',(1.,0.,0.)); +#247 = PCURVE('',#44,#248); +#248 = DEFINITIONAL_REPRESENTATION('',(#249),#253); +#249 = LINE('',#250,#251); +#250 = CARTESIAN_POINT('',(0.,0.)); +#251 = VECTOR('',#252,1.); +#252 = DIRECTION('',(0.,1.)); +#253 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#254 = PCURVE('',#72,#255); +#255 = DEFINITIONAL_REPRESENTATION('',(#256),#260); +#256 = LINE('',#257,#258); +#257 = CARTESIAN_POINT('',(0.,0.)); +#258 = VECTOR('',#259,1.); +#259 = DIRECTION('',(1.,0.)); +#260 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#261 = ORIENTED_EDGE('',*,*,#21,.T.); +#262 = ORIENTED_EDGE('',*,*,#263,.T.); +#263 = EDGE_CURVE('',#24,#144,#264,.T.); +#264 = SURFACE_CURVE('',#265,(#269,#276),.PCURVE_S1.); +#265 = LINE('',#266,#267); +#266 = CARTESIAN_POINT('',(0.,0.,10.)); +#267 = VECTOR('',#268,1.); +#268 = DIRECTION('',(1.,0.,0.)); +#269 = PCURVE('',#44,#270); +#270 = DEFINITIONAL_REPRESENTATION('',(#271),#275); +#271 = LINE('',#272,#273); +#272 = CARTESIAN_POINT('',(10.,0.)); +#273 = VECTOR('',#274,1.); +#274 = DIRECTION('',(0.,1.)); +#275 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#276 = PCURVE('',#126,#277); +#277 = DEFINITIONAL_REPRESENTATION('',(#278),#282); +#278 = LINE('',#279,#280); +#279 = CARTESIAN_POINT('',(0.,0.)); +#280 = VECTOR('',#281,1.); +#281 = DIRECTION('',(1.,0.)); +#282 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#283 = ORIENTED_EDGE('',*,*,#141,.F.); +#284 = ADVANCED_FACE('',(#285),#100,.T.); +#285 = FACE_BOUND('',#286,.T.); +#286 = EDGE_LOOP('',(#287,#308,#309,#330)); +#287 = ORIENTED_EDGE('',*,*,#288,.F.); +#288 = EDGE_CURVE('',#57,#172,#289,.T.); +#289 = SURFACE_CURVE('',#290,(#294,#301),.PCURVE_S1.); +#290 = LINE('',#291,#292); +#291 = CARTESIAN_POINT('',(0.,10.,0.)); +#292 = VECTOR('',#293,1.); +#293 = DIRECTION('',(1.,0.,0.)); +#294 = PCURVE('',#100,#295); +#295 = DEFINITIONAL_REPRESENTATION('',(#296),#300); +#296 = LINE('',#297,#298); +#297 = CARTESIAN_POINT('',(0.,0.)); +#298 = VECTOR('',#299,1.); +#299 = DIRECTION('',(0.,1.)); +#300 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#301 = PCURVE('',#72,#302); +#302 = DEFINITIONAL_REPRESENTATION('',(#303),#307); +#303 = LINE('',#304,#305); +#304 = CARTESIAN_POINT('',(0.,10.)); +#305 = VECTOR('',#306,1.); +#306 = DIRECTION('',(1.,0.)); +#307 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#308 = ORIENTED_EDGE('',*,*,#84,.T.); +#309 = ORIENTED_EDGE('',*,*,#310,.T.); +#310 = EDGE_CURVE('',#85,#195,#311,.T.); +#311 = SURFACE_CURVE('',#312,(#316,#323),.PCURVE_S1.); +#312 = LINE('',#313,#314); +#313 = CARTESIAN_POINT('',(0.,10.,10.)); +#314 = VECTOR('',#315,1.); +#315 = DIRECTION('',(1.,0.,0.)); +#316 = PCURVE('',#100,#317); +#317 = DEFINITIONAL_REPRESENTATION('',(#318),#322); +#318 = LINE('',#319,#320); +#319 = CARTESIAN_POINT('',(10.,0.)); +#320 = VECTOR('',#321,1.); +#321 = DIRECTION('',(0.,1.)); +#322 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#323 = PCURVE('',#126,#324); +#324 = DEFINITIONAL_REPRESENTATION('',(#325),#329); +#325 = LINE('',#326,#327); +#326 = CARTESIAN_POINT('',(0.,10.)); +#327 = VECTOR('',#328,1.); +#328 = DIRECTION('',(1.,0.)); +#329 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) +PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' + ) ); +#330 = ORIENTED_EDGE('',*,*,#194,.F.); +#331 = ADVANCED_FACE('',(#332),#72,.F.); +#332 = FACE_BOUND('',#333,.F.); +#333 = EDGE_LOOP('',(#334,#335,#336,#337)); +#334 = ORIENTED_EDGE('',*,*,#56,.F.); +#335 = ORIENTED_EDGE('',*,*,#241,.T.); +#336 = ORIENTED_EDGE('',*,*,#171,.T.); +#337 = ORIENTED_EDGE('',*,*,#288,.F.); +#338 = ADVANCED_FACE('',(#339),#126,.T.); +#339 = FACE_BOUND('',#340,.T.); +#340 = EDGE_LOOP('',(#341,#342,#343,#344)); +#341 = ORIENTED_EDGE('',*,*,#112,.F.); +#342 = ORIENTED_EDGE('',*,*,#263,.T.); +#343 = ORIENTED_EDGE('',*,*,#217,.T.); +#344 = ORIENTED_EDGE('',*,*,#310,.F.); +#345 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#349)) GLOBAL_UNIT_ASSIGNED_CONTEXT +((#346,#347,#348)) REPRESENTATION_CONTEXT('Context #1', + '3D Context with UNIT and UNCERTAINTY') ); +#346 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); +#347 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); +#348 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() ); +#349 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#346, + 'distance_accuracy_value','confusion accuracy'); +#350 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#7)); +#351 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#352) + ,#345); +#352 = STYLED_ITEM('color',(#353),#15); +#353 = PRESENTATION_STYLE_ASSIGNMENT((#354,#360)); +#354 = SURFACE_STYLE_USAGE(.BOTH.,#355); +#355 = SURFACE_SIDE_STYLE('',(#356)); +#356 = SURFACE_STYLE_FILL_AREA(#357); +#357 = FILL_AREA_STYLE('',(#358)); +#358 = FILL_AREA_STYLE_COLOUR('',#359); +#359 = COLOUR_RGB('',0.800000011921,0.800000011921,0.800000011921); +#360 = CURVE_STYLE('',#361,POSITIVE_LENGTH_MEASURE(0.1),#359); +#361 = DRAUGHTING_PRE_DEFINED_CURVE_FONT('continuous'); +ENDSEC; +END-ISO-10303-21; diff --git a/tests/inputs/cube.stla b/tests/inputs/cube.stla new file mode 100644 index 00000000..d79d1d97 --- /dev/null +++ b/tests/inputs/cube.stla @@ -0,0 +1,86 @@ +solid Mesh + facet normal -1.000000 0.000000 0.000000 + outer loop + vertex 0.000000 10.000000 0.000000 + vertex 0.000000 0.000000 10.000000 + vertex 0.000000 10.000000 10.000000 + endloop + endfacet + facet normal -1.000000 0.000000 0.000000 + outer loop + vertex 0.000000 0.000000 0.000000 + vertex 0.000000 0.000000 10.000000 + vertex 0.000000 10.000000 0.000000 + endloop + endfacet + facet normal 1.000000 -0.000000 0.000000 + outer loop + vertex 10.000000 0.000000 10.000000 + vertex 10.000000 10.000000 0.000000 + vertex 10.000000 10.000000 10.000000 + endloop + endfacet + facet normal 1.000000 0.000000 0.000000 + outer loop + vertex 10.000000 0.000000 10.000000 + vertex 10.000000 0.000000 0.000000 + vertex 10.000000 10.000000 0.000000 + endloop + endfacet + facet normal 0.000000 -1.000000 0.000000 + outer loop + vertex 10.000000 0.000000 0.000000 + vertex 10.000000 0.000000 10.000000 + vertex 0.000000 0.000000 0.000000 + endloop + endfacet + facet normal 0.000000 -1.000000 0.000000 + outer loop + vertex 0.000000 0.000000 0.000000 + vertex 10.000000 0.000000 10.000000 + vertex 0.000000 0.000000 10.000000 + endloop + endfacet + facet normal 0.000000 1.000000 0.000000 + outer loop + vertex 10.000000 10.000000 10.000000 + vertex 10.000000 10.000000 0.000000 + vertex 0.000000 10.000000 0.000000 + endloop + endfacet + facet normal 0.000000 1.000000 0.000000 + outer loop + vertex 10.000000 10.000000 10.000000 + vertex 0.000000 10.000000 0.000000 + vertex 0.000000 10.000000 10.000000 + endloop + endfacet + facet normal 0.000000 0.000000 -1.000000 + outer loop + vertex 0.000000 10.000000 0.000000 + vertex 10.000000 10.000000 0.000000 + vertex 0.000000 0.000000 0.000000 + endloop + endfacet + facet normal 0.000000 0.000000 -1.000000 + outer loop + vertex 0.000000 0.000000 0.000000 + vertex 10.000000 10.000000 0.000000 + vertex 10.000000 0.000000 0.000000 + endloop + endfacet + facet normal 0.000000 0.000000 1.000000 + outer loop + vertex 10.000000 10.000000 10.000000 + vertex 0.000000 10.000000 10.000000 + vertex 0.000000 0.000000 10.000000 + endloop + endfacet + facet normal 0.000000 0.000000 1.000000 + outer loop + vertex 10.000000 10.000000 10.000000 + vertex 0.000000 0.000000 10.000000 + vertex 10.000000 0.000000 10.000000 + endloop + endfacet +endsolid Mesh diff --git a/tests/inputs/cube.stlb b/tests/inputs/cube.stlb new file mode 100644 index 00000000..0cbcbf64 Binary files /dev/null and b/tests/inputs/cube.stlb differ diff --git a/tests/inputs/mayo_bezier_curve.brep b/tests/inputs/mayo_bezier_curve.brep new file mode 100644 index 00000000..e26b412e --- /dev/null +++ b/tests/inputs/mayo_bezier_curve.brep @@ -0,0 +1,58 @@ +DBRep_DrawableShape + +CASCADE Topology V1, (c) Matra-Datavision +Locations 3 +1 + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 +1 + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 +2 2 -1 0 +Curve2ds 0 +Curves 1 +6 0 25 -2.0687007904052734 -0.80712473392486572 0 -1.4959026575088501 0.082842633128166199 0 -0.41184672713279724 -0.27219754457473755 0 0.39291119575500488 -1.4509309530258179 0 1.5953140258789063 -0.60356831550598145 0 2.4900152683258057 0.76451992988586426 0 1.3680884838104248 1.4083260297775269 0 0.94203990697860718 0.33847159147262573 0 1.1077251434326172 0.082842633128166199 0 -0.099411211907863617 0.71718114614486694 0 0.58700001239776611 0.0071008182130753994 0 0.7621530294418335 -0.1633184552192688 0 0.64380604028701782 -0.22959263622760773 0 0.33610466122627258 -0.20592336356639862 0 -0.047338664531707764 0.1349153071641922 0 -0.089943453669548035 0.47101995348930359 0 0.10414533317089081 0.51835876703262329 0 0.47812077403068542 0.40474590659141541 0 1.041451096534729 0.73138278722763062 0 0.68641096353530884 1.4177937507629395 0 -0.71481424570083618 1.3041808605194092 0 -1.9456202983856201 1.0532858371734619 0 -1.8982815742492676 0.93020522594451904 0 -2.2059831619262695 0.3526732325553894 0 -2.1349751949310303 -0.11597978323698044 0 -2.0687007904052734 -0.80712473392486572 0 +Polygon3D 1 +38 1 +0.0094634740309418 +-2.06870079040527 -0.807124733924866 0 -1.90005549761968 -0.610394129339076 0 -1.70686092691924 -0.487673153736095 0 -1.47064089123253 -0.419023952523794 0 -1.16489804630405 -0.400466589608717 0 -0.536382336309022 -0.438902127198381 0 -0.0696395210492073 -0.441639561135149 0 0.332050339464453 -0.387050681564336 0 0.685230930137593 -0.272192265708521 0 0.957246463060909 -0.11544906253628 0 1.13586566883071 0.0580557571728849 0 1.20681951898441 0.197661406615419 0 1.20845551546763 0.280973435928377 0 1.18521771643738 0.325419014306279 0 1.14498852859531 0.355128302356871 0 1.09305460229748 0.369694392138216 0 0.985505128529617 0.363888257520818 0 0.860224501541349 0.322102730497713 0 0.486785516290164 0.0968415068229779 0 0.430630764550592 0.0887829783913383 0 0.380870459340077 0.103885251434166 0 0.332622148646904 0.148646168793751 0 0.296600097570417 0.219507235902828 0 0.230703526541551 0.561648615718651 0 0.195705778909868 0.645101079952272 0 0.143126442726032 0.718547291003469 0 -0.00435277015665525 0.829547744792665 0 -0.263849828629593 0.91944986533804 0 -0.63324506257492 0.957627538996884 0 -1.01573517883606 0.92751156252314 0 -1.37044259948788 0.835411446233525 0 -1.64945142884323 0.698305420314643 0 -1.84818650597347 0.53201299983694 0 -1.98156575610781 0.340667258067797 0 -2.07007611306771 0.08905112193678 0 -2.10410538659182 -0.231865377566014 0 -2.09571544950805 -0.504412517393006 0 -2.06869632028975 -0.807124677347019 0 +0 0.0106921518302642 0.0213843036605283 0.0333415263684115 0.0478671007668153 0.0766195642103649 0.0987345336052508 0.119930876448168 0.14245644889711 0.165999013816123 0.191308047826501 0.215142594336451 0.234047732609994 0.248226586315152 0.262813884365725 0.277401182416298 0.303241154702111 0.33231665857931 0.452355871087589 0.478449801902551 0.504130143914096 0.533485816080929 0.562841488247761 0.657645960782706 0.678202146491684 0.696694433398317 0.727247044294359 0.76000649572603 0.793412508477636 0.822920879648799 0.85011079383878 0.874192168563958 0.895668198549463 0.915731037128055 0.938083086593203 0.962714328032834 0.981357164016417 1 +PolygonOnTriangulations 0 +Surfaces 0 +Triangulations 0 + +TShapes 5 +Ve +1e-07 +-2.06870079040527 -0.807124733924866 0 +0 0 + +0101101 +* +Ve +1e-07 +-2.06869632028975 -0.807124677347019 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 1 0 0 1 +5 1 3 +0 + +0101000 ++5 0 -4 0 * +Wi + +0101000 ++3 0 * +Co + +1100000 ++2 1 * + ++1 0 \ No newline at end of file diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 00000000..c277a45e --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,21 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#include "test.h" + +#include +#include + +int main(int argc, char** argv) +{ + int retcode = 0; + std::vector> vecTest; + vecTest.emplace_back(new Mayo::Test); + for (const std::unique_ptr& test : vecTest) + retcode += QTest::qExec(test.get(), argc, argv); + + return retcode; +} diff --git a/tests/mayo_tests.pro b/tests/mayo_tests.pro new file mode 100644 index 00000000..1b31a9a0 --- /dev/null +++ b/tests/mayo_tests.pro @@ -0,0 +1,38 @@ +TARGET = mayo_tests +TEMPLATE = app + +CONFIG += c++17 no_batch + +QT += testlib + +*msvc*:QMAKE_CXXFLAGS += /std:c++17 +*g++*:QMAKE_CXXFLAGS += -std=c++17 + +INCLUDEPATH += \ + ../src/3rdparty + +HEADERS += \ + test.h \ + $$files(../src/base/*.h) \ + +SOURCES += \ + test.cpp \ + main.cpp \ + \ + ../src/3rdparty/fougtools/occtools/qt_utils.cpp \ + $$files(../src/base/*.cpp) \ + +include(../src/3rdparty/fougtools/qttools/task/qttools_task.pri) + +CONFIG += file_copies +COPIES += MayoInputs +MayoInputs.files = $$files(inputs/*.*) +MayoInputs.path = $$OUT_PWD/inputs + +# OpenCascade +include(../opencascade.pri) + +LIBS += -lTKernel -lTKMath -lTKBRep -lTKGeomBase -lTKTopAlgo -lTKPrim -lTKMesh -lTKG3d +LIBS += -lTKXSBase -lTKIGES -lTKSTEP -lTKXDESTEP -lTKXDEIGES +LIBS += -lTKLCAF -lTKXCAF -lTKCAF +LIBS += -lTKSTL diff --git a/tests/test.cpp b/tests/test.cpp new file mode 100644 index 00000000..812e9e3e --- /dev/null +++ b/tests/test.cpp @@ -0,0 +1,432 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +// Need to include this first because of MSVC conflicts with M_E, M_LOG2, ... +#include + +#include "test.h" +#include "../src/base/application.h" +#include "../src/base/brep_utils.h" +#include "../src/base/libtree.h" +#include "../src/base/geom_utils.h" +#include "../src/base/mesh_utils.h" +#include "../src/base/result.h" +#include "../src/base/string_utils.h" +#include "../src/base/unit.h" +#include "../src/base/unit_system.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(Mayo::UnitSystem::TranslateResult) +// For Application_test() +Q_DECLARE_METATYPE(Mayo::Application::PartFormat) +// For MeshUtils_orientation_test() +Q_DECLARE_METATYPE(std::vector) +Q_DECLARE_METATYPE(Mayo::MeshUtils::Orientation) + +namespace Mayo { + +// For the sake of QCOMPARE() +static bool operator==( + const UnitSystem::TranslateResult& lhs, + const UnitSystem::TranslateResult& rhs) +{ + return std::abs(lhs.value - rhs.value) < 1e-6 + && std::strcmp(lhs.strUnit, rhs.strUnit) == 0 + && std::abs(lhs.factor - rhs.factor) < 1e-6; +} + +void Test::Application_test() +{ + QFETCH(QString, filePath); + QFETCH(Application::PartFormat, expectedPartFormat); + + QCOMPARE(Application::findPartFormat(filePath), expectedPartFormat); +} + +void Test::Application_test_data() +{ + QTest::addColumn("filePath"); + QTest::addColumn("expectedPartFormat"); + + QTest::newRow("cube.step") << "inputs/cube.step" << Application::PartFormat::Step; + QTest::newRow("cube.iges") << "inputs/cube.iges" << Application::PartFormat::Iges; + QTest::newRow("cube.brep") << "inputs/cube.brep" << Application::PartFormat::OccBrep; + QTest::newRow("bezier_curve.brep") << "inputs/mayo_bezier_curve.brep" << Application::PartFormat::OccBrep; + QTest::newRow("cube.stla") << "inputs/cube.stla" << Application::PartFormat::Stl; + QTest::newRow("cube.stlb") << "inputs/cube.stlb" << Application::PartFormat::Stl; +} + +void Test::BRepUtils_test() +{ + QVERIFY(BRepUtils::moreComplex(TopAbs_COMPOUND, TopAbs_SOLID)); + QVERIFY(BRepUtils::moreComplex(TopAbs_SOLID, TopAbs_SHELL)); + QVERIFY(BRepUtils::moreComplex(TopAbs_SHELL, TopAbs_FACE)); + QVERIFY(BRepUtils::moreComplex(TopAbs_FACE, TopAbs_EDGE)); + QVERIFY(BRepUtils::moreComplex(TopAbs_EDGE, TopAbs_VERTEX)); + + { + const TopoDS_Shape shapeNull; + const TopoDS_Shape shapeBase = BRepPrimAPI_MakeBox(25, 25, 25); + const TopoDS_Shape shapeCopy = shapeBase; + QCOMPARE(BRepUtils::hashCode(shapeNull), -1); + QVERIFY(BRepUtils::hashCode(shapeBase) >= 0); + QCOMPARE(BRepUtils::hashCode(shapeBase), BRepUtils::hashCode(shapeCopy)); + } +} + +void Test::CafUtils_test() +{ + // TODO Add CafUtils::labelTag() test for multi-threaded safety +} + +void Test::MeshUtils_orientation_test() +{ + struct BasicPolyline2d : public Mayo::MeshUtils::AdaptorPolyline2d { + gp_Pnt2d pointAt(int index) const override { return this->vecPoint.at(index); } + int pointCount() const override { return this->vecPoint.size(); } + std::vector vecPoint; + }; + + QFETCH(std::vector, vecPoint); + QFETCH(Mayo::MeshUtils::Orientation, orientation); + BasicPolyline2d polyline2d; + polyline2d.vecPoint = std::move(vecPoint); + QCOMPARE(Mayo::MeshUtils::orientation(polyline2d), orientation); +} + +void Test::MeshUtils_orientation_test_data() +{ + QTest::addColumn>("vecPoint"); + QTest::addColumn("orientation"); + + std::vector vecPoint; + vecPoint.push_back(gp_Pnt2d(0, 0)); + vecPoint.push_back(gp_Pnt2d(0, 10)); + vecPoint.push_back(gp_Pnt2d(10, 10)); + vecPoint.push_back(gp_Pnt2d(10, 0)); + vecPoint.push_back(gp_Pnt2d(0, 0)); // Closed polyline + QTest::newRow("case1") << vecPoint << Mayo::MeshUtils::Orientation::Clockwise; + + vecPoint.erase(std::prev(vecPoint.end())); // Open polyline + QTest::newRow("case2") << vecPoint << Mayo::MeshUtils::Orientation::Clockwise; + + std::reverse(vecPoint.begin(), vecPoint.end()); + QTest::newRow("case3") << vecPoint << Mayo::MeshUtils::Orientation::CounterClockwise; + + vecPoint.clear(); + vecPoint.push_back(gp_Pnt2d(0, 0)); + vecPoint.push_back(gp_Pnt2d(0, 10)); + vecPoint.push_back(gp_Pnt2d(10, 10)); + QTest::newRow("case4") << vecPoint << Mayo::MeshUtils::Orientation::Clockwise; + + vecPoint.clear(); + vecPoint.push_back(gp_Pnt2d(0, 0)); + vecPoint.push_back(gp_Pnt2d(0, 10)); + vecPoint.push_back(gp_Pnt2d(-10, 10)); + vecPoint.push_back(gp_Pnt2d(-10, 0)); + QTest::newRow("case5") << vecPoint << Mayo::MeshUtils::Orientation::CounterClockwise; + + std::reverse(vecPoint.begin(), vecPoint.end()); + QTest::newRow("case6") << vecPoint << Mayo::MeshUtils::Orientation::Clockwise; + + { + QFile file("inputs/mayo_bezier_curve.brep"); + QVERIFY(file.open(QIODevice::ReadOnly)); + + const TopoDS_Shape shape = BRepUtils::shapeFromString(file.readAll().toStdString()); + QVERIFY(!shape.IsNull()); + + TopoDS_Edge edge; + BRepUtils::forEachSubShape(shape, TopAbs_EDGE, [&](const TopoDS_Shape& subShape) { + edge = TopoDS::Edge(subShape); + }); + QVERIFY(!edge.IsNull()); + + const GCPnts_TangentialDeflection discr(BRepAdaptor_Curve(edge), 0.1, 0.1); + vecPoint.clear(); + for (int i = 1; i <= discr.NbPoints(); ++i) { + const gp_Pnt pnt = discr.Value(i); + vecPoint.push_back(gp_Pnt2d(pnt.X(), pnt.Y())); + } + + QTest::newRow("case7") << vecPoint << Mayo::MeshUtils::Orientation::CounterClockwise; + + std::reverse(vecPoint.begin(), vecPoint.end()); + QTest::newRow("case8") << vecPoint << Mayo::MeshUtils::Orientation::Clockwise; + } +} + +void Test::MeshUtils_test() +{ + // Create box + QFETCH(double, boxDx); + QFETCH(double, boxDy); + QFETCH(double, boxDz); + const TopoDS_Shape shapeBox = BRepPrimAPI_MakeBox(boxDx, boxDy, boxDz); + + // Mesh box + { + BRepMesh_IncrementalMesh mesher(shapeBox, 0.1); + mesher.Perform(); + QVERIFY(mesher.IsDone()); + } + + // Count nodes and triangles + int countNode = 0; + int countTriangle = 0; + BRepUtils::forEachSubFace(shapeBox, [&](const TopoDS_Face& face) { + TopLoc_Location loc; + const Handle_Poly_Triangulation& polyTri = BRep_Tool::Triangulation(face, loc); + if (!polyTri.IsNull()) { + countNode += polyTri->NbNodes(); + countTriangle += polyTri->NbTriangles(); + } + }); + + // Merge all face triangulations into one + Handle_Poly_Triangulation polyTriBox = + new Poly_Triangulation(countNode, countTriangle, false); + { + int idNodeOffset = 0; + int idTriangleOffset = 0; + BRepUtils::forEachSubFace(shapeBox, [&](const TopoDS_Face& face) { + TopLoc_Location loc; + const Handle_Poly_Triangulation& polyTri = BRep_Tool::Triangulation(face, loc); + if (!polyTri.IsNull()) { + for (int i = 1; i <= polyTri->NbNodes(); ++i) + polyTriBox->ChangeNode(idNodeOffset + i) = polyTri->Node(i); + + for (int i = 1; i <= polyTri->NbTriangles(); ++i) { + int n1, n2, n3; + polyTri->Triangle(i).Get(n1, n2, n3); + polyTriBox->ChangeTriangle(idTriangleOffset + i).Set( + idNodeOffset + n1, idNodeOffset + n2, idNodeOffset + n3); + } + + idNodeOffset += polyTri->NbNodes(); + idTriangleOffset += polyTri->NbTriangles(); + } + }); + } + + // Checks + QCOMPARE(MeshUtils::triangulationVolume(polyTriBox), + double(boxDx * boxDy * boxDz)); + QCOMPARE(MeshUtils::triangulationArea(polyTriBox), + double(2 * boxDx * boxDy + 2 * boxDy * boxDz + 2 * boxDx * boxDz)); +} + +void Test::MeshUtils_test_data() +{ + QTest::addColumn("boxDx"); + QTest::addColumn("boxDy"); + QTest::addColumn("boxDz"); + + QTest::newRow("case1") << 10. << 15. << 20.; + QTest::newRow("case2") << 0.1 << 0.25 << 0.044; + QTest::newRow("case3") << 1e5 << 1e6 << 1e7; + QTest::newRow("case4") << 40. << 50. << 70.; +} + +void Test::Quantity_test() +{ + const QuantityArea area = (10 * Quantity_Millimeter) * (5 * Quantity_Centimeter); + QCOMPARE(area.value(), 500.); + QCOMPARE((Quantity_Millimeter / 5.).value(), 1/5.); +} + +namespace Result_test { + +struct Data { + static std::ostream* data_ostr; + + Data() { + *data_ostr << 0; + } + Data(const Data& other) : foo(other.foo) { + *data_ostr << 1; + } + Data(Data&& other) { + foo = std::move(other.foo); + *data_ostr << 2; + } + Data& operator=(const Data& other) { + this->foo = other.foo; + *data_ostr << 3; + return *this; + } + Data& operator=(Data&& other) { + this->foo = std::move(other.foo); + *data_ostr << 4; + return *this; + } + QString foo; +}; +std::ostream* Data::data_ostr = nullptr; + +} // Result_test + +void Test::Result_test() +{ + using Result = Result; + { + std::ostringstream sstr; + Result::Data::data_ostr = &sstr; + const Result res = Result::error("error_description"); + QVERIFY(res.errorText() == "error_description"); + QVERIFY(!res.valid()); + QCOMPARE(sstr.str().c_str(), "02"); + } + { + std::ostringstream sstr; + Result::Data::data_ostr = &sstr; + Result::Data data; + data.foo = "FooData"; + const Result res = Result::ok(std::move(data)); + QVERIFY(res.valid()); + QVERIFY(res.get().foo == "FooData"); + QCOMPARE(sstr.str().c_str(), "0042"); + } +} + +void Test::StringUtils_append_test() +{ + QFETCH(QString, strExpected); + QFETCH(QString, str1); + QFETCH(QString, str2); + QFETCH(QLocale, locale); + + QString strActual = str1; + StringUtils::append(&strActual, str2, locale); + QCOMPARE(strActual, strExpected); +} + +void Test::StringUtils_append_test_data() +{ + QTest::addColumn("strExpected"); + QTest::addColumn("str1"); + QTest::addColumn("str2"); + QTest::addColumn("locale"); + + QTest::newRow("locale_c") + << QString("1234") + << QStringLiteral("12") + << QStringLiteral("34") + << QLocale::c(); + QTest::newRow("locale_fr") + << QString("1234") + << QStringLiteral("12") + << QStringLiteral("34") + << QLocale(QLocale::French); + QTest::newRow("locale_arabic") + << QString("3412") + << QStringLiteral("12") + << QStringLiteral("34") + << QLocale(QLocale::Arabic); + QTest::newRow("locale_syriac") + << QString("3412") + << QStringLiteral("12") + << QStringLiteral("34") + << QLocale(QLocale::Syriac); +} + +void Test::StringUtils_text_test() +{ + QFETCH(QString, strActual); + QFETCH(QString, strExpected); + QCOMPARE(strActual, strExpected); +} + +void Test::StringUtils_text_test_data() +{ + QTest::addColumn("strActual"); + QTest::addColumn("strExpected"); + + const StringUtils::TextOptions opts_c_si_2 = { QLocale::c(), UnitSystem::SI, 2 }; + const StringUtils::TextOptions opts_fr_si_2 = { + QLocale(QLocale::French, QLocale::France), UnitSystem::SI, 2 }; + QTest::newRow("c_0.1") + << StringUtils::text(0.1, opts_c_si_2) + << QStringLiteral("0.1"); + QTest::newRow("c_0.155") + << StringUtils::text(0.155, opts_c_si_2) + << QStringLiteral("0.15"); + QTest::newRow("c_0.159") + << StringUtils::text(0.159, opts_c_si_2) + << QStringLiteral("0.16"); + QTest::newRow("fr_1.4995") + << StringUtils::text(1.4995, opts_fr_si_2) + << QStringLiteral("1,5"); + QTest::newRow("c_pnt0.55,4.8977,15.1445") + << StringUtils::text(gp_Pnt(0.55, 4.8977, 15.1445), opts_c_si_2) + << QStringLiteral("(0.55mm 4.9mm 15.14mm)"); +} + +void Test::UnitSystem_test() +{ + QFETCH(UnitSystem::TranslateResult, trResultActual); + QFETCH(UnitSystem::TranslateResult, trResultExpected); + QCOMPARE(trResultActual, trResultExpected); +} + +void Test::UnitSystem_test_data() +{ + QTest::addColumn("trResultActual"); + QTest::addColumn("trResultExpected"); + + const UnitSystem::Schema schemaSI = UnitSystem::SI; + QTest::newRow("80mm") + << UnitSystem::translate(schemaSI, 80 * Quantity_Millimeter) + << UnitSystem::TranslateResult{ 80., "mm", 1. }; + QTest::newRow("8cm") + << UnitSystem::translate(schemaSI, 8 * Quantity_Centimeter) + << UnitSystem::TranslateResult{ 80., "mm", 1. }; + QTest::newRow("8m") + << UnitSystem::translate(schemaSI, 8 * Quantity_Meter) + << UnitSystem::TranslateResult{ 8000., "mm", 1. }; + QTest::newRow("50mm²") + << UnitSystem::translate(schemaSI, 0.5 * Quantity_SquaredCentimer) + << UnitSystem::TranslateResult{ 50., "mm²", 1. }; + constexpr double radDeg = Quantity_Degree.value(); + QTest::newRow("degrees(PIrad)") + << UnitSystem::degrees(3.14159265358979323846 * Quantity_Radian) + << UnitSystem::TranslateResult{ 180., "°", radDeg }; +} + +void Test::LibTree_test() +{ + const TreeNodeId nullptrId = 0; + Tree tree; + TreeNodeId n0 = tree.appendChild(0, "0"); + TreeNodeId n0_1 = tree.appendChild(n0, "0-1"); + TreeNodeId n0_2 = tree.appendChild(n0, "0-2"); + TreeNodeId n0_1_1 = tree.appendChild(n0_1, "0-1-1"); + TreeNodeId n0_1_2 = tree.appendChild(n0_1, "0-1-2"); + + QCOMPARE(tree.nodeParent(n0_1), n0); + QCOMPARE(tree.nodeParent(n0_2), n0); + QCOMPARE(tree.nodeParent(n0_1_1), n0_1); + QCOMPARE(tree.nodeParent(n0_1_2), n0_1); + QCOMPARE(tree.nodeChildFirst(n0_1), n0_1_1); + QCOMPARE(tree.nodeChildLast(n0_1), n0_1_2); + QCOMPARE(tree.nodeSiblingNext(n0_1_1), n0_1_2); + QCOMPARE(tree.nodeSiblingPrevious(n0_1_2), n0_1_1); + QCOMPARE(tree.nodeSiblingNext(n0_1_2), nullptrId); +} + +} // namespace Mayo + diff --git a/tests/test.h b/tests/test.h new file mode 100644 index 00000000..452f514f --- /dev/null +++ b/tests/test.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** Copyright (c) 2020, Fougue Ltd. +** All rights reserved. +** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt +****************************************************************************/ + +#pragma once + +#include +#include + +namespace Mayo { + +class Test : public QObject { + Q_OBJECT + +private slots: + void Application_test(); + void Application_test_data(); + void BRepUtils_test(); + void CafUtils_test(); + void MeshUtils_test(); + void MeshUtils_test_data(); + void MeshUtils_orientation_test(); + void MeshUtils_orientation_test_data(); + void Quantity_test(); + void Result_test(); + void StringUtils_append_test(); + void StringUtils_append_test_data(); + void StringUtils_text_test(); + void StringUtils_text_test_data(); + void UnitSystem_test(); + void UnitSystem_test_data(); + + void LibTree_test(); +}; + +} // namespace Mayo diff --git a/version.pri b/version.pri new file mode 100644 index 00000000..ba025f60 --- /dev/null +++ b/version.pri @@ -0,0 +1,34 @@ +system(git --version):HAVE_GIT=1 +defined(HAVE_GIT, var) { + MAYO_VERSION_COMMIT = $$system(git rev-parse --short HEAD) + MAYO_VERSION_REVNUM = $$system(git rev-list --count HEAD) +} else { + MAYO_VERSION_COMMIT = ?? + MAYO_VERSION_REVNUM = 0 + warning("Git is not in PATH, cannot find commit ID nor revision number") +} + +MAYO_VERSION_MAJ = 0 +MAYO_VERSION_MIN = 2 +MAYO_VERSION_PAT = 0 +VERSION = $${MAYO_VERSION_MAJ}.$${MAYO_VERSION_MIN}.$${MAYO_VERSION_PAT}.$${MAYO_VERSION_REVNUM} +MAYO_VERSION = $${VERSION}-$$MAYO_VERSION_COMMIT + +equals(QT_ARCH, i386) { + VERSION_TARGET_ARCH = x86 +} else:equals(QT_ARCH, x86_64) { + VERSION_TARGET_ARCH = x64 +} else { + VERSION_TARGET_ARCH = $$QT_ARCH +} + +QMAKE_TARGET_PRODUCT = Mayo +QMAKE_TARGET_COMPANY = Fougue + +# Generate version files +QMAKE_SUBSTITUTES += \ + $$PWD/installer/version.iss.in \ + $$PWD/src/app/version.h.in + +INCLUDEPATH += $$OUT_PWD/src/app # To allow inclusion as "version.h" from source code +OTHER_FILES += $$PWD/src/app/version.h.in