pax_global_header00006660000000000000000000000064140516551740014522gustar00rootroot0000000000000052 comment=2304b8889f99333525ac1578ff57b977cdb76e38 qvge-0.6.3/000077500000000000000000000000001405165517400124725ustar00rootroot00000000000000qvge-0.6.3/.gitignore000066400000000000000000000006561405165517400144710ustar00rootroot00000000000000# C++ objects and libs *.slo *.lo *.o *.a *.la *.lai *.so *.dll *.dylib # Qt-es /.qmake.cache /.qmake.stash *.pro.user *.pro.user.* *.qbs.user *.qbs.user.* *.moc moc_*.cpp moc_*.h qrc_*.cpp ui_*.h Makefile* *build-* # QtCreator *.autosave # QtCtreator Qml *.qmlproject.user *.qmlproject.user.* # QtCtreator CMake CMakeLists.txt.user* /code/3rdParty/qsint-properties /_builds_qvge_msvc /code/makevc.bat *.ipch *.obj *.tlog qvge-0.6.3/CHANGES000066400000000000000000000311131405165517400134640ustar00rootroot00000000000000QVGE 0.6.3/Master - mostly merged back from 0.7.dev branch ------------------------------------------------------------------------------- Bugfixes: - fixed building with OGDF support (#130, #139) - fixed import of multiline labels from DOT (#141) - fixed DOT: shape="box" not recognized (#140) - thanks to casiosmu for fixing this! - fixed crash after exporting to SVG and reopening the document (#145) - fixed various typos and export to GraphML (#147) - thanks to luzpaz! QVGE 0.6.2 ------------------------------------------------------------------------------- New features/improvements: - import of GraphML in SocNetV format supported - GraphViz accessibility and version can be checked out of the Options dialog - if GraphViz layout engine happens to freeze, it can be aborted by user via GUI (no need to call Task Manager anymore) Bugfixes: - fixed crash when pressing Escape after creating of a node and immediately editing of a text label (#123) - fixed issue with forwarding keyboard events during editing of a text label (#124) - fixed importing default GraphML attributes - fixed a typo in the default attribute name (#125) - fixed loading edge id from DOT format - fixed moving nodes via keyboard - fixed nodes snapping after transformation - fixed restoring windows & panels layout - Fedora 32, Qt 5.14: too big font on startup buttons (#120) Windows: - GraphViz 2.44 binaries are shipped together QVGE 0.6.1 ------------------------------------------------------------------------------- New features/improvements: - added import of plain/plain_ext GraphViz format - added import of dot files via GraphViz engine (#116) - added layout via GraphViz engine (#118) Bugfixes: - fixed item transformation with pressed Shift key - fixed disappearing of the cursor when a key was pressed during transformation - fixed potential stack overflow during dragging (Qt bug?) - fixed cancelling the drag via Esc key - right clicks during drag are ignored Externals: - OGDF and Boost removed from source tree (only external libraries can be used for now) Linux: - fixed various "make install" related issues (#110, #113, #114, #115) Windows: - fixed installer issue with putting 64-bit executable under Program Files (x86) - GraphViz 2.38 binaries are shipped together QVGE 0.6.0 ------------------------------------------------------------------------------- New features/improvements: - added polyedges (#23) - added export to SVG format - recent files list entries can be cleaned up (#89) - Ctrl+Right/Ctrl+Left change weights of selected edges - when editing a label, Enter begins a new line, Esc finishes editing - transformation tool: Drag+Shift performs parallel transformation - "Factor" mode added next to "Transform" (#102) - improved export & import of Graphviz format (using boost-BGL instead of OGDF) - PDF export: automatically sets page orientation; printer options made persistent (#73) - a scene loaded from file is automatically centered by its contents - improved drawing of edge selection Bugfixes: - fixed crash after undoing of a recent drag operation - fixed issue when a document could not be opened (#96) - fixed issue with setting label properties while label editor is open - fixed issue with drawing arrows (#14) - fixed: objects being moved are always ensured to be visible during the movement - fixed: scroll offset during drag made constant (avoiding acceleration issue with dragging at viewport's edges) GCC/MinGW: - fixed include issue (#101) Externals: - read_proc is deprecated and replaced by QProcessInfo - QSint widgets updated to the latest snapshot (0.4.x) OGDF: - OGDF updated to v.2020-02 (more stable than previous one) - qvge can be built & linked against an external OGDF library - "Layout" menu is moved under "OGDF" submenu - "Create new graph" dialog is moved under "OGDF" menu (#97) - Davidson-Harel layout added Windows: - portable mode implemented (#54) - auto registration of XGR documents after starting the app (#74) Linux: - "qmake -r PREFIX=.." should be respected now (#69,#93) - fixed menu with opened windows (#88) - fixed "Segmentation fault" issue when loading documents (#82) - fixed "Buffer/Memory containment" issues (#80) - fixed desktop integration (#91) - fixed including Qt5 X11Extras into project (#92) - fixed glitches of some UI elements (#99) - fixed adding default file extensions while export (#86) QVGE 0.5.5 ------------------------------------------------------------------------------- - support of Qt 5.13 - support of MSVC 2017 - support of MinGW 7 - label editing can be finished with Enter; Shift+Enter starts new line (#77) - when exporting to image, a resolution can be customized (#73) - added export to GraphML format; node ports supported now (#28) - nodes & edges editor UI improved - "tooltip" attribute is shown as a popup tooltip - improvements/fixes in drawing arrows (#14) - some fixes of label editing logic - fixed project issue when building on MS Windows having Cygwin installed - fixed potential crash if wrong grid size was set/read - fixed interception of direct edges with elliptical nodes - fixed custom installation path under Linux (#69) - fixed crash on copying items with pressed Ctrl (#75) - fixed items ID visibility when dragging with pressed Ctrl (#78) - fixed handling of edge cancellation by right click - fixed issue with undo/redo manager - fixed grid snapping issue with pressed Alt key - fixed export of UTF-8 encoded text to GraphViz/DOT - fixed input/output of size attribute to GEXF format - fixed building issue under Linux/Unix (file name mismatch in one of 3rdParies) (#81) - fixed potential crash when using "Zoom Back" function after loading a graph document Windows installation: - Build moved from MSVC 2015 to MinGW 7 - Qt updated to 5.13.2 - Installation/binary packages made significantly smaller QVGE 0.5.4 ------------------------------------------------------------------------------- - added shortcuts for quick node resizing (Ctrl+Up, Ctrl+Down) - added mini help panel (#15) - added "restore zoom after fit" feature (#65) - added nodes transformation mode (#24) - auto scroll during drag implemented (#56) - some labels drawing optimizations - fixed crash after editing a node port - fixed drawing direction arrows when nodes are too close - fixed some edge drawing issues - fixed crash on reading *.xgr files in 32-bit versions - fixed regression on opening main window in maximized mode - fixed issue of scaling of the recent files list on the start page QVGE 0.5.3 ------------------------------------------------------------------------------- - default paste behavior modified: items will be preferably pasted into a visible scene's area - selection copied to clipboard can be pasted as an image to any software - DOT export: scene background attribute exported as well - DOT export: extended to optionally export only the topology (#63) - added more action hints - added fast movement of the selected items by Shift + Arrow keys - added start page with common file actions (#59) - added exit out of the complete application (with all windows) - fixed crash on deleting items via Cut or Delete actions (#55) - fixed some item selection issues - fixed export of image and PDF documents (auto crop added as well) QVGE 0.5.2 ------------------------------------------------------------------------------- - View Menu: added Toolbars & Panels submenu (#52) - View Menu: item ids can be shown/hidden separately from labels (#47) - added in-place label editing (by double click) - added node port colors - added timed auto backups (#60) - added basic import from GraphViz/DOT format via OGDF (#53) - added Sugiyama graph layout (via OGDF) - more diagnostic shown if file reading failed - selection of global attributes made more convenient - logic of movement of the selected items made more intuitive (#48) - snap to grid enabled by default (#45) - label font editor extended a little - item painting optimizations and corrections - item ids are now editable via context menu only (by right click) - double click on a node port shows its properties - newly started application instance now overtakes the parent's instance settings - Commutation Table: when adding a column, a list with available attribute ids is shown - Commutation Table: added button bar - fixed font reading/setting issue - fixed bug with changing style of selected items after applying a new scheme - fixed drawing of transparent items - fixed storing/applying of grid snap properties (#49) - fixed placement of edge labels (#50) - fixed some GEXF-related issues (#51) - fixed canvas expansion after changing item IDs (#44) - (32-bit-version): fixed crash while cloning the selection - fixed issue with storing DOT format if ids include spaces QVGE 0.5.1 (bugfix beta) ------------------------------------------------------------------------------- - some GEXF format IO fixes - port renaming optimizations QVGE 0.5.0 (beta) ------------------------------------------------------------------------------- - changed project directory structure - globally renamed: CConnection -> CEdge etc. - some menu texts corrected & tooltips added - added basic support of node ports - added buttons to change attribute's name & type - color schemes menu moved into Edit - added "Factor Nodes" dialog - added zoom/fit to selection - added custom columns to the Topology editor - added "Search" feature - fixed issue with document change notification when a new document is created - fixed issue with putting empty states into the undo/redo stack after editing of complex attributes (color, font etc) - fixed generation of the default ids for nodes/edges - fixed opening of documents with unicode names - fixed writing non-latin symbols to GEXF files as well as description & version number (#33) - fixed writing graph attributes to GEXF files - fixed storing of default class attributes DPSE changes: - added node models conversion via context menu for selected nodes QVGE 0.4.3 (beta) ------------------------------------------------------------------------------- - item tooltips visually improved - fixed issue with moving the mouse over the Mini Navigator when invoked by the corner button - fixed issue with restoring of scene interactive state after panning - fixed a crash when leaving property editor after changing a value - fixed editing of string and numerical values after typing next character - fixed a couple of visual issues with double values QVGE 0.4.2 (beta) ------------------------------------------------------------------------------- - added new color scheme (Sunny Spring) - added common editor modes to simplify the editing - default node & edge properties set to UI when new scene is attached - auto-assign of currently selected node & edge properties to the newly created items - more tool- & status tips displayed - some common operations made more intuitive (clone items with pressed Ctrl etc.) - fixed issue with dragging items over their labels - (Linux) fixed issue with default IO directory - (FreeBSD) fixed restoring of maximized windows (Qt issue) - (Windows) added uninstaller to the setup packages QVGE 0.4.1 (beta) ------------------------------------------------------------------------------- - mouse navigation speedup - more precise node outline & edge width (resolution of 0.1 px) - nodes can have no background (i.e. be transparent) - single nodes may be created by left double click on empty space - added cropping scene to contents - added "hexagon" node shape - added editing of nodes & edges textual labels - added default color schemes - added support for FreeBSD platform - fixed potential memory leaks & crash when setting attributes constrains - fixed some default node & edge attributes - removed "label.size" subattribute (font's pointSize is used instead) - graph creation dialog made optional - (Windows) fixed issue with opening of associated files by double click - (Windows) added version info to the executable - (Linux) fixed restoring of maximized windows (Qt issue) QVGE 0.4.0 (beta) ------------------------------------------------------------------------------- - added export to GEXF format - added import from GML format (via OGDF) - added support for Cygwin platform (not all features yet) - added support for node outline - corrected and improved import from GEXF format - fixed some issues with attribute inheritance - fixed some issues with files IO - fixed some issues with application UI - fixed issue when a node was sometimes created on a wrong place - fixed issue with cancelling of edge creation by right mouse button - fixed scene panning by right mouse button when initially clicked on an item QVGE 0.3.0 (alpha) -------------------------------------------------------------------------------- - initial public release qvge-0.6.3/LICENSE000066400000000000000000000020601405165517400134750ustar00rootroot00000000000000MIT License Copyright (c) 2018-2020 Ars Masiuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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. qvge-0.6.3/README.md000066400000000000000000000222541405165517400137560ustar00rootroot00000000000000## Qt Visual Graph Editor [![Download qvge](https://img.shields.io/sourceforge/dt/qvge.svg?style=for-the-badge)](https://sourceforge.net/projects/qvge/files/latest/download) [![Github All Releases](https://img.shields.io/github/downloads/ArsMasiuk/qvge/total.svg?style=for-the-badge)](https://github.com/ArsMasiuk/qvge/releases/latest) ![GitHub release](https://img.shields.io/github/release/ArsMasiuk/qvge.svg?style=for-the-badge) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg?style=for-the-badge)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z35EHHJ3729GG&source=url) **QVGE** is a multiplatform graph editor written in C++/Qt. Its main goal is to make possible visually edit two-dimensional graphs in a simple and intuitive way. ![Screenshot1](https://user-images.githubusercontent.com/19762856/89233004-f7846780-d5e8-11ea-8a18-ba395794e1d4.PNG) Please note that **QVGE** is not a replacement for such a software like Gephi, Inkscape, yEd, Dia and so on. It is neither a tool for "big data analysis" nor a math application. It is really just a simple graph editor with some advanced features (i.e. GraphViz integration). ### Support Since **QVGE** is a free software, it is developed in the free time on my own costs only. If you like the software and wish to support its further development, you could make a small donation using the button below: [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z35EHHJ3729GG&source=url) Thank you! ### Main Features - Easy creation and parameterising of small-sized till middle-sized graphs (1000+ nodes/edges) - Common visual properties of nodes and edges: shapes, sizes, colors, labels etc. - Directed, undirected and mixed graphs - Node ports - Straight and polygonal edges - Custom (user-defined) attributes of graphs and their elements - Dynamically maintained list of commutations between nodes - Search among the graph elements and their attributes - Windows: portable mode (no installation required) - Auto-layout of graphs via [GraphViz](https://graphviz.org/) engines: - dot - neato - fdp - sfdp - circo - Export of graphs into: - PDF - SVG - various image formats (BMP, PNG, JPG, TIFF etc.) - Graph file formats supported: - XGR (native graph persistence format) - GEXF (read/write of common subset, except clusters and dynamic properties) - GraphML (read/write) - GML (read via OGDF, write via QVGE) - [GraphViz DOT](https://graphviz.org/) (read via GraphViz/boost/OGDF, write via QVGE) ### Some users' feedback > "This graph editor is very promising for every day modeling." > "Qt Visual Graph Editor is a fairly straightforward, open-source tool that enables users to design relatively simple graphs for their projects. It comes with a decent set of features and is very intuitive." > "It seems to me that my development have become more efficient after when I began using QVGE. This is much more useful than UML, because that I don't have to change sheets and to remember several usages and I can draw graphs swiftly." > "Lightweight, multi-platform graph editor that allows users to edit two-dimensional graphs in a quick and intuitive way, as an alternative to more complex software." > "Its user experience is very good. It's because how to operate is sophisticated so intuitive and very simple. A user can entirely concentrate on essence of content the whole time. Because of simpleness, the content is not noisy and easy to understand, and usable much generally to design, refactor and output a structure such as a organization, a software, logic, routes and all other relationships without learning usage separately." > "I have been using QVGE for a few hours a week for over a year. It made my life better." ### Installation Prebuild Windows binaries can be loaded from here: [![Github All Releases](https://img.shields.io/github/downloads/ArsMasiuk/qvge/total.svg?style=for-the-badge)](https://github.com/ArsMasiuk/qvge/releases/latest) Or you can get QVGE's sources and build them by yourself. In this case you need to have installed Qt 5.x toolkit and corresponding C++ compiler with C++11 support. QVGE uses native Qt build system (main project file is qvgeapp.pro) so it should look like the following for Windows and common Linux distributions: ~~~ cd qmake -r ~~~ or, for Fedora-based distributions: ~~~ cd qmake-qt5 -r ~~~ or, for macOS (with Homebrew and XCode Command Line Tools): ~~~ brew install qt cd /usr/local/Cellar/qt/5.*/bin/qmake -r ~~~ Then run corresponding 'make' command to build the application: Linux GCC, macOS Clang: ~~~ make ~~~ or Windows MinGW: ~~~ mingw32-make ~~~ or Windows MSVC: ~~~ nmake ~~~ or by Jom: ~~~ jom ~~~ Linux only: once the application is compiled, install it using ~~~ sudo make install ~~~ ### Enabling OGDF Integration with [OGDF](https://ogdf.uos.de/) enables auto-creation and auto-layout of graphs using following algorithms: - Linear - Balloon - Circular - FMMM - Planar - Sugiyama - Davidson-Harel #### WARNING: bundled OGDF support has been removed since QVGE 0.6.1 due to memory access issues In order to build **QVGE** with external OGDF support (installed in your system): before running qmake, open the file `src/config.pri` and uncomment the following option: ~~~ CONFIG += USE_EXTERNAL_OGDF ~~~ This will allow to link against OGDF library which is already present in the system. In this case, the following lines have to be changed accordingly: ~~~ USE_EXTERNAL_OGDF{ ... # system-specific OGDF setup OGDF_LIB_NAME = OGDF_LIB_PATH = OGDF_INCLUDE_PATH = } ~~~ Then run qmake + make as described in the step before. ### Supported compilers Recent version of **QVGE** has been built with: - Microsoft Visual Studio 2017 (Community Edition) - MinGW 7.3 - GCC 7.5 (Linux) - GCC 6.4.0 (Cygwin) - Clang C++ (FreeBSD, macOS) Hopefully it can also be compiled with others compilers. If not please do not hesitate to provide description of the issue. ### Supported OS **QVGE** has been tested on Microsoft Windows 10, several Linux distributions (Mint, Mageia, Fedora etc) and macOS 11.2 Big Sur. Theoretically it should run on (almost) any OS which have Qt 5.x installed. **QVGE** can be compiled & run under Cygwin. ### Supported Qt **QVGE** has been tested with Qt 5.9-5.14. But it should work with any newer 5.x version too. ### Credits **QVGE** uses following 3rd party components: - [Qt](https://www.qt.io) - licensed under LGPLv3 - [Qt property browser](https://github.com/qtproject/qt-solutions) - licensed under BSD - [QProcessInfo](https://github.com/baldurk/qprocessinfo) - licensed under BSD - [QSint widgets library](https://sourceforge.net/projects/qsint) - licensed under LGPLv3 - SVG icons from [Inkscape](https://inkscape.org) - licensed under GPL (more details here: https://inkscape.org/de/ueber/lizenzierung/) - [GraphViz](https://graphviz.org) - licensed under CPLv1.0 (more details here: https://graphviz.org/license/) Special thanks to: - Dr. prof. [Vladimir A. Svjatnyj](https://wiki.donntu.edu.ua/view/%D0%A1%D0%B2%D1%8F%D1%82%D0%BD%D0%B8%D0%B9_%D0%92%D0%BE%D0%BB%D0%BE%D0%B4%D0%B8%D0%BC%D0%B8%D1%80_%D0%90%D0%BD%D0%B4%D1%80%D1%96%D0%B9%D0%BE%D0%B2%D0%B8%D1%87), head of [computer engineering chair](https://donntu.edu.ua/knt/kafedra-ki) at [DonNTU](https://donntu.edu.ua/en/donntu2020) and my scientific supervisor - [Tatsuro Ueda](https://github.com/weed), founder of [Feel Physics](https://feel-physics.jp), for comrehensive testing, feedback and suggestions ### External Links **QVGE** at [![Download qvge](https://sourceforge.net/sflogo.php?type=14&group_id=2914953)](https://sourceforge.net/p/qvge/) **QVGE** at [Softpedia.com](https://www.softpedia.com/get/Multimedia/Graphic/Graphic-Others/Qt-Visual-Graph-Editor.shtml) **QVGE** at [SoftX64.com](https://www.softx64.com/windows/qt-visual-graph-editor.html) Qt Visual Graph Editor review **QVGE** at [software-file.com](http://www.software-file.com/Qt_Visual_Graph_Editor-sfs-472477.html) Qt Visual Graph Editor on Software-File.com **QVGE** at Qt Visual Graph Editor - Software to visually create and manipulate graphs | Product Hunt Embed qvge-0.6.3/_config.yml000066400000000000000000000000341405165517400146160ustar00rootroot00000000000000theme: jekyll-theme-leap-dayqvge-0.6.3/examples/000077500000000000000000000000001405165517400143105ustar00rootroot00000000000000qvge-0.6.3/examples/class diagram - QComboBox.xgr000066400000000000000000000131621405165517400214560ustar00rootroot00000000000000 VersionId CDirectEdgeϾWstyle dashed label.colorCE9ϾHϾ;P CDirectEdgeϾYstyle dashed label.colorCE11ϾHϾJP CDirectEdgeϾ[pstyle dashed label.colorCE5ϾIϾI CDirectEdgeϾ] label.colorCcolorC3333E1Ͼ:PϾQ CDirectEdgeϾ^style dashed label.colorCE6Ͼ>PϾ? CDirectEdgeϾ`pstyle dashed label.colorCE4Ͼ?ϾI CDirectEdgeϾa label.colorCcolorC3333E2ϾQϾE CDirectEdgeϾistyle dashed label.colorCE10Ͼ;PϾJP CDirectEdgeϾjpstyle dashed label.colorCE12ϾJPϾ: CDirectEdgeϾkstyle solid label.colorCcolorC3333E3ϾQϾ? CDirectEdgeϾmstyle dashed label.colorCE7Ͼ?Ͼ>P CDirectEdgeϾn0style dashed label.colorCE8Ͼ>PϾHCNodeϾ:P@b@>@^@@qsize@b@>shape square label.font@MS Shell Dlg 2Fett@ K label.colorClabel QComboBoxcolorCN10CNodeϾ:@b@>pqsize@b@>shape square label.colorClabel QBasicAtomiccolorCN1CNodeϾ;P@b@>dP@size@b@>shape square label.colorClabel QListDatacolorCN3CNodeϾ>P@b@>S@dsize@b@>shape square label.colorClabel QObjectDatacolorCN6CNodeϾ?@b@>@<@Jsize@b@>shape square label.colorClabel QObjectcolorCN5CNodeϾE@b@>@p0@Jsize@b@>shape square label.colorClabel QPaintDevicecolorCN8CNodeϾH@b@>p@Isize@b@>shape square label.colorClabel QList<T>colorCN4CNodeϾI@b@>@MP@size@b@>shape square label.colorClabel QMetaObjectcolorCN7CNodeϾJP@b@>pgsize@b@>shape square label.colorClabel QListData::DatacolorCN2CNodeϾQ@b@>@n@esize@b@>shape square label.colorClabel QWidgetcolorCN9_attr_4Vxcommentcomment 2QComboBox Class Reference copyrightcopyright "Nokia Corporation creatorcreator 8Qt Visual Graph Editor 0.5.0 labels.policyLabels Policyurlurl https://cep.xray.aps.anl.gov/software/qt4-x11-4.2.2-browser/df/dae/class_q_combo_box.html edgecolor ColorCC directionDirection directed style Style solid weight Weight?itemidID  label Label  label.colorLabel ColorCC label.fontLabel Font@MS Shell Dlg 2@ 2@nodecolor ColorCCdegree DegreeposPositionshape Shape disc sizeSize@&@& stroke.colorStroke ColorCC stroke.sizeStroke Size? stroke.styleStroke Style solid polyedgeedgenodeitemedgeitemnodeitemlabelidedge???S???@?@@@@@@@qvge-0.6.3/examples/elements test.xgr000066400000000000000000000103511405165517400176060ustar00rootroot00000000000000 VersionId CNode>@Y@Y99 stroke.style dotted stroke.size@ stroke.colorC33size@Y@Yshape square label.font@ ArialStandard@"2 label.colorCfflabel Square 100x100 Fill: solid cyan Stroke: darkgreen dotted 3 Label: orange 9 strikeoutcolorCffN3CNode>@b@Y9wp stroke.style dashed stroke.size@ stroke.colorCsize@b@Y label.font@Courier@$K label.colorClabel Ellipse 150x100 Fill: solid yellow Stroke: red dashed 2.5 Label: blue courier 10 bold italic underlinecolorCN2CNode>@Y@Y@isize@Y@Y label.font@ ArialStandard@ 2label Ellipse 100x100 Fill: solid magenta Stroke: black solid 1 Label: black arial 8N1 CDirectEdge>,Pweight? label.font@ ArialStandard@Klabel Direct line: gray solid 1px Type: directed N1->N2 Label: black arial 7 italicE1>> CDirectEdge>,weight@style dashed label.font@MS Shell Dlg 2@(2 label.colorClabel jdashed green 5px two-directional N2<->N3 label red 12 direction mutualcolorCE2>> CPolyEdge>@Oweight@ style dotted label.font@MS Shell Dlg 2@ 2label jUndurected N1-N3 dot blue 3.5 polyline italic nocolor direction undirectedcolorCE3>>o@9tPe_attr_4VxcommentComment  creator&Creator of document LQt Visual Graph Editor 0.6.a (preview) labels.policyLabels Policyedgecolor ColorCC directionDirection directed pointsPolyline Points style Style solid weight Weight?itemidID label Label label.colorLabel ColorCC label.fontLabel Font@MS Shell Dlg 2@ 2@node color ColorCCdegree Degreeshape Shape disc sizeSize@&@& stroke.colorStroke ColorCC stroke.sizeStroke Size? stroke.styleStroke Style solid xX-Coordinate&yY-Coordinate&polyedgeedgenodeitemedgeitemnodeidlabelitemidlabeledgeidlabel滻???Q????@@@0@@qvge-0.6.3/examples/mine airing network graph - 117 branches.gexf000066400000000000000000001534711405165517400242700ustar00rootroot00000000000000 Qt Visual Graph Editor 0.5.2 (64bit) Mine airing network "Molodogvardeiskaya" Svjatnyj W.A. Mine airing network "Molodogvardeiskaya" Qt Visual Graph Editor 0.5.0 0 id #55aaff #444444 disc 11 #ffffff 1 solid 0 0 0 0 0 id #ffaa00 directed #55aa7f solid 1 qvge-0.6.3/examples/ports.xgr000066400000000000000000000163761405165517400162160ustar00rootroot00000000000000 VersionId CNode<0k@&@&@hshape triangle2colorC33N9 CDirectEdgek0x/Rx׌2`$;AkxA9~H,K9RjH>U|Y!xw,-0I,+F&,^|$#7)x5 KC}Ʋ M^#ߘO_'vAw6öv4pPx6$,:Qv+QCf : $Bi0)Z뒰,:Fc 5CmO{-WԹպVn0_+RIPEF / ^1(~R`2E£:G4cX0ctzU-f(\1z 2O,Ĉ8Z*A9" j,',u2Q5kФQםɧ67焥d-<9~h9wݵ\p]Q#UꡞD-coq_pZq֬n+52Vf8_eX%;w=9'L/~~S3xi;<6;nx|[t)\ ~)_-םݐe;neV\RߓV@<xc+))_O| >c?!&,4VMW~~~*ϳc&fawess LF-3>u8) ($Q忧x!.JKxGzozCQhDP I^~_Ma*jP3b&L- #>kL3լ) S{sGh^T$%Rx~bKYmȉyq #ZHhl|^z'Gdy+lqS"r]VSEk\tGQjuYZŃ_M<gD7_2 ZiݠtgxGL+zir)r ]u#Ksl9h%!"5PAYf#y0[S aD@+EfLM9Dt^ûgR}sg8^$4n/X+E13դJBwvR;Vx3< )u3lg,=8 v;Ajydh166J+D(h7y3:Pi~x ?;Y}(<۷]Ӡrҕ -4/PFk xν+Z5MP iELX&}lyOQ0I c92HCc#^8b~!r v*$c?9òm:|%S,|F:p|eӮǸ6>Nx?|C(%8M[`$.o!4}0Z3g]?zxc-Jy#k)w w޶iץ+XVCBK.Sq'yy`pN,i:[YKOiah%t}>__9AD#qN(=MbPd8V]sg/q#h<畣]wR$' ԓcRqߏ+X37T:e8{]` YAySJc #q (Eȭ) 4GS4c@wCei'9y' ҰgD3s<6<,K:dT ,Zt]Di74EQs趪T]P8W*E)C|/|-FD(A*S~\$D(5B vݶ"wlܲN,$=\qq$N%mPamA;iQ+K=&N!LPcڝQG !aQm}t9tkL]Ha%I"Zq>"2$t:УGyXa ,`$,RKQT&9Z=FJ(=s^P^SOU45Wge=,@XJT-a)'eb0Cu5u 5,,RTޯS}&,47J~54+u6\34;/t1 ~CW_tYU*4!E7 F:aCFy-,{Q#, SaP\(P|&Fkl;7xm;2[QYTH=Z!!JAx4kUEsY $ y҂(p *C\DS?/R窅4K6;L%|O}7+X;Vwi>}//e< d~fc58/~h}yI}/%'%j}9~j5`XF~#+I/릙}d?;{/*0FҮ{vO?Ad,5wӢog>߷B2PG*ta+1 oi9O[YkkتP)B(tVoyi[mh ,G 7S}֥]+])D ctxsޚ%P~h𒡶.9AaApSv30+=.Ƽ6vUdD3EoȧVf(|gQB'r|Ԏ#Gti395ӓݰHg؎(݇fY&PR_NejO朗Il/"@z:MPh^1>,[+E$pRAJB9q3=ӻ{7A\LMZ Y ՊI!,@P1Y9- UuF7U|o9=y Wz+r«+^9Ay<\y;^c׮bғf=QHoa!L+g{H%BĠgaY._bD/p>յaHX Yj%1O0 b bЦE~8?~gl^;~7F=vmoë[U!@ȀH"CLIZvǟ~',Mei~hGc_x\>#8{1~{ ih%KJrWpϯ~}STq/_oˏq'l߹s35:)Wϧ(уǙ`=7/[?_%&nhպ>žM fDSE9}I_dZW%Klq5(jU%j;^]=,YZz# 1 yVTڈ ŕLnNXЇZo -JiHkr"c-<^ζ̂Wd k.c9x-6l\M^ J R/u@Xje(Bʘm) 5~nQw| FR7Ϋ6G?<+xN;A vvm#pa_~ ]:AY+a.JXBݴ*L6 \X7N \g& -eW O #m>6O?2;nȆ58/h1Vl|7/ȕkku4ǏXvx ^ d!AX,0r<@Xv ZL\͸0#Ӽs49֬Yh)=R\TY*kdAP:R26o^+o\*Ld]rw9v:툖Ym?sw-|淫j{m1^aAQƉX\ry4agvQ/6CJR˪BRɘX6GopkX{Jre&ZIəo<0<'^8~u-;waIrfK[\R,X܀\c]׏q6^6 E^㥃qƊ+H%(M`4;y-QT脈'r7 ,Ks|!78 ,t'oI\K+]R(|qv#6obj333RpvV^̓~].Tr&cߝ7pq} 㫗ο~˘U$Pu 3ǹHSpiHR~o$,sф%d_`i[ܹs@e Srm牧I[0JExhY9v.HI^yM<sC +#~AG'kQrq!as0fx 0a}׏`֭beafvM6q x }#O0jI-"$"Q.W bbW ^[:xcr ILxXFٙtdd3 ͫ12=) 8HMAw:eڵ!K3yvQ.MitgUCcdi6X]hKcqsB\CHªw^ثY}+Y^79_3#&`{Fjm?Lvl$܄F5TI+b,q˲rDXZoPl˺~L~!ҟnNw{URaXGQ+5T#ľ$=As'Od[v{N<ز}{v?;UV9r4G}cKAc,ۺ3T;4`+~ZОH۰\T&A09|_B%SSeܼk;^ݏ5A9Iw:cyvt1ZF/Ȥ LrNsҴ}u>#r0zA;&ٰa otL ' :&ɏ|k鹔 +aJk\5[V`3qa#Kgò<7h/ܸe=Q %cGUSY.ߺUk>{3$+W[TA@v! 0yK@@@U3_آ22 $ ((mPVt @룪<*+޾.΄(dhZP\tjA@?d2Ya1^ ~ ˠ.vl=D۞Ì{4&N}7̌l6"asgRihдxQ}!&vCh;S3Yv$A"MB~/@B v 1SXf1}mj }y*7OEt4@a_A< qqJrrTȣ{[tA]cKo'V?LWP(>@oekO!V@V%,^a$^.^a:9^Z9#iE~] 2X7džSwVpVBHqoϚx7MAnN>Q; sZv,qqp+#=5?݀J薢Rn =5ӦaKk>\œ9ܹ-aKk`Ͳw'QL65ޱ=HxoJԴ#(!믫-m23}Z4h"P{eP[[-oZGّzЃ1`#gFl޸ @p`4~ktj-yHؼyTV7yT$l"(@W?B&DcM 'dA^UR/Y|vkg2++R[L>ճؑp]3lAt4xxٻu 9:*+nPzjce!VOnfihvOOwFO!=5`,ot)AFZ]\ɿyga\9ytzr2 ٵ)?y;dZ!;+ۺ=-.(kmAEy#_+U=øvǟ$\:g.-ΰVtFȾVs^.hjűr摇MR?Zz ֵʻX(( v>pYPUWB)7V﮴بJppjJ<(]bM>].7 0eN4"YLټ/N=),L[)u"8$ɛaWHh RpM^tw2BAn k])qQg'<<}(cO"CKHoу>}{A@rswa@`q(۬W(1#f|׃IQZ)뛃D(-0yx6ܻ gZ~=A`?&> n 'SǢPȀVz;Q(dL2& &vqqJ3qqJbb[_@PNF1#f uA)2#fJ{ vV=gϫ8vz1pAE=,F 쵒Al3sѯ7 azǣ /(sQPNF C|CKBRy>[U`+/r-[,o!1Q򗗶DQNkGC: ,[̅ˇlqߞ_Î-9}ZJ4TWС f-/mEA}zV"=(N ]e].3RYࡇH~e64b#'D P*cy/Y=prv5k_tj8xȎ|,KPFa޴9qV@J,FqcOD` cu:O ʸq NffFMu/W$(tQ=H?ۿEW(UPA0dYa (f O< >nxY4]0qc9uFRcpH$Eǰ`X́&c~t\ݑS0f}qܵż[X|slؗl3&e`i=8w:W{HJӭ[U2BlxP@@9h B@41濿 `Q=зp$(0Ao@P As@PئB,Aj( - U @PA(0R"@@ 82Ͽ ` @@PAldy `YA[h?PPA vlX"PPA Zf@PA@2LP#7#E $0xZ `@@@)7)@PӃ@ (7BaGQPR}S; (ؒ4Zk=@LuwP ^;nt,5grm-5sHjJEǰ`Xɿ@ ε\< y/(+t*+pvΰy8 vZQL?̤zsUV `ト3K8CeEτUbv Y0 `z`@CZPA5=h+0zhB8f7"XP+yZmlz X_@Pٵ;!=ϹKw0""A B D:fvPTX/PWu)Jc$%p)#ETTQ]wx(Qу;a$Jy"l^e߮Cfs)K6Э_~KH@Ťi ,kzoCغZQuCknq ]Fq 7wΌٓ;s`oMwؼq "y<ڟJ)0c$^ʠ~w"_o!.J:hZ6|e/fp@Gh(v[>q? wwWּu,2YLkh)W3;m :~vˇ|00c~jСO7ʊX0@`pN%ΠF Pc СـgWf@@pl;_!aA*O%^j֮\åѼzlq%8K?+Qki*jvaHdـz7]L5ch²?`Qh9Fk&9YLώw;0R;wxw?s9[w`ѻ߱gу}tt^7B/{t.~7P_1RW8̥_N\$TgJ*7x:tF=h|Sc飨O̅&K\0}ʽݹa#M;W4i\tG٨3Ջ7Ali52z::w.yp=c1J.\? |G{uu,/_)Ӯ왋‹E Hغf=L7;&eoo%׹o#,'x¬c'xH{gEjZS݉(}GYM_O4ϛO@V/{$vSn!evSl4&u jyx_iYX_}v:[ÖM;I</Qb\r%JT}Ed6x&xElŅ[>\6|ɦ(ZaşlO<}Zc6t5 P] (@]]=^Zk񲷸 Yҫ,RRZXg~%(@M8w }CxZ@n(gG^q?|<^+V17xF\ 8n^z$言Mz%R, -+̌lATWYPغ\+ۓ[Rjg[vjB?Y?!vl-(@;<gW+fYaYUpq:܆yQ an<1jj2 <0?߳^$%G嵜87WVZ(Vs gU*FrVk2tU PUQkl~[CkGFzV?l^—Hڂ+y4Ugs/ jW  0 .pnpPJr^9fPzg/-NMgųYZ B[klk0ܲFx\QUu5ρk$l)';?Ѫ @gr!%軆Vqq#[u)_~~_Nc1Z4[d .5K7Ec-rߦj. 6{(&YݿE=wZE XF{|, cN:[I'l~VGP7ƘvN[* 5oyִiaA~%/U䓟S^K8өSPHUB 4 LK(Qm=k-wx(iR(l |Z{' ׇȀt]~) r )Ngd` XCE W'6QуP- pU Gή>.":(9Or?[Np!"MR½.s,@Fb[aw$pqvc]zpe` `iXP*̘= yyfΞb1 &v9 ur.;2Ѻ #дZPz'7hU 'wہNH!voM!5%d [Qo OTmyA*o } :s_9=|* EƯBїh:.ew\%&AKUu0~(~!<4X;ܙH$_deX"F ݲaߧ חn5UuuSG2P5 0yz9w'=y{̌e ˼9y/O`dY/f{f'xy{ڃq+ 07N}M \@"o3 ˱+^Aw̛BwACu<#{UULCJVX7#rڄr#˜8kAM4>Om D P#\ ;vo`(FěvM`[Da tvJw9 9ïPiK=iq{`-És0 *` ص46e hi @oKA2g'ҧvaIҧ"^|>_!W wq09" ֣'8Q_Й-aR>2w(^ZsٗLYiϙ5^>ɖ]_ yط:"հ4ouDE/xn](@S/i3BB)rcwtcc|4i}ur#stg촁 ΐ{V~[p61 ɹbC:KAZ V7_nfKrF9@3',W?.v^ݕ_YʽmV"V/}oD~ke.s&}:I$x6s"3McʴxzÑPeZ*RA7gG^6`}UՠP\fԂu( PeɁ'1/v3b&+OS3ټq ̅sx( "??RH!K$i3^!}vW2lL8~{h H:lQ0 ċP+lfn$|c0u @3KRsqSHϢR􀏗~^ #*zc款;q:SE; ro!2Ҳȥ+É #˜<}<SԣtU3CP䊶k5Z.q3RNP{{XBl`<]?#kΏphv n\k+oԐt4٢+Ƅc߽k/ש fUih9mMw#x&uuw`DF"K N'?׋+:֪M=o?2B_ Bw;xx8jU}^}04k0 `[2o՛#N.nL==ep`j껄HP֦O (EdT6)h7Dz^("w4N2CCNtjk(Qބ$_G \|(xpz/ޞ.L3ߞDrlE&fkvRД (@Pop2B[w.k2P)9?ƥW9#ښNMJ nXd Vl َBW*P; ],@!I))(CաQkn2H$<]B24-u*Kr]҃z Yi6oa~x0mUc4P!(~ZB~8t H5P(caCûvC_E(@STǍ9u-9FגccT9٦뤦:V'p)ym[9et ߷E.r:'q 6j.rDVjG숈lfSdQtWGP m5?p!9H J ˈ7SwR : 4҇۽= ADBIwG%cRS:h<ˉ?ys "eg]I#˙s۰0x&R]Y{G2H;-IͶZ4{xD&3#)0aʦPaqEqBT&/7GJ jt6YB)јy8Vk( Ar^osGgf]Dch ;>r V˕QUeP"''G}z3L&ԁ `\gePF˙57ήƔ<A=8c:*Riѐ88v>dO hd|}Y23Iؼͻ8t[c)5iNWxh%QsR)hZJK*ٻ%>HMk z0uPΝ!;'?oMߞdʠ7k," `">+>z22 bYDEEハZ\\LQQEEE$%%mVrscO-w>B!@]mgNd7bOxze$DmMso`ޯGWj GdG^.9OVz6e7pqt Џ41ѡ{Kt0z=?`ҵ^/ǟ`ܹӧU_z=W_dPWʙB}84ؽM_l.7)=6̬ 6TVr_)K:(TChdPr׈̽w~N]tE P\tNcŸ5ywky/oOA:KSi9t&tAɠa<";c^obZ1nR9i=Za[zj*;{=ry0!R/p߼G ?߿CU1r.M'D'A(-$%*om3xD/;صZe7ysݥv[޽\I:@M;:nM?lߟS3e|l)Arf( 6n`d:(#-Cfrѳ1~nRxjB_?>밠&t8#kּoBaL.RɛokXt9|UȠ+T*!"2)s-)'ؿ-߽fD] GBՌp1୞uϭGRyRA9Y>}%Kk׮壏?PCdt z=%=m,%HГ~#a/{5:cɵ0/OIbH{ Ё枘;f?dF=1SUY-&!Hʹء a4 wYҋ'XcyC ,{SPKkWCw$R)>ZWCPA7{%#G0zrb`MU=GvTpY37 Z7 `N1>3gZt,۶m&9}?=Z ɹ/_@; g<[$'a0VCF1c e̙DE a^cB2"C3/gH:{-<:HXZA]ķ_mfUV'HXj5~LALɶxSB{ ?𚗚 _Ǔ|kmAttռ"[׃-vjU(Gu5tVlٴYf[ݸf͚-̄/?(gLKzhػW: /*g\RϓW ( }{묳>l-(\} 2ww7<(( `à3ٺ_ qа@dfh}_T2Ҳ}*!\5U~6a <Ķ6d+$s\,8pꪚV dkKvAZv?y (@3 TjrڃZ%={&~yYB"x{{sYlOϿYĀ #HH$cfH@"G sXқ^={ "nof^OV|=s}n>͗2r:|p @"q}]Vkݩi4Jۙ!VC!HP4uS :twC"J =]J <@"z%^H$WD"Jn 5u *Sݤf'gpK^!V/ԩ,Y &@UUcs/)Y,yO?YKn.[۟GUBnVkʵР3 @g 4m7nqdn(c-( CCPɍ@MCNpzi}CAڀ "gDEEYضoΠ!~6'\&>'D݀b1l=>+p ],()(ٶmMm[3Yd`z;*8ș`V"Uh#bEjjֳHZZ:2 lY O'[* 1VFzXV\az+X%&ĐH$*h\?C7;e xNNbǎVY f-ORV`5O>V@m'+lpppjjj8qcbFϗV#peam3gsl ( ځXd )O>Et:?82,{ZLd3ke/8nhrʒvuprv-püfkc?1S-"[Ow} 䜭̸5z7_Npx/=r!r!aA|}bOOO~aO>&nwv:<"&cwq$RwG)NܶmC8߼˲e/sϡR.@DRϲ|2.c'%&H$Zz<fd]Kl}}A:sOgM޳ ի>֫Wrٳw{njWЏ/R[>;J.8@PJsg X謁@C~L܂D#::+WR^^~-//gŊ 6 &n!rp?ꁇ;{3KrWkYĶߵ+KPۓm7ɗغ-!ꫤ)hHדʫJTH೯}_)mpptOyG!2#Xv)ٙx>K9ܸQNMu Օ Dv'C9_P6{b@@!v,!!K@PAl_b @@@@aP6 z@IENDB`qvge-0.6.3/pad_file.xml000066400000000000000000000106241405165517400147620ustar00rootroot00000000000000 3.11 PADGen 3.1.1.50 http://www.padgen.org Portable Application Description, or PAD for short, is a data set that is used by shareware authors to disseminate information to anyone interested in their software products. To find out more go to http://pad.asp-software.org Ars Masiuk https://github.com/ArsMasiuk/qvge Ars Masiuk ars.masiuk@gmail.com Ars Masiuk ars.masiuk@gmail.com ars.masiuk@gmail.com ars.masiuk@gmail.com ars.masiuk@gmail.com Qt Visual Graph Editor 0.5.5 07 15 2020 Freeware Minor Update Install and Uninstall Linux,Linux Gnome,Linux GPL,Linux Open Source,Unix,Win2000,Win7 x32,Win7 x64,WinOther,Other English Graphics Graphic Apps::Editors 33000000 32226 31.47 N Days graph,editor,visual,interactive,graphviz,dot,gexf,graphml Qt Visual Graph Editor Qt Visual Graph Editor - Software to create, manipulate, open and store graphs Qt Visual Graph Editor - Software to interactively create, manipulate, open and store graphs within various open formats (Graphviz/DOT, GEXF, GraphML...) Qt Visual Graph Editor - Software to interactively create, manipulate, open and store graphs within various open formats (Graphviz/DOT, GEXF, GraphML...) Qt Visual Graph Editor - Software to interactively create, manipulate, open and store graphs within various open formats (Graphviz/DOT, GEXF, GraphML...) https://github.com/ArsMasiuk/qvge https://user-images.githubusercontent.com/19762856/85934275-2a985480-b8e1-11ea-81a9-a5b81f3365e2.PNG https://raw.githubusercontent.com/ArsMasiuk/qvge/master/icon.png https://sourceforge.net/projects/qvge/files/0.5.5/qvge-0.5.5-setup-64bit.exe/download https://github.com/ArsMasiuk/qvge/releases/download/0.5.5/qvge-0.5.5-setup-64bit.exe qvge-0.6.3/qvge.cppcheck000066400000000000000000000011331405165517400151340ustar00rootroot00000000000000 qvge-cppcheck-build-dir win64 false true false 10 qt qvge-0.6.3/src/000077500000000000000000000000001405165517400132615ustar00rootroot00000000000000qvge-0.6.3/src/3rdParty/000077500000000000000000000000001405165517400147715ustar00rootroot00000000000000qvge-0.6.3/src/3rdParty/common.pri000066400000000000000000000003241405165517400167740ustar00rootroot00000000000000include(../lib.pri) # compiler stuff win32-msvc*{ QMAKE_CXXFLAGS += /MP } # output CONFIG(debug, debug|release){ DESTDIR = $$OUT_PWD/../../lib.debug } else{ DESTDIR = $$OUT_PWD/../../lib } qvge-0.6.3/src/3rdParty/qprocessinfo/000077500000000000000000000000001405165517400175045ustar00rootroot00000000000000qvge-0.6.3/src/3rdParty/qprocessinfo/LICENSE000066400000000000000000000024501405165517400205120ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2016, Baldur Karlsson All rights reserved. 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. 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 HOLDER 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. qvge-0.6.3/src/3rdParty/qprocessinfo/QProcessInfo000066400000000000000000000002731405165517400220040ustar00rootroot00000000000000// Copyright (c) 2016, Baldur Karlsson // // Licensed under BSD 2-Clause License, see LICENSE file. // // Obtained from https://github.com/baldurk/qprocessinfo #include "qprocessinfo.h" qvge-0.6.3/src/3rdParty/qprocessinfo/README.md000066400000000000000000000010051405165517400207570ustar00rootroot00000000000000# QProcessInfo Simple Qt class to enumerate running processes on a system # Building Should just be able to drop into any Qt project and go, it deliberately doesn't have any dependencies that shouldn't already be there (entirely Qt code on unix, only kernel32.dll on windows). # TODO Only tested briefly on Windows and Linux, enough for my purposes. Window titles are only present on windows and if xdotool is available on linux, on other systems they're always empty. # License 2-clause BSD license. Go hog wild! qvge-0.6.3/src/3rdParty/qprocessinfo/qprocessinfo.cpp000066400000000000000000000236361405165517400227350ustar00rootroot00000000000000// Copyright (c) 2016, Baldur Karlsson // // Licensed under BSD 2-Clause License, see LICENSE file. // // Obtained from https://github.com/baldurk/qprocessinfo #include "qprocessinfo.h" #if defined(Q_OS_WIN32) #include #include typedef DWORD(WINAPI *PFN_GETWINDOWTHREADPROCESSID)(HWND hWnd, LPDWORD lpdwProcessId); typedef HWND(WINAPI *PFN_GETWINDOW)(HWND hWnd, UINT uCmd); typedef BOOL(WINAPI *PFN_ISWINDOWVISIBLE)(HWND hWnd); typedef int(WINAPI *PFN_GETWINDOWTEXTLENGTHW)(HWND hWnd); typedef int(WINAPI *PFN_GETWINDOWTEXTW)(HWND hWnd, LPWSTR lpString, int nMaxCount); typedef BOOL(WINAPI *PFN_ENUMWINDOWS)(WNDENUMPROC lpEnumFunc, LPARAM lParam); namespace { struct callbackContext { callbackContext(QProcessList &l) : list(l) {} QProcessList &list; PFN_GETWINDOWTHREADPROCESSID GetWindowThreadProcessId = NULL; PFN_GETWINDOW GetWindow = NULL; PFN_ISWINDOWVISIBLE IsWindowVisible = NULL; PFN_GETWINDOWTEXTLENGTHW GetWindowTextLengthW = NULL; PFN_GETWINDOWTEXTW GetWindowTextW = NULL; PFN_ENUMWINDOWS EnumWindows = NULL; }; }; static BOOL CALLBACK fillWindowTitles(HWND hwnd, LPARAM lp) { callbackContext *ctx = (callbackContext *)lp; DWORD pid = 0; ctx->GetWindowThreadProcessId(hwnd, &pid); HWND parent = ctx->GetWindow(hwnd, GW_OWNER); if(parent != 0) return TRUE; if(!ctx->IsWindowVisible(hwnd)) return TRUE; for(QProcessInfo &info : ctx->list) { if(info.pid() == (uint32_t)pid) { int len = ctx->GetWindowTextLengthW(hwnd); wchar_t *buf = new wchar_t[len + 1]; ctx->GetWindowTextW(hwnd, buf, len + 1); buf[len] = 0; info.setWindowTitle(QString::fromStdWString(std::wstring(buf))); delete[] buf; return TRUE; } } return TRUE; } QProcessList QProcessInfo::enumerate(bool includeWindowTitles) { QProcessList ret; HANDLE h = NULL; PROCESSENTRY32 pe = {0}; pe.dwSize = sizeof(PROCESSENTRY32); h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(Process32First(h, &pe)) { do { QProcessInfo info; info.setPid((uint32_t)pe.th32ProcessID); info.setName(QString::fromStdWString(std::wstring(pe.szExeFile))); ret.push_back(info); } while(Process32Next(h, &pe)); } CloseHandle(h); if(!includeWindowTitles) return ret; HMODULE user32 = LoadLibraryA("user32.dll"); if(user32) { callbackContext ctx(ret); ctx.GetWindowThreadProcessId = (PFN_GETWINDOWTHREADPROCESSID)GetProcAddress(user32, "GetWindowThreadProcessId"); ctx.GetWindow = (PFN_GETWINDOW)GetProcAddress(user32, "GetWindow"); ctx.IsWindowVisible = (PFN_ISWINDOWVISIBLE)GetProcAddress(user32, "IsWindowVisible"); ctx.GetWindowTextLengthW = (PFN_GETWINDOWTEXTLENGTHW)GetProcAddress(user32, "GetWindowTextLengthW"); ctx.GetWindowTextW = (PFN_GETWINDOWTEXTW)GetProcAddress(user32, "GetWindowTextW"); ctx.EnumWindows = (PFN_ENUMWINDOWS)GetProcAddress(user32, "EnumWindows"); if(ctx.GetWindowThreadProcessId && ctx.GetWindow && ctx.IsWindowVisible && ctx.GetWindowTextLengthW && ctx.GetWindowTextW && ctx.EnumWindows) { ctx.EnumWindows(fillWindowTitles, (LPARAM)&ctx); } FreeLibrary(user32); } return ret; } #elif defined(Q_OS_UNIX) #include #include #include #include #include QProcessList QProcessInfo::enumerate(bool includeWindowTitles) { QProcessList ret; QDir proc(QStringLiteral("/proc")); QStringList files = proc.entryList(); for(const QString &f : files) { bool ok = false; uint32_t pid = f.toUInt(&ok); if(ok) { QProcessInfo info; info.setPid(pid); QDir processDir(QStringLiteral("/proc/") + f); // default to the exe symlink if valid QFileInfo exe(processDir.absoluteFilePath(QStringLiteral("exe"))); exe = QFileInfo(exe.symLinkTarget()); info.setName(exe.completeBaseName()); // if we didn't get a name from the symlink, check in the status file if(info.name().isEmpty()) { QFile status(processDir.absoluteFilePath(QStringLiteral("status"))); if(status.open(QIODevice::ReadOnly)) { QByteArray contents = status.readAll(); QTextStream in(&contents); while(!in.atEnd()) { QString line = in.readLine(); if(line.startsWith(QStringLiteral("Name:"))) { line.remove(0, 5); // if we're using this name, surround with []s to indicate it's not a file info.setName(QStringLiteral("[%1]").arg(line.trimmed())); break; } } status.close(); } } // get the command line QFile cmdline(processDir.absoluteFilePath(QStringLiteral("cmdline"))); if(cmdline.open(QIODevice::ReadOnly)) { QByteArray contents = cmdline.readAll(); int nullIdx = contents.indexOf('\0'); if(nullIdx > 0) { QString firstparam = QString::fromUtf8(contents.data(), nullIdx); // if name is a truncated form of a filename, replace it if(firstparam.endsWith(info.name()) && QFileInfo::exists(firstparam)) info.setName(QFileInfo(firstparam).completeBaseName()); // if we don't have a name, replace it but with []s if(info.name().isEmpty()) info.setName(QStringLiteral("[%1]").arg(firstparam)); contents.replace('\0', ' '); } info.setCommandLine(QString::fromUtf8(contents).trimmed()); cmdline.close(); } ret.push_back(info); } } if(includeWindowTitles) { // get a list of all windows. This is faster than searching with --pid // for every PID, and usually there will be fewer windows than PIDs. QStringList params; params << QStringLiteral("search") << QStringLiteral("--onlyvisible") << QStringLiteral(".*"); QList windowlist; QString inPath = QStandardPaths::findExecutable(QStringLiteral("xdotool")); if(inPath.isEmpty()) { // add a fake window title to the first process to indicate that xdotool is missing if(!ret.isEmpty()) ret[0].setWindowTitle(QStringLiteral("Window titles not available - install `xdotool`")); } else { QProcess process; process.start(QStringLiteral("xdotool"), params); process.waitForFinished(100); windowlist = process.readAll().split('\n'); } // if xdotool isn't installed or failed to run, we'll have an empty // list or else entries that aren't numbers, so we'll skip them for(const QByteArray &win : windowlist) { // empty result, no window matches if(win.size() == 0) continue; bool isUInt = false; win.toUInt(&isUInt); // skip invalid lines (maybe because xdotool failed) if(!isUInt) continue; // get the PID of the window first. If one isn't available we won't // be able to match it up to our entries so don't proceed further params.clear(); params << QStringLiteral("getwindowpid") << QString::fromLatin1(win); uint32_t pid = 0; { QProcess process; process.start(QStringLiteral("xdotool"), params); process.waitForFinished(100); pid = process.readAll().trimmed().toUInt(&isUInt); } // can't find a PID, skip this window if(!isUInt || pid == 0) continue; // check to see if the geometry is somewhere offscreen params.clear(); params << QStringLiteral("getwindowgeometry") << QString::fromLatin1(win); QList winGeometry; { QProcess process; process.start(QStringLiteral("xdotool"), params); process.waitForFinished(100); winGeometry = process.readAll().split('\n'); } // should be three lines: Window \n Position: ... \n Geometry: ... if(winGeometry.size() >= 3) { QRegExp pos(QStringLiteral("Position: (-?\\d+),(-?\\d+)")); QRegExp geometry(QStringLiteral("Geometry: (\\d+)x(\\d+)")); QString posString = QString::fromUtf8(winGeometry[1]); QString geometryString = QString::fromUtf8(winGeometry[2]); int x = 0, y = 0, w = 1000, h = 1000; if(pos.indexIn(posString) >= 0) { x = pos.cap(1).toInt(); y = pos.cap(2).toInt(); } if(geometry.indexIn(geometryString) >= 0) { w = geometry.cap(1).toInt(); h = geometry.cap(2).toInt(); } // some invisible windows are placed off screen, if we detect that skip it if(x + w < 0 && y + h < 0) continue; } // take the first window name { params.clear(); params << QStringLiteral("getwindowname") << QString::fromLatin1(win); QProcess process; process.start(QStringLiteral("xdotool"), params); process.waitForFinished(100); QString windowTitle = QString::fromUtf8(process.readAll().split('\n')[0]); for(QProcessInfo &info : ret) { if(info.pid() == pid) { info.setWindowTitle(windowTitle); break; } } } } } return ret; } #else QProcessList QProcessInfo::enumerate(bool includeWindowTitles) { QProcessList ret; qWarning() << "Process enumeration not supported on this platform"; return ret; } #endif QProcessInfo::QProcessInfo() { m_pid = 0; } uint32_t QProcessInfo::pid() const { return m_pid; } void QProcessInfo::setPid(uint32_t pid) { m_pid = pid; } const QString &QProcessInfo::name() const { return m_name; } void QProcessInfo::setName(const QString &name) { m_name = name; } const QString &QProcessInfo::windowTitle() const { return m_title; } void QProcessInfo::setWindowTitle(const QString &title) { m_title = title; } const QString &QProcessInfo::commandLine() const { return m_cmdLine; } void QProcessInfo::setCommandLine(const QString &cmd) { m_cmdLine = cmd; } qvge-0.6.3/src/3rdParty/qprocessinfo/qprocessinfo.h000066400000000000000000000014261405165517400223730ustar00rootroot00000000000000// Copyright (c) 2016, Baldur Karlsson // // Licensed under BSD 2-Clause License, see LICENSE file. // // Obtained from https://github.com/baldurk/qprocessinfo #pragma once #include #include #include class QProcessInfo; typedef QList QProcessList; class QProcessInfo { public: QProcessInfo(); static QProcessList enumerate(bool includeWindowTitles = true); uint32_t pid() const; void setPid(uint32_t pid); const QString &name() const; void setName(const QString &name); const QString &windowTitle() const; void setWindowTitle(const QString &title); const QString &commandLine() const; void setCommandLine(const QString &cmd); private: uint32_t m_pid; QString m_name; QString m_title; QString m_cmdLine; }; qvge-0.6.3/src/3rdParty/qsint-widgets/000077500000000000000000000000001405165517400175735ustar00rootroot00000000000000qvge-0.6.3/src/3rdParty/qsint-widgets/README.txt000066400000000000000000000173431405165517400213010ustar00rootroot00000000000000QSint Widgets module Taken from QSint library 0.4.x by Sintegrial Technologies https://sourceforge.net/projects/qsint Licensed under LGPLv3 ----------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. qvge-0.6.3/src/3rdParty/qsint-widgets/colorbutton.cpp000066400000000000000000000106431405165517400226550ustar00rootroot00000000000000#include "colorbutton.h" #include "colorgrid.h" #include #include #include #include #include #include namespace QSint { ColorButton::ColorButton(QWidget *parent) : QToolButton(parent), m_mode(PM_COLORGRID_DIALOG), m_tooltipMode(TM_NAMED_HEX_COLOR), m_labelMode(TM_NAMED_COLOR) { //setToolButtonStyle(Qt::ToolButtonTextBesideIcon); setPopupMode(QToolButton::MenuButtonPopup); // build up menu QMenu *menu = new QMenu(this); setMenu(menu); m_grid = new ColorGrid(this); m_grid->setPickByDrag(false); m_grid->setClickMode(ColorGrid::CM_RELEASE); connect(m_grid, SIGNAL(picked(const QColor&)), this, SLOT(setColor(const QColor&))); connect(m_grid, SIGNAL(accepted()), menu, SLOT(hide())); QPixmap npm(cellSize(), cellSize()); drawColorItem(npm, QColor()); m_noColorAction = menu->addAction(npm, tr("No Color")); connect(m_noColorAction, SIGNAL(triggered()), this, SLOT(onNoColorButton())); m_noColorAction->setVisible(false); // disabled by default m_colorGridAction = new QWidgetAction(this); m_colorGridAction->setDefaultWidget(m_grid); menu->addAction(m_colorGridAction); m_colorDialogAction = menu->addAction(tr("Choose Color...")); connect(m_colorDialogAction, SIGNAL(triggered()), this, SLOT(onDialogButton())); connect(this, SIGNAL(colorChanged(QColor)), this, SIGNAL(activated(QColor))); connect(this, SIGNAL(clicked()), this, SLOT(onClicked())); setColorScheme(QSint::OpenOfficeColors()); setColor(Qt::white); setPickMode(PM_COLORGRID_DIALOG); } ColorButton::~ColorButton() { } void ColorButton::setColor(const QColor& color) { if (m_color != color || text() != m_buttonText) { m_color = color; QPixmap pm(iconSize()); drawColorItem(pm, m_color); setIcon(QIcon(pm)); setText(m_buttonText = getColorName(m_labelMode, m_color)); if (m_tooltipMode != TM_NONE) setToolTip(getColorName(m_tooltipMode, m_color)); Q_EMIT colorChanged(color); } } void ColorButton::drawColorItem(QPixmap &pm, const QColor& color) { QPainter p(&pm); if (!color.isValid()) { p.setBrush(Qt::white); p.setPen(QPen(Qt::black, 1)); p.drawRect(pm.rect().adjusted(0, 0, -1, -1)); p.setPen(QPen(Qt::red, 1)); p.drawLine(pm.rect().topLeft(), pm.rect().bottomRight()); } else { p.setBrush(color); p.setPen(palette().color(QPalette::Shadow)); p.drawRect(pm.rect().adjusted(0, 0, -1, -1)); } } QString ColorButton::getColorName(ColorButton::TextMode tm, const QColor &color) const { if (!color.isValid()) { return tr("None"); } QString namedColor = m_colorScheme->colorName(color); switch (tm) { case TM_NAMED_COLOR: return namedColor; case TM_HEX_COLOR: return color.name(); case TM_NAMED_HEX_COLOR: if (namedColor == color.name()) return namedColor; else return namedColor + " (" + color.name() + ")"; default:; } return ""; } void ColorButton::setPickMode(PickMode mode) { m_mode = mode; m_colorGridAction->setVisible(mode == PM_COLORGRID || mode == PM_COLORGRID_DIALOG); m_colorDialogAction->setVisible(mode == PM_COLORDIALOG || mode == PM_COLORGRID_DIALOG); } void ColorButton::resizeEvent(QResizeEvent * /*event*/) { QPixmap pm(iconSize()); drawColorItem(pm, m_color); setIcon(QIcon(pm)); } void ColorButton::onDialogButton() { QColor c = QColorDialog::getColor(m_color, this); if (c.isValid()) { setColor(c); Q_EMIT colorChanged(c); } } void ColorButton::onNoColorButton() { setColor(QColor()); } void ColorButton::onClicked() { Q_EMIT activated(m_color); } void ColorButton::setColorScheme(const NamedColorsScheme &scheme) { m_colorScheme = &scheme; if (m_colorScheme->gridWidth > 0) { m_grid->setAutoSize(false); m_grid->setWidthInCells(m_colorScheme->gridWidth); } else m_grid->setAutoSize(true); m_grid->setScheme(&m_colorScheme->colors); } void ColorButton::setCellSize(int size) { m_grid->setCellSize(size); } int ColorButton::cellSize() const { return m_grid->cellSize(); } void ColorButton::setTooltipMode(TextMode tm) { m_tooltipMode = tm; } void ColorButton::setLabelMode(TextMode tm) { m_labelMode = tm; } void ColorButton::enableNoColor(bool on) { m_noColorAction->setVisible(on); } } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/colorbutton.h000066400000000000000000000072601405165517400223230ustar00rootroot00000000000000#ifndef COLORBUTTON_H #define COLORBUTTON_H #include "colordefs.h" #include #include namespace QSint { class ColorGrid; class ColorPopup; /** \brief A tool button to select a color from color dialog or grid. \image html ColorButton.png An example of ColorButton ColorButton is an extension of QToolButton designed to allow the user interactively choose a color from popping up dialog window. Depending on PickMode, different kinds of color dialogs will be shown when user clicks left or right mouse button over the ColorButton (see setPickModeLeft() and setPickModeRight() functions). You can modify the outlook of ColorButton by changing appropriate QToolButton properties. For instance, show text along with color box (ToolButtonStyle property), or show drop-down menu arrow (PopupMode property). \image html ColorButtons.png Different types of ColorButton */ class ColorButton : public QToolButton { Q_OBJECT Q_PROPERTY(int cellSize READ cellSize WRITE setCellSize) Q_PROPERTY(QColor color READ color WRITE setColor) Q_PROPERTY(PickMode pickMode READ pickMode WRITE setPickMode) public: /// \brief Defines color dialog type. enum PickMode { /// no dialog PM_NONE, /// standard system color dialog PM_COLORDIALOG, /// color grid based dialog PM_COLORGRID, /// color grid with standard color selector PM_COLORGRID_DIALOG }; enum TextMode { TM_NONE, TM_NAMED_COLOR, TM_HEX_COLOR, TM_NAMED_HEX_COLOR }; /** Constructor. */ ColorButton(QWidget *parent = 0); /** Destructor. */ virtual ~ColorButton(); /** Returns currently selected color. */ inline QColor color() const { return m_color; } /** Returns type of color dialog shown on left mouse click (PM_COLORGRID by default). \sa setPickMode() */ inline PickMode pickMode() const { return m_mode; } /** Sets type of color dialog shown on left mouse click to \a mode. */ void setPickMode(PickMode mode); /** Returns currently active color scheme (by default, defaultColors() is used). \sa setColorScheme() */ inline const NamedColorsScheme& colorScheme() const { return *m_colorScheme; } /** Sets color scheme to \a scheme. */ void setColorScheme(const NamedColorsScheme &scheme); /** Returns size of a color cell in pixels. */ int cellSize() const; /** Sets size of a color cell in pixels to \a size (must be > 0). */ void setCellSize(int size); void setTooltipMode(TextMode tm); void setLabelMode(TextMode tm); /** If \a on is true, it makes possible to select an empty (invalid) color from the drop-down menu. */ void enableNoColor(bool on); public Q_SLOTS: /** Sets current color to \a color. */ void setColor(const QColor& color); protected Q_SLOTS: void onNoColorButton(); void onDialogButton(); void onClicked(); Q_SIGNALS: /** Emitted when user selects a color from the dialog. \a color is the picked color value. */ void colorChanged(const QColor &color); void activated(const QColor &color); protected: virtual void drawColorItem(QPixmap &pm, const QColor& color); virtual QString getColorName(TextMode tm, const QColor& color) const; virtual void resizeEvent(QResizeEvent *event); QColor m_color; QString m_buttonText; PickMode m_mode; TextMode m_tooltipMode, m_labelMode; ColorGrid *m_grid; QWidgetAction *m_colorGridAction; QAction *m_colorDialogAction; QAction *m_noColorAction; const NamedColorsScheme *m_colorScheme; }; } // namespace #endif // COLORBUTTON_H qvge-0.6.3/src/3rdParty/qsint-widgets/colorcombobox.cpp000066400000000000000000000102341405165517400231460ustar00rootroot00000000000000#include "colorcombobox.h" #include #include #include #include #include namespace QSint { ColorComboBox::ColorComboBox(QWidget *parent) : QComboBox(parent), m_listOnly(false) { setDuplicatesEnabled(false); setInsertPolicy(QComboBox::NoInsert); connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int))); setColors(QColor::colorNames()); } void ColorComboBox::setColors(const QStringList &colorNames) { blockSignals(true); QColor current = currentColor(); clear(); for (int i = 0; i < colorNames.count(); i++) { QColor col(colorNames.at(i)); // add to the list addItem(colorIcon(col), colorNames.at(i), col); } setCurrentColor(current); blockSignals(false); // 1st color by default if (currentIndex() < 0 && count()) { setCurrentIndex(0); } } void ColorComboBox::setColors(const ColorList &colors) { blockSignals(true); QColor current = currentColor(); clear(); for (int i = 0; i < colors.count(); i++) { QColor col(colors.at(i)); // add to the list addItem(colorIcon(col), col.name(), col); } setCurrentColor(current); blockSignals(false); // 1st color by default if (currentIndex() < 0 && count()) { setCurrentIndex(0); } } QColor ColorComboBox::currentColor() const { if (currentIndex() >= 0) return currentData().value(); if (m_listOnly) return QColor(); return QColor(currentText()); } void ColorComboBox::allowListColorsOnly(bool on) { if (on != m_listOnly) { m_listOnly = on; if (m_listOnly && currentIndex() < 0 && count()) { setCurrentIndex(0); } } } void ColorComboBox::setEditable(bool editable) { if (editable == isEditable()) return; if (editable && lineEdit()) { connect(lineEdit(), SIGNAL(editingFinished()), this, SLOT(onEdited())); // workaround of QCompleter bug (QTBUG-49165) connect(lineEdit(), SIGNAL(selectionChanged()), this, SLOT(onSelectionTextChanged())); connect(lineEdit(), SIGNAL(textChanged(const QString&)), this, SLOT(onSelectionTextChanged())); } else if (lineEdit()) { lineEdit()->disconnect(); } QComboBox::setEditable(editable); } void ColorComboBox::setCurrentColor(const QColor &color) { int index = findData(color); if (index >= 0) { setCurrentIndex(index); } else { if (m_listOnly && count()) { setCurrentIndex(0); return; } setCurrentIndex(-1); setCurrentText(color.name()); Q_EMIT currentColorChanged(color); } } QIcon ColorComboBox::colorIcon(const QColor &color, int size) { // create icon QPixmap pm(size, size); pm.fill(color); QPen p(Qt::black, 1); QPainter pt(&pm); pt.drawRect(QRect(0,0,size-1,size-1)); return QIcon(pm); } QString ColorComboBox::colorName(const QColor &color) const { int index = findData(color); if (index >= 0) return itemText(index); return color.name(); } void ColorComboBox::onCurrentIndexChanged(int index) { if (index >= 0) { Q_EMIT currentColorChanged(currentColor()); } } void ColorComboBox::onEdited() { QString colorName = lineEdit()->text(); // qDebug() << colorName; if (QColor::isValidColor(colorName)) { if (m_listOnly) { int index = findData(QColor(colorName)); if (index >= 0) { setCurrentIndex(index); } else if (count()) { setCurrentIndex(0); } } else { setCurrentIndex(-1); setCurrentText(colorName); } // qDebug() << currentColor(); Q_EMIT(currentColorChanged(currentColor())); } } void ColorComboBox::onSelectionTextChanged() { // workaround of QCompleter bug (QTBUG-49165) if (completer()) { completer()->setCompletionPrefix(currentText()); } } } qvge-0.6.3/src/3rdParty/qsint-widgets/colorcombobox.h000066400000000000000000000030011405165517400226050ustar00rootroot00000000000000#ifndef QCOLORCOMBOBOX_H #define QCOLORCOMBOBOX_H #include #include "colordefs.h" namespace QSint { class ColorComboBox : public QComboBox { Q_OBJECT public: explicit ColorComboBox(QWidget *parent = 0); /** Sets active color list to \a colorNames. * The names are shown in the way how they are stored in the \a colorNames. */ void setColors(const QStringList& colorNames); /** Sets active color list to \a colors. * The names are shown in the QColor::name() format, i.e. "#RRGGBB" */ void setColors(const ColorList& colors); /** Returns current color (selected or written). */ QColor currentColor() const; void allowListColorsOnly(bool on); bool isListColorsOnly() const { return m_listOnly; } virtual void setEditable(bool editable); QString colorName(const QColor& color) const; static QIcon colorIcon(const QColor& color, int size = 14); Q_SIGNALS: /** Emitted when current color has been changed to \a color. */ void currentColorChanged(const QColor& color); public Q_SLOTS: /** Sets current color to \a color (same as setCurrentColor()). */ void setColor(const QColor& color) { setCurrentColor(color); } /** Sets current color to \a color. */ void setCurrentColor(const QColor& color); protected Q_SLOTS: void onCurrentIndexChanged(int index); void onEdited(); void onSelectionTextChanged(); private: bool m_listOnly; }; } #endif // QCOLORCOMBOBOX_H qvge-0.6.3/src/3rdParty/qsint-widgets/colordefs.cpp000066400000000000000000000144221405165517400222620ustar00rootroot00000000000000#include "colordefs.h" #include namespace QSint { /// named colors QString NamedColorsScheme::colorName(const QColor& color) const { if (colorNames.contains(color.rgb())) return colorNames[color.rgb()]; else return color.name(); } void NamedColorsScheme::addNamedColor(const QColor& color, const QString& name) { colors.append(color); colorNames[color.rgb()] = name; } const NamedColorsScheme& BaseColors() { static NamedColorsScheme s_colors; if (s_colors.colors.isEmpty()) { s_colors.gridWidth = 5; s_colors.addNamedColor(Qt::black, QCoreApplication::translate("Colors", "Black")); s_colors.addNamedColor(Qt::white, QCoreApplication::translate("Colors", "White")); s_colors.addNamedColor(Qt::gray, QCoreApplication::translate("Colors", "Gray")); s_colors.addNamedColor(Qt::darkGray, QCoreApplication::translate("Colors", "Dark Gray")); s_colors.addNamedColor(Qt::lightGray, QCoreApplication::translate("Colors", "Light Gray")); s_colors.addNamedColor(Qt::red, QCoreApplication::translate("Colors", "Red")); s_colors.addNamedColor(Qt::darkRed, QCoreApplication::translate("Colors", "Dark Red")); s_colors.addNamedColor(Qt::blue, QCoreApplication::translate("Colors", "Blue")); s_colors.addNamedColor(Qt::darkBlue, QCoreApplication::translate("Colors", "Dark Blue")); s_colors.addNamedColor(Qt::green, QCoreApplication::translate("Colors", "Green")); s_colors.addNamedColor(Qt::darkGreen, QCoreApplication::translate("Colors", "Dark Green")); s_colors.addNamedColor(Qt::cyan, QCoreApplication::translate("Colors", "Cyan")); s_colors.addNamedColor(Qt::darkCyan, QCoreApplication::translate("Colors", "Dark Cyan")); s_colors.addNamedColor(Qt::magenta, QCoreApplication::translate("Colors", "Magenta")); s_colors.addNamedColor(Qt::darkMagenta, QCoreApplication::translate("Colors", "Dark Magenta")); s_colors.addNamedColor(Qt::yellow, QCoreApplication::translate("Colors", "Yellow")); s_colors.addNamedColor(Qt::darkYellow, QCoreApplication::translate("Colors", "Dark Yellow")); //s_colors.addNamedColor(Qt::transparent, QCoreApplication::translate("Colors", "None")); } return s_colors; } const NamedColorsScheme& SvgColors() { static NamedColorsScheme s_colors; if (s_colors.colors.isEmpty()) { s_colors.gridWidth = 0; QStringList names = QColor::colorNames(); for (int i = 0; i < names.size(); i++) { s_colors.addNamedColor(QColor(names.at(i)), names.at(i)); } // avoid bug with "transparent" color name s_colors.colorNames[QColor(Qt::black).rgb()] = QCoreApplication::translate("Colors", "black"); } return s_colors; } const NamedColorsScheme& OpenOfficeColors() { static NamedColorsScheme s_colors; if (s_colors.colors.isEmpty()) { s_colors.gridWidth = 12; s_colors.colors << "#fff" << "#eee" << "#ddd" << "#ccc" << "#b2b2b2" << "#999" << "#808080" << "#666" << "#333" << "#1c1c1c" << "#111" << "#000"; s_colors.colors << "#ff9" << "#f60" << "#f33" << "#f0c" << "#f3f" << "#90f" << "#66f" << "#0cf" << "#6ff" << "#3f9" << "#9f6" << "#cf0"; s_colors.colors << "#ffff00" << "#ff9900" << "#ff6666" << "#ff3399" << "#ff66ff" << "#9933ff" << "#3333ff" << "#3399ff" << "#00ffff" << "#00ff66" << "#66ff66" << "#99ff33"; s_colors.colors << "#cc9900" << "#ff3300" << "#ff0000" << "#ff0066" << "#ff00ff" << "#6600ff" << "#0000ff" << "#0066ff" << "#00cccc" << "#00cc33" << "#00cc00" << "#66ff00"; const NamedColorsScheme& svgNames = SvgColors(); for (int i = 0; i < s_colors.colors.size(); i++) { QString colorName = svgNames.colorName(s_colors.colors.at(i)); s_colors.colorNames[s_colors.colors.at(i).rgb()] = colorName; } } return s_colors; } /// lists ColorList* defaultColors() { static ColorList s_defaultColors; if (!s_defaultColors.isEmpty()) return &s_defaultColors; const int step = 32; for (int b = 0; b <= 256; b += 16) { if (b == 256) b = 255; s_defaultColors.append(QColor(b,b,b)); } for (int r = 0; r <= 256; r += step) { if (r == 256) r = 255; for (int g = 0; g <= 256; g += step) { if (g == 256) g = 255; for (int b = 0; b <= 256; b += step) { if (b == 256) b = 255; s_defaultColors.append(QColor(r,g,b)); } } } return &s_defaultColors; } ColorList* defaultColors2() { static ColorList s_defaultColors2; if (!s_defaultColors2.isEmpty()) return &s_defaultColors2; const int step = 64; for (int b = 0; b <= 256; b += 16) { if (b == 256) b = 255; s_defaultColors2.append(QColor(b,b,b)); } for (int r = 0; r <= 256; r += step) { if (r == 256) r = 255; for (int g = 0; g <= 256; g += step) { if (g == 256) g = 255; for (int b = 0; b <= 256; b += step) { if (b == 256) b = 255; s_defaultColors2.append(QColor(r,g,b)); } } } return &s_defaultColors2; } ColorList* baseColors() { static ColorList s_baseColors; if (!s_baseColors.isEmpty()) return &s_baseColors; for (int i = Qt::black; i <= Qt::darkYellow; i++) s_baseColors.append((Qt::GlobalColor)i); return &s_baseColors; } ColorList* namedColors() { static ColorList s_namedColors; if (!s_namedColors.isEmpty()) return &s_namedColors; QStringList names = QColor::colorNames(); for (int i = 0; i < names.size(); i++) s_namedColors.append(QColor(names.at(i))); return &s_namedColors; } ColorList* openOfficeColors() { static ColorList s_namedColors; if (!s_namedColors.isEmpty()) return &s_namedColors; s_namedColors << "#fff" << "#eee" << "#ddd" << "#ccc" << "#b2b2b2" << "#999" << "#808080" << "#666" << "#333" << "#1c1c1c" << "#111" << "#000"; s_namedColors << "#ff9" << "#f60" << "#f33" << "#f0c" << "#f3f" << "#90f" << "#66f" << "#0cf" << "#6ff" << "#3f9" << "#9f6" << "#cf0"; s_namedColors << "#ffff00" << "#ff9900" << "#ff6666" << "#ff3399" << "#ff66ff" << "#9933ff" << "#3333ff" << "#3399ff" << "#00ffff" << "#00ff66" << "#66ff66" << "#99ff33"; s_namedColors << "#cc9900" << "#ff3300" << "#ff0000" << "#ff0066" << "#ff00ff" << "#6600ff" << "#0000ff" << "#0066ff" << "#00cccc" << "#00cc33" << "#00cc00" << "#66ff00"; return &s_namedColors; } } qvge-0.6.3/src/3rdParty/qsint-widgets/colordefs.h000066400000000000000000000020661405165517400217300ustar00rootroot00000000000000#ifndef COLORDEFS_H #define COLORDEFS_H #include #include #include #include namespace QSint { /** This type defines a list of QColor to be used in \a setScheme() functions. */ typedef QList ColorList; /** Returns default color scheme. \sa setScheme() */ ColorList* defaultColors(); /** Returns second default color scheme. \sa setScheme() */ ColorList* defaultColors2(); /** Returns default color scheme based on 16 base colors. \sa setScheme() */ ColorList* baseColors(); /** Returns default color scheme based on QColor::colorNames() list. \sa setScheme() */ ColorList* namedColors(); ColorList* openOfficeColors(); struct NamedColorsScheme { ColorList colors; QMap colorNames; int gridWidth; void addNamedColor(const QColor& color, const QString& name); QString colorName(const QColor& color) const; }; const NamedColorsScheme& BaseColors(); const NamedColorsScheme& SvgColors(); const NamedColorsScheme& OpenOfficeColors(); } #endif // COLORDEFS_H qvge-0.6.3/src/3rdParty/qsint-widgets/colorgrid.cpp000066400000000000000000000171701405165517400222710ustar00rootroot00000000000000#include "colorgrid.h" #include #include #include #include namespace QSint { ColorGrid::ColorGrid(QWidget *parent) : QWidget(parent), m_cellSize(16), m_widthInCells(32), m_autoSize(false), m_row(-1), m_col(-1), m_idx(-1), m_pickDrag(true), m_clickMode(CM_PRESS), m_colors(0) { setScheme(defaultColors()); //setFixedSize(minimumSizeHint()); setMouseTracking(true); } ColorGrid::~ColorGrid() { } QSize ColorGrid::minimumSizeHint() const { return QSize((m_cellSize+1) * m_widthInCells + 3, (m_cellSize+1) * heightInCells() + 3); } QSize ColorGrid::sizeHint() const { return minimumSizeHint(); } int ColorGrid::heightInCells() const { if (!m_colors) return 0; int d = m_colors->size() / m_widthInCells; if (m_colors->size() % m_widthInCells) d++; return d; } void ColorGrid::setAutoSize(bool autosize) { m_autoSize = autosize; if (m_autoSize && m_colors) { setWidthInCells(sqrt((float)m_colors->count())); } } void ColorGrid::setCellSize(int size) { if (size < 8) size = 8; m_cellSize = size; //setFixedSize(minimumSizeHint()); redraw(); } void ColorGrid::setWidthInCells(int width) { if (width < 1) width = 1; m_widthInCells = width; //setFixedSize(minimumSizeHint()); redraw(); } void ColorGrid::setScheme(const ColorList *list) { if (!list) return; m_colors = list; m_idx = -1; if (m_autoSize && m_colors) { setWidthInCells(sqrt((float)m_colors->count())); } else redraw(); update(); } ///////////////////////////////////////////////////////////////////// void ColorGrid::redraw() { int rows = heightInCells(); int c = m_cellSize+1; // frame m_pix = QPixmap(minimumSizeHint()); QPainter p(&m_pix); p.setBrush(palette().base()); p.setPen(palette().shadow().color()); p.drawRect(m_pix.rect().adjusted(0,0,-1,-1)); int x = 2, y = 2; int idx = 0; for (int j = 0; j < rows; j++, y+=c) { x = 2; for (int i = 0; i < m_widthInCells; i++, x+=c) { if (idx == m_colors->size()) return; p.fillRect(QRect(x,y,m_cellSize,m_cellSize), m_colors->at(idx++)); } } repaint(); } int ColorGrid::index() const { int i = m_widthInCells*m_row + m_col; if (m_col >= m_widthInCells || i < 0 || i >= m_colors->size()) i = -1; return i; } void ColorGrid::paintEvent ( QPaintEvent * /*event*/ ) { QPainter p(this); p.fillRect(rect(), palette().button()); p.drawPixmap(0,0, m_pix); m_hlColor = QColor(); if (m_idx >= 0) { m_hlColor = m_colors->at(m_idx); int c = m_cellSize+1; int x = m_col * c; int y = m_row * c;; p.setPen(QPen(palette().highlight(),2)); p.drawRect(QRect(x+1,y+1,c,c)); } } void ColorGrid::mouseMoveEvent(QMouseEvent *event) { QWidget::mouseMoveEvent(event); m_pos = event->pos(); int c = m_cellSize+1; m_row = m_pos.y() / c; m_col = m_pos.x() / c; int i = index(); if (i != m_idx) { m_idx = i; repaint(); QToolTip::hideText(); if (m_idx != -1) { emit highlighted(m_hlColor); QToolTip::showText(event->globalPos(), m_hlColor.name(), this); if (m_pickDrag && event->buttons() & Qt::LeftButton) { m_selColor = m_hlColor; emit picked(m_selColor); } } } } void ColorGrid::mousePressEvent ( QMouseEvent * event ) { if (!hasFocus()) setFocus(); if (m_clickMode == CM_PRESS && event->button() == Qt::LeftButton && m_hlColor.isValid()) { m_selColor = m_hlColor; emit picked(m_selColor); emit accepted(); } } void ColorGrid::mouseReleaseEvent ( QMouseEvent * event ) { if (!hasFocus()) setFocus(); if (m_clickMode == CM_RELEASE && event->button() == Qt::LeftButton && m_hlColor.isValid()) { m_selColor = m_hlColor; emit picked(m_selColor); emit accepted(); } } void ColorGrid::leaveEvent ( QEvent * /*event*/ ) { QToolTip::hideText(); if (m_idx != -1) { m_idx = -1; repaint(); } } void ColorGrid::keyPressEvent ( QKeyEvent * event ) { QToolTip::hideText(); switch (event->key()) { case Qt::Key_Right: if (m_idx == -1) { m_row = m_col = 0; m_idx = 0; } else { if (++m_col == m_widthInCells) { m_col = 0; m_row++; } m_idx = index(); if (m_idx == -1) { m_row = m_col = 0; m_idx = 0; } } repaint(); m_hlColor = m_colors->at(m_idx); emit highlighted(m_hlColor); event->accept(); return; case Qt::Key_Left: if (m_idx == -1) { m_row = m_col = 0; m_idx = 0; } else { if (--m_col < 0) { m_col = m_widthInCells-1; m_row--; } m_idx = index(); if (m_idx == -1) { m_row = heightInCells()-1; m_idx = m_colors->size()-1; m_col = m_idx % m_widthInCells; } } repaint(); m_hlColor = m_colors->at(m_idx); emit highlighted(m_hlColor); event->accept(); return; case Qt::Key_Up: if (m_idx == -1) { m_row = m_col = 0; m_idx = 0; } else { int h = heightInCells()-1; if (--m_row < 0) { m_row = h; if (--m_col < 0) { m_row = h; m_idx = m_colors->size()-1; m_col = m_idx % m_widthInCells; } } m_idx = index(); if (m_idx == -1 && m_row == h) { m_row--; m_idx = index(); } if (m_idx == -1) { m_row = h; m_idx = m_colors->size()-1; m_col = m_idx % m_widthInCells; } } repaint(); m_hlColor = m_colors->at(m_idx); emit highlighted(m_hlColor); event->accept(); return; case Qt::Key_Down: if (m_idx == -1) { m_row = m_col = 0; m_idx = 0; } else { int h = heightInCells()-1; if (++m_row > h) { m_row = 0; m_col++; } m_idx = index(); if (m_idx == -1 && m_row == h) { m_row = 0; m_col++; m_idx = index(); } if (m_idx == -1) { m_row = m_col = 0; m_idx = 0; } } repaint(); m_hlColor = m_colors->at(m_idx); emit highlighted(m_hlColor); event->accept(); return; case Qt::Key_Return: if (m_idx != -1) { emit picked(m_selColor = m_hlColor); emit accepted(); } event->accept(); return; case Qt::Key_Escape: emit rejected(); event->accept(); return; default: event->ignore(); } return QWidget::keyPressEvent(event); } /////////////////////////////////////////////////////// } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/colorgrid.h000066400000000000000000000115351405165517400217350ustar00rootroot00000000000000#ifndef COLORGRID_H #define COLORGRID_H #include "colordefs.h" #include namespace QSint { /** \brief Class for visual selection of a color from the color grid. \image html ColorGrid.png An example of ColorGrid ColorGrid can use a custom (user-defined) color scheme, as well as one of pre-defined ones (see \a setScheme() function). Also, the size of color cells and their layout can be customized. A color can be picked from the grid with the mouse or with the cursor and Enter keys (see setPickByDrag() and setClickMode() functions). Signal picked() is emitted when the user picks a color from the grid. Signal highlighted() is emitted when the user moves mouse cursor over the grid. */ class ColorGrid : public QWidget { Q_OBJECT Q_PROPERTY(int cellSize READ cellSize WRITE setCellSize) Q_PROPERTY(int widthInCells READ widthInCells WRITE setWidthInCells) Q_PROPERTY(bool autoSize READ autoSize WRITE setAutoSize) Q_PROPERTY(bool pickByDrag READ pickByDrag WRITE setPickByDrag) Q_PROPERTY(ClickMode clickMode READ clickMode WRITE setClickMode) public: /// \brief Defines color selection behavior. enum ClickMode { /// a color is picked when mouse button has been pressed CM_PRESS, /// a color is picked when mouse button has been released CM_RELEASE }; /** Constructor. */ ColorGrid(QWidget *parent = 0); /** Destructor. */ virtual ~ColorGrid(); virtual QSize minimumSizeHint() const; virtual QSize sizeHint() const; /** Returns size of a color cell in pixels. */ inline int cellSize() const { return m_cellSize; } /** Sets size of a color cell in pixels to \a size (must be > 0). */ void setCellSize(int size); /** Returns width of the grid in cells. */ inline int widthInCells() const { return m_widthInCells; } /** Sets width of the grid in cells to \a width (must be > 0). */ void setWidthInCells(int width); /** Returns height of the grid in cells. */ int heightInCells() const; /** Returns \a true if autosize has been enabled. \sa setAutoSize() */ inline bool autoSize() const { return m_autoSize; } /** Sets autosize mode to \a autosize (disabled by default). If autosize mode is enabled, the size of the grid is calculated automatically based on number of colors in the current color scheme. In this mode, calls to setWidthInCells() are ignored. */ void setAutoSize(bool autosize); /** Returns a recently highlighted color. \sa highlighted() */ inline const QColor &lastHighlighted() const { return m_hlColor; } /** Returns a recently picked color. \sa picked() */ inline const QColor &lastPicked() const { return m_selColor; } /** Returns \a true if pick-by-drag mode has been enabled. \sa setPickByDrag() */ inline bool pickByDrag() const { return m_pickDrag; } /** Sets pick-by-drag mode to \a set (disabled by default). If pick-by-drag mode is enabled, then signal picked() is emitted when the user drags mouse over the grid with pressed mouse button. */ inline void setPickByDrag(bool set) { m_pickDrag = set; } /** Returns currently active color picking mode. \sa setClickMode() */ inline ClickMode clickMode() const { return m_clickMode; } /** Sets color picking mode to \a mode. */ inline void setClickMode(ClickMode mode) { m_clickMode = mode; } /** Returns currently active color scheme (by default, defaultColors() is used). \sa setScheme() */ inline const ColorList* scheme() const { return m_colors; } /** Sets color scheme to \a scheme. */ void setScheme(const ColorList *scheme); Q_SIGNALS: /** Emitted when user moves mouse cursor over the grid or changes selection with the cursor keys. \a color is the color value under the cursor. */ void highlighted(const QColor &color); /** Emitted when user picks a color from the grid. \a color is the picked color value. */ void picked(const QColor &color); void accepted(); void rejected(); protected: virtual void paintEvent ( QPaintEvent * event ); virtual void mouseMoveEvent ( QMouseEvent * event ); virtual void mousePressEvent ( QMouseEvent * event ); virtual void mouseReleaseEvent ( QMouseEvent * event ); virtual void leaveEvent ( QEvent * event ); virtual void keyPressEvent ( QKeyEvent * event ); void redraw(); int index() const; int m_cellSize; int m_widthInCells; bool m_autoSize; int m_row, m_col, m_idx; QPixmap m_pix; bool m_pickDrag; ClickMode m_clickMode; QPoint m_pos; QColor m_hlColor, m_selColor; const ColorList *m_colors; }; } // namespace #endif // COLORGRID_H qvge-0.6.3/src/3rdParty/qsint-widgets/doublespincombobox.cpp000066400000000000000000000024221405165517400241740ustar00rootroot00000000000000#include "doublespincombobox.h" namespace QSint { DoubleSpinComboBox::DoubleSpinComboBox(QWidget *parent) : QDoubleSpinBox(parent) { m_button = new QToolButton(this); m_button->setFixedWidth(16); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); m_button->setPopupMode(QToolButton::InstantPopup); m_button->setVisible(false); connect(m_button, SIGNAL(triggered(QAction*)), this, SLOT(onAction(QAction*))); QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); setLayout(mainLayout); mainLayout->addStretch(); mainLayout->addWidget(m_button); } void DoubleSpinComboBox::setValueList(const QList &values) { m_button->setVisible(!values.isEmpty()); if (values.isEmpty()) return; QMenu *m = new QMenu(this); for (double i : values) { QAction *a = m->addAction(QString::number(i)); a->setData(i); } m_button->setMenu(m); } // protected members void DoubleSpinComboBox::resizeEvent(QResizeEvent *event) { QDoubleSpinBox::resizeEvent(event); int arrowSize = m_button->width(); layout()->setContentsMargins(1, 1, arrowSize - 1, 1); } void DoubleSpinComboBox::onAction(QAction* act) { double v = act->data().toDouble(); setValue(v); } } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/doublespincombobox.h000066400000000000000000000013161405165517400236420ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include namespace QSint { /** \brief Double spin editor with additional drop down menu. \since 0.4 \image html DoubleSpinComboBox.png An example of DoubleSpinComboBox */ class DoubleSpinComboBox : public QDoubleSpinBox { Q_OBJECT public: /** Constructor. */ explicit DoubleSpinComboBox(QWidget *parent = 0); void setValueList(const QList &values); Q_SIGNALS: protected Q_SLOTS: void onAction(QAction* action); protected: virtual void resizeEvent(QResizeEvent* event); QToolButton *m_button; }; } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/ledwidget.cpp000066400000000000000000000016571405165517400222600ustar00rootroot00000000000000#include "ledwidget.h" #include namespace QSint { LedWidget::LedWidget(QWidget *parent) : QWidget(parent) { setColor(Qt::gray); } void LedWidget::setColor(const QColor &ledColor) { m_gradient.setColorAt(0.0, Qt::white); m_gradient.setColorAt(1.0, ledColor); } void LedWidget::setColors(const QColor &ledColor, const QColor &highlightColor) { m_gradient.setColorAt(0.0, highlightColor); m_gradient.setColorAt(1.0, ledColor); } void LedWidget::paintEvent(QPaintEvent * /*event*/) { QPainter p(this); p.setPen(QPen(Qt::black)); p.setRenderHint(QPainter::Antialiasing); int radius = qMin(rect().width(), rect().height()) / 2 - 2; m_gradient.setCenter(rect().center()); m_gradient.setFocalPoint(rect().center() - QPoint(radius / 2, radius / 2)); m_gradient.setRadius(radius); p.setBrush(m_gradient); p.drawEllipse(rect().center(), radius, radius); } } qvge-0.6.3/src/3rdParty/qsint-widgets/ledwidget.h000066400000000000000000000024161405165517400217170ustar00rootroot00000000000000#ifndef LEDWIDGET_H #define LEDWIDGET_H #include namespace QSint { /** \brief Round LED-style widget with gradient fill. The gradient consists of two colors: led color (main color of the widget) and highlight color at the top-left corner (typically, white). \since 0.2.2 \image html LedWidget.png An example of LedWidget */ class LedWidget : public QWidget { Q_OBJECT public: explicit LedWidget(QWidget *parent = 0); virtual QSize minimumSizeHint() const { return QSize(12,12); } virtual int heightForWidth(int w) const { return w; } public Q_SLOTS: /** * @brief setColor Funtion sets color of LED to \a ledColor. Highlight color is set to Qt::white. * @param ledColor Color to set (Qt::gray is the default value). */ void setColor(const QColor &ledColor); /** * @brief setColors Funtion sets color of LED to \a ledColor and its highlight color to \a blickColor. * @param ledColor (Qt::gray is the default value). * @param highlightColor (Qt::white is the default value). */ void setColors(const QColor &ledColor, const QColor &highlightColor); protected: virtual void paintEvent(QPaintEvent *event); QRadialGradient m_gradient; }; } #endif // LEDWIDGET_H qvge-0.6.3/src/3rdParty/qsint-widgets/pathpicker.cpp000066400000000000000000000112331405165517400224310ustar00rootroot00000000000000#include "pathpicker.h" #include #include #include namespace QSint { PathPicker::PathPicker(QWidget *parent) : QWidget(parent), m_editorEnabled(true), m_pickMode(PF_EXISTING_FILE), m_dialogMode(DF_DEFAULT) { QHBoxLayout *hbl = new QHBoxLayout(); hbl->setSpacing(0); hbl->setMargin(0); setLayout(hbl); m_editor = new QLineEdit(this); m_button = new QToolButton(this); m_button->setToolButtonStyle(Qt::ToolButtonIconOnly); m_button->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton)); hbl->addWidget(m_editor); hbl->addWidget(m_button); connect(m_button, SIGNAL(clicked()), this, SLOT(showPickDialog())); connect(m_editor, SIGNAL(editingFinished()), this, SIGNAL(changed())); } void PathPicker::setEditorEnabled(bool set) { if (m_editorEnabled != set) { m_editorEnabled = set; m_editor->setEnabled(set); } } void PathPicker::setObjectsToPick(int flags, bool updateIcon) { if (m_pickMode != flags) { m_pickMode = flags; if (updateIcon) { QStyle::StandardPixmap iconStyle = QStyle::SP_DialogOpenButton; switch (m_pickMode) { case PF_EXISTING_FILES: iconStyle = QStyle::SP_FileDialogEnd; break; case PF_EXISTING_DIR: iconStyle = QStyle::SP_DirIcon; break; case PF_SAVE_FILE: iconStyle = QStyle::SP_DialogSaveButton; break; } m_button->setIcon(style()->standardIcon(iconStyle)); } } } void PathPicker::showPickDialog() { Q_EMIT beforePicked(); QString openDir = m_editor->text().trimmed(); if (openDir.isEmpty()) { openDir = m_dir; } QString result; QString caption(m_caption); // default caption if empty if (caption.isEmpty()){ switch (m_pickMode){ case PF_EXISTING_FILE: caption = tr("Choose a file to open"); break; case PF_EXISTING_FILES: caption = tr("Choose files to open"); break; case PF_EXISTING_DIR: caption = tr("Choose a directory"); break; case PF_SAVE_FILE: caption = tr("Choose a file to save"); break; } } bool isSystem = (m_dialogMode == DF_SYSTEM); // use native dialogs? if (isSystem) { switch (m_pickMode){ case PF_EXISTING_DIR: result = QFileDialog::getExistingDirectory(NULL, caption, openDir); break; case PF_EXISTING_FILE: result = QFileDialog::getOpenFileName(NULL, caption, openDir, m_filter); break; case PF_SAVE_FILE: result = QFileDialog::getSaveFileName(NULL, caption, openDir, m_filter); break; case PF_EXISTING_FILES: { QStringList list = QFileDialog::getOpenFileNames(NULL, caption, openDir, m_filter); if (!list.isEmpty()) result = list.join(";"); break; } default: return; } } // use Qt dialogs instead if (!isSystem) { QFileDialog dialog(NULL, caption, openDir, m_filter); dialog.setOption(QFileDialog::DontUseNativeDialog, true); switch (m_pickMode){ case PF_EXISTING_FILE: dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::ExistingFile); break; case PF_EXISTING_FILES: dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::ExistingFiles); break; case PF_EXISTING_DIR: dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::Directory); dialog.setOption(QFileDialog::ShowDirsOnly); break; case PF_SAVE_FILE: dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::AnyFile); break; default: return; } if (dialog.exec()) { QStringList list = dialog.selectedFiles(); if (!list.isEmpty()) result = list.join(";"); } } if (result.isEmpty()) return; m_editor->setText(result); Q_EMIT picked(result); Q_EMIT changed(); } } qvge-0.6.3/src/3rdParty/qsint-widgets/pathpicker.h000066400000000000000000000120031405165517400220720ustar00rootroot00000000000000#ifndef PATHPICKER_H #define PATHPICKER_H #include #include namespace QSint { /** \brief Widget combining a line edit and a tool button used for selection of file system objects. \since 0.2.1 \image html PathPicker.png An example of PathPicker Click on the tool button invokes a modal dialog where you can choose a file, a directory or a number of files to open (or a file to save). The selected path(es) will be then transferred to the line edit along with emitting the picked() signal. Using setObjectsToPick() and setDialogType(), you can specify the style of the pick dialog and the file system objects (see PickFlags and DialogFlags enums). Use setCaption() to modify the default caption of the pick dialog. Method setDefaultDirectory() lets you set the initial directory where to point the pick dialog. Via setFilters() you can specify additional file name wildcards (See Qt documentation on the QFileDialog class). To customize the look of the tool button (i.e. icon, text, etc.), retrieve the pointer to the tool button via button() method. Use editor() method to get the line edit widget. */ class PathPicker : public QWidget { Q_OBJECT public: /// \brief Defines file system objects to pick. enum PickFlags { /// single existing file can be picked (default) PF_EXISTING_FILE, /// one or more existing files can be picked PF_EXISTING_FILES, /// single existing directory can be picked PF_EXISTING_DIR, /// a file to save can be picked (non-existing as well) PF_SAVE_FILE }; /// \brief Defines pick dialog type enum DialogFlags { /// use system dialog DF_SYSTEM = 0, /// use default Qt dialog DF_DEFAULT }; /** Constructor. */ explicit PathPicker(QWidget *parent = 0); /** Returns current path text. */ QString currentPath() const { return m_editor->text(); } /** Sets current path text. */ void setCurrentPath(const QString& path) { m_editor->setText(path); } /** Enables (default) or disables manual path editor according to \a set parameter. */ void setEditorEnabled(bool set); /** Returns \a true if manual path editor is enabled, \a false otherwise. */ inline bool isEditorEnabled() const { return m_editorEnabled; } /** Defines objects being picked as \a PickFlags. * If \a updateIcon is \a true then style default icon will be assigned to the pick button. */ void setObjectsToPick(int flags, bool updateIcon = true); /** Returns \a PickFlags defining objects to pick. */ inline int objectsToPick() const { return m_pickMode; } /** Defines pick dialog type as \a DialogFlags. */ void setDialogType(int flags) { m_dialogMode = flags; } /** Returns \a DialogFlags defining dialog type. */ inline int dialogType() const { return m_dialogMode; } /** Defines the default directory to open when showing the dialog. */ void setDefaultDirectory(const QString& dirName) { m_dir = dirName; } /** Returns the default directory which is open when showing the dialog. */ inline QString defaultDirectory() const { return m_dir; } /** Returns the currently chosen directory. * \since 0.3 */ inline QString currentDirectory() const { return m_editor->text(); } /** Defines the file name filters applied to the filenames. */ void setFilters(const QString& filters) { m_filter = filters; } /** Returns the active file name filters applied to the filenames. */ inline QString filters() const { return m_filter; } /** Defines the caption of the pick dialog. If no caption has been specified, then the default one will be shown. */ void setCaption(const QString& text) { m_caption = text; } /** Returns the caption of the pick dialog, or empty string if the default one should be used. */ inline QString caption() const { return m_caption; } /** Returns the tool button widget. */ QToolButton* button() { return m_button; } /** Returns the line edit widget. */ QLineEdit* editor() { return m_editor; } Q_SIGNALS: /** Emitted when user is about to pick an object from the dialog or editor. */ void beforePicked(); /** Emitted when user picks an object from the dialog or editor. \a path */ void picked(const QString& path); /** Emitted when path is changed by some way. */ void changed(); protected Q_SLOTS: /** Invokes file object pick dialog. When a valid object(s) has been picked from the filesystem, the implementation should set the content of the editor and emit \a picked() signal. */ virtual void showPickDialog(); protected: QLineEdit *m_editor; bool m_editorEnabled; QToolButton *m_button; int m_pickMode; int m_dialogMode; QString m_filter; QString m_dir; QString m_caption; }; } #endif // PATHPICKER_H qvge-0.6.3/src/3rdParty/qsint-widgets/qfontbutton.cpp000066400000000000000000000035731405165517400226720ustar00rootroot00000000000000#include "qfontbutton.h" namespace QSint { QString QFontButton::fontToText(const QFont& font) { QString result(font.family()); if (font.pointSizeF() > 0) result += QString(",%1pt").arg(font.pointSizeF()); else result += QString(",%1px").arg(font.pixelSize()); if (font.bold()) result += ",Bold"; if (font.italic()) result += ",Italic"; if (font.underline()) result += ",Underline"; return result; } QFontButton::QFontButton(QWidget *parent) : QToolButton(parent) { setToolButtonStyle(Qt::ToolButtonTextOnly); setPopupMode(QToolButton::MenuButtonPopup); setText("Aa"); setCurrentFont(QFont()); connect(this, SIGNAL(clicked()), this, SLOT(onClicked())); m_fontDialog = new QFontDialog(this); m_fontDialog->setOption(QFontDialog::DontUseNativeDialog, false); m_fontDialog->setSizeGripEnabled(false); QMenu *menu = new QMenu(this); setMenu(menu); QWidgetAction *dialogAction = new QWidgetAction(this); dialogAction->setDefaultWidget(m_fontDialog); menu->addAction(dialogAction); connect(menu, SIGNAL(aboutToShow()), this, SLOT(onDialogShown())); connect(m_fontDialog, SIGNAL(accepted()), menu, SLOT(hide())); connect(m_fontDialog, SIGNAL(rejected()), menu, SLOT(hide())); connect(m_fontDialog, SIGNAL(fontSelected(const QFont&)), this, SLOT(onDialogFontSelected(const QFont&))); } void QFontButton::setCurrentFont(const QFont &font) { m_font = font; setToolTip(fontToText(font)); if (m_font.pixelSize() > 20 || m_font.pointSize() > 20) { QFont f(font); f.setPointSize(20); setFont(f); } else setFont(m_font); } void QFontButton::onClicked() { Q_EMIT activated(m_font); } void QFontButton::onDialogShown() { m_fontDialog->setCurrentFont(m_font); m_fontDialog->setVisible(true); } void QFontButton::onDialogFontSelected(const QFont &font) { setCurrentFont(font); onClicked(); } } qvge-0.6.3/src/3rdParty/qsint-widgets/qfontbutton.h000066400000000000000000000012421405165517400223260ustar00rootroot00000000000000#ifndef QFONTBUTTON_H #define QFONTBUTTON_H #include #include #include #include namespace QSint { class QFontButton : public QToolButton { Q_OBJECT public: QFontButton(QWidget *parent = Q_NULLPTR); const QFont& currentFont() const { return m_font; } static QString fontToText(const QFont& font); public Q_SLOTS: void setCurrentFont(const QFont &font); Q_SIGNALS: void activated(const QFont &font); private Q_SLOTS: void onClicked(); void onDialogShown(); void onDialogFontSelected(const QFont&); private: QFontDialog *m_fontDialog; QFont m_font; }; } #endif // QFONTBUTTON_H qvge-0.6.3/src/3rdParty/qsint-widgets/qmenubutton.cpp000066400000000000000000000041471405165517400226660ustar00rootroot00000000000000#include "qmenubutton.h" #include #include namespace QSint { QMenuButton::QMenuButton(QWidget *parent) : QToolButton(parent) { connect(this, SIGNAL(triggered(QAction*)), this, SLOT(onAction(QAction*))); setMenu(m_localMenu = new QMenu()); } QAction* QMenuButton::addAction(const QString &text, const QVariant &v) { QAction* act = new QAction(text, parent()); act->setData(v); m_localMenu->addAction(act); if (m_localMenu->actions().count() == 1) setDefaultAction(act); return act; } QAction* QMenuButton::addAction(const QIcon &icon, const QString &text, const QVariant &v) { QAction* act = addAction(text, v); act->setIcon(icon); return act; } QAction* QMenuButton::selectAction(const QVariant &data) { for (auto act: m_localMenu->actions()) { if (act->data() == data && act->isEnabled() && act->isVisible()) { setDefaultAction(act); return act; } } // not found return NULL; } QAction *QMenuButton::selectActionByIndex(int index) { if (index >= 0 && index < m_localMenu->actions().count()) { auto act = m_localMenu->actions()[index]; if (act->isEnabled() && act->isVisible()) { setDefaultAction(act); return act; } } // not found return NULL; } void QMenuButton::actionEvent(QActionEvent *event) { QToolButton::actionEvent(event); // set default action if (defaultAction() == NULL) { for (auto act: m_localMenu->actions()) { if (act->isEnabled() && act->isVisible()) { setDefaultAction(act); return; } } } } void QMenuButton::onAction(QAction* act) { setDefaultAction(act); if (act) Q_EMIT activated(act->data()); } void QMenuButton::setDefaultAction(QAction* act) { if (act != defaultAction()) { // prevent status tip QString oldStatusTip = statusTip(); QToolButton::setDefaultAction(act); m_localMenu->setDefaultAction(act); if (statusTip().isEmpty()) setStatusTip(oldStatusTip); } } } qvge-0.6.3/src/3rdParty/qsint-widgets/qmenubutton.h000066400000000000000000000013571405165517400223330ustar00rootroot00000000000000#pragma once #include #include #include #include namespace QSint { class QMenuButton : public QToolButton { Q_OBJECT public: QMenuButton(QWidget *parent = Q_NULLPTR); QAction* addAction(const QString &text, const QVariant &data = QVariant()); QAction* addAction(const QIcon &icon, const QString &text, const QVariant &data = QVariant()); void setDefaultAction(QAction* act); public Q_SLOTS: QAction* selectAction(const QVariant &data); QAction* selectActionByIndex(int index); Q_SIGNALS: void activated(QVariant data); protected Q_SLOTS: virtual void onAction(QAction* act); protected: virtual void actionEvent(QActionEvent *event); QMenu *m_localMenu; }; } qvge-0.6.3/src/3rdParty/qsint-widgets/qpenbutton.cpp000066400000000000000000000035071405165517400225030ustar00rootroot00000000000000#include "qpenbutton.h" #include #include #include namespace QSint { QPenButton::QPenButton(QWidget *parent) : QSplitButton(parent) { init(); } QPixmap QPenButton::drawPixmap(Qt::PenStyle style, int width, QSize size) { QPen pen; pen.setWidth(width); pen.setStyle(style); QPixmap pixmap(size); pixmap.fill(QColor(Qt::transparent)); QPainter painter(&pixmap); painter.setPen(pen); painter.drawLine(0, int(pixmap.height() / 2.), pixmap.width(), int(pixmap.height() / 2.)); return pixmap; } void QPenButton::init() { for (int i = Qt::NoPen; i < Qt::CustomDashLine; i++) { QPixmap pixmap = drawPixmap(Qt::PenStyle(i), 2, iconSize() * 2); switch (i) { case Qt::NoPen: addAction(pixmap, tr("None"), i); break; case Qt::SolidLine: addAction(pixmap, tr("Solid"), i); break; case Qt::DashLine: addAction(pixmap, tr("Dashed"), i); break; case Qt::DotLine: addAction(pixmap, tr("Dotted"), i); break; case Qt::DashDotLine: addAction(pixmap, tr("Dash-Dot"), i); break; case Qt::DashDotDotLine: addAction(pixmap, tr("Dash-Dot-Dot"), i); break; default: break; } } } void QPenButton::setUsedRange(Qt::PenStyle start, Qt::PenStyle end) { auto list = actions(); for (int i = 0; i setVisible(i >= start && i <= end); } selectActionByIndex(start); } void QPenButton::setPenStyle(Qt::PenStyle style) { selectAction((int)style); } void QPenButton::onAction(QAction* act) { QSplitButton::onAction(act); int style = act->data().toInt(); if (style < Qt::NoPen || style >= Qt::CustomDashLine) style = Qt::NoPen; Q_EMIT activated((Qt::PenStyle)style); } } qvge-0.6.3/src/3rdParty/qsint-widgets/qpenbutton.h000066400000000000000000000010421405165517400221400ustar00rootroot00000000000000#pragma once #include "qsplitbutton.h" #include namespace QSint { class QPenButton : public QSplitButton { Q_OBJECT public: QPenButton(QWidget *parent = Q_NULLPTR); void setUsedRange(Qt::PenStyle start, Qt::PenStyle end); static QPixmap drawPixmap(Qt::PenStyle style, int width = 2, QSize size = QSize(24,24)); public Q_SLOTS: void setPenStyle(Qt::PenStyle style); Q_SIGNALS: void activated(Qt::PenStyle style); protected Q_SLOTS: virtual void onAction(QAction* act); private: virtual void init(); }; } qvge-0.6.3/src/3rdParty/qsint-widgets/qpencombobox.cpp000066400000000000000000000023141405165517400227730ustar00rootroot00000000000000#include "qpencombobox.h" #include #include namespace QSint { QPenComboBox::QPenComboBox(QWidget *parent) : QComboBox(parent) { setEditable(false); QPen pen; pen.setWidth(2); for (int i = Qt::SolidLine; i < Qt::CustomDashLine; i++) { QPixmap pixmap(24, 24); pixmap.fill(QColor(Qt::transparent)); pen.setStyle(Qt::PenStyle(i)); QPainter painter(&pixmap); painter.setPen(pen); painter.drawLine(0, int(pixmap.height() / 2.), pixmap.width(), int(pixmap.height() / 2.)); switch (i) { case Qt::NoPen: addItem(pixmap, tr("None")); break; case Qt::SolidLine: addItem(pixmap, tr("Solid")); break; case Qt::DashLine: addItem(pixmap, tr("Dash")); break; case Qt::DotLine: addItem(pixmap, tr("Dot")); break; case Qt::DashDotLine: addItem(pixmap, tr("Dash Dot")); break; case Qt::DashDotDotLine: addItem(pixmap, tr("Dash Dot Dot")); break; default: addItem(tr("Custom")); break; } } setCurrentIndex(1); setFixedSize(sizeHint()); } void QPenComboBox::setCurrentStyle(Qt::PenStyle newStyle) { setCurrentIndex((int)newStyle); } Qt::PenStyle QPenComboBox::currentStyle() const { return Qt::PenStyle(currentIndex()); } } qvge-0.6.3/src/3rdParty/qsint-widgets/qpencombobox.h000066400000000000000000000004611405165517400224410ustar00rootroot00000000000000#ifndef QPENCOMBOBOX_H #define QPENCOMBOBOX_H #include #include namespace QSint { class QPenComboBox: public QComboBox { public: QPenComboBox(QWidget *parent = 0); void setCurrentStyle(Qt::PenStyle); Qt::PenStyle currentStyle() const; }; } #endif // QPENCOMBOBOX_H qvge-0.6.3/src/3rdParty/qsint-widgets/qsint-widgets.pro000066400000000000000000000003051405165517400231150ustar00rootroot00000000000000include(../common.pri) TARGET = qsint-widgets QT += core gui widgets SOURCES += $$files($$PWD/*.cpp) HEADERS += $$files($$PWD/*.h) FORMS += $$files($$PWD/*.ui) RESOURCES += $$files($$PWD/*.qrc) qvge-0.6.3/src/3rdParty/qsint-widgets/qsplitbutton.cpp000066400000000000000000000041611405165517400230510ustar00rootroot00000000000000#include "qsplitbutton.h" #include #include namespace QSint { QSplitButton::QSplitButton(QWidget *parent) : QToolButton(parent) { connect(this, SIGNAL(triggered(QAction*)), this, SLOT(onAction(QAction*))); setMenu(m_localMenu = new QMenu()); } QAction* QSplitButton::addAction(const QString &text, const QVariant &v) { QAction* act = new QAction(text, parent()); act->setData(v); m_localMenu->addAction(act); if (m_localMenu->actions().count() == 1) setDefaultAction(act); return act; } QAction* QSplitButton::addAction(const QIcon &icon, const QString &text, const QVariant &v) { QAction* act = addAction(text, v); act->setIcon(icon); return act; } QAction* QSplitButton::selectAction(const QVariant &data) { for (auto act: m_localMenu->actions()) { if (act->data() == data && act->isEnabled() && act->isVisible()) { setDefaultAction(act); return act; } } // not found return NULL; } QAction *QSplitButton::selectActionByIndex(int index) { if (index >= 0 && index < m_localMenu->actions().count()) { auto act = m_localMenu->actions()[index]; if (act->isEnabled() && act->isVisible()) { setDefaultAction(act); return act; } } // not found return NULL; } void QSplitButton::actionEvent(QActionEvent *event) { QToolButton::actionEvent(event); // set default action if (defaultAction() == NULL) { for (auto act: m_localMenu->actions()) { if (act->isEnabled() && act->isVisible()) { setDefaultAction(act); return; } } } } void QSplitButton::onAction(QAction* act) { setDefaultAction(act); if (act) Q_EMIT activated(act->data()); } void QSplitButton::setDefaultAction(QAction* act) { if (act != defaultAction()) { // prevent status tip QString oldStatusTip = statusTip(); QToolButton::setDefaultAction(act); m_localMenu->setDefaultAction(act); if (statusTip().isEmpty()) setStatusTip(oldStatusTip); } } } qvge-0.6.3/src/3rdParty/qsint-widgets/qsplitbutton.h000066400000000000000000000013611405165517400225150ustar00rootroot00000000000000#pragma once #include #include #include #include namespace QSint { class QSplitButton : public QToolButton { Q_OBJECT public: QSplitButton(QWidget *parent = Q_NULLPTR); QAction* addAction(const QString &text, const QVariant &data = QVariant()); QAction* addAction(const QIcon &icon, const QString &text, const QVariant &data = QVariant()); void setDefaultAction(QAction* act); public Q_SLOTS: QAction* selectAction(const QVariant &data); QAction* selectActionByIndex(int index); Q_SIGNALS: void activated(QVariant data); protected Q_SLOTS: virtual void onAction(QAction* act); protected: virtual void actionEvent(QActionEvent *event); QMenu *m_localMenu; }; } qvge-0.6.3/src/3rdParty/qsint-widgets/roundprogressbar.cpp000066400000000000000000000227231405165517400237060ustar00rootroot00000000000000#include "roundprogressbar.h" #include #include namespace QSint { RoundProgressBar::RoundProgressBar(QWidget *parent) : QWidget(parent), m_min(0), m_max(100), m_value(25), m_nullPosition(PositionTop), m_barStyle(StyleDonut), m_outlinePenWidth(1), m_dataPenWidth(1), m_rebuildBrush(false), m_format("%p%"), m_decimals(1), m_updateFlags(UF_PERCENT) { QPalette p(palette()); p.setBrush(QPalette::Window, Qt::transparent); setPalette(p); } void RoundProgressBar::setRange(double min, double max) { m_min = min; m_max = max; if (m_max < m_min) qSwap(m_max, m_min); if (m_value < m_min) m_value = m_min; else if (m_value > m_max) m_value = m_max; m_rebuildBrush = true; update(); } void RoundProgressBar::setMinimum(double min) { setRange(min, m_max); } void RoundProgressBar::setMaximum(double max) { setRange(m_min, max); } void RoundProgressBar::setValue(double val) { if (m_value != val) { if (val < m_min) m_value = m_min; else if (val > m_max) m_value = m_max; else m_value = val; update(); } } void RoundProgressBar::setValue(int val) { setValue(double(val)); } void RoundProgressBar::setNullPosition(double position) { if (position != m_nullPosition) { m_nullPosition = position; m_rebuildBrush = true; update(); } } void RoundProgressBar::setBarStyle(RoundProgressBar::BarStyle style) { if (style != m_barStyle) { m_barStyle = style; m_rebuildBrush = true; update(); } } void RoundProgressBar::setOutlinePenWidth(double penWidth) { if (penWidth != m_outlinePenWidth) { m_outlinePenWidth = penWidth; update(); } } void RoundProgressBar::setDataPenWidth(double penWidth) { if (penWidth != m_dataPenWidth) { m_dataPenWidth = penWidth; update(); } } void RoundProgressBar::setDataColors(const QGradientStops &stopPoints) { if (stopPoints != m_gradientData) { m_gradientData = stopPoints; m_rebuildBrush = true; update(); } } void RoundProgressBar::setFormat(const QString &format) { if (format != m_format) { m_format = format; valueFormatChanged(); } } void RoundProgressBar::resetFormat() { m_format = QString::null; valueFormatChanged(); } void RoundProgressBar::setDecimals(int count) { if (count >= 0 && count != m_decimals) { m_decimals = count; valueFormatChanged(); } } void RoundProgressBar::paintEvent(QPaintEvent* /*event*/) { double outerRadius = qMin(width(), height()); QRectF baseRect(1, 1, outerRadius-2, outerRadius-2); QImage buffer(outerRadius, outerRadius, QImage::Format_ARGB32_Premultiplied); buffer.fill(Qt::transparent); QPainter p(&buffer); p.setRenderHint(QPainter::Antialiasing); // data brush rebuildDataBrushIfNeeded(); // background drawBackground(p, buffer.rect()); // base circle drawBase(p, baseRect); // data circle double delta = (m_max - m_min) / (m_value - m_min); drawValue(p, baseRect, m_value, delta); // center circle double innerRadius(0); QRectF innerRect; calculateInnerRect(baseRect, outerRadius, innerRect, innerRadius); drawInnerBackground(p, innerRect); // text drawText(p, innerRect, innerRadius, m_value); // finally draw the bar p.end(); QPainter painter(this); painter.fillRect(baseRect, Qt::transparent); painter.drawImage((width() - outerRadius) / 2, (height() - outerRadius) / 2, buffer); } void RoundProgressBar::drawBackground(QPainter &p, const QRectF &baseRect) { p.fillRect(baseRect, palette().background()); } void RoundProgressBar::drawBase(QPainter &p, const QRectF &baseRect) { switch (m_barStyle) { case StyleDonut: p.setPen(QPen(palette().shadow().color(), m_outlinePenWidth)); p.setBrush(palette().base()); p.drawEllipse(baseRect); break; case StylePie: case StyleExpand: p.setPen(QPen(palette().base().color(), m_outlinePenWidth)); p.setBrush(palette().base()); p.drawEllipse(baseRect); break; case StyleLine: p.setPen(QPen(palette().base().color(), m_outlinePenWidth)); p.setBrush(Qt::NoBrush); p.drawEllipse(baseRect.adjusted(m_outlinePenWidth/2, m_outlinePenWidth/2, -m_outlinePenWidth/2, -m_outlinePenWidth/2)); break; default:; } } void RoundProgressBar::drawValue(QPainter &p, const QRectF &baseRect, double value, double delta) { // nothing to draw if (value == m_min) return; // for Expand style if (m_barStyle == StyleExpand) { p.setBrush(palette().highlight()); p.setPen(QPen(palette().shadow().color(), m_dataPenWidth)); double radius = (baseRect.height() / 2) / delta; p.drawEllipse(baseRect.center(), radius, radius); return; } // for Line style if (m_barStyle == StyleLine) { p.setPen(QPen(palette().highlight().color(), m_dataPenWidth)); p.setBrush(Qt::NoBrush); if (value == m_max) { p.drawEllipse( baseRect.adjusted(m_outlinePenWidth/2, m_outlinePenWidth/2, -m_outlinePenWidth/2, -m_outlinePenWidth/2)); } else { double arcLength = 360.0 / delta; p.drawArc( baseRect.adjusted(m_outlinePenWidth/2, m_outlinePenWidth/2, -m_outlinePenWidth/2, -m_outlinePenWidth/2), m_nullPosition * 16, -arcLength * 16); } return; } // for Pie and Donut styles QPainterPath dataPath; dataPath.setFillRule(Qt::WindingFill); // pie segment outer if (value == m_max) { dataPath.addEllipse(baseRect); } else { double arcLength = 360.0 / delta; dataPath.moveTo(baseRect.center()); dataPath.arcTo(baseRect, m_nullPosition, -arcLength); dataPath.lineTo(baseRect.center()); } p.setBrush(palette().highlight()); p.setPen(QPen(palette().shadow().color(), m_dataPenWidth)); p.drawPath(dataPath); } void RoundProgressBar::calculateInnerRect(const QRectF &/*baseRect*/, double outerRadius, QRectF &innerRect, double &innerRadius) { // for Line and Expand styles if (m_barStyle == StyleLine || m_barStyle == StyleExpand) { innerRadius = outerRadius - m_outlinePenWidth; } else // for Pie and Donut styles { innerRadius = outerRadius * 0.75; } double delta = (outerRadius - innerRadius) / 2; innerRect = QRectF(delta, delta, innerRadius, innerRadius); } void RoundProgressBar::drawInnerBackground(QPainter &p, const QRectF &innerRect) { if (m_barStyle == StyleDonut) { p.setBrush(palette().alternateBase()); p.drawEllipse(innerRect); } } void RoundProgressBar::drawText(QPainter &p, const QRectF &innerRect, double innerRadius, double value) { if (m_format.isEmpty()) return; // !!! to revise QFont f(font()); f.setPixelSize(10); QFontMetricsF fm(f); double maxWidth = fm.width(valueToText(m_max)); double delta = innerRadius / maxWidth; double fontSize = f.pixelSize() * delta * 0.75; f.setPixelSize(fontSize); //f.setPixelSize(innerRadius * qMax(0.05, (0.5 - (double)m_decimals * 0.2))); p.setFont(f); QRectF textRect(innerRect); p.setPen(palette().text().color()); p.drawText(textRect, Qt::AlignCenter, valueToText(value)); } QString RoundProgressBar::valueToText(double value) const { QString textToDraw(m_format); if (m_updateFlags & UF_VALUE) textToDraw.replace("%v", QString::number(value, 'f', m_decimals)); if (m_updateFlags & UF_PERCENT) { double procent = (value - m_min) / (m_max - m_min) * 100.0; textToDraw.replace("%p", QString::number(procent, 'f', m_decimals)); } if (m_updateFlags & UF_MAX) textToDraw.replace("%m", QString::number(m_max - m_min + 1, 'f', m_decimals)); return textToDraw; } void RoundProgressBar::valueFormatChanged() { m_updateFlags = 0; if (m_format.contains("%v")) m_updateFlags |= UF_VALUE; if (m_format.contains("%p")) m_updateFlags |= UF_PERCENT; if (m_format.contains("%m")) m_updateFlags |= UF_MAX; update(); } void RoundProgressBar::rebuildDataBrushIfNeeded() { if (!m_rebuildBrush) return; if (m_gradientData.isEmpty()) return; if (m_barStyle == StyleLine) return; m_rebuildBrush = false; QPalette p(palette()); if (m_barStyle == StyleExpand) { QRadialGradient dataBrush(0.5,0.5, 0.5, 0.5,0.5); dataBrush.setCoordinateMode(QGradient::StretchToDeviceMode); // set colors for (int i = 0; i < m_gradientData.count(); i++) dataBrush.setColorAt(m_gradientData.at(i).first, m_gradientData.at(i).second); p.setBrush(QPalette::Highlight, dataBrush); } else { QConicalGradient dataBrush(QPointF(0.5,0.5), m_nullPosition); dataBrush.setCoordinateMode(QGradient::StretchToDeviceMode); // invert colors for (int i = 0; i < m_gradientData.count(); i++) dataBrush.setColorAt(1.0 - m_gradientData.at(i).first, m_gradientData.at(i).second); p.setBrush(QPalette::Highlight, dataBrush); } setPalette(p); } } // namespace QSint qvge-0.6.3/src/3rdParty/qsint-widgets/roundprogressbar.h000066400000000000000000000204201405165517400233430ustar00rootroot00000000000000#ifndef ROUNDPROGRESSBAR_H #define ROUNDPROGRESSBAR_H #include namespace QSint { /** * @brief The RoundProgressBar class represents a circular progress bar and maintains its API * similar to the *QProgressBar*. * \since 0.3 * * ### Styles * RoundProgressBar currently supports Donut, Pie, Expand and Line styles. See setBarStyle() for more details. * * ### Colors * Generally RoundProgressBar uses its palette and font attributes to define how it will look. * * The following \a QPalette members are considered: * - *QPalette::Window* background of the whole widget (normally should be set to Qt::NoBrush) * - *QPalette::Base* background of the non-filled progress bar area (should be set to Qt::NoBrush to make it transparent) * - *QPalette::AlternateBase* background of the central circle where the text is shown (for \a Donut style) * - *QPalette::Shadow* foreground of the non-filled progress bar area (i.e. border color) * - *QPalette::Highlight* background of the filled progress bar area * - *QPalette::Text* color of the text shown in the center * * Create a \a QPalette with given attributes and apply it via `setPalette()`. * * ### Color gradient * \a Donut, \a Expand and \a Pie styles allow to use color gradient for currernt value area instead of plain brush fill. * See setDataColors() for more details. * * ### Value text * Value text is generally drawn inside the RoundProgressBar using its `font()` and \a QPalette::Text role from its `palette()`. * * To define pattern of the text, use setFormat() function (see Qt's \a QProgressBar for more details). * * To define number of decimals to be shown, use setDecimals() function. * * ### Font * To use own font for value text, apply it via `setFont()`. * * By default, font size will be adjusted automatically to fit the inner circle of the widget. */ class RoundProgressBar : public QWidget { Q_OBJECT public: explicit RoundProgressBar(QWidget *parent = 0); static const int PositionLeft = 180; static const int PositionTop = 90; static const int PositionRight = 0; static const int PositionBottom = -90; /** * @brief Return position (in degrees) of minimum value. * \sa setNullPosition */ double nullPosition() const { return m_nullPosition; } /** * @brief Defines position of minimum value. * @param position position on the circle (in degrees) of minimum value * \sa nullPosition */ void setNullPosition(double position); /** * @brief The BarStyle enum defines general look of the progress bar. */ enum BarStyle { /// Donut style (filled torus around the text) StyleDonut, /// Pie style (filled pie segment with the text in center) StylePie, /// Line style (thin round line around the text) StyleLine, /// Expand style (circle filled from inside to outline) StyleExpand }; /** * @brief Sets visual style of the widget. * \sa barStyle */ void setBarStyle(BarStyle style); /** * @brief Returns current progree bar style. * \sa setBarStyle */ BarStyle barStyle() const { return m_barStyle; } /** * @brief Sets width of the outline circle pen. * @param penWidth width of the outline circle pen (in pixels) */ void setOutlinePenWidth(double penWidth); /** * @brief Returns width of the outline circle pen. */ double outlinePenWidth() const { return m_outlinePenWidth; } /** * @brief Sets width of the data circle pen. * @param penWidth width of the data circle pen (in pixels) */ void setDataPenWidth(double penWidth); /** * @brief Returns width of the data circle pen. */ double dataPenWidth() const { return m_dataPenWidth; } /** * @brief Sets colors of the visible data and makes gradient brush from them. * Gradient colors can be set for \a Donut and \a Pie styles (see setBarStyle() function). * * *Warning*: this function will override widget's `palette()` to set dynamically created gradient brush. * * @param stopPoints List of colors (should have at least 2 values, see Qt's \a QGradientStops for more details). * Color value at point 0 corresponds to the minimum() value, while color value at point 1 * corresponds to the maximum(). Other colors will be distributed accordingly to the defined ranges (see setRange()). */ void setDataColors(const QGradientStops& stopPoints); /** * @brief Defines the string used to generate the current text. * If no format is set, no text will be shown. * @param format see \a QProgressBar's format description * \sa setDecimals */ void setFormat(const QString& format); /** * @brief Sets format string to empty string. No text will be shown therefore. * See setFormat() for more information. */ void resetFormat(); /** * @brief Returns the string used to generate the current text. */ QString format() const { return m_format; } /** * @brief Sets number of decimals to show after the comma (default is 1). * \sa setFormat */ void setDecimals(int count); /** * @brief Returns number of decimals to show after the comma (default is 1). * \sa setFormat, setDecimals */ int decimals() const { return m_decimals; } /** * @brief Returns current value shown on the widget. * \sa setValue() */ double value() const { return m_value; } /** * @brief Returns minimum of the allowed value range. * \sa setMinimum, setRange */ double minimum() const { return m_min; } /** * @brief Returns maximum of the allowed value range. * \sa setMaximum, setRange */ double maximum() const { return m_max; } public Q_SLOTS: /** * @brief Defines minimum und maximum of the allowed value range. * If the current value does not fit into the range, it will be automatically adjusted. * @param min minimum of the allowed value range * @param max maximum of the allowed value range */ void setRange(double min, double max); /** * @brief Defines minimum of the allowed value range. * If the current value does not fit into the range, it will be automatically adjusted. * @param min minimum of the allowed value range * \sa setRange */ void setMinimum(double min); /** * @brief Defines maximum of the allowed value range. * If the current value does not fit into the range, it will be automatically adjusted. * @param max maximum of the allowed value range * \sa setRange */ void setMaximum(double max); /** * @brief Sets a value which will be shown on the widget. * @param val must be between minimum() and maximum() */ void setValue(double val); /** * @brief Integer version of the previous slot. * @param val must be between minimum() and maximum() */ void setValue(int val); protected: virtual void paintEvent(QPaintEvent *event); virtual void drawBackground(QPainter& p, const QRectF& baseRect); virtual void drawBase(QPainter& p, const QRectF& baseRect); virtual void drawValue(QPainter& p, const QRectF& baseRect, double value, double delta); virtual void calculateInnerRect(const QRectF& baseRect, double outerRadius, QRectF& innerRect, double& innerRadius); virtual void drawInnerBackground(QPainter& p, const QRectF& innerRect); virtual void drawText(QPainter& p, const QRectF& innerRect, double innerRadius, double value); virtual QString valueToText(double value) const; virtual void valueFormatChanged(); virtual QSize minimumSizeHint() const { return QSize(32,32); } virtual bool hasHeightForWidth() const { return true; } virtual int heightForWidth(int w) const { return w; } void rebuildDataBrushIfNeeded(); double m_min, m_max; double m_value; double m_nullPosition; BarStyle m_barStyle; double m_outlinePenWidth, m_dataPenWidth; QGradientStops m_gradientData; bool m_rebuildBrush; QString m_format; int m_decimals; static const int UF_VALUE = 1; static const int UF_PERCENT = 2; static const int UF_MAX = 4; int m_updateFlags; }; } // namespace QSint #endif // ROUNDPROGRESSBAR_H qvge-0.6.3/src/3rdParty/qsint-widgets/slider.cpp000066400000000000000000000034631405165517400215670ustar00rootroot00000000000000#include "slider.h" #include #include namespace QSint { Slider::Slider(QWidget *parent): QSlider(parent), m_precise(false), m_clickJump(false) { setPreciseMovement(true); } void Slider::setPreciseMovement(bool on) { if (m_precise != on) { m_precise = on; if (m_precise) connect(this, SIGNAL(actionTriggered(int)), this, SLOT(onActionTriggered(int))); else disconnect(this); } } void Slider::setClickJump(bool on) { if (m_clickJump != on) { m_clickJump = on; } } void Slider::onActionTriggered(int action) { if (action == QAbstractSlider::SliderMove) { int v = (sliderPosition() / singleStep()) * singleStep(); setValue(v); } else if (action == QAbstractSlider::SliderPageStepAdd || action == QAbstractSlider::SliderPageStepSub) { int v = (sliderPosition() / pageStep()) * pageStep(); setValue(v); } } void Slider::mousePressEvent(QMouseEvent *event) { if (m_clickJump) { QStyleOptionSlider opt; initStyleOption(&opt); QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); if (event->button() == Qt::LeftButton && !sr.contains(event->pos())) { int v = minimum(); if (orientation() == Qt::Vertical) v += ((maximum()-minimum()) * (height()-event->y())) / height(); else v += ((maximum()-minimum()) * event->x()) / width(); if (m_precise) v = (v / singleStep()) * singleStep(); if (invertedAppearance()) v = (maximum() - v + 1); setValue(v); } } QSlider::mousePressEvent(event); } } qvge-0.6.3/src/3rdParty/qsint-widgets/slider.h000066400000000000000000000026011405165517400212250ustar00rootroot00000000000000#ifndef SLIDER_H #define SLIDER_H #include namespace QSint { /** \brief A slider allowing more precise user control by a mouse. See: - setPreciseMovement() - setClickJump() \since 0.3 */ class Slider : public QSlider { Q_OBJECT public: Slider(QWidget* parent = 0); /// \return true if presice movement has been activated. /// \sa setPreciseMovement() /// \since 0.3 bool preciseMovementActive() const { return m_precise; } /// \return true if click jump has been activated. /// \sa setClickJump() /// \since 0.3 bool clickJumpActive() const { return m_clickJump; } public Q_SLOTS: /// Activates precise movement of the slider. Its value will be always rounded up according to singleStep() /// when dragging & scrolling. /// Clicking on the slider will round up its value according to pageStep(). /// /// Enabled by default. /// \since 0.3 void setPreciseMovement(bool on = true); /// When activated, clicking on the slider will move its handle to the click position immediately. /// /// Not enabled by default. /// \since 0.3 void setClickJump(bool on = true); protected Q_SLOTS: void onActionTriggered(int id); protected: virtual void mousePressEvent(QMouseEvent *event); private: bool m_precise; bool m_clickJump; }; } #endif // SLIDER_H qvge-0.6.3/src/3rdParty/qsint-widgets/slider2d.cpp000066400000000000000000000211101405165517400220020ustar00rootroot00000000000000#include "slider2d.h" #include #include #include #include namespace QSint { // constructor Slider2d::Slider2d(QWidget *parent) : QWidget(parent), m_panning(true), m_sliderX(0), m_sliderY(0) { m_valueXpan = m_valueYpan = 0; m_sizeXpan = m_sizeYpan = 1; m_minX = m_maxX = m_valueX = 0; m_minY = m_maxY = m_valueY = 0; m_sizeX = m_sizeY = 1; m_viewSize = QSize(1,1); m_opacity = 1; m_panOpacity = 1; m_oldX = m_oldY = 0; } Slider2d::~Slider2d() { // disconnectSource(); } // properties void Slider2d::setBackgroundPen(const QPen& pen) { m_pen = pen; update(); } void Slider2d::setBackgroundBrush(const QBrush& brush) { m_brush = brush; update(); } void Slider2d::setSliderPen(const QPen& pen) { m_panPen = pen; update(); } void Slider2d::setSliderBrush(const QBrush& brush) { m_panBrush = brush; update(); } void Slider2d::setOpacity(double opacity) { m_opacity = opacity; update(); } void Slider2d::setSliderOpacity(double opacity) { m_panOpacity = opacity; update(); } // source connection void Slider2d::connectSource(QAbstractSlider *horizontal, QAbstractSlider *vertical) { disconnectSource(); connectH(horizontal); connectV(vertical); } void Slider2d::connectSource(QAbstractScrollArea *area) { connectSource(area->horizontalScrollBar(), area->verticalScrollBar()); } void Slider2d::connectH(QAbstractSlider *sl) { m_sliderX = sl; if (m_sliderX) { connect(m_sliderX, SIGNAL(rangeChanged(int,int)), this, SLOT(setHorizontalRange(int,int))); connect(m_sliderX, SIGNAL(valueChanged(int)), this, SLOT(setHorizontalValue(int))); connect(this, SIGNAL(scrollHorizontal(int)), m_sliderX, SLOT(setValue(int))); m_sliderX->installEventFilter(this); } } void Slider2d::connectV(QAbstractSlider *sl) { m_sliderY = sl; if (m_sliderY) { connect(m_sliderY, SIGNAL(rangeChanged(int,int)), this, SLOT(setVerticalRange(int,int))); connect(m_sliderY, SIGNAL(valueChanged(int)), this, SLOT(setVerticalValue(int))); connect(this, SIGNAL(scrollVertical(int)), m_sliderY, SLOT(setValue(int))); m_sliderY->installEventFilter(this); } } void Slider2d::disconnectSource() { if (m_sliderX) { disconnect(m_sliderX, SIGNAL(rangeChanged(int,int)), this, SLOT(setHorizontalRange(int,int))); disconnect(m_sliderX, SIGNAL(valueChanged(int)), this, SLOT(setHorizontalValue(int))); disconnect(this, SIGNAL(scrollHorizontal(int)), m_sliderX, SLOT(setValue(int))); m_sliderX->removeEventFilter(this); m_sliderX = 0; } if (m_sliderY) { disconnect(m_sliderY, SIGNAL(rangeChanged(int,int)), this, SLOT(setVerticalRange(int,int))); disconnect(m_sliderY, SIGNAL(valueChanged(int)), this, SLOT(setVerticalValue(int))); disconnect(this, SIGNAL(scrollVertical(int)), m_sliderY, SLOT(setValue(int))); m_sliderY->removeEventFilter(this); m_sliderY = 0; } } QToolButton *Slider2d::makeAsButton() { QToolButton *sliderButton = new QToolButton(parentWidget()); sliderButton->setPopupMode(QToolButton::InstantPopup); QWidgetAction *sliderAction = new QWidgetAction(sliderButton); sliderAction->setDefaultWidget(this); QMenu *sliderMenu = new QMenu(parentWidget()); sliderButton->setMenu(sliderMenu); sliderMenu->addAction(sliderAction); sliderMenu->setDefaultAction(sliderAction); connect(sliderMenu, SIGNAL(aboutToShow()), this, SLOT(onAboutToShow())); sliderMenu->installEventFilter(this); return sliderButton; } void Slider2d::setHorizontalRange(int min, int max) { m_minX = min; m_maxX = max; m_sizeX = max - min + m_viewSize.width(); update(); } void Slider2d::setHorizontalValue(int value) { double d = double(width()) / double(m_sizeX); int v = value - m_minX; double dv = v * d; m_valueXpan = dv; update(); } void Slider2d::setHorizontalViewSize(int size) { m_viewSize.setWidth(size); calculateXsize(size); update(); } void Slider2d::setVerticalRange(int min, int max) { m_minY = min; m_maxY = max; m_sizeY = max - min + m_viewSize.height(); update(); } void Slider2d::setVerticalValue(int value) { double d = double(height()) / double(m_sizeY); int v = value - m_minY; double dv = v * d; m_valueYpan = dv; update(); } void Slider2d::setVerticalViewSize(int size) { m_viewSize.setHeight(size); calculateYsize(size); update(); } void Slider2d::setViewSize(const QSize &size) { m_viewSize = size; calculateXsize(m_viewSize.width()); calculateYsize(m_viewSize.height()); update(); } // panning methods void Slider2d::enablePanning(bool on) { m_panning = on; } void QSint::Slider2d::onAboutToShow() { Q_EMIT aboutToShow(); } void QSint::Slider2d::mousePressEvent(QMouseEvent *event) { if (m_panning && event->buttons() & Qt::LeftButton) { m_oldX = m_valueXpan - event->pos().x(); m_oldY = m_valueYpan - event->pos().y(); // if clicked outside of the rect if (!QRect(m_valueXpan, m_valueYpan, m_sizeXpan, m_sizeYpan).contains(event->pos())) { m_oldX = -m_sizeXpan/2; m_oldY = -m_sizeYpan/2; m_valueXpan = event->pos().x() + m_oldX; m_valueYpan = event->pos().y() + m_oldY; mouseMoveEvent(event); } } } void QSint::Slider2d::mouseMoveEvent(QMouseEvent *event) { if (m_panning && event->buttons() & Qt::LeftButton) { m_valueXpan = event->pos().x() + m_oldX; if (m_valueXpan < 0) m_valueXpan = 0; else if (m_valueXpan >= (width()-m_sizeXpan)) m_valueXpan = width()-m_sizeXpan; double dx = double(width()) / double(m_sizeX); int viewX = double(m_valueXpan) / dx + m_minX; Q_EMIT scrollHorizontal(viewX); m_valueYpan = event->pos().y() + m_oldY; if (m_valueYpan < 0) m_valueYpan = 0; else if (m_valueYpan >= (height()-m_sizeYpan)) m_valueYpan = height()-m_sizeYpan; double dy = double(height()) / double(m_sizeY); int viewY = double(m_valueYpan) / dy + m_minY; Q_EMIT scrollVertical(viewY); } } // painting methods void Slider2d::paintEvent(QPaintEvent *) { QPainter p(this); p.setPen(m_pen); p.setBrush(m_brush); p.setOpacity(m_opacity); drawBackground(p, rect().adjusted(0,0,-1,-1)); p.setPen(m_panPen); p.setBrush(m_panBrush); p.setOpacity(m_panOpacity); drawSlider(p, QRect(m_valueXpan, m_valueYpan, m_sizeXpan, m_sizeYpan).adjusted(0,0,-1,-1)); } void Slider2d::drawBackground(QPainter& p, QRect r) { p.drawRect(r); } void Slider2d::drawSlider(QPainter& p, QRect r) { p.drawRect(r); } // helper methods void Slider2d::calculateXsize(int size) { m_sizeX = m_maxX - m_minX + m_viewSize.width(); double d = double(width()) / double(m_sizeX); m_sizeXpan = qMax(int(size * d), 1); } void Slider2d::calculateYsize(int size) { m_sizeY = m_maxY - m_minY + m_viewSize.height(); double d = double(height()) / double(m_sizeY); m_sizeYpan = qMax(int(size * d), 1); } // event filter bool Slider2d::eventFilter(QObject *obj, QEvent *event) { bool b = QObject::eventFilter(obj, event); QAbstractSlider *sl = dynamic_cast(obj); if (sl && event->type() == QEvent::Resize) { if (sl == m_sliderX) setHorizontalViewSize(sl->pageStep()); else if (sl == m_sliderY) setVerticalViewSize(sl->pageStep()); return b; } QMenu *tb = dynamic_cast(obj); if (tb && event->type() == QEvent::MouseMove) { this->mouseMoveEvent((QMouseEvent*)event); return b; } return b; } bool Slider2d::event(QEvent *e) { if (e->type() == QEvent::Paint) { if (m_sliderX) { setHorizontalRange(m_sliderX->minimum(), m_sliderX->maximum()); setHorizontalViewSize(m_sliderX->pageStep()); setHorizontalValue(m_sliderX->value()); } if (m_sliderY) { setVerticalRange(m_sliderY->minimum(), m_sliderY->maximum()); setVerticalViewSize(m_sliderY->pageStep()); setVerticalValue(m_sliderY->value()); } } return QWidget::event(e); } } // namespace QSint qvge-0.6.3/src/3rdParty/qsint-widgets/slider2d.h000066400000000000000000000104551405165517400214610ustar00rootroot00000000000000#pragma once #include #include #include #include namespace QSint { /** \brief 2-dimensional scrolling widget. \since 0.2 \image html Slider2d.png An example of Slider2d Slider2d is intended for scrolling in both direction (horizontal and vertical) at the same time. Main frame represents the scrollable area, and the slider inside the frame corresponds to the visible part. Slider is draggable within the frame (panning mode on). This behavior is enabled by default. If you want to disable the panning, use enablePanning(false). To use Slider2d, attach it to the source widget (which content intended to be scrolled) using one of connectSource() methods. Currently \a QAbstractScrollArea and \a QAbstractSlider descedants can be handled by Slider2d. \code // a QGraphicsView is a descedant of the QAbstractScrollArea QGraphicsView *myView; ... // create Slider2d and connect it to the QGraphicsView QSint::Slider2d *myPanner = new Slider2d(this); myPanner->connectSource(myView); \endcode */ class Slider2d : public QWidget { Q_OBJECT Q_PROPERTY(double opacity READ opacity WRITE setOpacity) Q_PROPERTY(double sliderOpacity READ sliderOpacity WRITE setSliderOpacity) Q_PROPERTY(bool panning READ isPanningEnabled WRITE enablePanning) Q_PROPERTY(QPen backgroundPen READ backgroundPen WRITE setBackgroundPen) Q_PROPERTY(QBrush backgroundBrush READ backgroundBrush WRITE setBackgroundBrush) Q_PROPERTY(QPen sliderPen READ sliderPen WRITE setSliderPen) Q_PROPERTY(QBrush sliderBrush READ sliderBrush WRITE setSliderBrush) public: /** Constructor */ explicit Slider2d(QWidget *parent = 0); /** Destructor */ virtual ~Slider2d(); void setBackgroundPen(const QPen& pen); inline QPen backgroundPen() const { return m_pen; } void setBackgroundBrush(const QBrush& brush); inline QBrush backgroundBrush() const { return m_brush; } void setSliderPen(const QPen& pen); inline QPen sliderPen() const { return m_panPen; } void setSliderBrush(const QBrush& brush); inline QBrush sliderBrush() const { return m_panBrush; } void setOpacity(double opacity); inline double opacity() const { return m_opacity; } void setSliderOpacity(double opacity); inline double sliderOpacity() const { return m_panOpacity; } /** Returns true if mouse panning is enabled (default), false otherwise. \sa enablePanning() */ inline bool isPanningEnabled() const { return m_panning; } void connectSource(QAbstractScrollArea *area); void connectSource(QAbstractSlider *horizontal, QAbstractSlider *vertical); void disconnectSource(); QToolButton* makeAsButton(); // reimp virtual QSize minimumSizeHint() const { return QSize(64,64); } Q_SIGNALS: void scrollHorizontal(int value); void scrollVertical(int value); void aboutToShow(); public Q_SLOTS: void onAboutToShow(); void setHorizontalRange(int min, int max); void setHorizontalValue(int value); void setHorizontalViewSize(int size); void setVerticalRange(int min, int max); void setVerticalValue(int value); void setVerticalViewSize(int size); void setViewSize(const QSize &size); /** Sets panning mode to \a on (true by default). When panning is enabled, you can move the slider by the mouse. */ void enablePanning(bool on = true); protected: virtual void paintEvent(QPaintEvent *); virtual bool eventFilter(QObject *, QEvent *); virtual void mousePressEvent(QMouseEvent *); virtual void mouseMoveEvent(QMouseEvent *); virtual bool event(QEvent *); virtual void drawBackground(QPainter& p, QRect r); virtual void drawSlider(QPainter& p, QRect r); void calculateXsize(int size); void calculateYsize(int size); void connectH(QAbstractSlider *sl); void connectV(QAbstractSlider *sl); int m_minX, m_maxX, m_sizeX, m_valueX; int m_valueXpan, m_sizeXpan; int m_minY, m_maxY, m_sizeY, m_valueY; int m_valueYpan, m_sizeYpan; QSize m_viewSize; QPen m_pen, m_panPen; QBrush m_brush, m_panBrush; double m_opacity, m_panOpacity; bool m_panning; int m_oldX, m_oldY; QAbstractSlider *m_sliderX, *m_sliderY; }; } // namespace QSint qvge-0.6.3/src/3rdParty/qsint-widgets/spincombobox.cpp000066400000000000000000000023311405165517400230000ustar00rootroot00000000000000#include "spincombobox.h" namespace QSint { SpinComboBox::SpinComboBox(QWidget *parent) : QSpinBox(parent) { m_button = new QToolButton(this); m_button->setFixedWidth(16); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); m_button->setPopupMode(QToolButton::InstantPopup); m_button->setVisible(false); connect(m_button, SIGNAL(triggered(QAction*)), this, SLOT(onAction(QAction*))); QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); setLayout(mainLayout); mainLayout->addStretch(); mainLayout->addWidget(m_button); } void SpinComboBox::setValueList(const QList &values) { m_button->setVisible(!values.isEmpty()); if (values.isEmpty()) return; QMenu *m = new QMenu(this); for (int i : values) { QAction *a = m->addAction(QString::number(i)); a->setData(i); } m_button->setMenu(m); } // protected members void SpinComboBox::resizeEvent(QResizeEvent *event) { QSpinBox::resizeEvent(event); int arrowSize = m_button->width(); layout()->setContentsMargins(1, 1, arrowSize - 1, 1); } void SpinComboBox::onAction(QAction* act) { int v = act->data().toInt(); setValue(v); } } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/spincombobox.h000066400000000000000000000012401405165517400224430ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include namespace QSint { /** \brief Spin editor with additional drop down menu. \since 0.4 \image html SpinComboBox.png An example of SpinComboBox */ class SpinComboBox : public QSpinBox { Q_OBJECT public: /** Constructor. */ explicit SpinComboBox(QWidget *parent = 0); void setValueList(const QList &values); Q_SIGNALS: protected Q_SLOTS: void onAction(QAction* action); protected: virtual void resizeEvent(QResizeEvent* event); QToolButton *m_button; }; } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/spinslider.cpp000066400000000000000000000066361405165517400224660ustar00rootroot00000000000000#include "spinslider.h" namespace QSint { SpinSlider::SpinSlider(QWidget *parent) : QWidget(parent) { QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout->setContentsMargins(0,0,0,0); m_editor = new QSpinBox(this); mainLayout->addWidget(m_editor); m_unitLabel = new QLabel(this); m_unitLabel->hide(); mainLayout->addWidget(m_unitLabel); m_minButton = new QToolButton(this); mainLayout->addWidget(m_minButton); m_slider = new QSlider(this); m_slider->setOrientation(Qt::Horizontal); mainLayout->addWidget(m_slider); m_maxButton = new QToolButton(this); mainLayout->addWidget(m_maxButton); m_sliderMultiplier = 1; UpdateConstrains(); connect(m_editor, SIGNAL(valueChanged(int)), this, SLOT(OnEditorValueChanged(int))); connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderMoved(int))); connect(m_minButton, SIGNAL(clicked()), this, SLOT(OnMinButtonClicked())); connect(m_maxButton, SIGNAL(clicked()), this, SLOT(OnMaxButtonClicked())); } void SpinSlider::setMinimum(int val) { m_editor->setMinimum(val); UpdateConstrains(); } void SpinSlider::setMaximum(int val) { m_editor->setMaximum(val); UpdateConstrains(); } void SpinSlider::setSliderMultiplier(int val) { if (val > 0){ m_sliderMultiplier = val; UpdateConstrains(); } } void SpinSlider::enableTicks(bool on) { m_slider->setTickPosition(on ? QSlider::TicksBelow : QSlider::NoTicks); } void SpinSlider::expandVertically(bool on) { if (on){ m_editor->setSizePolicy(m_editor->sizePolicy().horizontalPolicy(), QSizePolicy::Preferred); m_minButton->setSizePolicy(m_minButton->sizePolicy().horizontalPolicy(), QSizePolicy::Preferred); m_maxButton->setSizePolicy(m_maxButton->sizePolicy().horizontalPolicy(), QSizePolicy::Preferred); } else{ m_editor->setSizePolicy(m_editor->sizePolicy().horizontalPolicy(), QSizePolicy::Maximum); m_minButton->setSizePolicy(m_minButton->sizePolicy().horizontalPolicy(), QSizePolicy::Maximum); m_maxButton->setSizePolicy(m_maxButton->sizePolicy().horizontalPolicy(), QSizePolicy::Maximum); } } void SpinSlider::setEditorWidth(int width) { m_editor->setFixedWidth(width); } void SpinSlider::setUnitLabelWidth(int width) { m_unitLabel->setFixedWidth(width); m_unitLabel->setVisible(width > 0); } void SpinSlider::setUnitText(const QString &val) { m_unitLabel->setText(val); m_unitLabel->setVisible(!val.isEmpty()); } // protected members void SpinSlider::UpdateConstrains() { m_minButton->setText(QString::number(m_editor->minimum())); m_maxButton->setText(QString::number(m_editor->maximum())); m_slider->blockSignals(true); m_slider->setRange(m_editor->minimum() / m_sliderMultiplier, m_editor->maximum() / m_sliderMultiplier); m_slider->blockSignals(false); } // protected slots void SpinSlider::OnEditorValueChanged(int val) { m_slider->blockSignals(true); m_slider->setValue(val / m_sliderMultiplier); m_slider->blockSignals(false); m_minButton->setEnabled(val != minimum()); m_maxButton->setEnabled(val != maximum()); } void SpinSlider::OnSliderMoved(int val) { m_editor->setValue(val * m_sliderMultiplier); } void SpinSlider::OnMinButtonClicked() { m_editor->setValue(minimum()); } void SpinSlider::OnMaxButtonClicked() { m_editor->setValue(maximum()); } } // namespace qvge-0.6.3/src/3rdParty/qsint-widgets/spinslider.h000066400000000000000000000045431405165517400221260ustar00rootroot00000000000000#ifndef SPINSLIDER_H #define SPINSLIDER_H #include #include #include #include #include namespace QSint { /** \brief Spin editor with additional buttons and slider for quick value edition. \since 0.2.2 \image html SpinSlider.png An example of SpinSlider */ class SpinSlider : public QWidget { Q_OBJECT Q_PROPERTY(int minimum READ minimum WRITE setMinimum) Q_PROPERTY(int maximum READ maximum WRITE setMaximum) Q_PROPERTY(int value READ value WRITE setValue) Q_PROPERTY(int sliderMultiplier READ sliderMultiplier WRITE setSliderMultiplier) Q_PROPERTY(bool showTicks READ ticksEnabled WRITE enableTicks) Q_PROPERTY(QString unitText READ unitText WRITE setUnitText) public: /** Constructor. */ explicit SpinSlider(QWidget *parent = 0); int value() const { return m_editor->value(); } int minimum() const { return m_editor->minimum(); } int maximum() const { return m_editor->maximum(); } void setValue(int val) { m_editor->setValue(val); } void setMinimum(int val); void setMaximum(int val); int sliderMultiplier() const { return m_sliderMultiplier; } void setSliderMultiplier(int val); bool ticksEnabled() const { return m_slider->tickPosition() != QSlider::NoTicks; } void enableTicks(bool on = true); void expandVertically(bool on = true); void setEditorWidth(int width); void setUnitLabelWidth(int width); QString unitText() const { return m_unitLabel->text(); } void setUnitText(const QString& val); void setSingleStep(int step) { m_slider->setSingleStep(step); } void setPageStep(int step) { m_slider->setPageStep(step); } void setOrientation(int) {} Q_SIGNALS: /** Signal emitted when the current index is changed either by the user or programmatically. */ void valueChanged(int index); protected Q_SLOTS: void OnEditorValueChanged(int val); void OnSliderMoved(int val); void OnMinButtonClicked(); void OnMaxButtonClicked(); protected: void UpdateConstrains(); QSpinBox *m_editor; QSlider *m_slider; QToolButton *m_minButton, *m_maxButton; QLabel *m_unitLabel; int m_sliderMultiplier; }; } // namespace #endif // SPINSLIDER_H qvge-0.6.3/src/3rdParty/qsint-widgets/splitbutton.cpp000066400000000000000000000056221405165517400226730ustar00rootroot00000000000000#include "splitbutton.h" #include namespace QSint { SplitButton::SplitButton(QWidget *parent) : QWidget(parent) { m_button = new QToolButton(this); m_button->setObjectName("Button"); m_button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); m_button->setToolButtonStyle(Qt::ToolButtonIconOnly); m_split = new QToolButton(this); m_split->setObjectName("Split"); m_split->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); m_split->setToolButtonStyle(Qt::ToolButtonTextOnly); m_split->setPopupMode(QToolButton::InstantPopup); QVBoxLayout *vbl = new QVBoxLayout(); vbl->setContentsMargins(0,0,0,0); vbl->setSpacing(0); setLayout(vbl); vbl->addWidget(m_button); vbl->addWidget(m_split); m_menu = new QMenu(this); m_split->setMenu(m_menu); connect(m_menu, &QMenu::aboutToShow, this, &SplitButton::onMenuShow); connect(m_menu, &QMenu::triggered, this, &SplitButton::onMenuTriggered); connect(m_button, &QToolButton::clicked, this, &SplitButton::onButtonClicked); setIconSize(32); m_split->setMinimumHeight(24); // style setStyleSheet( "QToolButton#Button{" "border: 1px solid #ccc; border-top-left-radius: 5px; border-top-right-radius: 5px; " "background: #ddd;" "}" "QToolButton#Split{" "border: 1px solid #ccc; border-top-color: #ddd; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px;" "background: #ddd;" "}" "QToolButton#Button:hover, QToolButton#Split:hover" "{" "background: #def; border-color: #09e;" "}" "QToolButton#Button:clicked, QToolButton#Split:clicked" "{" "background: #09e;" "}" ); } void SplitButton::onMenuShow() { m_menu->clear(); m_menu->addActions(actions()); m_menu->setDefaultAction(m_button->defaultAction()); } void SplitButton::onMenuTriggered(QAction *action) { if (m_setLast) { setDefaultAction(action); } } void SplitButton::onButtonClicked() { const auto& acts = actions(); if (m_toggle && acts.count()) { int index = acts.indexOf(m_button->defaultAction()); if (index < 0 || index == acts.count()-1) setDefaultAction(acts.first()); else setDefaultAction(acts.at(index+1)); } } void SplitButton::setDefaultAction(QAction *action) { // Qt bug workaround: setDefaultAction is adding action to actions while (m_button->actions().count()) m_button->removeAction(m_button->actions().first()); m_button->setDefaultAction(action); m_split->setDefaultAction(action); } void SplitButton::setIconSize(int size) { m_button->setIconSize(QSize(size, size)); } void SplitButton::setLastActionDefault(bool on) { m_setLast = on; } void SplitButton::setActionsToggle(bool on) { m_toggle = on; } } qvge-0.6.3/src/3rdParty/qsint-widgets/splitbutton.h000066400000000000000000000030671405165517400223410ustar00rootroot00000000000000#ifndef CSPLITBUTTON_H #define CSPLITBUTTON_H #include #include #include namespace QSint { /** * @brief The SplitButton class represents Microsoft Office-like "Split Button" control which consists * of a clickable button itself and a drop-down list of some common actions connected with the button. * * Clicking on the button fires its default action (set via setDefaultAction() method). * Depending of the operation modes, default button action can be set automatically after choosing an option * from the drop-down list (see setLastActionDefault()) or can be toggled to the another one action * after the click on the button (see setActionsToggle()). * * \since 0.4 */ class SplitButton : public QWidget { Q_OBJECT public: explicit SplitButton(QWidget *parent = nullptr); /// Set button's icon size to \a size. void setIconSize(int size); /// Set action \a action as default (it will be invoked after clicking on the button). void setDefaultAction(QAction *action); /// If \a on, the recently chosen action from the list will be set as default. void setLastActionDefault(bool on); /// If \a on, clicking on the button will automatically advance to the next action in the list. void setActionsToggle(bool on); signals: private slots: void onMenuShow(); void onMenuTriggered(QAction *action); void onButtonClicked(); private: QToolButton *m_button; QToolButton *m_split; QMenu *m_menu; bool m_setLast = false; bool m_toggle = false; }; } #endif // CSPLITBUTTON_H qvge-0.6.3/src/3rdParty/qsint-widgets/timepicker.cpp000066400000000000000000000055731405165517400224450ustar00rootroot00000000000000#include "timepicker.h" #include #include #include #include #include #include namespace QSint { TimePicker::TimePicker(QWidget *parent) : QWidget(parent) { QHBoxLayout *hbl = new QHBoxLayout(); setLayout(hbl); QGroupBox *hourBox = new QGroupBox(this); hourBox->setTitle(tr("Hours")); QGridLayout *hourGrid = new QGridLayout(); hourGrid->setSpacing(0); hourGrid->setMargin(1); hourBox->setLayout(hourGrid); hbl->addWidget(hourBox); int hour = 0; for (int r = 0; r < 6; r++) { for (int c = 0; c < 4; c++) { QToolButton *hourButton = new QToolButton(this); hourButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); hourButton->setText(QString::number(hour)); hourGrid->addWidget(hourButton, r, c); m_hourButtons.addButton(hourButton, hour); hour++; } } QGroupBox *minuteBox = new QGroupBox(this); minuteBox->setTitle(tr("Minutes")); QGridLayout *minuteGrid = new QGridLayout(); minuteGrid->setSpacing(0); minuteGrid->setMargin(1); minuteBox->setLayout(minuteGrid); hbl->addWidget(minuteBox); int minute = 0; for (int r = 0; r < 6; r++) { for (int c = 0; c < 10; c++) { QToolButton *minuteButton = new QToolButton(this); minuteButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); minuteButton->setText(QString::number(minute)); minuteGrid->addWidget(minuteButton, r, c); m_minuteButtons.addButton(minuteButton, minute); minute++; } } m_time = QTime::currentTime(); connect(&m_hourButtons, SIGNAL(buttonClicked(int)), this, SLOT(hourClicked(int))); connect(&m_minuteButtons, SIGNAL(buttonClicked(int)), this, SLOT(minuteClicked(int))); } void TimePicker::setTime(const QTime& time) { m_time = time; } void TimePicker::hourClicked(int hour) { m_time.setHMS(hour, m_time.minute(), 0, 0); Q_EMIT timePicked(m_time); } void TimePicker::minuteClicked(int minute) { m_time.setHMS(m_time.hour(), minute, 0, 0); Q_EMIT timePicked(m_time); } // picker button TimePickerButton::TimePickerButton(QWidget *parent) : QToolButton(parent), m_editor(NULL) { QFrame *frame = new QFrame(); frame->setLayout(new QVBoxLayout()); frame->layout()->addWidget(&m_timePicker); frame->layout()->setMargin(0); frame->setFrameShape(QFrame::Box); m_dialog = new QDialog(this, Qt::Popup); m_dialog->setLayout(new QVBoxLayout()); m_dialog->layout()->addWidget(frame); m_dialog->layout()->setMargin(0); connect(this, SIGNAL(clicked()), this, SLOT(OnButtonClicked())); } void TimePickerButton::OnButtonClicked() { if (m_editor) { m_timePicker.setTime(m_editor->time()); connect(&m_timePicker, SIGNAL(timePicked(QTime)), m_editor, SLOT(setTime(QTime))); } m_dialog->move(parentWidget()->mapToGlobal(pos() + QPoint(-m_dialog->width() / 2, height()))); m_dialog->exec(); if (m_editor) { m_timePicker.disconnect(m_editor); } } } qvge-0.6.3/src/3rdParty/qsint-widgets/timepicker.h000066400000000000000000000023511405165517400221010ustar00rootroot00000000000000#ifndef TIMEPICKER_H #define TIMEPICKER_H #include #include #include #include #include namespace QSint { /** * @brief The TimePicker class allows to choose a time moment in a hour:minute form via simple UI. * \since 0.4 */ class TimePicker : public QWidget { Q_OBJECT public: /** Constructor. */ explicit TimePicker(QWidget *parent = 0); /** Returns current time. */ QTime time() const { return m_time; } public Q_SLOTS: /** Sets current time. */ void setTime(const QTime& time); Q_SIGNALS: void timePicked(const QTime& time); private Q_SLOTS: void hourClicked(int hour); void minuteClicked(int minute); protected: QTime m_time; QButtonGroup m_hourButtons; QButtonGroup m_minuteButtons; }; // button with popup dialog class TimePickerButton : public QToolButton { Q_OBJECT public: TimePickerButton(QWidget *parent = 0); void setTimeEdit(QTimeEdit *timeEdit) { m_editor = timeEdit; } TimePicker* pickerWidget() { return &m_timePicker; } QDialog* dialogWidget() { return m_dialog; } private Q_SLOTS: void OnButtonClicked(); protected: QDialog* m_dialog; QTimeEdit* m_editor; TimePicker m_timePicker; }; } #endif // TIMEPICKER_H qvge-0.6.3/src/3rdParty/qsint-widgets/widgets.pri000066400000000000000000000000761405165517400217600ustar00rootroot00000000000000HEADERS += $$files($$PWD/*.h) SOURCES += $$files($$PWD/*.cpp) qvge-0.6.3/src/3rdParty/qtpropertybrowser/000077500000000000000000000000001405165517400206265ustar00rootroot00000000000000qvge-0.6.3/src/3rdParty/qtpropertybrowser/LICENSE000066400000000000000000000030341405165517400216330ustar00rootroot00000000000000Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). Contact: http://www.qt-project.org/legal 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 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. qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtAbstractEditorFactoryBase000066400000000000000000000000371405165517400261130ustar00rootroot00000000000000#include "qtpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtAbstractPropertyBrowser000066400000000000000000000000371405165517400257320ustar00rootroot00000000000000#include "qtpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtAbstractPropertyManager000066400000000000000000000000371405165517400256610ustar00rootroot00000000000000#include "qtpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtBoolPropertyManager000066400000000000000000000000371405165517400250110ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtBrowserItem000066400000000000000000000000371405165517400233200ustar00rootroot00000000000000#include "qtpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtButtonPropertyBrowser000066400000000000000000000000451405165517400254410ustar00rootroot00000000000000#include "qtbuttonpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtCharEditorFactory000066400000000000000000000000351405165517400244300ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtCharPropertyManager000066400000000000000000000000371405165517400247730ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtCheckBoxFactory000066400000000000000000000000351405165517400240720ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtColorEditorFactory000066400000000000000000000000351405165517400246310ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtColorPropertyManager000066400000000000000000000000371405165517400251740ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtCursorEditorFactory000066400000000000000000000000351405165517400250300ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtCursorPropertyManager000066400000000000000000000000371405165517400253730ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtDateEditFactory000066400000000000000000000000351405165517400240670ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtDatePropertyManager000066400000000000000000000000371405165517400247730ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtDateTimeEditFactory000066400000000000000000000000351405165517400247060ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtDateTimePropertyManager000066400000000000000000000000371405165517400256120ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtDoublePropertyManager000066400000000000000000000000371405165517400253300ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtDoubleSpinBoxFactory000066400000000000000000000000351405165517400251210ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtEnumEditorFactory000066400000000000000000000000351405165517400244570ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtEnumPropertyManager000066400000000000000000000000371405165517400250220ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtFlagPropertyManager000066400000000000000000000000371405165517400247670ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtFontEditorFactory000066400000000000000000000000351405165517400244610ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtFontPropertyManager000066400000000000000000000000371405165517400250240ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtGroupBoxPropertyBrowser000066400000000000000000000000471405165517400257350ustar00rootroot00000000000000#include "qtgroupboxpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtGroupPropertyManager000066400000000000000000000000371405165517400252120ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtIntPropertyManager000066400000000000000000000000371405165517400246500ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtKeySequenceEditorFactory000066400000000000000000000000351405165517400257740ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtKeySequencePropertyManager000066400000000000000000000000371405165517400263370ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtLineEditFactory000066400000000000000000000000351405165517400241010ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtLocalePropertyManager000066400000000000000000000000371405165517400253150ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtPointFPropertyManager000066400000000000000000000000371405165517400253150ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtPointPropertyManager000066400000000000000000000000371405165517400252070ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtProperty000066400000000000000000000000371405165517400227020ustar00rootroot00000000000000#include "qtpropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtRectFPropertyManager000066400000000000000000000000371405165517400251210ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtRectPropertyManager000066400000000000000000000000371405165517400250130ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtScrollBarFactory000066400000000000000000000000351405165517400242670ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtSizeFPropertyManager000066400000000000000000000000371405165517400251360ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtSizePolicyPropertyManager000066400000000000000000000000371405165517400262100ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtSizePropertyManager000066400000000000000000000000371405165517400250300ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtSliderFactory000066400000000000000000000000351405165517400236260ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtSpinBoxFactory000066400000000000000000000000351405165517400237660ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtStringPropertyManager000066400000000000000000000000371405165517400253640ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtTimeEditFactory000066400000000000000000000000351405165517400241100ustar00rootroot00000000000000#include "qteditorfactory.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtTimePropertyManager000066400000000000000000000000371405165517400250140ustar00rootroot00000000000000#include "qtpropertymanager.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtTreePropertyBrowser000066400000000000000000000000431405165517400250630ustar00rootroot00000000000000#include "qttreepropertybrowser.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtVariantEditorFactory000066400000000000000000000000371405165517400251610ustar00rootroot00000000000000#include "qtvariantproperty.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtVariantProperty000066400000000000000000000000371405165517400242270ustar00rootroot00000000000000#include "qtvariantproperty.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/QtVariantPropertyManager000066400000000000000000000000371405165517400255220ustar00rootroot00000000000000#include "qtvariantproperty.h" qvge-0.6.3/src/3rdParty/qtpropertybrowser/README.TXT000066400000000000000000000114141405165517400221650ustar00rootroot00000000000000Qt 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). 2.7: (Extended because of needs of QVGE/DPSE projects) (See https://github.com/ArsMasiuk/qvge) - String, Int, Double, Float properties - value changed signals are now only sent when editing is finished by a user. - Double property: - input of either comma or dot as decimal point allowed independent of the current locale. - trailing decimal zeros are visually trimmed. - no group separators shown. - String property: editor of multiline text added. qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/000077500000000000000000000000001405165517400220735ustar00rootroot00000000000000qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-arrow.png000066400000000000000000000002531405165517400252460ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@fPIDATx^=α 0 ѤA"9Oh؁-k^cK?m :V-@Gêeΰqo_NpoYք^]IuZIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-busy.png000066400000000000000000000003111405165517400250710ustar00rootroot00000000000000PNG  IHDR g PLTE~OtRNS@fnIDATx^ͱ 0P ~)~6idJWO.l(@ X`@ tJ!9l&aqlQ] ~#-搫I 8{4u4IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-closedhand.png000066400000000000000000000002231405165517400262150ustar00rootroot00000000000000PNG  IHDR7 pHYs 7˭EIDAT(ϭ D-$pzS逢B@@r(2`' ـM^ PIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-cross.png000066400000000000000000000002021405165517400252370ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@f'IDATc`  P Vpm=XK "IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-forbidden.png000066400000000000000000000003071405165517400260500ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@flIDATx^uα C1P y \`4.L`"EB \RAc!OҾU+2ֵ_d\l+ Zz<'r:#7$/sIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-hand.png000066400000000000000000000002371405165517400250300ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@fDIDAT[c``aL(=XzjБ JcZd N Ѫf @&ЫV-J7U%IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-hsplit.png000066400000000000000000000002331405165517400254150ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f@IDATc`..@ ͡TY;AӀtS`` e Cap0 w/PܪIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-ibeam.png000066400000000000000000000001741405165517400251730ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f!IDATc`"`*@340܇^TIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-openhand.png000066400000000000000000000002401405165517400257040ustar00rootroot00000000000000PNG  IHDR7 pHYs 7˭RIDAT(υ_tW&DNt^a'`O#9#V*~Wa`'-$2d_=J;Ҁ>x0tbIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-sizeall.png000066400000000000000000000002561405165517400255620ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fSIDAT[c`\ f^5P00:H0:%BD&pÁ f/0watêNXIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-sizeb.png000066400000000000000000000002411405165517400252250ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fFIDATc` VjSC!*ҌPJBN1 D`uN:5J@(ƀbv l= jIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-sizef.png000066400000000000000000000002411405165517400252310ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fFIDATc` VjSCtD|j!z(00AtpBhQU 5JsBiPTa.$,= 'IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-sizeh.png000066400000000000000000000002211405165517400252310ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f6IDAT[c`h00p% l LSXBtg(D h8LL# /97IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-sizev.png000066400000000000000000000002151405165517400252520ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f2IDAT[c`L+ 4W kKC驡 Emf>>0܇4 SvIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-uparrow.png000066400000000000000000000002041405165517400256070ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f)IDAT[c`L+ 4W kKC驡 0` B7~2IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-vsplit.png000066400000000000000000000002411405165517400254320ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fFIDAT[c`  9Cjh3UfZR p`G3f~{VOIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-wait.png000066400000000000000000000002541405165517400250610ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@fQIDATc`@RVӡ|:r&KS.ьK& ʜ10bpfD~%󦢚37--{PY IENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/images/cursor-whatsthis.png000066400000000000000000000002771405165517400261400ustar00rootroot00000000000000PNG  IHDR g PLTEtRNS@fdIDATWch` ! U+Ai lS R #1B[&-3VHMa̘e,1TD֫6@D8 SÀ$W/qIENDB`qvge-0.6.3/src/3rdParty/qtpropertybrowser/lineedit.cpp000066400000000000000000000036751405165517400231420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (c) 2007 Trolltech ASA ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #include "lineedit.h" #include #include #include QInputDialog *LineEdit::inputDialog = NULL; LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) { editorButton = new QToolButton(this); editorButton->setText("..."); editorButton->setCursor(Qt::ArrowCursor); editorButton->setEnabled(true); editorButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); connect(editorButton, SIGNAL(clicked()), this, SLOT(showEditor())); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(editorButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); setMinimumSize(qMax(msz.width(), editorButton->sizeHint().height() + frameWidth * 2 + 2), qMax(msz.height(), editorButton->sizeHint().height() + frameWidth * 2 + 2)); if (!inputDialog) { inputDialog = new QInputDialog(NULL); inputDialog->setOption(QInputDialog::UsePlainTextEditForTextInput); inputDialog->setInputMode(QInputDialog::TextInput); inputDialog->setWindowTitle(tr("Text Property")); inputDialog->resize(480, 320); } } void LineEdit::resizeEvent(QResizeEvent *) { QSize sz = editorButton->sizeHint(); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); editorButton->move(rect().right() - frameWidth - sz.width(), (rect().bottom() + 1 - sz.height()) / 2); } void LineEdit::showEditor() { inputDialog->setTextValue(text()); if (inputDialog->exec() == QDialog::Accepted && inputDialog->textValue() != text()) { setText(inputDialog->textValue()); Q_EMIT editingFinished(); } }qvge-0.6.3/src/3rdParty/qtpropertybrowser/lineedit.h000066400000000000000000000013061405165517400225740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (c) 2007 Trolltech ASA ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #ifndef LINEEDIT_H #define LINEEDIT_H #include class QToolButton; class QInputDialog; class LineEdit : public QLineEdit { Q_OBJECT public: LineEdit(QWidget *parent = 0); protected: void resizeEvent(QResizeEvent *); private Q_SLOTS: void showEditor(); private: QToolButton *editorButton; static QInputDialog *inputDialog; }; #endif // LIENEDIT_H qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtbuttonpropertybrowser.cpp000066400000000000000000000462731405165517400264370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtbuttonpropertybrowser.h" #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE 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; } QT_END_NAMESPACE #include "moc_qtbuttonpropertybrowser.cpp" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtbuttonpropertybrowser.h000066400000000000000000000051241405165517400260720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTBUTTONPROPERTYBROWSER_H #define QTBUTTONPROPERTYBROWSER_H #include "qtpropertybrowser.h" QT_BEGIN_NAMESPACE class QtButtonPropertyBrowserPrivate; class 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)) }; QT_END_NAMESPACE #endif qvge-0.6.3/src/3rdParty/qtpropertybrowser/qteditorfactory.cpp000066400000000000000000002453351405165517400245710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qteditorfactory.h" #include "qtpropertybrowserutils_p.h" #include "lineedit.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 QT_BEGIN_NAMESPACE // 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 slotEditFinished(); }; 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::slotEditFinished() { 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, itEditor.key()->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(editingFinished()), this, SLOT(slotEditFinished())); 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 /* QDoubleSpinBox supporting . and , and cutting trailing zeros. */ class CDoubleSpinBox : public QDoubleSpinBox { public: CDoubleSpinBox(QWidget* parent = NULL) : QDoubleSpinBox(parent) { setGroupSeparatorShown(false); } virtual double valueFromText(const QString &text) const { QChar c1 = locale().decimalPoint(); QChar c2 = (c1 == '.') ? ',' : '.'; QString corrText = QString(text).replace(c2, c1); return QDoubleSpinBox::valueFromText(corrText); } virtual QString textFromValue(double value) const { QString text = QDoubleSpinBox::textFromValue(value); QChar c1 = locale().decimalPoint(); return QtPropertyBrowserUtils::trimDecimalZeros(c1, text); } }; 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 slotEditFinished(); }; void QtDoubleSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, double value) { QList editors = m_createdEditors[property]; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { CDoubleSpinBox *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()) { CDoubleSpinBox *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()) { CDoubleSpinBox *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()) { CDoubleSpinBox *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()) { CDoubleSpinBox *editor = itEditor.next(); editor->blockSignals(true); editor->setDecimals(prec); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotEditFinished() { QObject *object = q_ptr->sender(); const auto itcend = m_editorToProperty.constEnd(); for (auto 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, itEditor.key()->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(editingFinished()), this, SLOT(slotEditFinished())); 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 slotEditFinished(); 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()) { LineEdit *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()) { LineEdit *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()) { LineEdit *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()) { LineEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setReadOnly(readOnly); editor->blockSignals(false); } } void QtLineEditFactoryPrivate::slotEditFinished() { QObject *object = q_ptr->sender(); const auto ecend = m_editorToProperty.constEnd(); for (auto 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, itEditor.key()->text()); 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) { LineEdit *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(editingFinished()), this, SLOT(slotEditFinished())); 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))); } QT_END_NAMESPACE #include "moc_qteditorfactory.cpp" #include "qteditorfactory.moc" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qteditorfactory.h000066400000000000000000000361711405165517400242320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTEDITORFACTORY_H #define QTEDITORFACTORY_H #include "qtpropertymanager.h" QT_BEGIN_NAMESPACE class QtSpinBoxFactoryPrivate; class 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 slotEditFinished()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtSliderFactoryPrivate; class 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 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 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 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 slotEditFinished()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtLineEditFactoryPrivate; class 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 slotEditFinished()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtDateEditFactoryPrivate; class 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 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 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 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 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 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 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 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 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 &)) }; QT_END_NAMESPACE #endif qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp000066400000000000000000000415151405165517400267630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtgroupboxpropertybrowser.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE 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); } QT_END_NAMESPACE #include "moc_qtgroupboxpropertybrowser.cpp" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtgroupboxpropertybrowser.h000066400000000000000000000045501405165517400264260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTGROUPBOXPROPERTYBROWSER_H #define QTGROUPBOXPROPERTYBROWSER_H #include "qtpropertybrowser.h" QT_BEGIN_NAMESPACE class QtGroupBoxPropertyBrowserPrivate; class 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()) }; QT_END_NAMESPACE #endif qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowser.cpp000066400000000000000000001756341405165517400252070ustar00rootroot00000000000000/**************************************************************************** ** ** 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 QT_BEGIN_NAMESPACE 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); } QT_END_NAMESPACE #include "moc_qtpropertybrowser.cpp" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowser.h000066400000000000000000000245401405165517400246410ustar00rootroot00000000000000/**************************************************************************** ** ** 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 typedef QLineEdit::EchoMode EchoMode; QT_BEGIN_NAMESPACE class QtAbstractPropertyManager; class QtPropertyPrivate; class 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 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 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 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 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 *)) }; QT_END_NAMESPACE #endif // QTPROPERTYBROWSER_H qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowser.pri000066400000000000000000000015341405165517400252020ustar00rootroot00000000000000include(../common.pri) INCLUDEPATH += $$PWD DEPENDPATH += $$PWD 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 \ $$PWD/lineedit.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 \ $$PWD/lineedit.h RESOURCES += $$PWD/qtpropertybrowser.qrc qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowser.pro000066400000000000000000000000671405165517400252100ustar00rootroot00000000000000QT += core gui widgets include(qtpropertybrowser.pri) qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowser.qrc000066400000000000000000000016471405165517400252020ustar00rootroot00000000000000 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 qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowserutils.cpp000066400000000000000000000375751405165517400262710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtpropertybrowserutils_p.h" #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE QtCursorDatabase::QtCursorDatabase() { Q_INIT_RESOURCE(qtpropertybrowser); 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()); } QString QtPropertyBrowserUtils::trimDecimalZeros(const QChar &point, const QString &text) { int idx = text.indexOf(point); if (idx >= 0) { QString corrText(text); while (corrText.endsWith('0')) corrText.chop(1); if (corrText.endsWith(point)) corrText.chop(1); return corrText; } else return text; } QString QtPropertyBrowserUtils::dateFormat() { QLocale loc; return loc.dateFormat(QLocale::ShortFormat); } QString QtPropertyBrowserUtils::timeFormat() { QLocale loc; // ShortFormat is missing seconds on UNIX. return loc.timeFormat(QLocale::LongFormat); } QString QtPropertyBrowserUtils::dateTimeFormat() { QString format = dateFormat(); format += QLatin1Char(' '); format += timeFormat(); return format; } 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); } QT_END_NAMESPACE qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertybrowserutils_p.h000066400000000000000000000111441405165517400262350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $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 QT_BEGIN_NAMESPACE 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); static QString trimDecimalZeros(const QChar &point, const QString &text); static QString dateFormat(); static QString timeFormat(); static QString dateTimeFormat(); }; 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; }; QT_END_NAMESPACE #endif qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertymanager.cpp000066400000000000000000006452731405165517400251370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtpropertymanager.h" #include "qtpropertybrowserutils_p.h" #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 QT_BEGIN_NAMESPACE 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(); QString text = QLocale::system().toString(it.value().val, 'f', it.value().decimals); QChar c1 = QLocale::system().decimalPoint(); return QtPropertyBrowserUtils::trimDecimalZeros(c1, text); } /*! \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 echoModeChanged(property, data.echoMode); } /*! \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); } QT_END_NAMESPACE #include "moc_qtpropertymanager.cpp" #include "qtpropertymanager.moc" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtpropertymanager.h000066400000000000000000000640171405165517400245730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTPROPERTYMANAGER_H #define QTPROPERTYMANAGER_H #include "qtpropertybrowser.h" QT_BEGIN_NAMESPACE class QDate; class QTime; class QDateTime; class QLocale; class 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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) }; QT_END_NAMESPACE #endif qvge-0.6.3/src/3rdParty/qtpropertybrowser/qttreepropertybrowser.cpp000066400000000000000000001047431405165517400260600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qttreepropertybrowser.h" #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE 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()->setSectionsMovable(false); m_treeWidget->header()->setSectionResizeMode(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()->setSectionResizeMode(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); } QT_END_NAMESPACE #include "moc_qttreepropertybrowser.cpp" #include "qttreepropertybrowser.moc" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qttreepropertybrowser.h000066400000000000000000000105561405165517400255230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTTREEPROPERTYBROWSER_H #define QTTREEPROPERTYBROWSER_H #include "qtpropertybrowser.h" QT_BEGIN_NAMESPACE class QTreeWidgetItem; class QtTreePropertyBrowserPrivate; class 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 *)) }; QT_END_NAMESPACE #endif qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtvariantproperty.cpp000066400000000000000000003107041405165517400251550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $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 QT_BEGIN_NAMESPACE class QtEnumPropertyType { }; class QtFlagPropertyType { }; class QtGroupPropertyType { }; QT_END_NAMESPACE Q_DECLARE_METATYPE(QtEnumPropertyType) Q_DECLARE_METATYPE(QtFlagPropertyType) Q_DECLARE_METATYPE(QtGroupPropertyType) QT_BEGIN_NAMESPACE /*! 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, qvariant_cast(val)); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { doubleManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { boolManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { stringManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { dateManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { timeManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { dateTimeManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { keySequenceManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { charManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtLocalePropertyManager *localeManager = qobject_cast(manager)) { localeManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { pointManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { pointFManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { sizeManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { sizeFManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { rectManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { rectFManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { colorManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { enumManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtSizePolicyPropertyManager *sizePolicyManager = qobject_cast(manager)) { sizePolicyManager->setValue(internProp, qvariant_cast(val)); return; } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { fontManager->setValue(internProp, qvariant_cast(val)); return; #ifndef QT_NO_CURSOR } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { cursorManager->setValue(internProp, qvariant_cast(val)); return; #endif } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { flagManager->setValue(internProp, qvariant_cast(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, qvariant_cast(value)); else if (attribute == d_ptr->m_minimumAttribute) intManager->setMinimum(internProp, qvariant_cast(value)); else if (attribute == d_ptr->m_singleStepAttribute) intManager->setSingleStep(internProp, qvariant_cast(value)); else if (attribute == d_ptr->m_readOnlyAttribute) intManager->setReadOnly(internProp, qvariant_cast(value)); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) doubleManager->setMaximum(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_minimumAttribute) doubleManager->setMinimum(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_singleStepAttribute) doubleManager->setSingleStep(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_decimalsAttribute) doubleManager->setDecimals(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_readOnlyAttribute) doubleManager->setReadOnly(internProp, qvariant_cast(value)); return; } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { if (attribute == d_ptr->m_textVisibleAttribute) boolManager->setTextVisible(internProp, qvariant_cast(value)); return; } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { if (attribute == d_ptr->m_regExpAttribute) stringManager->setRegExp(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_echoModeAttribute) stringManager->setEchoMode(internProp, (EchoMode)qvariant_cast(value)); if (attribute == d_ptr->m_readOnlyAttribute) stringManager->setReadOnly(internProp, (EchoMode)qvariant_cast(value)); return; } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) dateManager->setMaximum(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_minimumAttribute) dateManager->setMinimum(internProp, qvariant_cast(value)); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_decimalsAttribute) pointFManager->setDecimals(internProp, qvariant_cast(value)); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) sizeManager->setMaximum(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_minimumAttribute) sizeManager->setMinimum(internProp, qvariant_cast(value)); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) sizeFManager->setMaximum(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_minimumAttribute) sizeFManager->setMinimum(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_decimalsAttribute) sizeFManager->setDecimals(internProp, qvariant_cast(value)); return; } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { if (attribute == d_ptr->m_constraintAttribute) rectManager->setConstraint(internProp, qvariant_cast(value)); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_constraintAttribute) rectFManager->setConstraint(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_decimalsAttribute) rectFManager->setDecimals(internProp, qvariant_cast(value)); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { if (attribute == d_ptr->m_enumNamesAttribute) enumManager->setEnumNames(internProp, qvariant_cast(value)); if (attribute == d_ptr->m_enumIconsAttribute) enumManager->setEnumIcons(internProp, qvariant_cast(value)); return; } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { if (attribute == d_ptr->m_flagNamesAttribute) flagManager->setFlagNames(internProp, qvariant_cast(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 = manager->findChildren(); QListIterator itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next()); QList doublePropertyManagers = manager->findChildren(); QListIterator itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next()); QList boolPropertyManagers = manager->findChildren(); QListIterator itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next()); QList stringPropertyManagers = manager->findChildren(); QListIterator itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->addPropertyManager(itString.next()); QList datePropertyManagers = manager->findChildren(); QListIterator itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->addPropertyManager(itDate.next()); QList timePropertyManagers = manager->findChildren(); QListIterator itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->addPropertyManager(itTime.next()); QList dateTimePropertyManagers = manager->findChildren(); QListIterator itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next()); QList keySequencePropertyManagers = manager->findChildren(); QListIterator itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next()); QList charPropertyManagers = manager->findChildren(); QListIterator itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->addPropertyManager(itChar.next()); QList localePropertyManagers = manager->findChildren(); QListIterator itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itLocale.next()->subEnumPropertyManager()); QList pointPropertyManagers = manager->findChildren(); QListIterator itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager()); QList pointFPropertyManagers = manager->findChildren(); QListIterator itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager()); QList sizePropertyManagers = manager->findChildren(); QListIterator itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager()); QList sizeFPropertyManagers = manager->findChildren(); QListIterator itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager()); QList rectPropertyManagers = manager->findChildren(); QListIterator itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager()); QList rectFPropertyManagers = manager->findChildren(); QListIterator itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager()); QList colorPropertyManagers = manager->findChildren(); 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 = manager->findChildren(); QListIterator itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next()); QList sizePolicyPropertyManagers = manager->findChildren(); 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 = manager->findChildren(); 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 = manager->findChildren(); QListIterator itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next()); QList flagPropertyManagers = manager->findChildren(); 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 = manager->findChildren(); QListIterator itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next()); QList doublePropertyManagers = manager->findChildren(); QListIterator itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next()); QList boolPropertyManagers = manager->findChildren(); QListIterator itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next()); QList stringPropertyManagers = manager->findChildren(); QListIterator itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->removePropertyManager(itString.next()); QList datePropertyManagers = manager->findChildren(); QListIterator itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->removePropertyManager(itDate.next()); QList timePropertyManagers = manager->findChildren(); QListIterator itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->removePropertyManager(itTime.next()); QList dateTimePropertyManagers = manager->findChildren(); QListIterator itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next()); QList keySequencePropertyManagers = manager->findChildren(); QListIterator itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next()); QList charPropertyManagers = manager->findChildren(); QListIterator itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->removePropertyManager(itChar.next()); QList localePropertyManagers = manager->findChildren(); QListIterator itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itLocale.next()->subEnumPropertyManager()); QList pointPropertyManagers = manager->findChildren(); QListIterator itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager()); QList pointFPropertyManagers = manager->findChildren(); QListIterator itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager()); QList sizePropertyManagers = manager->findChildren(); QListIterator itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager()); QList sizeFPropertyManagers = manager->findChildren(); QListIterator itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager()); QList rectPropertyManagers = manager->findChildren(); QListIterator itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager()); QList rectFPropertyManagers = manager->findChildren(); QListIterator itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager()); QList colorPropertyManagers = manager->findChildren(); 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 = manager->findChildren(); QListIterator itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next()); QList sizePolicyPropertyManagers = manager->findChildren(); 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 = manager->findChildren(); 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 = manager->findChildren(); QListIterator itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next()); QList flagPropertyManagers = manager->findChildren(); QListIterator itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager()); } QT_END_NAMESPACE #include "moc_qtvariantproperty.cpp" qvge-0.6.3/src/3rdParty/qtpropertybrowser/qtvariantproperty.h000066400000000000000000000200551405165517400246170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTVARIANTPROPERTY_H #define QTVARIANTPROPERTY_H #include "qtpropertybrowser.h" #include #include QT_BEGIN_NAMESPACE typedef QMap QtIconMap; class QtVariantPropertyManager; class QtVariantPropertyPrivate; class 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 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 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) }; QT_END_NAMESPACE Q_DECLARE_METATYPE(QIcon) Q_DECLARE_METATYPE(QtIconMap) #endif qvge-0.6.3/src/app.pri000066400000000000000000000016441405165517400145620ustar00rootroot00000000000000# This file is a part of # QVGE - Qt Visual Graph Editor # # (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) # # It can be used freely, maintaining the information above. # includes & libs INCLUDEPATH += $$PWD $$PWD/3rdParty/qtpropertybrowser $$PWD/3rdParty/qsint-widgets CONFIG(debug, debug|release){ DESTDIR = $$OUT_PWD/../bin.debug LIBS += -L$$OUT_PWD/../lib.debug } else{ DESTDIR = $$OUT_PWD/../bin LIBS += -L$$OUT_PWD/../lib } # workaround for #126 CONFIG += no_lflags_merge LIBS += -lcommonui -lqvgeioui -lcommonui -lqvge -lqvgeio -lqtpropertybrowser -lqsint-widgets USE_OGDF{ LIBS += -L$$OGDF_LIB_PATH -l$$OGDF_LIB_NAME INCLUDEPATH += $$OGDF_INCLUDE_PATH } USE_BOOST{ LIBS += -L$$BOOST_LIB_PATH -l$$BOOST_LIB_NAME INCLUDEPATH += $$BOOST_INCLUDE_PATH } win32{ LIBS += -lopengl32 -lglu32 -lshell32 -luser32 -lpsapi } unix{ !if(haiku|mac){ QT += x11extras LIBS += -lX11 } } qvge-0.6.3/src/appbase/000077500000000000000000000000001405165517400146745ustar00rootroot00000000000000qvge-0.6.3/src/appbase/CMainWindow.cpp000066400000000000000000000552131405165517400175650ustar00rootroot00000000000000#include "CMainWindow.h" #include "CPlatformServices.h" #include "CStartPage.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CMainWindow::CMainWindow(QWidget *parent) : QMainWindow(parent), m_isChanged(false) { qint64 pid = qApp->applicationPid(); m_stringPID = QString::number(pid); qApp->setOrganizationName("home"); qApp->setApplicationName("application"); setAcceptDrops(true); connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(onQuit())); } CMainWindow::~CMainWindow() { } void CMainWindow::onQuit() { removeInstance(); } void CMainWindow::exit() { // close all instances QVariantMap pidFileMap = getActiveInstances(); for (auto it = pidFileMap.constBegin(); it != pidFileMap.constEnd(); ++it) { bool isCurrent = (m_stringPID == it.key()); if (!isCurrent) { QVariantMap dataMap = it.value().value(); CPlatformServices::CloseWindow(dataMap["hwnd"].toUInt()); } } // close me as well close(); } void CMainWindow::addDocument(const CDocument& doc) { if (doc.canCreate) { m_docTypeCreate << doc.type; } m_docTypes[doc.type] = doc; } QDockWidget* CMainWindow::createDockWindow(const QString& name, const QString& title, Qt::DockWidgetArea area, QWidget* widget) { QDockWidget *docker = new QDockWidget(title); docker->setObjectName(name); addDockWidget(area, docker); if (area == Qt::NoDockWidgetArea) docker->setFloating(true); docker->setWidget(widget); return docker; } // protected void CMainWindow::init(const QStringList& args) { createMainMenu(); createFileToolbar(); createWindowsMenu(); createHelpMenu(); readSettings(); createStartPage(); processParams(args); } void CMainWindow::closeEvent(QCloseEvent *event) { if (saveOnExit()) { writeSettings(); event->accept(); } else { event->ignore(); } } void CMainWindow::dragEnterEvent(QDragEnterEvent* event) { event->acceptProposedAction(); } void CMainWindow::dragMoveEvent(QDragMoveEvent* event) { event->acceptProposedAction(); } void CMainWindow::dragLeaveEvent(QDragLeaveEvent* event) { event->accept(); } void CMainWindow::dropEvent(QDropEvent* event) { const QMimeData* mimeData = event->mimeData(); // check for our needed mime type, here a file or a list of files if (mimeData->hasUrls()) { QList urlList = mimeData->urls(); // extract the local paths of the files for (int i = 0; i < urlList.size() && i < 32; ++i) { QString filePath = urlList.at(i).toLocalFile(); if (!filePath.isEmpty()) doOpenDocument(filePath); } } } void CMainWindow::processParams(const QStringList& args) { if (args.count() >= 3) { QString command(args.at(1)); if (command == "create") { createNewDocument(args.at(2).toLocal8Bit()); return; } if (command == "open") { doOpenDocument(args.at(2)); return; } } // associated file? if (args.count() == 2) { doOpenDocument(args.at(1)); return; } onCurrentFileChanged(); } void CMainWindow::createMainMenu() { m_fileMenu = menuBar()->addMenu(tr("&File")); m_newDocument = m_fileMenu->addAction(QIcon(":/Icons/New"), tr("&New")); m_newDocument->setStatusTip(tr("Create new document")); fillNewFileMenu(); m_openDocument = m_fileMenu->addAction(QIcon(":/Icons/Open"), tr("&Open..."), this, SLOT(on_actionOpen_triggered())); m_openDocument->setStatusTip(tr("Open a document")); m_openDocument->setShortcut(QKeySequence::Open); m_saveDocument = m_fileMenu->addAction(QIcon(":/Icons/Save"), tr("&Save"), this, SLOT(on_actionSave_triggered())); m_saveDocument->setStatusTip(tr("Save current document")); m_saveDocument->setShortcut(QKeySequence::Save); m_saveAsDocument = m_fileMenu->addAction(tr("Save &As..."), this, SLOT(on_actionSaveAs_triggered())); m_saveAsDocument->setStatusTip(tr("Save current document under another name")); m_saveAsDocument->setShortcut(QKeySequence::SaveAs); m_exportDocument = m_fileMenu->addAction(QIcon(":/Icons/Export"), tr("&Export...")); m_exportDocument->setStatusTip(tr("Export current document into another format")); m_exportDocument->setVisible(false); m_fileMenu->addSeparator(); m_recentFilesMenu = m_fileMenu->addMenu(tr("Recent Files")); connect(m_recentFilesMenu, SIGNAL(aboutToShow()), this, SLOT(fillRecentFilesMenu())); connect(m_recentFilesMenu, SIGNAL(triggered(QAction*)), this, SLOT(onRecentFilesMenuAction(QAction*))); m_fileMenu->addSeparator(); QAction *closeDocument = m_fileMenu->addAction(tr("Close"), this, SLOT(close())); closeDocument->setStatusTip(tr("Close current document")); closeDocument->setShortcut(QKeySequence::Close); QAction *exitApp = m_fileMenu->addAction(tr("E&xit"), this, SLOT(exit())); exitApp->setStatusTip(tr("Leave the application closing all windows")); exitApp->setShortcut(QKeySequence::Quit); } void CMainWindow::fillNewFileMenu() { if (m_docTypeCreate.isEmpty()) return; if (m_docTypeCreate.count() == 1) { const CDocument& doc = m_docTypes[*m_docTypeCreate.begin()]; m_newDocument->setText(tr("New")); m_newDocument->setToolTip(tr("New") + " " + doc.name); m_newDocument->setStatusTip(doc.description); m_newDocument->setShortcut(QKeySequence::New); connect(m_newDocument, SIGNAL(triggered()), this, SLOT(createNewDocument())); m_newDocument->setEnabled(true); } else { QMenu *newActionsMenu = new QMenu(); m_newDocument->setMenu(newActionsMenu); for (const QByteArray& docType : m_docTypeCreate) { const CDocument& doc = m_docTypes[docType]; QAction *newAction = newActionsMenu->addAction(doc.name); newAction->setData(docType); newAction->setStatusTip(doc.description); } newActionsMenu->setDefaultAction(newActionsMenu->actions().first()); connect(m_newDocument, SIGNAL(triggered()), newActionsMenu->defaultAction(), SIGNAL(triggered())); connect(newActionsMenu, SIGNAL(triggered(QAction*)), this, SLOT(createNewDocument(QAction*))); m_newDocument->setEnabled(true); } } void CMainWindow::createFileToolbar() { QToolBar *fileToolbar = addToolBar(tr("File")); fileToolbar->setObjectName("fileToolbar"); fileToolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); fileToolbar->addAction(m_newDocument); fileToolbar->addAction(m_openDocument); fileToolbar->addAction(m_saveDocument); } void CMainWindow::createStartPage() { CStartPage *startPage = new CStartPage(this); setCentralWidget(startPage); } void CMainWindow::updateTitle() { setWindowTitle(QString("%1 - %2") .arg(m_mainTitleText, QApplication::applicationDisplayName()) ); } void CMainWindow::updateActions() { m_saveDocument->setEnabled(m_currentDocType.size()); m_saveAsDocument->setEnabled(m_currentDocType.size()); } void CMainWindow::onDocumentChanged() { // already changed - do nothing if (m_isChanged) return; m_isChanged = true; onCurrentFileChanged(); } void CMainWindow::onCurrentFileChanged() { m_mainTitleText = m_currentFileName; if (m_currentFileName.isEmpty()) m_mainTitleText = tr("New File"); if (m_isChanged) m_mainTitleText = "* " + m_mainTitleText; updateTitle(); updateActions(); updateInstance(); updateRecentFiles(); } // actions void CMainWindow::createNewDocument() { createNewDocument(*m_docTypeCreate.begin()); } void CMainWindow::createNewDocument(QAction *act) { QByteArray docType = act->data().toByteArray(); createNewDocument(docType); } void CMainWindow::createNewDocument(const QByteArray &docType) { // document presents - run new instance if (m_currentDocType.size()) { QStringList args; args << "create" << docType; QProcess::startDetached(QCoreApplication::applicationFilePath(), args); return; } // no document - create in place if (createDocument(docType)) { // restore settings for this instance readSettings(); m_currentDocType = docType; onNewDocumentCreated(docType); m_isChanged = false; onCurrentFileChanged(); return; } // failed qDebug() << "Cannot create document."; } bool CMainWindow::createDocument(const QByteArray &docType) { qDebug() << docType; return true; } void CMainWindow::selectAndOpenDocument() { on_actionOpen_triggered(); } bool CMainWindow::openDocument(const QString &fileName) { return doOpenDocument(fileName); } void CMainWindow::on_actionOpen_triggered() { QString title = tr("Open File"); QString filter = tr("Any File (*.*)"); onOpenDocumentDialog(title, filter); QString loadName = m_currentFileName; if (loadName.isEmpty()) loadName = m_lastPath; if (loadName.isEmpty()) loadName = QDir::homePath(); QString fileName = QFileDialog::getOpenFileName(NULL, title, loadName, filter, &m_lastOpenFilter); if (fileName.isEmpty()) return; doOpenDocument(fileName); } bool CMainWindow::getDocFormatFromName(const QString &normalizedName, const CDocument **doc, const CDocumentFormat **fmt, QString *suffix) { const QString ext = QFileInfo(normalizedName).suffix().toLower(); for (const auto &docType : m_docTypes) { for (int i = 0; i < docType.formats.size(); ++i) { const auto &format = docType.formats.at(i); if (format.suffixes.contains(ext)) { if (doc) *doc = &docType; if (fmt) *fmt = &format; if (suffix) *suffix = ext; return true; } } } // invalid format return false; } bool CMainWindow::doOpenDocument(const QString &fileName) { QString normalizedName = QDir::toNativeSeparators(QFileInfo(fileName).canonicalFilePath()); // file does not exist if (!QFile::exists(normalizedName)) { statusBar()->showMessage(tr("Failed to open: %1").arg(fileName)); QMessageBox::critical(NULL, fileName, tr("Document file does not exist or not accessible.") ); return false; } // check if the document already opened in another instance if (activateInstance(normalizedName)) return true; // document presents - run new instance if (m_currentDocType.size()) { // store current settings to be read by the new instance writeSettings(); QStringList args; args << "open" << normalizedName; QProcess::startDetached(QCoreApplication::applicationFilePath(), args); return true; } // guess document type (TO REVISE!) const CDocument *fdoc; const CDocumentFormat *fformat; QString fsuffix; bool found = getDocFormatFromName(normalizedName, &fdoc, &fformat, &fsuffix); QByteArray fileDocType; if (found) { fileDocType = fdoc->type; } // open in place (fileDocType can be changed by this fn!) if (openDocument(normalizedName, fileDocType)) { // restore settings for this instance readSettings(); m_currentFileName = normalizedName; m_currentDocType = fileDocType; m_isChanged = false; m_lastPath = QFileInfo(m_currentFileName).absolutePath(); statusBar()->showMessage(tr("Opened successfully: %1").arg(fileName)); onCurrentFileChanged(); return true; } // failure statusBar()->showMessage(tr("Failed to open: %1").arg(fileName)); QMessageBox::critical(NULL, fileName, tr("Document cannot be opened. Check access rights and path.")); return false; } void CMainWindow::onOpenDocumentDialog(QString &title, QString &filter) { filter = ""; QString allFilters; for (const CDocument& doc : m_docTypes) { for (const auto& format : doc.formats) { if (format.canRead) { filter += format.name + " (" + format.filters + ") ;;"; allFilters += format.filters + " "; } } } if (allFilters.size()) { allFilters.chop(1); allFilters = tr("Any supported format (%1)").arg(allFilters); filter += allFilters; if (m_lastOpenFilter.isEmpty()) m_lastOpenFilter = allFilters; } } void CMainWindow::on_actionSave_triggered() { save(); } void CMainWindow::on_actionSaveAs_triggered() { saveAs(); } bool CMainWindow::save() { if (m_currentFileName.isEmpty()) return saveAs(); return doSaveDocument(m_currentFileName, "", m_currentDocType); } static QString cutLastSuffix(const QString& fileName) { int idx = fileName.lastIndexOf("."); if (idx < 0) return fileName; else return fileName.left(idx); } bool CMainWindow::saveAs() { if (m_currentDocType.isEmpty()) return true; QString filter; QMap filterToSuffix; const CDocument& doc = m_docTypes[m_currentDocType]; for (const CDocumentFormat& format : doc.formats) { if (format.canSave) { QString formatFilter = format.name + " (" + format.filters + ")"; filter += formatFilter + ";;"; filterToSuffix[formatFilter] = format.suffixes.first(); } } if (filter.size()) filter.chop(2); QString title = tr("Save File"); onSaveDocumentDialog(title, filter); QString saveName = cutLastSuffix(m_currentFileName); if (saveName.isEmpty()) saveName = m_lastPath; if (saveName.isEmpty()) saveName = QDir::homePath(); QString selectedFilter = m_lastSaveFilter; QString fileName = QFileDialog::getSaveFileName(NULL, title, saveName, filter, &selectedFilter); if (fileName.isEmpty()) return false; // workaround: auto append suffix (QTBUG!) QString selectedSuffix = QFileInfo(fileName).suffix().toLower(); if (selectedSuffix.isEmpty() && filterToSuffix.contains(selectedFilter)) fileName += "." + filterToSuffix[selectedFilter]; QString normalizedName = QDir::toNativeSeparators(fileName); return doSaveDocument(normalizedName, selectedFilter, m_currentDocType); } bool CMainWindow::doSaveDocument(const QString &fileName, const QString &selectedFilter, const QByteArray &docType) { if (saveDocument(fileName, selectedFilter, docType)) { m_currentFileName = fileName; m_isChanged = false; m_lastSaveFilter = selectedFilter; m_lastPath = QFileInfo(m_currentFileName).absolutePath(); statusBar()->showMessage(tr("Document saved successfully.")); onCurrentFileChanged(); return true; } else { QMessageBox::critical(NULL, tr("Save Error"), tr("Document cannot be saved. Check access rights and path.")); } return false; } bool CMainWindow::saveOnExit() { if (!m_isChanged) return true; const QMessageBox::StandardButton ret = QMessageBox::warning( this, m_currentFileName, tr("The document has been modified.\n" "Do you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); switch (ret) { case QMessageBox::Save: return save(); case QMessageBox::Cancel: return false; default: break; } return true; } // recent files management QStringList CMainWindow::getRecentFilesList() const { QSettings &settings = getApplicationSettings(); return settings.value("recentFiles").toStringList(); } void CMainWindow::cleanRecentFilesList() { QSettings &settings = getApplicationSettings(); settings.remove("recentFiles"); } bool CMainWindow::removeRecentDocument(const QString &name) { QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); int cnt = recentFiles.removeAll(name); if (cnt) { settings.setValue("recentFiles", recentFiles); return true; } return false; } void CMainWindow::updateRecentFiles() { if (m_currentFileName.isEmpty()) return; QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); int index = recentFiles.indexOf(m_currentFileName); if (index == 0) return; if (index > 0) { recentFiles.move(index, 0); } else { recentFiles.prepend(m_currentFileName); // to parameterize if (recentFiles.size() > 20) recentFiles.removeLast(); } settings.setValue("recentFiles", recentFiles); } void CMainWindow::fillRecentFilesMenu() { m_recentFilesMenu->clear(); QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); for (int i = 0; i < recentFiles.size(); ++i) { QAction *recentAction = m_recentFilesMenu->addAction(recentFiles.at(i)); recentAction->setData(i); } } void CMainWindow::onRecentFilesMenuAction(QAction *recentAction) { QString filePath = recentAction->text(); if (doOpenDocument(filePath)) return; // failed - remove QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); recentFiles.removeAt(recentAction->data().toInt()); settings.setValue("recentFiles", recentFiles); } // instance management QVariantMap CMainWindow::getActiveInstances() { QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); QVariantMap pidFileMap = settings.value("instances").value(); CPlatformServices::PIDs livingPids = CPlatformServices::GetRunningPIDs(); bool mapUpdated = false; // check if alive QList spids = pidFileMap.keys(); for (auto spid : spids) { if (!livingPids.contains(spid.toUInt())) { pidFileMap.remove(spid); mapUpdated = true; } } // write cleaned map back if (mapUpdated) { settings.setValue("instances", pidFileMap); } return pidFileMap; } void CMainWindow::updateInstance() { QSettings &settings = getApplicationSettings(); QVariantMap pidFileMap = settings.value("instances").value(); QVariantMap dataMap = pidFileMap[m_stringPID].value(); dataMap["title"] = m_mainTitleText; dataMap["file"] = m_currentFileName; dataMap["hwnd"] = (uint)effectiveWinId(); dataMap["spid"] = m_stringPID; pidFileMap[m_stringPID] = dataMap; settings.setValue("instances", pidFileMap); } void CMainWindow::removeInstance() { QSettings &settings = getApplicationSettings(); QVariantMap pidFileMap = settings.value("instances").value(); pidFileMap.remove(m_stringPID); settings.setValue("instances", pidFileMap); } bool CMainWindow::activateInstance(const QString &fileName) { QString normalizedName = fileName; // QDir::toNativeSeparators(QFileInfo(fileName).canonicalFilePath()); #ifdef WIN32 normalizedName = normalizedName.toLower(); #endif // current instance? if (normalizedName == m_currentFileName) { raise(); activateWindow(); return true; } // else check running instances QVariantMap pidFileMap = getActiveInstances(); for (auto it = pidFileMap.constBegin(); it != pidFileMap.constEnd(); ++it) { QVariantMap dataMap = it.value().value(); QString fileName = dataMap["file"].toString(); #ifdef WIN32 fileName = fileName.toLower(); #endif if (normalizedName == fileName) { // found: switch to instance CPlatformServices::SetActiveWindow(dataMap["hwnd"].toUInt()); return true; } } return false; } void CMainWindow::createWindowsMenu() { m_windowsMenu = new QMenu(tr("&Window")); m_windowsMenuAction = menuBar()->addMenu(m_windowsMenu); connect(m_windowsMenu, SIGNAL(aboutToShow()), this, SLOT(fillWindowsMenu())); connect(m_windowsMenu, SIGNAL(triggered(QAction*)), this, SLOT(onWindowsMenuAction(QAction*))); } void CMainWindow::fillWindowsMenu() { QVariantMap pidFileMap = getActiveInstances(); m_windowsMenu->clear(); char hotKey = '1'; for (auto it = pidFileMap.constBegin(); it != pidFileMap.constEnd(); ++it) { QVariantMap dataMap = it.value().value(); QString fileTitle = dataMap["title"].toString(); QString text = QString("&%1 %2").arg(hotKey++).arg(fileTitle); QAction *windowAction = m_windowsMenu->addAction(text); windowAction->setCheckable(true); windowAction->setChecked(m_stringPID == it.key()); windowAction->setData(dataMap); } } void CMainWindow::onWindowsMenuAction(QAction *windowAction) { QVariantMap dataMap = windowAction->data().value(); QString spid = dataMap["spid"].toString(); if (spid.isEmpty() || spid == m_stringPID) return; CPlatformServices::SetActiveWindow(dataMap["hwnd"].toUInt()); } // help void CMainWindow::createHelpMenu() { m_helpMenu = new QMenu(tr("&Help")); menuBar()->addMenu(m_helpMenu); m_helpMenu->addAction(tr("About &Qt..."), qApp, SLOT(aboutQt())); m_helpMenu->addAction(tr("&About..."), this, SLOT(onAboutApplication())); } void CMainWindow::onAboutApplication() { QMessageBox::about(this, tr("About %1").arg(qApp->applicationDisplayName()), getAboutText()); } QString CMainWindow::getAboutText() const { return QString("%1
Version %2") .arg(qApp->applicationName()) .arg(qApp->applicationVersion()); } // settings QSettings& CMainWindow::getApplicationSettings() const { //static QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); //return settings; static QSettings* settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); return *settings; } void CMainWindow::readSettings() { QSettings& settings = getApplicationSettings(); settings.sync(); doReadSettings(settings); } void CMainWindow::doReadSettings(QSettings& settings) { showNormal(); // window geometry const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray(); if (geometry.isEmpty()) { const QRect availableGeometry = QApplication::desktop()->availableGeometry(this); resize(availableGeometry.width()-200, availableGeometry.height()-100); move(100, 50); } else { restoreGeometry(geometry); } // toolbars & dock widgets QApplication::processEvents(); const QByteArray state = settings.value("windowState").toByteArray(); if (!state.isEmpty()) restoreState(state); // window state if (settings.value("maximized", true).toBool()) { //#ifdef Q_OS_WIN32 showMaximized(); //#else // showNormal(); // QTimer::singleShot(0, this, SLOT(showMaximized())); //#endif } else showNormal(); // path m_lastPath = settings.value("lastPath").toString(); } void CMainWindow::writeSettings() { QSettings& settings = getApplicationSettings(); doWriteSettings(settings); settings.sync(); } void CMainWindow::doWriteSettings(QSettings& settings) { settings.setValue("windowState", saveState()); settings.setValue("geometry", saveGeometry()); settings.setValue("maximized", isMaximized()); settings.setValue("lastPath", m_lastPath); } qvge-0.6.3/src/appbase/CMainWindow.h000066400000000000000000000110551405165517400172260ustar00rootroot00000000000000#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include #include #include struct CDocumentFormat { QString name; // textual description i.e "Images" QString filters; // filters in form like: "*.png *.xpm *.jpg" QStringList suffixes; // supported suffixes like: png xpm jpg (first one assumed to be default) bool canSave, canRead; }; struct CDocument { QString name; QString description; QByteArray type; bool canCreate; QList formats; }; class CMainWindow : public QMainWindow { Q_OBJECT public: explicit CMainWindow(QWidget *parent = nullptr); virtual ~CMainWindow(); virtual void init(const QStringList& args); QDockWidget* createDockWindow(const QString& name, const QString& title, Qt::DockWidgetArea area, QWidget* widget = nullptr); virtual QSettings& getApplicationSettings() const; virtual void readSettings(); virtual void writeSettings(); void addDocument(const CDocument& doc); QList getRegisteredDocumentTypes() const { return m_docTypes.values(); } QStringList getRecentFilesList() const; void cleanRecentFilesList(); bool removeRecentDocument(const QString& name); QMenu* getFileMenu() { return m_fileMenu; } QMenu* getHelpMenu() { return m_helpMenu; } QAction* getFileExportAction() { return m_exportDocument; } QAction* getWindowMenuAction() { return m_windowsMenuAction; } QString getCurrentFileName() const { return m_currentFileName; } public Q_SLOTS: virtual void onDocumentChanged(); virtual void onAboutApplication(); virtual void createNewDocument(const QByteArray &docType); void selectAndOpenDocument(); bool openDocument(const QString &fileName); protected: void closeEvent(QCloseEvent *event); void dragEnterEvent(QDragEnterEvent* event); void dragMoveEvent(QDragMoveEvent* event); void dragLeaveEvent(QDragLeaveEvent* event); void dropEvent(QDropEvent* event); virtual void processParams(const QStringList& args); virtual void createMainMenu(); virtual void createWindowsMenu(); virtual void createHelpMenu(); virtual void createStartPage(); virtual void fillNewFileMenu(); virtual void createFileToolbar(); virtual void updateActions(); virtual void updateRecentFiles(); virtual void onCurrentFileChanged(); virtual void updateTitle(); virtual QString getAboutText() const; virtual bool createDocument(const QByteArray &docType); virtual void onNewDocumentCreated(const QByteArray &docType) {} virtual void onOpenDocumentDialog(QString &title, QString &filter); virtual bool doOpenDocument(const QString &fileName); virtual bool openDocument(const QString &fileName, QByteArray &docType) { return false; } virtual bool getDocFormatFromName(const QString &normalizedName, const CDocument **doc, const CDocumentFormat **format, QString *suffix); virtual void onSaveDocumentDialog(QString &title, QString &filter) {} virtual bool doSaveDocument(const QString &fileName, const QString &selectedFilter, const QByteArray &docType); virtual bool saveDocument(const QString &fileName, const QString &selectedFilter, const QByteArray &docType) { return true; } virtual bool saveOnExit(); virtual bool save(); virtual bool saveAs(); virtual bool activateInstance(const QString &fileName); virtual void updateInstance(); virtual void removeInstance(); virtual QVariantMap getActiveInstances(); virtual void doReadSettings(QSettings& settings); virtual void doWriteSettings(QSettings& settings); protected Q_SLOTS: void createNewDocument(); void createNewDocument(QAction*); void on_actionOpen_triggered(); void on_actionSave_triggered(); void on_actionSaveAs_triggered(); void fillRecentFilesMenu(); void onRecentFilesMenuAction(QAction*); void fillWindowsMenu(); void onWindowsMenuAction(QAction*); private Q_SLOTS: void exit(); void onQuit(); protected: QMenu *m_fileMenu; QMenu *m_newMenu; QMenu *m_recentFilesMenu; QMenu *m_helpMenu; QAction *m_newDocument; QAction *m_openDocument; QAction *m_saveDocument; QAction *m_saveAsDocument; QAction *m_exportDocument; QMenu *m_windowsMenu; QAction *m_windowsMenuAction; QString m_currentFileName; QString m_lastPath; QByteArray m_currentDocType; bool m_isChanged; QString m_mainTitleText; QString m_stringPID; QString m_lastOpenFilter, m_lastSaveFilter; QMap m_docTypes; QList m_docTypeCreate; }; #endif // MAINWINDOW_H qvge-0.6.3/src/appbase/CPlatformServices.cpp000066400000000000000000000104321405165517400207730ustar00rootroot00000000000000#include "CPlatformServices.h" int CPlatformServices::GetPlatformBits() { // Check windows #if _WIN32 || _WIN64 #if _WIN64 #define SYSTEM64 return 64; #else #define SYSTEM32 return 32; #endif #endif // Check GCC #if __GNUC__ #if __x86_64__ || __ppc64__ #define SYSTEM64 return 64; #else #define SYSTEM32 return 32; #endif #endif // not detected return 0; } #if defined (Q_OS_WIN32) && !defined(Q_OS_CYGWIN) #include #include bool CPlatformServices::SetActiveWindow(uint id) { HWND hWnd = (HWND)id; if (!hWnd) return false; BringWindowToTop(hWnd); HWND hCurrWnd = GetForegroundWindow(); DWORD myThreadID = GetCurrentThreadId(); DWORD currThreadID = GetWindowThreadProcessId(hCurrWnd, NULL); AttachThreadInput(myThreadID, currThreadID, TRUE); SetForegroundWindow(hWnd); SetFocus(hWnd); AttachThreadInput(myThreadID, currThreadID, FALSE); if (IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE); else ShowWindow(hWnd, SW_SHOW); return true; } bool CPlatformServices::CloseWindow(uint id) { HWND hWnd = (HWND)id; if (!hWnd) return false; int result = SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0); return true; } CPlatformServices::PIDs CPlatformServices::GetRunningPIDs() { PIDs result; DWORD pids[10240]; DWORD bytesReturned; if (EnumProcesses(pids, 10240 * sizeof(DWORD), &bytesReturned)) { int count = bytesReturned / sizeof(DWORD); for (int i = 0; i < count; ++i) { result << pids[i]; } } return result; } quint64 CPlatformServices::GetTotalRAMBytes() { MEMORYSTATUSEX memory_status; ZeroMemory(&memory_status, sizeof(MEMORYSTATUSEX)); memory_status.dwLength = sizeof(MEMORYSTATUSEX); if (GlobalMemoryStatusEx(&memory_status)) { return memory_status.ullTotalPhys; } else return 0; } #endif // windows #if (defined(Q_OS_LINUX) || defined (Q_OS_UNIX) || defined (Q_OS_CYGWIN)) && (!defined (Q_OS_HAIKU)) && (!defined (Q_OS_DARWIN)) #include #include #include #include #include #ifdef Q_OS_FREEBSD #include #else #include #endif bool CPlatformServices::SetActiveWindow(uint id) { Display *display = QX11Info::display(); XEvent event = { 0 }; event.xclient.type = ClientMessage; event.xclient.serial = 0; event.xclient.send_event = True; event.xclient.message_type = XInternAtom(display, "_NET_ACTIVE_WINDOW", False); event.xclient.window = id; event.xclient.format = 32; XSendEvent( display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &event ); XMapRaised( display, id ); return true; } bool CPlatformServices::CloseWindow(uint id) { Display *display = QX11Info::display(); XEvent event = { 0 }; event.xclient.type = ClientMessage; event.xclient.window = id; event.xclient.message_type = XInternAtom(display, "WM_PROTOCOLS", True); event.xclient.format = 32; event.xclient.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", False); event.xclient.data.l[1] = CurrentTime; XSendEvent(display, id, False, NoEventMask, &event); return true; } CPlatformServices::PIDs CPlatformServices::GetRunningPIDs() { PIDs result; auto procList = QProcessInfo::enumerate(false); for (auto &procInfo: procList) { result << procInfo.pid(); } return result; } quint64 CPlatformServices::GetTotalRAMBytes() { #ifdef Q_OS_FREEBSD int mib[2]; mib[0] = CTL_HW; mib[1] = HW_REALMEM; unsigned int size = 0; /* 32-bit */ size_t len = sizeof( size ); if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) return (size_t)size; else return 0L; #else // linux etc. struct sysinfo info; if (sysinfo(&info) == 0) { return info.totalram; } else return 0; #endif } #endif // linux // haiku #if (defined(Q_OS_HAIKU) || defined(Q_OS_DARWIN)) quint64 CPlatformServices::GetTotalRAMBytes() { return 0; } CPlatformServices::PIDs CPlatformServices::GetRunningPIDs() { PIDs result; return result; } bool CPlatformServices::CloseWindow(uint id) { return true; } bool CPlatformServices::SetActiveWindow(uint id) { return true; } #endif // haiku qvge-0.6.3/src/appbase/CPlatformServices.h000066400000000000000000000007021405165517400204370ustar00rootroot00000000000000#pragma once #include #include class CPlatformServices { public: static bool SetActiveWindow(uint id); static bool CloseWindow(uint id); typedef QSet PIDs; static PIDs GetRunningPIDs(); static int GetPlatformBits(); // 32 or 64 ... or more static quint64 GetTotalRAMBytes(); // total RAM in bytes, 0 if failed }; #if defined (Q_OS_WIN32) && !defined(Q_OS_CYGWIN) #include "CPlatformWin32.h" #endif qvge-0.6.3/src/appbase/CPlatformWin32.cpp000066400000000000000000000116521405165517400201170ustar00rootroot00000000000000// - /** * @file * @brief * @author Gerolf Reinwardt * @date 30. march 2011 * * Copyright 2011, Gerolf Reinwardt. All rights reserved. * * Simplified BSD License * * 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 ``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 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. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of Gerolf Reinwardt. */ // - #include "CPlatformWin32.h" #include #include #include #include #include void CPlatformWin32::registerFileType(const QString& documentId, const QString& fileTypeName, const QString& fileExtension, qint32 appIconIndex, DdeCommands commands) { // first register the type ID of our server if (!SetHkcrUserRegKey(documentId, fileTypeName)) return; QString exePath = QFileInfo(qApp->applicationFilePath()).absoluteFilePath(); QString nativePath = QDir::toNativeSeparators(exePath); if (!SetHkcrUserRegKey(QString("%1\\DefaultIcon").arg(documentId), QString("\"%1\",%2").arg(nativePath).arg(appIconIndex))) return; if (commands & DDEOpen) registerCommand("Open", documentId, "\"%1\"", "[open(\"%1\")]"); if (commands & DDENew) registerCommand("New", documentId, "-new \"%1\"", "[new(\"%1\")]"); if (commands & DDEPrint) registerCommand("Print", documentId, "-print \"%1\"", "[print(\"%1\")]"); LONG lSize = _MAX_PATH * 2; wchar_t szTempBuffer[_MAX_PATH * 2]; LONG lResult = ::RegQueryValue(HKEY_CLASSES_ROOT, (const wchar_t*)fileExtension.utf16(), szTempBuffer, &lSize); QString temp = QString::fromUtf16((unsigned short*)szTempBuffer); if (lResult != ERROR_SUCCESS || temp.isEmpty() || temp == documentId) { // no association for that suffix if (!SetHkcrUserRegKey(fileExtension, documentId)) return; SetHkcrUserRegKey(QString("%1\\Shell\\New").arg(fileExtension), QLatin1String(""), QLatin1String("NullFile")); } } void CPlatformWin32::registerCommand(const QString& command, const QString& documentId, const QString cmdLineArg, const QString ddeCommand) { QString exePath = QFileInfo(qApp->applicationFilePath()).absoluteFilePath(); QString commandLine = QDir::toNativeSeparators(exePath); commandLine.prepend(QLatin1String("\"")); commandLine.append(QLatin1String("\"")); if (!cmdLineArg.isEmpty()) { commandLine.append(QChar(' ')); commandLine.append(cmdLineArg); } if (!SetHkcrUserRegKey(QString("%1\\Shell\\%2\\Command").arg(documentId).arg(command), commandLine)) return; // just skip it if (!SetHkcrUserRegKey(QString("%1\\Shell\\%2\\ddeexec").arg(documentId).arg(command), ddeCommand)) return; } bool CPlatformWin32::SetHkcrUserRegKey(QString key, const QString& value, const QString& valueName) { HKEY hKey; key.prepend(QString::fromUtf8("Software\\Classes\\")); LONG lRetVal = RegCreateKeyW(HKEY_CURRENT_USER, (const wchar_t*)key.utf16(), &hKey); if (ERROR_SUCCESS == lRetVal) { LONG lResult = ::RegSetValueExW(hKey, valueName.isEmpty() ? 0 : (const wchar_t*)valueName.utf16(), 0, REG_SZ, (CONST BYTE*)value.utf16(), (value.length() + 1) * sizeof(wchar_t)); if ((::RegCloseKey(hKey) == ERROR_SUCCESS) && (lResult == ERROR_SUCCESS)) { return true; } QMessageBox::warning(0, QString::fromUtf8("Error in setting Registry values"), QString::fromUtf8("registration database update failed for key '%s'.").arg(key)); } else { wchar_t buffer[4096]; ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, lRetVal, 0, buffer, 4096, 0); QString szText = QString::fromUtf16((const ushort*)buffer); QMessageBox::warning(0, QString::fromUtf8("Error in setting Registry values"), szText); } return false; } qvge-0.6.3/src/appbase/CPlatformWin32.h000066400000000000000000000014001405165517400175520ustar00rootroot00000000000000#pragma once #include class CPlatformWin32 { public: enum DdeCommand { DDEOpen = 0x0001, /* open a file via explorer*/ DDENew = 0x0002, /* create a new file via explorer*/ DDEPrint = 0x0004, /* print a file via explorer*/ }; Q_DECLARE_FLAGS(DdeCommands, DdeCommand) static void registerFileType(const QString& documentId, const QString& fileTypeName, const QString& fileExtension, qint32 appIconIndex = 0, DdeCommands commands = DDEOpen); static void registerCommand(const QString& command, const QString& documentId, const QString cmdLineArg = QString::null, const QString ddeCommand = QString::null); private: static bool SetHkcrUserRegKey(QString key, const QString& value, const QString& valueName = QString::null); }; qvge-0.6.3/src/appbase/CStartPage.cpp000066400000000000000000000105571405165517400174050ustar00rootroot00000000000000#include "CStartPage.h" #include "CMainWindow.h" #include #include #include #include #include CStartPage::CStartPage(CMainWindow *parent) : QWidget(parent) { ui.setupUi(this); m_parent = parent; createActions(); createRecentDocs(); } CStartPage::~CStartPage() { } void CStartPage::createActions() { const auto &docTypes = m_parent->getRegisteredDocumentTypes(); // create document actions for (auto &doc : docTypes) { if (doc.canCreate) { QCommandLinkButton *newFileButton = new QCommandLinkButton( tr("Create") + " " + doc.name, doc.description, this ); newFileButton->setIcon(QIcon(":/Icons/New")); newFileButton->setMinimumHeight(64); QAction *newFile = new QAction(newFileButton); newFile->setData(doc.type); connect(newFileButton, &QCommandLinkButton::clicked, newFile, &QAction::triggered); connect(newFile, &QAction::triggered, this, &CStartPage::onCreateDocument); ui.LeftWidget->layout()->addWidget(newFileButton); } } // spacer ui.LeftWidget->layout()->addItem(new QSpacerItem(1, 50)); // open document actions QCommandLinkButton *openFileButton = new QCommandLinkButton( tr("Open..."), tr("Open existing document(s)"), this ); openFileButton->setIcon(QIcon(":/Icons/Open")); openFileButton->setMinimumHeight(64); connect(openFileButton, &QCommandLinkButton::clicked, m_parent, &CMainWindow::selectAndOpenDocument); ui.LeftWidget->layout()->addWidget(openFileButton); } void CStartPage::onCreateDocument() { QAction *act = dynamic_cast(sender()); if (act) m_parent->createNewDocument(act->data().toByteArray()); } void CStartPage::createRecentDocs() { const auto &recentList = m_parent->getRecentFilesList(); int i = 0; ui.CleanRecentButton->setVisible(recentList.size()); for (const QString &fileName : recentList) { QWidget *host = new QWidget(this); host->setLayout(new QHBoxLayout); QFileInfo fi(fileName); QToolButton *deleteButton = new QToolButton(host); deleteButton->setAutoRaise(true); deleteButton->setIcon(QIcon(":/Icons/Delete")); deleteButton->setToolTip(tr("Remove this file from the list")); QAction *deleteAction = new QAction(fileName, deleteButton); deleteAction->setData(i); connect(deleteButton, &QCommandLinkButton::clicked, deleteAction, &QAction::triggered); connect(deleteAction, &QAction::triggered, this, &CStartPage::onRemoveDocument); QCommandLinkButton *fileButton = new QCommandLinkButton( fi.baseName(), fi.lastModified().toString() + " | " + fileName, host ); fileButton->setMinimumHeight(64); QAction *recentAction = new QAction(fileName, fileButton); recentAction->setData(i); connect(fileButton, &QCommandLinkButton::clicked, recentAction, &QAction::triggered); connect(recentAction, &QAction::triggered, this, &CStartPage::onRecentDocument); host->layout()->addWidget(fileButton); host->layout()->addWidget(deleteButton); ui.RightWidget->layout()->addWidget(host); m_buttons[i++] = host; } // spacer QWidget *temp = new QWidget(this); temp->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); ui.RightWidget->layout()->addWidget(temp); } void CStartPage::onRecentDocument() { QAction *act = dynamic_cast(sender()); if (act) m_parent->openDocument(act->text()); } void CStartPage::onRemoveDocument() { QAction *act = dynamic_cast(sender()); if (act) { int r = QMessageBox::question(this, tr("Remove Document"), tr("Are you sure to remove the document from the list?\n\n(File itself will not be removed!)"), QMessageBox::Yes, QMessageBox::Cancel); if (r == QMessageBox::Cancel) return; if (m_parent->removeRecentDocument(act->text())) { int i = act->data().toInt(); QWidget *w = m_buttons[i]; if (w) { delete w; m_buttons.remove(i); ui.CleanRecentButton->setVisible(m_buttons.size()); } } } } void CStartPage::on_CleanRecentButton_clicked() { int r = QMessageBox::question(this, tr("Clean Recent Documents"), tr("Are you sure to clean the recent documents list?\n\n(Files will not be removed!)"), QMessageBox::Yes, QMessageBox::Cancel); if (r == QMessageBox::Yes) { m_parent->cleanRecentFilesList(); for (QWidget *w : m_buttons) { ui.RightWidget->layout()->removeWidget(w); } m_buttons.clear(); ui.CleanRecentButton->hide(); } } qvge-0.6.3/src/appbase/CStartPage.h000066400000000000000000000010131405165517400170350ustar00rootroot00000000000000#pragma once #include #include #include "ui_CStartPage.h" class CMainWindow; class CStartPage : public QWidget { Q_OBJECT public: CStartPage(CMainWindow *parent); ~CStartPage(); protected: void createActions(); void createRecentDocs(); protected Q_SLOTS: void onCreateDocument(); void onRecentDocument(); void onRemoveDocument(); private Q_SLOTS: void on_CleanRecentButton_clicked(); private: Ui::CStartPage ui; CMainWindow *m_parent = nullptr; QMap m_buttons; }; qvge-0.6.3/src/appbase/CStartPage.ui000066400000000000000000000130511405165517400172300ustar00rootroot00000000000000 CStartPage 0 0 658 424 Start Page 0 100 0 0 0 0 Qt::Vertical 20 40 Qt::Vertical Segoe UI 12 Recently Opened Documents 10 true Clear the list Clean... :/Icons/Delete:/Icons/Delete Qt::ToolButtonTextBesideIcon true Qt::Vertical QSizePolicy::Fixed 20 20 Qt::LeftToRight QFrame::NoFrame QAbstractScrollArea::AdjustToContents true 0 0 310 348 0 0 0 0 0 100 QLayout::SetDefaultConstraint 0 0 0 0 qvge-0.6.3/src/appbase/Icons/000077500000000000000000000000001405165517400157475ustar00rootroot00000000000000qvge-0.6.3/src/appbase/Icons/action-delete.png000066400000000000000000000016311405165517400211730ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATHMhe3Cg6"Mn4?.Wݙ+)^T#\o;Ziq!č .\ . Qif{$ޙf=f/1c"r l4KKKnNgcc㤪MX$HQRǍ1 %7 ydfDڂ׍Kr:r]z*T%9iDQtg!@^_c=dc`0'IzXO'%X@nEWJD\\kS^HZN%/I{>4 F_gLk `s*@DL$zcO+`0ZNܗJ%uݝ|,$ۺ#țNm!d5ZLɋL׌1nZT* $1\SJ ڮ9hY.3c^pPMh1k Ec@rO=kYIENDB`qvge-0.6.3/src/appbase/Icons/document-new.png000066400000000000000000000011651405165517400210650ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH픿kSQ?%:HN߅-ݲ,{8.]ڭ8t@Q{KS^g;\MZ/y `D9>>\jw |]h4w4Tx8zƘwY=nTEUk7v}m9rcrl$ɧz^89V_OJUe1枪.R}܈,|TՇb_.(zQn#"v,WU? ã jιמLm")JN:g I-k&>0 7͑A9U\1 ?hZ:&3M 5 3#DDvgu5IENDB`qvge-0.6.3/src/appbase/Icons/document-open.png000066400000000000000000000007671405165517400212440ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q.IDATH1N@E8N@ (pmS,rzn@BOMJl bCHB4hBmdYv( TdHD@wgN@j("Y VznmTEѬx,洵]p84,9h4:X??@7op$2 ʲlOsi-S|>),U9ؠtEĪ<߂ zDU-EdpUKBJD2O}HRjlJIENDB`qvge-0.6.3/src/appbase/Icons/document-print.png000066400000000000000000000005611405165517400214270ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH 0 E_Q؄*q5<+I%&J}8'JlLZGf}sf)qP; p)N r#wnPX}0a&@ cj^<믺eo]UMpj\^nyIENDB`qvge-0.6.3/src/appbase/Icons/document-save.png000066400000000000000000000012101405165517400212210ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH=SAs& w-E2Bn&(DJ\X`aeDwjEː967|l'z33s现bx;"}B2OW\4fy_U7 m6 D1~RQq\|z윫|4ι(9VZr!R Iesv:?!){y{9ntݳgc|l+ !mUX)YxAe7UC$[@bw<z^Q^|9@ᝈDU{{{jp]DV`];Je8(\\u!Sc.0;~& ~"`>:r#"-]0{1Ɨy?gY%"<Uzp~ԥIENDB`qvge-0.6.3/src/appbase/appbase.pri000066400000000000000000000011541405165517400170240ustar00rootroot00000000000000SOURCES += $$PWD/CPlatformServices.cpp $$PWD/CMainWindow.cpp $$PWD/CStartPage.cpp HEADERS += $$PWD/CPlatformServices.h $$PWD/CMainWindow.h $$PWD/CStartPage.h FORMS += $$files($$PWD/*.ui) RESOURCES += $$files($$PWD/*.qrc) unix{ !if(haiku|mac){ QT += x11extras LIBS += -lX11 } !haiku { SOURCES += $$PWD/../3rdParty/qprocessinfo/qprocessinfo.cpp HEADERS += $$PWD/../3rdParty/qprocessinfo/qprocessinfo.h INCLUDEPATH += $$PWD/../3rdParty/qprocessinfo } } win32{ SOURCES += $$PWD/CPlatformWin32.cpp HEADERS += $$PWD/CPlatformWin32.h } qvge-0.6.3/src/appbase/appbase.qrc000066400000000000000000000006041405165517400170160ustar00rootroot00000000000000 Icons/action-delete.png Icons/document-new.png Icons/document-open.png Icons/document-print.png Icons/document-save.png Icons/document-export.png qvge-0.6.3/src/commonui/000077500000000000000000000000001405165517400151075ustar00rootroot00000000000000qvge-0.6.3/src/commonui/CAttributesEditorUI.cpp000066400000000000000000000146571405165517400214660ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CAttributesEditorUI.h" #include "ui_CAttributesEditorUI.h" #include "CNewAttributeDialog.h" #include #include #include CAttributesEditorUI::CAttributesEditorUI(QWidget *parent) : QWidget(parent), ui(new Ui::CAttributesEditorUI) { ui->setupUi(this); ui->Editor->setFactoryForManager(&m_manager, &m_factory); connect(&m_manager, SIGNAL(valueChanged(QtProperty*, const QVariant&)), this, SLOT(onValueChanged(QtProperty*, const QVariant&))); } CAttributesEditorUI::~CAttributesEditorUI() { // important to avoid crash ui->Editor->disconnect(this); disconnect(this); delete ui; } CPropertyEditorUIBase* CAttributesEditorUI::getEditor() { return ui->Editor; } int CAttributesEditorUI::setupFromItems(CEditorScene& scene, QList &items) { QString oldName = ui->Editor->getCurrentTopPropertyName(); // order of clear() is important! ui->Editor->setUpdatesEnabled(false); ui->Editor->clear(); m_manager.blockSignals(true); m_manager.clear(); m_scene = &scene; m_items = items; struct AttrData { QVariant data; int dataType = -1; bool isSet = false; }; QSet ids; QMap attrs; // merge ids for (auto item : items) { auto localAttrs = item->getLocalAttributes(); ids = ids.unite(localAttrs.keys().toSet()); } // merge attrs for (auto id : ids) { for (auto item : items) { if (item->hasLocalAttribute(id)) { auto itemValue = item->getAttribute(id); // trick: float -> double if (itemValue.type() == QMetaType::Float) attrs[id].dataType = QMetaType::Double; else attrs[id].dataType = itemValue.type(); if (attrs[id].isSet && attrs[id].data != itemValue) { attrs[id].data = QVariant(); break; } else { attrs[id].data = itemValue; attrs[id].isSet = true; } } else { attrs[id].data = QVariant(); attrs[id].isSet = true; } } } int topCount = 0; for (auto it = attrs.constBegin(); it != attrs.constEnd(); ++it) { auto prop = m_manager.addProperty(it.value().dataType, it.key()); Q_ASSERT(prop != NULL); // add as string if unknown if (!prop) prop = m_manager.addProperty(QMetaType::QString, it.key()); if (!prop) continue; // ignore // add 13 commas if double if (it.value().dataType == QMetaType::Double) prop->setAttribute("decimals", 13); prop->setValue(it.value().data); ui->Editor->updateTooltip(prop); auto item = ui->Editor->addProperty(prop); ui->Editor->setExpanded(item, false); if (!it.value().data.isValid()) prop->setModified(true); topCount++; } ui->Editor->setUpdatesEnabled(true); m_manager.blockSignals(false); // restore selection if (oldName.size()) ui->Editor->selectItemByName(oldName); // force update on_Editor_currentItemChanged(ui->Editor->currentItem()); return topCount; } void CAttributesEditorUI::on_AddButton_clicked() { if (!m_scene || m_items.isEmpty()) return; CNewAttributeDialog dialog; if (dialog.exec() == QDialog::Rejected) return; auto id = dialog.getId(); if (id.isEmpty()) return; auto v = dialog.getValue(); bool used = false; for (auto sceneItem : m_items) { if (sceneItem->hasLocalAttribute(id)) continue; sceneItem->setAttribute(id, v); used = true; } if (!used) return; // store state m_scene->addUndoState(); // rebuild tree setupFromItems(*m_scene, m_items); // select item ui->Editor->selectItemByName(id); ui->Editor->setFocus(); } void CAttributesEditorUI::on_ChangeButton_clicked() { if (!m_scene || m_items.isEmpty()) return; QByteArray attrId = ui->Editor->getCurrentTopPropertyName().toLatin1(); if (attrId.isEmpty()) return; int attrType = ui->Editor->getCurrentTopPropertyValueType(); if (attrType < 0) return; QVariant attrValue = ui->Editor->getCurrentTopPropertyValue(); CNewAttributeDialog dialog; dialog.setWindowTitle(tr("Change Attribute")); dialog.setId(attrId); dialog.setType(attrType); if (dialog.exec() == QDialog::Rejected) return; QByteArray newId = dialog.getId(); if (newId.isEmpty()) return; int newType = dialog.getType(); if (newType == attrType && newId == attrId) return; // check for name duplicate //... if (newType != attrType) { if (attrValue.canConvert(newType)) attrValue.convert(newType); else attrValue = QVariant((QVariant::Type)newType); // we will loose the value but not type } for (auto sceneItem : m_items) { //if (!sceneItem->hasLocalAttribute(attrId)) // continue; // remove old one and add new sceneItem->removeAttribute(attrId); sceneItem->setAttribute(newId, attrValue); } // store state m_scene->addUndoState(); // update ui->Editor->selectItemByName(newId); ui->Editor->setFocus(); } void CAttributesEditorUI::on_RemoveButton_clicked() { if (!m_scene || m_items.isEmpty()) return; auto prop = ui->Editor->getCurrentTopProperty(); if (!prop) return; QByteArray attrId = prop->propertyName().toLatin1(); if (attrId.isEmpty()) return; int r = QMessageBox::question(NULL, tr("Remove Attribute"), tr("Remove attribute %1 from selected item(s)?").arg(QString(attrId)), QMessageBox::Yes, QMessageBox::Cancel); if (r == QMessageBox::Cancel) return; delete prop; bool used = false; for (auto sceneItem : m_items) { bool ok = sceneItem->removeAttribute(attrId); if (ok) sceneItem->getSceneItem()->update(); used |= ok; } if (!used) return; // store state m_scene->addUndoState(); ui->Editor->setFocus(); } void CAttributesEditorUI::on_Editor_currentItemChanged(QtBrowserItem* item) { ui->RemoveButton->setEnabled(item != NULL); ui->ChangeButton->setEnabled(item != NULL); } void CAttributesEditorUI::onValueChanged(QtProperty *property, const QVariant &val) { ui->Editor->updateTooltip(dynamic_cast(property)); if (!m_scene || m_items.isEmpty()) return; // no subprops if (!ui->Editor->topLevelItem(property)) return; auto attrId = property->propertyName().toLatin1(); for (auto sceneItem : m_items) { sceneItem->setAttribute(attrId, val); } // store state m_scene->addUndoState(); } qvge-0.6.3/src/commonui/CAttributesEditorUI.h000066400000000000000000000021761405165517400211240ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CATTRIBUTESEDITORUI_H #define CATTRIBUTESEDITORUI_H #include #include #include #include class CEditorScene; class CItem; class CPropertyEditorUIBase; namespace Ui { class CAttributesEditorUI; } class CAttributesEditorUI : public QWidget { Q_OBJECT public: explicit CAttributesEditorUI(QWidget *parent = 0); ~CAttributesEditorUI(); int setupFromItems(CEditorScene& scene, QList& items); CPropertyEditorUIBase* getEditor(); private Q_SLOTS: void on_AddButton_clicked(); void on_ChangeButton_clicked(); void on_RemoveButton_clicked(); void on_Editor_currentItemChanged(QtBrowserItem*); void onValueChanged(QtProperty *property, const QVariant &val); private: Ui::CAttributesEditorUI *ui; CEditorScene *m_scene; QList m_items; QtVariantPropertyManager m_manager; QtVariantEditorFactory m_factory; }; #endif // CATTRIBUTESEDITORUI_H qvge-0.6.3/src/commonui/CAttributesEditorUI.ui000066400000000000000000000047251405165517400213140ustar00rootroot00000000000000 CAttributesEditorUI 0 0 400 300 Custom Attributes 0 0 0 0 Qt::Horizontal 40 20 Add new custom attribute for the selected items Add... Change selected attribute's id and type Change... Remove the attribute from the selected items Remove... CPropertyEditorUIBase QTreeWidget
CPropertyEditorUIBase.h
Editor AddButton ChangeButton RemoveButton
qvge-0.6.3/src/commonui/CClassAttributesEditorUI.cpp000066400000000000000000000225131405165517400224420ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CClassAttributesEditorUI.h" #include "CNewAttributeDialog.h" #include #include #include #include CClassAttributesEditorUI::CClassAttributesEditorUI(QWidget *parent) : QWidget(parent), ui(new Ui::CClassAttributesEditorUI), m_scene(NULL), m_locked(false) { ui->setupUi(this); ui->Editor->setFactoryForManager(&m_manager, &m_factory); connect(&m_manager, SIGNAL(valueChanged(QtProperty*, const QVariant&)), this, SLOT(onValueChanged(QtProperty*, const QVariant&))); connect(ui->NodeButton, SIGNAL(clicked()), this, SLOT(rebuild())); connect(ui->EdgeButton, SIGNAL(clicked()), this, SLOT(rebuild())); connect(ui->GraphButton, SIGNAL(clicked()), this, SLOT(rebuild())); } CClassAttributesEditorUI::~CClassAttributesEditorUI() { // important to avoid crash ui->Editor->disconnect(this); disconnect(this); delete ui; } void CClassAttributesEditorUI::doReadSettings(QSettings& settings) { int pos = settings.value("splitterPosition", -1).toInt(); if (pos >= 0) ui->Editor->setSplitterPosition(pos); } void CClassAttributesEditorUI::doWriteSettings(QSettings& settings) { settings.setValue("splitterPosition", ui->Editor->splitterPosition()); } void CClassAttributesEditorUI::setScene(CEditorScene* scene) { if (m_scene) onSceneDetached(m_scene); m_scene = scene; setEnabled(m_scene); if (m_scene) onSceneAttached(m_scene); } void CClassAttributesEditorUI::connectSignals(CEditorScene* scene) { connect(scene, SIGNAL(sceneChanged()), this, SLOT(onSceneChanged())); } void CClassAttributesEditorUI::onSceneAttached(CEditorScene* scene) { connectSignals(scene); onSceneChanged(); } void CClassAttributesEditorUI::onSceneDetached(CEditorScene* scene) { scene->disconnect(this); } void CClassAttributesEditorUI::onSceneChanged() { rebuild(); } // //void CClassAttributesEditorUI::on_ClassId_currentIndexChanged(int) //{ // rebuild(); //} void CClassAttributesEditorUI::onValueChanged(QtProperty *property, const QVariant &val) { ui->Editor->updateTooltip(dynamic_cast(property)); if (!m_scene || m_locked) return; // reject changes from subproperties if (ui->Editor->topLevelItem(property) == nullptr) return; m_locked = true; QByteArray classId = getClassId(); auto attrId = property->propertyName().toLatin1(); bool isSet = false; // check for constrains auto conn = m_scene->getClassAttributeConstrains(classId, attrId); if (conn) { if (auto connList = dynamic_cast(conn)) { int index = val.toInt(); if (index >= 0 && index < connList->ids.size()) m_scene->setClassAttribute(classId, attrId, connList->ids[index]); else m_scene->setClassAttribute(classId, attrId, connList->ids.first()); isSet = true; } else if (auto enumList = dynamic_cast(conn)) { int index = val.toInt(); if (index >= 0 && index < enumList->ids.size()) m_scene->setClassAttribute(classId, attrId, (QVariant) enumList->ids[index]); else m_scene->setClassAttribute(classId, attrId, (QVariant) enumList->ids.first()); isSet = true; } } // default if (!isSet) m_scene->setClassAttribute(classId, attrId, val); // store state m_scene->addUndoState(); m_locked = false; } void CClassAttributesEditorUI::on_Editor_currentItemChanged(QtBrowserItem* item) { if (item) { // only custom attrs can be removed or changed ui->RemoveButton->setEnabled(item->property()->isModified()); ui->ChangeButton->setEnabled(item->property()->isModified()); } else { ui->RemoveButton->setEnabled(false); ui->ChangeButton->setEnabled(false); } } void CClassAttributesEditorUI::on_AddButton_clicked() { if (!m_scene) return; CNewAttributeDialog dialog; if (dialog.exec() == QDialog::Rejected) return; auto id = dialog.getId(); if (id.isEmpty()) return; QByteArray classId = getClassId(); if (m_scene->getClassAttributes(classId, false).contains(id)) { QMessageBox::critical(this, tr("Attribute exists"), tr("Class %1 already has attribute %2. Please pick another id.") .arg(QString(classId), QString(id)), QMessageBox::Ok); return; } auto v = dialog.getValue(); CAttribute attr(id, id, v); m_scene->setClassAttribute(classId, attr); // store state m_scene->addUndoState(); // update ui->Editor->selectItemByName(id); ui->Editor->setFocus(); } void CClassAttributesEditorUI::on_ChangeButton_clicked() { if (!m_scene) return; QByteArray attrId = ui->Editor->getCurrentTopPropertyName().toLatin1(); //if (attrId.isEmpty()) // return; QByteArray classId = getClassId(); auto attr = m_scene->getClassAttribute(classId, attrId, false); CNewAttributeDialog dialog; dialog.setWindowTitle(tr("Change Attribute")); dialog.setId(attrId); dialog.setType(attr.valueType); if (dialog.exec() == QDialog::Rejected) return; QByteArray newId = dialog.getId(); if (newId.isEmpty()) return; int newType = dialog.getType(); if (newType == attr.valueType && newId == attrId) return; // check for name duplicate if (newId != attrId && m_scene->getClassAttributes(classId, false).contains(newId)) { QMessageBox::critical(this, tr("Attribute exists"), tr("Class %1 already has attribute %2. Please pick another id.") .arg(QString(classId), QString(newId)), QMessageBox::Ok); return; } // remove old one and add new CAttribute newAttr(attr); newAttr.id = newId; newAttr.name = newId; newAttr.valueType = newType; m_scene->removeClassAttribute(classId, attrId); m_scene->setClassAttribute(classId, newAttr); // store state m_scene->addUndoState(); // update ui->Editor->selectItemByName(newId); ui->Editor->setFocus(); } void CClassAttributesEditorUI::on_RemoveButton_clicked() { if (!m_scene) return; auto prop = ui->Editor->getCurrentTopProperty(); if (!prop) return; QByteArray attrId = prop->propertyName().toLatin1(); QByteArray classId = getClassId(); int r = QMessageBox::question(NULL, tr("Remove Attribute"), tr("Remove attribute %1 from class %2?").arg(QString(attrId), QString(classId)), QMessageBox::Yes, QMessageBox::Cancel); if (r == QMessageBox::Cancel) return; // remove prop m_locked = true; delete prop; m_scene->removeClassAttribute(classId, attrId); // store state m_scene->addUndoState(); m_locked = false; ui->Editor->setFocus(); } // internal stuff void CClassAttributesEditorUI::rebuild() { if (!m_scene || m_locked) return; QString oldName = ui->Editor->getCurrentTopPropertyName(); on_Editor_currentItemChanged(NULL); ui->Editor->setUpdatesEnabled(false); ui->Editor->clear(); m_manager.blockSignals(true); m_manager.clear(); QByteArray classId = getClassId(); auto attrs = m_scene->getClassAttributes(classId, true); for (auto it = attrs.constBegin(); it != attrs.constEnd(); ++it) { // skip not default if (it.value().flags & ATTR_NODEFAULT) continue; QtVariantProperty* prop = NULL; // check for constrains auto conn = m_scene->getClassAttributeConstrains(classId, it.key()); if (conn) { if (auto connList = dynamic_cast(conn)) { prop = m_manager.addProperty(QtVariantPropertyManager::enumTypeId(), it.key()); prop->setAttribute(QLatin1String("enumNames"), connList->names); QVariant v; qVariantSetValue(v, connList->iconsAsMap()); prop->setAttribute(QLatin1String("enumIcons"), v); int index = connList->ids.indexOf(it.value().defaultValue.toString()); prop->setValue(index); } else if (auto enumList = dynamic_cast(conn)) { prop = m_manager.addProperty(QtVariantPropertyManager::enumTypeId(), it.key()); prop->setAttribute(QLatin1String("enumNames"), enumList->names); QVariant v; qVariantSetValue(v, enumList->iconsAsMap()); prop->setAttribute(QLatin1String("enumIcons"), v); int index = enumList->ids.indexOf(it.value().defaultValue.toInt()); prop->setValue(index); } } // else custom property if (!prop) { int type = it.value().valueType; if (type == QMetaType::Float) type = QMetaType::Double; prop = m_manager.addProperty(type, it.key()); Q_ASSERT(prop != NULL); if (!prop) continue; // ignore // add 13 commas if double if (type == QMetaType::Double) prop->setAttribute("decimals", 13); prop->setValue(it.value().defaultValue); } ui->Editor->updateTooltip(prop); auto item = ui->Editor->addProperty(prop); ui->Editor->setExpanded(item, false); if (it.value().isUserDefined()) prop->setModified(true); if (ui->Editor->currentItem() == NULL) ui->Editor->setCurrentItem(item); } ui->Editor->setUpdatesEnabled(true); m_manager.blockSignals(false); // restore selection if (oldName.size()) ui->Editor->selectItemByName(oldName); } QByteArray CClassAttributesEditorUI::getClassId() const { if (ui->NodeButton->isChecked()) return QByteArrayLiteral("node"); else if (ui->EdgeButton->isChecked()) return QByteArrayLiteral("edge"); else return QByteArrayLiteral(""); } qvge-0.6.3/src/commonui/CClassAttributesEditorUI.h000066400000000000000000000025671405165517400221160ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include #include #include "ui_CClassAttributesEditorUI.h" class CEditorScene; class CItem; class CClassAttributesEditorUI : public QWidget { Q_OBJECT public: explicit CClassAttributesEditorUI(QWidget *parent = 0); ~CClassAttributesEditorUI(); void setScene(CEditorScene* scene); void doReadSettings(QSettings& settings); void doWriteSettings(QSettings& settings); protected: void connectSignals(CEditorScene* scene); void onSceneAttached(CEditorScene* scene); void onSceneDetached(CEditorScene* scene); QByteArray getClassId() const; protected Q_SLOTS: void onSceneChanged(); //void on_ClassId_currentIndexChanged(int); void on_Editor_currentItemChanged(QtBrowserItem*); void rebuild(); private Q_SLOTS: void on_AddButton_clicked(); void on_ChangeButton_clicked(); void on_RemoveButton_clicked(); void onValueChanged(QtProperty *property, const QVariant &val); private: Ui::CClassAttributesEditorUI *ui; QtVariantPropertyManager m_manager; QtVariantEditorFactory m_factory; CEditorScene *m_scene; bool m_locked; }; qvge-0.6.3/src/commonui/CClassAttributesEditorUI.ui000066400000000000000000000163601405165517400223000ustar00rootroot00000000000000 CClassAttributesEditorUI 0 0 384 300 Custom Attributes 1 1 1 1 0 Qt::Horizontal QSizePolicy::Expanding 0 0 0 0 60 23 Edit graph attributes Graph :/Icons/Graph:/Icons/Graph 20 20 true true true Qt::ToolButtonTextBesideIcon 0 0 60 23 Edit default node attributes Node :/Icons/Node-Disc:/Icons/Node-Disc 20 20 true true Qt::ToolButtonTextBesideIcon 0 0 60 23 Edit default edge attributes Edge :/Icons/Edge-Undirected:/Icons/Edge-Undirected 20 20 true true Qt::ToolButtonTextBesideIcon Qt::Horizontal QSizePolicy::Expanding 0 0 Qt::Horizontal 40 20 Add new custom attribute for the selected items Add... Change selected attribute's id and type Change... Remove the attribute from the selected items Remove... CPropertyEditorUIBase QTreeWidget
CPropertyEditorUIBase.h
GraphButton NodeButton EdgeButton Editor AddButton ChangeButton RemoveButton
qvge-0.6.3/src/commonui/CColorSchemesUIController.cpp000066400000000000000000000071541405165517400226150ustar00rootroot00000000000000#include "CColorSchemesUIController.h" #include CColorSchemesUIController::CColorSchemesUIController(QObject *parent) : QObject(parent) { { Scheme scheme{ tr("Grayscale") }; scheme.bgColor = Qt::white; scheme.gridColor = Qt::gray; scheme.nodeColor = Qt::lightGray; scheme.nodeStrokeColor = Qt::black; scheme.nodeLabelColor = Qt::black; scheme.edgeColor = Qt::darkGray; scheme.edgeLabelColor = Qt::gray; addScheme(scheme); } { Scheme scheme{ tr("Inverse Grayscale") }; scheme.bgColor = Qt::black; scheme.gridColor = Qt::darkGray; scheme.nodeColor = Qt::darkGray; scheme.nodeStrokeColor = Qt::white; scheme.nodeLabelColor = Qt::white; scheme.edgeColor = Qt::gray; scheme.edgeLabelColor = Qt::lightGray; addScheme(scheme); } { Scheme scheme{ tr("Solarized Light") }; scheme.bgColor = QColor("#fdf6e3"); scheme.gridColor = QColor("#eee8d5"); scheme.nodeColor = QColor("#e0dbcb"); scheme.nodeStrokeColor = QColor("#073642"); scheme.nodeLabelColor = QColor("#657b83"); scheme.edgeColor = QColor("#556058"); scheme.edgeLabelColor = QColor("#808000"); addScheme(scheme); } { Scheme scheme{ tr("Blue && Orange") }; scheme.bgColor = QColor("#ffffff"); scheme.gridColor = QColor("#eeeeee"); scheme.nodeColor = QColor("#55aaff"); scheme.nodeStrokeColor = QColor("#ffffff"); scheme.nodeLabelColor = QColor("#444444"); scheme.edgeColor = QColor("#ffaa00"); scheme.edgeLabelColor = QColor("#55aa7f"); addScheme(scheme); } { Scheme scheme{ tr("Forest") }; scheme.bgColor = QColor("#e3e6bb"); scheme.gridColor = QColor("#eeeeee"); scheme.nodeColor = QColor("#aaff7f"); scheme.nodeStrokeColor = QColor("#8d4600"); scheme.nodeLabelColor = QColor("#343400"); scheme.edgeColor = QColor("#aaaa7f"); scheme.edgeLabelColor = QColor("#55aa00"); addScheme(scheme); } { Scheme scheme{ tr("Sunny Spring") }; scheme.bgColor = QColor("#f3ffe1"); scheme.gridColor = QColor("#eeeeee"); scheme.nodeColor = QColor("#b4ba00"); scheme.nodeStrokeColor = QColor("#b4ba00"); scheme.nodeLabelColor = QColor("#111111"); scheme.edgeColor = QColor("#ba4400"); scheme.edgeLabelColor = QColor("#267536"); addScheme(scheme); } { Scheme scheme{ tr("Night Sky") }; scheme.bgColor = QColor("#000640"); scheme.gridColor = QColor("#070f5a"); scheme.nodeColor = QColor("#000000"); scheme.nodeStrokeColor = QColor("#6f73c0"); scheme.nodeLabelColor = QColor("#dcdcdc"); scheme.edgeColor = QColor("#6f73c0"); scheme.edgeLabelColor = QColor("#aad6ff"); addScheme(scheme); } connect(&m_menu, SIGNAL(triggered(QAction*)), this, SLOT(onMenuTriggered(QAction*))); } void CColorSchemesUIController::onMenuTriggered(QAction *action) { int index = action->data().toInt(); applyScheme(m_schemes.at(index)); } void CColorSchemesUIController::addScheme(const Scheme& scheme) { int index = m_schemes.size(); m_schemes << scheme; auto action = m_menu.addAction(scheme.name); action->setData(index); } void CColorSchemesUIController::applyScheme(const Scheme& scheme) { if (m_scene) { m_scene->setBackgroundBrush(scheme.bgColor); m_scene->setGridPen(scheme.gridColor); m_scene->setClassAttribute("node", "color", scheme.nodeColor); m_scene->setClassAttribute("node", "stroke.color", scheme.nodeStrokeColor); m_scene->setClassAttribute("node", "label.color", scheme.nodeLabelColor); m_scene->setClassAttribute("edge", "color", scheme.edgeColor); m_scene->setClassAttribute("edge", "label.color", scheme.edgeLabelColor); m_scene->addUndoState(); Q_EMIT colorSchemeApplied(m_scene); } } qvge-0.6.3/src/commonui/CColorSchemesUIController.h000066400000000000000000000016141405165517400222550ustar00rootroot00000000000000#ifndef CCOLORSCHEMESUICONTROLLER_H #define CCOLORSCHEMESUICONTROLLER_H #include #include #include class CEditorScene; class CColorSchemesUIController : public QObject { Q_OBJECT public: explicit CColorSchemesUIController(QObject *parent = nullptr); void setScene(CEditorScene* scene) { m_scene = scene; } QMenu* getSchemesMenu() { return &m_menu; } Q_SIGNALS: void colorSchemeApplied(CEditorScene* scene); private Q_SLOTS: void onMenuTriggered(QAction *action); private: QMenu m_menu; CEditorScene *m_scene = NULL; struct Scheme { QString name; QColor bgColor, gridColor; QColor nodeColor, nodeStrokeColor, nodeLabelColor; QColor edgeColor, edgeLabelColor; }; QList m_schemes; void addScheme(const Scheme& scheme); void applyScheme(const Scheme& scheme); }; #endif // CCOLORSCHEMESUICONTROLLER_H qvge-0.6.3/src/commonui/CCommutationTable.cpp000066400000000000000000000213541405165517400211720ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CCommutationTable.h" #include #include #include #include #include #include #include #include // NumSortItem: numeric sorting by ids class NumSortItem : public QTreeWidgetItem { public: bool operator < (const QTreeWidgetItem &other) const { int col = treeWidget()->sortColumn(); bool b1, b2; int i1 = text(col).toInt(&b1); int i2 = other.text(col).toInt(&b2); if (b1 && b2) return i1 < i2; return QTreeWidgetItem::operator < (other); } }; // fixed section Ids enum FixedSectionIds { StartNodeId, EndNodeId, EdgeId, CustomId }; // CCommutationTable CCommutationTable::CCommutationTable(QWidget *parent) : QWidget(parent), m_scene(NULL) { ui.setupUi(this); ui.Table->header()->setSortIndicator(2, Qt::AscendingOrder); ui.Table->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui.Table, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenu(const QPoint &))); ui.Table->header()->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui.Table->header(), SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenu(const QPoint &))); } CCommutationTable::~CCommutationTable() { } void CCommutationTable::doReadSettings(QSettings& settings) { QByteArray extraSections = settings.value("userColumns").toByteArray(); if (!extraSections.isEmpty()) { m_extraSectionIds = extraSections.split(';'); onSceneChanged(); } auto *header = ui.Table->header(); QByteArray headerState = settings.value("headerState").toByteArray(); if (!headerState.isNull()) { header->restoreState(headerState); } } void CCommutationTable::doWriteSettings(QSettings& settings) { auto *header = ui.Table->header(); settings.setValue("headerState", header->saveState()); settings.setValue("userColumns", m_extraSectionIds.join(';')); } void CCommutationTable::setScene(CNodeEditorScene* scene) { ui.Table->clear(); if (m_scene) onSceneDetached(m_scene); m_scene = scene; setEnabled(m_scene); if (m_scene) onSceneAttached(m_scene); } void CCommutationTable::connectSignals(CEditorScene* scene) { connect(scene, SIGNAL(sceneChanged()), this, SLOT(onSceneChanged()), Qt::QueuedConnection); connect(scene, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()), Qt::QueuedConnection); } void CCommutationTable::onSceneAttached(CEditorScene* scene) { connectSignals(scene); onSceneChanged(); } void CCommutationTable::onSceneDetached(CEditorScene* scene) { scene->disconnect(this); } void CCommutationTable::onSceneChanged() { ui.Table->setUpdatesEnabled(false); ui.Table->blockSignals(true); ui.Table->clear(); m_edgeItemMap.clear(); ui.Table->setColumnCount(m_extraSectionIds.size() + CustomId); int extraSectionIndex = CustomId; for (const auto& paramId : m_extraSectionIds) { ui.Table->headerItem()->setText(extraSectionIndex++, paramId); } QList edges = m_scene->getItems(); for (auto edge : edges) { auto item = new NumSortItem(); ui.Table->addTopLevelItem(item); m_edgeItemMap[edge] = item; if (edge->firstPortId().size()) item->setText(StartNodeId, edge->firstNode()->getId() + ":" + edge->firstPortId()); else item->setText(StartNodeId, edge->firstNode()->getId()); if (edge->lastPortId().size()) item->setText(EndNodeId, edge->lastNode()->getId() + ":" + edge->lastPortId()); else item->setText(EndNodeId, edge->lastNode()->getId()); item->setText(EdgeId, edge->getId()); int extraSectionIndex = CustomId; for (const auto& paramId : m_extraSectionIds) { QString val = edge->getAttribute(paramId).toString(); item->setText(extraSectionIndex++, val); } } ui.Table->setUpdatesEnabled(true); ui.Table->blockSignals(false); // update active selections if any onSelectionChanged(); } void CCommutationTable::onSelectionChanged() { ui.Table->setUpdatesEnabled(false); ui.Table->blockSignals(true); ui.Table->clearSelection(); QTreeWidgetItem* scrollItem = NULL; QList edges = m_scene->getSelectedEdges(); //QElapsedTimer tm; //tm.start(); QItemSelection selection; for (auto edge : edges) { if (m_edgeItemMap.contains(edge)) { auto item = m_edgeItemMap[edge]; scrollItem = item; //item->setSelected(true); // version with QModelIndex is many ways faster... int row = ui.Table->indexOfTopLevelItem(item); QModelIndex leftIndex = ui.Table->model()->index(row, 0); QModelIndex rightIndex = ui.Table->model()->index(row, ui.Table->columnCount() - 1); QItemSelection rowSelection(leftIndex, rightIndex); selection.append(rowSelection); //selection.merge(rowSelection, QItemSelectionModel::Select); // slow } } ui.Table->selectionModel()->select(selection, QItemSelectionModel::Select); //qDebug() << "CCommutationTable::onSelectionChanged(): " << tm.elapsed(); if (scrollItem) ui.Table->scrollToItem(scrollItem); ui.Table->setUpdatesEnabled(true); ui.Table->blockSignals(false); } void CCommutationTable::on_Table_itemSelectionChanged() { if (!m_scene) return; ui.Table->blockSignals(true); m_scene->beginSelection(); m_scene->deselectAll(); auto selTableItems = ui.Table->selectedItems(); QSet selIds; for (auto item : selTableItems) { selIds.insert(item->text(2)); } QList edges = m_scene->getItems(); for (auto edge : edges) { if (selIds.contains(edge->getId())) { edge->setSelected(true); edge->ensureVisible(); } } ui.Table->blockSignals(false); m_scene->endSelection(); } void CCommutationTable::on_Table_itemDoubleClicked(QTreeWidgetItem *item, int column) { if (!m_scene || !item) return; if (column < 2) { auto nodes = m_scene->getItemsById(item->text(column)); if (nodes.count()) { m_scene->deselectAll(); nodes.first()->setSelected(true); nodes.first()->ensureVisible(); return; } } if (column == 2) { auto edges = m_scene->getItemsById(item->text(column)); if (edges.count()) { m_scene->deselectAll(); edges.first()->setSelected(true); edges.first()->ensureVisible(); return; } } } void CCommutationTable::onCustomContextMenu(const QPoint& pos) { QMenu contextMenu; int sectionIndex = ui.Table->header()->logicalIndexAt(pos); if (sectionIndex >= CustomId) { QAction* act = contextMenu.addAction( tr("Remove Column [%1]").arg(ui.Table->headerItem()->text(sectionIndex)), this, SLOT(onRemoveSection())); act->setData(sectionIndex - CustomId); contextMenu.addSeparator(); } QAction* act = contextMenu.addAction(tr("Add Column..."), this, SLOT(onAddSection())); act->setData(pos); contextMenu.exec(ui.Table->mapToGlobal(pos)); } void CCommutationTable::on_AddColumnButton_clicked() { onAddSection(); } void CCommutationTable::on_RestoreButton_clicked() { if (!m_extraSectionIds.isEmpty()) { int r = QMessageBox::question(NULL, tr("Restore Default Columns"), tr("Are you sure to reset all the custom columns?")); if (r == QMessageBox::Yes) { m_extraSectionIds.clear(); onSceneChanged(); } else return; } for (int i = 0; i < ui.Table->header()->count(); ++i) ui.Table->header()->moveSection(ui.Table->header()->visualIndex(i), i); ui.Table->header()->setSortIndicator(2, Qt::AscendingOrder); } void CCommutationTable::onAddSection() { QByteArrayList paramIdsList = m_scene->getClassAttributes("edge", true).keys(); QStringList paramIds; for (const auto& id : paramIdsList) if (!m_extraSectionIds.contains(id)) paramIds << id; QInputDialog dialog; dialog.setComboBoxItems(paramIds); dialog.setComboBoxEditable(true); dialog.setWindowTitle(tr("Add Column")); dialog.setLabelText(tr("Enter edge attribute ID:")); dialog.setInputMode(QInputDialog::TextInput); if (dialog.exec() != QDialog::Accepted) return; QByteArray paramId = dialog.textValue().toLocal8Bit(); if (paramId.size() && !m_extraSectionIds.contains(paramId)) { int sectionIndex = ui.Table->header()->count() - 1; QAction* act = dynamic_cast(sender()); if (act) { QPoint pos = act->data().toPoint(); sectionIndex = ui.Table->header()->logicalIndexAt(pos); } int listIndex = sectionIndex - CustomId; m_extraSectionIds.insert(listIndex+1, paramId); onSceneChanged(); if (ui.Table->horizontalScrollBar()) { int x = ui.Table->header()->sectionPosition(sectionIndex+1); ui.Table->horizontalScrollBar()->setSliderPosition(x); } } } void CCommutationTable::onRemoveSection() { QAction* act = (QAction*)sender(); int listIndex = act->data().toInt(); m_extraSectionIds.removeAt(listIndex); onSceneChanged(); } qvge-0.6.3/src/commonui/CCommutationTable.h000066400000000000000000000024731405165517400206400ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CCommutationTable_H #define CCommutationTable_H #include #include #include #include class CEditorScene; class CNodeEditorScene; struct CAttribute; class CEdge; #include "ui_CCommutationTable.h" class CCommutationTable : public QWidget { Q_OBJECT public: CCommutationTable(QWidget *parent = 0); ~CCommutationTable(); void setScene(CNodeEditorScene* scene); void doReadSettings(QSettings& settings); void doWriteSettings(QSettings& settings); protected: void connectSignals(CEditorScene* scene); void onSceneAttached(CEditorScene* scene); void onSceneDetached(CEditorScene* scene); protected Q_SLOTS: void onSceneChanged(); void onSelectionChanged(); void on_Table_itemSelectionChanged(); void on_Table_itemDoubleClicked(QTreeWidgetItem *item, int column); void onCustomContextMenu(const QPoint &); void onAddSection(); void onRemoveSection(); void on_AddColumnButton_clicked(); void on_RestoreButton_clicked(); private: Ui::CCommutationTable ui; CNodeEditorScene *m_scene; QMap m_edgeItemMap; QByteArrayList m_extraSectionIds; }; #endif // CCommutationTable_H qvge-0.6.3/src/commonui/CCommutationTable.ui000066400000000000000000000055371405165517400210320ustar00rootroot00000000000000 CCommutationTable 0 0 400 300 Form 0 0 0 0 QAbstractItemView::NoEditTriggers true QAbstractItemView::ExtendedSelection true true true true Start Node End Node Edge Qt::Horizontal 134 20 Append new edge attribute column | Right-click on a column's header - insert/delete a column at exact position New Column... Restore default columns (remove custom ones) Restore Defaults... qvge-0.6.3/src/commonui/CExtListInputDialog.cpp000066400000000000000000000040321405165517400214510ustar00rootroot00000000000000#include "CExtListInputDialog.h" #include "ui_CExtListInputDialog.h" #include CExtListInputDialog::CExtListInputDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CExtListInputDialog) { ui->setupUi(this); ui->comboBox->view()->setAlternatingRowColors(true); ui->comboBox->setStyleSheet("QAbstractItemView::item { height: 32px;}"); ui->comboBox->setIconSize(QSize(24, 24)); } CExtListInputDialog::~CExtListInputDialog() { delete ui; } int CExtListInputDialog::getItemIndex(const QString& title, const QString& label, const QStringList &texts, const QList& icons, int selectedIndex) { static CExtListInputDialog* dialog = new CExtListInputDialog(nullptr); dialog->setWindowTitle(title); dialog->ui->label->setText(label); dialog->ui->comboBox->clear(); dialog->ui->comboBox->addItems(texts); while (dialog->ui->comboBox->count() < icons.size()) { dialog->ui->comboBox->addItem(""); } for (int i = 0; i < icons.size(); i++) { dialog->ui->comboBox->setItemIcon(i, icons.at(i)); } dialog->ui->comboBox->setCurrentIndex(selectedIndex); if (dialog->exec() == QDialog::Rejected) return -1; return dialog->ui->comboBox->currentIndex(); } int CExtListInputDialog::getItemIndex(const QString& title, const QString& label, const QStringList &texts, int selectedIndex) { static CExtListInputDialog* dialog = new CExtListInputDialog(nullptr); dialog->setWindowTitle(title); dialog->ui->label->setText(label); dialog->ui->comboBox->clear(); dialog->ui->comboBox->addItems(texts); dialog->ui->comboBox->setCurrentIndex(selectedIndex); if (dialog->exec() == QDialog::Rejected) return -1; return dialog->ui->comboBox->currentIndex(); } qvge-0.6.3/src/commonui/CExtListInputDialog.h000066400000000000000000000014761405165517400211270ustar00rootroot00000000000000#ifndef CExtListInputDialog_H #define CExtListInputDialog_H #include namespace Ui { class CExtListInputDialog; } class CExtListInputDialog : public QDialog { Q_OBJECT public: ~CExtListInputDialog(); static int getItemIndex(const QString &title, const QString &label, const QStringList& texts, const QList& icons, int selectedIndex = 0); static int getItemIndex(const QString &title, const QString &label, const QStringList& texts, int selectedIndex = 0); private: explicit CExtListInputDialog(QWidget *parent = nullptr); Ui::CExtListInputDialog *ui; }; #endif // CExtListInputDialog_H qvge-0.6.3/src/commonui/CExtListInputDialog.ui000066400000000000000000000032221405165517400213040ustar00rootroot00000000000000 CExtListInputDialog 0 0 330 86 Dialog Select an item: Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() CExtListInputDialog accept() 248 254 157 274 buttonBox rejected() CExtListInputDialog reject() 316 260 286 274 qvge-0.6.3/src/commonui/CNewAttributeDialog.cpp000066400000000000000000000036101405165517400214530ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CNewAttributeDialog.h" #include "ui_CNewAttributeDialog.h" #include CNewAttributeDialog::CNewAttributeDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CNewAttributeDialog) { ui->setupUi(this); ui->ButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } CNewAttributeDialog::~CNewAttributeDialog() { delete ui; } QByteArray CNewAttributeDialog::getId() const { return ui->Id->text().toLatin1(); } void CNewAttributeDialog::setId(const QString& id) { ui->Id->setText(id); } int CNewAttributeDialog::getType() const { switch (ui->Type->currentIndex()) { case 0: return QVariant::Int; case 1: return QVariant::Double; case 2: return QVariant::Bool; case 3: return QVariant::Color; case 4: return QVariant::Font; default: return QVariant::String; } } int CNewAttributeDialog::setType(int type) { switch (type) { case QVariant::Int: ui->Type->setCurrentIndex(0); break; case QVariant::Double: ui->Type->setCurrentIndex(1); break; case QVariant::Bool: ui->Type->setCurrentIndex(2); break; case QVariant::Color: ui->Type->setCurrentIndex(3); break; case QVariant::Font: ui->Type->setCurrentIndex(4); break; default: ui->Type->setCurrentIndex(5); break; } return ui->Type->currentIndex(); } QVariant CNewAttributeDialog::getValue() const { switch (ui->Type->currentIndex()) { case 0: return int(0); case 1: return double(0.0); case 2: return bool(true); case 3: return QColor(); case 4: return QFont(); default: return QString(); } } void CNewAttributeDialog::on_Id_textChanged(const QString &text) { ui->ButtonBox->button(QDialogButtonBox::Ok)->setEnabled(text.size()); } qvge-0.6.3/src/commonui/CNewAttributeDialog.h000066400000000000000000000013421405165517400211200ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CNewAttributeDialog_H #define CNewAttributeDialog_H #include namespace Ui { class CNewAttributeDialog; } class CNewAttributeDialog : public QDialog { Q_OBJECT public: explicit CNewAttributeDialog(QWidget *parent = 0); ~CNewAttributeDialog(); QByteArray getId() const; void setId(const QString& id); int getType() const; int setType(int type); QVariant getValue() const; private Q_SLOTS: void on_Id_textChanged(const QString& text); private: Ui::CNewAttributeDialog *ui; }; #endif // CNewAttributeDialog_H qvge-0.6.3/src/commonui/CNewAttributeDialog.ui000066400000000000000000000064461405165517400213200ustar00rootroot00000000000000 CNewAttributeDialog 0 0 349 107 Add New Attribute 100 0 Id Id of the attribute (cannot be empty) 100 0 Type Integer Real Boolean Color Font String Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok ButtonBox accepted() CNewAttributeDialog accept() 248 254 157 274 ButtonBox rejected() CNewAttributeDialog reject() 316 260 286 274 qvge-0.6.3/src/commonui/CNodeEdgePropertiesUI.cpp000066400000000000000000000337271405165517400217170ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include "CAttributesEditorUI.h" #include "CPropertyEditorUIBase.h" #include "CNodeEdgePropertiesUI.h" #include "ui_CNodeEdgePropertiesUI.h" #include #include #include #include #include #include #include CNodeEdgePropertiesUI::CNodeEdgePropertiesUI(QWidget *parent) : QWidget(parent), m_scene(NULL), m_updateLock(false), ui(new Ui::CNodeEdgePropertiesUI) { ui->setupUi(this); ui->NodeColor->setColorScheme(QSint::OpenOfficeColors()); ui->NodeColor->enableNoColor(true); ui->NodeShape->addAction(QIcon(":/Icons/Node-Disc"), tr("Disc"), "disc"); ui->NodeShape->addAction(QIcon(":/Icons/Node-Square"), tr("Square"), "square"); ui->NodeShape->addAction(QIcon(":/Icons/Node-Triangle"), tr("Triangle Up"), "triangle"); ui->NodeShape->addAction(QIcon(":/Icons/Node-Diamond"), tr("Diamond"), "diamond"); ui->NodeShape->addAction(QIcon(":/Icons/Node-Triangle-Down"), tr("Triangle Down"), "triangle2"); ui->NodeShape->addAction(QIcon(":/Icons/Node-Hexagon"), tr("Hexagon"), "hexagon"); ui->NodeAttrBox->setChecked(false); ui->EdgeDirection->addAction(QIcon(":/Icons/Edge-Directed"), tr("Directed (one end)"), "directed"); ui->EdgeDirection->addAction(QIcon(":/Icons/Edge-Mutual"), tr("Mutual (both ends)"), "mutual"); ui->EdgeDirection->addAction(QIcon(":/Icons/Edge-Undirected"), tr("None (no ends)"), "undirected"); ui->EdgeType->addAction(QIcon(":/Icons/Edge-Line"), tr("Direct line"), "edge"); ui->EdgeType->addAction(QIcon(":/Icons/Edge-Polyline"), tr("Polyline"), "polyedge"); ui->EdgeColor->setColorScheme(QSint::OpenOfficeColors()); ui->EdgeStyle->setUsedRange(Qt::SolidLine, Qt::DashDotDotLine); ui->StrokeStyle->setUsedRange(Qt::SolidLine, Qt::DashDotDotLine); ui->EdgeAttrBox->setChecked(false); // font size QList fontSizes = { 5,6,7,8,9,10,11,12,14,16,18,20,24,28,32,36,40,44,48,54,60,66,72,80,88,96 }; ui->LabelFontSize->setValueList(fontSizes); // node size QList nodeSizes = { 5,10,15,20,30,40,50,75,100,150,200 }; ui->NodeSizeX->setValueList(nodeSizes); ui->NodeSizeY->setValueList(nodeSizes); // node outline QList strokeSizes = { 1,2,3,4,5,6,7,8,9,10 }; ui->StrokeSize->setValueList(strokeSizes); // edge weight QList edgeSizes = { 1,2,3,4,5,6,7,8,9,10 }; ui->EdgeWeight->setValueList(edgeSizes); // update status & tooltips etc. ui->retranslateUi(this); } CNodeEdgePropertiesUI::~CNodeEdgePropertiesUI() { delete ui; } void CNodeEdgePropertiesUI::doReadSettings(QSettings& settings) { int pos = settings.value("nodes/splitterPosition", -1).toInt(); if (pos >= 0) ui->NodeAttrEditor->getEditor()->setSplitterPosition(pos); /*int*/ pos = settings.value("edges/splitterPosition", -1).toInt(); if (pos >= 0) ui->EdgeAttrEditor->getEditor()->setSplitterPosition(pos); } void CNodeEdgePropertiesUI::doWriteSettings(QSettings& settings) { settings.setValue("nodes/splitterPosition", ui->NodeAttrEditor->getEditor()->splitterPosition()); settings.setValue("edges/splitterPosition", ui->EdgeAttrEditor->getEditor()->splitterPosition()); } void CNodeEdgePropertiesUI::setScene(CNodeEditorScene* scene) { if (m_scene) onSceneDetached(m_scene); m_scene = scene; setEnabled(m_scene); if (m_scene) onSceneAttached(m_scene); } void CNodeEdgePropertiesUI::connectSignals(CEditorScene* scene) { connect(scene, SIGNAL(sceneChanged()), this, SLOT(onSceneChanged())); connect(scene, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); } void CNodeEdgePropertiesUI::updateFromScene(CEditorScene* scene) { // default attrs auto nodeAttrs = scene->getClassAttributes("node", false); ui->NodeColor->setColor(nodeAttrs["color"].defaultValue.value()); ui->NodeShape->selectAction(nodeAttrs["shape"].defaultValue); QSize size = nodeAttrs["size"].defaultValue.toSize(); ui->NodeSizeSwitch->setChecked(size.width() == size.height()); ui->NodeSizeY->setVisible(size.width() != size.height()); ui->NodeSizeX->setValue(size.width()); ui->NodeSizeY->setValue(size.height()); ui->StrokeColor->setColor(nodeAttrs["stroke.color"].defaultValue.value()); ui->StrokeStyle->setPenStyle(CUtils::textToPenStyle(nodeAttrs["stroke.style"].defaultValue.toString())); ui->StrokeSize->setValue(nodeAttrs["stroke.size"].defaultValue.toDouble()); auto edgeAttrs = scene->getClassAttributes("edge", false); ui->EdgeColor->setColor(edgeAttrs["color"].defaultValue.value()); ui->EdgeWeight->setValue(edgeAttrs["weight"].defaultValue.toDouble()); ui->EdgeStyle->setPenStyle(CUtils::textToPenStyle(edgeAttrs["style"].defaultValue.toString())); ui->EdgeDirection->selectAction(edgeAttrs["direction"].defaultValue); QFont f(edgeAttrs["label.font"].defaultValue.value()); ui->LabelFont->setCurrentFont(f); ui->LabelFontSize->setValue(f.pointSize()); ui->LabelColor->setColor(edgeAttrs["label.color"].defaultValue.value()); } void CNodeEdgePropertiesUI::onSceneAttached(CEditorScene* scene) { // factories for new items m_nodeFactory = m_scene->getNodesFactory(); m_edgeFactory = m_scene->getEdgesFactory(); // default attrs updateFromScene(scene); // connect & go connectSignals(scene); onSceneChanged(); } void CNodeEdgePropertiesUI::onSceneDetached(CEditorScene* scene) { scene->disconnect(this); } void CNodeEdgePropertiesUI::onSceneChanged() { // update active selections if any onSelectionChanged(); } void CNodeEdgePropertiesUI::onSelectionChanged() { if (m_updateLock || m_scene == NULL) return; m_updateLock = true; QList edges = m_scene->getSelectedEdges(); QList nodes = m_scene->getSelectedNodes(); // nodes ui->NodesBox->setTitle(tr("Nodes: %1").arg(nodes.count())); if (nodes.count()) { auto node = nodes.first(); ui->NodeColor->setColor(node->getAttribute("color").value()); ui->NodeShape->selectAction(node->getAttribute("shape")); QSize size = node->getAttribute("size").toSize(); ui->NodeSizeSwitch->setChecked(size.width() == size.height()); ui->NodeSizeY->setVisible(size.width() != size.height()); ui->NodeSizeX->setValue(size.width()); ui->NodeSizeY->setValue(size.height()); ui->StrokeColor->setColor(node->getAttribute("stroke.color").value()); ui->StrokeStyle->setPenStyle(CUtils::textToPenStyle(node->getAttribute("stroke.style").toString())); ui->StrokeSize->setValue(node->getAttribute("stroke.size").toDouble()); } QList nodeItems; for (auto item: nodes) nodeItems << item; int attrCount = ui->NodeAttrEditor->setupFromItems(*m_scene, nodeItems); ui->NodeAttrBox->setTitle(tr("Custom Attributes: %1").arg(attrCount)); // edges ui->EdgesBox->setTitle(tr("Edges: %1").arg(edges.count())); if (edges.count()) { auto edge = edges.first(); ui->EdgeColor->setColor(edge->getAttribute("color").value()); ui->EdgeWeight->setValue(edge->getAttribute("weight").toDouble()); ui->EdgeStyle->setPenStyle(CUtils::textToPenStyle(edge->getAttribute("style").toString())); ui->EdgeDirection->selectAction(edge->getAttribute("direction")); } QList edgeItems; for (auto item: edges) edgeItems << item; attrCount = ui->EdgeAttrEditor->setupFromItems(*m_scene, edgeItems); ui->EdgeAttrBox->setTitle(tr("Custom Attributes: %1").arg(attrCount)); // labels QList itemList; for (auto edgeItem: edges) itemList << edgeItem; for (auto nodeItem: nodes) itemList << nodeItem; for (auto item: itemList) { QFont f(item->getAttribute("label.font").value()); ui->LabelFont->setCurrentFont(f); ui->LabelFontSize->setValue(f.pointSize()); ui->LabelFontBold->setChecked(f.bold()); ui->LabelFontItalic->setChecked(f.italic()); ui->LabelFontUnderline->setChecked(f.underline()); ui->LabelColor->setColor(item->getAttribute("label.color").value()); break; } // allow updates m_updateLock = false; } void CNodeEdgePropertiesUI::setNodesAttribute(const QByteArray& attrId, const QVariant& v) { //if (m_nodeFactory) // m_nodeFactory->setAttribute(attrId, v); if (m_updateLock || m_scene == NULL) return; QList nodes = m_scene->getSelectedNodes(); if (nodes.isEmpty()) return; for (auto node : nodes) node->setAttribute(attrId, v); m_scene->addUndoState(); } void CNodeEdgePropertiesUI::setEdgesAttribute(const QByteArray& attrId, const QVariant& v) { //if (m_edgeFactory) // m_edgeFactory->setAttribute(attrId, v); if (m_updateLock || m_scene == NULL) return; QList edges = m_scene->getSelectedEdges(); if (edges.isEmpty()) return; for (auto edge : edges) edge->setAttribute(attrId, v); m_scene->addUndoState(); } void CNodeEdgePropertiesUI::on_NodeColor_activated(const QColor &color) { setNodesAttribute("color", color); } void CNodeEdgePropertiesUI::on_NodeShape_activated(QVariant data) { setNodesAttribute("shape", data); } void CNodeEdgePropertiesUI::on_NodeSizeX_valueChanged(int /*value*/) { ui->NodeSizeX->blockSignals(true); ui->NodeSizeY->blockSignals(true); if (ui->NodeSizeSwitch->isChecked()) ui->NodeSizeY->setValue(ui->NodeSizeX->value()); QSize size(ui->NodeSizeX->value(), ui->NodeSizeY->value()); setNodesAttribute("size", size); ui->NodeSizeX->blockSignals(false); ui->NodeSizeY->blockSignals(false); } void CNodeEdgePropertiesUI::on_NodeSizeY_valueChanged(int value) { on_NodeSizeX_valueChanged(value); } void CNodeEdgePropertiesUI::on_NodeSizeSwitch_toggled(bool on) { ui->NodeSizeY->setVisible(!on); if (on) { ui->NodeSizeY->setValue(ui->NodeSizeX->value()); //ui->NodeSizeX->setFocus(); } //else // ui->NodeSizeY->setFocus(); } void CNodeEdgePropertiesUI::on_StrokeColor_activated(const QColor &color) { setNodesAttribute("stroke.color", color); } void CNodeEdgePropertiesUI::on_StrokeStyle_activated(QVariant data) { QString style = CUtils::penStyleToText(data.toInt()); setNodesAttribute("stroke.style", style); } void CNodeEdgePropertiesUI::on_StrokeSize_valueChanged(double value) { setNodesAttribute("stroke.size", value); } void CNodeEdgePropertiesUI::on_EdgeColor_activated(const QColor &color) { setEdgesAttribute("color", color); } void CNodeEdgePropertiesUI::on_EdgeWeight_valueChanged(double value) { setEdgesAttribute("weight", value); } void CNodeEdgePropertiesUI::on_EdgeStyle_activated(QVariant data) { QString style = CUtils::penStyleToText(data.toInt()); setEdgesAttribute("style", style); } void CNodeEdgePropertiesUI::on_EdgeDirection_activated(QVariant data) { setEdgesAttribute("direction", data); } void CNodeEdgePropertiesUI::on_EdgeType_activated(QVariant data) { if (m_scene) { if (data.toString() == "edge") { m_scene->setEdgesFactory(m_scene->factory()); changeEdgesClass(); } else if (data.toString() == "polyedge") { m_scene->setEdgesFactory(m_scene->factory()); changeEdgesClass(); } m_edgeFactory = m_scene->getEdgesFactory(); } } void CNodeEdgePropertiesUI::on_LabelFont_activated(const QFont &font) { ui->LabelFontSize->blockSignals(true); ui->LabelFontSize->setValue(font.pointSize()); ui->LabelFontSize->blockSignals(false); if (m_updateLock || m_scene == NULL) return; QList items = m_scene->getSelectedNodesEdges(); if (items.isEmpty()) return; for (auto item : items) { item->setAttribute(attr_label_font, font); } m_scene->addUndoState(); } void CNodeEdgePropertiesUI::on_LabelColor_activated(const QColor &color) { if (m_updateLock || m_scene == NULL) return; QList items = m_scene->getSelectedNodesEdges(); if (items.isEmpty()) return; for (auto item : items) { item->setAttribute(attr_label_color, color); } m_scene->addUndoState(); } void CNodeEdgePropertiesUI::on_LabelFontSize_valueChanged(int value) { if (m_updateLock || m_scene == NULL) return; QList items = m_scene->getSelectedNodesEdges(); if (items.isEmpty()) return; bool set = false; for (auto item : items) { QFont font = item->getAttribute(attr_label_font).value(); if (font.pointSize() != value) { font.setPointSize(value); item->setAttribute(attr_label_font, font); set = true; } } if (set) m_scene->addUndoState(); } void CNodeEdgePropertiesUI::on_LabelFontBold_toggled(bool on) { if (m_updateLock || m_scene == NULL) return; QList items = m_scene->getSelectedNodesEdges(); if (items.isEmpty()) return; bool set = false; for (auto item : items) { QFont font = item->getAttribute(attr_label_font).value(); if (font.bold() != on) { font.setBold(on); item->setAttribute(attr_label_font, font); set = true; } } if (set) m_scene->addUndoState(); } void CNodeEdgePropertiesUI::on_LabelFontItalic_toggled(bool on) { if (m_updateLock || m_scene == NULL) return; QList items = m_scene->getSelectedNodesEdges(); if (items.isEmpty()) return; bool set = false; for (auto item : items) { QFont font = item->getAttribute(attr_label_font).value(); if (font.italic() != on) { font.setItalic(on); item->setAttribute(attr_label_font, font); item->updateLabelContent(); set = true; } } if (set) m_scene->addUndoState(); } void CNodeEdgePropertiesUI::on_LabelFontUnderline_toggled(bool on) { if (m_updateLock || m_scene == NULL) return; QList items = m_scene->getSelectedNodesEdges(); if (items.isEmpty()) return; bool set = false; for (auto item : items) { QFont font = item->getAttribute(attr_label_font).value(); if (font.underline() != on) { font.setUnderline(on); item->setAttribute(attr_label_font, font); set = true; } } if (set) m_scene->addUndoState(); } qvge-0.6.3/src/commonui/CNodeEdgePropertiesUI.h000066400000000000000000000052411405165517400213520ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CNODEPROPERTIESUI_H #define CNODEPROPERTIESUI_H #include #include #include #include class CEditorScene; //class CNodeEditorScene; class CNode; class CEdge; namespace Ui { class CNodeEdgePropertiesUI; } class CNodeEdgePropertiesUI : public QWidget { Q_OBJECT public: explicit CNodeEdgePropertiesUI(QWidget *parent = nullptr); ~CNodeEdgePropertiesUI(); void setScene(CNodeEditorScene* scene); void doReadSettings(QSettings& settings); void doWriteSettings(QSettings& settings); public Q_SLOTS: void updateFromScene(CEditorScene* scene); protected: void connectSignals(CEditorScene* scene); void onSceneAttached(CEditorScene* scene); void onSceneDetached(CEditorScene* scene); protected Q_SLOTS: void onSceneChanged(); void onSelectionChanged(); void on_NodeColor_activated(const QColor &color); void on_NodeShape_activated(QVariant data); void on_NodeSizeX_valueChanged(int value); void on_NodeSizeY_valueChanged(int value); void on_NodeSizeSwitch_toggled(bool on); void on_StrokeColor_activated(const QColor &color); void on_StrokeStyle_activated(QVariant data); void on_StrokeSize_valueChanged(double value); void on_EdgeColor_activated(const QColor &color); void on_EdgeWeight_valueChanged(double value); void on_EdgeStyle_activated(QVariant data); void on_EdgeDirection_activated(QVariant data); void on_EdgeType_activated(QVariant data); void on_LabelFont_activated(const QFont &font); void on_LabelColor_activated(const QColor &color); void on_LabelFontSize_valueChanged(int value); void on_LabelFontBold_toggled(bool on); void on_LabelFontItalic_toggled(bool on); void on_LabelFontUnderline_toggled(bool on); private: void setNodesAttribute(const QByteArray& attrId, const QVariant& v); void setEdgesAttribute(const QByteArray& attrId, const QVariant& v); CNodeEditorScene *m_scene; bool m_updateLock; CNode *m_nodeFactory; CEdge *m_edgeFactory; Ui::CNodeEdgePropertiesUI *ui; private: template void changeEdgesClass() { if (m_updateLock || m_scene == NULL) return; QList edges = m_scene->getSelectedEdges(); if (edges.isEmpty()) return; QList newEdges; for (auto edge : edges) { auto e = m_scene->changeEdgeClass(edge); if (e && e != edge) newEdges << e; } if (newEdges.size()) { m_scene->addUndoState(); m_scene->selectItems(newEdges, false); } } }; #endif // CNODEPROPERTIESUI_H qvge-0.6.3/src/commonui/CNodeEdgePropertiesUI.ui000066400000000000000000000723331405165517400215460ustar00rootroot00000000000000 CNodeEdgePropertiesUI 0 0 419 430 0 0 Form /* QDoubleSpinBox, QSpinBox, QComboBox { border: 1px solid #aaa; background: white; } QSpinBox:hover, QDoubleSpinBox:hover, QComboBox:hover { border: 1px solid #00a; background: white; } QToolButton { border: 1px none; background: transparent; } QToolButton::menu-button { background: transparent; } QToolButton:on { border: 1px solid #00a; background: #bbb; } QToolButton:hover:!on { border: 1px solid #00a; background: #eee; } */ 0 0 0 0 Nodes (1) Qt::AlignCenter 0 0 44 28 Set fill color of the selected nodes ... 18 18 QToolButton::MenuButtonPopup 44 28 16777215 28 Set shape of the selected nodes ... 18 18 QToolButton::MenuButtonPopup 0 0 60 28 60 28 Set width of the selected nodes QAbstractSpinBox::CorrectToNearestValue 1 1000 0 0 Uniform nodes size editing if checked # true false 0 0 60 28 60 28 Set height of the selected nodes QAbstractSpinBox::CorrectToNearestValue 1 1000 Qt::Horizontal 40 20 QFrame::StyledPanel QFrame::Sunken Shape Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 0 0 44 28 Set stroke color of the selected nodes ... 18 18 QToolButton::MenuButtonPopup 44 28 Set stroke style of the selected nodes ... 18 18 QToolButton::MenuButtonPopup 0 0 60 28 60 28 Set stroke width of the selected nodes QAbstractSpinBox::CorrectToNearestValue 1 0.100000000000000 0.100000000000000 Qt::Horizontal 40 20 QFrame::StyledPanel QFrame::Sunken Outline Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Custom attributes Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true true 0 0 0 0 Edges (1) Qt::AlignCenter 0 0 44 28 Set color of the selected edges ... 18 18 QToolButton::MenuButtonPopup 44 28 Set pen style of the selected edges ... 18 18 QToolButton::MenuButtonPopup 0 0 60 28 60 28 Set weight of the selected edges QAbstractSpinBox::CorrectToNearestValue 1 0.100000000000000 0.100000000000000 44 28 Set direction of the selected edges ... 18 18 QToolButton::MenuButtonPopup Qt::Horizontal 40 20 44 28 Set type of the selected edges ... 18 18 QToolButton::MenuButtonPopup 0 0 Custom attributes Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true true 0 0 0 0 Labels Qt::AlignCenter 0 0 44 28 16777215 28 Set color of the selected labels ... 18 18 QToolButton::MenuButtonPopup 0 0 0 28 28 28 12 75 true Bold font look of the selected labels B true 0 0 0 28 28 28 12 50 true false Italic font look of the selected labels I true 0 0 0 28 28 28 12 50 false false true Underlined font look of the selected labels U true 0 0 60 28 60 28 Set font size of the selected labels QAbstractSpinBox::CorrectToNearestValue 1 1000 0 0 70 28 16777215 28 Set font of the selected labels Aa1 QToolButton::MenuButtonPopup Qt::ToolButtonTextOnly Qt::Horizontal 40 20 QSint::ColorButton QToolButton
colorbutton.h
QSint::QSplitButton QToolButton
qsplitbutton.h
QSint::QPenButton QToolButton
qpenbutton.h
QSint::QFontButton QToolButton
qfontbutton.h
CAttributesEditorUI QWidget
CAttributesEditorUI.h
1
QSint::SpinComboBox QSpinBox
spincombobox.h
QSint::DoubleSpinComboBox QDoubleSpinBox
doublespincombobox.h
NodeColor NodeShape NodeSizeX NodeSizeSwitch NodeSizeY StrokeColor StrokeStyle StrokeSize NodeAttrBox EdgeColor EdgeStyle EdgeWeight EdgeDirection EdgeAttrBox LabelColor LabelFont NodeAttrBox toggled(bool) NodeAttrEditor setVisible(bool) 100 71 113 89 EdgeAttrBox toggled(bool) EdgeAttrEditor setVisible(bool) 38 195 58 218
qvge-0.6.3/src/commonui/CNodeEditorUIController.cpp000066400000000000000000001004301405165517400222520ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_OGDF #include #include #endif #ifdef USE_GVGRAPH #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CNodeEditorUIController::CNodeEditorUIController(CMainWindow *parent) : QObject(nullptr), m_parent(parent) { // create document m_editorScene = new CNodeEditorScene(parent); m_editorView = new CEditorView(m_editorScene, parent); parent->setCentralWidget(m_editorView); // connect scene connect(m_editorScene, &CEditorScene::sceneChanged, parent, &CMainWindow::onDocumentChanged); connect(m_editorScene, &CEditorScene::sceneChanged, this, &CNodeEditorUIController::onSceneChanged); connect(m_editorScene, &CEditorScene::selectionChanged, this, &CNodeEditorUIController::onSelectionChanged); connect(m_editorScene, &CEditorScene::infoStatusChanged, this, &CNodeEditorUIController::onSceneStatusChanged); connect(m_editorScene, &CNodeEditorScene::editModeChanged, this, &CNodeEditorUIController::onEditModeChanged); connect(m_editorScene, &CEditorScene::sceneDoubleClicked, this, &CNodeEditorUIController::onSceneDoubleClicked); CSceneMenuUIController *menuController = new CSceneMenuUIController(this); m_editorScene->setContextMenuController(menuController); // connect view connect(m_editorView, SIGNAL(scaleChanged(double)), this, SLOT(onZoomChanged(double))); // slider2d createNavigator(); // menus & actions createMenus(); // dock panels createPanels(); // status bar m_statusLabel = new QLabel(); parent->statusBar()->addPermanentWidget(m_statusLabel); // update actions onSceneChanged(); onSelectionChanged(); onZoomChanged(1); onSceneStatusChanged(m_editorScene->getInfoStatus()); // search dialog m_searchDialog = new CSearchDialog(parent); // IO m_ioController = new CImportExportUIController(parent); // OGDF #ifdef USE_OGDF m_ogdfController = new COGDFLayoutUIController(parent, m_editorScene); connect(m_ogdfController, SIGNAL(layoutFinished()), this, SLOT(onLayoutFinished())); #endif // GraphViz #ifdef USE_GVGRAPH m_gvController = new CGVGraphLayoutUIController(parent, m_editorScene); connect(m_gvController, SIGNAL(layoutFinished()), this, SLOT(onLayoutFinished())); #ifdef Q_OS_WIN32 QString pathToGraphviz = QCoreApplication::applicationDirPath() + "/../tools/graphviz"; m_optionsData.graphvizPath = QFileInfo(pathToGraphviz).absoluteFilePath(); #else m_optionsData.graphvizPath = ""; #endif m_gvController->setPathToGraphviz(m_optionsData.graphvizPath); m_optionsData.graphvizDefaultEngine = "dot"; m_ioController->setGVGraphController(m_gvController); #endif // workaround for full screen #ifndef Q_OS_WIN32 if (parent->isMaximized()) { parent->showNormal(); QTimer::singleShot(0, parent, SLOT(showMaximized())); } #endif // default scene settings readDefaultSceneSettings(); // backup timer connect(&m_backupTimer, &QTimer::timeout, this, &CNodeEditorUIController::doBackup); } CNodeEditorUIController::~CNodeEditorUIController() { } // IO bool CNodeEditorUIController::loadFromFile(const QString &format, const QString &fileName, QString* lastError) { if (m_ioController) return m_ioController->loadFromFile(format, fileName, *m_editorScene, lastError); else return false; } bool CNodeEditorUIController::saveToFile(const QString &format, const QString &fileName, QString* lastError) { if (m_ioController) return m_ioController->saveToFile(format, fileName, *m_editorScene, lastError); else return false; } // tbd: move to m_ioController void CNodeEditorUIController::exportFile() { m_ioController->exportImage(*m_editorScene); } void CNodeEditorUIController::exportPDF() { m_ioController->exportPDF(*m_editorScene); } void CNodeEditorUIController::exportSVG() { m_ioController->exportSVG(*m_editorScene); } void CNodeEditorUIController::exportDOT() { m_ioController->exportDOT(*m_editorScene); } bool CNodeEditorUIController::importCSV(const QString &fileName, QString* lastError) { return m_ioController->importCSV(*m_editorScene, fileName, lastError); } // UI void CNodeEditorUIController::createMenus() { // file actions QAction *exportAction = m_parent->getFileExportAction(); exportAction->setVisible(true); exportAction->setText(tr("Export to &Image...")); connect(exportAction, &QAction::triggered, this, &CNodeEditorUIController::exportFile); QAction *exportActionSVG = new QAction(QIcon(":/Icons/SVG"), tr("Export to &SVG...")); m_parent->getFileMenu()->insertAction(exportAction, exportActionSVG); connect(exportActionSVG, &QAction::triggered, this, &CNodeEditorUIController::exportSVG); QAction *exportActionPDF = new QAction(QIcon(":/Icons/PDF"), tr("Export to &PDF...")); m_parent->getFileMenu()->insertAction(exportActionSVG, exportActionPDF); connect(exportActionPDF, &QAction::triggered, this, &CNodeEditorUIController::exportPDF); QAction *exportActionDOT = new QAction(QIcon(":/Icons/DOT"), tr("Export to &DOT/GraphViz...")); m_parent->getFileMenu()->insertAction(exportActionPDF, exportActionDOT); connect(exportActionDOT, &QAction::triggered, this, &CNodeEditorUIController::exportDOT); m_parent->getFileMenu()->insertSeparator(exportActionDOT); // add edit menu QMenu *editMenu = new QMenu(tr("&Edit")); m_parent->menuBar()->insertMenu(m_parent->getWindowMenuAction(), editMenu); QAction *undoAction = editMenu->addAction(QIcon(":/Icons/Undo"), tr("&Undo")); undoAction->setStatusTip(tr("Undo latest action")); undoAction->setShortcut(QKeySequence::Undo); connect(undoAction, &QAction::triggered, this, &CNodeEditorUIController::undo); connect(m_editorScene, &CEditorScene::undoAvailable, undoAction, &QAction::setEnabled); undoAction->setEnabled(m_editorScene->availableUndoCount()); QAction *redoAction = editMenu->addAction(QIcon(":/Icons/Redo"), tr("&Redo")); redoAction->setStatusTip(tr("Redo latest action")); redoAction->setShortcut(QKeySequence::Redo); connect(redoAction, &QAction::triggered, this, &CNodeEditorUIController::redo); connect(m_editorScene, &CEditorScene::redoAvailable, redoAction, &QAction::setEnabled); redoAction->setEnabled(m_editorScene->availableRedoCount()); editMenu->addSeparator(); editMenu->addAction(m_editorScene->actions()->cutAction); editMenu->addAction(m_editorScene->actions()->copyAction); editMenu->addAction(m_editorScene->actions()->pasteAction); editMenu->addAction(m_editorScene->actions()->delAction); QAction *selAction = editMenu->addAction(QIcon(":/Icons/SelectAll"), tr("Select All")); selAction->setStatusTip(tr("Select all items on the scene")); selAction->setToolTip(tr("Select all items")); selAction->setShortcut(QKeySequence::SelectAll); connect(selAction, &QAction::triggered, m_editorScene, &CEditorScene::selectAll); editMenu->addSeparator(); findAction = editMenu->addAction(QIcon(":/Icons/Search"), tr("&Find...")); findAction->setStatusTip(tr("Search for items and attributes")); findAction->setToolTip(tr("Search for items")); findAction->setShortcut(QKeySequence::Find); connect(findAction, &QAction::triggered, this, &CNodeEditorUIController::find); // edit modes editMenu->addSeparator(); m_editModesGroup = new QActionGroup(this); m_editModesGroup->setExclusive(true); connect(m_editModesGroup, &QActionGroup::triggered, this, &CNodeEditorUIController::sceneEditMode); modeDefaultAction = editMenu->addAction(QIcon(":/Icons/Mode-Select"), tr("Select Items")); modeDefaultAction->setToolTip(tr("Items selection mode")); modeDefaultAction->setStatusTip(tr("Select/deselect items in the document")); modeDefaultAction->setCheckable(true); modeDefaultAction->setActionGroup(m_editModesGroup); modeDefaultAction->setChecked(m_editorScene->getEditMode() == EM_Default); modeDefaultAction->setData(EM_Default); modeNodesAction = editMenu->addAction(QIcon(":/Icons/Mode-AddNodes"), tr("Create Nodes")); modeNodesAction->setToolTip(tr("Adding new nodes mode")); modeNodesAction->setStatusTip(tr("Quickly add nodes & edges")); modeNodesAction->setCheckable(true); modeNodesAction->setActionGroup(m_editModesGroup); modeNodesAction->setChecked(m_editorScene->getEditMode() == EM_AddNodes); modeNodesAction->setData(EM_AddNodes); modeTransformAction = editMenu->addAction(QIcon(":/Icons/Mode-Transform"), tr("Transform")); modeTransformAction->setToolTip(tr("Items transformation mode")); modeTransformAction->setStatusTip(tr("Transform selected nodes (scale & move)")); modeTransformAction->setCheckable(true); modeTransformAction->setActionGroup(m_editModesGroup); modeTransformAction->setChecked(m_editorScene->getEditMode() == EM_Transform); modeTransformAction->setData(EM_Transform); modeFactorAction = editMenu->addAction(QIcon(":/Icons/Mode-Factor"), tr("Factor")); modeFactorAction->setToolTip(tr("Positions transformation mode")); modeFactorAction->setStatusTip(tr("Scale position of selected nodes (move only)")); modeFactorAction->setCheckable(true); modeFactorAction->setActionGroup(m_editModesGroup); modeFactorAction->setChecked(m_editorScene->getEditMode() == EM_Factor); modeFactorAction->setData(EM_Factor); // scene actions editMenu->addSeparator(); QAction *sceneCropAction = editMenu->addAction(QIcon(":/Icons/Crop"), tr("&Crop Area")); sceneCropAction->setStatusTip(tr("Crop document area to contents")); connect(sceneCropAction, &QAction::triggered, m_editorScene, &CEditorScene::crop); // color schemes editMenu->addSeparator(); m_schemesController = new CColorSchemesUIController(this); m_schemesController->setScene(m_editorScene); QAction *schemesAction = editMenu->addMenu(m_schemesController->getSchemesMenu()); schemesAction->setText(tr("Apply Colors")); schemesAction->setStatusTip(tr("Apply predefined color scheme to the document")); // scene options editMenu->addSeparator(); QAction *sceneAction = editMenu->addAction(QIcon(":/Icons/Settings"), tr("&Options...")); sceneAction->setStatusTip(tr("Change document properties")); connect(sceneAction, &QAction::triggered, this, &CNodeEditorUIController::sceneOptions); // add edit toolbar QToolBar *editToolbar = m_parent->addToolBar(tr("Edit")); editToolbar->setObjectName("editToolbar"); editToolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); editToolbar->addAction(undoAction); editToolbar->addAction(redoAction); editToolbar->addSeparator(); editToolbar->addAction(m_editorScene->actions()->cutAction); editToolbar->addAction(m_editorScene->actions()->copyAction); editToolbar->addAction(m_editorScene->actions()->pasteAction); editToolbar->addAction(m_editorScene->actions()->delAction); editToolbar->addSeparator(); editToolbar->addAction(findAction); // add edit modes toolbar QToolBar *editModesToolbar = m_parent->addToolBar(tr("Edit Modes")); editModesToolbar->setObjectName("editModesToolbar"); editModesToolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); editModesToolbar->addAction(modeDefaultAction); editModesToolbar->addAction(modeNodesAction); editModesToolbar->addAction(modeTransformAction); editModesToolbar->addAction(modeFactorAction); // add view menu m_viewMenu = new QMenu(tr("&View")); m_parent->menuBar()->insertMenu(m_parent->getWindowMenuAction(), m_viewMenu); gridAction = m_viewMenu->addAction(QIcon(":/Icons/Grid-Show"), tr("Show &Grid")); gridAction->setCheckable(true); gridAction->setStatusTip(tr("Show/hide background grid")); gridAction->setChecked(m_editorScene->gridEnabled()); connect(gridAction, SIGNAL(toggled(bool)), m_editorScene, SLOT(enableGrid(bool))); gridSnapAction = m_viewMenu->addAction(QIcon(":/Icons/Grid-Snap"), tr("&Snap to Grid")); gridSnapAction->setCheckable(true); gridSnapAction->setStatusTip(tr("Snap to grid when dragging")); gridSnapAction->setChecked(m_editorScene->gridSnapEnabled()); connect(gridSnapAction, SIGNAL(toggled(bool)), m_editorScene, SLOT(enableGridSnap(bool))); m_actionShowNodeIds = m_viewMenu->addAction(tr("Show Node Ids")); m_actionShowNodeIds->setCheckable(true); m_actionShowNodeIds->setStatusTip(tr("Show/hide node ids")); m_actionShowNodeIds->setChecked(m_editorScene->isClassAttributeVisible(class_node, attr_id)); connect(m_actionShowNodeIds, SIGNAL(toggled(bool)), this, SLOT(showNodeIds(bool))); m_actionShowEdgeIds = m_viewMenu->addAction(tr("Show Edge Ids")); m_actionShowEdgeIds->setCheckable(true); m_actionShowEdgeIds->setStatusTip(tr("Show/hide edge ids")); m_actionShowEdgeIds->setChecked(m_editorScene->isClassAttributeVisible(class_edge, attr_id)); connect(m_actionShowEdgeIds, SIGNAL(toggled(bool)), this, SLOT(showEdgeIds(bool))); m_viewMenu->addSeparator(); zoomAction = m_viewMenu->addAction(QIcon(":/Icons/ZoomIn"), tr("&Zoom")); zoomAction->setStatusTip(tr("Zoom view in")); zoomAction->setShortcut(QKeySequence::ZoomIn); connect(zoomAction, &QAction::triggered, this, &CNodeEditorUIController::zoom); unzoomAction = m_viewMenu->addAction(QIcon(":/Icons/ZoomOut"), tr("&Unzoom")); unzoomAction->setStatusTip(tr("Zoom view out")); unzoomAction->setShortcut(QKeySequence::ZoomOut); connect(unzoomAction, &QAction::triggered, this, &CNodeEditorUIController::unzoom); resetZoomAction = m_viewMenu->addAction(QIcon(":/Icons/ZoomReset"), tr("&Reset Zoom")); resetZoomAction->setStatusTip(tr("Zoom view to 100%")); connect(resetZoomAction, &QAction::triggered, this, &CNodeEditorUIController::resetZoom); fitZoomAction = m_viewMenu->addAction(QIcon(":/Icons/ZoomFit"), tr("&Fit to View")); fitZoomAction->setStatusTip(tr("Zoom to fit all the items to view")); connect(fitZoomAction, &QAction::triggered, m_editorView, &CEditorView::fitToView); fitZoomSelectedAction = m_viewMenu->addAction(QIcon(":/Icons/ZoomFitSelected"), tr("Fit &Selection")); fitZoomSelectedAction->setToolTip(tr("Fit selected items to view")); fitZoomSelectedAction->setStatusTip(tr("Zoom to fit selected items to view")); connect(fitZoomSelectedAction, &QAction::triggered, m_editorView, &CEditorView::fitSelectedToView); fitZoomBackAction = m_viewMenu->addAction(QIcon(":/Icons/ZoomFitBack"), tr("Zoom &Back")); fitZoomBackAction->setStatusTip(tr("Zoom to previous state before last fit")); connect(fitZoomBackAction, &QAction::triggered, m_editorView, &CEditorView::zoomBack); // add zoom toolbar QToolBar *zoomToolbar = m_parent->addToolBar(tr("Zoom")); zoomToolbar->setObjectName("zoomToolbar"); zoomToolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); zoomToolbar->addAction(zoomAction); resetZoomAction2 = zoomToolbar->addAction(QIcon(":/Icons/Zoom"), ""); resetZoomAction2->setStatusTip(resetZoomAction->statusTip()); resetZoomAction2->setToolTip(resetZoomAction->statusTip()); connect(resetZoomAction2, &QAction::triggered, this, &CNodeEditorUIController::resetZoom); zoomToolbar->addAction(unzoomAction); zoomToolbar->addAction(fitZoomAction); zoomToolbar->addAction(fitZoomSelectedAction); zoomToolbar->addAction(fitZoomBackAction); } void CNodeEditorUIController::createPanels() { // default properties m_parent->createDockWindow( "defaultsDock", tr("Default Properties"), Qt::LeftDockWidgetArea, m_defaultsPanel = new CClassAttributesEditorUI(m_parent) ); m_defaultsPanel->setScene(m_editorScene); // properties m_parent->createDockWindow( "propertyDock", tr("Item Properties"), Qt::RightDockWidgetArea, m_propertiesPanel = new CNodeEdgePropertiesUI(m_parent) ); m_propertiesPanel->setScene(m_editorScene); // connections m_parent->createDockWindow( "connectionsDock", tr("Topology"), Qt::LeftDockWidgetArea, m_connectionsPanel = new CCommutationTable(m_parent) ); m_connectionsPanel->setScene(m_editorScene); // quick help auto *quickHelpDock = m_parent->createDockWindow( "quickHelpDock", tr("Quick Help"), Qt::RightDockWidgetArea, m_quickHelpPanel = new CQuickHelpUI(m_parent) ); // update view menu with created toolbars & panels m_viewMenu->addSeparator(); QAction *panelsAction = m_viewMenu->addMenu(m_parent->createPopupMenu()); panelsAction->setText("Toolbars and Panels"); // update help menu QAction *quickHelpAction = quickHelpDock->toggleViewAction(); quickHelpAction->setShortcut(QKeySequence::HelpContents); m_parent->getHelpMenu()->insertAction( m_parent->getHelpMenu()->actions().first(), quickHelpAction); } void CNodeEditorUIController::createNavigator() { m_sliderView = new QSint::Slider2d(m_parent); m_sliderView->connectSource(m_editorView); QToolButton *sliderButton = m_sliderView->makeAsButton(); m_editorView->setCornerWidget(sliderButton); sliderButton->setIcon(QIcon(":/Icons/Navigator")); sliderButton->setToolTip(tr("Show scene navigator")); connect(m_sliderView, SIGNAL(aboutToShow()), this, SLOT(onNavigatorShown())); m_sliderView->setFixedSize(200,200); m_sliderView->setSliderOpacity(0.3); m_sliderView->setSliderBrush(Qt::green); } void CNodeEditorUIController::onNavigatorShown() { double w = m_editorScene->sceneRect().width(); double h = m_editorScene->sceneRect().height(); double cw = w > h ? 200.0 : 200.0 * (w/h); double ch = h > w ? 200.0 : 200.0 * (h/w) ; m_sliderView->setFixedSize(cw, ch); // Qt bug: update menu size QResizeEvent re(m_sliderView->size(), m_sliderView->parentWidget()->size()); qApp->sendEvent(m_sliderView->parentWidget(), &re); QPixmap pm(m_sliderView->size()); QPainter p(&pm); CEditorScene* tempScene = m_editorScene->clone(); tempScene->enableGrid(false); tempScene->enableItemLabels(false); tempScene->render(&p); delete tempScene; m_sliderView->setBackgroundBrush(pm); } void CNodeEditorUIController::onSelectionChanged() { int selectionCount = m_editorScene->selectedItems().size(); fitZoomSelectedAction->setEnabled(selectionCount > 0); } void CNodeEditorUIController::onSceneChanged() { auto nodes = m_editorScene->getItems(); auto edges = m_editorScene->getItems(); m_statusLabel->setText(tr("Nodes: %1 | Edges: %2").arg(nodes.size()).arg(edges.size())); updateActions(); } // scene void CNodeEditorUIController::onSceneHint(const QString& text) { m_parent->statusBar()->showMessage(text); } void CNodeEditorUIController::onSceneStatusChanged(int status) { bool isAddNodesMode = (m_editorScene->getEditMode() == EM_AddNodes); const QString arrowMoveHint = tr(" | Cursor keys - move selected items by one point | Shift + Cursor keys - move selected items by grid step"); switch (status) { case SIS_Edit_Label: onSceneHint(tr("Enter - finish edit | Esc - cancel edit | Shift + Enter - insert line break")); return; case SIS_Hover: if (isAddNodesMode) onSceneHint(tr("Click & drag - create new connection | Double click - edit item's label") + arrowMoveHint); else onSceneHint(tr("Ctrl + Click - (un)select item | Click & drag or Ctrl/Shift + Cursor keys - move selected items | Ctrl + Click & drag - clone selected items | Double click - edit item's label")); return; case SIS_Drag: onSceneHint(tr("Shift - horizontal or vertical snap | Alt - toggle grid snap")); return; case SIS_Hover_Port: onSceneHint(tr("Click & drag - make a connection at this port | Double click - show port properties")); return; default: if (isAddNodesMode) onSceneHint(tr("Click - create new node | Click & drag - create new connection") + arrowMoveHint); else onSceneHint(tr("Click & drag - select an area") + arrowMoveHint); } } void CNodeEditorUIController::onSceneDoubleClicked(QGraphicsSceneMouseEvent* /*mouseEvent*/, QGraphicsItem* clickedItem) { CNodePort *port = dynamic_cast(clickedItem); if (port) editNodePort(*port); } void CNodeEditorUIController::sceneEditMode(QAction* act) { int mode = act->data().toInt(); m_editorScene->setEditMode((EditMode)mode); } void CNodeEditorUIController::onEditModeChanged(int mode) { modeNodesAction->setChecked(mode == EM_AddNodes); modeDefaultAction->setChecked(mode == EM_Default); modeTransformAction->setChecked(mode == EM_Transform); modeFactorAction->setChecked(mode == EM_Factor); } // documents void CNodeEditorUIController::doBackup() { QString backupFileName = m_parent->getCurrentFileName(); if (backupFileName.isEmpty()) { m_parent->statusBar()->showMessage(tr("Cannot backup non-saved document"), 2000); return; } else { backupFileName = CUtils::cutLastSuffix(backupFileName) + ".bak.xgr"; } m_parent->statusBar()->showMessage(tr("Running backup... (%1)").arg(backupFileName)); qApp->processEvents(); CFileSerializerXGR writer; if (writer.save(backupFileName, *m_editorScene)) { m_parent->statusBar()->showMessage(tr("Backup done (%1)").arg(backupFileName), 2000); } else { m_parent->statusBar()->showMessage(tr("Backup failed (%1)").arg(backupFileName), 2000); } } void CNodeEditorUIController::onNewDocumentCreated() { readDefaultSceneSettings(); m_editorScene->createClassAttribute("", "comment", "Comment", QString(), ATTR_NONE); m_editorScene->createClassAttribute("", "creator", "Creator of document", QApplication::applicationName() + " " + QApplication::applicationVersion(), ATTR_NONE); // store newly created state m_editorScene->addUndoState(); } void CNodeEditorUIController::onDocumentLoaded(const QString &fileName) { QSettings& settings = m_parent->getApplicationSettings(); // read custom topology of the current document settings.beginGroup("CustomFiles"); QString filename = QFileInfo(fileName).fileName(); if (!filename.isEmpty() && settings.childGroups().contains(filename)) { settings.beginGroup(filename); settings.beginGroup("UI/Topology"); m_connectionsPanel->doReadSettings(settings); settings.endGroup(); settings.endGroup(); } settings.endGroup(); // workaround: always make the labels visible m_editorScene->setClassAttributeVisible(class_item, attr_label, true); m_editorScene->setClassAttributeVisible(class_node, attr_label, true); m_editorScene->setClassAttributeVisible(class_edge, attr_label, true); // store newly created state m_editorScene->setInitialState(); // center scene contents m_editorView->centerContent(); } // settings QSettings& CNodeEditorUIController::getApplicationSettings() const { return m_parent->getApplicationSettings(); } void CNodeEditorUIController::doReadSettings(QSettings& settings) { // options int cacheRam = QPixmapCache::cacheLimit(); cacheRam = settings.value("cacheRam", cacheRam).toInt(); QPixmapCache::setCacheLimit(cacheRam); bool isAA = m_editorView->renderHints().testFlag(QPainter::Antialiasing); isAA = settings.value("antialiasing", isAA).toBool(); m_editorView->setRenderHint(QPainter::Antialiasing, isAA); m_editorScene->setFontAntialiased(isAA); m_optionsData.backupPeriod = settings.value("backupPeriod", m_optionsData.backupPeriod).toInt(); settings.beginGroup("GraphViz"); m_optionsData.graphvizPath = settings.value("path", m_optionsData.graphvizPath).toString(); m_optionsData.graphvizDefaultEngine = settings.value("defaultEngine", m_optionsData.graphvizDefaultEngine).toString(); settings.endGroup(); updateSceneOptions(); // IO settings.beginGroup("IO"); m_ioController->doReadSettings(settings); settings.endGroup(); // UI elements settings.beginGroup("UI/ItemProperties"); m_propertiesPanel->doReadSettings(settings); settings.endGroup(); settings.beginGroup("UI/ClassAttributes"); m_defaultsPanel->doReadSettings(settings); settings.endGroup(); } void CNodeEditorUIController::doWriteSettings(QSettings& settings) { // temp writeDefaultSceneSettings(); bool isAA = m_editorView->renderHints().testFlag(QPainter::Antialiasing); settings.setValue("antialiasing", isAA); int cacheRam = QPixmapCache::cacheLimit(); settings.setValue("cacheRam", cacheRam); settings.setValue("backupPeriod", m_optionsData.backupPeriod); // Graphviz settings.beginGroup("GraphViz"); settings.setValue("path", m_optionsData.graphvizPath); settings.setValue("defaultEngine", m_optionsData.graphvizDefaultEngine); settings.endGroup(); // IO settings.beginGroup("IO"); m_ioController->doWriteSettings(settings); settings.endGroup(); // UI elements settings.beginGroup("UI/ItemProperties"); m_propertiesPanel->doWriteSettings(settings); settings.endGroup(); settings.beginGroup("UI/ClassAttributes"); m_defaultsPanel->doWriteSettings(settings); settings.endGroup(); // custom topology of the current document settings.beginGroup("CustomFiles"); QString filename = QFileInfo(m_parent->getCurrentFileName()).fileName(); if (!filename.isEmpty()) { settings.beginGroup(filename); settings.beginGroup("UI/Topology"); m_connectionsPanel->doWriteSettings(settings); settings.endGroup(); settings.endGroup(); } settings.endGroup(); } void CNodeEditorUIController::readDefaultSceneSettings() { QSettings& settings = m_parent->getApplicationSettings(); settings.beginGroup("Scene/Defaults"); bool showNodeIds = settings.value("showNodeIds", true).toBool(); bool showEdgeIds = settings.value("showEdgeIds", true).toBool(); QColor bgColor = settings.value("background", m_editorScene->backgroundBrush().color()).value(); QPen gridPen = settings.value("grid.color", m_editorScene->getGridPen()).value(); int gridSize = settings.value("grid.size", m_editorScene->getGridSize()).toInt(); bool gridEnabled = settings.value("grid.enabled", m_editorScene->gridEnabled()).toBool(); bool gridSnap = settings.value("grid.snap", m_editorScene->gridSnapEnabled()).toBool(); settings.endGroup(); // workaround: always make the labels visible m_editorScene->setClassAttributeVisible(class_item, attr_label, true); m_editorScene->setClassAttributeVisible(class_node, attr_label, true); m_editorScene->setClassAttributeVisible(class_edge, attr_label, true); m_editorScene->setClassAttributeVisible(class_node, attr_id, showNodeIds); m_editorScene->setClassAttributeVisible(class_edge, attr_id, showEdgeIds); m_editorScene->setBackgroundBrush(bgColor); m_editorScene->setGridPen(gridPen); m_editorScene->setGridSize(gridSize); m_editorScene->enableGrid(gridEnabled); m_editorScene->enableGridSnap(gridSnap); updateFromActions(); } void CNodeEditorUIController::writeDefaultSceneSettings() { QSettings& settings = m_parent->getApplicationSettings(); settings.beginGroup("Scene/Defaults"); bool showNodeIds = m_editorScene->isClassAttributeVisible(class_node, attr_id); bool showEdgeIds = m_editorScene->isClassAttributeVisible(class_edge, attr_id); //bool showLabels = m_editorScene->isClassAttributeVisible("item", "label"); settings.setValue("showNodeIds", showNodeIds); settings.setValue("showEdgeIds", showEdgeIds); settings.setValue("background", m_editorScene->backgroundBrush().color()); settings.setValue("grid.color", m_editorScene->getGridPen()); settings.setValue("grid.size", m_editorScene->getGridSize()); settings.setValue("grid.enabled", m_editorScene->gridEnabled()); settings.setValue("grid.snap", m_editorScene->gridSnapEnabled()); settings.endGroup(); settings.sync(); } void CNodeEditorUIController::sceneOptions() { CSceneOptionsDialog dialog; #ifdef USE_GVGRAPH connect(&dialog, &CSceneOptionsDialog::testGraphviz, m_gvController, &CGVGraphLayoutUIController::runGraphvizTest); #endif if (dialog.exec(*m_editorScene, *m_editorView, m_optionsData)) { updateSceneOptions(); m_parent->writeSettings(); } } void CNodeEditorUIController::updateSceneOptions() { #ifdef USE_GVGRAPH if (m_gvController) { m_gvController->setPathToGraphviz(m_optionsData.graphvizPath); m_gvController->setDefaultEngine(m_optionsData.graphvizDefaultEngine); } #endif if (m_optionsData.backupPeriod > 0) { m_backupTimer.setInterval(m_optionsData.backupPeriod * 60000); m_backupTimer.start(); } else m_backupTimer.stop(); updateActions(); } void CNodeEditorUIController::updateActions() { if (m_editorScene) { gridAction->setChecked(m_editorScene->gridEnabled()); gridSnapAction->setChecked(m_editorScene->gridSnapEnabled()); m_actionShowNodeIds->setChecked(m_editorScene->isClassAttributeVisible(class_node, attr_id)); m_actionShowEdgeIds->setChecked(m_editorScene->isClassAttributeVisible(class_edge, attr_id)); } } void CNodeEditorUIController::updateFromActions() { if (m_editorScene) { m_editorScene->setClassAttributeVisible(class_node, attr_id, m_actionShowNodeIds->isChecked()); m_editorScene->setClassAttributeVisible(class_edge, attr_id, m_actionShowEdgeIds->isChecked()); } } void CNodeEditorUIController::onLayoutFinished() { m_editorScene->crop(); // make an option?? //m_editorView->fitToView(); } // zooming void CNodeEditorUIController::onZoomChanged(double currentZoom) { resetZoomAction2->setText(QString("%1%").arg((int)(currentZoom * 100))); fitZoomBackAction->setEnabled(m_editorView->getZoomBeforeFit() > 0); } void CNodeEditorUIController::zoom() { m_editorView->zoomBy(1.3); } void CNodeEditorUIController::unzoom() { m_editorView->zoomBy(1.0 / 1.3); } void CNodeEditorUIController::resetZoom() { m_editorView->zoomTo(1.0); } // other actions void CNodeEditorUIController::factorNodes() { CNodesFactorDialog dialog; if (dialog.exec(*m_editorScene) == QDialog::Accepted) m_editorScene->addUndoState(); else m_editorScene->revertUndoState(); } void CNodeEditorUIController::addNodePort() { CNode *node = dynamic_cast(m_editorScene->getContextMenuTrigger()); if (!node) return; CNodePort *port = node->addPort(); if (!port) return; CNodePortEditorDialog dialog; if (dialog.exec(*port) == QDialog::Accepted) m_editorScene->addUndoState(); else delete port; } void CNodeEditorUIController::editNodePort() { CNodePort *port = dynamic_cast(m_editorScene->getContextMenuTrigger()); if (port) editNodePort(*port); } void CNodeEditorUIController::editNodePort(CNodePort &port) { CNodePortEditorDialog dialog; if (dialog.exec(port) == QDialog::Accepted) m_editorScene->addUndoState(); else m_editorScene->revertUndoState(); } void CNodeEditorUIController::find() { m_searchDialog->exec(*m_editorScene); } void CNodeEditorUIController::showNodeIds(bool on) { m_editorScene->setClassAttributeVisible(class_node, attr_id, on); m_editorScene->addUndoState(); } void CNodeEditorUIController::showEdgeIds(bool on) { m_editorScene->setClassAttributeVisible(class_edge, attr_id, on); m_editorScene->addUndoState(); } void CNodeEditorUIController::undo() { m_editorScene->undo(); updateFromActions(); } void CNodeEditorUIController::redo() { m_editorScene->redo(); updateFromActions(); } void CNodeEditorUIController::changeItemId() { auto sceneActions = dynamic_cast(m_editorScene->getActions()); int nodesCount = m_editorScene->getSelectedNodes().size(); int edgesCount = m_editorScene->getSelectedEdges().size(); if (nodesCount == 1 && edgesCount == 0 && sceneActions) { sceneActions->editNodeId(m_editorScene->getSelectedNodes().first()); return; } if (nodesCount == 0 && edgesCount == 1 && sceneActions) { sceneActions->editEdgeId(m_editorScene->getSelectedEdges().first()); return; } } qvge-0.6.3/src/commonui/CNodeEditorUIController.h000066400000000000000000000071571405165517400217330ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include #include #include #include #include class CMainWindow; class CNodeEditorScene; class CNodePort; class CEditorView; class IFileSerializer; class CNodeEditorUIController : public QObject { Q_OBJECT public: CNodeEditorUIController(CMainWindow *parent); virtual ~CNodeEditorUIController(); QSettings& getApplicationSettings() const; void doReadSettings(QSettings& settings); void doWriteSettings(QSettings& settings); bool loadFromFile(const QString &format, const QString &fileName, QString* lastError); bool saveToFile(const QString &format, const QString &fileName, QString* lastError); // callbacks void onNewDocumentCreated(); void onDocumentLoaded(const QString &fileName); // protected API protected: CNodeEditorScene* scene() { return m_editorScene; } private Q_SLOTS: // tbd: move to export controller void exportFile(); void exportPDF(); void exportSVG(); void exportDOT(); bool importCSV(const QString &fileName, QString* lastError); void doBackup(); void onNavigatorShown(); void onSelectionChanged(); void onSceneChanged(); void onSceneHint(const QString& text); void onSceneStatusChanged(int status); void onSceneDoubleClicked(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem); void sceneEditMode(QAction*); void onEditModeChanged(int mode); void onZoomChanged(double currentZoom); void zoom(); void unzoom(); void resetZoom(); void sceneOptions(); void showNodeIds(bool on); void showEdgeIds(bool on); void undo(); void redo(); void changeItemId(); void addNodePort(); void editNodePort(); void factorNodes(); void find(); void onLayoutFinished(); private: void createMenus(); void createPanels(); void createNavigator(); void readDefaultSceneSettings(); void writeDefaultSceneSettings(); void updateSceneOptions(); void updateActions(); void updateFromActions(); void editNodePort(CNodePort &port); private: CMainWindow *m_parent = nullptr; CNodeEditorScene *m_editorScene = nullptr; CEditorView *m_editorView = nullptr; class QSint::Slider2d *m_sliderView = nullptr; QLabel *m_statusLabel = nullptr; QMenu *m_viewMenu = nullptr; QAction *findAction = nullptr; QActionGroup *m_editModesGroup; QAction *modeDefaultAction; QAction *modeNodesAction; QAction *modeTransformAction; QAction *modeFactorAction; QAction *zoomAction; QAction *unzoomAction; QAction *resetZoomAction; QAction *resetZoomAction2; QAction *fitZoomAction; QAction *fitZoomSelectedAction; QAction *fitZoomBackAction; QAction *gridAction; QAction *gridSnapAction; QAction *actionShowLabels; QAction *m_actionShowNodeIds; QAction *m_actionShowEdgeIds; OptionsData m_optionsData; QTimer m_backupTimer; #ifdef USE_OGDF class COGDFLayoutUIController *m_ogdfController = nullptr; #endif #ifdef USE_GVGRAPH class CGVGraphLayoutUIController *m_gvController = nullptr; #endif class CColorSchemesUIController *m_schemesController = nullptr; class CImportExportUIController *m_ioController = nullptr; class CNodeEdgePropertiesUI *m_propertiesPanel = nullptr; class CCommutationTable *m_connectionsPanel = nullptr; class CClassAttributesEditorUI *m_defaultsPanel = nullptr; class CQuickHelpUI *m_quickHelpPanel = nullptr; class CSearchDialog *m_searchDialog = nullptr; }; qvge-0.6.3/src/commonui/CNodePortEditorDialog.cpp000066400000000000000000000041711405165517400217420ustar00rootroot00000000000000#include "CNodePortEditorDialog.h" #include "ui_CNodePortEditorDialog.h" #include #include CNodePortEditorDialog::CNodePortEditorDialog(): ui(new Ui::CNodePortEditorDialog) { ui->setupUi(this); ui->Anchor->addItem(tr("Left"), Qt::AlignLeft + Qt::AlignVCenter); ui->Anchor->addItem(tr("Top-Left"), Qt::AlignTop + Qt::AlignLeft); ui->Anchor->addItem(tr("Top"), Qt::AlignTop + Qt::AlignHCenter); ui->Anchor->addItem(tr("Top-Right"), Qt::AlignTop + Qt::AlignRight); ui->Anchor->addItem(tr("Right"), Qt::AlignRight + Qt::AlignVCenter); ui->Anchor->addItem(tr("Bottom-Right"), Qt::AlignBottom + Qt::AlignRight); ui->Anchor->addItem(tr("Bottom"), Qt::AlignBottom + Qt::AlignHCenter); ui->Anchor->addItem(tr("Bottom-Left"), Qt::AlignBottom + Qt::AlignLeft); ui->Anchor->addItem(tr("Center"), Qt::AlignCenter); } CNodePortEditorDialog::~CNodePortEditorDialog() { } int CNodePortEditorDialog::exec(CNodePort &port) { m_port = nullptr; m_node = nullptr; ui->PortId->setText(port.getId()); int align = port.getAlign(); int alignIndex = ui->Anchor->findData(align); if (alignIndex < 0) alignIndex = 0; ui->Anchor->setCurrentIndex(alignIndex); ui->OffsetX->setValue(port.getX()); ui->OffsetY->setValue(port.getY()); ui->Color->setColor(port.getColor()); // set here in order to make interactive during editing m_port = &port; m_node = port.getNode(); int result = QDialog::exec(); if (result == QDialog::Accepted) { m_node->renamePort(m_port->getId(), ui->PortId->text().toLocal8Bit()); } return result; } void CNodePortEditorDialog::doUpdate() { if (m_port && m_node) { int align = ui->Anchor->currentData().toInt(); int xv = ui->OffsetX->value(); int yv = ui->OffsetY->value(); m_node->movePort(m_port->getId(), align, xv, yv); m_port->setColor(ui->Color->color()); } } void CNodePortEditorDialog::on_Color_activated(const QColor &) { doUpdate(); } void CNodePortEditorDialog::on_Anchor_currentIndexChanged(int) { doUpdate(); } void CNodePortEditorDialog::on_OffsetX_valueChanged(int) { doUpdate(); } void CNodePortEditorDialog::on_OffsetY_valueChanged(int) { doUpdate(); } qvge-0.6.3/src/commonui/CNodePortEditorDialog.h000066400000000000000000000010771405165517400214110ustar00rootroot00000000000000#pragma once #include namespace Ui { class CNodePortEditorDialog; } class CNode; class CNodePort; class CNodePortEditorDialog : public QDialog { Q_OBJECT public: CNodePortEditorDialog(); ~CNodePortEditorDialog(); int exec(CNodePort &port); private Q_SLOTS: void on_Anchor_currentIndexChanged(int index); void on_OffsetX_valueChanged(int v); void on_OffsetY_valueChanged(int v); void on_Color_activated(const QColor &color); private: void doUpdate(); Ui::CNodePortEditorDialog *ui; CNodePort *m_port = nullptr; CNode *m_node = nullptr; }; qvge-0.6.3/src/commonui/CNodePortEditorDialog.ui000066400000000000000000000111101405165517400215640ustar00rootroot00000000000000 CNodePortEditorDialog 0 0 319 132 Edit Node Port true Anchor Id Y-offset -1000 1000 10 X-offset Color -1000 1000 10 0 0 ... QToolButton::InstantPopup Qt::ToolButtonTextBesideIcon Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok QSint::ColorButton QToolButton
colorbutton.h
PortId Anchor Color OffsetX OffsetY buttonBox accepted() CNodePortEditorDialog accept() 228 132 157 153 buttonBox rejected() CNodePortEditorDialog reject() 296 138 286 153
qvge-0.6.3/src/commonui/CNodesFactorDialog.cpp000066400000000000000000000025711405165517400212520ustar00rootroot00000000000000#include "CNodesFactorDialog.h" #include "ui_CNodesFactorDialog.h" #include #include CNodesFactorDialog::CNodesFactorDialog(): ui(new Ui::CNodesFactorDialog) { ui->setupUi(this); } CNodesFactorDialog::~CNodesFactorDialog() { } int CNodesFactorDialog::exec(CNodeEditorScene& scene) { m_scene = &scene; auto nodes = scene.getSelectedNodes(); if (nodes.isEmpty()) return QDialog::Rejected; ui->FactorX->setValue(100); ui->FactorY->setValue(100); m_sourceMap.clear(); QRectF boundingRect; for (auto node : nodes) { m_sourceMap[node] = node->pos(); boundingRect = boundingRect.united(QRectF(node->pos(), QSizeF(1,1))); } m_sourceCenter = boundingRect.center(); return QDialog::exec(); } void CNodesFactorDialog::on_FactorX_valueChanged(int v) { double dv = (double)v / 100.0; for (auto it = m_sourceMap.begin(); it != m_sourceMap.end(); ++it) { double dx = it.value().x() - m_sourceCenter.x(); dx *= dv; double newx = dx + m_sourceCenter.x(); it.key()->setPos(newx, it.key()->pos().y()); } } void CNodesFactorDialog::on_FactorY_valueChanged(int v) { double dv = (double)v / 100.0; for (auto it = m_sourceMap.begin(); it != m_sourceMap.end(); ++it) { double dy = it.value().y() - m_sourceCenter.y(); dy *= dv; double newy = dy + m_sourceCenter.y(); it.key()->setPos(it.key()->pos().x(), newy); } } qvge-0.6.3/src/commonui/CNodesFactorDialog.h000066400000000000000000000010421405165517400207070ustar00rootroot00000000000000#pragma once #include #include #include #include namespace Ui { class CNodesFactorDialog; } class CNode; class CNodeEditorScene; class CNodesFactorDialog : public QDialog { Q_OBJECT public: CNodesFactorDialog(); ~CNodesFactorDialog(); int exec(CNodeEditorScene& scene); private Q_SLOTS: void on_FactorX_valueChanged(int v); void on_FactorY_valueChanged(int v); private: Ui::CNodesFactorDialog *ui; QMap m_sourceMap; QPointF m_sourceCenter; CNodeEditorScene *m_scene; }; qvge-0.6.3/src/commonui/CNodesFactorDialog.ui000066400000000000000000000063101405165517400211000ustar00rootroot00000000000000 CNodesFactorDialog 0 0 241 106 Factor Nodes true Y-factor: X-factor: % 1 10000 10 100 % 1 10000 10 100 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() CNodesFactorDialog accept() 228 132 157 153 buttonBox rejected() CNodesFactorDialog reject() 296 138 286 153 qvge-0.6.3/src/commonui/CPropertyEditorUIBase.cpp000066400000000000000000000037571405165517400217560ustar00rootroot00000000000000#include "CPropertyEditorUIBase.h" CPropertyEditorUIBase::CPropertyEditorUIBase(QWidget * parent) : QtTreePropertyBrowser(parent) { setResizeMode(Interactive); } CPropertyEditorUIBase::~CPropertyEditorUIBase() { } QtBrowserItem* CPropertyEditorUIBase::selectItemByName(const QString& name) { QList items = topLevelItems(); for (auto item : items) { if (item->property()->propertyName() == name) { setCurrentItem(item); return item; } } return NULL; } QtProperty* CPropertyEditorUIBase::getCurrentTopProperty() const { auto item = currentItem(); if (!item) return NULL; while (item->parent()) item = item->parent(); return item->property(); } QString CPropertyEditorUIBase::getCurrentTopPropertyName() const { QtProperty *prop = getCurrentTopProperty(); if (prop) return prop->propertyName(); else return ""; } QVariant CPropertyEditorUIBase::getCurrentTopPropertyValue() const { QtVariantProperty* vprop = dynamic_cast(getCurrentTopProperty()); if (vprop) return vprop->value(); else return QVariant(); } int CPropertyEditorUIBase::getCurrentTopPropertyValueType() const { QtVariantProperty* vprop = dynamic_cast(getCurrentTopProperty()); if (vprop) return vprop->valueType(); else return -1; } QVariant CPropertyEditorUIBase::getCurrentPropertyValue() const { auto item = currentItem(); if (item) { QtVariantProperty* vprop = dynamic_cast(item->property()); if (vprop) return vprop->value(); } return QVariant(); } int CPropertyEditorUIBase::getCurrentPropertyValueType() const { auto item = currentItem(); if (item) { QtVariantProperty* vprop = dynamic_cast(item->property()); if (vprop) return vprop->valueType(); } return QVariant().type(); } void CPropertyEditorUIBase::updateTooltip(QtVariantProperty* prop) { if (prop) prop->setToolTip(QString("%2
[%1]").arg(prop->value().typeName()).arg(prop->valueText())); } qvge-0.6.3/src/commonui/CPropertyEditorUIBase.h000066400000000000000000000011641405165517400214110ustar00rootroot00000000000000#pragma once #include #include class CPropertyEditorUIBase : public QtTreePropertyBrowser { Q_OBJECT public: CPropertyEditorUIBase(QWidget *parent = Q_NULLPTR); virtual ~CPropertyEditorUIBase(); QtBrowserItem* selectItemByName(const QString& name); QtProperty* getCurrentTopProperty() const; QString getCurrentTopPropertyName() const; QVariant getCurrentTopPropertyValue() const; int getCurrentTopPropertyValueType() const; QVariant getCurrentPropertyValue() const; int getCurrentPropertyValueType() const; virtual void updateTooltip(QtVariantProperty* prop); }; qvge-0.6.3/src/commonui/CQuickHelpUI.cpp000066400000000000000000000010641405165517400200420ustar00rootroot00000000000000#include "CQuickHelpUI.h" #include "ui_CQuickHelpUI.h" #include #include CQuickHelpUI::CQuickHelpUI(QWidget *parent): QWidget(parent), ui(new Ui::CQuickHelpUI) { ui->setupUi(this); //QStringList sl; //sl << QApplication::applicationDirPath() + "/../lang/en"; //ui->Viewer->setSearchPaths(sl); //ui->Viewer->setSource(QUrl("help.htm")); QFile file(":/Help/Mini_EN"); if (file.open(QFile::ReadOnly | QFile::Text)) { QTextStream stream(&file); ui->Viewer->setHtml(stream.readAll()); } } CQuickHelpUI::~CQuickHelpUI() { } qvge-0.6.3/src/commonui/CQuickHelpUI.h000066400000000000000000000003361405165517400175100ustar00rootroot00000000000000#pragma once #include namespace Ui { class CQuickHelpUI; } class CQuickHelpUI : public QWidget { Q_OBJECT public: CQuickHelpUI(QWidget *parent = 0); ~CQuickHelpUI(); private: Ui::CQuickHelpUI *ui; }; qvge-0.6.3/src/commonui/CQuickHelpUI.ui000066400000000000000000000014461405165517400177010ustar00rootroot00000000000000 CQuickHelpUI 0 0 400 300 Form 0 0 0 0 qvge-0.6.3/src/commonui/CSceneMenuUIController.cpp000066400000000000000000000063261405165517400221110ustar00rootroot00000000000000#include "CSceneMenuUIController.h" #include #include #include #include #include #include #include #include CSceneMenuUIController::CSceneMenuUIController(QObject *parent) : QObject(parent) { } CSceneMenuUIController::~CSceneMenuUIController() { } bool CSceneMenuUIController::exec(CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent *contextMenuEvent) { m_scene = dynamic_cast(scene); m_scene->setPastePosition(contextMenuEvent->scenePos()); QMenu menu; fillMenu(menu, scene, triggerItem, contextMenuEvent); Q_EMIT onContextMenu(menu); // execute menu.exec(contextMenuEvent->screenPos()); m_scene->setPastePosition(QPointF()); return false; } void CSceneMenuUIController::fillMenu(QMenu &menu, CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent* /*contextMenuEvent*/) { auto sceneActions = scene->getActions(); auto nodeScene = m_scene; int nodesCount = nodeScene->getSelectedNodes().size(); bool nodesSelected = (nodesCount > 0); int edgesCount = nodeScene->getSelectedEdges().size(); bool edgesSelected = (edgesCount > 0); // add default actions QAction *changeIdAction = menu.addAction(tr("Change Id..."), parent(), SLOT(changeItemId())); changeIdAction->setEnabled((nodesCount + edgesCount) == 1); menu.addSeparator(); menu.addAction(scene->actions()->cutAction); menu.addAction(scene->actions()->copyAction); menu.addAction(scene->actions()->pasteAction); menu.addAction(scene->actions()->delAction); // add default node actions menu.addSeparator(); QAction *linkAction = menu.addAction(tr("Link"), sceneActions, SLOT(onActionLink())); linkAction->setEnabled(nodesCount > 1); QAction *unlinkAction = menu.addAction(tr("Unlink"), sceneActions, SLOT(onActionUnlink())); unlinkAction->setEnabled(nodesSelected); QAction *nodeColorAction = menu.addAction(tr("Node(s) Color..."), sceneActions, SLOT(onActionNodeColor())); nodeColorAction->setEnabled(nodesSelected); //QAction *factorAction = menu.addAction(tr("Factor Nodes..."), parent(), SLOT(factorNodes())); //factorAction->setEnabled(nodesCount > 1); menu.addSeparator(); QAction *addPortAction = menu.addAction(tr("Add Port..."), parent(), SLOT(addNodePort())); addPortAction->setEnabled(nodesCount == 1); QAction *editPortAction = menu.addAction(tr("Edit Port..."), parent(), SLOT(editNodePort())); editPortAction->setEnabled(dynamic_cast(triggerItem)); // add default edge actions menu.addSeparator(); QAction *edgeColorAction = menu.addAction(tr("Edge(s) Color..."), sceneActions, SLOT(onActionEdgeColor())); edgeColorAction->setEnabled(edgesSelected); QMenu *arrowsMenu = menu.addMenu(tr("Direction")); arrowsMenu->setEnabled(edgesSelected); arrowsMenu->addAction(tr("Directed"), sceneActions, SLOT(onActionEdgeDirected())); arrowsMenu->addAction(tr("Mutual"), sceneActions, SLOT(onActionEdgeMutual())); arrowsMenu->addAction(tr("None"), sceneActions, SLOT(onActionEdgeUndirected())); arrowsMenu->addSeparator(); arrowsMenu->addAction(tr("Reverse"), sceneActions, SLOT(onActionEdgeReverse())); } qvge-0.6.3/src/commonui/CSceneMenuUIController.h000066400000000000000000000014121405165517400215450ustar00rootroot00000000000000#pragma once #include #include #include class CNodeEditorScene; class CSceneMenuUIController : public QObject, public ISceneMenuController { Q_OBJECT public: CSceneMenuUIController(QObject *parent = nullptr); virtual ~CSceneMenuUIController(); // called before \a menu is about to show. virtual void fillMenu(QMenu &menu, CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent *contextMenuEvent); // reimp: ISceneMenuController virtual bool exec(CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent *contextMenuEvent); Q_SIGNALS: // emitted before \a menu is about to show. void onContextMenu(QMenu &menu); private: CNodeEditorScene* m_scene = nullptr; }; qvge-0.6.3/src/commonui/CSceneOptionsDialog.cpp000066400000000000000000000052111405165517400214460ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include "CSceneOptionsDialog.h" #include "ui_CSceneOptionsDialog.h" CSceneOptionsDialog::CSceneOptionsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CSceneOptionsDialog) { ui->setupUi(this); ui->BackgroundColor->setColorScheme(QSint::OpenOfficeColors()); ui->GridColor->setColorScheme(QSint::OpenOfficeColors()); } CSceneOptionsDialog::~CSceneOptionsDialog() { delete ui; } int CSceneOptionsDialog::exec(CEditorScene &scene, CEditorView &view, OptionsData &data) { ui->BackgroundColor->setColor(scene.backgroundBrush().color()); QPen gridPen = scene.getGridPen(); ui->GridColor->setColor(gridPen.color()); ui->GridSize->setValue(scene.getGridSize()); ui->GridVisible->setChecked(scene.gridEnabled()); ui->GridSnap->setChecked(scene.gridSnapEnabled()); ui->Antialiasing->setChecked(view.renderHints().testFlag(QPainter::Antialiasing)); ui->CacheSlider->setValue(QPixmapCache::cacheLimit() / 1024); quint64 ram = CPlatformServices::GetTotalRAMBytes() / (1024 * 1024); // mb ram /= 2; // 50% ui->CacheSlider->setMaximum((int)ram); ui->CacheSlider->setUnitText(tr("MB")); ui->EnableBackups->setChecked(data.backupPeriod > 0); ui->BackupPeriod->setValue(data.backupPeriod); #ifdef USE_GVGRAPH ui->ExtraSection->setVisible(true); ui->GraphvizPath->setObjectsToPick(QSint::PathPicker::PF_EXISTING_DIR); ui->GraphvizPath->setCurrentPath(data.graphvizPath); ui->GraphvizDefaultEngine->setCurrentText(data.graphvizDefaultEngine); #else ui->ExtraSection->setVisible(false); #endif if (QDialog::exec() == QDialog::Rejected) return QDialog::Rejected; scene.setBackgroundBrush(ui->BackgroundColor->color()); gridPen.setColor(ui->GridColor->color()); scene.setGridPen(gridPen); scene.setGridSize(ui->GridSize->value()); scene.enableGrid(ui->GridVisible->isChecked()); scene.enableGridSnap(ui->GridSnap->isChecked()); bool isAA = ui->Antialiasing->isChecked(); view.setRenderHint(QPainter::Antialiasing, isAA); scene.setFontAntialiased(isAA); QPixmapCache::setCacheLimit(ui->CacheSlider->value() * 1024); data.backupPeriod = ui->EnableBackups->isChecked() ? ui->BackupPeriod->value() : 0; #ifdef USE_GVGRAPH data.graphvizPath = ui->GraphvizPath->currentPath(); data.graphvizDefaultEngine = ui->GraphvizDefaultEngine->currentText(); #endif return QDialog::Accepted; } void CSceneOptionsDialog::on_GraphvizTest_clicked() { Q_EMIT testGraphviz(ui->GraphvizPath->currentPath()); } qvge-0.6.3/src/commonui/CSceneOptionsDialog.h000066400000000000000000000016471405165517400211240ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CSCENEOPTIONSDIALOG_H #define CSCENEOPTIONSDIALOG_H #include #include #include namespace Ui { class CSceneOptionsDialog; } struct OptionsData { int backupPeriod = 10; QString graphvizPath; //QStringList graphvizEngines; QString graphvizDefaultEngine; }; class CSceneOptionsDialog : public QDialog { Q_OBJECT public: explicit CSceneOptionsDialog(QWidget *parent = 0); ~CSceneOptionsDialog(); public Q_SLOTS: virtual int exec(CEditorScene &scene, CEditorView &view, OptionsData &data); Q_SIGNALS: void testGraphviz(const QString &graphvizPath); private Q_SLOTS: void on_GraphvizTest_clicked(); private: Ui::CSceneOptionsDialog *ui; }; #endif // CSCENEOPTIONSDIALOG_H qvge-0.6.3/src/commonui/CSceneOptionsDialog.ui000066400000000000000000000342361405165517400213120ustar00rootroot00000000000000 CSceneOptionsDialog 0 0 423 546 Scene Options Scene true QFormLayout::FieldsStayAtSizeHint 120 0 Background color 0 0 100 0 ... QToolButton::InstantPopup Qt::ToolButtonTextBesideIcon Qt::NoArrow Grid true QFormLayout::FieldsStayAtSizeHint 120 0 Size 0 0 100 0 1 40 px 120 0 Color 0 0 100 0 ... QToolButton::InstantPopup Qt::ToolButtonTextBesideIcon Qt::NoArrow Snap to grid Show grid Performance true 120 0 100 16777215 Painting 0 0 Enable antialiasing 120 0 100 16777215 Cache 1000 10 10 Qt::Horizontal Data security true Back up the data every true 0 0 min 5 200 5 120 0 100 16777215 Extra tools true 120 0 Path to GraphViz binaries false dot neato fdp sfdp twopi circo 120 0 Default layout engine Run dot... 120 0 Test GraphViz execution Qt::Vertical 20 40 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok QSint::ColorButton QToolButton
colorbutton.h
QSint::SpinSlider QSlider
spinslider.h
QSint::PathPicker QLineEdit
pathpicker.h
BackgroundColor GridSize GridColor GridVisible GridSnap Antialiasing CacheSlider EnableBackups BackupPeriod GraphvizPath GraphvizDefaultEngine buttonBox accepted() CSceneOptionsDialog accept() 248 254 157 274 buttonBox rejected() CSceneOptionsDialog reject() 316 260 286 274
qvge-0.6.3/src/commonui/CSearchDialog.cpp000066400000000000000000000072741405165517400202550ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CSearchDialog.h" #include "ui_CSearchDialog.h" #include #include #include #include #include #include #include #include static bool look(const QString& where, const QString& what, Qt::CaseSensitivity sens, bool word) { if (word) return (where.compare(what, sens) == 0); else return where.contains(what, sens); } CSearchDialog::CSearchDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CSearchDialog) { ui->setupUi(this); connect(ui->Text, &QLineEdit::textChanged, this, &CSearchDialog::updateButtons); connect(ui->NamesScope, &QCheckBox::toggled, this, &CSearchDialog::updateButtons); connect(ui->AttrNamesScope, &QCheckBox::toggled, this, &CSearchDialog::updateButtons); connect(ui->AttrValuesScope, &QCheckBox::toggled, this, &CSearchDialog::updateButtons); } CSearchDialog::~CSearchDialog() { delete ui; } void CSearchDialog::exec(CNodeEditorScene &scene) { m_scene = &scene; ui->Text->setFocus(); ui->Text->selectAll(); updateButtons(); show(); } void CSearchDialog::updateButtons() { bool isOk = false; isOk |= ui->NamesScope->isChecked(); isOk |= ui->AttrNamesScope->isChecked(); isOk |= ui->AttrValuesScope->isChecked(); isOk &= !ui->Text->text().isEmpty(); ui->Find->setEnabled(isOk); } void CSearchDialog::on_Find_clicked() { ui->Results->setUpdatesEnabled(false); ui->Results->clear(); auto items = ui->EdgesOnly->isChecked() ? m_scene->getItems() : ui->NodesOnly->isChecked() ? m_scene->getItems() : m_scene->getItems(); bool lookNames = ui->NamesScope->isChecked(); bool lookAttrNames = ui->AttrNamesScope->isChecked(); bool lookAttrs = ui->AttrValuesScope->isChecked(); QString text = ui->Text->text(); Qt::CaseSensitivity sens = ui->CaseSense->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive; bool word = ui->WholeWords->isChecked(); for (const CItem* item : items) { QString textToShow; if (lookNames) { QString id = item->getId(); if (look(id, text, sens, word)) { textToShow = "ID:" + id; } } if (lookAttrNames || lookAttrs) { const auto& attrMap = item->getLocalAttributes(); for (auto it = attrMap.constBegin(); it != attrMap.constEnd(); it++) { QString key(it.key()); QString val(it.value().toString()); if ( (lookAttrNames && look(key, text, sens, word)) || (lookAttrs && look(val, text, sens, word)) ) { if (textToShow.size()) textToShow += " | "; textToShow += key + ": " + val; } } } if (textToShow.isEmpty()) continue; QStringList res; res << item->typeId() << item->getId() << textToShow; auto *ritem = new QTreeWidgetItem(res); bool isNode = (dynamic_cast(item) != NULL); ritem->setData(0, Qt::UserRole, isNode); ui->Results->addTopLevelItem(ritem); } ui->Results->setUpdatesEnabled(true); } void CSearchDialog::on_Results_itemSelectionChanged() { auto ritems = ui->Results->selectedItems(); QList selected; for (const auto* ritem : ritems) { QString id = ritem->text(1); bool isNode = ritem->data(0, Qt::UserRole).toBool(); if (isNode) { auto itemList = m_scene->getItemsById(id); if (!itemList.isEmpty()) selected << itemList.first(); } else { auto itemList = m_scene->getItemsById(id); if (!itemList.isEmpty()) selected << itemList.first(); } } m_scene->selectItems(selected); m_scene->ensureSelectionVisible(); } qvge-0.6.3/src/commonui/CSearchDialog.h000066400000000000000000000011771405165517400177160ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include class CNodeEditorScene; namespace Ui { class CSearchDialog; } class CSearchDialog : public QDialog { Q_OBJECT public: explicit CSearchDialog(QWidget *parent = 0); ~CSearchDialog(); public Q_SLOTS: void exec(CNodeEditorScene &scene); private Q_SLOTS: void updateButtons(); void on_Find_clicked(); void on_Results_itemSelectionChanged(); private: Ui::CSearchDialog *ui; CNodeEditorScene *m_scene = 0; }; qvge-0.6.3/src/commonui/CSearchDialog.ui000066400000000000000000000172151405165517400201040ustar00rootroot00000000000000 CSearchDialog 0 0 470 407 427 0 Search Items 0 0 Scope true Object names true Attribute names true Attribute values true 0 0 Objects to search true Any true Edges only Nodes only 0 0 Search flags true Case sensitive Whole words only Qt::Vertical 20 16 Text to search true Input text to find... true Find... true 0 0 Results true 0 0 false true QAbstractItemView::ExtendedSelection true true true true Type ID Result Text Find AnyObject EdgesOnly NodesOnly NamesScope AttrNamesScope AttrValuesScope CaseSense WholeWords Results Text returnPressed() Find click() 191 40 390 46 qvge-0.6.3/src/commonui/Icons/000077500000000000000000000000001405165517400161625ustar00rootroot00000000000000qvge-0.6.3/src/commonui/Icons/Action-Crop.png000066400000000000000000000020241405165517400210040ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYsv$ tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qKIDATHOh\UVfL\&RmŶEbuQ7]T%Ȼ7n$`UB2lXJޝ f"tUEJ+ dтĉV"X^fq75 dR[ww=O( qOO;J`."Tmz8x Z{VDslSUD8X[DFU9huFDv48 @U^EಪZ`^+a P2l.9zDkm|:11q{$˲^`e[7\-b;[$If/>$"JvQU} 8 NUc@E䂪rȲ$I~npέ*o `(,&IrSjp5Q{J>^Rin(ccc3̿!B~63ιC@W;nْe>UXVog,@U * `ii0 Z9 Lh#@V{; ,8Bު#\Xc o~IENDB`qvge-0.6.3/src/commonui/Icons/Action-Link.png000066400000000000000000000007221405165517400210010ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYsv$ tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q IDATH͖1R0EO@-֣3P0C҅+s%24 ɒx/%ZJ9%1sn[tBxAYB^PsX z;b7^Dv%:.mۻacԻ1 @U_EҘ뺯QlTs$@>Wc5LKċ &k/*孎JNj 7jY EKE}Ѳ$/ v}Z_6*9IENDB`qvge-0.6.3/src/commonui/Icons/Action-Unlink.png000066400000000000000000000007161405165517400213470ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATHՕMN0!>knߠlʪ!vuX; Ij+[{?y,B1F=샣 dIMv:5 Lu}+" yhf-C;KKVUuQ@3S+yPէm۾I9LUz>FP%{y\USJS,?.f xI)XLuY]z+rN?.P[yI^L\IENDB`qvge-0.6.3/src/commonui/Icons/Direction-Both.png000066400000000000000000000006111405165517400215000ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs`p tEXtSoftwarewww.inkscape.org<IDATH푽J@L`MB)7F7Iv|DA$@VTd]=&&}(XeY^քs%I親bs @8]0,2@Jx`޳Ӷ3ƜO'W?63A @Cic+)eu-֚~ CZZK`(VG~~BWy?(811;,N IENDB`qvge-0.6.3/src/commonui/Icons/Direction-None.png000066400000000000000000000006551405165517400215130ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs`p tEXtSoftwarewww.inkscape.org<*IDATH핻M@@߮ ].8 C;Ob"$*p t>$DyO3;  H$*9n-,+&~faۼ!%'U՜k*"syaպuJE90n0"9mYyAǧsAd "'}KϾ^1P!^(V CQ8EU3.!/ACvG`w r8tA#h|%p &Z?n:>vt1r9IENDB`qvge-0.6.3/src/commonui/Icons/Direction-One.png000066400000000000000000000004401405165517400213250ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs!!tEXtSoftwarewww.inkscape.org<IDATH!0-pMP>nCp5 K Z_*w1VU^f~QM @n+ 16|38t]Ԁ!r@1}")w=iڋs$($GIENDB`qvge-0.6.3/src/commonui/Icons/Edge-Direct.png000066400000000000000000000007631405165517400207520ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q*IDATH핻M@@߮ ].8 C;Ob"$*p t>$DyO3;  H$*9n-,+&~faۼ!%'U՜k*"syaպuJE90n0"9mYyAǧsAd "'}KϾ^1P!^(V CQ8EU3.!/ACvG`w r8tA#h|%p &Z?n:>vt1r9IENDB`qvge-0.6.3/src/commonui/Icons/Edge-Polyline.png000066400000000000000000000007601405165517400213300ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q'IDATH픱J1ɆEc+AA| mlN8@T)[-F;E\bw.# ]Mfd uzN?1Ƭz7DdMD:;EdFUR=4=8Ex|~pνyVۢ#ޟFcLmb@k>#QTѳ.5oLg2>7Z 4m|(I*sHDDz,/R9  Ni>dYཿmBX=8^[(RO$m?U>utSt(#IENDB`qvge-0.6.3/src/commonui/Icons/Format-DOT.png000066400000000000000000000600351405165517400205500ustar00rootroot00000000000000PNG  IHDR>agAMA|Q cHRMR@}y<s,٩<9SbL!GĈ 3,F0+7T3IlpX"61"H _qW,d ėrIKst.ښAdp&+g]RәY2EE44432PuoJEzg`̉j- -b8o׿M]9La.+-%Mȧg3YះuAxEK i<:ŹPcu*@~(  ]o0 ~y*s7g%9%(3H*@C`-pn VH@ A1 jPA3hA'8΃Kn`Lg` a!2D!H҇ dAP B Byf*z: @]h ~L CUp΅ p%;56< ?" GxG iE>&2 oQEGlQP UFFuzQ7QcYG4G۠t]nB/o'Я1 xb"1I>Lf3bX} *QYvGĩp( &q x)&gsF|7:~@&h!$&B%pH$D.q#xx8F|K!\H$!i.%L";r3EHK-AFCbH$^RSIrdd 3Rx)-))zR#RsiSiT#Wd2Z2n2l2d)EBaQ6S))T UEMSPgeedɆfȞ!4--VJ;N g%K-sɵݖ{'OwO%)P_RRۥEK/+))U<د8䡔TtAiF쨜\|FyZbU)W9.Kw+YUEUOUjꂚZZZCu:C=^\G}VCEO#OE&^WOs^K[+\kV֔vv[]n>z^^u}XROm`m3h01$:fь|:kG23hbabhrT4ߴw3=3Y-s.q_vǂbgբ⃥%߲rJ*֪jAe0JOY6rvvtXLǎl&I']$NϝM.6.\ι"En2nnn[g=,=t٪E2}4\j5loDŽǞ~q=''Z^utv&vvEv >mяN9-{ LOgsΝK?7s>xOL n\x }N}g/]>uɫ,u[dS@u]7ot.<30tKn]p;;SwSyoEVqU\rW._Q[[]vMIrMM .\*TTϝ;kG;^YY2"7'TEKPRRPE`rtY]]{IӧI?{~5QTT_S\\/9./g~yTTTLSRl-@߿O../3Q${+=w#&&ڒЂBoŽuNݰ=r;w; oL^&+q}\A_%cyygz*ǟҟw./™;uhMBtfYds `"| ^rdb>tH\^gg4 h֙ H7I#H|;yֹZvT+K Ynvl߮-oyXpy 62n~~^HQl'|TU*ǜˎvVZnj9rk֬AbB\ 1l;dmڝ;oSalMzUT$#$] !qYH:|=-ϢEt6@Qw8·&tɏӬxq-#-m#KL.p<S Xd J7opyĽq+xc>&HP&߳FgEvʏ;h $ 򺝕t '8q.WYlb˖ضu-}?8lFwG?IY:9Àˋq^ʏ'+?̙3h (ݻ1jԨoѡ3^wu֤?:g^>ҥ 틵kb}y4fϬ,v$Pv>8(5}평 :8~*py~|/~Vq?#v7\^6Y'<2xs| ?u6:COpU[ƪ ?`'e.x1@X`p ם uyN΃ _qZ^:UF!G F%+['M3̛OX,SyN6lXP;bzk={=<'\iS 0TVgZm_?}4ĖsaM)d8qMOGH7suf]/Bt+@`fEG+W)NBWZʕN=y8ԑO0=8xm؜ѱ9xYCdJ>RXN!:'_㓖gߔKr9?M{?rJC_FD5ώs$=$]D >_ȧ/PBE˖-CHqpudW<򚀖|R~_sx~mXb"Yh/Srp(M/_N `}7D9s෥1]}'XJS7;[Ss*Ť)hթ+gq[ ӏr9$0pK`Su)݆  X柾EcL1v窞z{dǴo*$/OT^DXN |䳺#+|b9R…|+𳈗/A\<**J|$=59EqO;J+C;b۶yYxcW=_xoڴQ yS$[LvVe_q %(y* `aBaG.bkI-1|!~ dXG!{{4DMϮϵU{Y?3 ^n8|yeYx-ϟBd]gϗ:gD:}4,?!u"[s)f0@_]a)708"FGgoO&Ě?H3@ẍ́nV}7?}$xMwH>jWk~>,/ߪ {*DH|Y'$h%ȺȽGu\d'XVA_dk>>+G_~7 ް$̙@gp${mW,S묈|\r{:|~=_c{/e6m 6?`&ǧ8~_bg8jGt/ %z!ݩ^Sh[ H#|fFI8}?],U7nzLat[V9r`o[h<{ެ@bMo>oE@Ҩ@*188H/JCpb>VTjN903Ǩ5 3<-ZDs̱ {M<ٺ &wP+yNy$~gbRҴKpz"\K|ǫ8@Va*a1u@FL> g ׵83D"?jH!'OLJ ? h9Kزe ^ߋvQ3}𪻝hZ!x$Ù}ڡCl8}?_(nݺi/YI&Y_1ט~8 $KeO%3{i)N's4ǎc\Ę@^|WhyvP)[sSX@"" .yئdxABi%У5?sߺz8ęq[f{njZş5gp|ޓ6?i$-N|Q~}^~QE4 ÷ѽ^? 0@3'ώԄSV0}ix~i4?BI(hݹ:vfK9r8:vPk)!S -u]VI| Jwftk+w2X^/nܳ1'L qg_D;&[z鿿^oxE^\>}؂?6TƧG6/qI7@>!o2sCŎ.=E w~2W}QV/yN=O"L.bNxB:cO#5, K˰<>/ipTZqǎw6 7|,&X|;! Eptqaf% z-zth9Ow l°~Hݟ<|Vy 8S&y5F>!qGͰpoP[G*"V$}2mEMX} خbb8[+BZna, ؉M'x<*-~1-sn>Z{ GRIuJBr{v į9>w&4q/A7e'­`t]ߨzϩ|GgaU`O!z]{k[wE 8>S k6`)bggY:)ix}y,DЮ_(z߅;4;CgaX{2s󐘓|g)p;Rr;9 sp0%Qg2BO趡 $.]җat9Ś[%A^swA4>s嗃4Dߌ30q>^6^@P* {{==uc{ zR2cJ!Eq=HEuh@8{`M4 W|g.?I*ڞ0I_b %xvA! ?=r*>`gB&v%ebKB6|g˶P)sng-T` ]8Sp\5oѾ|w2+#LKƎզߕl݇=z`~KR΢~Kw=c%Ç㈊)H"4mT0T/|3g:`qb'0#!֘X $wR 'UMnLZf_&M D`P<}:BWmؐU8UPce8U*[ZQq@ cU+PEv>ܨPih9 h_=Uґlpw?=`dDς AA N ~D4o9Ub20L({Gk^!ѿXiIO6]'0b I'D\\`d*\/_#7u^=XS琫 źti4&O`L:ASaB^]EQQ((?Jl,A *SHı4l:;=1:tJwn %h6N޻5OyB"z4:K,MƄ [U+*׃F`+7i;5h@7rkcߜ ?"NO+gU7:Q) sU_K^7gh\JU!yH>#(b.N >g d,̈^)+9PUsյZ T*H!d"LlQXq<w&cdeU 7vioOǴun-޹ҫ4|{p pƣ7œ@HkYBBBt͝?ZKul=tT7xx%=ϖa%6Y:t&;!\O?R?ZsHk*gnϹG\>X|2F!ayHWα3Xm'&ώY|"0j!،B\Wo*!\G΅WZ8q0 {T|: IŒSl NkѸ 57bup׮0 oOCLFq-FтG~`&'$ea)L0 02VqZ?zQe{>?.$^*O-S vLDNy+w&Ro`o5SVd%U7R1.%K~ٹ pWa={\7.VD8luekN\CUHQl3O0Z&Mt落8_$ims6Kr g`f200RUOoL߇Éiy*IVW|IL`,\&bM۰#)in!-ShrQkJaklL:.㉫SP:1_๲HݮO k ^˛r8a@sxxQ-(CzX'8e`"ɀwr4=)=bt/`0:TgmK]_`lgָt[wmcӘ3o>6l߉RPR5Z*Z˵)* 0U7d!a*b"vB^Uת /+s}sc/Pkk^VBh50 O P)ܰ]5t) ;NK C:ڬ襈>6uY%\_Ɗb XP= '$;͚ &N r)ZHyyy2/Hk#U_*fJ._Ê1m A a836"1+%kp-T_T jըOƯh/c-۝ѣF=HvU@wM ZIJ9df9Li*w-ޚA3,P?x^7`tNzTF 0#+رG:ꃏG`VbagG 2zRsq2iORöpR1[lef$nݽYEV @v/ޜޜOc7'Rì0Lڑ+tl>^pj †@M` }okLpobSQYsY &9 ]_ݘGo)LƟ.GgLU.h"v">3[w( }l*:9DV !^.aP!po~R,UKs )eE[ Rb#H>w{N)V^wO{6np3&D1^cƴ98v&E,Od`Ϟ=X` CfcaX )!)q֮W{U Tc 4DlG_߅ɰ Bҝ0;e(j`Hy*!cqCɼ.@Ü$`{P(YpE ϬA5Ljb8L  jHϗ6Vv @0tS}"1r-^;vbإl 4fo,m9*r&'rg LWPn 3k(K p_,E R#lAH\@LM|*4!*/Eɳ\&⥛{c3G+"|17k7]яɋƚ B( 9RQ5KͶ8nxxK8N@cN=R1<"R*@d7ϐu"פ (F$6F٦^&F!˿rsX*N1}Q,[s"2U 2 3Q{^~k7gLC)L᳣0gvW"QY 7Qq |zc)޺]DKxzjl_e}snNك+_(Cxz~($Wf8"H䵼NuUR(<@3qi+OܴX "nB|ߓznu~uB .Gw!uibbbcf cݦ͈T7C XEmފHUQ+Œr6#g\GԲKIGa9=3xAOߚvMZRsᒙxf<*+u{OADH#I+  gL{^?&:)z bab%P\ 4RY p2``O=|g)=!8c0&mî857`F,QĎQwj?0_޳eذ Bf+7uX%lG*)~c޹9O ˫;w r^Th勡xx=nUX$K\0Ϫ#0#OS$9<æ; HT*H;g/Xw3#m3l6:@M,0 9I@X&*.ůCOjvۓ2/;axB|a3`):8,~Wp<1 FcrBOh8q$l";X^S*7 |pm)]މWPsPO 5 + \aVks$B~7yFb9b䵄33`0-)镈/ `X dHl-[ `h hg0p: &۷w!oF9/!I'2 5 iKVXt ֜.¼qp%+ozB@I9ɗ@f^>6܅9 a)0m|¤qa$U乫XX]Ig1t<#3f9ځWd\du=iU`q8 F^]pQlACwq!xPV/X~SCGsXv3 Qϻ|҈R>(*N Ť ǂk[KU(EaEd#Ym:7cpGpTEYTE\ <;K h8ﰵ5`(q,A"-pSrl~wNr [w]13r&䩡L(/ۀmgJp\}GԱ5:5[waP +-XC 8<ϩ^zڊYy=A]o*򢀄7cFVAbP8{ @ @܀fcA-VvDiIG\< 9HV`BO~6sNNӁexO#M_0FĔhg棰rבZ} Eܙ;yK0 `&:O8XY8~lN"? 0E'|w0fXj)~ݡ)~WvjxE l} λ(ZqWN @fe((g͞5&~_VjP}`-T{،3}x *;U(xM* I*Rz 1[r21C_@K ` ʝDDT/[/|{.{ݯLL<]w]+}E\5mMH<#g`tOeIVYSYESxun_(.^}p r qN=o۶Mw>vB\^t0{Ctq݀gex\V)2cE(h?6V. p^,P=)W !w"d2tw$čsڣM6hѢZm /, *Q=bOi-v"]Y j iBÕwFO簙o{C_*a!h2p:LEk'6`Z&X0K0Q}[ i[P7Ǭ](^Nzqˋp5<7y`Y8e8/`v;Gr5r^,60R(uV$a?!B:5|Nf,!^<9-;@Ѥ@MZik@tzBffqh+FG+Oq>| Ga=X޽7<<cY9a : ⁞;sOⳁ~x 5ot;S`񪝺j62zlA./M46EE9spd}0; pBmKxr/ZibvSI?Z# C[ni1Vh۶-lg>i?6j?6n*u{$AaĬK$%nێkiAn oqmD`8fmخTN, #F0Ue/[>xq7/RjmߴP} 9$fY،87`p\sf0fMs0A@RC}^gGhwZm |.GF%Xtʺ%[u;kga?ZތŧK4De&xm&:ُ=>{_?%̟?Ow>޲7ˋwͷ0i@ h8܀&uo Yf,XbanO$snf^#Bt]B@P5}R7N}'N =19'+iG>J^S# $A 'sRCXaM%5s>p3oj_o6eku6}%`{8M@›7or( AAÞFW0z1p$Z `,UlY"::Zgpp17jCV),L&mq姞"7CH( P;ţ9o>|U yt\PˌjXB3͔2 ~#xG?4&_ѥhƞI ƙ{ˋ_\v!g7@+, 2w= 'g)"%ɠptuxD`v)t"n'G7P)d>ڒN2\nqXy8svD8L۲##!q |1 b(?/~S5_6qK\^:PeaĴQ@*M|"< f @D'At^SZgUKo ?zd9ntrM' M,{X)Kτ3w_H. nzV,JoΆ#|㋧_脟?6~^/| x"x oDsUYA)9bL 8@Jun/8}ZW1*bX`P@79B.6w5ge e`~"}T@2esi!w[fǴzЪt`w$(Fm0ul޼T uOweW_O?ů_euVBn؆lg\ůߘع,Llx"A= (E'M}% A 8HCƤXD w؀9QYE# SVׁ%˺Vv=CѹK2o5y,":nCxݏLJЯxp)'^>x/=gMwn#l{ˋwr. s+8So; 0P\9FsxUxpC sEE\cN&=+:8s"Lف~\M5\ƹMzXTs" ^Sq 'z{Ka2'|'AWx+3E㿨u$O뀘vrτˋwfY[ :j-iaX6M9Liq^YSIEZ [pTw %E Bpɝ%KJ fRaP蜫@ς#yxG^SPcxp2.Q_x7׿nՐ & x 9.焇^ibM+@"/R!{v$IJkuej(JtvD!bM&$ t&\BkGF9pB<˼NPBYʵy?j$}E [㭆ШQ#RWw|ܰG(z?4??#{ؾN3.8½9Y0@x%3VuP/0 W.qhYE[Vl!}9g`J!Σl|g2L q'¸IaNݞc\¬: {ӶxOu1zh(@f}o*{yEs~{g?Q V;%8t䛀ofKΫ& TDt"n'8? n%K ӤL8:G-Co@iވE'΢Tr&䜠<¤ Q2x@aՐVͭڴn oGA[GǞVxF)xt29%]¶o#^GW +A @DKX`ZsR|0p-A%D6* dM2~VٰZC{c;7>R1C?:3=Y.pxMHwU@7 F )D?rs~ͅ.ɽW(8 55AO9SpqB@Debpq ,h빩Dlq*ok-!H 1g*ndVB>=4eM›g8~(NqU*e" !h(vV 會@3rH-ީK_U:[?y ? z?q;]5d{s$^*شqMDX+ +@={(qPXe 9 pK˩` ) IQ*U<7f XGbbI%s1FMx:fZ"tVWZ ([UJJ;13~7qSi1w5e1;rޖoڴ:٩K/<'"O~ WK.~.WXDVYCt*.f L]J[n!E0f.Wǚ,! bd]Ҹll6:<Υgep ""lː4aϹ9YiE( 6(Wif81G[FE2<-oǎ>zM?~R=+OK@BN{ì20$^!$xoaU"/A!#xōS=!#^\h1 !HY*&ht ,#MUd/hU" }^eb/<<{ +SymZNY&&(o-_ik">@E  u xN.6_HՑE.U"Z&3d;DŽiii)5|)o3=8g[DA'!I%T|Q` {hMLGd~.uTi'ZˊxHzHO n4:iM7@u5x >\T䋘0 E\U%vA$-2#[d'\ >LArY[tg6SX7/J{tmyXMX?+eUAA?~~7^i/9S'J=S6:` ~dF/\WBFN'FkPTH1 f6")) "{pEmBcHUg,&=#UqdX S[,WdڵS>رcZt̔x?g=_MU@;r\g?а18bȩn7:F8_ A"\ӷ%1P]ƙpP삓$!WwIwflgբiJ΂{zՐ (Z= )f.4Ϣx6 *Eݎ)K]u9$3f")f艈V j48|VŐ&<"d9nm(n#{3{=1/H {05B8]pg!$tc-z郗&A+(=$^~7'26ᱨZim^c`-=_@ߔfGV 7Y|ֺ{y%? gJ0&T2A!`*Ⱦ;,iΥ,҅p$\`>lGL<mDvd-*E^ 3o꠬/϶Qト嫵ܻ"`GZr%Of {)JgN- 4-=w`ɴ X'r};o<[׼gߎo( AD eWj6pK:(]MS 16! d"F{0E,pC&J*.YȻ+LuguWdˋ$yxp"hwr3bf^xn`*&D\rn_XJC/\D@wYN昂ܳ@@1(; Xʴ[~_x`g\J0ϴPe(JP uijMϛ*{ԩ*ۨLy7Ho~I[:XW_(D]Z;?e>no_:EZM3x+ڃ*C5NqTwOBB`'(A:F6V-ABQ&<̵[ qqTb ,f]?cLFtI8Τ\>bpl>>k)ڵk^={vf;p`)vcfϝⷁ0iSNK)R 8GnȳVMJ;pOB&PW5-VQ d㡣6 @h6-ܫ`J"# Xy^z8-Gq!Jӧc$bBpՏdxzCO>V䷀{{%, FmLu~"j  H9<̡Kba\b^Qh"ә,!+S],}A+nz/uipM3 pŹ% 1aao޽{]G}:ڥGDh:hK>ߤ./~[5FA"杺1h̸`YܚV\-h ƅk XG AV #oy4:2=0uZ0?>!>?дi=F8{9;ۓn֕?G@9sr7mDG/st9Tjp5 Ed' : W>'k+D-.s |?ZO9pT֫%N,&9 IpmoMB6GN?NiOt/pw=3OB32 EX ە;>v ~o./~[L UBo='yxIDXThY02ߛG%"–RtjOh 1B8AK J6MP1Ƚhye~άsc',">N+L8ۆmHFmm!q,I-@u16 vQDw!1pHٜf(>pK8߃ցk$N8YGm;" ӳA>{9PXFg%4uv;vvno T9<̠OD@K%@?ukkOUf Pb (TR6ր68=J]DrE49v-ыUE+M0g9bķbsmC_Nw|W;43irU Ƀyz+Ap G2J;.ba+Kgw Ĥ_H7hu?ôjeUpcUф) YMŬ??Ba1. wˋ*?8qۣ']" 8}UX{*r ejw DcQZC=tc BuğtD=ՎBF3T޽[;ǿI ?ɞnsXϱX>jT,݂:-HYBᾺXDt]zxi҉{/{㏭GTIEgwf][WWC4eg0*q2\>svk<𹻇C`ȣUCBƼ o[c /(v -Ihf ",:ZͿ}z-9-"u<VL@93rZt좭M[h/Z)zX7h $VFD  ] ~ߟVaˋ xsxx&"8x:OCf Nel xU4 \xp#,2ӳ./>aXfYA#; (,ƜRBL>(zZUy,rC )i}UqÏiӳ ./>FBt:XWla"N0%.*.ȴhj9%s H !P7t`4oˋ!4lT64{WWQĒ3ؔb ׉[0@bXwˬf6&NS;rL "0@0 Q)c2?\^|P`òwĒÇcϞ=:6 "!0p|;}/?62*bO4EnBǿ?F˹JeYz:*p1c?ڻyn./>(YSg ,$8^*<$HJEy˖Ec4q"Ə 5./>HZ4,6 ߾mۿC?.AN4IENDB`qvge-0.6.3/src/commonui/Icons/Format-GEXF.png000066400000000000000000000104641405165517400206540ustar00rootroot00000000000000PNG  IHDR>asRGBgAMA a pHYsodtEXtSoftwarepaint.net 4.1.5dGXRIDATx^휱D!)" " FIHyBB$ހ !fqvkkis>ҧ;Sn~Xc~*7 kL_)E` wχ~8c` w71nb>hXcm>:Gb wrqpE` wsrqXO>G` wcrqśT֘p7%(ěR֘p7$(>SN1~)1nFQ.<1nDQ.kxdXc݄8\g1Xc݀8\"Ƅs^Q.[1g=dXc9-({y"ƄsXQ.{_0^Xc9+(81gÞY֘pN3ao*kL8p_~%9ي5&srq81qF8W_}emnb 8\f"ƄsHQ./_mfƄsFQ./ŽE` 8\^{ qF84C6W kL8 \%1gK3dsƄs@\:N.b*a 瀸t\ŐUq8x!5&qrC6W kL8ĥ-l֘pK[ \%1JXc9 .'o1dsƄs@\:N.b*a 瀸t\ŐU_=O??>[o?`o~?eXWl֘p=IOy$co~g8េ8{}-l֘p$N8'cnM!z+C6W kL8?M$%J~ 1(=c]JXc9 ԟ0${c78wl֘p{EbE Y{DQ1KO~mSt }^!5&8V#({coٸm1@¦sg*a آ~yV;=6TlZr09,x{,YJXc9 ֊†A=<[\MҴpٍId4x 8)`I]"в5{%U;C6W kL8|=o|~fثu]:I<2I5Nǧ﹯g*a 瀘[BнײAJDעX@t3AkT3dsƄs@̈ a!{]B8h=kB1lQΐU1#G7:3܆hi=-)Ե 2F-νnQʐU1#fEO^mvF,%1{Eΰ~tl֘pzlK,'q:u"Ģ}=Ul֘pdQ,>.nJi㧺K.K{~E̸`3wK$_k>;#Na 8Q\_.73Co~fz}Z [7zAx[~o!5&bF 6녏[}bґ4,w/Ncm[B'm*iբQز!eAX ` k)VqYHz`ֹYul֘p(ı{uXڅ#Ds4b^>0 < D{{s \%13bq,IktS aXg,EcH3;tQ)TQZYz!5&bFc {DaA'A]$$s<3X$֝sˬv8zԭJXc9 fD27{֨UM>߻~p,K  H(i {7EI0ts \%1EU^0J~H(V8>/tg Žmgg*a 瀘3TĚWW_6|N@B{{Ypr}:}vl֘p5xD8^1^_J-q Zxf4~mMb{K+C6W kL8Z1# }? ?1CIe H,EF~,<}_-V+?3+ -:AtŲ2{kƘ]'{QnH(k yU,\W7%(QXKE0dsƄs@#UMZ*<נ3AZz<[+2BO> q|O}ٗD">.&(k9QL0dsƄs@!H&$[k*RBE q}_ }ztD5 nYZd$lKu}u %Q !5&AgOQ7[[ԢsS,-}lfvni0dsDx"\ܵ")f|Mjd͢Sœ,gl,f''H?+&f2~_|`P|%'`Mg)$ˆp<}2.>c[*ayK U: z`sL%*^$ D"18r-f2%ߖc {Kx$@=O \%1[$ wZMR*Hp|u( %B 4 jWِDWI Kl94ÕK 8.?[`SH``\!5&bt>gE2 }}-\fECIĈtG[b Isf,Բ^,Uv( '-AT\U8f-ΰjRXoTg=tS[ s.L[rr=qt[bz<^߇,V\%1[D l _jIʥ͟`q_~ Ͳ4a*a "fmRݴ9vre7w=9ӫ-͌]ܦ&(LՍ#n9zϡ8kѫ-e`vF0{PoCD nRm@2{>p?u 8:!5&b]>3D? p%$j GjP!5&)KJ#M֬.=@)B5I<Jv·%JXc9 c f^_z媄0{yϿE$7~|E0l|r~so^3dsƄs@+f%AcV kc J"(K\kkX*tyKcUVg*a 瀸W$6"ؚ%ڶѲgE27]ΐUhڀQ {_g.?3^B`i8wKZ!5&b/36-w.,;]5/c$qsZU;C6W kL8Ğ"q$D]amke i~Fqor;wl֘p#"h :3X;"3-JO,edk1ͪ^3dsƄs@)f,ɧ+Df4Z;|Gj Vsg*a x 1X؄F'`t޳=X#Оq \%1ef.yo{Q>]@:B5Ν!5&,6G?ΐUqGJOƹ3dsƄs@A,9uSKǺ2dsƄs@AlBI< ^ x!5&qrC6W kL8ĥ-l֘pK[ \%1JXc9 .'o1dsƄs@\:N.b*a 瀸t\ŐUq8x!5&qrC6W kL8ĥ-l֘pK[ \%1JXc9pXzfƄsb c9΁s45&hkL8.K,֘p\<9o[㊚dIENDB`qvge-0.6.3/src/commonui/Icons/Format-GraphML.png000066400000000000000000000105751405165517400214200ustar00rootroot00000000000000PNG  IHDR>agAMA a pHYsodtEXtSoftwarepaint.net 4.1.5dGXRIDATx^y|LZjm.z*rkRT)D^j J墸vDH,%؂$bH""h$AD6>y13 sf}>g{;y67P1d|VSCM.àìuluvEȠ%: ƃVMvP]g!sd/dPjf30;lLd PqL 8YTOēm`"sd/dPj_%ǗB_*^ֿD^ȠW1Y '{ "TCDn5{Γv6?CȠ㬒 `R3v;3vEݙ Pxl3QWޔf `vΥ4f-w3#8k}D3BȀ<)bXEO ?GnWÇ0fXR-WUlJ-|uIPPP 8^]ETmTߠLYV IIIR-E6_R9"gaRM᧲yl!%OwseTV]6Od$ip0<4|&Mr+ȒeI#ׯj>P47'mR`!z6n?N|lg>J!f.hQ{TT)[NT_R6l ;jhD `Fڵ ۽g)??'k`Tx0{QD @(;;*U~Z"rq%ӳTb*ZoԶҋfB8rh)8bڈX:ouX?ܾ%3:רiS~RrHtlJ6OU0pE ǟBi)ŊOH/(G$] S6]&.Ңj[HKKXdX^(9yE $[½5ެk(Z ["oAa3㏆:'Hߨ,KZCsdV]:3BcFxy !%%EVeIHȅ&C ?qRCgWg * c^0ItU\sIcǥoVTgOmWMf _$3@ʿRg%`wL,Y ުoYy: [c瓳(K2vCVȒemf Ps7CـegFxv݆0`9KiR6L5$$"3G= e^ E%D9Rr~ehԮu=v|xiW@XK̔%$4*3qArۤ"QzEʐj p$$!Ҩmofc߲+97$UqɄÇ: mr|5h\jM3 9w$UCJU C˕?U^ç[!3eeUʐ* LTT:4t?!>^ԭ6l[x{+VlϋOʒ< -i}o~{;"eֲ䓰~Vxo@%wKTAzX%`t%=/_ k&9d#x{)l< ILY:G$h|h,v31\N}R!CH {I&4__K* XT.*fR>_XNJ01dv02O@E8gw7mS;HLdnɠPG hc2ɭIZ# 5E577, sP qn;CICN[qsr+00G30fezQl*=tbX.U.A{G_:vidf  vLp%dzXvT֪oN5n3/ۺqW#f1\6#>#8EpcI?/o9xi9d5{(x+¢6r>wπuq/i0ͅ;|'!)-/䅛`^^l|˱ 1TXgֳ|aW[n: >+@Nn>/OHɀoƮh-u [wi3 I+9xv.Ǘ{c4̹4{0%.4avݘ42x\Ɗmg4.{_unTk9s9uϣZz|? ǺO*X)Gú=>"v2B^z,b{+Nẁ69,Q`eRO]Lz8ȧgЛd<6q>}><'ƽmy|jQ|+;]C'!UNm & 0$ 3E6/N Wڻ3t0zK8;O΅gyiha4qVl0@ܵm؀1=o5;~:h8$X2@l]뎗X^f#L౼_gwoc*EFw@48%5uNo)W&*Qo1 y<*hsc8 { <^GoLnvZze90.a+S V"hvfy}m1q}=ؠ매g k%?agh?G^ :?et״ͼǔP46x`a;Nqz|zd*c^sym|: eFQb ccӭ387c[%ݨM׃k- 19/&LWbc愜Y"N=yPno,c8λB H@)X{/7;qszKz3뻰@/)xIy%@帬j5]Sq& ɕЁOM 1 83Gy7gtC5,#IENDB`qvge-0.6.3/src/commonui/Icons/Format-PDF.png000066400000000000000000000203711405165517400205320ustar00rootroot00000000000000PNG  IHDR>asRGBgAMA a pHYsod IDATx^wmU3EŮX;k l"4<4B,P{؍(%w(**|Λu3ΝW7Y3߻{崥 ?V;X---5\pA9/_]"i/ws|^./6Ǘe_{s|K]%/8ttss|ы^.+2*+:[?a娪kնPz測|ʣ\Pk9/]]hK[u9 s3eQ&(mQk?9VvuV+HŏQ*Թ3a|{N(ä)ϙ4}OxfX]=:7%b.Vzj}_=Dӈ*!p]_cꠃ^W_Ƈ7=q3XavN,՞Տe#D^@xJ畉 m۶O|p'C<餓͛77a<Áщ~v0>W"LYafa㏯;y y'\r!}v=F|P}#Yav,=b 7 1yY6?au;ޱ]&/&94x((;5`7 CЦzh*..^2Ltʜ >W?>4 ԧ6d(!w@Q OO\WjsPN8:#vU7곟zիO?w$=^tGƅ{__a6Kuϫb̻?՛f5 =ؕv J=0)5>z32_[~6@4:3ߝq#dk׼5Wt\<ϮmK4ԏVxĪIQ&J捩_Սo|Vc֭}sU!fCe!$<)y;?<iw:ꨣV]u~kx2–aLTAsNuӛ޴9)Rwm5㛞^d )oQY=%(0r/ wݛ!xy a#R^hm 2w^a7rɺr۫ >яVw󝛞'JixeQ&Kx8(:PUQl!޻zeg:e^ R'/.d2 ^ن',|WS/8zfڽufɝ|ǵZu^ S@/̎zN~0T7{~ⓟduݭ O< !.Lx Q&teޝ0,7dKYٳ^l¸u_>Uwӝp.l%g[p i4DB ]zj¸a"aw*U2uU2uU2U2C(mA}@|-w]/| 7/(+|:kIWvz q =)y(kaXz2iIx`W}'8ḷ2u_5 ]z`y x`ssǼQNNaۍ}C""or4ǃԧ>i Bx¾' n1,!syC_RB970Wr4+c{-iBbycv1Jޜ͞{+./%k!L? ^“Iy2 ?h oٲy&VUí7T{sUгo]B~fl`ag+<͓Qʓ />o}ksa'%}w X'(WzMzs")CJ7="'@aSi(gV~Es<AР1*JRi\q:2@tIH8V,ʓN((\ڢsl񖷼yvtՓ~9'TsX)8ì*`X'iYD@ zb`v/xmDXфwYyVD6Ww^awW.Ix2 ?-#3muNmneGb8ICG'4\ yO; \ {8: UᅎFB'&=K޹' Ix2 _"""Ax/^s_YA> ~K^'F0^ /Da/5VkQK޹8JW^ $<)y S/ "< K[@xVgtEO-kxp,^џ 9^tg}vulp+% z`R-+1wՙkK>OJ[tY׮ !`bX,uEa#^ oaKza,e= qxi;7p+[xe/4Ó óEx K[@xVgtoIle ^C+ă%q !?O:u3C zeBKd%WFe R.Fs_֭0[xՓ+!wu"B]1;!WEW6fI0 uX^,׻K K wk|Ԟg>5R\򾞺gᆧ/:8<)yp{zHi-CѬSֹ}uK޹75.ozȺDi!dk ä!zT{kh.nexW={ڣVIDHt9P ?=\780rx`1.S O' ٷNDsIk}AHz'zD.*:%B'D(2K;LȸXDT$z +\]maG%ǩIo$z8 ˛.a?yЛ<\ү,ҫOҋvv6!]},"5 6kʴv5W|}{-KI/ ˹i!8W!8n//cOǣ zԨ ʞ@C -$1 oxfm z\yz7VX]^cKEWmuq| &m 0n0ނP""`Mpc6WUw^^eѣ-Ǻ?0>'=ݓ,.a?y9p=K޹5txmt &~co_oc0,8΀Ra0䌂x(P^xǎd\G6'(&%$Q&yI.[@x_2(Ox6:Erfku2/DG BU(<ws WQ1mRpXXɃKmP:+K*AU(W3en /| ȳ+A&2D.!7ihkr{:ϵ&.+adp=&sT76kdL#p.8zޛk-S[sb ,у}ڐP֭[;n~K_߮^y{܄Mpz7+BL^2.v0@>Ky,;<n+b7b ٍeͅzeH4?}+.`Vn,v>y;٪@&[lz9 '](mle ,=S} }ǯ0=z_j=]V!MË*Hޣmᣔs+xԍOpM GII7B 3nzsO=#I6B:&,r(gf ~p n uG<<7L6_SЗbc! 01:,T8J1#Aq Pԙ-4t@CgY P8@YB]"gwN]]<<յ2vixXhtO;|=8;yd B~ʮ3^Jx<;k~qvnCo8g|j1W'( "Z's"2m޼yҫ`ˉ,s>qܦ5 G@; kx2U]7x{[zn!JO\ê:x`+'{+X%P8C. 4r&BkbD8&D3ёY3eU(c$ Id =?I(uf#~xMNcW+ [sl,Y6;?f:b#b;`fFP\(PZAS :RAPڂSqv,MxsW^hkxmOO4?='Hh mztg(Ka?=C%)Q'!I,G&](묾D]ugJ[:w:),MOl俢=TJ=`0x[5R>@D2`,˪YUk42f<Ӌd]QGYb8pXdRʙrl6n€s.3ZD\Z#,B,+g~ngi`ø]U@)uDD 1 ES;PTT;pl CW>Aڗ0 o 0e?n(,ߺn-e:k~#6|JuR'b=B8CRlt?@k}}}nw$AI|.VH6.2[K[,-X3AEfYDd\k})urC@C?~< IENDB`qvge-0.6.3/src/commonui/Icons/Grid.png000066400000000000000000000003531405165517400175560ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs`p tEXtSoftwarewww.inkscape.org<hIDATH @ b_ZʹٙV? 'rrABH֐wI9ϒ&3[o:8PPW} ǿC|ZrA-$E _${uIENDB`qvge-0.6.3/src/commonui/Icons/Mode-AddNodes.png000066400000000000000000000006221405165517400212330ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH픱 E! )C6fHc{ Y\@69rpW;'Tbi;N4ԜS߲* K46oR,{Akf/HqJT؃51843kTއ.M2R&akk)';݇;f"s3?Gv!o]l*J,z; IENDB`qvge-0.6.3/src/commonui/Icons/Mode-Factor.png000066400000000000000000000013051405165517400207670ustar00rootroot00000000000000PNG  IHDRw= pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q IDATH͖nA݋D'%HDA ]!ݜsnpBBHGE^ : K[8ؘnvٽS""It:0Bq/Ƙv(o 4}dYv4M_y~Ԋa +y(3VS,~]'E ǟ&"5a;u]OL4+B1gJ"1 7Zkey ofccVkuQU;CkXleEQTk]$"kZk 6H)Z10ι9pJ>=6j;Y=D7c@D(G0,?xgw57s H^X"߻ߦMԃ^֞AW{QŨp`^:`%ZW".菘R\DOw OE$"9l0;*pUm"CH&"o| m$#qkm-?V@*IENDB`qvge-0.6.3/src/commonui/Icons/Mode-Select.png000066400000000000000000000010721405165517400207710ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qqIDATHݓ?KAB OR&E$]+!X31cXXɩCq;$Buof`ys2SzeZôPf{ V9 ÀKi`=3+ZXeqAZ(рZm5 @rEz?-"2PJ5ΤF6AXEQ)p8kU|iDDdD4"r[{W,oXu~L1HIENDB`qvge-0.6.3/src/commonui/Icons/Mode-Transform.png000066400000000000000000000006511405165517400215270ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYspMBtEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH 0 E?Vءs0 Bb!݁8%"z_c~ Y4MSyfDap7揨G$hVV^q29,%JmrR1ƌ}ߏs5OIIg\|3\9 /T4R|bX1s1Z3[iX %)8!/\ء9Zl@"rQ)IENDB`qvge-0.6.3/src/commonui/Icons/Node-Hexagon.png000066400000000000000000000013661405165517400211520ustar00rootroot00000000000000PNG  IHDR\.&sBIT|d pHYs(($ŬtEXtSoftwarewww.inkscape.org<sIDAT8kA?oJA(֣Ѓ` ^"9MSl*V$"Q& UՂ (U<)JAZd!IIV{'d29;&Ulx>v pb}n"j e1U?W #Q`v RTwTHJ&D1Fg2ښU1 Û@s T],oԯm<믖تTUkg\ة{@TD s{zi`(ax]$)"îD鴽8Le vD$}kuuu Bn59s Ȩ\^y㖈V'mƚIdh4MGOJv΍TujmU$"s XfsXka࢈|54b`T* "<4YF2/b;_Ak~ʌ]8o8=mc9H#i2 '#yTD2| ; 0IENDB`qvge-0.6.3/src/commonui/Icons/Node-Triangle.png000066400000000000000000000012161405165517400213200ustar00rootroot00000000000000PNG  IHDRsBIT|d pHYsj7tEXtSoftwarewww.inkscape.org< IDAT8p?$t⹴99^K"irCQ98r-:8Yȝ&?#mo{}OiiV `pV#i m`<_t:Υ5}L&Vj˲AթiV(Ij0 Q=A:̀U"V]בA>)_qiڦ 0W輸l)C@IENDB`qvge-0.6.3/src/commonui/Icons/Scroll-Navigator.png000066400000000000000000000006511405165517400220600ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH 0 E?Vءs0 Bb!݁8%"z_c~ Y4MSyfDap7揨G$hVV^q29,%JmrR1ƌ}ߏs5OIIg\|3\9 /T4R|bX1s1Z3[iX %)8!/\ء9Zl@"rQ)IENDB`qvge-0.6.3/src/commonui/Icons/Search.png000066400000000000000000000013001405165517400200670ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATH͕AocJY8,XYk͕Bx6'xڈ,Kj; g"? sM{#^ޙgZNOƘἫꤿ5@y`4w]w5XOOBۉ'ƘrE(Ƙ18v@Ec̍ S]a^wbAh8WE2UJ=<_5xoUbǛ"X`Z}^' `Yk۶ȵC,mK{Ddym9"̀$I.c>̰nDQbcnf:s% áRjIDƠ)0j d2w,˺j܉^5|YxU*z|P("wsmǹdY'LV@Z.MԊy?kڅ\.fkjqׇgBsYN"" + #IENDB`qvge-0.6.3/src/commonui/Icons/Settings.png000066400000000000000000000022221405165517400204660ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qIDATHOhUǿ7[T.B!!xMEX#ͼO2ڃAY7[Lj6IZ!XŃSDS)b/Id~n޼7h1uRDfIJd298N`###Ju/a`5\Xb<',C1VTL'(D^/g&䃍0wC {jugHȠH'zP&y m{( l/N8g1*wnM8Nkv\-+$1$ZErZ}@kQz_^@ {7(M-7:rMx?O@n2bx\ȑm.G;HCѰ-of p䳮~[UUJ&"QuZcܽT-8G3u˶mIx^=o(m~R)5L&G w\.g%Q c;mΛ00 K]rG"r}j\,/z|#EApqGU`hTWVI;ot+++v8PD@yT*0 6S SrKNR3>1ն+١*8)P(n'cRtcK1/"HePo(Mu2@\^"iumBvs:@R$|^MԲR*cw3{zz.t7elu`D;Z xR(2]rkoT[J*n%#8~2 R7lA˲FŶRtCD%yY+"z(zJ'{(8˲i?p_r:SVb. /Ddt;-d 8ADj1CO///,'—+qԙ0 2MH~z~SD⇔RgR^1r'-( z{\ׯ5 4c<Шq-YZFj䦞yOǂSe Xt'#" F?^ ð8~1Wp>L$ 3HT*&,czv?|1IMZ n+")64"rɻ0 j###Q]E\Z_qrËIENDB`qvge-0.6.3/src/commonui/Icons/edit-delete.png000066400000000000000000000014751405165517400210640ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qtIDATHŕOAƟw 0:$J)YKK =lr[J+ogDc@[ Zb'YjLXK n7~ķ}~8dQ""@D"m6~A9EZv?Rj*ŗn;jvcnC'CDf00$ɏN@oC}s$`-e񉽽}ȆsnZ;O{#ksnID6 8JP'm3 ι'ٹ|+]Hqc Ykäu """,$ |Ԁt lRg $"b a5rS@T{Uˤo7'}*TnޭW׌<Ƙ;ELlYk@93@3'}1n(LW1JɩSnGQDF;Mr’p6:ccc+ 3pZ d a[=Ed&k09y\ȭ VlaC>Zb\$D$_qIENDB`qvge-0.6.3/src/commonui/Icons/edit-paste.png000066400000000000000000000007551405165517400207360ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q$IDATH;N@E}Abtf6RXHH }#쁀c'F|f tƘӮz-˲>Q'YYU'[_q/9/@gx s.?ޟ"xR,VU.{1Mm=xjs:Y-E pϮns5r윻]U{ymJU-~ܛ#hF(z<`Eeͮlz,n4_cfc>B8fmHC)PVUIV5GIENDB`qvge-0.6.3/src/commonui/Icons/edit-redo.png000066400000000000000000000010531405165517400205430ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qbIDATH풱JPsDDtpA=:(n"jICO $@E>" qI$I{`*.s w7$˲Ɗ\Tr߿I* h%h%ڶ-&͎2:]JyPA^_BaG2:3322 H@_ K>sE3$5]mhC۶tp`/ZK 0n6 uϪa0)|23 !ap l@ZEN:F)5`/njڶRj=t\QE-OqK|_R}*to>[AD;% c{i5IENDB`qvge-0.6.3/src/commonui/Icons/edit-undo.png000066400000000000000000000010241405165517400205550ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qKIDATH1K@, XZDkȡ$V6Bi.`+ۜv"Z `\`Cn^7þo6 V,5GEdw@sx w8PM^DG)u`\DhѤDJ Cn#dYv78 QLDZ3_)3Mo!]N3/bw[BuY5+Aߚ]ԶL<[lL08lM81mn^޼~DDi^>M$;Q;8IDcf~5?Fx`1IENDB`qvge-0.6.3/src/commonui/Icons/text-label.png000066400000000000000000000014161405165517400207330ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qEIDATH?Aƿ7N"AP8D*AAND8rurXBÞB8@,9TH iO,ٝgrI.}{3 3߉ȾrRafc4T\Pqƙyrp!,duF) `N覝cfРJܒN\"Ȯֺ6 tDZ>xj DT$f^ R,i]kR5,b Wp5\T/[A\ 8!;9Hpsτ83V@fޯ/&i_}E̼n@(Ғ~X""ceK;,r]w9z)˻]ywJ"f矵Z[a6Wqzr2ہRj='Gqa ċ0Bs;K[ EA I ,VAARI*t I#=MJ9w+P4|:zN`SUEm T[-q"} pP̀Om۾JbXFSիlv cLeYK" ?VVV>U&vZUϫUEd8N/LNNU5Ud2Nc>L366vDUlh$wC'|x=h\TDJe NcNf2U 8S$"Cl@Ue Pl.V, %"vsUxNc\FGnc"Uۤ"m~qX,ˉl6{K/&_{Ā|إt0L8C;;;/JUB!cW7Y PI U*"W r9oMcL.|c\.RD]ukt(DXXlEhz 'ԔP(QyW(bLSIENDB`qvge-0.6.3/src/commonui/Icons/zoom-fit-selection.png000066400000000000000000000014521405165517400224210ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qaIDATH1hSQso*bnPn(V2Vbl_C ".\\J"T* TJAPBHBC6?{ݟ˽BdX4=I`U.L \J@ [koA.&vW<[]8sڣ8@DD2t{?acwXqgffNo3Vճ"Vbm Vh@U{wb ~qCmvmDRoyWtsg@+LRyjFDIhXġ 0V0,Ty 5@t%"cGh~Km$Sfs azR0k@M.j㗵^{az{{o߃[])?<$*dP*[|>l>AUR)KKKO1(;<;`MU?ȖUDҵZ-Qq40\oyGZ ̭C) G777#ڍzRVl6D" 9_q(FEufvFiIENDB`qvge-0.6.3/src/commonui/Icons/zoom-in.png000066400000000000000000000020331405165517400202560ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.qRIDATHMh\U7ali MF%B EpwMEEd:,t'.:J؅$wL (%AAI@D܈%ҍїɘ9.=wP,3t9U}Aপ^1 z4$I N5݂.cޮLP*C8UU}h,$^}2~."O&]BVGZVpvevvv-X,fzzzgb$fY^f_m/3"IENDB`qvge-0.6.3/src/commonui/Icons/zoom-original.png000066400000000000000000000015071405165517400214610ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q~IDATHkSaH-mB5 PQ+YJ KHɬtӿ $A X:X.U(N Z"t ISr4kgz{9} ].eU0yab&t900p Hnŀ id2= h&{w7bgl>Xo2pvN Rm{€Ƶ0񖖈d czM8UJ\-C:FrEXRI n#ęx<~G]9"22k Uàg̲x'{ "riS˪z߮nwwe]uU4l0Иz5 6>tz,p *yVh3 .J~333CZa$]gbQy > |t:]vDT^?8>,kO FaoADW eei*0ґ7yP.ȅު%Lj@iJSP"t.m͵]R)WZEUZEĨG{IENDB`qvge-0.6.3/src/commonui/Icons/zoom-out.png000066400000000000000000000017511405165517400204650ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs%%IR$tEXtSoftwarewww.inkscape.org<tEXtTitleInkscape Icon Theme"tEXtAuthorBarbara Muraus.q IDATHOh\U7ali MF%BŖ?((."d[NKIkb UHbH*"wbSAI+B71s\{u?3V||{v@PȤTu8 ?U7XVI@ډ|>o*û-NZg{Cz 'XkC p^DIRtfss1U} ">lllv|_W3:!"|w'GPDmȩ)`-S q/]d Ƙo322Ot*033suՈ}3;lyZWඈ\T<8Vv;QxZ;GIzZ[b]Q`!L| ,' 0fQPa6.p;f2@.1(2QIqx8|A,u+^,OFO\6"Qw cL>T*8SSS+d>FT*h4>s@*q_G;־ 7fggl GT{`_D.a':sc̥$.?=Nt׀\T< x$"[w 8b7 sPl7Ce ƒX=E$Uq/.Πq|߿S@U3 0 u U} cRTWm;f3Qzx"#WVV>ݩx>^*U]m?Q.YkmGP(Ǟ.$3*cX|qk UUsrrF␪쎨0 %Z|>k9<kh7UTUuEsd2 Of>a'u̩꜈ݜs XkGKM%\HDHӼT(bq^cj|R.KZ1hCCCZV>kZIENDB`qvge-0.6.3/src/commonui/commonui.pri000066400000000000000000000013401405165517400174470ustar00rootroot00000000000000# config include($$PWD/../config.pri) # app sources SOURCES += $$files($$PWD/*.cpp) HEADERS += $$files($$PWD/*.h) FORMS += $$files($$PWD/*.ui) RESOURCES += $$files($$PWD/*.qrc) # base sources include($$PWD/../appbase/appbase.pri) # includes INCLUDEPATH += $$PWD $$PWD/.. INCLUDEPATH += $$PWD/../3rdParty INCLUDEPATH += $$PWD/../3rdParty/qsint-widgets INCLUDEPATH += $$PWD/../3rdParty/qtpropertybrowser USE_OGDF{ INCLUDEPATH += $$OGDF_INCLUDE_PATH SOURCES += $$files($$PWD/ogdf/*.cpp) HEADERS += $$files($$PWD/ogdf/*.h) FORMS += $$files($$PWD/ogdf/*.ui) } USE_BOOST{ INCLUDEPATH += $$BOOST_INCLUDE_PATH } USE_GVGRAPH{ SOURCES += $$files($$PWD/gvgraph/*.cpp) HEADERS += $$files($$PWD/gvgraph/*.h) } qvge-0.6.3/src/commonui/commonui.pro000066400000000000000000000001611405165517400174550ustar00rootroot00000000000000include($$PWD/../lib.pri) TARGET = commonui QT += core gui widgets printsupport xml include($$PWD/commonui.pri)qvge-0.6.3/src/commonui/commonui.qrc000066400000000000000000000050421405165517400174450ustar00rootroot00000000000000 Icons/Direction-Both.png Icons/Direction-One.png Icons/Direction-None.png Icons/Grid.png Icons/Grid-Snap.png Icons/Node-Romb.png Icons/Node-Round.png Icons/Node-Square.png Icons/Node-Triangle.png Icons/Node-Triangle-Down.png Icons/Scroll-Navigator.png Icons/Settings.png Icons/Action-Unlink.png Icons/Action-Crop.png Icons/Action-Link.png Icons/Node-Hexagon.png Icons/Mode-AddNodes.png Icons/Mode-Select.png Icons/Mode-Transform.png Icons/edit-copy.png Icons/edit-cut.png Icons/edit-paste.png Icons/edit-redo.png Icons/edit-undo.png Icons/zoom.png Icons/zoom-fit-items.png Icons/zoom-fit-selection.png Icons/zoom-in.png Icons/zoom-original.png Icons/zoom-out.png Icons/zoom-previous.png Icons/edit-delete.png Icons/text-label.png Icons/Graph.png Icons/Search.png Icons/Format-DOT.png Icons/Format-GEXF.png Icons/Format-GraphML.png Icons/Edge-Direct.png Icons/Edge-Polyline.png Icons/Mode-Factor.png Icons/Format-PDF.png qvge-0.6.3/src/commonui/gvgraph/000077500000000000000000000000001405165517400165455ustar00rootroot00000000000000qvge-0.6.3/src/commonui/gvgraph/CGVGraphLayoutUIController.cpp000066400000000000000000000144621405165517400243610ustar00rootroot00000000000000#include "CGVGraphLayoutUIController.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CGVGraphLayoutUIController::CGVGraphLayoutUIController(CMainWindow *parent, CEditorScene *scene) : m_parent(parent), m_scene(scene), m_defaultEngine("dot") { // add layout menu QMenu *layoutMenu = new QMenu(tr("&GraphViz")); m_parent->menuBar()->insertMenu(m_parent->getWindowMenuAction(), layoutMenu); layoutMenu->addAction(tr("Hierarchical Layout (dot default)"), this, SLOT(doDotLayout())); layoutMenu->addAction(tr("Spring Energy Layout (neato)"), this, SLOT(doNeatoLayout())); layoutMenu->addAction(tr("Spring Force Layout (fdp)"), this, SLOT(doFDPLayout())); layoutMenu->addAction(tr("Multiscaled Spring Force Layout (sfdp)"), this, SLOT(doSFDPLayout())); layoutMenu->addAction(tr("Radial Layout (twopi)"), this, SLOT(doTwopiLayout())); layoutMenu->addAction(tr("Circular Layout (circo)"), this, SLOT(doCircularLayout())); } void CGVGraphLayoutUIController::setPathToGraphviz(const QString &pathToGraphviz) { m_pathToGraphviz = pathToGraphviz; } void CGVGraphLayoutUIController::setDefaultEngine(const QString &engine) { if (!engine.isEmpty()) m_defaultEngine = engine; } QString CGVGraphLayoutUIController::errorNotWritable(const QString &path) const { return QObject::tr("Cannot create GraphViz output in %1. Check if the directory is writable.").arg(path); } QString CGVGraphLayoutUIController::errorCannotRun(const QString &path) const { return QObject::tr("Cannot run %1. Check if GraphViz has been correctly installed.").arg(path); } QString CGVGraphLayoutUIController::errorCannotFinish(const QString &path) const { return QObject::tr("Execution of %1 took too long and has been therefore cancelled by user.").arg(path); } bool CGVGraphLayoutUIController::doRunDOT(const QString &engine, const QString &dotFilePath, QString &plainFilePath, QString* lastError /*= nullptr*/) { // run dot to convert filename.dot -> filename.temp.plain QTemporaryFile tempFile(QDir::tempPath() + "/qvge-XXXXXX.plain"); if (!tempFile.open()) { if (lastError) *lastError = errorNotWritable(QDir::tempPath()); return false; } plainFilePath = tempFile.fileName(); tempFile.setAutoRemove(false); QString pathToDot = "dot"; if (m_pathToGraphviz.size()) pathToDot = m_pathToGraphviz + "/dot"; QString cmd = QString("\"%1\" -K\"%2\" -Tplain-ext \"%3\" -o\"%4\"").arg(pathToDot, engine).arg(dotFilePath).arg(plainFilePath); QProgressDialog progressDialog(tr("Running dot takes longer than expected.\n\nAbort execution?"), tr("Abort"), 0, 100); progressDialog.setWindowModality(Qt::ApplicationModal); progressDialog.setAutoReset(false); progressDialog.setMinimumDuration(1000); QProcess process; process.setWorkingDirectory(m_pathToGraphviz); process.start(cmd); int res = 0; process.waitForStarted(1000); while (process.state() != QProcess::NotRunning) { process.waitForFinished(100); qApp->processEvents(); if (progressDialog.wasCanceled()) { if (lastError) *lastError = errorCannotFinish(pathToDot); return false; } if (progressDialog.isVisible()) { progressDialog.setValue(progressDialog.value() + 1); if (progressDialog.value() > 30) progressDialog.setMaximum(progressDialog.maximum() + 1); } } //int res = QProcess::execute(cmd); if (res != 0) { if (lastError) *lastError = errorCannotRun(pathToDot); return false; } // run successful return true; } bool CGVGraphLayoutUIController::loadGraph(const QString &filename, CEditorScene &scene, QString* lastError /*= nullptr*/) { // run dot to convert filename.dot -> filename.temp.plain QString plainFilePath; if (!doRunDOT(m_defaultEngine, filename, plainFilePath, lastError)) return false; // import generated plain text bool ok = CFileSerializerPlainDOT().load(plainFilePath, scene, lastError); if (ok) Q_EMIT loadFinished(); else if (lastError) *lastError = tr("Cannot load file content"); QFile::remove(plainFilePath); return ok; } bool CGVGraphLayoutUIController::doLayout(const QString &engine, CEditorScene &scene) { QString lastError; QString plainFilePath; // export to dot QTemporaryFile tempFile(QDir::tempPath() + "/qvge-XXXXXX.dot"); if (!tempFile.open()) { lastError = errorNotWritable(QDir::tempPath()); QMessageBox::critical(m_parent, tr("Layout failed"), lastError); return false; } bool ok = CFileSerializerDOT().save(tempFile.fileName(), scene, &lastError); if (!ok) { QMessageBox::critical(m_parent, tr("Layout failed"), lastError); return false; } // convert dot -> plain if (!doRunDOT(engine, tempFile.fileName(), plainFilePath, &lastError)) { QMessageBox::critical(m_parent, tr("Layout failed"), lastError); return false; } // import layout only CFormatPlainDOT graphFormat; Graph graphModel; if (!graphFormat.load(plainFilePath, graphModel, &lastError)) { QFile::remove(plainFilePath); QMessageBox::critical(m_parent, tr("Layout failed"), lastError); return false; } // update node positions auto nodes = scene.getItems(); for (auto & node : nodes) { int nodeIndex = graphModel.findNodeIndex(node->getId()); if (nodeIndex >= 0) { const auto & attrs = graphModel.nodes.at(nodeIndex).attrs; node->setX(attrs["x"].toDouble()); node->setY(attrs["y"].toDouble()); } } Q_EMIT layoutFinished(); QFile::remove(plainFilePath); return true; } void CGVGraphLayoutUIController::runGraphvizTest(const QString &graphvizPath) { QString pathToDot = "dot"; if (graphvizPath.size()) pathToDot = graphvizPath + "/dot"; QString cmd = QString("\"%1\" -V").arg(pathToDot); QProcess process; process.setProcessChannelMode(QProcess::MergedChannels); process.setWorkingDirectory(graphvizPath); process.start(cmd); bool done = process.waitForFinished(5000); if (done) { QString outputText = process.readAll(); QMessageBox::information(nullptr, tr("Test passed"), outputText); } else { QMessageBox::critical(nullptr, tr("Test failed"), tr("Was not able to run %1").arg(cmd)); } } qvge-0.6.3/src/commonui/gvgraph/CGVGraphLayoutUIController.h000066400000000000000000000026131405165517400240210ustar00rootroot00000000000000#pragma once #include class CMainWindow; class CEditorScene; class CGVGraphLayoutUIController : public QObject { Q_OBJECT public: explicit CGVGraphLayoutUIController(CMainWindow *parent, CEditorScene *scene); void setPathToGraphviz(const QString &pathToGraphviz); void setDefaultEngine(const QString &engine); // file IO (think: to move?) bool loadGraph(const QString &filename, CEditorScene &scene, QString* lastError = nullptr); Q_SIGNALS: void loadFinished(); void layoutFinished(); public Q_SLOTS: void runGraphvizTest(const QString &graphvizPath); private Q_SLOTS: void doDotLayout() { doLayout("dot", *m_scene); } void doNeatoLayout() { doLayout("neato", *m_scene); } void doFDPLayout() { doLayout("fdp", *m_scene); } void doSFDPLayout() { doLayout("sfdp", *m_scene); } void doTwopiLayout() { doLayout("twopi", *m_scene); } void doCircularLayout() { doLayout("circo", *m_scene); } private: bool doLayout(const QString &engine, CEditorScene &scene); bool doRunDOT(const QString &engine, const QString &dotFilePath, QString &plainFilePath, QString* lastError /*= nullptr*/); QString errorNotWritable(const QString &path) const; QString errorCannotRun(const QString &path) const; QString errorCannotFinish(const QString &path) const; CMainWindow *m_parent = nullptr; CEditorScene *m_scene = nullptr; QString m_pathToGraphviz; QString m_defaultEngine; }; qvge-0.6.3/src/commonui/ogdf/000077500000000000000000000000001405165517400160265ustar00rootroot00000000000000qvge-0.6.3/src/commonui/ogdf/COGDFLayout.cpp000066400000000000000000000164751405165517400205670ustar00rootroot00000000000000#include "COGDFLayout.h" #include #include #include #include #include #include #include #include #include // std::ios, std::istream, std::cout #include // std::filebuf #include #include #include COGDFLayout::COGDFLayout() { } static QVariant toVariant(ogdf::Shape shape) { using namespace ogdf; switch (shape) { case Shape::Rect: return "square"; case Shape::RoundedRect: return "rsquare"; case Shape::Ellipse: return "disc"; case Shape::Triangle: return "triangle"; case Shape::Pentagon: return "star"; case Shape::Hexagon: return "hexagon"; case Shape::Octagon: return "octagon"; case Shape::Rhomb: return "diamond"; case Shape::Trapeze: return "trapeze"; case Shape::Parallelogram: return "parallelogram"; case Shape::InvTriangle: return "triangle2"; case Shape::InvTrapeze: return "trapeze2"; case Shape::InvParallelogram: return "parallelogram2"; case Shape::Image: return "image"; } return QVariant(); } static QVariant toVariant(ogdf::StrokeType stroke) { using namespace ogdf; switch (stroke) { case StrokeType::Solid: return "solid"; case StrokeType::Dash: return "dashed"; case StrokeType::Dot: return "dotted"; case StrokeType::Dashdot: return "dashdot"; case StrokeType::Dashdotdot: return "dashdotdot"; default:; } return QVariant(); } void COGDFLayout::doLayout(ogdf::LayoutModule &layout, CNodeEditorScene &scene) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); ogdf::Graph G; ogdf::GraphAttributes GA(G, ogdf::GraphAttributes::nodeGraphics | ogdf::GraphAttributes::edgeGraphics); // qvge -> ogdf auto nodes = scene.getItems(); auto edges = scene.getItems(); QMap nodeMap; for (CNode* node : nodes) { ogdf::node n = G.newNode(); // GA.x(n) = node->pos().x(); // GA.y(n) = node->pos().y(); GA.x(n) = 0; GA.y(n) = 0; nodeMap[node] = n; } for (CEdge* edge: edges) { ogdf::node n1 = nodeMap[edge->firstNode()]; ogdf::node n2 = nodeMap[edge->lastNode()]; ogdf::edge e = G.newEdge(n1, n2); } // ogdf layout layout.call(GA); // ogdf -> qvge for (auto it = nodeMap.begin(); it != nodeMap.end(); ++it) { CNode* node = it.key(); ogdf::node n = it.value(); node->setPos(GA.x(n), GA.y(n)); } // finalize scene.setSceneRect(scene.itemsBoundingRect()); scene.addUndoState(); QApplication::restoreOverrideCursor(); } void COGDFLayout::graphTopologyToScene(const ogdf::Graph &G, const ogdf::GraphAttributes &GA, CNodeEditorScene &scene) { //scene.reset(); scene.initialize(); // create nodes QMap nodeMap; for (auto n: G.nodes) { CNode* node = new CNode; scene.addItem(node); nodeMap[n] = node; if (GA.has(GA.nodeGraphics)) { node->setPos(GA.x(n), GA.y(n)); } } for (auto e: G.edges) { CEdge* edge = new CDirectEdge; scene.addItem(edge); edge->setFirstNode(nodeMap[e->source()]); edge->setLastNode(nodeMap[e->target()]); } // finalize scene.setSceneRect(scene.itemsBoundingRect()); } void COGDFLayout::graphToScene(const ogdf::Graph &G, const ogdf::GraphAttributes &GA, CNodeEditorScene &scene) { scene.reset(); // create nodes QMap nodeMap; for (auto n: G.nodes) { CNode* node = scene.createNewNode(); scene.addItem(node); nodeMap[n] = node; if (GA.has(GA.nodeGraphics)) { node->setPos(GA.x(n), GA.y(n)); node->setAttribute("size", QSizeF(GA.width(n), GA.height(n))); node->setAttribute("shape", toVariant(GA.shape(n))); } if (GA.has(GA.nodeStyle)) { auto c = GA.fillColor(n); node->setAttribute("color", QColor(c.red(), c.green(), c.blue())); auto sc = GA.strokeColor(n); node->setAttribute("stroke.color", QColor(c.red(), c.green(), c.blue())); node->setAttribute("stroke.style", toVariant(GA.strokeType(n))); node->setAttribute("stroke.size", GA.strokeWidth(n)); } int id = -1; if (GA.has(GA.nodeId)) { id = GA.idNode(n); if (id >= 0) node->setId(QString::number(id)); } if (GA.has(GA.nodeLabel)) { auto label = QString::fromStdString(GA.label(n)); // label -> ID if (id < 0 && label.size()) node->setId(label); } if (GA.has(GA.nodeTemplate)) { auto label = QString::fromStdString(GA.templateNode(n)); // comment -> label if (label.size()) node->setAttribute("label", label); } if (GA.has(GA.nodeWeight)) node->setAttribute("weight", GA.weight(n)); } for (auto e: G.edges) { CEdge* edge = scene.createNewConnection(); scene.addItem(edge); edge->setFirstNode(nodeMap[e->source()]); edge->setLastNode(nodeMap[e->target()]); if (GA.has(GA.edgeDoubleWeight)) edge->setAttribute("weight", GA.doubleWeight(e)); else if (GA.has(GA.edgeIntWeight)) edge->setAttribute("weight", GA.intWeight(e)); if (GA.has(GA.edgeLabel)) edge->setAttribute("label", QString::fromStdString(GA.label(e))); if (GA.has(GA.edgeStyle)) { auto c = GA.strokeColor(e); edge->setAttribute("color", QColor(c.red(), c.green(), c.blue())); edge->setAttribute("style", toVariant(GA.strokeType(e))); } } // finalize scene.setSceneRect(scene.itemsBoundingRect()); } // file IO bool COGDFLayout::loadGraph(const QString &filename, CNodeEditorScene &scene, QString* lastError) { ogdf::Graph G; ogdf::GraphAttributes GA(G, -1); // all attrs QString format = QFileInfo(filename).suffix().toLower(); std::filebuf fb; if (!fb.open (filename.toStdString(), std::ios::in)) return false; std::istream is(&fb); bool ok = false; if (format == "gml") { ok = ogdf::GraphIO::readGML(GA, G, is); } else if (format == "dot" || format == "gv") { ok = ogdf::GraphIO::readDOT(GA, G, is); // normalize node positions if (ok && GA.has(GA.nodeGraphics)) { for (auto n : G.nodes) { if (GA.x(n) != 0.0 || GA.y(n) != 0.0) { GA.x(n) *= 72.0; GA.y(n) *= -72.0; GA.width(n) *= 72.0; GA.height(n) *= 72.0; } } } } if (ok) { autoLayoutIfNone(G, GA); graphToScene(G, GA, scene); scene.addUndoState(); } fb.close(); return ok; } // privates bool COGDFLayout::autoLayoutIfNone(const ogdf::Graph &G, ogdf::GraphAttributes &GA) { if (GA.has(GA.nodeGraphics)) { for (auto n : G.nodes) { if (GA.x(n) != 0.0 || GA.y(n) != 0.0) return false; } } else return false; ogdf::BalloonLayout layout; layout.call(GA); // factor x2 for (auto n : G.nodes) { GA.x(n) *= 2.0; GA.y(n) *= 2.0; } return true; } qvge-0.6.3/src/commonui/ogdf/COGDFLayout.h000066400000000000000000000014361405165517400202230ustar00rootroot00000000000000#ifndef COGDFLAYOUT_H #define COGDFLAYOUT_H // stl #include // qt #include // qvge class CNodeEditorScene; // ogdf namespace ogdf { class LayoutModule; class Graph; class GraphAttributes; } class COGDFLayout { public: COGDFLayout(); static void doLayout(ogdf::LayoutModule& layout, CNodeEditorScene &scene); static void graphTopologyToScene(const ogdf::Graph &G, const ogdf::GraphAttributes &GA, CNodeEditorScene &scene); static void graphToScene(const ogdf::Graph &G, const ogdf::GraphAttributes &GA, CNodeEditorScene &scene); static bool loadGraph(const QString &filename, CNodeEditorScene &scene, QString* lastError = nullptr); private: static bool autoLayoutIfNone(const ogdf::Graph &G, ogdf::GraphAttributes &GA); }; #endif // COGDFLAYOUT_H qvge-0.6.3/src/commonui/ogdf/COGDFLayoutUIController.cpp000066400000000000000000000064071405165517400230630ustar00rootroot00000000000000#include "COGDFLayoutUIController.h" #include "COGDFLayout.h" #include "COGDFNewGraphDialog.h" #include #include #include #include #include #include #include #include #include #include #include // crashes #include // crashes #include // crashes #include // crashes #include #include COGDFLayoutUIController::COGDFLayoutUIController(CMainWindow *parent, CNodeEditorScene *scene) : QObject(parent), m_parent(parent), m_scene(scene) { // add layout menu QMenu *layoutMenu = new QMenu(tr("&OGDF")); m_parent->menuBar()->insertMenu(m_parent->getWindowMenuAction(), layoutMenu); layoutMenu->addAction(tr("Linear Layout"), this, SLOT(doLinearLayout())); layoutMenu->addAction(tr("Balloon Layout"), this, SLOT(doBalloonLayout())); layoutMenu->addAction(tr("Circular Layout"), this, SLOT(doCircularLayout())); //layoutMenu->addAction(tr("Tree Layout"), this, SLOT(doTreeLayout())); layoutMenu->addAction(tr("FMMM Layout"), this, SLOT(doFMMMLayout())); layoutMenu->addAction(tr("Planar Layout"), this, SLOT(doPlanarLayout())); layoutMenu->addAction(tr("Davidson-Harel Layout"), this, SLOT(doDHLayout())); layoutMenu->addAction(tr("Sugiyama Layout"), this, SLOT(doSugiyamaLayout())); layoutMenu->addSeparator(); layoutMenu->addAction(tr("Create new graph..."), this, SLOT(createNewGraph())); } void COGDFLayoutUIController::createNewGraph() { COGDFNewGraphDialog dialog; dialog.exec(*m_scene); } void COGDFLayoutUIController::doPlanarLayout() { ogdf::PlanarizationLayout layout; COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doLinearLayout() { ogdf::LinearLayout layout; COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doBalloonLayout() { ogdf::BalloonLayout layout; COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doCircularLayout() { ogdf::CircularLayout layout; COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doFMMMLayout() { ogdf::FMMMLayout layout; COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doTreeLayout() { ogdf::RadialTreeLayout layout; // crashing COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doDHLayout() { ogdf::DavidsonHarelLayout layout; //layout.setSpeed(ogdf::DavidsonHarelLayout::SpeedParameter::Fast); //layout.fixSettings(ogdf::DavidsonHarelLayout::SettingsParameter::Repulse); COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } void COGDFLayoutUIController::doSugiyamaLayout() { ogdf::SugiyamaLayout layout; COGDFLayout::doLayout(layout, *m_scene); Q_EMIT layoutFinished(); } qvge-0.6.3/src/commonui/ogdf/COGDFLayoutUIController.h000066400000000000000000000012531405165517400225220ustar00rootroot00000000000000#ifndef COGDFLAYOUTUICONTROLLER_H #define COGDFLAYOUTUICONTROLLER_H #include class CMainWindow; class CNodeEditorScene; class COGDFLayoutUIController : public QObject { Q_OBJECT public: explicit COGDFLayoutUIController(CMainWindow *parent, CNodeEditorScene *scene); Q_SIGNALS: void layoutFinished(); private Q_SLOTS: void doPlanarLayout(); void doLinearLayout(); void doBalloonLayout(); void doCircularLayout(); void doTreeLayout(); void doFMMMLayout(); void doDHLayout(); void doSugiyamaLayout(); void createNewGraph(); private: CMainWindow *m_parent; CNodeEditorScene *m_scene; }; #endif // COGDFLAYOUTUICONTROLLER_H qvge-0.6.3/src/commonui/ogdf/COGDFNewGraphDialog.cpp000066400000000000000000000064061405165517400221360ustar00rootroot00000000000000#include "COGDFNewGraphDialog.h" #include "ui_COGDFNewGraphDialog.h" #include "COGDFLayout.h" #include #include #include #include #include #include enum GraphTypes { Random, Simple, Tree, RoundTree, PlanarTree, Wheel, Petersen, PlanarPetersen }; COGDFNewGraphDialog::COGDFNewGraphDialog(QWidget *parent) : QDialog(parent), ui(new Ui::COGDFNewGraphDialog) { ui->setupUi(this); QStringList graphTypes; graphTypes << tr("Random Graph"); graphTypes << tr("Simple Graph"); graphTypes << tr("Tree Graph"); graphTypes << tr("Round Tree Graph"); graphTypes << tr("Planar Tree Graph"); graphTypes << tr("Wheel Graph"); graphTypes << tr("Petersen Graph"); graphTypes << tr("Planar Petersen Graph"); ui->List->addItems(graphTypes); ui->List->setCurrentRow(0); } COGDFNewGraphDialog::~COGDFNewGraphDialog() { delete ui; } void COGDFNewGraphDialog::on_List_itemActivated(QListWidgetItem *item) { if (item) accept(); } void COGDFNewGraphDialog::on_List_currentRowChanged(int currentRow) { // hide all items ui->Nodes->setEnabled(true); ui->Edges->setEnabled(true); ui->Jumps->setEnabled(true); switch (currentRow) { case Tree: case RoundTree: case PlanarTree: case Wheel: case Petersen: case PlanarPetersen: ui->Edges->setEnabled(false); break; } switch (currentRow) { case Random: case Simple: case Tree: case RoundTree: case PlanarTree: case Wheel: ui->Jumps->setEnabled(false); break; } } bool COGDFNewGraphDialog::exec(CNodeEditorScene &scene) { QTimer::singleShot(0, this, SLOT(raise())); if (QDialog::exec() == Rejected) return false; // create graph ogdf::Graph G; ogdf::GraphAttributes GA(G, ogdf::GraphAttributes::nodeGraphics | ogdf::GraphAttributes::edgeGraphics); ogdf::FMMMLayout fmmm; ogdf::CircularLayout circle; ogdf::PlanarizationLayout planar; switch (ui->List->currentRow()) { case Random: ogdf::randomGraph(G, ui->Nodes->value(), ui->Edges->value()); fmmm.call(GA); break; case Simple: ogdf::randomSimpleGraph(G, ui->Nodes->value(), ui->Edges->value()); fmmm.call(GA); break; case Tree: ogdf::randomTree(G, ui->Nodes->value()); fmmm.call(GA); break; case RoundTree: ogdf::randomTree(G, ui->Nodes->value()); circle.call(GA); break; case PlanarTree: ogdf::randomTree(G, ui->Nodes->value()); planar.call(GA); break; case Wheel: ogdf::wheelGraph(G, ui->Nodes->value()); circle.call(GA); break; case Petersen: ogdf::petersenGraph(G, ui->Nodes->value() / 2, ui->Jumps->value()); fmmm.call(GA); break; case PlanarPetersen: ogdf::petersenGraph(G, ui->Nodes->value() / 2, ui->Jumps->value()); planar.call(GA); break; } scene.addUndoState(); COGDFLayout::graphTopologyToScene(G, GA, scene); scene.addUndoState(); return true; } qvge-0.6.3/src/commonui/ogdf/COGDFNewGraphDialog.h000066400000000000000000000010731405165517400215760ustar00rootroot00000000000000#ifndef COGDFNEWGRAPHDIALOG_H #define COGDFNEWGRAPHDIALOG_H #include #include class CNodeEditorScene; namespace Ui { class COGDFNewGraphDialog; } class COGDFNewGraphDialog : public QDialog { Q_OBJECT public: explicit COGDFNewGraphDialog(QWidget *parent = 0); ~COGDFNewGraphDialog(); bool exec(CNodeEditorScene &scene); private Q_SLOTS: void on_List_currentRowChanged(int currentRow); void on_List_itemActivated(QListWidgetItem *item); private: Ui::COGDFNewGraphDialog *ui; }; #endif // COGDFNEWGRAPHDIALOG_H qvge-0.6.3/src/commonui/ogdf/COGDFNewGraphDialog.ui000066400000000000000000000114411405165517400217640ustar00rootroot00000000000000 COGDFNewGraphDialog 0 0 468 292 Create a Graph Graph Type false QAbstractItemView::NoEditTriggers false Qt::IgnoreAction true true Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok true Parameters Nodes 1 10000 10 20 Edges 1 10000 10 30 Jumps 1 10000 10 10 Buttons accepted() COGDFNewGraphDialog accept() 248 254 157 274 Buttons rejected() COGDFNewGraphDialog reject() 316 260 286 274 qvge-0.6.3/src/config.pri000066400000000000000000000023721405165517400152460ustar00rootroot00000000000000# This file is a part of # QVGE - Qt Visual Graph Editor # # (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) # # It can be used freely, maintaining the information above. #CONFIG += USE_OGDF CONFIG += USE_GVGRAPH #CONFIG += USE_BOOST # external OGDF USE_OGDF{ DEFINES += USE_OGDF # system-specific OGDF setup OGDF_LIB_NAME = ogdf OGDF_LIB_PATH = OGDF_INCLUDE_PATH = /usr/share/ogdf/include } # external boost::graph USE_BOOST{ DEFINES += USE_BOOST # system-specific Boost setup BOOST_LIB_NAME = boost_graph BOOST_LIB_PATH = BOOST_INCLUDE_PATH = /usr/share/boost/include } # external GraphViz (only #define) USE_GVGRAPH{ DEFINES += USE_GVGRAPH } # compiler stuff win32-msvc*{ QMAKE_CXXFLAGS += /MP } gcc{ QMAKE_CXXFLAGS += -Wno-unused-variable -Wno-unused-parameter -Wno-misleading-indentation QMAKE_CXXFLAGS += -isystem } # common config QT += core gui widgets xml opengl network printsupport svg CONFIG += c++14 # output CONFIG(debug, debug|release){ LIBS += -L$$OUT_PWD/../lib.debug } else{ LIBS += -L$$OUT_PWD/../lib } # temp dirs (unix) unix{ MOC_DIR = $$OUT_PWD/_generated OBJECTS_DIR = $$OUT_PWD/_generated UI_DIR = $$OUT_PWD/_generated RCC_DIR = $$OUT_PWD/_generated } qvge-0.6.3/src/lib.pri000066400000000000000000000005341405165517400145450ustar00rootroot00000000000000# This file is a part of # QVGE - Qt Visual Graph Editor # # (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) # # It can be used freely, maintaining the information above. TEMPLATE=lib CONFIG+=static include($$PWD/config.pri) CONFIG(debug, debug|release){ DESTDIR = $$OUT_PWD/../lib.debug } else{ DESTDIR = $$OUT_PWD/../lib } qvge-0.6.3/src/qvge/000077500000000000000000000000001405165517400142235ustar00rootroot00000000000000qvge-0.6.3/src/qvge/CAttribute.cpp000066400000000000000000000030261405165517400167760ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CAttribute.h" // attributes CAttribute::CAttribute(): flags(ATTR_NONE) { valueType = QVariant::String; } CAttribute::CAttribute(const QByteArray& attrId, const QString& attrName) : flags(ATTR_NODEFAULT) { id = attrId; name = attrName; if (name.isEmpty()) name = id; valueType = QVariant::String; } CAttribute::CAttribute( const QByteArray& attrId, const QString& attrName, const QVariant& defaultValue_, const int attrFlags_) : flags(attrFlags_) { id = attrId; name = attrName.isEmpty() ? id : attrName; valueType = defaultValue_.type(); defaultValue = (flags & ATTR_NODEFAULT) ? QVariant() : defaultValue_; } bool CAttribute::storeTo(QDataStream& out, quint64 /*version64*/) const { out << id << name << defaultValue << true << true << valueType; return true; } bool CAttribute::restoreFrom(QDataStream& out, quint64 version64) { out >> id; static bool dummy; if (version64 < 6) out >> classId; // dummy value out >> name >> defaultValue >> dummy >> dummy; //attrFlags = ATTR_USER; // size must be converted if (version64 < 7) { if (id == "size") defaultValue = QSizeF(defaultValue.toDouble(), defaultValue.toDouble()); } if (version64 < 10) valueType = defaultValue.type(); else out >> valueType; return true; } // attribute constrains CAttributeConstrains::~CAttributeConstrains() { // dummy } qvge-0.6.3/src/qvge/CAttribute.h000066400000000000000000000055611405165517400164510ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include #include #include #include #include // attribute class struct CAttribute: public AttrInfo { CAttribute(); CAttribute(const QByteArray& attrId, const QString& attrName = QString()); CAttribute(const QByteArray& attrId, const QString& attrName, const QVariant& defaultValue, const int attrFlags = ATTR_NONE); /*const*/ int flags = ATTR_NONE; bool isUserDefined() const { return !(flags & ATTR_FIXED); } // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; virtual bool restoreFrom(QDataStream& out, quint64 version64); // dummy member QByteArray classId; }; typedef QMap AttributesMap; // typedef QMap ClassAttributesMap; // // attribute constrains typedef QPair ClassAttrIndex; struct CAttributeConstrains; typedef QMap AttributeConstrainsMap; struct CAttributeConstrains { virtual ~CAttributeConstrains(); }; // integer values struct CIntegerConstrains : public CAttributeConstrains { CIntegerConstrains(int minV = INT_MIN, int maxV = INT_MAX) { minValue = minV; maxValue = maxV; } CIntegerConstrains(CAttributeConstrains *ptr = NULL) { CIntegerConstrains *dptr = dynamic_cast(ptr); if (dptr) { minValue = dptr->minValue; maxValue = dptr->maxValue; } } int minValue = INT_MIN; int maxValue = INT_MAX; }; // double values struct CDoubleConstrains : public CAttributeConstrains { CDoubleConstrains(double minV, double maxV, int decs = 4) { minValue = minV; maxValue = maxV; decPoints = decs; } CDoubleConstrains(CAttributeConstrains *ptr = NULL) { CDoubleConstrains *dptr = dynamic_cast(ptr); if (dptr) { minValue = dptr->minValue; maxValue = dptr->maxValue; decPoints = dptr->decPoints; } } double minValue = std::numeric_limits::lowest(); double maxValue = std::numeric_limits::max(); int decPoints = 4; }; // list of id items typedef QList IconsList; struct CAttributeConstrainsListBase : public CAttributeConstrains { QStringList names; IconsList icons; // convenience method to conform property browser API QMap iconsAsMap() const { QMap result; for (int i = 0; i < icons.size(); ++i) result[i] = icons[i]; return result; } }; struct CAttributeConstrainsList: public CAttributeConstrainsListBase { QStringList ids; }; struct CAttributeConstrainsEnum : public CAttributeConstrainsListBase { QList ids; }; qvge-0.6.3/src/qvge/CControlPoint.cpp000066400000000000000000000023101405165517400174600ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CControlPoint.h" #include "CItem.h" CControlPoint::CControlPoint(CItem *parent) : Shape(dynamic_cast(parent)), m_parentItem(parent) { Q_ASSERT(parent != NULL); setRect(-4, -4, 8, 8); setBrush(Qt::black); setPen(QPen(Qt::gray, 1)); } // reimp QVariant CControlPoint::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { //if (change == ItemPositionChange) //{ // if (auto editScene = dynamic_cast(scene())) // { // return editScene->getSnapped(value.toPointF()); // } // return value; //} if (change == ItemPositionHasChanged) { m_parentItem->onControlPointMoved(this, value.toPointF()); return value; } return Shape::itemChange(change, value); } // menu bool CControlPoint::populateMenu(QMenu& menu, const QList& /*selectedItems*/) { /*QAction *deleteAction =*/ menu.addAction(tr("Delete point"), this, SLOT(onActionDelete())); return true; } void CControlPoint::onActionDelete() { m_parentItem->onControlPointDelete(this); } qvge-0.6.3/src/qvge/CControlPoint.h000066400000000000000000000013761405165517400171400ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include "IContextMenuProvider.h" class CItem; class CControlPoint : public QObject, public QGraphicsRectItem, public IContextMenuProvider { Q_OBJECT public: typedef QGraphicsRectItem Shape; explicit CControlPoint(CItem *parent); virtual ~CControlPoint() {} // menu virtual bool populateMenu(QMenu& menu, const QList& selectedItems); protected Q_SLOTS: void onActionDelete(); protected: // reimp virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); CItem *m_parentItem; }; qvge-0.6.3/src/qvge/CDiffUndoManager.cpp000066400000000000000000000052701405165517400200270ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CDiffUndoManager.h" #include "CEditorScene.h" #include CDiffUndoManager::CDiffUndoManager(CEditorScene & scene) : m_scene(&scene) { } void CDiffUndoManager::reset() { m_redoStack.clear(); m_undoStack.clear(); m_redoStackTemp.clear(); m_undoStackTemp.clear(); m_lastState.clear(); } void CDiffUndoManager::addState() { // drop temp stacks m_redoStack.clear(); m_undoStackTemp.clear(); // serialize & compress QByteArray snap; QDataStream ds(&snap, QIODevice::WriteOnly); m_scene->storeTo(ds, true); // check if 1st store if (m_lastState.isEmpty() && m_undoStack.isEmpty() && m_redoStack.isEmpty()) { m_lastState = snap; return; } // push states into stacks int leftDiffIndex = 0; int len = qMin(snap.size(), m_lastState.size()); while (leftDiffIndex < len && snap[leftDiffIndex] == m_lastState[leftDiffIndex]) ++leftDiffIndex; int rightDiffIndex1 = m_lastState.size() - 1; int rightDiffIndex2 = snap.size() - 1; while (rightDiffIndex1 >= 0 && rightDiffIndex2 >= 0 && rightDiffIndex1 > leftDiffIndex && rightDiffIndex2 > leftDiffIndex && snap[rightDiffIndex2] == m_lastState[rightDiffIndex1]) --rightDiffIndex1, --rightDiffIndex2; int len1 = rightDiffIndex1 - leftDiffIndex + 1; int len2 = rightDiffIndex2 - leftDiffIndex + 1; Command cUndo = { leftDiffIndex, len2, qCompress(m_lastState.mid(leftDiffIndex, len1)) }; Command cRedo = { leftDiffIndex, len1, qCompress(snap.mid(leftDiffIndex, len2)) }; m_undoStack << cUndo; m_redoStackTemp << cRedo; // write last state m_lastState = snap; } void CDiffUndoManager::revertState() { QDataStream ds(&m_lastState, QIODevice::ReadOnly); m_scene->restoreFrom(ds, true); } void CDiffUndoManager::undo() { if (availableUndoCount()) { Command cUndo = m_undoStack.takeLast(); m_lastState.replace(cUndo.index, cUndo.sizeToReplace, qUncompress(cUndo.data)); QDataStream ds(&m_lastState, QIODevice::ReadOnly); m_scene->restoreFrom(ds, true); m_redoStack << m_redoStackTemp.takeLast(); m_undoStackTemp << cUndo; } } void CDiffUndoManager::redo() { if (availableRedoCount()) { Command cRedo = m_redoStack.takeLast(); m_lastState.replace(cRedo.index, cRedo.sizeToReplace, qUncompress(cRedo.data)); QDataStream ds(&m_lastState, QIODevice::ReadOnly); m_scene->restoreFrom(ds, true); m_undoStack << m_undoStackTemp.takeLast(); m_redoStackTemp << cRedo; } } int CDiffUndoManager::availableUndoCount() const { return m_undoStack.size(); } int CDiffUndoManager::availableRedoCount() const { return m_redoStack.size(); } qvge-0.6.3/src/qvge/CDiffUndoManager.h000066400000000000000000000014751405165517400174770ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "IUndoManager.h" #include #include class CEditorScene; class CDiffUndoManager : public IUndoManager { public: CDiffUndoManager(CEditorScene &scene); // reimp virtual void reset(); virtual void addState(); virtual void revertState(); virtual void undo(); virtual void redo(); virtual int availableUndoCount() const; virtual int availableRedoCount() const; private: struct Command { int index; int sizeToReplace; QByteArray data; }; CEditorScene *m_scene; QList m_redoStack, m_undoStack; QList m_redoStackTemp, m_undoStackTemp; QByteArray m_lastState; }; qvge-0.6.3/src/qvge/CDirectEdge.cpp000066400000000000000000000163631405165517400170420ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include "CDirectEdge.h" #include "CNode.h" #include "CEditorSceneDefines.h" CDirectEdge::CDirectEdge(QGraphicsItem *parent): Super(parent) { m_bendFactor = 0; } void CDirectEdge::setBendFactor(int bf) { if (bf != m_bendFactor) { m_bendFactor = bf; onParentGeometryChanged(); } } // reimp CEdge* CDirectEdge::clone() { CDirectEdge* c = new CDirectEdge(parentItem()); // assign directly! c->m_firstNode = m_firstNode; c->m_firstPortId = m_firstPortId; c->m_lastNode = m_lastNode; c->m_lastPortId = m_lastPortId; if (scene()) scene()->addItem(c); c->copyDataFrom(this); return c; } void CDirectEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget* widget) { //qDebug() << boundingRect() << option->exposedRect << option->rect; // dont draw if no cache if (m_shapeCachePath.isEmpty()) return; // selection drawSelection(painter, option); // called before draw setupPainter(painter, option, widget); painter->setClipRect(boundingRect()); auto len = line().length(); bool isArrow = (len > ARROW_SIZE * 2); bool isDirect = (!isCircled() && (m_bendFactor == 0)); if (isDirect) // straight line { painter->setBrush(Qt::NoBrush); painter->drawPath(m_shapeCachePath); // arrows if (isArrow && m_itemFlags & CF_Start_Arrow) drawArrow(painter, option, true, QLineF(line().p2(), line().p1())); if (isArrow && m_itemFlags & CF_End_Arrow) drawArrow(painter, option, false, line()); } else // curve { painter->setBrush(Qt::NoBrush); painter->drawPath(m_shapeCachePath); // arrows if (isArrow && m_itemFlags & CF_Start_Arrow) { QLineF arrowLine = calculateArrowLine(m_shapeCachePath, true, QLineF(m_controlPos, line().p1())); drawArrow(painter, option, true, arrowLine); } if (isArrow && m_itemFlags & CF_End_Arrow) { QLineF arrowLine = calculateArrowLine(m_shapeCachePath, false, QLineF(m_controlPos, line().p2())); drawArrow(painter, option, false, arrowLine); } } } void CDirectEdge::updateLabelPosition() { auto r = m_labelItem->boundingRect(); int w = r.width(); int h = r.height(); m_labelItem->setTransformOriginPoint(w / 2, h / 2); if (isCircled()) { m_labelItem->setPos(m_controlPoint.x() - w / 2, m_controlPoint.y() - boundingRect().height() / 2 - h); m_labelItem->setRotation(0); } else { m_labelItem->setPos(m_controlPoint.x() - w / 2, m_controlPoint.y() - h / 2); // update label rotation //qreal angle = 180 - line().angle(); //if (angle > 90) angle -= 180; //else if (angle < -90) angle += 180; //qDebug() << angle; //m_labelItem->setRotation(angle); } } // callbacks void CDirectEdge::onParentGeometryChanged() { // optimize: no update while restoring if (s_duringRestore) return; if (!m_firstNode || !m_lastNode) return; prepareGeometryChange(); // update line position QPointF p1c = m_firstNode->pos(); if (m_firstPortId.size() && m_firstNode->getPort(m_firstPortId)) p1c = m_firstNode->getPort(m_firstPortId)->scenePos(); QPointF p2c = m_lastNode->pos(); if (m_lastPortId.size() && m_lastNode->getPort(m_lastPortId)) p2c = m_lastNode->getPort(m_lastPortId)->scenePos(); QPointF p1 = m_firstNode->getIntersectionPoint(QLineF(p1c, p2c), m_firstPortId); QPointF p2 = m_lastNode->getIntersectionPoint(QLineF(p2c, p1c), m_lastPortId); bool intersected = (!p1.isNull()) && (!p2.isNull()); QLineF l(p1, p2); setLine(l); // update shape path m_shapeCachePath = QPainterPath(); double arrowSize = getVisibleWeight() + ARROW_SIZE; // circled connection if (isCircled()) { int nodeDiameter = m_firstNode->boundingRect().height(); double nr = nodeDiameter; double r = nr + qAbs(m_bendFactor) * nr / 4; // left up point QPointF lp = p1c + QPointF(-r, -r); QPointF p1 = m_firstNode->getIntersectionPoint(QLineF(p1c, lp), m_firstPortId); // right up point QPointF rp = p2c + QPointF(r, -r); QPointF p2 = m_lastNode->getIntersectionPoint(QLineF(p2c, rp), m_lastPortId); // up point m_controlPos = (p1c + p2c) / 2 + QPointF(0, -r * 2); m_controlPoint = (lp + rp) / 2; QLineF l(p1, p2); setLine(l); createCurvedPath(true, l, QLineF(p1c, p2c), p1, lp, rp, p2, arrowSize); } else // not circled { // center m_controlPos = (p1c + p2c) / 2; if (m_bendFactor == 0) { // shift line by arrows auto len = l.length(); bool isArrow = (len > arrowSize * 2); if (isArrow && (m_itemFlags & CF_Mutual_Arrows)) { l = CUtils::extendLine(l, m_itemFlags & CF_Start_Arrow ? -arrowSize : 0, m_itemFlags & CF_End_Arrow ? arrowSize : 0); } m_shapeCachePath.moveTo(l.p1()); m_shapeCachePath.lineTo(l.p2()); #if QT_VERSION < 0x050a00 m_controlPoint = (line().p1() + line().p2()) / 2; #else m_controlPoint = line().center(); #endif auto fullLen = QLineF(p1c, p2c).length(); //qDebug() << len << fullLen; // if no intersection or len == fullLen : drop the shape if (!intersected || qAbs(len - fullLen) < 5) { m_shapeCachePath = QPainterPath(); } } else { QPointF t1 = m_controlPos; float posFactor = qAbs(m_bendFactor); bool bendDirection = (quint64(m_firstNode) > quint64(m_lastNode)); if (m_bendFactor < 0) bendDirection = !bendDirection; QLineF f1(t1, p2c); f1.setAngle(bendDirection ? f1.angle() + 90 : f1.angle() - 90); f1.setLength(f1.length() * 0.2 * posFactor); m_controlPos = f1.p2(); m_controlPoint = m_controlPos - (t1 - m_controlPos) * 0.33; createCurvedPath(intersected, l, QLineF(p1c, p2c), p1, m_controlPoint, m_controlPoint, p2, arrowSize); } } // rasterise the line stroke QPainterPathStroker stroker; stroker.setWidth(6); m_selectionShapePath = stroker.createStroke(m_shapeCachePath); //update(); // update text label if (getScene() && getScene()->itemLabelsEnabled()) { if (m_shapeCachePath.isEmpty()) { m_labelItem->hide(); } else { m_labelItem->show(); updateLabelPosition(); updateLabelDecoration(); } } } void CDirectEdge::createCurvedPath(bool intersected, const QLineF& shortLine, const QLineF& fullLine, const QPointF& p1, const QPointF& lp, const QPointF& rp, const QPointF& p2, double arrowSize) { auto len = shortLine.length(); auto fullLen = fullLine.length(); //qDebug() << len << fullLen; m_shapeCachePath = QPainterPath(); // if no intersection or len == fullLen : drop the shape if (!intersected || qAbs(len - fullLen) < 5) { } else { m_shapeCachePath.moveTo(p1); m_shapeCachePath.cubicTo(lp, rp, p2); // check arrows if (m_itemFlags & CF_Mutual_Arrows) { QPointF newP1 = p1, newP2 = p2; if (m_itemFlags & CF_Start_Arrow) { qreal arrowStart = m_shapeCachePath.percentAtLength(arrowSize); newP1 = m_shapeCachePath.pointAtPercent(arrowStart); } if (m_itemFlags & CF_End_Arrow) { qreal arrowStart = m_shapeCachePath.percentAtLength(m_shapeCachePath.length() - arrowSize); newP2 = m_shapeCachePath.pointAtPercent(arrowStart); } m_shapeCachePath = QPainterPath(); m_shapeCachePath.moveTo(newP1); m_shapeCachePath.cubicTo(lp, rp, newP2); } } } qvge-0.6.3/src/qvge/CDirectEdge.h000066400000000000000000000026331405165517400165020ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "CEdge.h" class CDirectEdge : public CEdge { public: typedef CEdge Super; CDirectEdge(QGraphicsItem *parent = Q_NULLPTR); void setBendFactor(int bf); // reimp static QByteArray factoryId() { return "CDirectEdge"; } virtual QByteArray typeId() const { return this->factoryId(); } virtual QByteArray classId() const { return "edge"; } virtual QByteArray superClassId() const { return Super::classId(); } virtual CItem* create() const { return new CDirectEdge(parentItem()); } CEdge* clone(); virtual QPointF getLabelCenter() const { return m_controlPoint; } // transformations virtual void transform(const QRectF& oldRect, const QRectF& newRect, double xc, double yc, bool changeSize, bool changePos) override {} protected: // reimp virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR); virtual void updateLabelPosition(); // callbacks virtual void onParentGeometryChanged(); private: void createCurvedPath(bool intersected, const QLineF& shortLine, const QLineF& fullLine, const QPointF& p1, const QPointF& lp, const QPointF& rp, const QPointF& p2, double arrowSize); protected: int m_bendFactor; QPointF m_controlPoint, m_controlPos; }; qvge-0.6.3/src/qvge/CEdge.cpp000066400000000000000000000233061405165517400157020ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CEdge.h" #include "CNode.h" #include "CEditorSceneDefines.h" #include #include #include #include #include #define _USE_MATH_DEFINES #include CEdge::CEdge(QGraphicsItem *parent): Shape(parent) { m_firstNode = m_lastNode = NULL; setZValue(-1); //setBoundingRegionGranularity(1); // non-movable but selectable auto flags = ItemIsSelectable | ItemSendsGeometryChanges | ItemIsMovable | ItemUsesExtendedStyleOption; setFlags(flags); // no selection frame setItemFlag(IF_FramelessSelection); // accept hovers setAcceptHoverEvents(true); // cache //setCacheMode(DeviceCoordinateCache); // label m_labelItem = new QGraphicsSimpleTextItem(this); m_labelItem->setFlags(0); m_labelItem->setCacheMode(DeviceCoordinateCache); m_labelItem->setPen(Qt::NoPen); m_labelItem->setAcceptedMouseButtons(Qt::NoButton); } CEdge::~CEdge() { if (m_firstNode) m_firstNode->onConnectionDeleted(this); if (m_lastNode && m_lastNode != m_firstNode) m_lastNode->onConnectionDeleted(this); } // attributes bool CEdge::hasLocalAttribute(const QByteArray& attrId) const { if (attrId == attr_edge_direction) return true; else return Super::hasLocalAttribute(attrId); } bool CEdge::setAttribute(const QByteArray& attrId, const QVariant& v) { if (attrId == attr_edge_direction) { updateArrowFlags(v.toString()); } bool res = Super::setAttribute(attrId, v); if (res) update(); return res; } bool CEdge::removeAttribute(const QByteArray& attrId) { bool res = Super::removeAttribute(attrId); if (attrId == attr_edge_direction) { updateArrowFlags(getAttribute(attr_edge_direction).toString()); } if (res) update(); return res; } // cached attributes void CEdge::updateCachedItems() { Super::updateCachedItems(); updateArrowFlags(getAttribute(attr_edge_direction).toString()); } void CEdge::updateArrowFlags(const QString& direction) { if (direction == "directed") { setItemFlag(CF_End_Arrow); resetItemFlag(CF_Start_Arrow); } else if (direction == "mutual") { setItemFlag(CF_Mutual_Arrows); } else if (direction == "undirected") { resetItemFlag(CF_Mutual_Arrows); } } // reimp QRectF CEdge::boundingRect() const { return Shape::boundingRect().adjusted(-10,-10,10,10); } void CEdge::setupPainter(QPainter *painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) { double weight = getVisibleWeight(); Qt::PenStyle penStyle = (Qt::PenStyle) CUtils::textToPenStyle(getAttribute(attr_style).toString(), Qt::SolidLine); // get color (to optimize!) QColor color = getAttribute(attr_color).value(); QPen p(color, weight, penStyle, Qt::FlatCap, Qt::RoundJoin); painter->setPen(p); painter->setOpacity(1.0); } void CEdge::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *option) const { bool isSelected = (option->state & QStyle::State_Selected); if (isSelected) { double weight = getVisibleWeight(); QPen p(QColor(Qt::darkCyan), weight * 2 + 2, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); painter->setOpacity(0.3); painter->setPen(p); painter->setBrush(Qt::NoBrush); painter->drawPath(m_shapeCachePath); } } double CEdge::getWeight() const { bool ok = false; double weight = getAttribute(attr_weight).toDouble(&ok); return ok ? weight : 1; } double CEdge::getVisibleWeight() const { bool ok = false; double weight = qMax(0.1, getAttribute(attr_weight).toDouble(&ok)); if (!ok) return 1; else if (weight > 10) weight = 10; // safety return weight; } QLineF CEdge::calculateArrowLine(const QPainterPath &path, bool first, const QLineF &direction) const { //// optimization: disable during drag or pan //Qt::MouseButtons buttons = QGuiApplication::mouseButtons(); //if ((buttons & Qt::LeftButton) || (buttons & Qt::RightButton)) // return direction; //// optimization: disable during zoom //Qt::KeyboardModifiers keys = QGuiApplication::keyboardModifiers(); //if (keys & Qt::ControlModifier) // return direction; if (first && m_firstNode) { qreal arrowStart = path.percentAtLength(ARROW_SIZE); return QLineF(path.pointAtPercent(arrowStart), direction.p2()); } else if (!first && m_lastNode) { qreal len = path.length(); qreal arrowStart = path.percentAtLength(len - ARROW_SIZE); return QLineF(path.pointAtPercent(arrowStart), direction.p2()); } return direction; } void CEdge::drawArrow(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, bool first, const QLineF& direction) const { if (first && m_firstNode) { drawArrow(painter, 0, direction); } else if (!first && m_lastNode) { drawArrow(painter, 0, direction); } } void CEdge::drawArrow(QPainter* painter, qreal /*shift*/, const QLineF& direction) const { static QPolygonF arrowHead; if (arrowHead.isEmpty()) arrowHead << QPointF(0, 0) << QPointF(-ARROW_SIZE/2, ARROW_SIZE) << QPointF(ARROW_SIZE/2, ARROW_SIZE) << QPointF(0, 0); QPen oldPen = painter->pen(); painter->save(); painter->setPen(QPen(oldPen.color(), oldPen.widthF(), Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin)); painter->setBrush(oldPen.color()); static QLineF hl(0, 0, 0, 100); qreal a = direction.angleTo(hl); painter->translate(direction.p2()); painter->rotate(180 + a); painter->translate(QPointF(0, oldPen.widthF())); painter->drawPolygon(arrowHead); painter->restore(); } // IO bool CEdge::storeTo(QDataStream &out, quint64 version64) const { Super::storeTo(out, version64); out << quint64(m_firstNode) << quint64(m_lastNode); // since version 11 out << m_firstPortId << m_lastPortId; return true; } bool CEdge::restoreFrom(QDataStream &out, quint64 version64) { if (Super::restoreFrom(out, version64)) { // these are TEMP ids out >> m_tempFirstNodeId >> m_tempLastNodeId; if (version64 >= 11) out >> m_firstPortId >> m_lastPortId; return true; } return false; } bool CEdge::linkAfterRestore(const CItemLinkMap &idToItem) { //qDebug() << m_tempFirstNodeId << m_tempLastNodeId; auto p1 = idToItem[m_tempFirstNodeId]; auto p2 = idToItem[m_tempLastNodeId]; CNode *node1 = dynamic_cast(p1); CNode *node2 = dynamic_cast(p2); m_firstNode = m_lastNode = nullptr; setFirstNode(node1, m_firstPortId); setLastNode(node2, m_lastPortId); return true; } bool CEdge::linkAfterPaste(const CItemLinkMap& idToItem) { bool res = linkAfterRestore(idToItem); return res && isValid(); } // impl void CEdge::setFirstNode(CNode *node, const QByteArray& portId) { if (m_firstNode && m_firstNode != node) m_firstNode->onConnectionDetach(this); m_firstNode = node; if (m_firstPortId != portId) m_firstPortId = portId; if (m_firstNode) m_firstNode->onConnectionAttach(this); onParentGeometryChanged(); } void CEdge::setLastNode(CNode *node, const QByteArray& portId) { if (m_lastNode && m_lastNode != node) m_lastNode->onConnectionDetach(this); m_lastNode = node; if (m_lastPortId != portId) m_lastPortId = portId; if (m_lastNode) m_lastNode->onConnectionAttach(this); onParentGeometryChanged(); } bool CEdge::reattach(CNode *oldNode, CNode *newNode, const QByteArray& portId) { if (newNode && oldNode == newNode && !newNode->allowCircledConnection()) return false; bool done = false; if (m_firstNode == oldNode) setFirstNode(newNode, portId), done = true; if (m_lastNode == oldNode) setLastNode(newNode, portId), done = true; return done; } bool CEdge::reattach(CNode *node, const QByteArray& oldPortId, const QByteArray& newPortId) { if (node == nullptr) return false; if (oldPortId == newPortId && !node->allowCircledConnection()) return false; bool done = false; if (m_firstNode == node && m_firstPortId == oldPortId) setFirstNode(node, newPortId), done = true; if (m_lastNode == node && m_lastPortId == oldPortId) setLastNode(node, newPortId), done = true; return done; } void CEdge::reverse() { qSwap(m_firstNode, m_lastNode); qSwap(m_firstPortId, m_lastPortId); onParentGeometryChanged(); } // reimp QString CEdge::createNewId() const { static const QString tmpl("E%1"); return createUniqueId(tmpl); } // callbacks void CEdge::onNodeMoved(CNode *node) { Q_UNUSED(node); Q_ASSERT(node == m_firstNode || node == m_lastNode); Q_ASSERT(node != NULL); onParentGeometryChanged(); } void CEdge::onNodeDetached(CNode *node) { if (node == m_firstNode) { m_firstNode = NULL; } if (node == m_lastNode) { m_lastNode = NULL; } } void CEdge::onNodeDeleted(CNode *node) { onNodeDetached(node); delete this; // die as well } void CEdge::onNodePortDeleted(CNode *node, const QByteArray& portId) { reattach(node, portId, ""); } void CEdge::onNodePortRenamed(CNode *node, const QByteArray& portId, const QByteArray& oldPortId) { if (m_firstNode == node && m_firstPortId == oldPortId) m_firstPortId = portId; if (m_lastNode == node && m_lastPortId == oldPortId) m_lastPortId = portId; } // reimp void CEdge::onItemRestored() { updateCachedItems(); onParentGeometryChanged(); } QVariant CEdge::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { if (change == ItemSceneHasChanged) { // set default ID setDefaultId(); onItemRestored(); return value; } if (change == ItemPositionChange) { // discard any movement return QVariant(); } if (change == ItemPositionHasChanged) { // discard any movement return QVariant(); } if (change == ItemSelectedHasChanged) { onItemSelected(value.toBool()); return value; } return value; } void CEdge::hoverEnterEvent(QGraphicsSceneHoverEvent* event) { onHoverEnter(this, event); } qvge-0.6.3/src/qvge/CEdge.h000066400000000000000000000072531405165517400153520ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CEdge_H #define CEdge_H #include #include #include #include "CItem.h" class CNode; enum ConnectionFlags // extends ItemFlags { CF_Start_Arrow = IF_LastFlag, CF_End_Arrow = IF_LastFlag << 2, CF_Mutual_Arrows = CF_Start_Arrow | CF_End_Arrow // start | end }; class CEdge : public CItem, public QGraphicsLineItem { public: typedef CItem Super; typedef QGraphicsLineItem Shape; CEdge(QGraphicsItem *parent = Q_NULLPTR); virtual ~CEdge(); // public void setFirstNode(CNode *node, const QByteArray& portId = ""); void setLastNode(CNode *node, const QByteArray& portId = ""); bool reattach(CNode *oldNode, CNode *newNode, const QByteArray& portId = ""); bool reattach(CNode *node, const QByteArray& oldPortId, const QByteArray& newPortId); CNode* firstNode() const { return m_firstNode; } CNode* lastNode() const { return m_lastNode; } const QByteArray& firstPortId() const { return m_firstPortId; } const QByteArray& lastPortId() const { return m_lastPortId; } bool isValid() const { return m_firstNode != NULL && m_lastNode != NULL; } bool isCircled() const { return isValid() && m_firstNode == m_lastNode; } double getWeight() const; virtual void reverse(); // reimp virtual QString createNewId() const; // reimp virtual ItemDragTestResult acceptDragFromItem(QGraphicsItem* /*draggedItem*/) { return Ignored; } // reimp virtual QRectF boundingRect() const; virtual QPainterPath shape() const { return m_selectionShapePath; } // attributes virtual bool hasLocalAttribute(const QByteArray& attrId) const; virtual bool setAttribute(const QByteArray& attrId, const QVariant& v); virtual bool removeAttribute(const QByteArray& attrId); // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; virtual bool restoreFrom(QDataStream& out, quint64 version64); virtual bool linkAfterRestore(const CItemLinkMap& idToItem); virtual bool linkAfterPaste(const CItemLinkMap& idToItem); // callbacks virtual void onNodeMoved(CNode *node); virtual void onNodeDetached(CNode *node); virtual void onNodeDeleted(CNode *node); virtual void onNodePortDeleted(CNode *node, const QByteArray& portId); virtual void onNodePortRenamed(CNode *node, const QByteArray& portId, const QByteArray& oldId); virtual void onParentGeometryChanged() = 0; virtual void onItemRestored(); protected: /*virtual*/ void setupPainter(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR); /*virtual*/ void drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *option) const; /*virtual*/ void drawArrow(QPainter *painter, const QStyleOptionGraphicsItem *option, bool first, const QLineF &direction) const; /*virtual*/ void drawArrow(QPainter *painter, qreal shift, const QLineF &direction) const; QLineF calculateArrowLine(const QPainterPath &path, bool first, const QLineF &direction) const; // reimp virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); // cached attributes virtual void updateCachedItems(); virtual void updateArrowFlags(const QString& direction); double getVisibleWeight() const; protected: CNode *m_firstNode = nullptr; quint64 m_tempFirstNodeId = 0; CNode *m_lastNode = nullptr; quint64 m_tempLastNodeId = 0; QByteArray m_firstPortId, m_lastPortId; QPainterPath m_selectionShapePath; QPainterPath m_shapeCachePath; const int ARROW_SIZE = 6; }; #endif // CEdge_H qvge-0.6.3/src/qvge/CEditorScene.cpp000066400000000000000000001326471405165517400172530ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016 Ars L.Masiuk(ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CEditorScene.h" #include "CEditorScene_p.h" #include "CEditorSceneDefines.h" #include "CEditorSceneActions.h" #include "CItem.h" #include "CControlPoint.h" #include "CSimpleUndoManager.h" #include "CDiffUndoManager.h" #include "IContextMenuProvider.h" #include "ISceneItemFactory.h" #include "ISceneMenuController.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include const quint64 version64 = 12; // build const char* versionId = "VersionId"; CEditorScene::CEditorScene(QObject *parent): Super(parent), m_doubleClick(false), m_dragInProgress(false), m_startDragItem(nullptr), m_draggedItem(nullptr), m_pimpl(new CEditorScene_p(this)), m_infoStatus(-1), //m_undoManager(new CSimpleUndoManager(*this)), m_undoManager(new CDiffUndoManager(*this)), m_menuTriggerItem(nullptr), m_needUpdateItems(true), m_labelsEnabled(true), m_labelsUpdate(false), m_isFontAntialiased(true) { m_gridSize = 25; m_gridEnabled = true; m_gridSnap = true; m_gridPen = QPen(Qt::gray, 0, Qt::DotLine); setBackgroundBrush(Qt::white); setSceneRect(-500, -500, 1000, 1000); // optimizations setItemIndexMethod(QGraphicsScene::NoIndex); setMinimumRenderSize(5); QPixmapCache::setCacheLimit(100000); // connections connect(this, &CEditorScene::selectionChanged, this, &CEditorScene::onSelectionChanged, Qt::DirectConnection); connect(this, &CEditorScene::focusItemChanged, this, &CEditorScene::onFocusItemChanged); } CEditorScene::~CEditorScene() { disconnect(); clear(); delete m_pimpl; } void CEditorScene::reset() { initialize(); if (m_undoManager) m_undoManager->reset(); setSceneRect(QRectF(-500,-500,1000,1000)); } void CEditorScene::initialize() { removeItems(); m_classAttributes.clear(); m_classAttributesVis.clear(); m_classAttributesConstrains.clear(); // default item attrs createClassAttribute(class_item, "label", "Label", "", ATTR_NODEFAULT | ATTR_FIXED, nullptr, true); createClassAttribute(class_item, "label.color", "Label Color", QColor(Qt::black)); QFont labelFont; CAttribute labelFontAttr("label.font", "Label Font", labelFont, ATTR_FIXED); setClassAttribute(class_item, labelFontAttr); createClassAttribute(class_item, "id", "ID", "", ATTR_NODEFAULT | ATTR_FIXED, nullptr, true); // labels policy static CAttributeConstrainsEnum *labelsPolicy = new CAttributeConstrainsEnum(); if (labelsPolicy->ids.isEmpty()) { labelsPolicy->names << tr("Auto") << tr("Always On") << tr("Always Off"); labelsPolicy->ids << Auto << AlwaysOn << AlwaysOff; } createClassAttribute(class_scene, attr_labels_policy, "Labels Policy", Auto, ATTR_FIXED, labelsPolicy); } void CEditorScene::removeItems() { CItem::beginRestore(); deselectAll(); while (!items().isEmpty()) delete items().first(); clear(); CItem::endRestore(); } // properties void CEditorScene::setGridSize(int newSize) { if (newSize <= 0) return; m_gridSize = newSize; update(); } void CEditorScene::enableGrid(bool on) { m_gridEnabled = on; update(); } void CEditorScene::enableGridSnap(bool on) { m_gridSnap = on; } void CEditorScene::setGridPen(const QPen &gridPen) { m_gridPen = gridPen; update(); } void CEditorScene::enableItemLabels(bool on) { m_labelsEnabled = on; layoutItemLabels(); } void CEditorScene::setFontAntialiased(bool on) { m_isFontAntialiased = on; layoutItemLabels(); update(); } void CEditorScene::copyProperties(const CEditorScene& from) { m_classAttributes = from.m_classAttributes; m_classToSuperIds = from.m_classToSuperIds; m_classAttributesVis = from.m_classAttributesVis; } CEditorScene* CEditorScene::clone() { QByteArray buffer; QDataStream out(&buffer, QIODevice::WriteOnly); if (!storeTo(out, true)) return nullptr; CEditorScene* tempScene = createScene(); QDataStream in(buffer); if (tempScene->restoreFrom(in, true)) return tempScene; delete tempScene; return nullptr; } // undo-redo void CEditorScene::undo() { if (m_inProgress) return; m_inProgress = true; if (m_undoManager) { m_undoManager->undo(); checkUndoState(); onSceneChanged(); } m_inProgress = false; } void CEditorScene::redo() { if (m_inProgress) return; m_inProgress = true; if (m_undoManager) { m_undoManager->redo(); checkUndoState(); onSceneChanged(); } m_inProgress = false; } void CEditorScene::addUndoState() { if (m_inProgress) return; m_inProgress = true; onSceneChanged(); // canvas size QRectF minRect(sceneRect()); minRect |= itemsBoundingRect().adjusted(-10, -10, 10, 10); setSceneRect(minRect); // undo-redo if (m_undoManager) { m_undoManager->addState(); checkUndoState(); } m_inProgress = false; } void CEditorScene::revertUndoState() { if (m_inProgress) return; m_inProgress = true; if (m_undoManager) { m_undoManager->revertState(); checkUndoState(); } onSceneChanged(); m_inProgress = false; } void CEditorScene::setInitialState() { m_inProgress = false; if (m_undoManager) { m_undoManager->reset(); } addUndoState(); } int CEditorScene::availableUndoCount() const { return m_undoManager ? m_undoManager->availableUndoCount() : 0; } int CEditorScene::availableRedoCount() const { return m_undoManager ? m_undoManager->availableRedoCount() : 0; } void CEditorScene::checkUndoState() { Q_EMIT undoAvailable(m_undoManager->availableUndoCount() > 0); Q_EMIT redoAvailable(m_undoManager->availableRedoCount() > 0); } // io bool CEditorScene::storeTo(QDataStream& out, bool storeOptions) const { out << versionId << version64; // items QMap sortedMap; QList allItems = items(); for (QGraphicsItem* item : allItems) { CItem* citem = dynamic_cast(item); if (citem) { sortedMap[citem] = quint64(citem); } } for (CItem* citem : sortedMap.keys()) { out << citem->typeId() << quint64(citem); citem->storeTo(out, version64); } // attributes out << QByteArray("_attr_"); out << (quint64)0x12345678; out << m_classAttributes.size(); for (auto classAttrsIt = m_classAttributes.constBegin(); classAttrsIt != m_classAttributes.constEnd(); ++classAttrsIt) { out << classAttrsIt.key(); out << classAttrsIt.value().size(); for (const auto &attr : classAttrsIt.value()) { attr.storeTo(out, version64); } } out << m_classToSuperIds; // visible attributes out << m_classAttributesVis; // options if (storeOptions) { out << backgroundBrush(); out << m_gridPen; out << m_gridSize; out << m_gridEnabled << m_gridSnap; } // 9+: scene rect out << sceneRect(); return true; } bool CEditorScene::restoreFrom(QDataStream& out, bool readOptions) { initialize(); // version quint64 storedVersion = 0; // read CItem::CItemLinkMap idToItem; while (!out.atEnd()) { QByteArray id; out >> id; quint64 ptrId; out >> ptrId; if (storedVersion == 0 && strcmp(id.data(), versionId) == 0) { storedVersion = ptrId; out >> id >> ptrId; } // started attr section if (storedVersion >= 3 && id == "_attr_" && ptrId == 0x12345678) break; CItem* item = createItemOfType(id); if (item) { if (item->restoreFrom(out, storedVersion)) { idToItem[ptrId] = item; continue; } } // failed: cleanup qDeleteAll(idToItem.values()); return false; } // link items CItem::beginRestore(); for (CItem* item : idToItem.values()) { if (item->linkAfterRestore(idToItem)) { addItem(dynamic_cast(item)); } else { // failed: cleanup qDeleteAll(idToItem.values()); clear(); CItem::endRestore(); return false; } } // attributes if (storedVersion >= 3) { int classAttrSize = 0; out >> classAttrSize; for (int i = 0; i < classAttrSize; ++i) { QByteArray classId; if (storedVersion >= 6) out >> classId; int attrSize = 0; out >> attrSize; for (int j = 0; j < attrSize; ++j) { CAttribute attr; if (attr.restoreFrom(out, storedVersion)) { if (storedVersion < 6) classId = attr.classId; // deprecated for now setClassAttribute(classId, attr); } else { CItem::endRestore(); return false; } } } } // visible attributes if (storedVersion >= 5) { out >> m_classToSuperIds; out >> m_classAttributesVis; } // options if (readOptions && storedVersion >= 8) { QBrush b; out >> b; setBackgroundBrush(b); out >> m_gridPen; out >> m_gridSize; out >> m_gridEnabled >> m_gridSnap; } // scene rect if (storedVersion >= 9) { QRectF sr; out >> sr; setSceneRect(sr); } // finish CItem::endRestore(); for (CItem* item : idToItem.values()) { item->onItemRestored(); } return true; } // factorization bool CEditorScene::setItemFactory(CItem *factoryItem, const QByteArray& typeId) { if (factoryItem) { // register class inheritance QByteArray classId = factoryItem->classId(); QByteArray superClassId = factoryItem->superClassId(); m_classToSuperIds[classId] = superClassId; QByteArray id = typeId.isEmpty() ? factoryItem->typeId() : typeId; m_itemFactories[id] = factoryItem; return true; } return false; } CItem* CEditorScene::getItemFactory(const QByteArray& typeId) const { return m_itemFactories.contains(typeId) ? m_itemFactories[typeId] : NULL; } CItem* CEditorScene::createItemOfType(const QByteArray &id) const { // check for filter if (m_itemFactoryFilter) { if (CItem* item = m_itemFactoryFilter->createItemOfType(id, *this)) return item; } // else default creation if (m_itemFactories.contains(id)) { return m_itemFactories[id]->create(); } return NULL; } // attributes CAttribute& CEditorScene::createClassAttribute( const QByteArray& classId, const QByteArray& attrId, const QString& attrName, const QVariant& defaultValue, int attrFlags, CAttributeConstrains* constrains, bool vis) { if (m_classAttributes[classId].contains(attrId)) { // just update the value m_classAttributes[classId][attrId].defaultValue = defaultValue; } else { m_classAttributes[classId][attrId] = CAttribute(attrId, attrName, defaultValue, attrFlags); setClassAttributeVisible(classId, attrId, vis); if (constrains) setClassAttributeConstrains(classId, attrId, constrains); } return m_classAttributes[classId][attrId]; } void CEditorScene::setClassAttribute(const QByteArray& classId, const CAttribute& attr, bool vis) { // only update value if exists if (m_classAttributes[classId].contains(attr.id)) m_classAttributes[classId][attr.id].defaultValue = attr.defaultValue; else // else insert m_classAttributes[classId][attr.id] = attr; setClassAttributeVisible(classId, attr.id, vis); needUpdate(); } void CEditorScene::setClassAttribute(const QByteArray& classId, const QByteArray& attrId, const QVariant& defaultValue) { if (m_classAttributes[classId].contains(attrId)) { // just update the value m_classAttributes[classId][attrId].defaultValue = defaultValue; needUpdate(); return; } // clone from super if not found auto superId = getSuperClassId(classId); while (!superId.isEmpty() && !m_classAttributes[superId].contains(attrId)) { superId = getSuperClassId(superId); } if (!superId.isEmpty()) { auto attr = m_classAttributes[superId][attrId]; attr.defaultValue = defaultValue; m_classAttributes[classId][attrId] = attr; needUpdate(); return; } // else create new attribute with name = id CAttribute attr(attrId, attrId, defaultValue); m_classAttributes[classId][attrId] = attr; needUpdate(); } bool CEditorScene::removeClassAttribute(const QByteArray& classId, const QByteArray& attrId) { auto it = m_classAttributes.find(classId); if (it == m_classAttributes.end()) return false; needUpdate(); return (*it).remove(attrId); } void CEditorScene::setClassAttributeVisible(const QByteArray& classId, const QByteArray& attrId, bool vis) { if (vis == m_classAttributesVis[classId].contains(attrId)) return; if (vis) m_classAttributesVis[classId].insert(attrId); else m_classAttributesVis[classId].remove(attrId); // set label update flag m_labelsUpdate = true; // schedule update invalidate(); } bool CEditorScene::isClassAttributeVisible(const QByteArray& classId, const QByteArray& attrId) const { return m_classAttributesVis[classId].contains(attrId); } QSet CEditorScene::getVisibleClassAttributes(const QByteArray& classId, bool inherited) const { QSet result = m_classAttributesVis[classId]; if (inherited) { QByteArray superId = getSuperClassId(classId); while (!superId.isEmpty()) { result = result.unite(m_classAttributesVis[superId]); superId = getSuperClassId(superId); } } return result; } void CEditorScene::setVisibleClassAttributes(const QByteArray& classId, const QSet& vis) { m_classAttributesVis[classId] = vis; // set label update flag m_labelsUpdate = true; // schedule update invalidate(); } const CAttribute CEditorScene::getClassAttribute(const QByteArray& classId, const QByteArray& attrId, bool inherited) const { CAttribute attr = m_classAttributes[classId][attrId]; if (attr.id.size() || !inherited) return attr; // else inherited QByteArray superId = getSuperClassId(classId); if (superId.isEmpty()) // fail return CAttribute(); return getClassAttribute(superId, attrId, true); } AttributesMap CEditorScene::getClassAttributes(const QByteArray& classId, bool inherited) const { AttributesMap result = m_classAttributes[classId]; if (inherited) { QByteArray superId = getSuperClassId(classId); while (!superId.isEmpty()) { //result = result.unite(m_classAttributes[superId]); // unite does not check for existing elements :( // there must be insertUnique CUtils::insertUnique(result, m_classAttributes[superId]); superId = getSuperClassId(superId); } } return result; } CAttributeConstrains* CEditorScene::getClassAttributeConstrains(const QByteArray& classId, const QByteArray& attrId) const { ClassAttrIndex index(classId, attrId); if (m_classAttributesConstrains.contains(index)) return m_classAttributesConstrains[index]; else return nullptr; } void CEditorScene::setClassAttributeConstrains(const QByteArray& classId, const QByteArray& attrId, CAttributeConstrains* cptr) { ClassAttrIndex index(classId, attrId); // do we need to clean up? //if (m_classAttributesConstrains.contains(index)) // delete m_classAttributesConstrains[index]; if (cptr) m_classAttributesConstrains[index] = cptr; else m_classAttributesConstrains.remove(index); } // copy-paste void CEditorScene::cut() { copy(); del(); } void CEditorScene::del() { QList itemList = createSelectedList(CDeletableItems()); if (itemList.isEmpty()) return; beginSelection(); for (QGraphicsItem* item : itemList) { if (items().contains(item)) delete item; } endSelection(); addUndoState(); } void CEditorScene::copy() { // store selected items only QMap sortedMap; QList allItems = getCopyPasteItems(); for (QGraphicsItem* item : allItems) { if (CItem* citem = dynamic_cast(item)) { sortedMap[citem] = quint64(citem); } } if (sortedMap.isEmpty()) { QApplication::clipboard()->clear(); return; } // write version and items QByteArray buffer; QDataStream out(&buffer, QIODevice::WriteOnly); out << version64; for (CItem* citem : sortedMap.keys()) { out << citem->typeId() << quint64(citem); citem->storeTo(out, version64); } // create mime object QMimeData* mimeData = new QMimeData; mimeData->setData("qvge/selection", buffer); QApplication::clipboard()->setMimeData(mimeData); // paste it to a temp scene & render into mime image CEditorScene* tempScene = createScene(); tempScene->copyProperties(*this); tempScene->enableGrid(false); tempScene->paste(); tempScene->deselectAll(); tempScene->crop(); QImage image(tempScene->sceneRect().size().toSize(), QImage::Format_ARGB32); image.fill(Qt::white); QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); tempScene->render(&painter); painter.end(); mimeData->setImageData(QVariant(image)); QApplication::clipboard()->setMimeData(mimeData); delete tempScene; } void CEditorScene::paste() { if (!m_pastePos.isNull()) { pasteAt(m_pastePos); return; } auto *view = getCurrentView(); if (view) { if (view->underMouse()) { auto p = view->mapFromGlobal(QCursor::pos()); pasteAt(view->mapToScene(p)); } else { QRectF vp = view->mapToScene(view->viewport()->geometry()).boundingRect(); auto center = vp.center(); pasteAt(center); } } else { pasteAt(QPointF()); } } void CEditorScene::pasteAt(const QPointF &anchor) { const QClipboard *clipboard = QApplication::clipboard(); const QMimeData *mimeData = clipboard->mimeData(); if (!mimeData) return; if (!mimeData->hasFormat("qvge/selection")) return; deselectAll(); // read items from the buffer QByteArray buffer = mimeData->data("qvge/selection"); QDataStream out(buffer); // version quint64 storedVersion = 0; out >> storedVersion; CItem::CItemLinkMap idToItem; QList deathList, lifeList; while (!out.atEnd()) { QByteArray typeId; out >> typeId; quint64 ptrId; out >> ptrId; CItem* item = createItemOfType(typeId); if (item) { if (item->restoreFrom(out, storedVersion)) { idToItem[ptrId] = item; } else deathList << item; } } // link items QSignalBlocker blocker(this); for (CItem* item : idToItem.values()) { if (item->linkAfterPaste(idToItem)) { auto sceneItem = dynamic_cast(item); addItem(sceneItem); sceneItem->setSelected(true); lifeList << item; } else deathList << item; } // cleanup qDeleteAll(deathList); if (lifeList.isEmpty()) return; // shift & rename pasted items which were not removed QMap ids; auto allItems = getItems(); for (auto item : allItems) ids[item->getId() + item->typeId()]++; // shift if not in-place auto selItems = selectedItems(); if (!anchor.isNull()) { QRectF r = CUtils::getBoundingRect(selItems); QPointF d = anchor - r.center(); moveSelectedItemsBy(d); } // rename pasted items for (auto sceneItem : selItems) { CItem* item = dynamic_cast(sceneItem); if (item) { QString id = item->getId(); QString typeId = item->typeId(); if (ids[id + typeId] > 1) { int counter = 1; QString newId = id; while (ids.contains(newId + typeId)) newId = QString("Copy%1 of %2").arg(counter++).arg(id); item->setId(newId); } } } for (CItem* item : idToItem.values()) { item->onItemRestored(); } blocker.unblock(); Q_EMIT selectionChanged(); // finish addUndoState(); } QList CEditorScene::getCopyPasteItems() const { return selectedItems(); } QList CEditorScene::cloneSelectedItems() { QList clonedList; // store selected items only QMap sortedMap; QList allItems = getCopyPasteItems(); for (QGraphicsItem* item : allItems) { if (CItem* citem = dynamic_cast(item)) { sortedMap[citem] = quint64(citem); } } if (sortedMap.isEmpty()) return clonedList; // write version and items QByteArray buffer; { QDataStream out(&buffer, QIODevice::WriteOnly); for (CItem* citem : sortedMap.keys()) { out << citem->typeId() << quint64(citem); citem->storeTo(out, version64); } } // read cloned items from the buffer deselectAll(); CItem::CItemLinkMap idToItem; QList deathList; { QDataStream in(buffer); while (!in.atEnd()) { QByteArray typeId; in >> typeId; quint64 ptrId; in >> ptrId; CItem* item = createItemOfType(typeId); if (item) { if (item->restoreFrom(in, version64)) { idToItem[ptrId] = item; } else deathList << item; } } } // link items QSignalBlocker blocker(this); for (CItem* item : idToItem.values()) { if (item->linkAfterPaste(idToItem)) { auto sceneItem = dynamic_cast(item); addItem(sceneItem); sceneItem->setSelected(true); clonedList << item; } else deathList << item; } // cleanup qDeleteAll(deathList); if (clonedList.isEmpty()) return clonedList; // shift & rename pasted items which were not removed QMap ids; auto allCItems = getItems(); for (auto item : allCItems) ids[item->getId() + item->typeId()]++; // shift if not in-place auto selItems = selectedItems(); // rename pasted items for (auto sceneItem : selItems) { CItem* item = dynamic_cast(sceneItem); if (item) { QString id = item->getId(); QString typeId = item->typeId(); if (ids[id + typeId] > 1) { int counter = 1; QString newId = id; while (ids.contains(newId + typeId)) newId = QString("Copy%1 of %2").arg(counter++).arg(id); item->setId(newId); } } } for (CItem* item : idToItem.values()) { item->onItemRestored(); } blocker.unblock(); Q_EMIT selectionChanged(); return clonedList; } // crop void CEditorScene::crop() { QRectF itemsRect = itemsBoundingRect().adjusted(-20, -20, 20, 20); if (itemsRect == sceneRect()) return; // update scene rect setSceneRect(itemsRect); addUndoState(); } // transform QList CEditorScene::getTransformableItems() const { return selectedItems(); } // callbacks void CEditorScene::onItemDestroyed(CItem *citem) { Q_ASSERT(citem); } void CEditorScene::onSceneChanged() { Q_EMIT sceneChanged(); layoutItemLabels(); if (m_editController) { m_editController->onSceneChanged(*this); } } void CEditorScene::onSelectionChanged() { int selectionCount = selectedItems().size(); actions()->cutAction->setEnabled(selectionCount > 0); actions()->copyAction->setEnabled(selectionCount > 0); actions()->delAction->setEnabled(selectionCount > 0); if (m_editController) { m_editController->onSelectionChanged(*this); } } void CEditorScene::onFocusItemChanged(QGraphicsItem *newFocusItem, QGraphicsItem *oldFocusItem, Qt::FocusReason reason) { } // drawing void CEditorScene::drawBackground(QPainter *painter, const QRectF &) { // invalidate items if needed if (m_needUpdateItems) { m_needUpdateItems = false; auto citems = getItems(); for (auto citem : citems) { citem->updateCachedItems(); citem->getSceneItem()->update(); } } // update layout if needed if (m_labelsUpdate) { layoutItemLabels(); } // fill background if (painter->paintEngine()->type() == QPaintEngine::OpenGL || painter->paintEngine()->type() == QPaintEngine::OpenGL2) { glClearColor(1, 1, 1, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } painter->setPen(QPen(Qt::darkGray, 2, Qt::SolidLine)); painter->setBrush(backgroundBrush()); painter->drawRect(sceneRect()); // draw grid if needed if (m_gridSize <= 0 || !m_gridEnabled) return; painter->setPen(m_gridPen); QRectF rect = sceneRect(); qreal left = int(rect.left()) - (int(rect.left()) % m_gridSize); qreal top = int(rect.top()) - (int(rect.top()) % m_gridSize); QVarLengthArray lines; for (qreal x = left; x < rect.right(); x += m_gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += m_gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); //qDebug() << lines.size(); painter->drawLines(lines.data(), lines.size()); } void CEditorScene::drawForeground(QPainter *painter, const QRectF &r) { Super::drawForeground(painter, r); // drop label update flag m_labelsUpdate = false; // draw transformer etc if (m_editController) m_editController->draw(*this, painter, r); } bool CEditorScene::checkLabelRegion(const QRectF &r) { if (!r.isValid()) return false; if (m_usedLabelsRegion.intersects(r)) return false; m_usedLabelsRegion.addRect(r); return true; } CEditorScene::LabelsPolicy CEditorScene::getLabelsPolicy() const { int labelPolicy = getClassAttribute(class_scene, attr_labels_policy, false).defaultValue.toInt(); return (CEditorScene::LabelsPolicy) labelPolicy; } void CEditorScene::setLabelsPolicy(CEditorScene::LabelsPolicy v) { setClassAttribute(class_scene, attr_labels_policy, (QVariant) v); } void CEditorScene::layoutItemLabels() { // reset region m_usedLabelsRegion = QPainterPath(); QList allItems = getItems(); // get labeling policy auto labelPolicy = getLabelsPolicy(); // hide all if disabled if (!m_labelsEnabled || labelPolicy == AlwaysOff) { for (auto citem : allItems) { citem->showLabel(false); } return; } QElapsedTimer tm; tm.start(); // else layout texts for (auto citem : allItems) { citem->updateLabelContent(); citem->updateLabelPosition(); if (labelPolicy == AlwaysOn) citem->showLabel(true); else { QRectF labelRect = citem->getSceneLabelRect(); QRectF reducedRect(labelRect.topLeft() / 10, labelRect.size() / 10); citem->showLabel(checkLabelRegion(reducedRect)); } } //qDebug() << "layout labels: " << tm.elapsed(); } void CEditorScene::needUpdate() { m_labelsUpdate = true; m_needUpdateItems = true; update(); } // mousing void CEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) { if (mouseEvent->button() == Qt::LeftButton) { m_cancelled = false; } if (m_editController) { if (m_editItem) { m_pimpl->m_labelEditor.finishEdit(); } if (m_editController->onMousePressed(*this, mouseEvent)) { mouseEvent->setAccepted(true); return; } else mouseEvent->setAccepted(false); } if (m_editItem) { // call super Super::mousePressEvent(mouseEvent); return; } // check RMB if (mouseEvent->button() == Qt::RightButton) { onRightButtonPressed(mouseEvent); } // check LMB if (mouseEvent->button() == Qt::LeftButton) { onLeftButtonPressed(mouseEvent); } // call super is allowed if (!mouseEvent->isAccepted()) { Super::mousePressEvent(mouseEvent); } } void CEditorScene::selectUnderMouse(QGraphicsSceneMouseEvent *mouseEvent) { auto item = getItemAt(mouseEvent->scenePos()); if (item) { if (!item->isSelected()) { deselectAll(); item->setSelected(true); } } } void CEditorScene::onLeftButtonPressed(QGraphicsSceneMouseEvent *mouseEvent) { m_draggedItem = NULL; m_dragInProgress = false; m_leftClickPos = mouseEvent->scenePos(); } void CEditorScene::onRightButtonPressed(QGraphicsSceneMouseEvent *mouseEvent) { auto item = getItemAt(mouseEvent->scenePos()); if (!item) return; // bypass control points if (dynamic_cast(item)) return; // do not deselect selected items by RMB, but select exclusive if not selected if (!item->isSelected()) { deselectAll(); item->setSelected(true); } mouseEvent->accept(); return; } void CEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { // by some reason (Qt bug?) this method can be entered twice -> stack overflow // so this is an ugly workaround... static bool entered = false; if (entered) return; entered = true; // ignore if cancelled if (m_cancelled) { entered = false; return; } if (m_editController) { if (m_editController->onMouseMove(*this, mouseEvent)) { mouseEvent->accept(); entered = false; return; } else mouseEvent->ignore(); } if (m_editItem) { // call super Super::mouseMoveEvent(mouseEvent); entered = false; return; } // store the last position m_mousePos = mouseEvent->scenePos(); m_dragInProgress = mouseEvent->buttons() == Qt::LeftButton; if (m_doubleClick) { m_doubleClick = false; // moved after double click? if (m_dragInProgress && !onDoubleClickDrag(mouseEvent, m_leftClickPos)) { entered = false; return; } } // no double click and no drag if (m_startDragItem == NULL) { // moved after single click? if (m_dragInProgress && onClickDrag(mouseEvent, m_leftClickPos)) { moveDrag(mouseEvent, m_startDragItem, true); entered = false; return; } // call super Super::mouseMoveEvent(mouseEvent); m_draggedItem = mouseGrabberItem(); moveDrag(mouseEvent, m_draggedItem, false); updateCursorState(); entered = false; return; } // custom dragging moveDrag(mouseEvent, m_startDragItem, m_dragInProgress); entered = false; } void CEditorScene::startDrag(QGraphicsItem* dragItem) { m_startDragItem = dragItem; m_dragInProgress = true; m_lastDragPos = m_leftClickPos; m_cancelled = false; } void CEditorScene::processDrag(QGraphicsSceneMouseEvent *mouseEvent, QGraphicsItem* dragItem) { if (m_editController) { m_editController->onDragItem(*this, mouseEvent, dragItem); } QPointF d = mouseEvent->scenePos() - mouseEvent->lastScenePos(); // delta pos if (m_startDragItem) { auto keys = qApp->queryKeyboardModifiers(); if (keys & Qt::ShiftModifier) { auto hpos = mouseEvent->scenePos(); auto delta = hpos - m_leftClickPos; if (qAbs(delta.x()) > qAbs(delta.y())) hpos.setY(m_leftClickPos.y()); else hpos.setX(m_leftClickPos.x()); d = hpos - m_lastDragPos; m_lastDragPos = hpos; } else { d = mouseEvent->scenePos() - m_lastDragPos; // delta pos m_lastDragPos = mouseEvent->scenePos(); } } // if control point: move only it if (auto ctrl = dynamic_cast(m_startDragItem)) { //deselectAll(); ctrl->moveBy(d.x(), d.y()); return; } // fallback moveSelectedItemsBy(d); } void CEditorScene::moveDrag(QGraphicsSceneMouseEvent *mouseEvent, QGraphicsItem* dragItem, bool performDrag) { if (dragItem) { if (dragItem->flags() & dragItem->ItemIsMovable) { if (performDrag) { processDrag(mouseEvent, dragItem); } QSet oldHovers = m_acceptedHovers + m_rejectedHovers; QList hoveredItems = dragItem->collidingItems(); for (auto hoverItem: hoveredItems) { // filter out children if (hoverItem->parentItem() == dragItem) continue; // dont drop on disabled if (!hoverItem->isEnabled()) continue; IInteractive* item = dynamic_cast(hoverItem); CItem* citem = dynamic_cast(hoverItem); if (item) { oldHovers.remove(item); if (m_acceptedHovers.contains(item) || m_rejectedHovers.contains(item)) continue; ItemDragTestResult result = item->acceptDragFromItem(dragItem); if (result == Accepted) { m_acceptedHovers.insert(item); if (citem) { citem->setItemStateFlag(IS_Drag_Accepted); citem->resetItemStateFlag(IS_Drag_Rejected); } } else if (result == Rejected) { m_rejectedHovers.insert(item); if (citem) { citem->resetItemStateFlag(IS_Drag_Accepted); citem->setItemStateFlag(IS_Drag_Rejected); } } hoverItem->update(); } } // deactivate left hovers for (IInteractive* item : oldHovers) { item->leaveDragFromItem(dragItem); m_acceptedHovers.remove(item); m_rejectedHovers.remove(item); CItem* citem = dynamic_cast(item); if (citem) { citem->resetItemStateFlag(IS_Drag_Accepted); citem->resetItemStateFlag(IS_Drag_Rejected); } if (auto hoverItem = dynamic_cast(item)) hoverItem->update(); } // inform the dragger IInteractive* draggedItem = dynamic_cast(dragItem); if (draggedItem) { draggedItem->onDraggedOver(m_acceptedHovers, m_rejectedHovers); } // inform the scene onDragging(dragItem, m_acceptedHovers, m_rejectedHovers); } } else // no drag, just hover { QGraphicsItem *hoverItem = getItemAt(mouseEvent->scenePos()); // inform the scene onMoving(mouseEvent, hoverItem); } } void CEditorScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent) { Super::mouseDoubleClickEvent(mouseEvent); if (mouseEvent->button() == Qt::LeftButton) { m_doubleClick = true; } } void CEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) { // ignore if cancelled if (m_cancelled) { if (mouseEvent->button() == Qt::LeftButton) m_cancelled = false; Super::mouseReleaseEvent(mouseEvent); return; } if (m_editController) { if (m_editController->onMouseReleased(*this, mouseEvent)) { mouseEvent->setAccepted(true); return; } else mouseEvent->setAccepted(false); } QGraphicsItem* prevGrabber = m_draggedItem; Super::mouseReleaseEvent(mouseEvent); m_draggedItem = mouseGrabberItem(); if (mouseEvent->button() == Qt::LeftButton) { if (m_dragInProgress) { finishDrag(mouseEvent, prevGrabber, false); } else if (m_leftClickPos == mouseEvent->scenePos()) { QGraphicsItem *hoverItem = getItemAt(mouseEvent->scenePos()); if (m_doubleClick) onLeftDoubleClick(mouseEvent, hoverItem); else onLeftClick(mouseEvent, hoverItem); } } m_doubleClick = false; m_dragInProgress = false; m_cancelled = false; } void CEditorScene::finishDrag(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* dragItem, bool dragCancelled) { // cleanup drag state m_startDragItem = NULL; m_dragInProgress = false; m_cancelled = dragCancelled; if (m_cancelled) { m_leftClickPos = QPointF(); m_lastDragPos = QPointF(); m_mousePos = QPointF(); m_draggedItem = NULL; } if (dragItem) { // deactivate left hovers for (IInteractive* item : m_acceptedHovers) { item->leaveDragFromItem(dragItem); if (auto *citem = dynamic_cast(item)) { citem->resetItemStateFlag(IS_Drag_Accepted); citem->resetItemStateFlag(IS_Drag_Rejected); } } for (IInteractive* item : m_rejectedHovers) { item->leaveDragFromItem(dragItem); if (auto *citem = dynamic_cast(item)) { citem->resetItemStateFlag(IS_Drag_Accepted); citem->resetItemStateFlag(IS_Drag_Rejected); } } // inform the dragger IInteractive* draggedItem = dynamic_cast(dragItem); if (draggedItem && !dragCancelled) { draggedItem->onDroppedOn(m_acceptedHovers, m_rejectedHovers); } // drag finish m_acceptedHovers.clear(); m_rejectedHovers.clear(); if (!dragCancelled) { // snap after drop if dragItem still alive (can die after onDroppedOn??) if (items().contains(dragItem)) { onDropped(mouseEvent, dragItem); } // update undo manager addUndoState(); } } } void CEditorScene::onMoving(QGraphicsSceneMouseEvent *mouseEvent, QGraphicsItem* hoverItem) { updateCursorState(); if (hoverItem) setInfoStatus(SIS_Hover); else setInfoStatus(SIS_Select); } void CEditorScene::onDragging(QGraphicsItem* /*dragItem*/, const QSet& /*acceptedItems*/, const QSet& /*rejectedItems*/) { updateCursorState(); setInfoStatus(SIS_Drag); } void CEditorScene::onDropped(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* dragItem) { auto keys = mouseEvent->modifiers(); bool isSnap = (keys & Qt::AltModifier) ? !m_gridSnap : m_gridSnap; if (isSnap) { auto pos = getSnapped(dragItem->pos()); auto d = pos - dragItem->pos(); dragItem->setPos(pos); for (auto item : selectedItems()) { if (item != dragItem) item->moveBy(d.x(), d.y()); } } } void CEditorScene::onLeftClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem) { if (CItem *item = dynamic_cast(clickedItem)) { item->onClick(mouseEvent); } } void CEditorScene::onLeftDoubleClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem) { // clicked on empty space? //if (!clickedItem) // return; // else check clicked item... if (CItem *item = dynamic_cast(clickedItem)) { onActionEditLabel(item); //item->onDoubleClick(mouseEvent); } // emit signals Q_EMIT sceneDoubleClicked(mouseEvent, clickedItem); } bool CEditorScene::onClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos) { if (QGraphicsItem* item = getItemAt(clickPos)) { if (!item->isEnabled()) return false; if (!(item->flags() & item->ItemIsMovable)) return false; if (CItem *citem = dynamic_cast(item)) { // clone? if (mouseEvent->modifiers() == Qt::ControlModifier) { // select under mouse if clone selectUnderMouse(mouseEvent); // clone selection QList clonedList = cloneSelectedItems(); if (clonedList.isEmpty()) return false; selectItems(clonedList); // start drag via 1st item startDrag(clonedList.first()->getSceneItem()); return true; } //qDebug() << clickPos << citem; // else handle by item if (!citem->onClickDrag(mouseEvent, clickPos)) return false; } // else start drag of item startDrag(item); return true; } // nothing to do return false; } bool CEditorScene::onDoubleClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos) { // handle by object under mouse QGraphicsItem* item = getItemAt(clickPos); if (item) { if (!item->isEnabled()) return false; if (!(item->flags() & item->ItemIsMovable)) return false; CItem *citem = dynamic_cast(item); if (citem) return citem->onDoubleClickDrag(mouseEvent, clickPos); } // nothing to do return false; } // scene void CEditorScene::setInfoStatus(int status) { if (m_infoStatus != status) { m_infoStatus = status; Q_EMIT infoStatusChanged(status); } } void CEditorScene::updateCursorState() { auto keys = qApp->queryKeyboardModifiers(); auto buttons = qApp->mouseButtons(); QGraphicsItem *hoverItem = getItemAt(m_mousePos); doUpdateCursorState(keys, buttons, hoverItem); } bool CEditorScene::doUpdateCursorState(Qt::KeyboardModifiers keys, Qt::MouseButtons buttons, QGraphicsItem *hoverItem) { // drag? if (m_dragInProgress) { if (m_acceptedHovers.size()) { setSceneCursor(Qt::CrossCursor); return true; } if (m_rejectedHovers.size()) { setSceneCursor(Qt::ForbiddenCursor); return true; } // clone? //if (keys == Qt::ControlModifier) //{ // setSceneCursor(Qt::DragCopyCursor); // return; //} setSceneCursor(Qt::SizeAllCursor); return true; } // can drag a hover item? if (hoverItem) { if (hoverItem->isEnabled() && (hoverItem->flags() & hoverItem->ItemIsMovable)) { // clone? if (keys == Qt::ControlModifier) { setSceneCursor(Qt::DragCopyCursor); return true; } if (buttons == Qt::NoButton) { setSceneCursor(Qt::SizeAllCursor); return true; } } } // default setSceneCursor(Qt::ArrowCursor); return false; } QPointF CEditorScene::getSnapped(const QPointF& pos) const { auto keys = qApp->queryKeyboardModifiers(); bool isSnap = (keys & Qt::AltModifier) ? !gridSnapEnabled() : gridSnapEnabled(); if (isSnap) { QPointF newPos(pos); if (newPos.x() < 0) newPos.setX(newPos.x() - m_gridSize / 2); else newPos.setX(newPos.x() + m_gridSize / 2); if (newPos.y() < 0) newPos.setY(newPos.y() - m_gridSize / 2); else newPos.setY(newPos.y() + m_gridSize / 2); newPos.setX((int)newPos.x() - (int)newPos.x() % m_gridSize); newPos.setY((int)newPos.y() - (int)newPos.y() % m_gridSize); return newPos; } else return pos; } QGraphicsItem* CEditorScene::getItemAt(const QPointF& pos) const { QGraphicsItem *hoverItem = itemAt(pos, QTransform()); // if label: return parent instead if (dynamic_cast(hoverItem)) { return hoverItem->parentItem(); } else return hoverItem; } QGraphicsView* CEditorScene::getCurrentView() { for (auto view: views()) { if (view->underMouse() || view->hasFocus()) return view; } if (views().count() == 1) return views().first(); return nullptr; } // private void CEditorScene::setSceneCursor(const QCursor& c) { for (QGraphicsView* v : views()) { v->setCursor(c); } } // keys void CEditorScene::keyReleaseEvent(QKeyEvent *keyEvent) { if (m_editController) { if (m_editController->onKeyReleased(*this, keyEvent)) { updateCursorState(); return; } } updateCursorState(); } void CEditorScene::keyPressEvent(QKeyEvent *keyEvent) { if (m_editController) { if (m_editController->onKeyPressed(*this, keyEvent)) { updateCursorState(); return; } } updateCursorState(); bool isCtrl = (keyEvent->modifiers() & Qt::ControlModifier); bool isAlt = (keyEvent->modifiers() & Qt::AltModifier); bool isShift = (keyEvent->modifiers() & Qt::ShiftModifier); //if (isAlt /*|| keyEvent->isAccepted()*/) // return; if (keyEvent->key() == Qt::Key_Delete) { onActionDelete(); keyEvent->accept(); return; } if (keyEvent->key() == Qt::Key_A && isCtrl) { onActionSelectAll(); keyEvent->accept(); return; } // no modifier moves by 1 pixel, shift moves by grid size int moveStep = isShift ? m_gridSize : 1; bool moveSnapped = isShift; if (keyEvent->key() == Qt::Key_Right) { moveSelectedItemsBy(moveStep, 0, moveSnapped); addUndoState(); keyEvent->accept(); return; } if (keyEvent->key() == Qt::Key_Left) { moveSelectedItemsBy(-moveStep, 0, moveSnapped); addUndoState(); keyEvent->accept(); return; } if (keyEvent->key() == Qt::Key_Up) { moveSelectedItemsBy(0, -moveStep, moveSnapped); addUndoState(); keyEvent->accept(); return; } if (keyEvent->key() == Qt::Key_Down) { moveSelectedItemsBy(0, moveStep, moveSnapped); addUndoState(); keyEvent->accept(); return; } } // general events void CEditorScene::focusInEvent(QFocusEvent *focusEvent) { Super::focusInEvent(focusEvent); static bool s_firstRun = true; if (s_firstRun) { s_firstRun = false; // init scene //addUndoState(); } } // menu stuff void CEditorScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent) { if (m_skipMenuEvent) { m_skipMenuEvent = false; return; } m_menuTriggerItem = getItemAt(contextMenuEvent->scenePos()); //Get the item at the position // check if item provides own menu if (auto menuItem = dynamic_cast(m_menuTriggerItem)) { QMenu sceneMenu; if (menuItem->populateMenu(sceneMenu, selectedItems())) { sceneMenu.exec(contextMenuEvent->screenPos()); return; } } // else custom menu if (m_menuController) m_menuController->exec(this, m_menuTriggerItem, contextMenuEvent); } void CEditorScene::onActionDelete() { QList itemList = createSelectedList(CDeletableItems()); if (itemList.isEmpty()) return; if (QMessageBox::question(NULL, tr("Delete Items"), tr("You are about to delete %1 item(s). Sure?").arg(itemList.size())) == QMessageBox::No) return; del(); } void CEditorScene::onActionSelectAll() { selectAll(); } // label edit void CEditorScene::onActionEditLabel(CItem *item) { setInfoStatus(SIS_Edit_Label); setSceneCursor(Qt::IBeamCursor); m_pimpl->m_labelEditor.startEdit(item); m_editItem = item; } void CEditorScene::onItemEditingFinished(CItem * /*item*/, bool /*cancelled*/) { m_editItem = nullptr; } // selections void CEditorScene::selectAll() { QPainterPath path; path.addRect(sceneRect()); setSelectionArea(path, QTransform()); } void CEditorScene::deselectAll() { QPainterPath path; setSelectionArea(path, QTransform()); } void CEditorScene::selectItem(CItem* item, bool exclusive) { if (!item) return; beginSelection(); if (exclusive) deselectAll(); item->getSceneItem()->setSelected(true); endSelection(); } void CEditorScene::selectItems(const QList& items, bool exclusive) { beginSelection(); if (exclusive) deselectAll(); for (auto item : items) if (item) item->getSceneItem()->setSelected(true); endSelection(); } void CEditorScene::beginSelection() { blockSignals(true); } void CEditorScene::endSelection() { blockSignals(false); Q_EMIT selectionChanged(); } void CEditorScene::ensureSelectionVisible() { auto items = selectedItems(); QRectF r; for (const auto item : items) r |= item->sceneBoundingRect(); if (items.count()) items.first()->ensureVisible(r); } void CEditorScene::moveSelectedItemsBy(const QPointF& d, bool /*snapped*/) { auto items = selectedItems(); for (auto sceneItem : items) { sceneItem->moveBy(d.x(), d.y()); } if (items.count()) items.first()->ensureVisible(); } // evaluators QList CEditorScene::createSelectedList(const CItemsEvaluator& eval) const { QList result; QList itemList = getSelectedItems(true); for (int i = 0; i < itemList.size(); ++i) { if (eval.evaluate(*itemList.at(i))) result << itemList.at(i); } return result; } bool CDeletableItems::evaluate(const QGraphicsItem& item) const { const CItem* citem = dynamic_cast(&item); if (citem) { return citem->itemFlags() & IF_DeleteAllowed; } // can delete QGraphicsItem return true; } // actions CEditorSceneActions* CEditorScene::actions() { return dynamic_cast(getActions()); } QObject* CEditorScene::getActions() { if (m_actions == nullptr) m_actions = createActions(); return m_actions; } QObject* CEditorScene::createActions() { return new CEditorSceneActions(this); } // edit extenders void CEditorScene::startTransform(bool on, bool moveOnly) { if (on) { setSceneEditController(&m_pimpl->m_transformRect); m_pimpl->m_transformRect.setMoveOnly(moveOnly); } else setSceneEditController(nullptr); } void CEditorScene::setSceneEditController(ISceneEditController *controller) { if (m_editController != controller) { if (m_editController) m_editController->onDeactivated(*this); m_editController = controller; if (m_editController) m_editController->onActivated(*this); } } qvge-0.6.3/src/qvge/CEditorScene.h000066400000000000000000000304701405165517400167070ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CEDITORSCENE_H #define CEDITORSCENE_H #include #include #include #include #include #include "CAttribute.h" class IUndoManager; class ISceneItemFactory; class IInteractive; class ISceneMenuController; class ISceneEditController; class CItem; class CEditorSceneActions; struct Graph; class CItemsEvaluator { public: virtual bool evaluate(const QGraphicsItem& item) const = 0; }; class CDeletableItems: public CItemsEvaluator { public: virtual bool evaluate(const QGraphicsItem& item) const; }; class CEditorScene : public QGraphicsScene { Q_OBJECT public: typedef QGraphicsScene Super; friend class CEditorScene_p; CEditorScene(QObject *parent = NULL); virtual ~CEditorScene(); virtual void reset(); virtual void initialize(); virtual bool fromGraph(const Graph&) { return false; } virtual bool toGraph(Graph&) { return false; } // properties void setGridSize(int newSize); int getGridSize() const { return m_gridSize; } bool gridEnabled() const { return m_gridEnabled; } bool gridSnapEnabled() const { return m_gridSnap; } void setGridPen(const QPen& gridPen); const QPen& getGridPen() const { return m_gridPen; } void setFontAntialiased(bool on); bool isFontAntialiased() const { return m_isFontAntialiased; } bool itemLabelsEnabled() const { return m_labelsEnabled; } bool itemLabelsNeedUpdate() const { return m_labelsUpdate; } enum LabelsPolicy { Auto, AlwaysOn, AlwaysOff }; LabelsPolicy getLabelsPolicy() const; void setLabelsPolicy(LabelsPolicy v); // undo-redo int availableUndoCount() const; int availableRedoCount() const; // must be called after scene state changed void addUndoState(); // must be called to discard recent changes without undo void revertUndoState(); // sets initial scene state void setInitialState(); // serialization virtual bool storeTo(QDataStream& out, bool storeOptions) const; virtual bool restoreFrom(QDataStream& out, bool readOptions); // item factories template bool registerItemFactory() { static T f; return setItemFactory(&f); } template static T* factory() { static T s_item; return &s_item; } bool setItemFactory(CItem *factoryItem, const QByteArray& typeId = ""); CItem* getItemFactory(const QByteArray& typeId) const; virtual CItem* createItemOfType(const QByteArray& typeId) const; template T* createItemOfType(QPointF* at = NULL) const; void setItemFactoryFilter(ISceneItemFactory *filter) { m_itemFactoryFilter = filter; } // scene factory & copy virtual CEditorScene* createScene() const { return new CEditorScene(); } virtual CEditorScene* clone(); virtual void copyProperties(const CEditorScene& from); // attributes QByteArray getSuperClassId(const QByteArray& classId) const { if (m_classToSuperIds.contains(classId)) return m_classToSuperIds[classId]; return QByteArray(); } const CAttribute getClassAttribute(const QByteArray& classId, const QByteArray& attrId, bool inherited) const; AttributesMap getClassAttributes(const QByteArray& classId, bool inherited) const; bool removeClassAttribute(const QByteArray& classId, const QByteArray& attrId); void setClassAttribute(const QByteArray& classId, const CAttribute& attr, bool vis = false); void setClassAttribute(const QByteArray& classId, const QByteArray& attrId, const QVariant& defaultValue); // convenience method to create a class attribute by single call CAttribute& createClassAttribute( const QByteArray& classId, const QByteArray& attrId, const QString& attrName, const QVariant& defaultValue = QVariant(), int attrFlags = ATTR_FIXED, CAttributeConstrains* constrains = NULL, bool vis = false); QSet getVisibleClassAttributes(const QByteArray& classId, bool inherited) const; void setVisibleClassAttributes(const QByteArray& classId, const QSet& vis); void setClassAttributeVisible(const QByteArray& classId, const QByteArray& attrId, bool vis = true); bool isClassAttributeVisible(const QByteArray& classId, const QByteArray& attrId) const; CAttributeConstrains* getClassAttributeConstrains(const QByteArray& classId, const QByteArray& attrId) const; void setClassAttributeConstrains(const QByteArray& classId, const QByteArray& attrId, CAttributeConstrains* cptr); // items template QList getItems() const; template QList getItemsById(const QString& id) const; QGraphicsItem* getItemAt(const QPointF& pos) const; template T* isItemAt(const QPointF& pos) const { return dynamic_cast(getItemAt(pos)); } // selections QList createSelectedList(const CItemsEvaluator&) const; template QList getSelectedItems(bool triggeredIfEmpty = false) const; virtual void beginSelection(); virtual void endSelection(); void ensureSelectionVisible(); void moveSelectedItemsBy(double x, double y, bool snapped = false) { moveSelectedItemsBy(QPointF(x, y), snapped); } virtual void moveSelectedItemsBy(const QPointF& d, bool snapped = false); virtual QList cloneSelectedItems(); virtual int getBoundingMargin() const { return 0; } // to reimplement virtual QList getCopyPasteItems() const; virtual QList getTransformableItems() const; // operations void startDrag(QGraphicsItem* dragItem); void startTransform(bool on, bool moveOnly = false); // actions QObject* getActions(); CEditorSceneActions* actions(); // edit extenders void setSceneEditController(ISceneEditController *controller); ISceneEditController* getSceneEditController() const { return m_editController; } // context menu void setContextMenuController(ISceneMenuController *controller) { m_menuController = controller; } ISceneMenuController* getContextMenuController() const { return m_menuController; } QGraphicsItem* getContextMenuTrigger() const { return m_menuTriggerItem; } // other bool checkLabelRegion(const QRectF& r); void layoutItemLabels(); void needUpdate(); virtual QPointF getSnapped(const QPointF& pos) const; int getInfoStatus() const { return m_infoStatus; } QGraphicsView* getCurrentView(); // callbacks virtual void onItemDestroyed(CItem *citem); public Q_SLOTS: void enableGrid(bool on = true); void enableGridSnap(bool on = true); void enableItemLabels(bool on = true); void undo(); void redo(); void selectAll(); void deselectAll(); void selectItem(CItem* item, bool exclusive = true); void selectItems(const QList& items, bool exclusive = true); void del(); void cut(); void copy(); void setPastePosition(const QPointF &anchor) { m_pastePos = anchor; } void pasteAt(const QPointF &anchor); void paste(); void crop(); void setSceneCursor(const QCursor& c); Q_SIGNALS: void undoAvailable(bool); void redoAvailable(bool); void sceneChanged(); void sceneDoubleClicked(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem); void infoStatusChanged(int status); protected: void setInfoStatus(int status); void updateCursorState(); virtual bool doUpdateCursorState(Qt::KeyboardModifiers keys, Qt::MouseButtons buttons, QGraphicsItem *hoverItem); virtual QObject* createActions(); // internal call void selectUnderMouse(QGraphicsSceneMouseEvent *mouseEvent); // reimp virtual void drawBackground(QPainter *painter, const QRectF &rect); virtual void drawForeground(QPainter *painter, const QRectF &rect); virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void keyPressEvent(QKeyEvent *keyEvent); virtual void keyReleaseEvent(QKeyEvent *keyEvent); virtual void focusInEvent(QFocusEvent *focusEvent); virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent); // call from reimp void moveDrag(QGraphicsSceneMouseEvent *mouseEvent, QGraphicsItem* dragItem, bool performDrag); virtual void processDrag(QGraphicsSceneMouseEvent *mouseEvent, QGraphicsItem* dragItem); void finishDrag(QGraphicsSceneMouseEvent *mouseEvent, QGraphicsItem* dragItem, bool dragCancelled); // callbacks virtual void onDragging(QGraphicsItem* dragItem, const QSet& acceptedItems, const QSet& rejectedItems); virtual void onMoving(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* hoverItem); virtual void onDropped(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* dragItem); virtual void onLeftButtonPressed(QGraphicsSceneMouseEvent *mouseEvent); virtual void onRightButtonPressed(QGraphicsSceneMouseEvent *mouseEvent); virtual void onLeftClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem); virtual void onLeftDoubleClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem); // called on drag after single click; returns true if handled virtual bool onClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos); // called on drag after double click; returns true if handled virtual bool onDoubleClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos); virtual void onSceneChanged(); protected Q_SLOTS: virtual void onSelectionChanged(); void onFocusItemChanged(QGraphicsItem *newFocusItem, QGraphicsItem *oldFocusItem, Qt::FocusReason reason); void onItemEditingFinished(CItem *item, bool cancelled); void onActionDelete(); void onActionSelectAll(); void onActionEditLabel(CItem *item); private: void removeItems(); void checkUndoState(); protected: QPointF m_leftClickPos; QPointF m_mousePos; bool m_doubleClick = false; bool m_cancelled = false; bool m_dragInProgress = false; QGraphicsItem *m_startDragItem = nullptr; QPointF m_lastDragPos; QGraphicsItem *m_draggedItem = nullptr; QSet m_acceptedHovers, m_rejectedHovers; bool m_skipMenuEvent = false; CItem *m_editItem = nullptr; // pimpl class CEditorScene_p* m_pimpl = nullptr; private: int m_infoStatus; QMap m_itemFactories; ISceneItemFactory *m_itemFactoryFilter = nullptr; IUndoManager *m_undoManager = nullptr; bool m_inProgress = false; QGraphicsItem *m_menuTriggerItem = nullptr; ISceneMenuController *m_menuController = nullptr; QObject *m_actions = nullptr; ISceneEditController *m_editController = nullptr; QMap m_classToSuperIds; ClassAttributesMap m_classAttributes; QMap> m_classAttributesVis; AttributeConstrainsMap m_classAttributesConstrains; int m_gridSize; bool m_gridEnabled; bool m_gridSnap; QPen m_gridPen; bool m_needUpdateItems = true; QPointF m_pastePos; // labels QPainterPath m_usedLabelsRegion; bool m_labelsEnabled, m_labelsUpdate; bool m_isFontAntialiased = true; }; // factorization template T* CEditorScene::createItemOfType(QPointF* at) const { if (CItem* item = createItemOfType(T::factoryId())) { if (T* titem = dynamic_cast(item)) { if (at) { (const_cast(this))->addItem(titem); titem->setPos(*at); } return titem; } delete item; return NULL; } return NULL; } // selections template QList CEditorScene::getSelectedItems(bool triggeredIfEmpty) const { QList result; auto selItems = selectedItems(); if (selItems.isEmpty() && triggeredIfEmpty && m_menuTriggerItem) selItems.append(m_menuTriggerItem); for (auto* item : selItems) { T* titem = dynamic_cast(item); if (titem) result.append(titem); } return result; } template QList CEditorScene::getItems() const { QList result; auto allItems = items(); for (auto item : allItems) { T* titem = dynamic_cast(item); if (titem) result.append(titem); } return result; } template QList CEditorScene::getItemsById(const QString& id) const { QList res; auto allItems = items(); for (auto item : allItems) { T* titem = dynamic_cast(item); if (titem && titem->getId() == id) res << titem; } return res; } #endif // CEDITORSCENE_H qvge-0.6.3/src/qvge/CEditorSceneActions.cpp000066400000000000000000000031211405165517400205540ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include "CEditorSceneActions.h" #include "CEditorScene.h" #include "CNode.h" #include "CEdge.h" CEditorSceneActions::CEditorSceneActions(CEditorScene *scene) { cutAction = new QAction(QIcon(":/Icons/Cut"), tr("Cut"), scene); cutAction->setStatusTip(tr("Cut selected item(s) to clipboard")); cutAction->setToolTip(tr("Cut selection")); cutAction->setShortcut(QKeySequence::Cut); connect(cutAction, &QAction::triggered, scene, &CEditorScene::cut); copyAction = new QAction(QIcon(":/Icons/Copy"), tr("Copy"), scene); copyAction->setStatusTip(tr("Copy selected item(s) to clipboard")); copyAction->setToolTip(tr("Copy selection")); copyAction->setShortcut(QKeySequence::Copy); connect(copyAction, &QAction::triggered, scene, &CEditorScene::copy); pasteAction = new QAction(QIcon(":/Icons/Paste"), tr("Paste"), scene); pasteAction->setStatusTip(tr("Paste item(s) from clipboard")); pasteAction->setToolTip(tr("Paste from clipboard")); pasteAction->setShortcut(QKeySequence::Paste); connect(pasteAction, &QAction::triggered, scene, &CEditorScene::paste); delAction = new QAction(QIcon(":/Icons/Delete"), QObject::tr("Delete"), scene); delAction->setStatusTip(QObject::tr("Delete selected item(s)")); delAction->setToolTip(QObject::tr("Delete selection")); delAction->setShortcut(QKeySequence::Delete); QObject::connect(delAction, &QAction::triggered, scene, &CEditorScene::del); } qvge-0.6.3/src/qvge/CEditorSceneActions.h000066400000000000000000000006371405165517400202320ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include class CEditorScene; class CEditorSceneActions: public QObject { public: CEditorSceneActions(CEditorScene *scene); QAction *cutAction; QAction *copyAction; QAction *pasteAction; QAction *delAction; }; qvge-0.6.3/src/qvge/CEditorSceneDefines.h000066400000000000000000000024111405165517400201770ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include // common scene states enum SceneInfoState { SIS_Select = 0, SIS_Hover, SIS_Drag, SIS_Hover_Port, SIS_Edit_Label }; // common scene attributes const QByteArray class_scene = QByteArrayLiteral(""); const QByteArray class_item = QByteArrayLiteral("item"); const QByteArray class_node = QByteArrayLiteral("node"); const QByteArray class_edge = QByteArrayLiteral("edge"); const QByteArray attr_id = QByteArrayLiteral("id"); const QByteArray attr_size = QByteArrayLiteral("size"); const QByteArray attr_weight = QByteArrayLiteral("weight"); const QByteArray attr_color = QByteArrayLiteral("color"); const QByteArray attr_style = QByteArrayLiteral("style"); const QByteArray attr_label = QByteArrayLiteral("label"); const QByteArray attr_label_font = QByteArrayLiteral("label.font"); const QByteArray attr_label_color = QByteArrayLiteral("label.color"); const QByteArray attr_labels_policy = QByteArrayLiteral("labels.policy"); const QByteArray attr_labels_visIds = QByteArrayLiteral("labels.visibleIds"); const QByteArray attr_edge_direction = QByteArrayLiteral("direction"); qvge-0.6.3/src/qvge/CEditorScene_p.cpp000066400000000000000000000011101405165517400175460ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CEditorScene_p.h" #include "CEditorScene.h" #include "CItem.h" CEditorScene_p::CEditorScene_p(class CEditorScene *scene): m_transformRect(), m_scene(scene) { //QObject::connect(&m_labelEditor, &CTextLabelEdit::editingStarted, m_scene, &CEditorScene::onItemEditingStarted); QObject::connect(&m_labelEditor, &CTextLabelEdit::editingFinished, m_scene, &CEditorScene::onItemEditingFinished); } qvge-0.6.3/src/qvge/CEditorScene_p.h000066400000000000000000000006061405165517400172240ustar00rootroot00000000000000#pragma once #include "CTextLabelEdit.h" #include "CTransformRect.h" // pimpl for CEditorScene class CEditorScene_p { public: CEditorScene_p(class CEditorScene *scene); //void attachScene(class CEditorScene *scene); //void detachScene(class CEditorScene *scene); CTextLabelEdit m_labelEditor; CTransformRect m_transformRect; private: class CEditorScene *m_scene = nullptr; }; qvge-0.6.3/src/qvge/CEditorView.cpp000066400000000000000000000175631405165517400171270ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CEditorView.h" #include "CEditorScene.h" #include #include #include #include #include CEditorView::CEditorView(QWidget *parent) : Super(parent), m_menuModeTmp(Qt::PreventContextMenu) { setAttribute(Qt::WA_TranslucentBackground, false); setViewportUpdateMode(BoundingRectViewportUpdate); //setViewport(new QGLWidget); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setDragMode(RubberBandDrag); setRenderHint(QPainter::Antialiasing); setOptimizationFlags(DontSavePainterState); setOptimizationFlags(DontAdjustForAntialiasing); setFocus(); connect(&m_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimeout())); m_scrollTimer.setInterval(100); } CEditorView::CEditorView(CEditorScene *scene, QWidget *parent): CEditorView(parent) { setScene(scene); } CEditorView::~CEditorView() { } // zoom void CEditorView::zoomTo(double target) { QTransform mat; mat.scale(target, target); setTransform(mat); m_currentZoom = target; Q_EMIT scaleChanged(m_currentZoom); } void CEditorView::zoomBy(double factor) { double target = m_currentZoom * factor; zoomTo(target); } void CEditorView::fitToView() { m_zoomBeforeFit = m_currentZoom; m_dxyBeforeFit = getCenter(); fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio); m_currentZoom = matrix().m11(); Q_EMIT scaleChanged(m_currentZoom); } void CEditorView::fitSelectedToView() { auto items = scene()->selectedItems(); if (items.isEmpty()) return; m_zoomBeforeFit = m_currentZoom; m_dxyBeforeFit = getCenter(); QRectF r; for (const auto item : items) { r |= item->sceneBoundingRect(); } fitInView(r, Qt::KeepAspectRatio); m_currentZoom = matrix().m11(); Q_EMIT scaleChanged(m_currentZoom); } void CEditorView::zoomBack() { zoomTo(m_zoomBeforeFit); centerOn(m_dxyBeforeFit); } QPointF CEditorView::getCenter() const { return mapToScene(viewport()->rect().center()); } void CEditorView::centerContent() { fitToView(); zoomTo(1); } void CEditorView::restoreContextMenu() { setContextMenuPolicy(m_menuModeTmp); } void CEditorView::onScrollTimeout() { const int ScrollStep = 100; if (QGuiApplication::mouseButtons() & Qt::LeftButton) { auto globTopLeft = viewport()->mapToGlobal(QPoint(viewport()->x(), viewport()->y())); QRect globRect = QRect(globTopLeft, viewport()->size()); if (QCursor::pos().x() > globRect.right()) { //int dx = QCursor::pos().x() - globRect.right(); int dx = ScrollStep; horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx); } else if (QCursor::pos().x() < globRect.left()) { //int dx = globRect.left() - QCursor::pos().x(); int dx = ScrollStep; horizontalScrollBar()->setValue(horizontalScrollBar()->value() - dx); } if (QCursor::pos().y() > globRect.bottom()) { int dy = ScrollStep; //int dy = QCursor::pos().y() - globRect.bottom(); verticalScrollBar()->setValue(verticalScrollBar()->value() + dy); } else if (QCursor::pos().y() < globRect.top()) { int dy = ScrollStep; //int dy = globRect.top() - QCursor::pos().y(); verticalScrollBar()->setValue(verticalScrollBar()->value() - dy); } } } // reimp #if defined Q_OS_WIN && !defined Q_OS_CYGWIN // Windows-conform panning & context menu void CEditorView::contextMenuEvent(QContextMenuEvent *e) { // ignore when dragging if (getDragItem()) { e->accept(); return; } Super::contextMenuEvent(e); } void CEditorView::mousePressEvent(QMouseEvent *e) { // ignore when dragging if (e->button() == Qt::RightButton && getDragItem()) { e->accept(); return; } Super::mousePressEvent(e); // start scroll when dragging if (e->button() == Qt::LeftButton) { //m_scrollTimer.start(); } } void CEditorView::mouseMoveEvent(QMouseEvent *e) { // enable RMB pan if (e->buttons() == Qt::RightButton) { if (dragMode() != ScrollHandDrag) { m_menuModeTmp = contextMenuPolicy(); setContextMenuPolicy(Qt::PreventContextMenu); m_dragModeTmp = dragMode(); setDragMode(ScrollHandDrag); m_interactiveTmp = isInteractive(); setInteractive(false); QMouseEvent fake(e->type(), e->pos(), Qt::LeftButton, Qt::LeftButton, e->modifiers()); Super::mousePressEvent(&fake); } } Super::mouseMoveEvent(e); } void CEditorView::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { m_scrollTimer.stop(); } // disable RMB pan if (e->button() == Qt::RightButton && !e->buttons() && (dragMode() == ScrollHandDrag)) { QMouseEvent fake(e->type(), e->pos(), Qt::LeftButton, Qt::LeftButton, e->modifiers()); Super::mouseReleaseEvent(&fake); setDragMode(m_dragModeTmp); setInteractive(m_interactiveTmp); QTimer::singleShot(100, this, SLOT(restoreContextMenu())); } //else { Super::mouseReleaseEvent(e); } } #else // Linux/Unix/etc. void CEditorView::mousePressEvent(QMouseEvent *e) { m_moved = false; // enable RMB pan if (e->button() == Qt::RightButton) { if (dragMode() != ScrollHandDrag) { m_menuModeTmp = contextMenuPolicy(); setContextMenuPolicy(Qt::PreventContextMenu); setDragMode(ScrollHandDrag); m_interactiveTmp = isInteractive(); setInteractive(false); QMouseEvent fake(e->type(), e->pos(), Qt::LeftButton, Qt::LeftButton, e->modifiers()); Super::mousePressEvent(&fake); return; } } Super::mousePressEvent(e); } void CEditorView::mouseMoveEvent(QMouseEvent *e) { m_moved = true; Super::mouseMoveEvent(e); // check LMB selection //if (e->buttons() == Qt::LeftButton) //{ // onLeftClickMouseMove(e); //} } void CEditorView::mouseReleaseEvent(QMouseEvent *e) { // disabel RMB pan if (e->button() == Qt::RightButton && dragMode() == ScrollHandDrag) { QMouseEvent fake(e->type(), e->pos(), Qt::LeftButton, Qt::LeftButton, e->modifiers()); Super::mouseReleaseEvent(&fake); setDragMode(RubberBandDrag); setInteractive(m_interactiveTmp); setContextMenuPolicy(m_menuModeTmp); if (!m_moved) { QMouseEvent fake(QEvent::MouseButtonPress, e->pos(), Qt::RightButton, Qt::RightButton, Qt::NoModifier); Super::mousePressEvent(&fake); Super::mouseReleaseEvent(e); QContextMenuEvent fake2(QContextMenuEvent::Mouse, e->pos()); contextMenuEvent(&fake2); } return; } Super::mouseReleaseEvent(e); } void CEditorView::contextMenuEvent(QContextMenuEvent *e) { Super::contextMenuEvent(e); } #endif void CEditorView::wheelEvent(QWheelEvent *e) { // original taken from // http://blog.automaton2000.com/2014/04/mouse-centered-zooming-in-qgraphicsview.html if ((e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier && e->angleDelta().x() == 0) { QPoint pos = e->pos(); QPointF posf = this->mapToScene(pos); double by = 1.0; double angle = e->angleDelta().y(); if (angle > 0) { by = 1 + (angle / 360 * 0.5); } else if (angle < 0) { by = 1 - (-angle / 360 * 0.5); } //this->scale(by, by); zoomBy(by); double w = this->viewport()->width(); double h = this->viewport()->height(); double wf = this->mapToScene(QPoint(w - 1, 0)).x() - this->mapToScene(QPoint(0, 0)).x(); double hf = this->mapToScene(QPoint(0, h - 1)).y() - this->mapToScene(QPoint(0, 0)).y(); double lf = posf.x() - pos.x() * wf / w; double tf = posf.y() - pos.y() * hf / h; /* try to set viewport properly */ this->ensureVisible(lf, tf, wf, hf, 0, 0); QPointF newPos = this->mapToScene(pos); /* readjust according to the still remaining offset/drift * I don't know how to do this any other way */ this->ensureVisible(QRectF(QPointF(lf, tf) - newPos + posf, QSizeF(wf, hf)), 0, 0); e->accept(); } if ((e->modifiers() & Qt::ControlModifier) != Qt::ControlModifier) { /* no scrolling while control is held */ Super::wheelEvent(e); } } qvge-0.6.3/src/qvge/CEditorView.h000066400000000000000000000037321405165517400165650ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CEDITORVIEW_H #define CEDITORVIEW_H #include #include #include #include class CEditorScene; class CEditorView : public QGraphicsView { Q_OBJECT public: typedef QGraphicsView Super; CEditorView(CEditorScene *scene, QWidget *parent = NULL); CEditorView(QWidget *parent = NULL); virtual ~CEditorView(); // zoom double getZoom() const { return m_currentZoom; } // target is % value to zoom to (1.0 = 100% = reset zoom, 0.25 = 25% = 1/4 etc.) void zoomTo(double target); // factor if relative % value to zoom by (2 = 2x from current etc.) void zoomBy(double factor); double getZoomBeforeFit() const { return m_zoomBeforeFit; } void fitToView(); void fitSelectedToView(); void zoomBack(); // center QPointF getCenter() const; void centerContent(); // scene QGraphicsItem* getDragItem() { if (scene()) return scene()->mouseGrabberItem(); else return nullptr; } // reimp virtual void mousePressEvent(QMouseEvent *e); virtual void mouseMoveEvent(QMouseEvent *e); virtual void mouseReleaseEvent(QMouseEvent *e); virtual void contextMenuEvent(QContextMenuEvent *e); virtual void wheelEvent(QWheelEvent *e); void paintEvent(QPaintEvent * event) { QPaintEvent *newEvent = new QPaintEvent(event->region().boundingRect()); QGraphicsView::paintEvent(newEvent); delete newEvent; } Q_SIGNALS: void scaleChanged(double); private Q_SLOTS: void restoreContextMenu(); void onScrollTimeout(); private: DragMode m_dragModeTmp; Qt::ContextMenuPolicy m_menuModeTmp; bool m_interactiveTmp = false; bool m_moved = false; QPoint m_pos; double m_currentZoom = 1.0; double m_zoomBeforeFit = 0.0; // 0 means no zoom called yet QPointF m_dxyBeforeFit; QTimer m_scrollTimer; float m_scrollThreshold = 30; }; #endif // CEDITORVIEW_H qvge-0.6.3/src/qvge/CFileSerializerCSV.cpp000066400000000000000000000023741405165517400203250ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CFileSerializerCSV.h" #include "CAttribute.h" #include "CNode.h" #include "CDirectEdge.h" #include "CGraphInterface.h" #include "CNodeEditorScene.h" #include #include #include // reimp bool CFileSerializerCSV::load(const QString& fileName, CEditorScene& scene, QString* lastError) const { CNodeEditorScene* nodeScene = dynamic_cast(&scene); if (nodeScene == nullptr) return false; QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) return false; // try to parse scene.reset(); CGraphInterface graph(*nodeScene); QTextStream ts(&file); while (!ts.atEnd()) { QString line = ts.readLine(); QStringList items = line.split(m_delimiter, QString::SkipEmptyParts); if (items.size() < 3) continue; // edge - start node - end node /*auto edge =*/ graph.addEdge(items[0], items[1], items[2]); } file.close(); // update scene rect scene.setSceneRect(scene.itemsBoundingRect()); scene.addUndoState(); // done return true; } qvge-0.6.3/src/qvge/CFileSerializerCSV.h000066400000000000000000000017501405165517400177670ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "IFileSerializer.h" class CNode; class CFileSerializerCSV : public IFileSerializer { public: // reimp virtual QString description() const { return "Comma Separated Values"; } virtual QString filters() const { return "*.csv"; } virtual QString defaultFileExtension() const { return "csv"; } virtual bool loadSupported() const { return true; } virtual bool load(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; virtual bool saveSupported() const { return false; } virtual bool save(const QString& /*fileName*/, CEditorScene& /*scene*/, QString* /*lastError = nullptr*/) const { return false; } // setup void setDelimiter(const char d) { m_delimiter = d; } private: char m_delimiter = ';'; }; qvge-0.6.3/src/qvge/CFileSerializerDOT.cpp000066400000000000000000000175151405165517400203230ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CFileSerializerDOT.h" #include "CNode.h" #include "CEdge.h" #include "CPolyEdge.h" #include #include #include #include // reimp bool CFileSerializerDOT::save(const QString& fileName, CEditorScene& scene, QString* lastError) const { QFile saveFile(fileName); if (saveFile.open(QFile::WriteOnly)) { QTextStream ts(&saveFile); ts.setCodec("UTF-8"); //ts.setGenerateByteOrderMark(true); QString graphId = QFileInfo(fileName).completeBaseName(); ts << "digraph \"" << graphId << "\"\n{"; ts << "\n\n"; // we'll output points, not inches //ts << "\n\n"; //ts << "inputscale = 72;"; // background if (m_writeBackground) { ts << "bgcolor = \"" << scene.backgroundBrush().color().name() << "\""; ts << "\n\n"; } // nodes if (m_writeAttrs) { doWriteNodeDefaults(ts, scene); ts << "\n\n"; } auto nodes = scene.getItems(); for (auto node: nodes) { doWriteNode(ts, *node, scene); } ts << "\n\n"; // edges if (m_writeAttrs) { doWriteEdgeDefaults(ts, scene); ts << "\n\n"; } auto edges = scene.getItems(); for (auto edge: edges) { doWriteEdge(ts, *edge, scene); } ts << "\n}\n"; return true; } return false; } bool CFileSerializerDOT::load(const QString& fileName, CEditorScene& scene, QString* lastError) const { CFormatDOT dot; Graph graphModel; if (dot.load(fileName, graphModel, lastError)) return scene.fromGraph(graphModel); else return false; } // helpers static QString toDotShape(const QString& shape) { // rename to conform dot if (shape == "disc") return "ellipse"; if (shape == "square") return "rect"; if (shape == "triangle2") return "invtriangle"; // else take original return shape; } static QString toDotString(const QVariant& v) { QString val = v.toString(); return val.replace('"', "'"); } void CFileSerializerDOT::doWriteNodeDefaults(QTextStream& ts, const CEditorScene& scene) const { // build map of default attrs QMap nodeAttrs; const AttributesMap& nodeAttrMap = scene.getClassAttributes("node", false); for (const auto &attr : nodeAttrMap) { if (!(attr.flags & ATTR_NODEFAULT)) nodeAttrs[attr.id] = attr.defaultValue; } // add visible state if any QSet visSet = scene.getVisibleClassAttributes("node", false); if (!visSet.isEmpty()) nodeAttrs["_vis_"] = visSet.toList().join('|'); // write it down if (nodeAttrs.size()) { ts << "node [\n"; ts << "class = \"node\"\n"; doWriteNodeAttrs(ts, nodeAttrs); ts << "];\n"; } } void CFileSerializerDOT::doWriteNode(QTextStream& ts, const CNode& node, const CEditorScene& /*scene*/) const { ts << "\"" << node.getId() << "\""; if (m_writeAttrs) { ts << " [\n"; ts << "pos = \"" << node.pos().x() / 72.0 << "," << -node.pos().y() / 72.0 << "!\"\n"; // / 72.0 -> point to inch; -y const QMap& nodeAttrs = node.getLocalAttributes(); doWriteNodeAttrs(ts, nodeAttrs); ts << "]"; } ts << "\n\n"; } void CFileSerializerDOT::doWriteNodeAttrs(QTextStream& ts, QMap nodeAttrs) const { bool styleUsed = false; // to avoid duplicated setting of node style // standard attrs if (nodeAttrs.contains("color")) { QColor c(nodeAttrs["color"].value()); if (c.isValid()) { ts << ",fillcolor = \"" << c.name() << "\""; ts << ",style = \"filled\"\n"; styleUsed = true; } nodeAttrs.remove("color"); } if (nodeAttrs.contains("size")) { ts << ",width = \"" << nodeAttrs["size"].toSizeF().width() / 72.0 << "\""; // / 72.0 -> point to inch ts << ",height = \"" << nodeAttrs["size"].toSizeF().height() / 72.0 << "\""; ts << "\n"; nodeAttrs.remove("size"); } if (nodeAttrs.contains("shape")) { ts << ",shape = \"" << toDotShape(nodeAttrs["shape"].toString()) << "\"\n"; nodeAttrs.remove("shape"); } if (nodeAttrs.contains("stroke.color")) { ts << ",color = \"" << nodeAttrs["stroke.color"].toString() << "\"\n"; nodeAttrs.remove("stroke.color"); } if (nodeAttrs.contains("stroke.size")) { ts << ",penwidth = \"" << nodeAttrs["stroke.size"].toString() << "\"\n"; nodeAttrs.remove("stroke.size"); } if (nodeAttrs.contains("stroke.style")) { if (!styleUsed) { ts << ",style = \"" << nodeAttrs["stroke.style"].toString() << "\"\n"; styleUsed = true; } nodeAttrs.remove("stroke.style"); } // label doWriteLabel(ts, nodeAttrs); // custom attrs for (auto it = nodeAttrs.constBegin(); it != nodeAttrs.constEnd(); ++it) { ts << ",\"" << it.key() << "\" = \"" << toDotString(it.value()) << "\"\n"; } } void CFileSerializerDOT::doWriteEdgeDefaults(QTextStream& ts, const CEditorScene& scene) const { // build map of default attrs QMap edgeAttrs; const AttributesMap& edgeAttrMap = scene.getClassAttributes("edge", false); for (const auto &attr : edgeAttrMap) { if (!(attr.flags & ATTR_NODEFAULT)) edgeAttrs[attr.id] = attr.defaultValue; } // add visible state if any QSet visSet = scene.getVisibleClassAttributes("edge", false); if (!visSet.isEmpty()) edgeAttrs["_vis_"] = visSet.toList().join('|'); // write it down if (edgeAttrs.size()) { ts << "edge [\n"; ts << "class = \"edge\"\n"; doWriteEdgeAttrs(ts, edgeAttrs); ts << "];\n"; } } void CFileSerializerDOT::doWriteEdge(QTextStream& ts, const CEdge& edge, const CEditorScene& /*scene*/) const { const auto& edgeAttrs = edge.getLocalAttributes(); ts << "\"" << edge.firstNode()->getId() << "\""; if (edge.firstPortId().size()) ts << ":" << "\"" << edge.firstPortId() << "\""; ts << " -> "; ts << "\"" << edge.lastNode()->getId() << "\""; if (edge.lastPortId().size()) ts << ":" << "\"" << edge.lastPortId() << "\""; ts << " [id = \"" << edge.getId() << "\"\n"; if (m_writeAttrs) { doWriteEdgeAttrs(ts, edgeAttrs); // polyline: positions //const CPolyEdge *poly = dynamic_cast(&edge); //if (poly) //{ // ts << ", pos=\""; // auto points = poly->getPoints(); // for (int i = 0; i < points.count(); i++) // { // ts << points.at(i).x() / 72.0 << "," << points.at(i).y() / 72.0 << " "; // } // ts << "\"\n"; //} } ts << "];\n\n"; } void CFileSerializerDOT::doWriteEdgeAttrs(QTextStream& ts, QMap edgeAttrs) const { if (edgeAttrs.contains("direction")) { auto dir = edgeAttrs["direction"].toString(); edgeAttrs.remove("direction"); if (dir == "mutual") ts << ",dir=both" << "\n"; else if (dir == "undirected") ts << ",dir=none" << "\n"; } if (edgeAttrs.contains("weight")) { ts << ",weight = \"" << edgeAttrs["weight"].toString() << "\"\n"; ts << ",penwidth = \"" << edgeAttrs["weight"].toString() << "\"\n"; edgeAttrs.remove("weight"); } // label doWriteLabel(ts, edgeAttrs); // custom attrs for (auto it = edgeAttrs.constBegin(); it != edgeAttrs.constEnd(); ++it) { ts << ",\"" << it.key() << "\" = \"" << toDotString(it.value()) << "\"\n"; } } void CFileSerializerDOT::doWriteLabel(QTextStream& ts, QMap& attrs) const { if (attrs.contains("label")) { ts << ",xlabel = \"" << toDotString(attrs["label"]) << "\"\n"; attrs.remove("label"); } if (attrs.contains("label.color")) { ts << ",fontcolor = \"" << attrs["label.color"].toString() << "\"\n"; attrs.remove("label.color"); } if (attrs.contains("label.font")) { auto f = attrs["label.font"].value(); QString fontname = f.family(); if (f.bold()) fontname += " bold"; if (f.italic()) fontname += " italic"; ts << ",fontname = \"" << fontname << "\"\n"; ts << ",fontsize = \"" << f.pointSizeF() << "\"\n"; attrs.remove("label.font"); } } qvge-0.6.3/src/qvge/CFileSerializerDOT.h000066400000000000000000000033631405165517400177640ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include "qvge/IFileSerializer.h" class CNode; class CEdge; class QTextStream; class CFileSerializerDOT : public IFileSerializer { public: CFileSerializerDOT(bool writeBackground = true, bool writeAttrs = true) : m_writeBackground(writeBackground), m_writeAttrs(writeAttrs) {} // reimp virtual QString description() const { return "DOT/GraphViz graph format"; } virtual QString filters() const { return "DOT/GraphViz graphs (*.gv *.dot)"; } virtual QString defaultFileExtension() const { return "gv"; } virtual bool loadSupported() const { return true; } virtual bool load(const QString& /*fileName*/, CEditorScene& /*scene*/, QString* /*lastError = nullptr*/) const; virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; private: void doWriteNodeDefaults(QTextStream& ts, const CEditorScene& scene) const; void doWriteNode(QTextStream& ts, const CNode& node, const CEditorScene& scene) const; void doWriteNodeAttrs(QTextStream& ts, QMap nodeAttrs) const; void doWriteEdgeDefaults(QTextStream& ts, const CEditorScene& scene) const; void doWriteEdge(QTextStream& ts, const CEdge& edge, const CEditorScene& scene) const; void doWriteEdgeAttrs(QTextStream& ts, QMap edgeAttrs) const; void doWriteLabel(QTextStream& ts, QMap& attrs) const; bool m_writeBackground = true; bool m_writeAttrs = true; }; qvge-0.6.3/src/qvge/CFileSerializerGEXF.cpp000066400000000000000000000436011405165517400204210ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CFileSerializerGEXF.h" #include "CNode.h" #include "CDirectEdge.h" #include "CPolyEdge.h" #include #include #include #include #include // reimp bool CFileSerializerGEXF::load(const QString& fileName, CEditorScene& scene, QString* lastError) const { // read file into document QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) return false; QString errorString; int errorLine, errorColumn; QDomDocument doc("gexf"); if (!doc.setContent(&file, false, &errorString, &errorLine, &errorColumn)) { file.close(); if (lastError) *lastError = QObject::tr("%1\nline: %2, column: %3").arg(errorString).arg(errorLine).arg(errorColumn); return false; } file.close(); // try to parse scene.reset(); m_classIdMap.clear(); m_nodeMap.clear(); QDomNodeList graph = doc.elementsByTagName("graph"); if (graph.count()) { m_edgeType = graph.at(0).toElement().attribute("defaultedgetype", "undirected"); } QDomNodeList attrs = doc.elementsByTagName("attributes"); for (int i = 0; i < attrs.count(); ++i) { readAttrs(i, attrs.at(i), scene); } auto nodeIds = m_classIdMap["node"]; QDomNodeList nodes = doc.elementsByTagName("node"); for (int i = 0; i < nodes.count(); ++i) { readNode(i, nodes.at(i), nodeIds, scene); } auto edgeIds = m_classIdMap["edge"]; QDomNodeList edges = doc.elementsByTagName("edge"); for (int i = 0; i < edges.count(); ++i) { readEdge(i, edges.at(i), edgeIds, scene); } // update scene rect scene.setSceneRect(scene.itemsBoundingRect()); scene.addUndoState(); return true; } bool CFileSerializerGEXF::readAttrs(int /*index*/, const QDomNode &domNode, CEditorScene &scene) const { QDomElement elem = domNode.toElement(); QByteArray classId = elem.attribute("class", "").toLatin1(); AttributesMap existingAttrs = scene.getClassAttributes(classId, true); auto attrs = elem.elementsByTagName("attribute"); for (int i = 0; i < attrs.count(); ++i) { QDomElement attrElem = attrs.at(i).toElement(); QByteArray id = attrElem.attribute("id", "").toLatin1(); if (id.isEmpty()) continue; QByteArray attrId = attrElem.attribute("title", "").toLatin1(); if (attrId.isEmpty()) attrId = id; QByteArray type = attrElem.attribute("type", "").toLatin1(); AttrInfo attrInfo = {attrId, 0}; QString def; auto defs = attrElem.elementsByTagName("default"); if (defs.size()) def = defs.at(0).toElement().text(); if (type == "integer" || type == "long") { attrInfo.variantType = QVariant::Int; } else if (type == "double" || type == "float") { attrInfo.variantType = QVariant::Double; } else if (type == "boolean") { attrInfo.variantType = QVariant::Bool; } else if (type == "liststring") { attrInfo.variantType = QVariant::StringList; } else // string { attrInfo.variantType = QVariant::String; } CAttribute attr = existingAttrs[attrId]; if (attr.id.isEmpty()) { // no such attr attr.id = attrId; attr.classId = classId; attr.valueType = attrInfo.variantType; } else // exist attrInfo.variantType = attr.valueType; if (def.size()) { // visibility attr if (attrId == "_vis_") { auto visList = def.splitRef('|'); for (auto& id : visList) scene.setClassAttributeVisible(classId, id.toLatin1()); continue; } // stringlists if (attrInfo.variantType == QVariant::StringList) { attr.defaultValue = def.split('|'); continue; } // other attrs QVariant v = CUtils::textToVariant(def, attrInfo.variantType); if (attrId == "size" && classId == "node") { v = QSizeF(v.toDouble(), v.toDouble()); } attr.defaultValue = v; } scene.setClassAttribute(classId, attr); m_classIdMap[classId][id] = attrInfo; } return true; } bool CFileSerializerGEXF::readNode(int index, const QDomNode &domNode, const IdToAttrMap &idMap, CEditorScene &scene) const { QDomElement elem = domNode.toElement(); CNode* node = scene.createItemOfType(); if (!node) return false; // common attrs QString id = elem.attribute("id", ""); node->setAttribute("id", id); QString label = elem.attribute("label", ""); node->setAttribute("label", label); // viz: attrs (v1.2), ns0: attrs (v1.1) QDomNodeList viz_pos = elem.elementsByTagName("viz:position"); // v1.2 if (viz_pos.isEmpty()) viz_pos = elem.elementsByTagName("ns0:position"); // v1.1 if (viz_pos.size()) { QDomElement viz_elem = viz_pos.at(0).toElement(); float x = viz_elem.attribute("x", "0").toFloat(); float y = viz_elem.attribute("y", "0").toFloat(); float z = viz_elem.attribute("z", QString(index)).toFloat(); node->setPos(x, y); node->setZValue(z); } QDomNodeList viz_color = elem.elementsByTagName("viz:color"); // v1.2 if (viz_color.isEmpty()) viz_color = elem.elementsByTagName("ns0:color"); // v1.1 if (viz_color.size()) { QDomElement viz_elem = viz_color.at(0).toElement(); int r = viz_elem.attribute("r", "0").toInt(); int g = viz_elem.attribute("g", "0").toInt(); int b = viz_elem.attribute("b", "0").toInt(); QColor color(r, g, b); node->setAttribute("color", color); } QDomNodeList viz_size = elem.elementsByTagName("viz:size"); // v1.2 if (viz_size.isEmpty()) viz_size = elem.elementsByTagName("ns0:size"); // v1.1 if (viz_size.size()) { QSizeF sz = node->getSize(); QDomElement viz_elem = viz_size.at(0).toElement(); if (viz_elem.hasAttribute("value")) { float v = viz_elem.attribute("value", "5").toFloat(); sz.setWidth(v); sz.setHeight(v); } if (viz_elem.hasAttribute("width")) sz.setWidth(viz_elem.attribute("width").toFloat()); if (viz_elem.hasAttribute("height")) sz.setHeight(viz_elem.attribute("height").toFloat()); node->setAttribute("size", sz); } // shape QDomNodeList viz_shape = elem.elementsByTagName("viz:shape"); // v1.2 if (viz_shape.isEmpty()) viz_shape = elem.elementsByTagName("ns0:shape"); // v1.1 if (viz_shape.size()) { QDomElement viz_elem = viz_shape.at(0).toElement(); QString v = viz_elem.attribute("value", "disc"); node->setAttribute("shape", v); } // attrs QDomNodeList attrs = elem.elementsByTagName("attvalue"); for (int i = 0; i < attrs.count(); ++i) { auto attrElem = attrs.at(i).toElement(); QByteArray attrId = attrElem.attribute("id", "").toLatin1(); // v1.2 if (attrId.isEmpty()) attrId = attrElem.attribute("for", "").toLatin1(); // v1.1 if (attrId.isEmpty()) continue; // error: no id if (!idMap.contains(attrId)) continue; // error: not valid id QVariant value = CUtils::textToVariant(attrElem.attribute("value"), idMap[attrId].variantType); node->setAttribute(idMap[attrId].id, value); } scene.addItem(node); m_nodeMap[id] = node; //node->onItemRestored(); return true; } bool CFileSerializerGEXF::readEdge(int /*index*/, const QDomNode &domNode, const IdToAttrMap &idMap, CEditorScene& scene) const { QDomElement elem = domNode.toElement(); CEdge *link = nullptr; // polypoints (qvge specific: not a part of v1.2) QDomNodeList viz_points = elem.elementsByTagName("qvge:points"); if (viz_points.size()) { link = scene.createItemOfType(); if (!link) return false; QDomElement viz_elem = viz_points.at(0).toElement(); QString v = viz_elem.attribute("data", ""); link->setAttribute("points", v); } else { link = scene.createItemOfType(); if (!link) return false; } // common attrs QString id = elem.attribute("id", ""); link->setAttribute("id", id); QString label = elem.attribute("label", ""); link->setAttribute("label", label); QString source = elem.attribute("source", ""); QString target = elem.attribute("target", ""); CNode* start = m_nodeMap[source]; CNode* last = m_nodeMap[target]; link->setFirstNode(start); link->setLastNode(last); // line double weight = elem.attribute("weight", "-1").toDouble(); if (weight >= 0) link->setAttribute("weight", weight); // direction QString edgeType = elem.attribute("edgetype", ""); if (edgeType.isEmpty()) edgeType = m_edgeType; link->setAttribute("direction", edgeType); // color QDomNodeList viz_color = elem.elementsByTagName("viz:color"); // v1.2 if (viz_color.isEmpty()) viz_color = elem.elementsByTagName("ns0:color"); // v1.1 if (viz_color.size()) { QDomElement viz_elem = viz_color.at(0).toElement(); int r = viz_elem.attribute("r", "0").toInt(); int g = viz_elem.attribute("g", "0").toInt(); int b = viz_elem.attribute("b", "0").toInt(); QColor color(r, g, b); link->setAttribute("color", color); } // thickness QDomNodeList viz_thickness = elem.elementsByTagName("viz:thickness"); // v1.2 if (viz_thickness.isEmpty()) viz_thickness = elem.elementsByTagName("ns0:thickness"); // v1.1 if (viz_thickness.size()) { QDomElement viz_elem = viz_thickness.at(0).toElement(); float v = viz_elem.attribute("value", "1").toFloat(); link->setAttribute("thickness", v); } // shape QDomNodeList viz_shape = elem.elementsByTagName("viz:shape"); // v1.2 if (viz_shape.isEmpty()) viz_shape = elem.elementsByTagName("ns0:shape"); // v1.1 if (viz_shape.size()) { QDomElement viz_elem = viz_shape.at(0).toElement(); QString v = viz_elem.attribute("value", "solid"); link->setAttribute("style", v); } // attrs QDomNodeList attrs = elem.elementsByTagName("attvalue"); for (int i = 0; i < attrs.count(); ++i) { auto attrElem = attrs.at(i).toElement(); QByteArray attrId = attrElem.attribute("id", "").toLatin1(); // v1.2 if (attrId.isEmpty()) attrId = attrElem.attribute("for", "").toLatin1(); // v1.1 if (attrId.isEmpty()) continue; // error: no id if (!idMap.contains(attrId)) continue; // error: not valid id QVariant value = CUtils::textToVariant(attrElem.attribute("value"), idMap[attrId].variantType); link->setAttribute(idMap[attrId].id, value); } scene.addItem(link); //link->onItemRestored(); return true; } bool CFileSerializerGEXF::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) return false; QTextStream ts(&file); ts.setCodec("UTF-8"); // header ts << "\n" "\n"; ts << " \n" " " << QApplication::applicationDisplayName() << "\n" " " << scene.getClassAttribute("", "comment", false).defaultValue.toString().toHtmlEscaped() << "\n" " \n"; // graph QString edgetype = scene.getClassAttribute("edge", "direction", false).defaultValue.toString(); //QString edgetype = scene.getClassAttribute("direction", false).defaultValue.toString(); ts << " \n"; writeClassAttrs(ts, scene, ""); // node attrs writeClassAttrs(ts, scene, "node"); // edge attrs writeClassAttrs(ts, scene, "edge"); // nodes writeNodes(ts, scene); // edges writeEdges(ts, scene); // footer ts << " \n"; ts << "\n"; return true; } static QString typeToString(int valueType) { switch (valueType) { case QMetaType::Bool: return "boolean"; case QMetaType::Int: case QMetaType::UInt: return "integer"; case QMetaType::Long: case QMetaType::ULong: return "long"; case QMetaType::Double: return "double"; case QMetaType::Float: return "float"; case QMetaType::QStringList: return "liststring"; // url default: return "string"; } } void CFileSerializerGEXF::writeClassAttrs(QTextStream &ts, const CEditorScene& scene, const QByteArray &classId) const { auto attrs = scene.getClassAttributes(classId, false); // add local attributes if any if (classId.size()) { auto items = (classId == "node") ? scene.getItems(): scene.getItems(); for (auto item : items) { auto itemAttrs = item->getLocalAttributes(); for (auto it = itemAttrs.constBegin(); it != itemAttrs.constEnd(); ++it) { auto id = it.key(); if (!attrs.contains(id)) attrs[id] = CAttribute(id); } } } // add visible state if any QSet visSet = scene.getVisibleClassAttributes(classId, false); if (!visSet.isEmpty()) { QStringList visList; for (auto& id : visSet) visList << id; CAttribute visAttr("_vis_", "Visibility", visList); attrs["_vis_"] = visAttr; } if (attrs.isEmpty()) return; ts << " \n"; for (auto it = attrs.constBegin(); it != attrs.constEnd(); ++it) { const auto &attr = it.value(); if (attr.flags & ATTR_VIRTUAL) continue; // size if (it.key() == "size") { ts << " \n"; if (attr.defaultValue.canConvert(QMetaType::QSizeF)) { QSizeF size = attr.defaultValue.toSizeF(); ts << " " << qMax(size.width(), size.height()) << "\n"; } else ts << " " << attr.defaultValue.toFloat() << "\n"; ts << " \n"; continue; } // others (id = title) ts << " \n"; if (!(attr.flags & ATTR_NODEFAULT) && attr.defaultValue.isValid()) { ts << " "; if (attr.valueType == QMetaType::QStringList) ts << attr.defaultValue.toStringList().join('|'); else ts << attr.defaultValue.toString(); ts << "\n"; } ts << " \n"; } ts << " \n"; } void CFileSerializerGEXF::writeNodes(QTextStream &ts, const CEditorScene& scene) const { ts << " \n"; auto nodes = scene.getItems(); for (const auto &node : nodes) { QMap nodeAttrs = node->getLocalAttributes(); ts << " getId() << "\" label=\"" << nodeAttrs.take("label").toString().toHtmlEscaped() << "\">\n"; ts << " pos().x() << "\" y=\"" << node->pos().y() << "\"/>\n"; if (nodeAttrs.contains("size")) { QVariant sizeV = nodeAttrs.take("size"); if (sizeV.canConvert(QMetaType::QSizeF)) { QSizeF size = sizeV.toSizeF(); if (size.width() == size.height()) ts << " \n"; else ts << " \n"; // non-standard extension } else ts << " \n"; } if (nodeAttrs.contains("color")) { QColor c = nodeAttrs.take("color").value(); ts << " \n"; } if (nodeAttrs.contains("shape")) { QString shape = nodeAttrs.take("shape").toString(); ts << " \n"; } writeAttValues(ts, nodeAttrs); ts << " \n"; } ts << " \n"; } void CFileSerializerGEXF::writeEdges(QTextStream &ts, const CEditorScene& scene) const { ts << " \n"; auto edges = scene.getItems(); for (auto edge : edges) { QMap edgeAttrs = edge->getLocalAttributes(); ts << " getId() << "\" label=\"" << edgeAttrs.take("label").toString().toHtmlEscaped() << "\" source=\"" << edge->firstNode()->getId() << "\" target=\"" << edge->lastNode()->getId(); QString edgetype = edgeAttrs.take("direction").toString(); if (edgetype.size()) { ts << "\" edgetype=\"" << edgetype; } ts << "\">\n"; if (edgeAttrs.contains("thickness")) { ts << " \n"; } if (edgeAttrs.contains("color")) { QColor c = edgeAttrs.take("color").value(); ts << " \n"; } if (edgeAttrs.contains("style")) { QString shape = edgeAttrs.take("style").toString(); ts << " \n"; } // polypoints auto polyEdge = dynamic_cast(edge); if (polyEdge) { const QList& points = polyEdge->getPoints(); if (points.size()){ QString pointStr = CUtils::pointsToString(points); ts << " \n"; } } writeAttValues(ts, edgeAttrs); ts << " \n"; } ts << " \n"; } void CFileSerializerGEXF::writeAttValues(QTextStream &ts, const QMap& attvalues) const { if (attvalues.size()) { ts << " \n"; for (auto it = attvalues.constBegin(); it != attvalues.constEnd(); ++it) { ts << " \n"; } ts << " \n"; } } qvge-0.6.3/src/qvge/CFileSerializerGEXF.h000066400000000000000000000035241405165517400200660ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "IFileSerializer.h" #include #include #include #include class CNode; class CFileSerializerGEXF : public IFileSerializer { public: // reimp virtual QString description() const { return "Graph Exchange XML Format"; } virtual QString filters() const { return "*.gexf"; } virtual QString defaultFileExtension() const { return "gexf"; } virtual bool loadSupported() const { return true; } virtual bool load(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; private: struct AttrInfo { QByteArray id; int variantType; }; typedef QMap IdToAttrMap; mutable QMap m_classIdMap; bool readAttrs(int index, const QDomNode &domNode, CEditorScene& scene) const; bool readNode(int index, const QDomNode &domNode, const IdToAttrMap &idMap, CEditorScene& scene) const; bool readEdge(int index, const QDomNode &domNode, const IdToAttrMap &idMap, CEditorScene& scene) const; void writeClassAttrs(QTextStream &ts, const CEditorScene& scene, const QByteArray &classId) const; void writeNodes(QTextStream &ts, const CEditorScene& scene) const; void writeEdges(QTextStream &ts, const CEditorScene& scene) const; void writeAttValues(QTextStream &ts, const QMap& attvalues) const; mutable QMap m_nodeMap; enum EdgeType { Directed, Undirected, Mutual }; mutable QString m_edgeType; }; qvge-0.6.3/src/qvge/CFileSerializerGraphML.cpp000066400000000000000000000015761405165517400211670ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CFileSerializerGraphML.h" #include "CAttribute.h" #include "CNode.h" #include "CDirectEdge.h" #include #include #include // reimp bool CFileSerializerGraphML::load(const QString& fileName, CEditorScene& scene, QString* lastError) const { CFormatGraphML graphML; Graph graphModel; if (graphML.load(fileName, graphModel, lastError)) return scene.fromGraph(graphModel); else return false; } bool CFileSerializerGraphML::save(const QString& fileName, CEditorScene& scene, QString* lastError) const { CFormatGraphML graphML; Graph graphModel; if (scene.toGraph(graphModel)) return graphML.save(fileName, graphModel, lastError); else return false; } qvge-0.6.3/src/qvge/CFileSerializerGraphML.h000066400000000000000000000014631405165517400206270ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "IFileSerializer.h" class CFileSerializerGraphML : public IFileSerializer { public: // reimp virtual QString description() const { return "GraphML Format"; } virtual QString filters() const { return "*.graphml"; } virtual QString defaultFileExtension() const { return "graphml"; } virtual bool loadSupported() const { return true; } virtual bool load(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; }; qvge-0.6.3/src/qvge/CFileSerializerPlainDOT.cpp000066400000000000000000000016241405165517400213010ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CFileSerializerPlainDOT.h" #include "CAttribute.h" #include "CNode.h" #include "CDirectEdge.h" #include #include #include // reimp bool CFileSerializerPlainDOT::load(const QString& fileName, CEditorScene& scene, QString* lastError) const { CFormatPlainDOT graphFormat; Graph graphModel; if (graphFormat.load(fileName, graphModel, lastError)) return scene.fromGraph(graphModel); else return false; } bool CFileSerializerPlainDOT::save(const QString& fileName, CEditorScene& scene, QString* lastError) const { CFormatPlainDOT graphFormat; Graph graphModel; if (scene.toGraph(graphModel)) return graphFormat.save(fileName, graphModel, lastError); else return false; } qvge-0.6.3/src/qvge/CFileSerializerPlainDOT.h000066400000000000000000000015351405165517400207470ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "IFileSerializer.h" class CFileSerializerPlainDOT : public IFileSerializer { public: // reimp virtual QString description() const { return "Plain Text DOT Format"; } virtual QString filters() const { return "Plain Text DOT/GraphViz Graphs (*.plain *.txt)"; } virtual QString defaultFileExtension() const { return "txt"; } virtual bool loadSupported() const { return true; } virtual bool load(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; virtual bool saveSupported() const { return false; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; }; qvge-0.6.3/src/qvge/CFileSerializerXGR.cpp000066400000000000000000000034431405165517400203300ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CFileSerializerXGR.h" #include "CEditorScene.h" #include "ISceneItemFactory.h" #include #include // static reader with DPSE format support class CDPSERecoder : public ISceneItemFactory { public: virtual CItem* createItemOfType(const QByteArray& typeId, const CEditorScene& scene) const { if (typeId == "CBranchNode") { return scene.createItemOfType("CNode"); } if (typeId == "CFanNode") { return scene.createItemOfType("CNode"); } if (typeId == "CBranchConnection" || typeId == "CDirectConnection") { return scene.createItemOfType("CDirectEdge"); } return nullptr; } }; static CDPSERecoder s_dpseRecoder; // reimp bool CFileSerializerXGR::load(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { // read file into document QFile openFile(fileName); if (!openFile.open(QIODevice::ReadOnly)) return false; scene.reset(); scene.setItemFactoryFilter(&s_dpseRecoder); QDataStream ds(&openFile); #if (QT_VERSION >= 0x050a00) ds.setVersion(QDataStream::Qt_5_10); #endif scene.restoreFrom(ds, true); scene.setItemFactoryFilter(nullptr); scene.addUndoState(); return true; } bool CFileSerializerXGR::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { QFile saveFile(fileName); if (saveFile.open(QFile::WriteOnly)) { QDataStream ds(&saveFile); #if (QT_VERSION >= 0x050a00) ds.setVersion(QDataStream::Qt_5_10); #endif scene.storeTo(ds, true); return true; } return false; } qvge-0.6.3/src/qvge/CFileSerializerXGR.h000066400000000000000000000015351405165517400177750ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include "qvge/IFileSerializer.h" class CNode; class CFileSerializerXGR : public IFileSerializer { public: // reimp virtual QString description() const { return "QVGE graph scene format"; } virtual QString filters() const { return "*.xgr"; } virtual QString defaultFileExtension() const { return "xgr"; } virtual bool loadSupported() const { return true; } virtual bool load(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; }; qvge-0.6.3/src/qvge/CGraphInterface.cpp000066400000000000000000000053531405165517400177220ustar00rootroot00000000000000#include "CGraphInterface.h" #include "CNodeEditorScene.h" #include "CNode.h" #include "CDirectEdge.h" CGraphInterface::CGraphInterface(CNodeEditorScene &scene) { m_scene = &scene; } CEdge* CGraphInterface::addEdge(const QString &edgeId, const QString &startNodeId, const QString &endNodeId) { if (m_scene == nullptr) return nullptr; // look for existing edge if (m_scene->getItemsById(edgeId).count()) return nullptr; auto* edge = m_scene->createItemOfType(); if (!edge) return nullptr; auto* node1 = getNode(startNodeId, true); if (!node1) return nullptr; auto* node2 = getNode(endNodeId, true); if (!node2) return nullptr; edge->setId(edgeId); edge->setFirstNode(node1); edge->setLastNode(node2); m_scene->addItem(edge); return edge; } CNode* CGraphInterface::addNode(const QString &nodeId) { if (m_scene == nullptr) return nullptr; // look for existing node if (m_scene->getItemsById(nodeId).count()) return nullptr; auto* node = m_scene->createItemOfType(); if (!node) return nullptr; node->setId(nodeId); m_scene->addItem(node); return node; } CNode* CGraphInterface::getNode(const QString &nodeId, bool autoCreate) { if (m_scene == nullptr) return nullptr; // look for existing node auto nodes = (m_scene->getItemsById(nodeId)); if (nodes.count()) return nodes.first(); if (autoCreate) { auto* node = m_scene->createItemOfType(); if (!node) return nullptr; node->setId(nodeId); m_scene->addItem(node); return node; } return nullptr; } CEdge* CGraphInterface::getEdge(const QString& edgeId) { if (m_scene == nullptr) return nullptr; // look for existing edge auto edges = (m_scene->getItemsById(edgeId)); if (edges.count()) return edges.first(); return nullptr; } bool CGraphInterface::setEdgeAttr(const QString& edgeId, const QByteArray& attrId, const QVariant& value) { CEdge* edge = getEdge(edgeId); if (edge) return edge->setAttribute(attrId, value); else return false; } QList CGraphInterface::getEdges() const { QList edges; if (m_scene) { auto items = m_scene->items(); for (auto item: items) if (auto edge = dynamic_cast(item)) edges << edge; } return edges; } QList CGraphInterface::getNodes() const { QList nodes; if (m_scene) { auto items = m_scene->items(); for (auto item: items) if (auto node = dynamic_cast(item)) nodes << node; } return nodes; } qvge-0.6.3/src/qvge/CGraphInterface.h000066400000000000000000000016541405165517400173670ustar00rootroot00000000000000#ifndef CGRAPHINTERFACE_H #define CGRAPHINTERFACE_H #include "IGraphInterface.h" class CNodeEditorScene; class CGraphInterface: public IGraphInterface { public: CGraphInterface() {} explicit CGraphInterface(CNodeEditorScene& scene); virtual ~CGraphInterface() {} void setScene(CNodeEditorScene& scene) { m_scene = &scene; } // interface (to move out?) virtual CNode* addNode(const QString& nodeId); virtual CNode* getNode(const QString& nodeId, bool autoCreate = false); virtual CEdge* addEdge(const QString& edgeId, const QString& startNodeId, const QString& endNodeId); virtual CEdge* getEdge(const QString& edgeId); virtual bool setEdgeAttr(const QString& edgeId, const QByteArray& attrId, const QVariant& value); virtual QList getEdges() const; virtual QList getNodes() const; private: CNodeEditorScene *m_scene = nullptr; }; #endif // CGRAPHINTERFACE_H qvge-0.6.3/src/qvge/CImageExport.cpp000066400000000000000000000057201405165517400172620ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L.Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include #include #include #include #include #include "CImageExport.h" #include "CEditorScene.h" QString CImageExport::filters() const { static QList formats = QImageWriter::supportedImageFormats(); if (formats.isEmpty()) return QString(); static QMap formatNames = { { "bmp", "Windows Bitmap (*.bmp)" }, { "ico", "Windows Icon (*.ico *.cur)" }, { "gif", "Graphic Interchange Format (*.gif)" }, { "jpg", "Joint Photographic Experts Group (*.jpg *.jpeg)" }, { "png", "Portable Network Graphics (*.png)" }, { "pbm", "Portable Bitmap (*.pbm)" }, { "pgm", "Portable Graymap (*.pgm)" }, { "ppm", "Portable Pixmap (*.ppm)" }, { "svg", "Scalable Vector Graphics (*.svg)" }, { "tif", "Tagged Image File Format (*.tif *.tiff)" }, { "xbm", "X11 Bitmap (*.xbm)" }, { "xpm", "X11 Pixmap (*.xpm)" }, { "wbmp", "Wireless Bitmap (*.wbmp)" }, { "webp", "WebP (*.webp)" }, { "icns", "Apple Icon Image (*.icns)" } }; static QMap recodeMap = { { "jpeg", "jpg" }, { "tiff", "tif" }, { "cur", "ico" } }; static QString filter; if (filter.isEmpty()) { QSet usedFormats; for (auto format : formats) { auto suffix = format.toLower(); if (recodeMap.contains(suffix)) usedFormats << recodeMap[suffix]; else usedFormats << suffix; } // add known formats for (auto it = formatNames.constBegin(); it != formatNames.constEnd(); ++it) { if (usedFormats.contains(it.key())) { usedFormats.remove(it.key()); filter += it.value() + ";;"; } } // add evtl. unlisted ones for (auto format : usedFormats) { filter += format + " (*." + format + ");;"; } filter.chop(2); } return filter; } bool CImageExport::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { QScopedPointer tempScene(scene.clone()); if (m_cutContent) tempScene->crop(); QImage image(tempScene->sceneRect().size().toSize(), QImage::Format_ARGB32); QRect targetRect; // empty by default // resolution int old_dpi = image.physicalDpiX(); if (old_dpi <= 0) old_dpi = 96; if (m_resolution > 0 && old_dpi != m_resolution) { double coeff = (double)m_resolution / (double)old_dpi; int dpm = m_resolution / 0.0254; image.setDotsPerMeterX(dpm); image.setDotsPerMeterY(dpm); QSize newSize = image.size() * coeff; image = image.scaled(newSize); targetRect = QRect(0,0, newSize.width(), newSize.height()); } image.fill(Qt::white); QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); tempScene->render(&painter, targetRect); painter.end(); return image.save(fileName); } qvge-0.6.3/src/qvge/CImageExport.h000066400000000000000000000017631405165517400167320ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L.Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include "qvge/IFileSerializer.h" class CImageExport : public IFileSerializer { public: CImageExport(bool cutContent = true, int resolution = 0) : m_cutContent(cutContent), m_resolution(resolution) {} // reimp virtual QString description() const { return "Image Format"; } virtual QString filters() const; virtual QString defaultFileExtension() const { return "bmp"; } virtual bool loadSupported() const { return false; } virtual bool load(const QString& /*fileName*/, CEditorScene& /*scene*/, QString* /*lastError = nullptr*/) const { return false; } virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; private: bool m_cutContent = true; int m_resolution = 96; }; qvge-0.6.3/src/qvge/CItem.cpp000066400000000000000000000147241405165517400157400ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CItem.h" #include "CEditorSceneDefines.h" #include #include bool CItem::s_duringRestore = false; CItem::CItem() { m_labelItem = NULL; // default item flags m_itemFlags = IF_DeleteAllowed | IF_FramelessSelection; m_internalStateFlags = IS_Attribute_Changed | IS_Need_Update; } CItem::~CItem() { CEditorScene *scene = getScene(); if (scene) scene->onItemDestroyed(this); } // IO bool CItem::storeTo(QDataStream &out, quint64 version64) const { if (version64 >= 2) { out << m_attributes; } if (version64 >= 4) { out << m_id; } return true; } bool CItem::restoreFrom(QDataStream &out, quint64 version64) { if (!out.atEnd()) { if (version64 >= 2) { out >> m_attributes; } else m_attributes.clear(); if (version64 >= 4) { out >> m_id; } return true; } return false; } // attributes bool CItem::hasLocalAttribute(const QByteArray& attrId) const { if (attrId == "id") return true; else return m_attributes.contains(attrId); } bool CItem::setAttribute(const QByteArray& attrId, const QVariant& v) { setItemStateFlag(IS_Attribute_Changed); if (attrId == "id") { m_id = v.toString(); return true; } // real attributes m_attributes[attrId] = v; return true; } bool CItem::removeAttribute(const QByteArray& attrId) { if (m_attributes.remove(attrId)) { setItemStateFlag(IS_Attribute_Changed); return true; } else return false; } QVariant CItem::getAttribute(const QByteArray& attrId) const { if (attrId == "id") return m_id; if (m_attributes.contains(attrId)) return m_attributes[attrId]; if (auto scene = getScene()) return scene->getClassAttribute(classId(), attrId, true).defaultValue; return QVariant(); } QSet CItem::getVisibleAttributeIds(int flags) const { QSet result; if (flags == VF_ANY || flags == VF_TOOLTIP) result = getLocalAttributes().keys().toSet(); if (flags == VF_LABEL) result += "label"; if (auto scene = getScene()) { if (flags == VF_ANY || flags == VF_TOOLTIP) result += scene->getClassAttributes(classId(), false).keys().toSet(); else result += scene->getVisibleClassAttributes(classId(), false); } return result; } bool CItem::setDefaultId() { if (m_id.isEmpty()) { m_id = createNewId(); return true; } return false; } // scene stuff CEditorScene* CItem::getScene() const { if (auto sceneItem = getSceneItem()) return dynamic_cast(sceneItem->scene()); else return NULL; } void CItem::addUndoState() { if (auto scene = getScene()) scene->addUndoState(); } // cloning void CItem::copyDataFrom(CItem* from) { m_itemFlags = from->m_itemFlags; // copy attrs m_attributes = from->m_attributes; updateCachedItems(); } // painting void CItem::updateLabelContent() { auto scene = getScene(); if (!scene) return; if (!(m_internalStateFlags & IS_Attribute_Changed) && !(scene->itemLabelsEnabled()) && !(scene->itemLabelsNeedUpdate()) ) return; resetItemStateFlag(IS_Attribute_Changed); if (!m_labelItem) return; QString labelToShow; auto idsToShow = getVisibleAttributeIds(CItem::VF_LABEL); QMap visibleLabels; for (const QByteArray& id : idsToShow) { QString text = CUtils::variantToText(getAttribute(id)); if (text.size()) visibleLabels[id] = text; } // ids first if (idsToShow.contains("id")) { labelToShow = "[" + visibleLabels["id"] + "]"; visibleLabels.remove("id"); } // other labels if (visibleLabels.size() == 1 && idsToShow.contains("label")) { if (labelToShow.size()) labelToShow += "\n"; labelToShow += visibleLabels.values().first(); } else { for (auto it = visibleLabels.constBegin(); it != visibleLabels.constEnd(); ++it) { if (labelToShow.size()) labelToShow += "\n"; labelToShow += QString("%1: %2").arg(QString(it.key())).arg(it.value()); } } // text setLabelText(labelToShow); // label attrs m_labelItem->setBrush(getAttribute(attr_label_color).value()); QFont f(getAttribute(attr_label_font).value()); if (!scene->isFontAntialiased()) f.setStyleStrategy(QFont::NoAntialias); m_labelItem->setFont(f); // update explicitly m_labelItem->update(); } void CItem::updateLabelDecoration() { if (!m_labelItem) return; if (m_internalStateFlags & IS_Selected) m_labelItem->setOpacity(0.6); else m_labelItem->setOpacity(1.0); //if (m_internalStateFlags & IS_Selected) // m_labelItem->setBrush(QColor(QStringLiteral("orange"))); //else // m_labelItem->setBrush(getAttribute(QByteArrayLiteral("label.color")).value()); } void CItem::setLabelText(const QString& text) { if (m_labelItem) m_labelItem->setText(text); } void CItem::showLabel(bool on) { if (m_labelItem) { m_labelItem->setVisible(on); if (on) updateLabelDecoration(); } } QRectF CItem::getSceneLabelRect() const { if (!m_labelItem) return QRectF(); else return m_labelItem->mapRectToScene(m_labelItem->boundingRect()); } QPointF CItem::getLabelCenter() const { if (m_labelItem) return getSceneLabelRect().center(); else if (auto sceneItem = getSceneItem()) return sceneItem->boundingRect().center(); else return QPointF(); } // callbacks void CItem::onItemRestored() { updateCachedItems(); } void CItem::onItemSelected(bool state) { if (state) m_internalStateFlags |= IS_Selected; else m_internalStateFlags &= ~IS_Selected; updateLabelDecoration(); } void CItem::onHoverEnter(QGraphicsItem* sceneItem, QGraphicsSceneHoverEvent*) { /* // update tooltip auto idsToShow = getVisibleAttributeIds(CItem::VF_TOOLTIP).toList(); if (idsToShow.isEmpty()) { sceneItem->setToolTip(""); return; } qSort(idsToShow); QString tooltipToShow(""); for (const QByteArray& id : idsToShow) { QString text = CUtils::variantToText(getAttribute(id)); tooltipToShow += QString("").arg(QString(id)).arg(text); } tooltipToShow += "
%1: %2
"; */ QString tooltipToShow = CUtils::variantToText(getAttribute("tooltip")); sceneItem->setToolTip(tooltipToShow); } // internal void CItem::updateCachedItems() { setItemStateFlag(IS_Attribute_Changed); // update text label if (getScene() && getScene()->itemLabelsEnabled()) { updateLabelContent(); updateLabelPosition(); updateLabelDecoration(); } } qvge-0.6.3/src/qvge/CItem.h000066400000000000000000000113701405165517400153770ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CITEM_H #define CITEM_H #include #include #include #include #include "CEditorScene.h" #include "Properties.h" #include "CUtils.h" #include "IInteractive.h" enum ItemFlags { IF_FramelessSelection = 1, IF_DeleteAllowed = 2, IF_LastFlag = 4 }; enum ItemStateFlags { IS_Normal = 0, IS_Selected = 1, IS_Hover = 2, IS_Drag_Accepted = 4, IS_Drag_Rejected = 8, IS_Attribute_Changed = 16, IS_Need_Update = 32 }; class CControlPoint; class Stub { public: typedef Stub Super; static QByteArray factoryId() { return ""; } }; class CItem: public IInteractive { public: typedef Stub Super; CItem(); virtual ~CItem(); int itemFlags() const { return m_itemFlags; } void setItemFlags(int f) { m_itemFlags = f; } void setItemFlag(int f) { m_itemFlags |= f; } void resetItemFlag(int f) { m_itemFlags &= ~f; } int itemStateFlags() const { return m_internalStateFlags; } void setItemStateFlag(int f) { m_internalStateFlags |= f; } void resetItemStateFlag(int f) { m_internalStateFlags &= ~f; } // to be reimplemented static QByteArray factoryId() { return "CItem"; } virtual QByteArray typeId() const { return this->factoryId(); } virtual QString createNewId() const { return QString::number((quint64)this); } virtual bool setDefaultId(); template QString createUniqueId(const QString& Tmpl) const; // attributes virtual bool hasLocalAttribute(const QByteArray& attrId) const; const QMap& getLocalAttributes() const { return m_attributes; } virtual bool setAttribute(const QByteArray& attrId, const QVariant& v); virtual bool removeAttribute(const QByteArray& attrId); virtual QVariant getAttribute(const QByteArray& attrId) const; virtual QByteArray classId() const { return "item"; } virtual QByteArray superClassId() const { return QByteArray(); } QString getId() const { return m_id; } void setId(const QString& id) { setAttribute("id", id); } enum VisibleFlags { VF_ANY = 0, VF_LABEL = 1, VF_TOOLTIP = 2 }; virtual QSet getVisibleAttributeIds(int flags) const; // scene access QGraphicsItem* getSceneItem() const { return dynamic_cast((CItem*)this); } CEditorScene* getScene() const; void addUndoState(); // labels virtual void updateLabelContent(); virtual void updateLabelDecoration(); virtual void updateLabelPosition() {} void setLabelText(const QString& text); void showLabel(bool on); QRectF getSceneLabelRect() const; virtual QPointF getLabelCenter() const; // transformations virtual void transform(const QRectF& oldRect, const QRectF& newRect, double xc, double yc, bool changeSize, bool changePos) {} // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; virtual bool restoreFrom(QDataStream& out, quint64 version64); typedef QMap CItemLinkMap; virtual bool linkAfterRestore(const CItemLinkMap& /*idToItem*/) { return true; } virtual bool linkAfterPaste(const CItemLinkMap& idToItem) { return linkAfterRestore(idToItem); } // default the same static void beginRestore() { s_duringRestore = true; } static void endRestore() { s_duringRestore = false; } // returns new item of this class virtual CItem* clone() = 0; virtual CItem* create() const = 0; // copy data from item virtual void copyDataFrom(CItem* from); // callbacks virtual void onItemRestored(); virtual void onItemSelected(bool state); virtual void onHoverEnter(QGraphicsItem* sceneItem, QGraphicsSceneHoverEvent* event); // call from control points virtual void onControlPointMoved(CControlPoint* /*controlPoint*/, const QPointF& /*pos*/) {} virtual void onControlPointDelete(CControlPoint* /*controlPoint*/) {} // call from drag event virtual ItemDragTestResult acceptDragFromItem(QGraphicsItem* /*draggedItem*/) { return Accepted; } // called after restoring data (reimplement to update cached attribute values) virtual void updateCachedItems(); protected: int m_itemFlags; int m_internalStateFlags; QMap m_attributes; QString m_id; QGraphicsSimpleTextItem *m_labelItem; // restore optimization static bool s_duringRestore; }; template QString CItem::createUniqueId(const QString& tmpl) const { auto editorScene = getScene(); if (editorScene == NULL) { static int count = 0; return tmpl.arg(++count); } auto citems = editorScene->getItems(); QSet ids; for (const auto &citem : citems) ids << citem->getId(); int count = 0; QString newId; do newId = tmpl.arg(++count); while (ids.contains(newId)); return newId; }; #endif // CITEM_H qvge-0.6.3/src/qvge/CNode.cpp000066400000000000000000000440731405165517400157270ustar00rootroot00000000000000#include "CNode.h" #include "CEdge.h" #include "CDirectEdge.h" #include #include #include #include #include #include // test #include //////////////////////////////////////////////////////////////////// /// \brief CNode::CNode CNode::CNode(QGraphicsItem* parent) : QGraphicsRectItem(parent) { // no selection frame setItemFlag(IF_FramelessSelection); // default size resize(9); // default node flags m_nodeFlags = NF_OrphanAllowed; // default flags: movable & selectable auto flags = ItemIsMovable | ItemIsSelectable | ItemSendsGeometryChanges | ItemUsesExtendedStyleOption; setFlags(flags); // accept hovers setAcceptHoverEvents(true); //setFiltersChildEvents(true); // cache setCacheMode(DeviceCoordinateCache); // label m_labelItem = new QGraphicsSimpleTextItem(this); m_labelItem->setFlags(0); m_labelItem->setCacheMode(DeviceCoordinateCache); m_labelItem->setPen(Qt::NoPen); m_labelItem->setAcceptedMouseButtons(Qt::NoButton); m_labelItem->setAcceptHoverEvents(false); } CNode::~CNode() { for (CNodePort *port : m_ports) { port->onParentDeleted(); } for (CEdge *conn : m_connections) { conn->onNodeDeleted(this); } } // reimp QString CNode::createNewId() const { static const QString tmpl("N%1"); return createUniqueId(tmpl); } void CNode::copyDataFrom(CItem* from) { Super::copyDataFrom(from); CNode* fromNode = dynamic_cast(from); if (fromNode) { // shape & position resize(fromNode->getSize()); setPos(fromNode->pos()); setZValue(fromNode->zValue()); // ports qDeleteAll(m_ports); m_ports.clear(); for (auto it = fromNode->m_ports.begin(); it != fromNode->m_ports.end(); ++it) { CNodePort* port = new CNodePort(this); port->copyDataFrom(**it); m_ports[it.key()] = port; } updatePortsLayout(); } updateCachedItems(); } CItem* CNode::clone() { CItem *item = create(); CNode *node = dynamic_cast(item); if (scene()) scene()->addItem(node); node->copyDataFrom(this); return item; } // transformations void CNode::transform( const QRectF &oldRect, const QRectF &newRect, double xc, double yc, bool changeSize, bool changePos) { double w = getSize().width(); double h = getSize().height(); double wc = w; double hc = h; if (changeSize) { wc = (w * xc); hc = (h * yc); setSize(wc, hc); } else { w = h = wc = hc = 0.0; } if (changePos) { double dx = x() - w / 2; double dy = y() - h / 2; double xp = (dx - oldRect.left()) * xc + newRect.left() + wc / 2; double yp = (dy - oldRect.top()) * yc + newRect.top() + hc / 2; setPos(xp, yp); } } // attributes void CNode::setSize(float w, float h) { setAttribute("size", QSizeF(w, h)); } bool CNode::hasLocalAttribute(const QByteArray& attrId) const { if (attrId == "width" || attrId == "height" || attrId == "pos" || attrId == "x" || attrId == "y" || attrId == "z") return true; return Super::hasLocalAttribute(attrId); } bool CNode::setAttribute(const QByteArray& attrId, const QVariant& v) { setItemStateFlag(IS_Attribute_Changed); update(); if (attrId == "shape") { Super::setAttribute(attrId, v); updateCachedItems(); return true; } // mapped attributes if (attrId == "size") { if (v.type() == QVariant::Size || v.type() == QVariant::SizeF) { QSizeF sp = v.toSizeF(); if (!sp.isNull()) { Super::setAttribute(attrId, sp); resize(sp); updateCachedItems(); return true; } return false; } float s = v.toFloat(); if (s > 0) { Super::setAttribute(attrId, QSizeF(s,s)); resize(s); updateCachedItems(); return true; } return false; } if (attrId == "width") { float s = v.toFloat(); QSizeF sf = getSize(); Super::setAttribute("size", QSizeF(s, sf.height())); resize(s, sf.height()); return true; } if (attrId == "height") { float s = v.toFloat(); QSizeF sf = getSize(); Super::setAttribute("size", QSizeF(sf.width(), s)); resize(sf.width(), s); return true; } if (attrId == "x") { setX(v.toDouble()); return true; } if (attrId == "y") { setY(v.toDouble()); return true; } if (attrId == "z") { setZValue(v.toDouble()); return true; } if (attrId == "pos") { setPos(v.toPointF()); return true; } return Super::setAttribute(attrId, v); } bool CNode::removeAttribute(const QByteArray& attrId) { if (Super::removeAttribute(attrId)) { updateCachedItems(); return true; } else return false; } QVariant CNode::getAttribute(const QByteArray& attrId) const { // mapped attributes if (attrId == "x") { return x(); } if (attrId == "y") { return y(); } if (attrId == "z") { return zValue(); } if (attrId == "pos") { return pos(); } // virtual attributes if (attrId == "degree") { return m_connections.size(); } return Super::getAttribute(attrId); } // ports CNodePort* CNode::addPort(const QByteArray& portId, int align, double xoff, double yoff) { if (m_ports.contains(portId)) return NULL; QByteArray newPortId(portId); if (portId.isEmpty()) { int suffix = 1; do { newPortId = "Port " + QByteArray::number(suffix++); } while (m_ports.contains(newPortId)); } CNodePort* port = new CNodePort(this, newPortId, align, xoff, yoff); m_ports[newPortId] = port; updateCachedItems(); return port; } bool CNode::removePort(const QByteArray& portId) { if (portId.isEmpty() || !m_ports.contains(portId)) return false; CNodePort* port = m_ports.take(portId); // to do. update edges. delete port; updateCachedItems(); return true; } bool CNode::movePort(const QByteArray& portId, int align, double xoff, double yoff) { if (!m_ports.contains(portId)) return false; CNodePort *port = m_ports[portId]; port->setAlign(align); port->setOffset(xoff, yoff); updatePortsLayout(); return true; } bool CNode::renamePort(const QByteArray& portId, const QByteArray& newId) { if (!m_ports.contains(portId)) return false; if (portId == newId) return true; if (!m_ports.contains(newId)) { CNodePort *port = m_ports[portId]; m_ports[newId] = port; m_ports.remove(portId); port->setId(newId); updateCachedItems(); return true; } // port exists: bail out for now... return false; } CNodePort* CNode::getPort(const QByteArray& portId) const { if (portId.isEmpty() || !m_ports.contains(portId)) return NULL; else return m_ports[portId]; } QByteArrayList CNode::getPortIds() const { return m_ports.keys(); } // serialization bool CNode::storeTo(QDataStream& out, quint64 version64) const { out << getSize(); out << pos() << itemFlags(); out << zValue(); // ports since v.11 int portsCount = m_ports.size(); out << portsCount; for (auto port: m_ports) port->storeTo(out, version64); return Super::storeTo(out, version64); } bool CNode::restoreFrom(QDataStream& out, quint64 version64) { if (version64 >= 7) { QSizeF size; out >> size; resize(size); } else if (version64 > 0) { float size; out >> size; resize(size); } static QPointF p; out >> p; setPos(p); static int f; out >> f; //setItemFlags(f); if (version64 > 0) { qreal z; out >> z; setZValue(z); } // ports m_ports.clear(); if (version64 >= 11) { int count = 0; out >> count; QByteArray id; int align; double xoff, yoff; for (int i = 0; i < count; ++i) { out >> id; out >> align >> xoff >> yoff; CNodePort *port = new CNodePort(this, id, align, xoff, yoff); m_ports[id] = port; if (version64 >= 12) { QBrush br; out >> br; port->setBrush(br); QPen pn; out >> pn; port->setPen(pn); QRectF r; out >> r; port->setRect(r); } // update port->onParentGeometryChanged(); } } return Super::restoreFrom(out, version64); } // node operations bool CNode::merge(CNode *node, const QByteArray& portId) { if (!node || (node == this)) return false; bool allowCircled = allowCircledConnection(); // make a copy because node's connections list will be updated QSet toReconnect = node->m_connections; for (CEdge *conn : toReconnect) { conn->reattach(node, this, portId); } // kill old node delete node; // will be removed by removed connections if (!allowCircled) { toReconnect = m_connections; for (CEdge *conn : toReconnect) { if (conn->isCircled()) delete conn; } } return true; } QList CNode::unlink() { QList nodes; float xpos = x(); float ypos = y(); float xstep = getScene() ? getScene()->getGridSize() : 10; while (m_connections.size() >= 2) { CEdge *c = *m_connections.begin(); CNode *n = dynamic_cast(clone()); xpos += xstep; n->setPos(xpos, ypos); c->reattach(this, n); nodes.append(n); } return nodes; } QList CNode::getCollidingNodes() const { QList nodes; CEditorScene* scene = getScene(); if (!scene) return nodes; QList itemsUnderMouse = scene->items(pos()); for (int i = 0; i < itemsUnderMouse.size(); ++i) { CNode *node = dynamic_cast(itemsUnderMouse.at(i)); if (!node || node == this) continue; nodes.append(node); } return nodes; } QSet CNode::getInConnections() const { QSet edges; for (auto edge: m_connections) { if (edge->lastNode() == this) edges << edge; } return edges; } QSet CNode::getOutConnections() const { QSet edges; for (auto edge: m_connections) { if (edge->firstNode() == this) edges << edge; } return edges; } QPointF CNode::getIntersectionPoint(const QLineF& line, const QByteArray& portId) const { // port if (portId.size()) { if (CNodePort* port = getPort(portId)) { double shift = (port->boundingRect().width() / 2); auto angle = qDegreesToRadians(line.angle()); return port->scenePos() + QPointF(shift * qCos(angle), - shift * qSin(angle)); } } // circular shape if (m_shapeCache.isEmpty()) { // circle/ring if (rect().height() == rect().width()) { auto shift = rect().width() / 2; auto angle = qDegreesToRadians(line.angle()); return pos() + QPointF(shift * qCos(angle), -shift * qSin(angle)); } // ellipse { QRectF r(rect()); r.moveCenter(pos()); QPolygonF p(r); return CUtils::closestIntersection(line, p); } } // polygon (must be cashed) QPolygonF scenePolygon = m_shapeCache.translated(pos()); return CUtils::closestIntersection(line, scenePolygon); } /// /// \brief CNode::onConnectionAttach /// \param conn /// void CNode::onConnectionAttach(CEdge *conn) { Q_ASSERT(conn != NULL); m_connections.insert(conn); updateConnections(); } /// /// \brief CNode::onConnectionDetach /// \param conn /// void CNode::onConnectionDetach(CEdge *conn) { Q_ASSERT(conn != NULL); m_connections.remove(conn); updateConnections(); } void CNode::updateConnections() { // optimize: no update while restoring if (s_duringRestore) return; typedef QList EdgeList; typedef QSet> Key; QHash edgeGroups; for (auto conn : m_connections) { CDirectEdge* dconn = dynamic_cast(conn); if (dconn) { QPair key1 = { dconn->firstNode(), dconn->firstPortId() }; QPair key2 = { dconn->lastNode(), dconn->lastPortId() }; Key key = { key1, key2 }; edgeGroups[key].append(dconn); } } for (const EdgeList& values: edgeGroups) { if (values.count() == 1) { values.first()->setBendFactor(0); } else { if (values.first()->isCircled()) { int bf = 0; for (auto conn : values) { conn->setBendFactor(bf++); } } else { int bf = (values.count() & 1) ? 0 : 1; for (auto conn : values) { conn->setBendFactor(bf); if (bf > 0) bf = 0 - bf; else bf = 1 - bf; } } } } } void CNode::onConnectionDeleted(CEdge *conn) { onConnectionDetach(conn); // remove orphan node if allowed if (m_connections.isEmpty() && !(m_nodeFlags & NF_OrphanAllowed)) delete this; } void CNode::onPortDeleted(CNodePort *port) { for (auto edge : m_connections) { edge->onNodePortDeleted(this, port->getId()); } m_ports.remove(port->getId()); } void CNode::onPortRenamed(CNodePort *port, const QByteArray& oldId) { for (auto edge : m_connections) { edge->onNodePortRenamed(this, port->getId(), oldId); } } void CNode::onItemMoved(const QPointF& /*delta*/) { for (CEdge *conn : m_connections) { conn->onNodeMoved(this); } } void CNode::onItemRestored() { updateCachedItems(); updateConnections(); } void CNode::onDroppedOn(const QSet& acceptedItems, const QSet& /*rejectedItems*/) { if (acceptedItems.size()) { // check for ports for (auto item : acceptedItems) { CNodePort* port = dynamic_cast(item); if (port) { CNode* node = port->getNode(); node->merge(this, port->getId()); node->setSelected(true); return; } } // check for nodes for (auto item : acceptedItems) { CNode* node = dynamic_cast(item); if (node) { node->merge(this); node->setSelected(true); return; } } // nothing... } } ItemDragTestResult CNode::acceptDragFromItem(QGraphicsItem* draggedItem) { if (dynamic_cast(draggedItem)) return Accepted; else return Ignored; } // reimp QVariant CNode::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { if (change == ItemSceneHasChanged) { // set default ID setDefaultId(); // update attributes cache after attach to scene updateCachedItems(); return value; } if (change == ItemPositionHasChanged) { setItemStateFlag(IS_Attribute_Changed); QPointF d = value.toPointF() - scenePos(); onItemMoved(d); return value; } if (change == ItemSelectedHasChanged) { onItemSelected(value.toBool()); return value; } return value; } void CNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget*) { bool isSelected = (option->state & QStyle::State_Selected); painter->setClipRect(boundingRect()); // get color (to optimize!) QColor color = getAttribute(QByteArrayLiteral("color")).value(); if (color.isValid()) painter->setBrush(color); else painter->setBrush(Qt::NoBrush); qreal strokeSize = getAttribute(QByteArrayLiteral("stroke.size")).toDouble(); strokeSize = qMax(0.1, strokeSize); QColor strokeColor = getAttribute(QByteArrayLiteral("stroke.color")).value(); int strokeStyle = CUtils::textToPenStyle(getAttribute(QByteArrayLiteral("stroke.style")).toString(), Qt::SolidLine); // selection background outline if (isSelected) { painter->setPen(QPen(Qt::darkCyan, strokeSize+5, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin)); painter->setOpacity(0.3); // draw shape: disc if no cache if (m_shapeCache.isEmpty()) { QRectF r = Shape::boundingRect(); painter->drawEllipse(r); } else { painter->drawPolygon(m_shapeCache); } } // hover opacity if (itemStateFlags() & IS_Drag_Accepted) painter->setOpacity(0.6); else painter->setOpacity(1.0); painter->setPen(QPen(strokeColor, strokeSize, (Qt::PenStyle)strokeStyle)); // draw shape: disc if no cache if (m_shapeCache.isEmpty()) { QRectF r = Shape::boundingRect(); painter->drawEllipse(r); } else { painter->drawPolygon(m_shapeCache); } } QRectF CNode::boundingRect() const { QRectF r = Shape::boundingRect(); // in case of bold selection if (auto scene = getScene()) { const int margin = scene->getBoundingMargin(); return r.adjusted(-margin, -margin, margin, margin); } else return r; } void CNode::updateCachedItems() { Super::updateCachedItems(); auto shapeCache = m_shapeCache; auto sizeCache = m_sizeCache; recalculateShape(); // update caches & connections if (m_shapeCache != shapeCache || m_sizeCache != sizeCache) { // update ports & edges updatePortsLayout(); } update(); } void CNode::updatePortsLayout() { prepareGeometryChange(); // update ports layout for (auto port : m_ports.values()) { port->onParentGeometryChanged(); } // update edges as well for (auto edge : m_connections) { edge->onParentGeometryChanged(); } } void CNode::updateLabelPosition() { int w = m_labelItem->boundingRect().width(); int h = m_labelItem->boundingRect().height(); QRectF r = Shape::boundingRect(); if (r.width() < 16 || r.height() < 16) m_labelItem->setPos(-w / 2, boundingRect().height() / 2); // if too small: put label at the bottom else m_labelItem->setPos(-w / 2, -h / 2); // else center } // priv void CNode::recalculateShape() { QSizeF sz = getAttribute("size").toSizeF(); resize(sz); QRectF r = Shape::boundingRect(); m_shapeCache.clear(); m_sizeCache = r; QByteArray shapeType = getAttribute("shape").toByteArray(); if (shapeType == "square") { m_shapeCache = r; } else if (shapeType == "diamond") { float rx = r.center().x(); float ry = r.center().y(); m_shapeCache << QPointF(rx, ry - r.height() / 2) << QPointF(rx + r.width() / 2, ry) << QPointF(rx, ry + r.height() / 2) << QPointF(rx - r.width() / 2, ry) << QPointF(rx, ry - r.height() / 2); } else if (shapeType == "hexagon") { float rx = r.center().x(); float ry = r.center().y(); m_shapeCache << QPointF(r.left() + r.width() / 3, ry - r.height() / 2) << QPointF(r.left() + r.width() / 3 * 2, ry - r.height() / 2) << QPointF(rx + r.width() / 2, ry) << QPointF(r.left() + r.width() / 3 * 2, ry + r.height() / 2) << QPointF(r.left() + r.width() / 3, ry + r.height() / 2) << QPointF(r.left(), ry) << QPointF(r.left() + r.width() / 3, ry - r.height() / 2); } else if (shapeType == "triangle") { m_shapeCache << r.bottomLeft() << r.bottomRight() << QPointF(r.topRight() + r.topLeft()) / 2 << r.bottomLeft(); } else if (shapeType == "triangle2") { m_shapeCache << r.topLeft() << r.topRight() << QPointF(r.bottomRight() + r.bottomLeft()) / 2 << r.topLeft(); } else // "disc" { // no cache } } // events void CNode::hoverEnterEvent(QGraphicsSceneHoverEvent* event) { m_internalStateFlags |= IS_Hover; onHoverEnter(this, event); update(); } void CNode::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) { m_internalStateFlags &= ~IS_Hover; onHoverLeave(this, event); update(); } qvge-0.6.3/src/qvge/CNode.h000066400000000000000000000116211405165517400153650ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CNODE_H #define CNODE_H #include "CItem.h" #include "CNodePort.h" #include #include #include class CEdge; enum NodeFlags { NF_OrphanAllowed = 1 // allow node to have no connections }; class CNode : public CItem, public QGraphicsRectItem { public: typedef CItem Super; typedef QGraphicsRectItem Shape; CNode(QGraphicsItem* parent = NULL); virtual ~CNode(); static QByteArray factoryId() { return "CNode"; } virtual QByteArray typeId() const { return this->factoryId(); } virtual QString createNewId() const; int nodeFlags() const { return m_nodeFlags; } void setNodeFlags(int f) { m_nodeFlags = f; } void setNodeFlag(int f) { m_nodeFlags |= f; } void resetNodeFlag(int f) { m_nodeFlags &= ~f; } // reimp virtual CItem* create() const { return new CNode(parentItem()); } virtual CItem* clone(); virtual void copyDataFrom(CItem* from); // transformations virtual void transform(const QRectF& oldRect, const QRectF& newRect, double xc, double yc, bool changeSize, bool changePos) override; // attributes virtual QSizeF getSize() const { return rect().size(); } virtual void setSize(float w, float h); virtual bool hasLocalAttribute(const QByteArray& attrId) const; virtual bool setAttribute(const QByteArray& attrId, const QVariant& v); virtual bool removeAttribute(const QByteArray& attrId); virtual QVariant getAttribute(const QByteArray& attrId) const; virtual QByteArray classId() const { return "node"; } virtual QByteArray superClassId() const { return Super::classId(); } // ports CNodePort* addPort(const QByteArray& portId = "", int align = Qt::AlignCenter, double xoff = 0, double yoff = 0); bool removePort(const QByteArray& portId); bool movePort(const QByteArray& portId, int align = Qt::AlignCenter, double xoff = 0, double yoff = 0); bool renamePort(const QByteArray& portId, const QByteArray& newId); CNodePort* getPort(const QByteArray& portId) const; QByteArrayList getPortIds() const; // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; virtual bool restoreFrom(QDataStream& out, quint64 version64); // merges node with the current one. // node will be deleted afterwards if no circled connection allowed. virtual bool merge(CNode *node, const QByteArray& portId = ""); // splits all the connections from this node. // result is the list of the newly created nodes (or empty list if connections < 2). virtual QList unlink(); // returns all nodes colliding with this one. QList getCollidingNodes() const; // returns all connections of the node. QSet getConnections() const { return m_connections; } // returns all incoming connections of the node. QSet getInConnections() const; // returns all outgoing connections of the node. QSet getOutConnections() const; // returns true if new connection from this node is allowed. virtual bool allowStartConnection() const { return true; } // returns true if a connection from this node to itself is allowed. virtual bool allowCircledConnection() const { return true; } // calculates point on the node's outline intersecting with line. virtual QPointF getIntersectionPoint(const QLineF& line, const QByteArray& portId) const; // callbacks virtual void onConnectionAttach(CEdge *conn); virtual void onConnectionDetach(CEdge *conn); virtual void onConnectionDeleted(CEdge *conn); virtual void onPortDeleted(CNodePort *port); virtual void onPortRenamed(CNodePort *port, const QByteArray& oldId); virtual void onItemMoved(const QPointF& delta); virtual void onItemRestored(); virtual void onDroppedOn(const QSet& acceptedItems, const QSet& rejectedItems); virtual ItemDragTestResult acceptDragFromItem(QGraphicsItem* draggedItem); // reimp virtual QRectF boundingRect() const; protected: // reimp virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR); virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); virtual void updatePortsLayout(); virtual void updateLabelPosition(); virtual void updateCachedItems(); private: void recalculateShape(); void updateConnections(); void resize(float size) { setRect(-size / 2, -size / 2, size, size); } void resize(float w, float h) { setRect(-w / 2, -h / 2, w, h); } void resize(const QSizeF& size) { resize(size.width(), size.height()); } protected: QSet m_connections; int m_nodeFlags = 0; QMap m_ports; QPolygonF m_shapeCache; QRectF m_sizeCache; }; #endif // CNODE_H qvge-0.6.3/src/qvge/CNodeEditorScene.cpp000066400000000000000000000566551405165517400200650ustar00rootroot00000000000000#include "CNodeEditorScene.h" #include "CNodeSceneActions.h" #include "CNode.h" #include "CNodePort.h" #include "CEdge.h" #include "CDirectEdge.h" #include "CPolyEdge.h" #include "CControlPoint.h" #include "CEditorSceneDefines.h" #include "CEditorScene_p.h" #include #include #include #include #include #include #include #include CNodeEditorScene::CNodeEditorScene(QObject *parent) : Super(parent), m_editMode(EM_Default), m_startNode(NULL), m_endNode(NULL), m_connection(NULL), m_realStart(false), m_state(IS_None) { // default factories registerItemFactory(); registerItemFactory(); registerItemFactory(); m_nodesFactory = factory(); m_edgesFactory = factory(); // go initialize(); } bool CNodeEditorScene::fromGraph(const Graph& g) { reset(); // Graph attrs for (const auto& attr : g.graphAttrs) { if (attr.id == attr_labels_visIds) { auto graphVis = CUtils::visFromString(attr.defaultValue.toString()); setVisibleClassAttributes("", graphVis); continue; } createClassAttribute("", attr.id, attr.name, attr.defaultValue, ATTR_NONE); } for (auto it = g.attrs.constBegin(); it != g.attrs.constEnd(); ++it) { if (it.key() == attr_labels_visIds) continue; setClassAttribute("", it.key(), it.value()); } // Class attrs for (const auto& attr : g.nodeAttrs) { if (attr.id == attr_labels_visIds) { auto nodeVis = CUtils::visFromString(attr.defaultValue.toString()); setVisibleClassAttributes("node", nodeVis); continue; } if (attr.id == attr_size) continue; // ignore for now createClassAttribute("node", attr.id, attr.name, attr.defaultValue, ATTR_NONE); } for (const auto& attr : g.edgeAttrs) { if (attr.id == attr_labels_visIds) { auto edgeVis = CUtils::visFromString(attr.defaultValue.toString()); setVisibleClassAttributes("edge", edgeVis); continue; } createClassAttribute("edge", attr.id, attr.name, attr.defaultValue, ATTR_NONE); } // Nodes QMap nodesMap; for (const Node& n : g.nodes) { CNode* node = createNewNode(); addItem(node); node->setId(n.id); nodesMap[n.id] = node; for (auto it = n.attrs.constBegin(); it != n.attrs.constEnd(); ++it) { node->setAttribute(it.key(), it.value()); } for (auto it = n.ports.constBegin(); it != n.ports.constEnd(); ++it) { CNodePort* port = node->addPort(it.key().toLatin1(), it.value().anchor, it.value().x, it.value().y); Q_ASSERT(port != nullptr); port->setColor(it.value().color); } } // Edges for (const Edge& e : g.edges) { bool isPolyEdge = e.attrs.contains("points"); CPolyEdge* polyEdge = isPolyEdge ? new CPolyEdge : nullptr; if (polyEdge) { QString pointStr = e.attrs["points"].toString(); polyEdge->setPoints(CUtils::pointsFromString(pointStr)); } CEdge* edge = polyEdge ? polyEdge : new CDirectEdge; addItem(edge); edge->setId(e.id); edge->setFirstNode(nodesMap[e.startNodeId], e.startPortId); edge->setLastNode(nodesMap[e.endNodeId], e.endPortId); for (auto it = e.attrs.constBegin(); it != e.attrs.constEnd(); ++it) { edge->setAttribute(it.key(), it.value()); } } // finalize setSceneRect(itemsBoundingRect()); addUndoState(); return true; } bool CNodeEditorScene::toGraph(Graph& g) { g.clear(); // class attributes auto graphAttrs = getClassAttributes("", false); for (auto it = graphAttrs.constBegin(); it != graphAttrs.constEnd(); ++it) { const auto& attr = *it; if (attr.flags & ATTR_VIRTUAL) continue; g.graphAttrs[it.key()] = attr; } auto nodeAttrs = getClassAttributes("node", false); for (auto it = nodeAttrs.constBegin(); it != nodeAttrs.constEnd(); ++it) { const auto& attr = *it; if (attr.flags & ATTR_VIRTUAL) continue; g.nodeAttrs[it.key()] = attr; } auto edgeAttrs = getClassAttributes("edge", false); for (auto it = edgeAttrs.constBegin(); it != edgeAttrs.constEnd(); ++it) { const auto& attr = *it; if (attr.flags & ATTR_VIRTUAL) continue; g.edgeAttrs[it.key()] = attr; } // temp solution g.nodeAttrs.remove("size"); g.nodeAttrs.remove("pos"); // visibility static AttrInfo _vis_({ attr_labels_visIds , "Visible Labels", QVariant::StringList}); auto nodeVis = getVisibleClassAttributes("node", false); if (nodeVis.size()) { _vis_.defaultValue = CUtils::byteArraySetToStringList(nodeVis); g.nodeAttrs[attr_labels_visIds] = _vis_; } auto edgeVis = getVisibleClassAttributes("edge", false); if (edgeVis.size()) { _vis_.defaultValue = CUtils::byteArraySetToStringList(edgeVis); g.edgeAttrs[attr_labels_visIds] = _vis_; } auto graphVis = getVisibleClassAttributes("", false); if (graphVis.size()) { _vis_.defaultValue = CUtils::byteArraySetToStringList(graphVis); g.graphAttrs[attr_labels_visIds] = _vis_; } // nodes auto nodes = getItems(); for (const auto &node : nodes) { Node n; n.id = node->getId().toLatin1(); QByteArrayList ports = node->getPortIds(); for (const auto &portId : ports) { auto port = node->getPort(portId); Q_ASSERT(port != NULL); NodePort p; p.name = portId; p.anchor = port->getAlign(); p.x = port->getX(); p.y = port->getY(); p.color = port->getColor(); n.ports[portId] = p; } n.attrs = node->getLocalAttributes(); // temp solution n.attrs["x"] = node->pos().x(); n.attrs["y"] = node->pos().y(); n.attrs.remove("pos"); n.attrs["width"] = node->getSize().width(); n.attrs["height"] = node->getSize().height(); n.attrs.remove("size"); g.nodes.append(n); } // edges auto edges = getItems(); for (const auto &edge : edges) { Edge e; e.id = edge->getId().toLatin1(); e.startNodeId = edge->firstNode()->getId().toLatin1(); e.endNodeId = edge->lastNode()->getId().toLatin1(); e.startPortId = edge->firstPortId(); e.endPortId = edge->lastPortId(); e.attrs = edge->getLocalAttributes(); // polypoints auto polyEdge = dynamic_cast(edge); if (polyEdge) { const QList& points = polyEdge->getPoints(); if (points.size()) e.attrs["points"] = CUtils::pointsToString(points); } g.edges.append(e); } // TODO return true; } // reimp void CNodeEditorScene::initialize() { Super::initialize(); // common constrains static CAttributeConstrainsList *edgeStyles = new CAttributeConstrainsList(); if (edgeStyles->ids.isEmpty()) { edgeStyles->names << tr("None") << tr("Solid") << tr("Dots") << tr("Dashes") << tr("Dash-Dot") << tr("Dash-Dot-Dot"); edgeStyles->ids << "none" << "solid" << "dotted" << "dashed" << "dashdot" << "dashdotdot"; } // default node attr CAttribute nodeAttr("color", "Color", QColor(Qt::magenta), ATTR_FIXED); setClassAttribute("node", nodeAttr); CAttribute shapeAttr("shape", "Shape", "disc", ATTR_FIXED); setClassAttribute("node", shapeAttr); createClassAttribute("node", "size", "Size", QSizeF(11.0, 11.0), ATTR_MAPPED | ATTR_FIXED); //createClassAttribute("node", "width", "Width", 11.0f, ATTR_MAPPED); //createClassAttribute("node", "height", "Height", 11.0f, ATTR_MAPPED); //createClassAttribute("node", "pos", "Position", QPointF(), ATTR_NODEFAULT | ATTR_MAPPED); createClassAttribute("node", "x", "X-Coordinate", 0.0f, ATTR_NODEFAULT | ATTR_MAPPED | ATTR_FIXED); createClassAttribute("node", "y", "Y-Coordinate", 0.0f, ATTR_NODEFAULT | ATTR_MAPPED | ATTR_FIXED); createClassAttribute("node", "stroke.style", "Stroke Style", "solid", ATTR_FIXED, edgeStyles); createClassAttribute("node", "stroke.size", "Stroke Size", 1.0, ATTR_FIXED); createClassAttribute("node", "stroke.color", "Stroke Color", QColor(Qt::black), ATTR_FIXED); createClassAttribute("node", "degree", "Degree", 0, ATTR_NODEFAULT | ATTR_VIRTUAL | ATTR_FIXED); // default edge attr CAttribute edgeAttr("color", "Color", QColor(Qt::gray), ATTR_FIXED); setClassAttribute("edge", edgeAttr); CAttribute directionAttr("direction", "Direction", "directed", ATTR_FIXED); setClassAttribute("edge", directionAttr); CAttribute weightAttr("weight", "Weight", 1.0, ATTR_FIXED); setClassAttribute("edge", weightAttr); CAttribute styleAttr("style", "Style", "solid", ATTR_FIXED); setClassAttribute("edge", styleAttr); createClassAttribute("edge", "points", "Polyline Points", "", ATTR_NODEFAULT | ATTR_MAPPED | ATTR_FIXED); static CAttributeConstrainsList *edgeDirections = new CAttributeConstrainsList(); if (edgeDirections->ids.isEmpty()) { edgeDirections->names << tr("Directed (one end)") << tr("Mutual (both ends)") << tr("None (no ends)"); edgeDirections->ids << "directed" << "mutual" << "undirected"; edgeDirections->icons << QIcon(":/Icons/Edge-Directed") << QIcon(":/Icons/Edge-Mutual") << QIcon(":/Icons/Edge-Undirected"); } setClassAttributeConstrains("edge", "direction", edgeDirections); setClassAttributeConstrains("edge", "style", edgeStyles); static CAttributeConstrainsList *nodeShapes = new CAttributeConstrainsList(); if (nodeShapes->ids.isEmpty()) { nodeShapes->names << tr("Disc") << tr("Square") << tr("Triangle (up)") << tr("Triangle (down)") << tr("Diamond") << tr("Hexagon"); nodeShapes->ids << "disc" << "square" << "triangle" << "triangle2" << "diamond" << "hexagon"; nodeShapes->icons << QIcon(":/Icons/Node-Disc") << QIcon(":/Icons/Node-Square") << QIcon(":/Icons/Node-Triangle") << QIcon(":/Icons/Node-Triangle-Down") << QIcon(":/Icons/Node-Diamond") << QIcon(":/Icons/Node-Hexagon"); } setClassAttributeConstrains("node", "shape", nodeShapes); } // nodes creation void CNodeEditorScene::setEditMode(EditMode mode) { if (m_editMode != mode) { m_editMode = mode; switch (m_editMode) { case EM_Transform: getCurrentView()->setDragMode(QGraphicsView::RubberBandDrag); startTransform(true, false); break; case EM_Factor: getCurrentView()->setDragMode(QGraphicsView::RubberBandDrag); startTransform(true, true); break; case EM_AddNodes: getCurrentView()->setDragMode(QGraphicsView::NoDrag); startTransform(false); break; default: getCurrentView()->setDragMode(QGraphicsView::RubberBandDrag); startTransform(false); break; } Q_EMIT editModeChanged(m_editMode); } } bool CNodeEditorScene::startNewConnection(const QPointF& pos) { if (m_editMode == EM_Transform) return false; if (m_editMode == EM_Factor) return false; if (QGraphicsItem* item = getItemAt(pos)) { if (!item->isEnabled()) return false; // check for port first CNodePort *port = dynamic_cast(item); if (port) { CNode *node = port->getNode(); Q_ASSERT(node != NULL); if (!node->allowStartConnection()) return false; m_realStart = false; m_startNode = node; m_startNodePort = port; } else { // check for node CNode *node = dynamic_cast(item); if (!node) return false; if (!node->allowStartConnection()) return false; m_realStart = false; m_startNode = node; m_startNodePort = NULL; } } else { m_realStart = true; m_startNode = createNewNode(getSnapped(pos)); m_startNodePort = NULL; } m_endNode = createNewNode(getSnapped(pos)); Super::startDrag(m_endNode); m_connection = createNewConnection(m_startNode, m_endNode); if (m_startNodePort) m_connection->setFirstNode(m_startNode, m_startNodePort->getId()); m_state = IS_Creating; // auto select created items m_startNode->setSelected(false); m_connection->setSelected(true); m_endNode->setSelected(true); return true; } void CNodeEditorScene::cancel(const QPointF& /*pos*/) { // nothing to cancel if (m_state == IS_None) return; // if not cancelling already if (m_state != IS_Cancelling) { // cancel current drag operation Super::finishDrag(NULL, m_startDragItem, true); } m_state = IS_None; // if no creating state: return if (m_connection == NULL) return; // kill connector m_connection->setFirstNode(NULL); m_connection->setLastNode(NULL); delete m_connection; m_connection = NULL; // kill end delete m_endNode; m_endNode = NULL; // kill start if real if (m_realStart) delete m_startNode; m_startNode = NULL; m_realStart = false; } CNode* CNodeEditorScene::createNewNode() const { if (m_nodesFactory) { auto node = dynamic_cast(m_nodesFactory->create()); Q_ASSERT(node); node->copyDataFrom(m_nodesFactory); return node; } // here default return new CNode; } CNode* CNodeEditorScene::createNewNode(const QPointF& pos) { auto node = createNewNode(); addItem(node); node->setPos(pos); return node; } CEdge* CNodeEditorScene::createNewConnection() const { if (m_edgesFactory) { auto edge = dynamic_cast(m_edgesFactory->create()); Q_ASSERT(edge); edge->copyDataFrom(m_edgesFactory); return edge; } // here default return new CDirectEdge(); } CEdge* CNodeEditorScene::createNewConnection(CNode* startNode, CNode* endNode) { auto edge = createNewConnection(); addItem(edge); edge->setFirstNode(startNode); edge->setLastNode(endNode); return edge; } void CNodeEditorScene::setNodesFactory(CNode* nodeFactory) { m_nodesFactory = nodeFactory; } void CNodeEditorScene::setEdgesFactory(CEdge* edgeFactory) { m_edgesFactory = edgeFactory; } // events void CNodeEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) { if (m_cancelled) { // call super Super::mouseReleaseEvent(mouseEvent); return; } if (m_editItem) { // call super Super::mouseReleaseEvent(mouseEvent); return; } if (m_startDragItem == NULL) { // call super Super::mouseReleaseEvent(mouseEvent); return; } else // cancel on RMB if (mouseEvent->button() == Qt::RightButton) { m_state = IS_Cancelling; m_skipMenuEvent = true; } // release local grabber if any if (m_state == IS_Creating) { m_state = IS_Finishing; // cancel on RMB if (mouseEvent->button() == Qt::RightButton) { m_state = IS_Cancelling; m_skipMenuEvent = true; } // cancel on same position if (m_startNode->pos() == m_endNode->pos()) { m_state = IS_Cancelling; } } // finish or cancel drag finishDrag(mouseEvent, m_startDragItem, m_state == IS_Cancelling); // finalize if (m_state == IS_Cancelling) { cancel(mouseEvent->scenePos()); } m_state = IS_None; // necessary to handle scene events properly QGraphicsScene::mouseReleaseEvent(mouseEvent); updateCursorState(); } void CNodeEditorScene::keyReleaseEvent(QKeyEvent *keyEvent) { // forward scene events if in text editor mode if (m_editItem) { bool done = m_pimpl->m_labelEditor.onKeyReleased(*this, keyEvent); if (done) updateCursorState(); return; } Super::keyReleaseEvent(keyEvent); } void CNodeEditorScene::keyPressEvent(QKeyEvent *keyEvent) { // forward scene events if in text editor mode if (m_editItem) { m_pimpl->m_labelEditor.onKeyPressed(*this, keyEvent); return; } bool isCtrl = (keyEvent->modifiers() == Qt::ControlModifier); // bool isAlt = (keyEvent->modifiers() == Qt::AltModifier); // bool isShift = (keyEvent->modifiers() == Qt::ShiftModifier); // Ctrl+Up/Down; alter node size by 10% if (keyEvent->key() == Qt::Key_Up && isCtrl) { auto &nodes = getSelectedNodes(); if (nodes.isEmpty()) { keyEvent->accept(); return; } for (auto &node : nodes) { node->setAttribute(attr_size, node->getSize() * 1.1); } addUndoState(); keyEvent->accept(); return; } if (keyEvent->key() == Qt::Key_Down && isCtrl) { auto &nodes = getSelectedNodes(); if (nodes.isEmpty()) { keyEvent->accept(); return; } for (auto &node : nodes) { node->setAttribute(attr_size, node->getSize() / 1.1); } addUndoState(); keyEvent->accept(); return; } // Ctrl+Left/Right; alter edge weight by 10% if (keyEvent->key() == Qt::Key_Right && isCtrl) { auto &edges = getSelectedEdges(); if (edges.isEmpty()) { keyEvent->accept(); return; } for (auto &edge : edges) { edge->setAttribute(attr_weight, edge->getWeight() * 1.1); } addUndoState(); keyEvent->accept(); return; } if (keyEvent->key() == Qt::Key_Left && isCtrl) { auto &edges = getSelectedEdges(); if (edges.isEmpty()) { keyEvent->accept(); return; } for (auto &edge : edges) { edge->setAttribute(attr_weight, edge->getWeight() / 1.1); } addUndoState(); keyEvent->accept(); return; } // cancel label edit if (keyEvent->key() == Qt::Key_Escape) { cancel(); return; } Super::keyPressEvent(keyEvent); } // handlers void CNodeEditorScene::onLeftButtonPressed(QGraphicsSceneMouseEvent *mouseEvent) { Super::onLeftButtonPressed(mouseEvent); // add nodes? if (m_editMode == EM_AddNodes || isItemAt(mouseEvent->scenePos())) { deselectAll(); // skip calling super to avoid auto selection mouseEvent->accept(); } } bool CNodeEditorScene::onClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos) { // add nodes? if ((m_editMode == EM_AddNodes) || isItemAt(clickPos)) { if (startNewConnection(clickPos)) { //setEditMode(EM_Default); return true; } } // else super return Super::onClickDrag(mouseEvent, clickPos); } bool CNodeEditorScene::onDoubleClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos) { // debug if (clickPos == QPointF()) qDebug() << "bug"; // try to start new connection at click point if (startNewConnection(clickPos)) { //mouseEvent->accept(); return true; } // else call super return Super::onDoubleClickDrag(mouseEvent, clickPos); } void CNodeEditorScene::onDropped(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* dragItem) { CNode *dragNode = dynamic_cast(dragItem); CEdge *dragEdge = dynamic_cast(dragItem); // perform snap auto keys = mouseEvent->modifiers(); bool isSnap = (keys & Qt::AltModifier) ? !gridSnapEnabled() : gridSnapEnabled(); if (isSnap) { // control point: if (auto cp = dynamic_cast(dragItem)) { auto newPos = getSnapped(cp->scenePos()); cp->setPos(newPos); return; } // nodes & edges: QSet items; QSet edges; if (dragEdge) { edges << dragEdge; dragNode = dragEdge->firstNode(); } if (dragNode) { items << dragNode; auto newPos = getSnapped(dragNode->scenePos()); auto d = newPos - dragNode->scenePos(); for (auto item : selectedItems()) { if (auto edge = dynamic_cast(item)) { edges << edge; if (dragEdge) { items << edge->firstNode(); items << edge->lastNode(); } } else items << item; } for (auto item : items) item->moveBy(d.x(), d.y()); for (auto edge : edges) edge->onItemMoved(d); return; } // whatever: } Super::onDropped(mouseEvent, dragItem); } void CNodeEditorScene::onLeftClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem) { if (m_editMode == EM_AddNodes) { // clicked on empty space? if (!clickedItem) { onLeftDoubleClick(mouseEvent, clickedItem); //setEditMode(EM_Default); return; } } Super::onLeftClick(mouseEvent, clickedItem); } void CNodeEditorScene::onLeftDoubleClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem) { // clicked on empty space? if (!clickedItem) { // create a node here auto node = createNewNode(getSnapped(mouseEvent->scenePos())); node->setSelected(true); addUndoState(); return; } Super::onLeftDoubleClick(mouseEvent, clickedItem); } // movement void CNodeEditorScene::moveSelectedEdgesBy(const QPointF& d) { auto edges = getSelectedEdges(); if (edges.size()) { QSet unselNodes; // not selected nodes // move selected edges for (auto edge : edges) { if (!edge->firstNode()->isSelected()) unselNodes << edge->firstNode(); if (!edge->lastNode()->isSelected()) unselNodes << edge->lastNode(); edge->onItemMoved(d); } // force move non selected nodes of the selected edges for (auto node : unselNodes) { node->moveBy(d.x(), d.y()); } } } // reimp void CNodeEditorScene::moveSelectedItemsBy(const QPointF& d, bool snapped) { QSet items; QSet edges; QGraphicsItem* focusItem = nullptr; // if dragging nodes and there are selected nodes: do not drag not-selected nodes auto dragNode = dynamic_cast(m_startDragItem); for (auto item : selectedItems()) { if (!(item->flags() & item->ItemIsMovable)) continue; if (!focusItem) focusItem = item; if (auto edge = dynamic_cast(item)) { edges << edge; if (!dragNode) { items << edge->firstNode(); items << edge->lastNode(); } } else items << item; } for (auto item : items) item->moveBy(d.x(), d.y()); if (snapped) for (auto item : items) item->setPos(getSnapped(item->pos())); for (auto edge : edges) edge->onItemMoved(d); if (focusItem) focusItem->ensureVisible(); } QList CNodeEditorScene::getCopyPasteItems() const { // only selected edges & their nodes QList result; QSet nodes; for (auto item: selectedItems()) { if (auto edge = dynamic_cast(item)) { result << edge; nodes << edge->firstNode(); nodes << edge->lastNode(); } else if (auto node = dynamic_cast(item)) { // orphaned nodes only if (node->nodeFlags() & NF_OrphanAllowed) nodes << node; } else result << item; } result << nodes.toList(); return result; } QList CNodeEditorScene::getTransformableItems() const { QList result; auto items = getSelectedItems(); for (auto item : items) result << item->getSceneItem(); return result; } bool CNodeEditorScene::doUpdateCursorState(Qt::KeyboardModifiers keys, Qt::MouseButtons buttons, QGraphicsItem *hoverItem) { // port? if (CNodePort *portItem = dynamic_cast(hoverItem)) { if (portItem->isEnabled()) { setSceneCursor(Qt::CrossCursor); setInfoStatus(SIS_Hover_Port); return true; } } // hover item? if (m_editMode == EM_AddNodes) { if (hoverItem) { if (hoverItem->isEnabled()) { setSceneCursor(Qt::CrossCursor); setInfoStatus(SIS_Hover); return true; } } } // handled by super? if (Super::doUpdateCursorState(keys, buttons, hoverItem)) return true; // still not handled return false; } // painting void CNodeEditorScene::drawBackground(QPainter *painter, const QRectF &r) { Super::drawBackground(painter, r); } // selections const QList& CNodeEditorScene::getSelectedNodes() const { if (m_selNodes.isEmpty()) prefetchSelection(); return m_selNodes; } const QList& CNodeEditorScene::getSelectedEdges() const { if (m_selEdges.isEmpty()) prefetchSelection(); return m_selEdges; } const QList& CNodeEditorScene::getSelectedNodesEdges() const { if (m_selItems.isEmpty()) prefetchSelection(); return m_selItems; } void CNodeEditorScene::onSelectionChanged() { // drop cached selections m_selNodes.clear(); m_selEdges.clear(); m_selItems.clear(); Super::onSelectionChanged(); } void CNodeEditorScene::prefetchSelection() const { m_selNodes.clear(); m_selEdges.clear(); m_selItems.clear(); auto selItems = selectedItems(); for (auto* item : selItems) { if (CNode* node = dynamic_cast(item)) { m_selNodes << node; m_selItems << node; continue; } if (CEdge* edge = dynamic_cast(item)) { m_selEdges << edge; m_selItems << edge; continue; } } } // menu & actions QObject* CNodeEditorScene::createActions() { return new CNodeSceneActions(this); } qvge-0.6.3/src/qvge/CNodeEditorScene.h000066400000000000000000000107231405165517400175140ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "CEditorScene.h" #include "CEdge.h" class CNode; //class CEdge; class CNodePort; class CNodeSceneActions; enum EditMode { EM_Default, EM_AddNodes, EM_AddEdges, EM_Transform, EM_Factor }; class CNodeEditorScene : public CEditorScene { Q_OBJECT public: typedef CEditorScene Super; CNodeEditorScene(QObject *parent = NULL); // reimp virtual CEditorScene* createScene() const { return new CNodeEditorScene(); } virtual void initialize(); virtual bool fromGraph(const Graph& g); virtual bool toGraph(Graph& g); // operations bool startNewConnection(const QPointF& pos); void cancel(const QPointF& pos = QPointF()); EditMode getEditMode() const { return m_editMode; } template CEdge* changeEdgeClass(CEdge* edge); // factorizations virtual CNode* createNewNode() const; CNode* createNewNode(const QPointF& pos); // calls createNewNode(), attaches to scene and sets pos virtual CEdge* createNewConnection() const; CEdge* createNewConnection(CNode* startNode, CNode* endNode); // calls createNewConnection(), attaches to scene and sets nodes void setNodesFactory(CNode* node); void setEdgesFactory(CEdge* node); CNode* getNodesFactory() { return m_nodesFactory; } CEdge* getEdgesFactory() { return m_edgesFactory; } // selections virtual void moveSelectedItemsBy(const QPointF& d, bool snapped = false); virtual int getBoundingMargin() const { return 5; } const QList& getSelectedNodes() const; const QList& getSelectedEdges() const; const QList& getSelectedNodesEdges() const; Q_SIGNALS: void editModeChanged(int mode); public Q_SLOTS: void setEditMode(EditMode mode); protected Q_SLOTS: virtual void onSelectionChanged(); protected: // selection void moveSelectedEdgesBy(const QPointF& d); void prefetchSelection() const; // scene events //virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void keyPressEvent(QKeyEvent *keyEvent); virtual void keyReleaseEvent(QKeyEvent *keyEvent); virtual void onLeftButtonPressed(QGraphicsSceneMouseEvent *mouseEvent); // called on drag after single click; returns true if handled virtual bool onClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos); // called on drag after double click; returns true if handled virtual bool onDoubleClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos); virtual void onDropped(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* dragItem); virtual void onLeftClick(QGraphicsSceneMouseEvent* mouseEvent, QGraphicsItem* clickedItem); virtual void onLeftDoubleClick(QGraphicsSceneMouseEvent* /*mouseEvent*/, QGraphicsItem* clickedItem); // reimp virtual QList getCopyPasteItems() const; virtual QList getTransformableItems() const; virtual bool doUpdateCursorState(Qt::KeyboardModifiers keys, Qt::MouseButtons buttons, QGraphicsItem *hoverItem); virtual QObject* createActions(); // draw virtual void drawBackground(QPainter *painter, const QRectF &); protected: // edit mode EditMode m_editMode; // creating CNode *m_startNode = nullptr, *m_endNode = nullptr; CEdge *m_connection = nullptr; bool m_realStart = false; CNodePort *m_startNodePort = nullptr, *m_endNodePort = nullptr; enum InternState { IS_None, IS_Creating, IS_Finishing, IS_Cancelling }; InternState m_state = IS_None; CNode *m_nodesFactory = nullptr; CEdge *m_edgesFactory = nullptr; // cached selections mutable QList m_selNodes; mutable QList m_selEdges; mutable QList m_selItems; // drawing int m_nextIndex = 0; }; // operations template inline CEdge* CNodeEditorScene::changeEdgeClass(CEdge* edge) { if (!edge) return NULL; // same class, dont change if (edge->factoryId() == E::factoryId()) return edge; // clone & kill original E* newEdge = new E; // assign nodes newEdge->setFirstNode(edge->firstNode(), edge->firstPortId()); newEdge->setLastNode(edge->lastNode(), edge->lastPortId()); // add to scene addItem(newEdge); // copy attrs & flags newEdge->copyDataFrom(edge); // copy id QString id = edge->getId(); // remove original removeItem(edge); delete edge; // set id to copy newEdge->setId(id); return newEdge; } qvge-0.6.3/src/qvge/CNodePort.cpp000066400000000000000000000055371405165517400165760ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CNodePort.h" #include "CNode.h" CNodePort::CNodePort(CNode *node, const QByteArray& portId, int align, double xoff, double yoff) : Shape(dynamic_cast(node)), m_node(node), m_id(portId), m_align(align), m_xoff(xoff), m_yoff(yoff) { Q_ASSERT(m_node != NULL); setRect(-4, -4, 9, 9); setBrush(Qt::gray); setPen(QPen(Qt::black, 1)); setToolTip(portId); setFlags(QGraphicsItem::ItemClipsToShape | QGraphicsItem::ItemIgnoresParentOpacity); } CNodePort::~CNodePort() { if (m_node) m_node->onPortDeleted(this); } void CNodePort::onParentDeleted() { // clear m_node if it is removed already m_node = NULL; } void CNodePort::onParentGeometryChanged() { Q_ASSERT(m_node != NULL); QRectF nodeBox = m_node->Shape::boundingRect(); int x = m_xoff, y = m_yoff; if (m_align & Qt::AlignLeft) x -= nodeBox.width() / 2; else if (m_align & Qt::AlignRight) x += nodeBox.width() / 2; if (m_align & Qt::AlignTop) y -= nodeBox.height() / 2; else if (m_align & Qt::AlignBottom) y += nodeBox.height() / 2; setX(x); setY(y); } void CNodePort::setId(const QByteArray& portId) { if (m_id == portId) return; auto oldId = m_id; m_id = portId; setToolTip(portId); if (m_node) m_node->onPortRenamed(this, oldId); } void CNodePort::setAlign(int newAlign) { m_align = newAlign; } void CNodePort::setOffset(double xoff, double yoff) { m_xoff = xoff; m_yoff = yoff; } QColor CNodePort::getColor() const { return brush().color(); } void CNodePort::setColor(const QColor& color) { setBrush(color); } void CNodePort::copyDataFrom(const CNodePort &port) { m_id = port.m_id; m_align = port.m_align; m_xoff = port.m_xoff; m_yoff = port.m_yoff; setBrush(port.brush()); setPen(port.pen()); setRect(port.rect()); } ItemDragTestResult CNodePort::acceptDragFromItem(QGraphicsItem* draggedItem) { if (dynamic_cast(draggedItem)) { setOpacity(0.5); return Accepted; } else { setOpacity(1); return Ignored; } } void CNodePort::leaveDragFromItem(QGraphicsItem* /*draggedItem*/) { setOpacity(1); } void CNodePort::onClick(QGraphicsSceneMouseEvent* /*mouseEvent*/) { setSelected(true); } // // //void CNodePort::hoverEnterEvent(QGraphicsSceneHoverEvent *event) //{ // //} // // //void CNodePort::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) //{ // //} // serialization bool CNodePort::storeTo(QDataStream& out, quint64 /*version64*/) const { out << m_id; out << m_align << m_xoff << m_yoff; // color etc. since v12 out << brush() << pen() << rect(); return true; } //bool CNodePort::restoreFrom(QDataStream& out, quint64 version64) //{ // out >> m_id; // out >> m_align >> m_xoff >> m_yoff; // return out.status() == QDataStream::Ok; //} qvge-0.6.3/src/qvge/CNodePort.h000066400000000000000000000031431405165517400162320ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include "IInteractive.h" class CNode; class CNodePort : public QGraphicsRectItem, public IInteractive { public: typedef QGraphicsRectItem Shape; explicit CNodePort(CNode *node, const QByteArray& portId = QByteArray(), int align = 0, double xoff = 0, double yoff = 0); virtual ~CNodePort(); CNode* getNode() const { return m_node; } const QByteArray& getId() const { return m_id; } int getAlign() const { return m_align; } double getX() const { return m_xoff; } double getY() const { return m_yoff; } QColor getColor() const; void setId(const QByteArray& portId); void setAlign(int newAlign); void setOffset(double xoff, double yoff); void setColor(const QColor& color); void copyDataFrom(const CNodePort &port); // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; //virtual bool restoreFrom(QDataStream& out, quint64 version64); // callbacks void onParentDeleted(); virtual void onParentGeometryChanged(); virtual void onClick(QGraphicsSceneMouseEvent* /*mouseEvent*/); virtual ItemDragTestResult acceptDragFromItem(QGraphicsItem* draggedItem); virtual void leaveDragFromItem(QGraphicsItem* draggedItem); //virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); //virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); protected: CNode *m_node = nullptr; QByteArray m_id; int m_align; double m_xoff, m_yoff; }; qvge-0.6.3/src/qvge/CNodeSceneActions.cpp000066400000000000000000000122011405165517400202120ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include #include "CNodeSceneActions.h" #include "CNodeEditorScene.h" #include "CNode.h" #include "CEdge.h" CNodeSceneActions::CNodeSceneActions(CNodeEditorScene *scene) : CEditorSceneActions(scene), nodeScene(*scene) { } bool CNodeSceneActions::editNodeId(CNode* editNode) { if (editNode == nullptr) return false; QString id = editNode->getId(); QString editId = id; _again: QString newId = QInputDialog::getText(0, tr("Change node Id"), tr("Specify new node Id:"), QLineEdit::Normal, editId); if (newId.isEmpty() || newId == id) return false; auto items = nodeScene.getItemsById(newId); for (auto item : items) { CNode* node = dynamic_cast(item); if (node == NULL || node == editNode) continue; if (node->getId() == newId) { int count = 0; QString nextFreeId = newId + QString::number(count++); while (nodeScene.getItemsById(nextFreeId).count()) { nextFreeId = newId + QString::number(count++); } QString autoId = QString(tr("Suggested Id: %1").arg(nextFreeId)); int r = QMessageBox::warning(0, tr("Warning: Id is in use"), tr("Id %1 is already used by another node.").arg(newId), autoId, tr("Swap node Ids"), tr("Continue editing"), 0, 2); if (r == 2) { editId = newId; goto _again; } if (r == 1) { editNode->setId(newId); node->setId(id); nodeScene.addUndoState(); return true; } // r = 0 editId = nextFreeId; goto _again; } } editNode->setId(newId); nodeScene.addUndoState(); return true; } void CNodeSceneActions::onActionNodeColor() { auto nodes = nodeScene.getSelectedNodes(); if (nodes.isEmpty()) return; QColor color = QColorDialog::getColor(nodes.first()->getAttribute("color").value()); if (!color.isValid()) return; for (auto node : nodes) { node->setAttribute("color", color); } nodeScene.addUndoState(); } void CNodeSceneActions::onActionLink() { auto nodes = nodeScene.getSelectedNodes(); if (nodes.count() < 2) return; auto baseNode = nodes.takeFirst(); for (auto node : nodes) { baseNode->merge(node); } nodeScene.addUndoState(); } void CNodeSceneActions::onActionUnlink() { auto nodes = nodeScene.getSelectedNodes(); if (nodes.isEmpty()) return; for (auto node : nodes) { node->unlink(); } nodeScene.addUndoState(); } bool CNodeSceneActions::editEdgeId(CEdge* editEdge) { if (editEdge == nullptr) return false; QString id = editEdge->getId(); QString editId = id; _again: QString newId = QInputDialog::getText(0, tr("Change edge Id"), tr("Specify new edge Id:"), QLineEdit::Normal, editId); if (newId.isEmpty() || newId == id) return false; auto items = nodeScene.getItemsById(newId); for (auto item : items) { CEdge* edge = dynamic_cast(item); if (edge == NULL || edge == editEdge) continue; if (edge->getId() == newId) { int count = 0; QString nextFreeId = newId + QString::number(count++); while (nodeScene.getItemsById(nextFreeId).count()) { nextFreeId = newId + QString::number(count++); } QString autoId = QString(tr("Suggested Id: %1").arg(nextFreeId)); int r = QMessageBox::warning(0, tr("Warning: Id is in use"), tr("Id %1 is already used by another edge.").arg(newId), autoId, tr("Swap edge Ids"), tr("Continue editing"), 0, 2); if (r == 2) { editId = newId; goto _again; } if (r == 1) { editEdge->setId(newId); edge->setId(id); nodeScene.addUndoState(); return true; } // r = 0 editId = nextFreeId; goto _again; } } editEdge->setId(newId); nodeScene.addUndoState(); return true; } void CNodeSceneActions::onActionEdgeColor() { auto edges = nodeScene.getSelectedEdges(); if (edges.isEmpty()) return; QColor color = QColorDialog::getColor(edges.first()->getAttribute("color").value()); if (!color.isValid()) return; for (auto edge : edges) { edge->setAttribute("color", color); } nodeScene.addUndoState(); } void CNodeSceneActions::onActionEdgeReverse() { auto edges = nodeScene.getSelectedEdges(); if (edges.isEmpty()) return; for (auto edge : edges) { edge->reverse(); } nodeScene.addUndoState(); } void CNodeSceneActions::onActionEdgeDirected() { auto edges = nodeScene.getSelectedEdges(); if (edges.isEmpty()) return; for (auto edge : edges) { edge->setAttribute("direction", "directed"); edge->update(); } nodeScene.addUndoState(); } void CNodeSceneActions::onActionEdgeMutual() { auto edges = nodeScene.getSelectedEdges(); if (edges.isEmpty()) return; for (auto edge : edges) { edge->setAttribute("direction", "mutual"); edge->update(); } nodeScene.addUndoState(); } void CNodeSceneActions::onActionEdgeUndirected() { auto edges = nodeScene.getSelectedEdges(); if (edges.isEmpty()) return; for (auto edge : edges) { edge->setAttribute("direction", "undirected"); edge->update(); } nodeScene.addUndoState(); } qvge-0.6.3/src/qvge/CNodeSceneActions.h000066400000000000000000000013411405165517400176620ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "CEditorSceneActions.h" class CNodeEditorScene; class CNode; class CEdge; class CNodeSceneActions : public CEditorSceneActions { Q_OBJECT public: CNodeSceneActions(CNodeEditorScene *scene); public Q_SLOTS: bool editNodeId(CNode* node); bool editEdgeId(CEdge* edge); void onActionNodeColor(); void onActionLink(); void onActionUnlink(); void onActionEdgeColor(); void onActionEdgeReverse(); void onActionEdgeDirected(); void onActionEdgeMutual(); void onActionEdgeUndirected(); private: CNodeEditorScene &nodeScene; }; qvge-0.6.3/src/qvge/CPDFExport.cpp000066400000000000000000000062651405165517400166560ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L.Masiuk(ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include #include #include #include #include #include "CPDFExport.h" #include "CEditorScene.h" CPDFExport::CPDFExport() { #ifdef Q_OS_WIN32 m_printer = m_pageDialog.printer(); #else m_printer = new QPrinter; #endif m_printer->setOutputFormat(QPrinter::NativeFormat); } CPDFExport::~CPDFExport() { #ifdef Q_OS_WIN32 #else delete m_printer; #endif } // impl: setup interface void CPDFExport::readSettings(QSettings& settings) { settings.beginGroup("PDFExport"); auto size = settings.value("PaperSize").toSize(); QPageSize pageSize(size); m_printer->setPageSize(pageSize); QString paperName = settings.value("PaperName").toString(); m_printer->setPaperName(paperName); #ifdef Q_OS_WIN32 int id = settings.value("WinPageSize").toInt(); m_printer->setWinPageSize(id); #endif QPrinter::Margins mm; mm.left = settings.value("MarginLeft").toDouble(); mm.right = settings.value("MarginRight").toDouble(); mm.top = settings.value("MarginTop").toDouble(); mm.bottom = settings.value("MarginBottom").toDouble(); m_printer->setMargins(mm); //QMarginsF mmf(mm.left, mm.top, mm.right, mm.bottom); //QPageLayout pl(pageSize, QPageLayout::Portrait, mmf); //m_printer->setPageLayout(pl); settings.endGroup(); } void CPDFExport::writeSettings(QSettings& settings) { settings.beginGroup("PDFExport"); auto size = m_printer->pageLayout().pageSize().sizePoints(); settings.setValue("PaperSize", size); QString paper = m_printer->paperName(); settings.setValue("PaperName", paper); #ifdef Q_OS_WIN32 int id = m_printer->winPageSize(); settings.setValue("WinPageSize", id); #endif auto mm = m_printer->margins(); settings.setValue("MarginLeft", mm.left); settings.setValue("MarginRight", mm.right); settings.setValue("MarginTop", mm.top); settings.setValue("MarginBottom", mm.bottom); settings.endGroup(); settings.sync(); } bool CPDFExport::setupDialog(CEditorScene& scene) { auto bbox = scene.itemsBoundingRect(); if (bbox.width() > bbox.height()) m_printer->setOrientation(QPrinter::Landscape); else m_printer->setOrientation(QPrinter::Portrait); #ifdef Q_OS_WIN32 if (m_pageDialog.exec() == QDialog::Rejected) return false; #else QPageSetupDialog pd(m_printer); if (pd.exec() == QDialog::Rejected) return false; #endif return true; } // impl: IFileSerializer bool CPDFExport::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { Q_ASSERT(m_printer); QScopedPointer tempScene(scene.clone()); tempScene->crop(); QPdfWriter writer(fileName); writer.setPageSize(m_printer->pageSize()); writer.setPageOrientation(m_printer->orientation() == QPrinter::Landscape ? QPageLayout::Landscape : QPageLayout::Portrait); writer.setMargins(m_printer->margins()); QPainter painter(&writer); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); tempScene->render(&painter); painter.end(); return true; } qvge-0.6.3/src/qvge/CPDFExport.h000066400000000000000000000023441405165517400163150ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2017 Ars L.Masiuk(ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include #include "qvge/IFileSerializer.h" class CPDFExport : public IFileSerializer { public: CPDFExport(); virtual ~CPDFExport(); // setup interface void readSettings(QSettings& settings); void writeSettings(QSettings& settings); bool setupDialog(CEditorScene& scene); // reimp: IFileSerializer virtual QString description() const { return "Adobe Portable Document Format"; } virtual QString filters() const { return "Adobe Portable Document Format (*.pdf)"; } virtual QString defaultFileExtension() const { return "pdf"; } virtual bool loadSupported() const { return false; } virtual bool load(const QString& /*fileName*/, CEditorScene& /*scene*/, QString* /*lastError = nullptr*/) const { return false; } virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; private: mutable QPrinter *m_printer = nullptr; QPageSetupDialog m_pageDialog; }; qvge-0.6.3/src/qvge/CPolyEdge.cpp000066400000000000000000000174251405165517400165530ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include "CPolyEdge.h" #include "CNode.h" #include "CControlPoint.h" CPolyEdge::CPolyEdge(QGraphicsItem *parent): Super(parent) { } void CPolyEdge::setPoints(const QList &points) { m_polyPoints = points; onParentGeometryChanged(); } bool CPolyEdge::insertPointAt(const QPointF &pos) { // no points yet if (m_polyPoints.isEmpty()) { m_polyPoints.append(pos); update(); return true; } // find segment for this point auto points = m_polyPoints; points.prepend(m_firstNode->pos()); points.append(m_lastNode->pos()); for (int i = 0; i < points.size() - 1; ++i) { qreal l1 = QLineF(points.at(i), points.at(i + 1)).length(); qreal l2 = QLineF(points.at(i), pos).length(); qreal l3 = QLineF(pos, points.at(i + 1)).length(); if (qAbs(l1 - (l2 + l3)) < 1) { m_polyPoints.insert(i, pos); update(); return true; } } return false; } // reimp CEdge* CPolyEdge::clone() { CPolyEdge* c = new CPolyEdge(parentItem()); // assign directly! c->m_firstNode = m_firstNode; c->m_firstPortId = m_firstPortId; c->m_lastNode = m_lastNode; c->m_lastPortId = m_lastPortId; c->m_polyPoints = m_polyPoints; if (scene()) scene()->addItem(c); c->copyDataFrom(this); return c; } void CPolyEdge::reverse() { std::reverse(m_polyPoints.begin(), m_polyPoints.end()); std::reverse(m_controlPoints.begin(), m_controlPoints.end()); Super::reverse(); } void CPolyEdge::transform(const QRectF & oldRect, const QRectF & newRect, double xc, double yc, bool changeSize, bool changePos) { Super::transform(oldRect, newRect, xc, yc, changeSize, changePos); // snap //auto scene = getScene(); // transform subpoints as well for (auto &point : m_polyPoints) { double xp = (point.x() - oldRect.left()) * xc + newRect.left(); double yp = (point.y() - oldRect.top()) * yc + newRect.top(); //if (scene) //{ // QPointF psnap = scene->getSnapped(QPointF(xp,yp)); // point.setX(psnap.x()); // point.setY(psnap.y()); //} //else { point.setX(xp); point.setY(yp); } } createControlPoints(); updateShapeFromPoints(); } // attributes bool CPolyEdge::hasLocalAttribute(const QByteArray& attrId) const { if (attrId == "points") return true; else return Super::hasLocalAttribute(attrId); } bool CPolyEdge::setAttribute(const QByteArray& attrId, const QVariant& v) { if (attrId == "points") { QString pointStr = v.toString(); setPoints(CUtils::pointsFromString(pointStr)); return true; } return Super::setAttribute(attrId, v); } bool CPolyEdge::removeAttribute(const QByteArray& attrId) { if (attrId == "points") { setPoints({}); return true; } return Super::removeAttribute(attrId); } // serialization bool CPolyEdge::storeTo(QDataStream& out, quint64 version64) const { Super::storeTo(out, version64); out << m_polyPoints; return true; } bool CPolyEdge::restoreFrom(QDataStream& out, quint64 version64) { if (Super::restoreFrom(out, version64)) { dropControlPoints(); m_polyPoints.clear(); out >> m_polyPoints; return true; } return false; } // mousing bool CPolyEdge::onDoubleClickDrag(QGraphicsSceneMouseEvent* /*mouseEvent*/, const QPointF &clickPos) { // create control point at click pos if (insertPointAt(clickPos)) { createControlPoints(); // start drag of the inserted point for (auto cp : m_controlPoints) { if (cp->scenePos() == clickPos) { getScene()->startDrag(cp); return true; } } return false; } return false; } void CPolyEdge::onControlPointMoved(CControlPoint* /*controlPoint*/, const QPointF& /*pos*/) { updateShapeFromPoints(); } void CPolyEdge::onControlPointDelete(CControlPoint* controlPoint) { int index = m_controlPoints.indexOf(controlPoint); Q_ASSERT(index >= 0); m_controlPoints.removeAt(index); delete controlPoint; updateShapeFromPoints(); addUndoState(); } // selection void CPolyEdge::onItemSelected(bool state) { Super::onItemSelected(state); if (!state) dropControlPoints(); else createControlPoints(); } // moving void CPolyEdge::onItemMoved(const QPointF& delta) { for (auto &p : m_polyPoints) { p += delta; } for (auto cp : m_controlPoints) { cp->moveBy(delta.x(), delta.y()); } } // drawing void CPolyEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { // straight line if (m_polyPoints.isEmpty()) { Super::paint(painter, option, widget); return; } // selection drawSelection(painter, option); // polyline setupPainter(painter, option, widget); painter->setClipRect(boundingRect()); painter->save(); painter->setBrush(Qt::NoBrush); painter->drawPath(m_shapeCachePath); painter->restore(); qreal r = qMax(3.0, painter->pen().widthF()); painter->setBrush(painter->pen().brush()); for (const QPointF &p : m_polyPoints) painter->drawEllipse(p, r, r); // arrows if (m_itemFlags & CF_Start_Arrow) { QLineF arrowLine(m_polyPoints.first(), line().p1()); if (arrowLine.length() > ARROW_SIZE * 2) drawArrow(painter, option, true, arrowLine); } if (m_itemFlags & CF_End_Arrow) { QLineF arrowLine(m_polyPoints.last(), line().p2()); if (arrowLine.length() > ARROW_SIZE * 2) drawArrow(painter, option, true, arrowLine); } } // callbacks void CPolyEdge::onParentGeometryChanged() { // straight line if (m_polyPoints.isEmpty()) { Super::onParentGeometryChanged(); return; } // optimize: no update while restoring if (s_duringRestore) return; // polyline if (!m_firstNode || !m_lastNode) return; prepareGeometryChange(); // update line position QPointF p1c = m_firstNode->pos(); if (m_firstPortId.size() && m_firstNode->getPort(m_firstPortId)) p1c = m_firstNode->getPort(m_firstPortId)->scenePos(); QPointF p2c = m_lastNode->pos(); if (m_lastPortId.size() && m_lastNode->getPort(m_lastPortId)) p2c = m_lastNode->getPort(m_lastPortId)->scenePos(); QLineF l1(p1c, m_polyPoints.first()); QPointF p1 = m_firstNode->getIntersectionPoint(l1, m_firstPortId); QLineF l2(p2c, m_polyPoints.last()); QPointF p2 = m_lastNode->getIntersectionPoint(l2, m_lastPortId); QLineF l(p1, p2); setLine(l); // shift line by arrows double arrowSize = getVisibleWeight() + ARROW_SIZE; l1 = QLineF(p1, m_polyPoints.first()); if (l1.length() < 5) p1 = m_polyPoints.first(); else if (m_itemFlags & CF_Start_Arrow) { l1 = CUtils::extendLine(l1, -arrowSize, 0); p1 = l1.p1(); } l2 = QLineF(m_polyPoints.last(), p2); if (l2.length() < 5) p2 = m_polyPoints.last(); else if (m_itemFlags & CF_End_Arrow) { l2 = CUtils::extendLine(l2, 0, arrowSize); p2 = l2.p2(); } // update shape path m_shapeCachePath = QPainterPath(); m_shapeCachePath.moveTo(p1); for (const QPointF &p : m_polyPoints) m_shapeCachePath.lineTo(p); m_shapeCachePath.lineTo(p2); m_controlPoint = m_shapeCachePath.pointAtPercent(0.5); QPainterPathStroker stroker; stroker.setWidth(6); m_selectionShapePath = stroker.createStroke(m_shapeCachePath); update(); // update text label if (getScene() && getScene()->itemLabelsEnabled()) { updateLabelPosition(); updateLabelDecoration(); } } // private void CPolyEdge::dropControlPoints() { qDeleteAll(m_controlPoints); m_controlPoints.clear(); } void CPolyEdge::createControlPoints() { dropControlPoints(); for (const QPointF &point: m_polyPoints) { auto cp = new CControlPoint(this); // first set position, then flags (to avoid recursion) cp->setPos(point); cp->setFlags(ItemIsMovable | ItemSendsGeometryChanges); m_controlPoints.append(cp); } } void CPolyEdge::updateShapeFromPoints() { m_polyPoints.clear(); for (auto cp : m_controlPoints) { m_polyPoints.append(cp->scenePos()); } onParentGeometryChanged(); } qvge-0.6.3/src/qvge/CPolyEdge.h000066400000000000000000000042251405165517400162120ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include "CDirectEdge.h" class CControlPoint; class CPolyEdge : public CDirectEdge { public: typedef CDirectEdge Super; CPolyEdge(QGraphicsItem *parent = Q_NULLPTR); const QList& getPoints() const { return m_polyPoints; } void setPoints(const QList &points); bool insertPointAt(const QPointF &pos); // reimp static QByteArray factoryId() { return "CPolyEdge"; } virtual QByteArray typeId() const { return this->factoryId(); } virtual QByteArray classId() const { return "polyedge"; } virtual QByteArray superClassId() const { return Super::classId(); } virtual CItem* create() const { return new CPolyEdge(parentItem()); } CEdge* clone(); virtual void reverse(); // transformations virtual void transform(const QRectF& oldRect, const QRectF& newRect, double xc, double yc, bool changeSize, bool changePos) override; // attributes virtual bool hasLocalAttribute(const QByteArray& attrId) const; virtual bool setAttribute(const QByteArray& attrId, const QVariant& v); virtual bool removeAttribute(const QByteArray& attrId); // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; virtual bool restoreFrom(QDataStream& out, quint64 version64); // mousing virtual bool onDoubleClickDrag(QGraphicsSceneMouseEvent *mouseEvent, const QPointF &clickPos); virtual void onControlPointMoved(CControlPoint* controlPoint, const QPointF& pos); // deleting virtual void onControlPointDelete(CControlPoint* controlPoint); // selection virtual void onItemMoved(const QPointF& delta); virtual void onItemSelected(bool state); protected: // reimp virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR); // callbacks virtual void onParentGeometryChanged(); private: void dropControlPoints(); void createControlPoints(); void updateShapeFromPoints(); private: // data model QList m_polyPoints; // visual control points QList m_controlPoints; }; qvge-0.6.3/src/qvge/CSVGExport.cpp000066400000000000000000000026771405165517400167070ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L.Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include #include #include "CSVGExport.h" #include "CEditorScene.h" bool CSVGExport::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { QScopedPointer tempScene(scene.clone()); if (m_cutContent) tempScene->crop(); QSvgGenerator svgWriter; svgWriter.setFileName(fileName); QString comment = scene.getClassAttribute("", "comment", false).defaultValue.toString(); if (comment.size()) svgWriter.setTitle(comment); QString desc = QString("Created with: ") + QApplication::applicationDisplayName(); svgWriter.setDescription(desc); // resolution if (m_resolution > 0) { int res = svgWriter.resolution(); double coeff = m_resolution / (double)res; auto size = tempScene->sceneRect().size(); auto sizeInch = size * coeff; //auto sizeMM = sizeInch * 25.4; //svgWriter.setSize(sizeMM.toSize()); //svgWriter.setResolution(m_resolution); svgWriter.setSize(sizeInch.toSize()); } else svgWriter.setSize(tempScene->sceneRect().size().toSize()); // export QPainter painter(&svgWriter); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); tempScene->render(&painter); painter.end(); return true; } qvge-0.6.3/src/qvge/CSVGExport.h000066400000000000000000000020631405165517400163410ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L.Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include "qvge/IFileSerializer.h" class CSVGExport : public IFileSerializer { public: CSVGExport(bool cutContent = true, int resolution = 0) : m_cutContent(cutContent), m_resolution(resolution) {} // reimp virtual QString description() const { return "Scalable Vector Graphics Format"; } virtual QString filters() const { return "Scalable Vector Graphics (*.svg)"; } virtual QString defaultFileExtension() const { return "svg"; } virtual bool loadSupported() const { return false; } virtual bool load(const QString& /*fileName*/, CEditorScene& /*scene*/, QString* /*lastError = nullptr*/) const { return false; } virtual bool saveSupported() const { return true; } virtual bool save(const QString& fileName, CEditorScene& scene, QString* lastError = nullptr) const; private: bool m_cutContent = true; int m_resolution = 96; }; qvge-0.6.3/src/qvge/CSimpleUndoManager.cpp000066400000000000000000000035401405165517400204060ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CSimpleUndoManager.h" #include "CEditorScene.h" #include CSimpleUndoManager::CSimpleUndoManager(CEditorScene & scene) : m_scene(&scene), m_stackIndex(-1) { } void CSimpleUndoManager::reset() { m_stackIndex = -1; m_stateStack.clear(); } void CSimpleUndoManager::addState() { // serialize & compress QByteArray snap; QDataStream ds(&snap, QIODevice::WriteOnly); m_scene->storeTo(ds, false); QByteArray compressedSnap = qCompress(snap); // push state into stack if (m_stateStack.size() == ++m_stackIndex) { m_stateStack.append(compressedSnap); } else { while (m_stateStack.size() > m_stackIndex) m_stateStack.takeLast(); m_stateStack.append(compressedSnap); } } void CSimpleUndoManager::revertState() { if (availableUndoCount()) { QByteArray &compressedSnap = m_stateStack[m_stackIndex]; QByteArray snap = qUncompress(compressedSnap); QDataStream ds(&snap, QIODevice::ReadOnly); m_scene->restoreFrom(ds, false); } } void CSimpleUndoManager::undo() { if (availableUndoCount()) { QByteArray &compressedSnap = m_stateStack[--m_stackIndex]; QByteArray snap = qUncompress(compressedSnap); QDataStream ds(&snap, QIODevice::ReadOnly); m_scene->restoreFrom(ds, false); } } void CSimpleUndoManager::redo() { if (availableRedoCount()) { QByteArray &compressedSnap = m_stateStack[++m_stackIndex]; QByteArray snap = qUncompress(compressedSnap); QDataStream ds(&snap, QIODevice::ReadOnly); m_scene->restoreFrom(ds, false); } } int CSimpleUndoManager::availableUndoCount() const { return (m_stackIndex > 0); } int CSimpleUndoManager::availableRedoCount() const { return (m_stackIndex >= 0) && (m_stackIndex < m_stateStack.size() - 1); } qvge-0.6.3/src/qvge/CSimpleUndoManager.h000066400000000000000000000013721405165517400200540ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #ifndef CSIMPLEUNDOMANAGER_H #define CSIMPLEUNDOMANAGER_H #include "IUndoManager.h" #include #include class CEditorScene; class CSimpleUndoManager : public IUndoManager { public: CSimpleUndoManager(CEditorScene &scene); // reimp virtual void reset(); virtual void addState(); virtual void revertState(); virtual void undo(); virtual void redo(); virtual int availableUndoCount() const; virtual int availableRedoCount() const; private: CEditorScene *m_scene; QList m_stateStack; int m_stackIndex; }; #endif // CUNDOMANAGER_H qvge-0.6.3/src/qvge/CTextLabelEdit.cpp000066400000000000000000000044331405165517400175300ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include "CTextLabelEdit.h" #include "CItem.h" #include #include #include CTextLabelEdit::CTextLabelEdit() { setTextInteractionFlags(Qt::TextEditorInteraction); connect(document(), &QTextDocument::contentsChanged, this, &CTextLabelEdit::updateGeometry); } CTextLabelEdit::~CTextLabelEdit() { } void CTextLabelEdit::updateGeometry() { if (m_item) { QPointF center = m_item->getLabelCenter(); double w = boundingRect().width(); double h = boundingRect().height(); setPos(center.x() - w/2, center.y() - h/2); } } bool CTextLabelEdit::onKeyPressed(CEditorScene& scene, QKeyEvent *keyEvent) { return QGraphicsTextItem::sceneEvent(keyEvent); } bool CTextLabelEdit::onKeyReleased(CEditorScene& scene, QKeyEvent *keyEvent) { if (keyEvent->matches(QKeySequence::Cancel)) // Esc { finishEdit(true); return true; } return QGraphicsTextItem::sceneEvent(keyEvent); } bool CTextLabelEdit::sceneEvent(QEvent *event) { if (event->type() == QEvent::FocusOut) { finishEdit(true); return true; } return QGraphicsTextItem::sceneEvent(event); } void CTextLabelEdit::startEdit(CItem *item) { m_item = item; if (m_item == nullptr) return; auto scene = m_item->getScene(); if (scene == nullptr) return; scene->selectItem(m_item); m_storedText = m_item->getAttribute("label").toString(); m_item->showLabel(false); setPlainText(m_storedText); setFont(m_item->getAttribute("label.font").value()); setDefaultTextColor(m_item->getAttribute("label.color").value()); updateGeometry(); QTextCursor c = textCursor(); c.select(QTextCursor::Document); setTextCursor(c); setFocus(); scene->addItem(this); show(); Q_EMIT editingStarted(m_item); } void CTextLabelEdit::finishEdit(bool accept) { if (m_item == nullptr) return; Q_EMIT editingFinished(m_item, !accept); auto scene = m_item->getScene(); if (scene == nullptr) return; QString text = toPlainText(); if (accept && m_storedText != text) { m_item->setAttribute("label", text); scene->addUndoState(); } m_item->showLabel(true); m_item = nullptr; scene->removeItem(this); } qvge-0.6.3/src/qvge/CTextLabelEdit.h000066400000000000000000000014711405165517400171740ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include class CItem; class CEditorScene; class CTextLabelEdit: public QGraphicsTextItem { Q_OBJECT public: CTextLabelEdit(); ~CTextLabelEdit(); void startEdit(CItem *item); void finishEdit(bool accept = true); virtual bool onKeyPressed(CEditorScene& scene, QKeyEvent *keyEvent); virtual bool onKeyReleased(CEditorScene& scene, QKeyEvent *keyEvent); Q_SIGNALS: void editingStarted(CItem *item); void editingFinished(CItem *item, bool cancelled); protected: virtual bool sceneEvent(QEvent *event); private Q_SLOT: void updateGeometry(); private: CItem *m_item = nullptr; QString m_storedText; }; qvge-0.6.3/src/qvge/CTransformRect.cpp000066400000000000000000000175321405165517400176330ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #include #include #include "CTransformRect.h" #include "CEditorScene.h" #include "CItem.h" #include "CNode.h" #include "CEdge.h" const double MIN_RECT_SIZE = 15.0; CTransformRect::CTransformRect() { m_points[0].cursor = Qt::SizeFDiagCursor; m_points[1].cursor = Qt::SizeVerCursor; m_points[2].cursor = Qt::SizeBDiagCursor; m_points[3].cursor = Qt::SizeHorCursor; m_points[4].cursor = Qt::SizeHorCursor; m_points[5].cursor = Qt::SizeBDiagCursor; m_points[6].cursor = Qt::SizeVerCursor; m_points[7].cursor = Qt::SizeFDiagCursor; } CTransformRect::~CTransformRect() { } void CTransformRect::setMoveOnly(bool on) { m_moveOnlyMode = on; } void CTransformRect::onActivated(CEditorScene& scene) { m_dragPoint = -1; onSelectionChanged(scene); } void CTransformRect::onSelectionChanged(CEditorScene& scene) { auto selItems = scene.getTransformableItems(); if (selItems.size()) { QRectF r = CUtils::getBoundingRect(selItems); m_lastRect = r; } else { m_lastRect = QRectF(); } scene.update(); } void CTransformRect::onSceneChanged(CEditorScene& scene) { onSelectionChanged(scene); } void CTransformRect::onDragItem(CEditorScene& scene, QGraphicsSceneMouseEvent* /*mouseEvent*/, QGraphicsItem* /*dragItem*/) { onSelectionChanged(scene); } void CTransformRect::draw(class CEditorScene &scene, QPainter *painter, const QRectF &) { QRectF r = m_lastRect; if (r.isEmpty() || r.isNull() || !r.isValid()) return; // update points m_points[0].pos = r.topLeft(); m_points[1].pos = QPointF(r.center().x(), r.top()); m_points[2].pos = r.topRight(); m_points[3].pos = QPointF(r.left(), r.center().y()); m_points[4].pos = QPointF(r.right(), r.center().y()); m_points[5].pos = r.bottomLeft(); m_points[6].pos = QPointF(r.center().x(), r.bottom()); m_points[7].pos = r.bottomRight(); const QPen rectPen(QColor(0x333333), 0, Qt::SolidLine); painter->setPen(rectPen); painter->drawRect(r); auto view = scene.getCurrentView(); if (view) { for (int i = 0; i < 8; ++i) { // zoom-independend control points QPoint viewPos = view->mapFromScene(m_points[i].pos); QPointF topLeft = view->mapToScene(QPoint(viewPos.x() - 4, viewPos.y() - 4)); QPointF bottomRight = view->mapToScene(QPoint(viewPos.x() + 4, viewPos.y() + 4)); m_points[i].sceneRect = QRectF(topLeft, bottomRight); painter->fillRect(m_points[i].sceneRect, Qt::SolidPattern); } scene.invalidate(); } } bool CTransformRect::onMousePressed(CEditorScene& scene, QGraphicsSceneMouseEvent* mouseEvent) { bool isDragging = (mouseEvent->button() == Qt::LeftButton); if (!isDragging) return false; auto pos = mouseEvent->scenePos(); for (int i = 0; i < 8; ++i) { if (m_points[i].sceneRect.contains(pos)) { m_dragRect = m_lastRect; m_dragPos = m_lastPos = pos; m_dragPoint = i; doSetupItems(scene); return true; } } doReset(); return false; } bool CTransformRect::onMouseReleased(CEditorScene& scene, QGraphicsSceneMouseEvent *mouseEvent) { bool isDragging = (mouseEvent->button() == Qt::LeftButton); if (!isDragging) return false; // nothing was dragged if (m_dragPoint == -1) return false; // else finish the drag if (m_lastPos != m_dragPos) { // snap after transform //if (scene.gridSnapEnabled()) { for (auto node : m_nodesTransform) { node->setPos(scene.getSnapped(node->pos())); } for (auto node : m_nodesMove) { node->setPos(scene.getSnapped(node->pos())); } } scene.addUndoState(); } scene.setSceneCursor(Qt::ArrowCursor); doReset(); return true; } bool CTransformRect::onMouseMove(CEditorScene& scene, QGraphicsSceneMouseEvent *mouseEvent) { auto pos = mouseEvent->scenePos(); bool isDragging = (mouseEvent->buttons() & Qt::LeftButton); if (isDragging && m_dragPoint >= 0) { // drag QPointF deltaPos = pos - m_lastPos; if (!deltaPos.isNull()) { QRectF newRect = m_lastRect; bool isShift = (mouseEvent->modifiers() & Qt::ShiftModifier); // default transform switch (m_dragPoint) { case 0: newRect.setTopLeft(pos); break; case 1: newRect.setTop(pos.y()); break; case 2: newRect.setTopRight(pos); break; case 3: newRect.setLeft(pos.x()); break; case 4: newRect.setRight(pos.x()); break; case 5: newRect.setBottomLeft(pos); break; case 6: newRect.setBottom(pos.y()); break; case 7: newRect.setBottomRight(pos); break; } // if shift pressed: mirror around center if (isShift && newRect.isValid() && m_dragRect.isValid()) { qreal dx_r = newRect.right() - m_dragRect.right(); qreal dx_l = newRect.left() - m_dragRect.left(); qreal dy_t = newRect.top() - m_dragRect.top(); qreal dy_b = newRect.bottom() - m_dragRect.bottom(); switch (m_dragPoint) { case 0: newRect.setBottomRight(m_dragRect.bottomRight() - QPointF(dx_l, dy_t)); break; case 1: newRect.setBottom(m_dragRect.bottom() - dy_t); break; case 2: newRect.setBottomLeft(m_dragRect.bottomLeft() - QPointF(dx_r, dy_t)); break; case 3: newRect.setRight(m_dragRect.right() - dx_l); break; case 4: newRect.setLeft(m_dragRect.left() - dx_r); break; case 5: newRect.setTopRight(m_dragRect.topRight() - QPointF(dx_l, dy_b)); break; case 6: newRect.setTop(m_dragRect.top() - dy_b); break; case 7: newRect.setTopLeft(m_dragRect.topLeft() - QPointF(dx_r, dy_b)); break; } } // do transform if rect is valid if (newRect.isValid() && newRect.width() >= MIN_RECT_SIZE && newRect.height() >= MIN_RECT_SIZE) { doTransformBy(scene, m_lastRect, newRect); m_lastRect = newRect; } else return false; } m_lastPos = pos; return true; } // no drag - check hover for (int i = 0; i < 8; ++i) { if (m_points[i].sceneRect.contains(pos)) { scene.setSceneCursor(m_points[i].cursor); return true; } } // no hit return false; } // privates void CTransformRect::doReset() { m_dragRect = QRectF(); m_dragPos = m_lastPos = QPointF(); m_dragPoint = -1; m_nodesTransform.clear(); m_nodesMove.clear(); m_others.clear(); } void CTransformRect::doSetupItems(CEditorScene& scene) { // prepare transform lists auto selItems = scene.getTransformableItems(); // go for nodes for (auto item : selItems) { auto cnode = dynamic_cast(item); if (cnode) { m_nodesTransform << cnode; continue; } } // go for edges & rest for (auto item : selItems) { auto cnode = dynamic_cast(item); if (cnode) continue; auto cedge = dynamic_cast(item); if (cedge) { m_others << cedge; auto n1 = cedge->firstNode(); auto n2 = cedge->lastNode(); if (!m_nodesTransform.contains(n1) && !m_nodesMove.contains(n1)) m_nodesMove << n1; if (!m_nodesTransform.contains(n2) && !m_nodesMove.contains(n2)) m_nodesMove << n2; continue; } auto citem = dynamic_cast(item); if (citem) { m_others << citem; continue; } } } void CTransformRect::doTransformBy(CEditorScene& scene, QRectF oldRect, QRectF newRect) { if (oldRect == newRect) return; // normalize borders const int margin = scene.getBoundingMargin(); oldRect.adjust(margin, margin, -margin, -margin); newRect.adjust(margin, margin, -margin, -margin); if (!oldRect.isValid() || !newRect.isValid()) return; double xc = newRect.width() / oldRect.width(); double yc = newRect.height() / oldRect.height(); // run transformation bool changeSize = !m_moveOnlyMode; for (auto node : m_nodesTransform) { node->transform(oldRect, newRect, xc, yc, changeSize, true); } for (auto node : m_nodesMove) { node->transform(oldRect, newRect, xc, yc, false, true); } for (auto item : m_others) { item->transform(oldRect, newRect, xc, yc, changeSize, true); } } qvge-0.6.3/src/qvge/CTransformRect.h000066400000000000000000000033221405165517400172700ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include #include #include "ISceneEditController.h" class CEditorScene; class CItem; class CNode; class QGraphicsItem; class CTransformRect: public QObject, public ISceneEditController { Q_OBJECT public: CTransformRect(); ~CTransformRect(); // move-only mode void setMoveOnly(bool on); // ISceneEditController virtual void onActivated(CEditorScene& scene); virtual void onDeactivated(CEditorScene& /*scene*/) {} virtual void onSelectionChanged(CEditorScene& /*scene*/); virtual void onSceneChanged(CEditorScene& scene); virtual void onDragItem(CEditorScene& /*scene*/, QGraphicsSceneMouseEvent* /*mouseEvent*/, QGraphicsItem* /*dragItem*/); virtual void draw(CEditorScene& scene, QPainter *painter, const QRectF &r); virtual bool onMousePressed(CEditorScene& scene, QGraphicsSceneMouseEvent *mouseEvent); virtual bool onMouseMove(CEditorScene& scene, QGraphicsSceneMouseEvent *mouseEvent); virtual bool onMouseReleased(CEditorScene& scene, QGraphicsSceneMouseEvent *mouseEvent); private: void doSetupItems(CEditorScene& scene); void doReset(); void doTransformBy(CEditorScene& scene, QRectF oldRect, QRectF newRect); struct ControlPoint { QPointF pos; QCursor cursor; QRectF sceneRect; }; ControlPoint m_points[8]; int m_dragPoint = -1; QPointF m_dragPos; QRectF m_dragRect; QPointF m_lastPos; QRectF m_lastRect; bool m_moveOnlyMode = false; // transform lists QList m_nodesTransform, m_nodesMove; QList m_others; }; qvge-0.6.3/src/qvge/CUtils.cpp000066400000000000000000000107501405165517400161350ustar00rootroot00000000000000#include "CUtils.h" #include #include #include #include #include #include QVariant CUtils::textToVariant(const QString& text, int type) { switch (type) { case QMetaType::QStringList: return text.split('|', QString::SkipEmptyParts); case QVariant::Int: return text.toInt(); case QVariant::Double: return text.toDouble(); case QMetaType::Float: return text.toFloat(); case QVariant::Bool: if (text.toLower() == "true") return true; else return false; case QVariant::Color: return QColor(text); case QVariant::Font: { QFont f; f.fromString(text); return f; } default: return text; // string } } QString CUtils::variantToText(const QVariant& v, int type) { if (type < 0) type = v.type(); switch (type) { case QVariant::Point: return QString("%1;%2").arg(v.toPoint().x()).arg(v.toPoint().y()); case QVariant::PointF: return QString("%1;%2").arg(v.toPointF().x()).arg(v.toPointF().y()); case QVariant::Size: return QString("%1:%2").arg(v.toSize().width()).arg(v.toSize().height()); case QVariant::SizeF: return QString("%1:%2").arg(v.toSizeF().width()).arg(v.toSizeF().height()); case QVariant::Bool: return v.toBool() ? "true" : "false"; case QVariant::Double: return QString::number(v.toDouble(), 'f', 4); case QMetaType::Float: return QString::number(v.value(), 'f', 4); case QMetaType::QStringList: return v.toStringList().join('|'); default:; return v.toString(); } } Qt::PenStyle CUtils::textToPenStyle(const QString& text, Qt::PenStyle def) { static QMap s_penStyles = { { "none", Qt::NoPen }, { "solid", Qt::SolidLine }, { "dashed", Qt::DashLine }, { "dotted", Qt::DotLine }, { "dashdot", Qt::DashDotLine }, { "dashdotdot", Qt::DashDotDotLine } }; if (s_penStyles.contains(text)) return s_penStyles[text]; else return def; } QString CUtils::penStyleToText(int style) { switch (style) { case Qt::SolidLine: return QStringLiteral("solid"); case Qt::DashLine: return QStringLiteral("dashed"); case Qt::DotLine: return QStringLiteral("dotted"); case Qt::DashDotLine: return QStringLiteral("dashdot"); case Qt::DashDotDotLine: return QStringLiteral("dashdotdot"); default: return QStringLiteral("none"); } } QString CUtils::visToString(const QSet& visIds) { return visIds.toList().join('|'); } QSet CUtils::visFromString(const QString& text) { return text.toUtf8().split('|').toSet(); } QStringList CUtils::byteArraySetToStringList(const QSet& ids) { QStringList sl; for (const auto& id : ids) sl << id; return sl; } QString CUtils::pointsToString(const QList& points) { QString s; QTextStream ds(&s, QIODevice::WriteOnly); for (const auto& p : points) { float x = p.x(); float y = p.y(); ds << x << " " << y << " "; } return s; } QList CUtils::pointsFromString(const QString& text) { QList pl; QString str(text.trimmed()); if (str.size()) { float x = 0, y = 0; QTextStream ds(&str); while (!ds.atEnd()) { ds >> x; ds >> y; // to do: check validity pl.append(QPointF(x, y)); } } return pl; } QPointF CUtils::closestIntersection(const QLineF& line, const QPolygonF& endPolygon) { QPointF intersectPoint; QPointF p1 = endPolygon.first(); QPointF p2; for (int i = 1; i < endPolygon.count(); ++i) { p2 = endPolygon.at(i); QLineF polyLine = QLineF(p1, p2); QLineF::IntersectType intersectType = polyLine.intersect(line, &intersectPoint); if (intersectType == QLineF::BoundedIntersection) return intersectPoint; p1 = p2; } return QPointF(); } QString CUtils::cutLastSuffix(const QString& fileName) { int idx = fileName.lastIndexOf("."); if (idx < 0) return fileName; else return fileName.left(idx); } QRectF CUtils::getBoundingRect(const QList& items) { QRectF r; for (const auto item : items) r |= item->sceneBoundingRect(); return r; } QLineF CUtils::extendLine(const QLineF& line, float fromStart, float fromEnd) { QPointF v(line.p2().x() - line.p1().x(), line.p2().y() - line.p1().y()); float l = std::sqrt(v.x() * v.x() + v.y() * v.y()); v.setX(v.x() / l); v.setY(v.y() / l); return QLineF( line.p1().x() - v.x() * fromStart, line.p1().y() - v.y() * fromStart, line.p2().x() - v.x() * fromEnd, line.p2().y() - v.y() * fromEnd ); } qvge-0.6.3/src/qvge/CUtils.h000066400000000000000000000030561405165517400156030ustar00rootroot00000000000000/* This file is a part of QVGE - Qt Visual Graph Editor (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once #include #include #include #include #include #include #include #include #include #include class CUtils { public: static QString variantToText(const QVariant& v, int type = -1); static QVariant textToVariant(const QString& text, int type = QVariant::String); static Qt::PenStyle textToPenStyle(const QString& text, Qt::PenStyle def = Qt::NoPen); static QString penStyleToText(int style); static QString visToString(const QSet& visIds); static QSet visFromString(const QString& text); static QStringList byteArraySetToStringList(const QSet& visIds); static QString pointsToString(const QList& points); static QList pointsFromString(const QString& text); template static void insertUnique(X& dest, const X& from); static QPointF closestIntersection(const QLineF& line, const QPolygonF& with); static QString cutLastSuffix(const QString& fileName); static QRectF getBoundingRect(const QList& items); static QLineF extendLine(const QLineF& line, float fromStart, float fromEnd); }; template void CUtils::insertUnique(X& dest, const X& from) { for (auto it = from.constBegin(); it != from.constEnd(); ++it) { if (!dest.contains(it.key())) dest[it.key()] = it.value(); } } qvge-0.6.3/src/qvge/Doxyfile000066400000000000000000003237531405165517400157460ustar00rootroot00000000000000# Doxyfile 1.8.13 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = qvge # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 0.5.5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Qt Visual Graph Editor" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = g:\Doctor\2016\BranchEditor\v3\qvge_doc # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 0. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = g:\Doctor\2016\BranchEditor\v3\qvge\ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.pyw \ *.f90 \ *.f95 \ *.f03 \ *.f08 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the # cost of reduced performance. This can be particularly helpful with template # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse-libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /