From e6112cdb964c2b5b85404822a9dac3acbf18422b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Fri, 12 May 2017 12:10:48 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@188 a8b55f48-bf90-11e4-a774-851b48703e85 --- CMakeLists.txt | 37 +- FindMinGW.cmake | 8 +- QtProject.cmake | 30 + SDKMacros.cmake | 22 + cd_utils/CMakeLists.txt | 23 +- make_libs.bat | 2 +- piqt/CMakeLists.txt | 44 +- piqt_utils/CMakeLists.txt | 71 +- qad/CMakeLists.txt | 72 + qad/FindQAD.cmake | 31 + qad/QADConfig.cmake | 1 + qad/application/CMakeLists.txt | 2 + qad/application/edockwidget.cpp | 51 + qad/application/edockwidget.h | 37 + qad/application/emainwindow.cpp | 333 ++++ qad/application/emainwindow.h | 109 ++ qad/application/etabwidget.cpp | 104 ++ qad/application/etabwidget.h | 54 + qad/application/historyview.cpp | 140 ++ qad/application/historyview.h | 74 + qad/application/lang/qad_application_ru.ts | 290 +++ qad/application/plugin/CMakeLists.txt | 1 + qad/application/plugin/edockwidgetplugin.cpp | 69 + qad/application/plugin/edockwidgetplugin.h | 31 + qad/application/plugin/emainwindowplugin.cpp | 69 + qad/application/plugin/emainwindowplugin.h | 31 + qad/application/plugin/historyviewplugin.cpp | 69 + qad/application/plugin/historyviewplugin.h | 31 + qad/application/plugin/qad_application.cpp | 19 + qad/application/plugin/qad_application.h | 21 + qad/application/qad_application.qrc | 33 + qad/application/qsingleapplication.cpp | 87 + qad/application/qsingleapplication.h | 30 + qad/application/ribbon.cpp | 196 ++ qad/application/ribbon.h | 62 + qad/blockview/CMakeLists.txt | 2 + qad/blockview/alignedtextitem.cpp | 45 + qad/blockview/alignedtextitem.h | 45 + qad/blockview/blockbase.cpp | 104 ++ qad/blockview/blockbase.h | 57 + qad/blockview/blockbusitem.cpp | 733 ++++++++ qad/blockview/blockbusitem.h | 119 ++ qad/blockview/blockeditor.cpp | 347 ++++ qad/blockview/blockeditor.h | 81 + qad/blockview/blockeditor.ui | 458 +++++ qad/blockview/blockeditor_main.cpp | 10 + qad/blockview/blockitem.cpp | 448 +++++ qad/blockview/blockitem.h | 207 +++ qad/blockview/blockview.cpp | 1630 +++++++++++++++++ qad/blockview/blockview.h | 200 ++ qad/blockview/blockviewwavetrace.cpp | 197 ++ qad/blockview/blockviewwavetrace.h | 43 + qad/blockview/drawtools.cpp | 791 ++++++++ qad/blockview/drawtools.h | 129 ++ qad/blockview/drawtools.ui | 666 +++++++ qad/blockview/lang/qad_blockview_ru.qm | Bin 0 -> 3377 bytes qad/blockview/lang/qad_blockview_ru.ts | 290 +++ qad/blockview/plugin/CMakeLists.txt | 1 + qad/blockview/plugin/blockviewplugin.cpp | 69 + qad/blockview/plugin/blockviewplugin.h | 31 + qad/blockview/plugin/qad_blockview.cpp | 14 + qad/blockview/plugin/qad_blockview.h | 21 + qad/blockview/qad_blockview.qrc | 53 + qad/graphic/CMakeLists.txt | 2 + qad/graphic/graphic.cpp | 1522 +++++++++++++++ qad/graphic/graphic.h | 459 +++++ qad/graphic/graphic.ui | 485 +++++ qad/graphic/graphic_conf.cpp | 103 ++ qad/graphic/graphic_conf.h | 90 + qad/graphic/graphic_conf.ui | 678 +++++++ qad/graphic/lang/qad_graphic_ru.qm | Bin 0 -> 3662 bytes qad/graphic/lang/qad_graphic_ru.ts | 351 ++++ qad/graphic/plugin/CMakeLists.txt | 1 + qad/graphic/plugin/graphicplugin.cpp | 69 + qad/graphic/plugin/graphicplugin.h | 31 + qad/graphic/plugin/qad_graphic.cpp | 14 + qad/graphic/plugin/qad_graphic.h | 21 + qad/graphic/qad_graphic.qrc | 32 + qad/graphic/uglwidget.h | 48 + qad/graphic/uwidget.h | 52 + qad/icons/align-bottom-center.png | Bin 0 -> 342 bytes qad/icons/align-bottom-left.png | Bin 0 -> 384 bytes qad/icons/align-bottom-right.png | Bin 0 -> 382 bytes qad/icons/align-center-center.png | Bin 0 -> 303 bytes qad/icons/align-center-left.png | Bin 0 -> 354 bytes qad/icons/align-center-right.png | Bin 0 -> 348 bytes qad/icons/align-hor.png | Bin 0 -> 992 bytes qad/icons/align-top-center.png | Bin 0 -> 344 bytes qad/icons/align-top-left.png | Bin 0 -> 403 bytes qad/icons/align-top-right.png | Bin 0 -> 387 bytes qad/icons/align-ver.png | Bin 0 -> 1038 bytes qad/icons/alpha.png | Bin 0 -> 158 bytes qad/icons/archive-extract.png | Bin 0 -> 626 bytes qad/icons/archive-insert-directory.png | Bin 0 -> 588 bytes qad/icons/archive-insert.png | Bin 0 -> 433 bytes qad/icons/arrow-down.png | Bin 0 -> 525 bytes qad/icons/arrow-up.png | Bin 0 -> 484 bytes qad/icons/axis_x.png | Bin 0 -> 235 bytes qad/icons/axis_y.png | Bin 0 -> 259 bytes qad/icons/blockview.png | Bin 0 -> 943 bytes qad/icons/border-line.png | Bin 0 -> 183 bytes {touch_widgets => qad}/icons/button.png | Bin qad/icons/case-sensitive.png | Bin 0 -> 326 bytes qad/icons/chardialog.png | Bin 0 -> 943 bytes qad/icons/checkbox-unchecked.png | Bin 0 -> 419 bytes qad/icons/checkbox.png | Bin 0 -> 654 bytes qad/icons/clear-history.png | Bin 0 -> 3825 bytes qad/icons/clineedit.png | Bin 0 -> 9153 bytes qad/icons/code-error.png | Bin 0 -> 722 bytes qad/icons/code-parents.png | Bin 0 -> 641 bytes qad/icons/code-struct.png | Bin 0 -> 676 bytes qad/icons/code-union.png | Bin 0 -> 731 bytes qad/icons/code-variable.png | Bin 0 -> 387 bytes qad/icons/code-word.png | Bin 0 -> 543 bytes qad/icons/colorbutton.png | Bin 0 -> 7468 bytes qad/icons/configure.png | Bin 0 -> 717 bytes qad/icons/database.png | Bin 0 -> 1918 bytes qad/icons/dialog-close.png | Bin 0 -> 813 bytes qad/icons/dialog-ok-apply.png | Bin 0 -> 840 bytes qad/icons/document-edit-.png | Bin 0 -> 2955 bytes qad/icons/document-edit.png | Bin 0 -> 726 bytes qad/icons/document-new.png | Bin 0 -> 579 bytes qad/icons/document-open.png | Bin 0 -> 2798 bytes qad/icons/document-open_16.png | Bin 0 -> 701 bytes qad/icons/document-print.png | Bin 0 -> 880 bytes qad/icons/document-save.png | Bin 0 -> 2122 bytes qad/icons/draw-ellipse.png | Bin 0 -> 1794 bytes qad/icons/draw-line.png | Bin 0 -> 621 bytes qad/icons/draw-rectangle.png | Bin 0 -> 699 bytes qad/icons/draw-text.png | Bin 0 -> 815 bytes qad/icons/ecombobox.png | Bin 0 -> 1215 bytes qad/icons/edit-clear-locationbar-rtl.png | Bin 0 -> 644 bytes qad/icons/edit-clear.png | Bin 0 -> 3911 bytes qad/icons/edit-copy.png | Bin 0 -> 485 bytes qad/icons/edit-delete.png | Bin 0 -> 2101 bytes qad/icons/edit-find.png | Bin 0 -> 634 bytes qad/icons/edit-guides.png | Bin 0 -> 544 bytes qad/icons/edit-paste.png | Bin 0 -> 529 bytes qad/icons/edit-table-insert-row-below.png | Bin 0 -> 852 bytes qad/icons/edockwidget.png | Bin 0 -> 638 bytes qad/icons/etabwidget.png | Bin 0 -> 693 bytes qad/icons/expand_s_x.png | Bin 0 -> 571 bytes qad/icons/expand_s_y.png | Bin 0 -> 577 bytes qad/icons/expand_x.png | Bin 0 -> 579 bytes qad/icons/expand_y.png | Bin 0 -> 577 bytes qad/icons/f1.png | Bin 0 -> 1046 bytes qad/icons/format-fill-color.png | Bin 0 -> 2434 bytes qad/icons/format-stroke-color.png | Bin 0 -> 1627 bytes qad/icons/format-text-subscript.png | Bin 0 -> 824 bytes qad/icons/games-solve.png | Bin 0 -> 992 bytes qad/icons/go-next.png | Bin 0 -> 940 bytes qad/icons/go-previous.png | Bin 0 -> 907 bytes qad/icons/graphic.png | Bin 0 -> 1630 bytes qad/icons/graphics.png | Bin 0 -> 391 bytes qad/icons/historyview.png | Bin 0 -> 1262 bytes {touch_widgets => qad}/icons/icons.xcf | Bin qad/icons/item-add.png | Bin 0 -> 639 bytes qad/icons/item.png | Bin 0 -> 448 bytes qad/icons/lastmoves.png | Bin 0 -> 592 bytes qad/icons/layer-visible-off.png | Bin 0 -> 3446 bytes qad/icons/layer-visible-on.png | Bin 0 -> 4016 bytes qad/icons/led_3.png | Bin 0 -> 8532 bytes qad/icons/led_off.png | Bin 0 -> 540 bytes qad/icons/led_on.png | Bin 0 -> 533 bytes qad/icons/legend.png | Bin 0 -> 810 bytes qad/icons/list-add.png | Bin 0 -> 2658 bytes qad/icons/list-remove.png | Bin 0 -> 332 bytes qad/icons/log_parser.png | Bin 0 -> 18635 bytes qad/icons/mail.png | Bin 0 -> 918 bytes qad/icons/media-playback-pause.png | Bin 0 -> 721 bytes qad/icons/media-playback-stop.png | Bin 0 -> 736 bytes qad/icons/media-record.png | Bin 0 -> 1155 bytes qad/icons/node-add.png | Bin 0 -> 694 bytes qad/icons/node.png | Bin 0 -> 658 bytes qad/icons/pause-back.png | Bin 0 -> 6397 bytes qad/icons/pause-front.png | Bin 0 -> 3146 bytes qad/icons/qcodeedit.png | Bin 0 -> 818 bytes qad/icons/qpiconsole.png | Bin 0 -> 9858 bytes qad/icons/quickopen.png | Bin 0 -> 556 bytes qad/icons/qvariantedit.png | Bin 0 -> 1247 bytes qad/icons/run-build.png | Bin 0 -> 880 bytes qad/icons/spinslider.png | Bin 0 -> 830 bytes qad/icons/sql_table.png | Bin 0 -> 1405 bytes qad/icons/tools-wizard.png | Bin 0 -> 797 bytes .../icons/touchbuttframe.png | Bin {touch_widgets => qad}/icons/touchbutton.png | Bin {touch_widgets => qad}/icons/touchslider.png | Bin qad/icons/transform-move.png | Bin 0 -> 1103 bytes qad/icons/variable-add.png | Bin 0 -> 557 bytes qad/icons/variable-copy.png | Bin 0 -> 567 bytes qad/icons/variable-edit.png | Bin 0 -> 567 bytes qad/icons/variable-remove.png | Bin 0 -> 588 bytes qad/icons/view-fullscreen.png | Bin 0 -> 329 bytes qad/icons/view-grid.png | Bin 0 -> 691 bytes qad/icons/view-preview.png | Bin 0 -> 2643 bytes qad/icons/view-refresh.png | Bin 0 -> 1283 bytes qad/icons/z-bottom.png | Bin 0 -> 987 bytes qad/icons/z-down.png | Bin 0 -> 1026 bytes qad/icons/z-top.png | Bin 0 -> 1182 bytes qad/icons/z-up.png | Bin 0 -> 1025 bytes qad/icons/zoom-fit-best.png | Bin 0 -> 539 bytes qad/icons/zoom-in.png | Bin 0 -> 1191 bytes qad/icons/zoom-out.png | Bin 0 -> 1173 bytes qad/icons/zoom-range.png | Bin 0 -> 1311 bytes qad/icons/zoom-rect.png | Bin 0 -> 1378 bytes qad/sql_table/CMakeLists.txt | 2 + qad/sql_table/lang/qad_sql_table_ru.qm | Bin 0 -> 763 bytes qad/sql_table/lang/qad_sql_table_ru.ts | 58 + qad/sql_table/plugin/CMakeLists.txt | 1 + qad/sql_table/plugin/qad_sql_table.cpp | 17 + qad/sql_table/plugin/qad_sql_table.h | 21 + qad/sql_table/plugin/sql_record_plugin.cpp | 69 + qad/sql_table/plugin/sql_record_plugin.h | 31 + qad/sql_table/plugin/sql_table_plugin.cpp | 69 + qad/sql_table/plugin/sql_table_plugin.h | 31 + qad/sql_table/qad_sql_table.qrc | 25 + qad/sql_table/sql_record_widget.cpp | 352 ++++ qad/sql_table/sql_record_widget.h | 74 + qad/sql_table/sql_table_widget.cpp | 1067 +++++++++++ qad/sql_table/sql_table_widget.h | 334 ++++ qad/sql_table/sql_table_widget.ui | 310 ++++ qad/touch_widgets/CMakeLists.txt | 2 + qad/touch_widgets/plugin/CMakeLists.txt | 1 + .../touch_widgets}/plugin/touch_widgets.cpp | 0 .../touch_widgets}/plugin/touch_widgets.h | 0 .../plugin/touchbuttframeplugin.cpp | 0 .../plugin/touchbuttframeplugin.h | 0 .../plugin/touchbuttonplugin.cpp | 0 .../touch_widgets}/plugin/touchbuttonplugin.h | 0 .../plugin/touchsliderplugin.cpp | 0 .../touch_widgets}/plugin/touchsliderplugin.h | 0 .../touch_widgets}/touch_bar.h | 0 qad/touch_widgets/touch_widgets.qrc | 7 + .../touch_widgets}/touchbuttframe.cpp | 0 .../touch_widgets}/touchbuttframe.h | 0 .../touch_widgets}/touchbutton.cpp | 0 .../touch_widgets}/touchbutton.h | 0 .../touch_widgets}/touchslider.cpp | 0 .../touch_widgets}/touchslider.h | 0 .../touch_widgets}/touchslider.ui | 0 qad/utils/CMakeLists.txt | 2 + qad/utils/chunkstream.cpp | 38 + qad/utils/chunkstream.h | 58 + qad/utils/plugin/CMakeLists.txt | 1 + qad/utils/plugin/qad_utils.cpp | 13 + qad/utils/plugin/qad_utils.h | 21 + qad/utils/propertystorage.cpp | 148 ++ qad/utils/propertystorage.h | 107 ++ qad/utils/qad_types.cpp | 123 ++ qad/utils/qad_types.h | 115 ++ qad/utils/qad_utils.qrc | 17 + qad/utils/qpiconfig.cpp | 825 +++++++++ qad/utils/qpiconfig.h | 280 +++ qad/utils/qpievaluator.cpp | 1065 +++++++++++ qad/utils/qpievaluator.h | 196 ++ qad/widgets/CMakeLists.txt | 2 + qad/widgets/chardialog.cpp | 151 ++ qad/widgets/chardialog.h | 50 + qad/widgets/chardialog.ui | 92 + qad/widgets/clineedit.cpp | 51 + qad/widgets/clineedit.h | 43 + qad/widgets/colorbutton.cpp | 112 ++ qad/widgets/colorbutton.h | 63 + qad/widgets/ecombobox.cpp | 99 + qad/widgets/ecombobox.h | 36 + qad/widgets/iconedlabel.h | 68 + qad/widgets/lang/qad_widgets_ru.qm | Bin 0 -> 3938 bytes qad/widgets/lang/qad_widgets_ru.ts | 853 +++++++++ qad/widgets/lang/ru.qm | Bin 0 -> 3938 bytes qad/widgets/lang/ru.ts | 853 +++++++++ qad/widgets/plugin/CMakeLists.txt | 1 + qad/widgets/plugin/chardialogplugin.cpp | 69 + qad/widgets/plugin/chardialogplugin.h | 31 + qad/widgets/plugin/clineeditplugin.cpp | 69 + qad/widgets/plugin/clineeditplugin.h | 31 + qad/widgets/plugin/colorbuttonplugin.cpp | 69 + qad/widgets/plugin/colorbuttonplugin.h | 31 + qad/widgets/plugin/ecomboboxplugin.cpp | 69 + qad/widgets/plugin/ecomboboxplugin.h | 31 + qad/widgets/plugin/iconedlabelplugin.h | 31 + qad/widgets/plugin/lconedlabelplugin.cpp | 69 + qad/widgets/plugin/qad_widgets.cpp | 40 + qad/widgets/plugin/qad_widgets.h | 21 + qad/widgets/plugin/qcodeeditplugin.cpp | 69 + qad/widgets/plugin/qcodeeditplugin.h | 31 + qad/widgets/plugin/qipeditplugin.cpp | 69 + qad/widgets/plugin/qipeditplugin.h | 31 + qad/widgets/plugin/qpiconfigplugin.cpp | 69 + qad/widgets/plugin/qpiconfigplugin.h | 31 + qad/widgets/plugin/qpiconsoleplugin.cpp | 69 + qad/widgets/plugin/qpiconsoleplugin.h | 31 + qad/widgets/plugin/qpointeditplugin.cpp | 69 + qad/widgets/plugin/qpointeditplugin.h | 31 + qad/widgets/plugin/qrecteditplugin.cpp | 69 + qad/widgets/plugin/qrecteditplugin.h | 31 + qad/widgets/plugin/qvarianteditplugin.cpp | 69 + qad/widgets/plugin/qvarianteditplugin.h | 31 + qad/widgets/plugin/shortcutsplugin.cpp | 69 + qad/widgets/plugin/shortcutsplugin.h | 31 + qad/widgets/plugin/spinsliderplugin.cpp | 69 + qad/widgets/plugin/spinsliderplugin.h | 31 + qad/widgets/qad_widgets.qrc | 40 + qad/widgets/qcodeedit.cpp | 1003 ++++++++++ qad/widgets/qcodeedit.h | 130 ++ qad/widgets/qipedit.cpp | 82 + qad/widgets/qipedit.h | 48 + qad/widgets/qpiconfignewdialog.cpp | 77 + qad/widgets/qpiconfignewdialog.h | 40 + qad/widgets/qpiconfignewdialog.ui | 432 +++++ qad/widgets/qpiconfigvaluewidget.cpp | 98 + qad/widgets/qpiconfigvaluewidget.h | 58 + qad/widgets/qpiconfigwidget.cpp | 380 ++++ qad/widgets/qpiconfigwidget.h | 111 ++ qad/widgets/qpiconsole.cpp | 268 +++ qad/widgets/qpiconsole.h | 187 ++ qad/widgets/qpointedit.cpp | 34 + qad/widgets/qpointedit.h | 42 + qad/widgets/qrectedit.cpp | 56 + qad/widgets/qrectedit.h | 51 + qad/widgets/qvariantedit.cpp | 449 +++++ qad/widgets/qvariantedit.h | 129 ++ qad/widgets/session_manager.cpp | 123 ++ qad/widgets/session_manager.h | 99 + qad/widgets/shortcuts.cpp | 233 +++ qad/widgets/shortcuts.h | 90 + qad/widgets/spinslider.cpp | 85 + qad/widgets/spinslider.h | 102 ++ qcd_utils/CMakeLists.txt | 51 +- qcd_utils/clean.bat | 4 - qcd_utils/make_lib.bat | 1 - qcd_utils/pult/CMakeLists.txt | 17 +- touch_widgets/CMakeLists.txt | 46 - touch_widgets/clean | 4 - touch_widgets/clean.bat | 4 - touch_widgets/make_lib.bat | 1 - touch_widgets/plugin/CMakeLists.txt | 20 - touch_widgets/touch_widgets.qrc | 7 - 337 files changed, 26799 insertions(+), 251 deletions(-) create mode 100644 QtProject.cmake create mode 100644 SDKMacros.cmake create mode 100644 qad/CMakeLists.txt create mode 100644 qad/FindQAD.cmake create mode 100644 qad/QADConfig.cmake create mode 100644 qad/application/CMakeLists.txt create mode 100644 qad/application/edockwidget.cpp create mode 100644 qad/application/edockwidget.h create mode 100644 qad/application/emainwindow.cpp create mode 100644 qad/application/emainwindow.h create mode 100644 qad/application/etabwidget.cpp create mode 100644 qad/application/etabwidget.h create mode 100644 qad/application/historyview.cpp create mode 100644 qad/application/historyview.h create mode 100644 qad/application/lang/qad_application_ru.ts create mode 100644 qad/application/plugin/CMakeLists.txt create mode 100644 qad/application/plugin/edockwidgetplugin.cpp create mode 100644 qad/application/plugin/edockwidgetplugin.h create mode 100644 qad/application/plugin/emainwindowplugin.cpp create mode 100644 qad/application/plugin/emainwindowplugin.h create mode 100644 qad/application/plugin/historyviewplugin.cpp create mode 100644 qad/application/plugin/historyviewplugin.h create mode 100644 qad/application/plugin/qad_application.cpp create mode 100644 qad/application/plugin/qad_application.h create mode 100644 qad/application/qad_application.qrc create mode 100644 qad/application/qsingleapplication.cpp create mode 100644 qad/application/qsingleapplication.h create mode 100644 qad/application/ribbon.cpp create mode 100644 qad/application/ribbon.h create mode 100644 qad/blockview/CMakeLists.txt create mode 100644 qad/blockview/alignedtextitem.cpp create mode 100644 qad/blockview/alignedtextitem.h create mode 100644 qad/blockview/blockbase.cpp create mode 100644 qad/blockview/blockbase.h create mode 100644 qad/blockview/blockbusitem.cpp create mode 100644 qad/blockview/blockbusitem.h create mode 100644 qad/blockview/blockeditor.cpp create mode 100644 qad/blockview/blockeditor.h create mode 100644 qad/blockview/blockeditor.ui create mode 100644 qad/blockview/blockeditor_main.cpp create mode 100644 qad/blockview/blockitem.cpp create mode 100644 qad/blockview/blockitem.h create mode 100644 qad/blockview/blockview.cpp create mode 100644 qad/blockview/blockview.h create mode 100644 qad/blockview/blockviewwavetrace.cpp create mode 100644 qad/blockview/blockviewwavetrace.h create mode 100644 qad/blockview/drawtools.cpp create mode 100644 qad/blockview/drawtools.h create mode 100644 qad/blockview/drawtools.ui create mode 100644 qad/blockview/lang/qad_blockview_ru.qm create mode 100644 qad/blockview/lang/qad_blockview_ru.ts create mode 100644 qad/blockview/plugin/CMakeLists.txt create mode 100644 qad/blockview/plugin/blockviewplugin.cpp create mode 100644 qad/blockview/plugin/blockviewplugin.h create mode 100644 qad/blockview/plugin/qad_blockview.cpp create mode 100644 qad/blockview/plugin/qad_blockview.h create mode 100644 qad/blockview/qad_blockview.qrc create mode 100644 qad/graphic/CMakeLists.txt create mode 100644 qad/graphic/graphic.cpp create mode 100644 qad/graphic/graphic.h create mode 100644 qad/graphic/graphic.ui create mode 100644 qad/graphic/graphic_conf.cpp create mode 100644 qad/graphic/graphic_conf.h create mode 100644 qad/graphic/graphic_conf.ui create mode 100644 qad/graphic/lang/qad_graphic_ru.qm create mode 100644 qad/graphic/lang/qad_graphic_ru.ts create mode 100644 qad/graphic/plugin/CMakeLists.txt create mode 100644 qad/graphic/plugin/graphicplugin.cpp create mode 100644 qad/graphic/plugin/graphicplugin.h create mode 100644 qad/graphic/plugin/qad_graphic.cpp create mode 100644 qad/graphic/plugin/qad_graphic.h create mode 100644 qad/graphic/qad_graphic.qrc create mode 100644 qad/graphic/uglwidget.h create mode 100644 qad/graphic/uwidget.h create mode 100644 qad/icons/align-bottom-center.png create mode 100644 qad/icons/align-bottom-left.png create mode 100644 qad/icons/align-bottom-right.png create mode 100644 qad/icons/align-center-center.png create mode 100644 qad/icons/align-center-left.png create mode 100644 qad/icons/align-center-right.png create mode 100644 qad/icons/align-hor.png create mode 100644 qad/icons/align-top-center.png create mode 100644 qad/icons/align-top-left.png create mode 100644 qad/icons/align-top-right.png create mode 100644 qad/icons/align-ver.png create mode 100644 qad/icons/alpha.png create mode 100644 qad/icons/archive-extract.png create mode 100644 qad/icons/archive-insert-directory.png create mode 100644 qad/icons/archive-insert.png create mode 100644 qad/icons/arrow-down.png create mode 100644 qad/icons/arrow-up.png create mode 100644 qad/icons/axis_x.png create mode 100644 qad/icons/axis_y.png create mode 100644 qad/icons/blockview.png create mode 100644 qad/icons/border-line.png rename {touch_widgets => qad}/icons/button.png (100%) create mode 100644 qad/icons/case-sensitive.png create mode 100644 qad/icons/chardialog.png create mode 100644 qad/icons/checkbox-unchecked.png create mode 100644 qad/icons/checkbox.png create mode 100644 qad/icons/clear-history.png create mode 100644 qad/icons/clineedit.png create mode 100644 qad/icons/code-error.png create mode 100644 qad/icons/code-parents.png create mode 100644 qad/icons/code-struct.png create mode 100644 qad/icons/code-union.png create mode 100644 qad/icons/code-variable.png create mode 100644 qad/icons/code-word.png create mode 100644 qad/icons/colorbutton.png create mode 100644 qad/icons/configure.png create mode 100644 qad/icons/database.png create mode 100644 qad/icons/dialog-close.png create mode 100644 qad/icons/dialog-ok-apply.png create mode 100644 qad/icons/document-edit-.png create mode 100644 qad/icons/document-edit.png create mode 100644 qad/icons/document-new.png create mode 100644 qad/icons/document-open.png create mode 100644 qad/icons/document-open_16.png create mode 100644 qad/icons/document-print.png create mode 100644 qad/icons/document-save.png create mode 100644 qad/icons/draw-ellipse.png create mode 100644 qad/icons/draw-line.png create mode 100644 qad/icons/draw-rectangle.png create mode 100644 qad/icons/draw-text.png create mode 100644 qad/icons/ecombobox.png create mode 100644 qad/icons/edit-clear-locationbar-rtl.png create mode 100644 qad/icons/edit-clear.png create mode 100644 qad/icons/edit-copy.png create mode 100644 qad/icons/edit-delete.png create mode 100644 qad/icons/edit-find.png create mode 100644 qad/icons/edit-guides.png create mode 100644 qad/icons/edit-paste.png create mode 100644 qad/icons/edit-table-insert-row-below.png create mode 100644 qad/icons/edockwidget.png create mode 100644 qad/icons/etabwidget.png create mode 100644 qad/icons/expand_s_x.png create mode 100644 qad/icons/expand_s_y.png create mode 100644 qad/icons/expand_x.png create mode 100644 qad/icons/expand_y.png create mode 100644 qad/icons/f1.png create mode 100644 qad/icons/format-fill-color.png create mode 100644 qad/icons/format-stroke-color.png create mode 100644 qad/icons/format-text-subscript.png create mode 100644 qad/icons/games-solve.png create mode 100644 qad/icons/go-next.png create mode 100644 qad/icons/go-previous.png create mode 100644 qad/icons/graphic.png create mode 100644 qad/icons/graphics.png create mode 100644 qad/icons/historyview.png rename {touch_widgets => qad}/icons/icons.xcf (100%) create mode 100644 qad/icons/item-add.png create mode 100644 qad/icons/item.png create mode 100644 qad/icons/lastmoves.png create mode 100644 qad/icons/layer-visible-off.png create mode 100644 qad/icons/layer-visible-on.png create mode 100644 qad/icons/led_3.png create mode 100644 qad/icons/led_off.png create mode 100644 qad/icons/led_on.png create mode 100644 qad/icons/legend.png create mode 100644 qad/icons/list-add.png create mode 100644 qad/icons/list-remove.png create mode 100644 qad/icons/log_parser.png create mode 100644 qad/icons/mail.png create mode 100644 qad/icons/media-playback-pause.png create mode 100644 qad/icons/media-playback-stop.png create mode 100644 qad/icons/media-record.png create mode 100644 qad/icons/node-add.png create mode 100644 qad/icons/node.png create mode 100644 qad/icons/pause-back.png create mode 100644 qad/icons/pause-front.png create mode 100644 qad/icons/qcodeedit.png create mode 100644 qad/icons/qpiconsole.png create mode 100644 qad/icons/quickopen.png create mode 100644 qad/icons/qvariantedit.png create mode 100644 qad/icons/run-build.png create mode 100644 qad/icons/spinslider.png create mode 100644 qad/icons/sql_table.png create mode 100644 qad/icons/tools-wizard.png rename {touch_widgets => qad}/icons/touchbuttframe.png (100%) rename {touch_widgets => qad}/icons/touchbutton.png (100%) rename {touch_widgets => qad}/icons/touchslider.png (100%) create mode 100644 qad/icons/transform-move.png create mode 100644 qad/icons/variable-add.png create mode 100644 qad/icons/variable-copy.png create mode 100644 qad/icons/variable-edit.png create mode 100644 qad/icons/variable-remove.png create mode 100644 qad/icons/view-fullscreen.png create mode 100644 qad/icons/view-grid.png create mode 100644 qad/icons/view-preview.png create mode 100644 qad/icons/view-refresh.png create mode 100644 qad/icons/z-bottom.png create mode 100644 qad/icons/z-down.png create mode 100644 qad/icons/z-top.png create mode 100644 qad/icons/z-up.png create mode 100644 qad/icons/zoom-fit-best.png create mode 100644 qad/icons/zoom-in.png create mode 100644 qad/icons/zoom-out.png create mode 100644 qad/icons/zoom-range.png create mode 100644 qad/icons/zoom-rect.png create mode 100644 qad/sql_table/CMakeLists.txt create mode 100644 qad/sql_table/lang/qad_sql_table_ru.qm create mode 100644 qad/sql_table/lang/qad_sql_table_ru.ts create mode 100644 qad/sql_table/plugin/CMakeLists.txt create mode 100644 qad/sql_table/plugin/qad_sql_table.cpp create mode 100644 qad/sql_table/plugin/qad_sql_table.h create mode 100644 qad/sql_table/plugin/sql_record_plugin.cpp create mode 100644 qad/sql_table/plugin/sql_record_plugin.h create mode 100644 qad/sql_table/plugin/sql_table_plugin.cpp create mode 100644 qad/sql_table/plugin/sql_table_plugin.h create mode 100644 qad/sql_table/qad_sql_table.qrc create mode 100644 qad/sql_table/sql_record_widget.cpp create mode 100644 qad/sql_table/sql_record_widget.h create mode 100644 qad/sql_table/sql_table_widget.cpp create mode 100644 qad/sql_table/sql_table_widget.h create mode 100644 qad/sql_table/sql_table_widget.ui create mode 100644 qad/touch_widgets/CMakeLists.txt create mode 100644 qad/touch_widgets/plugin/CMakeLists.txt rename {touch_widgets => qad/touch_widgets}/plugin/touch_widgets.cpp (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touch_widgets.h (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touchbuttframeplugin.cpp (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touchbuttframeplugin.h (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touchbuttonplugin.cpp (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touchbuttonplugin.h (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touchsliderplugin.cpp (100%) rename {touch_widgets => qad/touch_widgets}/plugin/touchsliderplugin.h (100%) rename {touch_widgets => qad/touch_widgets}/touch_bar.h (100%) create mode 100644 qad/touch_widgets/touch_widgets.qrc rename {touch_widgets => qad/touch_widgets}/touchbuttframe.cpp (100%) rename {touch_widgets => qad/touch_widgets}/touchbuttframe.h (100%) rename {touch_widgets => qad/touch_widgets}/touchbutton.cpp (100%) rename {touch_widgets => qad/touch_widgets}/touchbutton.h (100%) rename {touch_widgets => qad/touch_widgets}/touchslider.cpp (100%) rename {touch_widgets => qad/touch_widgets}/touchslider.h (100%) rename {touch_widgets => qad/touch_widgets}/touchslider.ui (100%) create mode 100644 qad/utils/CMakeLists.txt create mode 100644 qad/utils/chunkstream.cpp create mode 100644 qad/utils/chunkstream.h create mode 100644 qad/utils/plugin/CMakeLists.txt create mode 100644 qad/utils/plugin/qad_utils.cpp create mode 100644 qad/utils/plugin/qad_utils.h create mode 100644 qad/utils/propertystorage.cpp create mode 100644 qad/utils/propertystorage.h create mode 100644 qad/utils/qad_types.cpp create mode 100644 qad/utils/qad_types.h create mode 100644 qad/utils/qad_utils.qrc create mode 100644 qad/utils/qpiconfig.cpp create mode 100644 qad/utils/qpiconfig.h create mode 100644 qad/utils/qpievaluator.cpp create mode 100644 qad/utils/qpievaluator.h create mode 100644 qad/widgets/CMakeLists.txt create mode 100644 qad/widgets/chardialog.cpp create mode 100644 qad/widgets/chardialog.h create mode 100644 qad/widgets/chardialog.ui create mode 100644 qad/widgets/clineedit.cpp create mode 100644 qad/widgets/clineedit.h create mode 100644 qad/widgets/colorbutton.cpp create mode 100644 qad/widgets/colorbutton.h create mode 100644 qad/widgets/ecombobox.cpp create mode 100644 qad/widgets/ecombobox.h create mode 100644 qad/widgets/iconedlabel.h create mode 100644 qad/widgets/lang/qad_widgets_ru.qm create mode 100644 qad/widgets/lang/qad_widgets_ru.ts create mode 100644 qad/widgets/lang/ru.qm create mode 100644 qad/widgets/lang/ru.ts create mode 100644 qad/widgets/plugin/CMakeLists.txt create mode 100644 qad/widgets/plugin/chardialogplugin.cpp create mode 100644 qad/widgets/plugin/chardialogplugin.h create mode 100644 qad/widgets/plugin/clineeditplugin.cpp create mode 100644 qad/widgets/plugin/clineeditplugin.h create mode 100644 qad/widgets/plugin/colorbuttonplugin.cpp create mode 100644 qad/widgets/plugin/colorbuttonplugin.h create mode 100644 qad/widgets/plugin/ecomboboxplugin.cpp create mode 100644 qad/widgets/plugin/ecomboboxplugin.h create mode 100644 qad/widgets/plugin/iconedlabelplugin.h create mode 100644 qad/widgets/plugin/lconedlabelplugin.cpp create mode 100644 qad/widgets/plugin/qad_widgets.cpp create mode 100644 qad/widgets/plugin/qad_widgets.h create mode 100644 qad/widgets/plugin/qcodeeditplugin.cpp create mode 100644 qad/widgets/plugin/qcodeeditplugin.h create mode 100644 qad/widgets/plugin/qipeditplugin.cpp create mode 100644 qad/widgets/plugin/qipeditplugin.h create mode 100644 qad/widgets/plugin/qpiconfigplugin.cpp create mode 100644 qad/widgets/plugin/qpiconfigplugin.h create mode 100644 qad/widgets/plugin/qpiconsoleplugin.cpp create mode 100644 qad/widgets/plugin/qpiconsoleplugin.h create mode 100644 qad/widgets/plugin/qpointeditplugin.cpp create mode 100644 qad/widgets/plugin/qpointeditplugin.h create mode 100644 qad/widgets/plugin/qrecteditplugin.cpp create mode 100644 qad/widgets/plugin/qrecteditplugin.h create mode 100644 qad/widgets/plugin/qvarianteditplugin.cpp create mode 100644 qad/widgets/plugin/qvarianteditplugin.h create mode 100644 qad/widgets/plugin/shortcutsplugin.cpp create mode 100644 qad/widgets/plugin/shortcutsplugin.h create mode 100644 qad/widgets/plugin/spinsliderplugin.cpp create mode 100644 qad/widgets/plugin/spinsliderplugin.h create mode 100644 qad/widgets/qad_widgets.qrc create mode 100644 qad/widgets/qcodeedit.cpp create mode 100644 qad/widgets/qcodeedit.h create mode 100644 qad/widgets/qipedit.cpp create mode 100644 qad/widgets/qipedit.h create mode 100644 qad/widgets/qpiconfignewdialog.cpp create mode 100644 qad/widgets/qpiconfignewdialog.h create mode 100644 qad/widgets/qpiconfignewdialog.ui create mode 100644 qad/widgets/qpiconfigvaluewidget.cpp create mode 100644 qad/widgets/qpiconfigvaluewidget.h create mode 100644 qad/widgets/qpiconfigwidget.cpp create mode 100644 qad/widgets/qpiconfigwidget.h create mode 100644 qad/widgets/qpiconsole.cpp create mode 100644 qad/widgets/qpiconsole.h create mode 100644 qad/widgets/qpointedit.cpp create mode 100644 qad/widgets/qpointedit.h create mode 100644 qad/widgets/qrectedit.cpp create mode 100644 qad/widgets/qrectedit.h create mode 100644 qad/widgets/qvariantedit.cpp create mode 100644 qad/widgets/qvariantedit.h create mode 100644 qad/widgets/session_manager.cpp create mode 100644 qad/widgets/session_manager.h create mode 100644 qad/widgets/shortcuts.cpp create mode 100644 qad/widgets/shortcuts.h create mode 100644 qad/widgets/spinslider.cpp create mode 100644 qad/widgets/spinslider.h delete mode 100644 qcd_utils/clean.bat delete mode 100644 qcd_utils/make_lib.bat delete mode 100644 touch_widgets/CMakeLists.txt delete mode 100644 touch_widgets/clean delete mode 100644 touch_widgets/clean.bat delete mode 100644 touch_widgets/make_lib.bat delete mode 100644 touch_widgets/plugin/CMakeLists.txt delete mode 100644 touch_widgets/touch_widgets.qrc diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c800a8..ca91c06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,14 +5,31 @@ if(MINGW) find_package(MinGW REQUIRED) endif() set(LIB 1) +set(LIBPROJECT 1) +set(PULT 1) set(USB 1) set(ICU 1) set(CRYPT 1) set(FFTW 1) -set(LIBPROJECT 1) set(PIP_LIBRARY pip) set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io" "console" "math" "code" "geo") set(PIP_INCLUDES) + +if (LIB) + if (WIN32) + set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) + else () + if(APPLE) + set(CMAKE_INSTALL_PREFIX /usr/local) + else() + set(CMAKE_INSTALL_PREFIX /usr) + endif() + endif () + message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") +else () + message(STATUS "Install to local \"bin\"") +endif () + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") foreach(F ${PIP_FOLDERS}) @@ -24,17 +41,21 @@ if(WIN32) set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}/pip") endif() -set(LIST_LIBS pip qad_utils qad_widgets qad_application qad_blockview qad_graphic qad_sql_table piqt cd_utils qcd_utils kx_utils piqt_utils touch_widgets qglview) -#set(LIST_LIBS pip) -foreach(L ${LIST_LIBS}) - add_subdirectory(${L}) - include_directories(${L}) -endforeach(L) +set(QAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/qad) + +add_subdirectory(pip) +add_subdirectory(qad) +set(_DIRS piqt piqt_utils cd_utils qcd_utils) +foreach(_D ${_DIRS}) + include_directories(${_D}) + add_subdirectory(${_D}) +endforeach(_D) if(WIN32) get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH) foreach(PIP_LT ${PIP_LIBS_TARGETS}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pip/lib${PIP_LT}.dll" DESTINATION ${QTDIR}) endforeach() - install(FILES "FindMinGW.cmake" DESTINATION ${CMAKE_ROOT}/Modules) + set(CMAKES "FindMinGW.cmake" "QtProject.cmake") + install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) endif() diff --git a/FindMinGW.cmake b/FindMinGW.cmake index a796fb7..c0c60dc 100644 --- a/FindMinGW.cmake +++ b/FindMinGW.cmake @@ -5,7 +5,7 @@ if(${MINGW}) find_path(MINGW_INCLUDE windows.h PATHS - EVN INCLUDE + ENV INCLUDE ${MINGW_DIR} ${MINGW_DIR}/i686-w64-mingw32 ${MINGW_DIR}/x86_64-w64-mingw32 @@ -15,8 +15,8 @@ if(${MINGW}) #if(NOT ${MINGW_INCLUDE}) MINGW_INCLUDE = ${MINGW_DIR}/include find_library(MINGW_LIB m HINTS ${MINGW_BIN}/../lib ${MINGW_INCLUDE}/../lib) get_filename_component(MINGW_LIB ${MINGW_LIB} PATH) - message(STATUS "Find MinGW binary path = ${MINGW_BIN}") - message(STATUS "Find MinGW include path = ${MINGW_INCLUDE}") - message(STATUS "Find MinGW library path = ${MINGW_LIB}") + message(STATUS "Found MinGW binary path = ${MINGW_BIN}") + message(STATUS "Found MinGW include path = ${MINGW_INCLUDE}") + message(STATUS "Found MinGW library path = ${MINGW_LIB}") endif() endif(${MINGW}) diff --git a/QtProject.cmake b/QtProject.cmake new file mode 100644 index 0000000..43c4e64 --- /dev/null +++ b/QtProject.cmake @@ -0,0 +1,30 @@ +set(QTVERSION 4) +find_package(Qt${QTVERSION} REQUIRED) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES}) + +macro(qt_project NAME _TYPE _LIBS _H_OUT _CPP_OUT) + project(${NAME}) + find_package(Qt4 REQUIRED) + include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES}) + file(GLOB ${_H_OUT} "./*.h") + file(GLOB CPPS "./*.cpp") + file(GLOB UIS "./*.ui") + file(GLOB RES "./*.qrc") + qt4_wrap_ui(CUIS ${UIS}) + qt4_wrap_cpp(CMOCS ${${_H_OUT}} OPTIONS -nw) + qt4_add_resources(CRES ${RES}) + set(${_CPP_OUT} ${CPPS}) + list(APPEND ${_CPP_OUT} ${CUIS}) + list(APPEND ${_CPP_OUT} ${CMOCS}) + list(APPEND ${_CPP_OUT} ${CRES}) + if ("_${_TYPE}" STREQUAL "_EXE") + add_executable(${PROJECT_NAME} ${${_H_OUT}} ${${_CPP_OUT}}) + else() + if ("_${_TYPE}" STREQUAL "_LIB") + add_library(${PROJECT_NAME} SHARED ${${_H_OUT}} ${${_CPP_OUT}}) + else() + message(FATAL_ERROR "You must specify \"EXE\" ot \"LIB\" by second argument of \"qt_project()\"!") + endif() + endif() + target_link_libraries(${PROJECT_NAME} ${_LIBS}) +endmacro() diff --git a/SDKMacros.cmake b/SDKMacros.cmake new file mode 100644 index 0000000..9ff3bbc --- /dev/null +++ b/SDKMacros.cmake @@ -0,0 +1,22 @@ + +macro(sdk_install _DIR _TARGET _H_FILES) + if (LIB) + if (WIN32) + if (NOT _H_FILES STREQUAL "") + #message("HFILES ${_H_FILES}") + install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR}) + endif() + install(TARGETS ${_TARGET} DESTINATION ${MINGW_LIB}) + install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN}) + get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH) + install(TARGETS ${_TARGET} DESTINATION ${QTDIR}) + else () + if (NOT _H_FILES STREQUAL "") + install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${_DIR}) + endif() + install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) + endif () + else () + install(TARGETS ${_TARGET} DESTINATION bin) + endif () +endmacro() diff --git a/cd_utils/CMakeLists.txt b/cd_utils/CMakeLists.txt index 81d6422..7a0e8f5 100644 --- a/cd_utils/CMakeLists.txt +++ b/cd_utils/CMakeLists.txt @@ -7,7 +7,6 @@ if (MINGW) find_package(MinGW REQUIRED) endif() include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES}) -set(PULT_NAME "cd_pult") option(LIB "System install" 1) option(DEBUG "Build with -g3" 0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall") @@ -28,23 +27,7 @@ target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY}) add_executable(cdutilstest "cdutilstest.cpp" "cdtest.h") target_link_libraries(cdutilstest ${PIP_LIBRARY} ${PROJECT_NAME}) - if (LIB) - if (WIN32) - set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) - install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN}) - else () - if(APPLE) - set(CMAKE_INSTALL_PREFIX /usr/local) - else() - set(CMAKE_INSTALL_PREFIX /usr) - endif() - install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) - install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) - endif () - message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") -else () - install(TARGETS ${PROJECT_NAME} DESTINATION bin) - message(STATUS "Install to local \"bin\"") +if (LIB) + include(SDKMacros) + sdk_install("" "${PROJECT_NAME}" "${HDRS_UTILS}") endif () diff --git a/make_libs.bat b/make_libs.bat index b1a56bf..2f95771 100644 --- a/make_libs.bat +++ b/make_libs.bat @@ -1,3 +1,3 @@ @echo off mkdir ../libs_build_win -cd ../libs_build_win && cmake_mgw ../libs && cmake_mgw ../libs && make install -j8 && cd ../libs && pause +cd ../libs_build_win && cmake_mgw ../libs && make install -j8 && cd ../libs && pause diff --git a/piqt/CMakeLists.txt b/piqt/CMakeLists.txt index 05adae8..c615ad8 100644 --- a/piqt/CMakeLists.txt +++ b/piqt/CMakeLists.txt @@ -1,41 +1,13 @@ project(piqt) cmake_minimum_required(VERSION 2.6) -option(LIB "System install" 0) -find_package(Qt4 REQUIRED) -if(LIBPROJECT) - include(PIPMacros) -else() +if(NOT LIBPROJECT) find_package(PIP REQUIRED) endif() -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES} ${QT_INCLUDES}) -file(GLOB HDRS "*.h") -file(GLOB CPPS "*.cpp") -if(DEFINED ENV{QNX_HOST}) - add_library(${PROJECT_NAME} STATIC ${CPPS}) -else() - add_library(${PROJECT_NAME} SHARED ${CPPS}) -endif() -set(LIBS ${QT_QTCORE_LIBRARY} ${PIP_LIBRARY} qad_utils) -target_link_libraries(${PROJECT_NAME} ${LIBS}) -if(LIB) - if(WIN32) - set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) - install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN}) - get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH) - install(TARGETS ${PROJECT_NAME} DESTINATION ${QTDIR}) - else() - if(APPLE) - set(CMAKE_INSTALL_PREFIX /usr/local) - else() - set(CMAKE_INSTALL_PREFIX /usr) - endif() - install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) - install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) - endif() - message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") -else() - install(TARGETS ${PROJECT_NAME} DESTINATION bin) - message(STATUS "Install to local \"bin\"") +find_package(QAD REQUIRED) +include_directories(${PIP_INCLUDES} ${QAD_INCLUDES}) +set(LIBS ${PIP_LIBRARY} ${QAD_UTILS_LIBRARY}) +qt_project(${PROJECT_NAME} "LIB" "${LIBS}" H CPP) +if(LIBPROJECT) + include(SDKMacros) + sdk_install("" "${PROJECT_NAME}" "${H}") endif() diff --git a/piqt_utils/CMakeLists.txt b/piqt_utils/CMakeLists.txt index 077d298..3efaefc 100644 --- a/piqt_utils/CMakeLists.txt +++ b/piqt_utils/CMakeLists.txt @@ -3,21 +3,22 @@ cmake_minimum_required(VERSION 2.6) if(MINGW) find_package(MinGW REQUIRED) endif() -find_package(Qt4 REQUIRED) -if(LIBPROJECT) - include(PIPMacros) -else() - find_package(PIP REQUIRED) -endif() -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES} ${QT_INCLUDES}) option(LIB "System install" 0) option(DEBUG "Build with -g3" 0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall") if(DEBUG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") endif() -set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${PIP_LIBRARY} qad_widgets qad_utils qad_blockview) +if(LIBPROJECT) + include(PIPMacros) + include(SDKMacros) +else() + find_package(PIP REQUIRED) +endif() +find_package(QAD REQUIRED) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES} ${PIP_INCLUDES} ${QAD_INCLUDES}) pip_code_model(CCM "../pip/src_main/io/piiodevice.h" "../pip/src_main/io/pipacketextractor.h" OPTIONS "-DPIP_EXPORT" "-Es") +set(LIBS ${QAD_WIDGETS_LIBRARY} ${QAD_UTILS_LIBRARY} ${QAD_BLOCKVIEW_LIBRARY} ${PIP_LIBRARY}) #message(STATUS "pip_code_model for iodevice = ${CCM}") #message(STATUS "pip_INCLUDES = ${PIP_INCLUDES}") file(GLOB CPPS_UTILS "piqt_*.cpp") @@ -58,29 +59,31 @@ if (NOT DEFINED ENV{QNX_HOST}) add_executable(piconnectionedit "piconnedit_main.cpp" ${RESS}) target_link_libraries(piconnectionedit ${LIBS} ${PROJECT_NAME}) endif() -if(LIB) - if(WIN32) - set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) - install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN}) - get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH) - install(TARGETS ${PROJECT_NAME} DESTINATION ${QTDIR}) - else() - if(APPLE) - set(CMAKE_INSTALL_PREFIX /usr/local) - else() - set(CMAKE_INSTALL_PREFIX /usr) - endif() - install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) - install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) - endif() - message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") -else() - install(TARGETS ${PROJECT_NAME} DESTINATION bin) - message(STATUS "Install to local \"bin\"") -endif() -if(NOT DEFINED ENV{QNX_HOST}) - install(TARGETS pidumper DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) - install(TARGETS piconnectionedit DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -endif() +set(_TARGETS ${PROJECT_NAME} pidumper piconnectionedit) +sdk_install("" "${TARGETS}" "${HDRS_UTILS}") +#if(LIB) +# if(WIN32) +# set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) +# install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE}) +# install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB}) +# install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN}) +# get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH) +# install(TARGETS ${PROJECT_NAME} DESTINATION ${QTDIR}) +# else() +# if(APPLE) +# set(CMAKE_INSTALL_PREFIX /usr/local) +# else() +# set(CMAKE_INSTALL_PREFIX /usr) +# endif() +# install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) +# install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +# endif() +# message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") +#else() +# install(TARGETS ${PROJECT_NAME} DESTINATION bin) +# message(STATUS "Install to local \"bin\"") +#endif() +#if(NOT DEFINED ENV{QNX_HOST}) +# install(TARGETS pidumper DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +# install(TARGETS piconnectionedit DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +#endif() diff --git a/qad/CMakeLists.txt b/qad/CMakeLists.txt new file mode 100644 index 0000000..74e33ba --- /dev/null +++ b/qad/CMakeLists.txt @@ -0,0 +1,72 @@ +project(qad) +cmake_minimum_required(VERSION 2.6) +include(../SDKMacros.cmake) +include(../QtProject.cmake) +find_package(OpenGL REQUIRED) +if (MINGW) + find_package(MinGW REQUIRED) +endif() +#include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES}) +option(LIB "System install" 0) +option(DEBUG "Build with -g3" 0) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall") +if (DEBUG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") +endif () +#set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} qad_widgets qad_utils) +if (NOT LIBPROJECT) + if (LIB) + if (WIN32) + set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) + else () + if(APPLE) + set(CMAKE_INSTALL_PREFIX /usr/local) + else() + set(CMAKE_INSTALL_PREFIX /usr) + endif() + endif () + message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") + else () + message(STATUS "Install to local \"bin\"") + endif () +endif() +set(CMAKES "FindQAD.cmake") +install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) + +macro(qad_install _TARGET _H_FILES) + sdk_install(qad "${_TARGET}" "${_H_FILES}") +endmacro() + +macro(qad_plugin NAME _LIBS) + project(qad_${NAME}_plugin) + include_directories("..") + set(LIBS ${_${NAME}_LIBS} qad_${NAME} "${_LIBS}") + #message(${_${NAME}_PLUGIN_LIBS}) + add_definitions(-DQT_PLUGIN) + add_definitions(-DQT_NO_DEBUG) + add_definitions(-DQT_SHARED) + add_definitions(-DQDESIGNER_EXPORT_WIDGETS) + file(GLOB PMOCS "./*.h") + file(GLOB PCPPS "./*.cpp") + qt4_wrap_cpp(PCMOCS ${PMOCS} OPTIONS -nw) + add_library(${PROJECT_NAME} SHARED ${PCMOCS} ${PCPPS} ${PMOCS}) + target_link_libraries(${PROJECT_NAME} ${LIBS} ${QT_QTDESIGNER_LIBRARY}) + install(TARGETS ${PROJECT_NAME} DESTINATION ${QT_PLUGINS_DIR}/designer) +endmacro() + +macro(qad_project NAME _LIBS) + qt_project(qad_${NAME} "LIB" "${_LIBS}" _H _CPP) + message(STATUS "Building ${PROJECT_NAME}") + qad_install(${PROJECT_NAME} "${_H}") + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin") + set(_${NAME}_PLUGIN_LIBS "${_LIBS}") + add_subdirectory(plugin) + endif() +endmacro() + +set(DIRS utils widgets application blockview graphic sql_table touch_widgets) +foreach(D ${DIRS}) + include_directories(${D}) + add_subdirectory(${D}) +endforeach(D) + diff --git a/qad/FindQAD.cmake b/qad/FindQAD.cmake new file mode 100644 index 0000000..c393515 --- /dev/null +++ b/qad/FindQAD.cmake @@ -0,0 +1,31 @@ +include(QtProject) +set(_SEARCH_DIR) +if(WIN32) + find_package(MinGW REQUIRED) + set(_SEARCH_DIR ${MINGW_LIB}) + set(QAD_INCLUDES ${MINGW_INCLUDE}/qad) +else() + set(_DIR_ "/usr") + if(APPLE) + set(_DIR_ "/usr/local") + endif() + set(_SEARCH_DIR ${_DIR_}/lib/) + set(QAD_INCLUDES ${_DIR_}/include/qad) +endif() +set(_QAD_LIBS utils widgets application blockview graphic sql_table touch_widgets) +if(LIBPROJECT) + set(QAD_INCLUDES) +endif() +foreach(_Q ${_QAD_LIBS}) + string(TOUPPER ${_Q} _QU) + if(LIBPROJECT) + set(QAD_${_QU}_LIBRARY qad_${_Q}) + list(APPEND QAD_INCLUDES ${QAD_DIR}/${_Q}) + else() + find_library(QAD_${_QU}_LIBRARY qad_${_Q} ${_SEARCH_DIR}) + endif() + #message(STATUS "Library ${_Q} (${_QU}) -> ${QAD_${_QU}_LIBRARY} found in ${_SEARCH_DIR}") +endforeach() +if(NOT LIBPROJECT) + message(STATUS "Found QAD") +endif() diff --git a/qad/QADConfig.cmake b/qad/QADConfig.cmake new file mode 100644 index 0000000..b80e857 --- /dev/null +++ b/qad/QADConfig.cmake @@ -0,0 +1 @@ +include(${QAD_DIR}/FindQAD.cmake) diff --git a/qad/application/CMakeLists.txt b/qad/application/CMakeLists.txt new file mode 100644 index 0000000..72e9256 --- /dev/null +++ b/qad/application/CMakeLists.txt @@ -0,0 +1,2 @@ +set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} qad_widgets) +qad_project(application "${LIBS}") diff --git a/qad/application/edockwidget.cpp b/qad/application/edockwidget.cpp new file mode 100644 index 0000000..7bca8f5 --- /dev/null +++ b/qad/application/edockwidget.cpp @@ -0,0 +1,51 @@ +#include "edockwidget.h" +#include + + +void EDockWidget::setFeatures(QDockWidget::DockWidgetFeatures features) { + btn_dock->setVisible(features.testFlag(DockWidgetFloatable)); + btn_hide->setVisible(features.testFlag(DockWidgetClosable)); + QDockWidget::setFeatures(features); +} + + +void EDockWidget::init() { + header = new QFrame(); + header->setFrameShape(QFrame::StyledPanel); + QBoxLayout * lay = new QBoxLayout(features().testFlag(QDockWidget::DockWidgetVerticalTitleBar) ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); + lay->setContentsMargins(2, 2, 2, 2); + lay->setSpacing(2); + lbl_icon = new QLabel(); + lbl_icon->setPixmap(windowIcon().pixmap(QSize(24, 24))); + lbl_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + lbl_title = new QLabel(windowTitle()); + lbl_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + btn_dock = new QToolButton(); + //btn_dock->setIconSize(QSize(16, 16)); + int btn_wh = style()->pixelMetric(QStyle::PM_SmallIconSize); + QSize icon_size(btn_wh, btn_wh); + btn_wh += 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, 0, this); + QSize btn_size(btn_wh, btn_wh); + btn_dock->setIcon(style()->standardIcon(QStyle::SP_TitleBarNormalButton)); + btn_dock->setIconSize(icon_size); + btn_dock->setFixedSize(btn_size); + btn_dock->setAutoRaise(true); + btn_dock->setFocusPolicy(Qt::NoFocus); + btn_dock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + btn_hide = new QToolButton(); + //btn_hide->setIconSize(QSize(16, 16)); + btn_hide->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton)); + btn_hide->setIconSize(icon_size); + btn_hide->setFixedSize(btn_size); + btn_hide->setAutoRaise(true); + btn_hide->setFocusPolicy(Qt::NoFocus); + btn_hide->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + connect(btn_dock, SIGNAL(clicked(bool)), this, SLOT(dockClicked())); + connect(btn_hide, SIGNAL(clicked(bool)), this, SLOT(hide())); + lay->addWidget(lbl_icon); + lay->addWidget(lbl_title); + lay->addWidget(btn_dock); + lay->addWidget(btn_hide); + header->setLayout(lay); + setTitleBarWidget(header); +} diff --git a/qad/application/edockwidget.h b/qad/application/edockwidget.h new file mode 100644 index 0000000..cdf2501 --- /dev/null +++ b/qad/application/edockwidget.h @@ -0,0 +1,37 @@ +#ifndef EDOCKWIDGET_H +#define EDOCKWIDGET_H + +#include +#include +#include +#include +#include +#include +#include + + +class EDockWidget: public QDockWidget +{ + Q_OBJECT +public: + explicit EDockWidget(const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0): QDockWidget(title, parent, flags) {init();} + explicit EDockWidget(QWidget * parent = 0, Qt::WindowFlags flags = 0): QDockWidget(parent, flags) {init();} + ~EDockWidget() {delete btn_hide; delete btn_dock; delete lbl_title; delete lbl_icon; delete header;} + + void setFeatures(QDockWidget::DockWidgetFeatures features); + void setWindowTitle(const QString & title) {lbl_title->setText(title); QDockWidget::setWindowTitle(title);} + void setWindowIcon(const QIcon & icon) {lbl_icon->setPixmap(icon.pixmap(QSize(24, 24))); QDockWidget::setWindowIcon(icon);} + +private: + void init(); + + QFrame * header; + QLabel * lbl_title, * lbl_icon; + QToolButton * btn_hide, * btn_dock; + +private slots: + void dockClicked() {setFloating(!isFloating());} + +}; + +#endif // EDOCKWIDGET_H diff --git a/qad/application/emainwindow.cpp b/qad/application/emainwindow.cpp new file mode 100644 index 0000000..030a67f --- /dev/null +++ b/qad/application/emainwindow.cpp @@ -0,0 +1,333 @@ +/* + Peri4 Paint + Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "emainwindow.h" +#include +#include +#include + + +EMainWindow::EMainWindow(QWidget * parent): QMainWindow(parent), action_show_all_tools(this), action_hide_all_tools(this), +action_show_all_docks(this), action_hide_all_docks(this), first_show(true) { + qRegisterMetaType("Qt::DockWidgetArea"); + action_show_all_tools.setText(trUtf8("Show all")); + action_show_all_docks.setText(trUtf8("Show all")); + action_hide_all_tools.setText(trUtf8("Hide all")); + action_hide_all_docks.setText(trUtf8("Hide all")); + action_show_all_tools.setIcon(QIcon(":/icons/layer-visible-on.png")); + action_show_all_docks.setIcon(QIcon(":/icons/layer-visible-on.png")); + action_hide_all_tools.setIcon(QIcon(":/icons/layer-visible-off.png")); + action_hide_all_docks.setIcon(QIcon(":/icons/layer-visible-off.png")); + setChanged(false); + initMenus(); + tid = startTimer(200); +} + + +EMainWindow::~EMainWindow() { + saveSession(); +} + + +void EMainWindow::showEvent(QShowEvent * e) { + QWidget::showEvent(e); + initMenus(); + if (!first_show) return; + first_show = false; + QList docks(findChildren()); + foreach (QDockWidget * d, docks) { + connect(d, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(changedDock())); + connect(d, SIGNAL(topLevelChanged(bool)), this, SLOT(changedDock())); + } + changedDock(); +} + + +void EMainWindow::closeEvent(QCloseEvent * e) { + if (!checkSave()) e->ignore(); +} + + +bool EMainWindow::eventFilter(QObject * o, QEvent * e) { + //qDebug() << o << e; + if (tbars.contains((QTabBar*)o) && e->type() == QEvent::MouseButtonDblClick) { + int tab = ((QTabBar*)o)->tabAt(((QMouseEvent * )e)->pos()); + if (tab >= 0) { + QDockWidget * dock = (QDockWidget * )(((QTabBar*)o)->tabData(tab).toULongLong()); + if (dock != 0) { + dock->setFloating(true); + } + } + } + if (e->type() == QEvent::Show || e->type() == QEvent::Hide || e->type() == QEvent::ChildAdded || e->type() == QEvent::ChildRemoved || e->type() == QEvent::MouseButtonPress) { + if (tbars.contains((QTabBar*)o) || tdocks.contains((QDockWidget*)o)) { + if (e->type() == QEvent::MouseButtonPress) { + if (((QMouseEvent*)e)->button() == Qt::RightButton) { + bool popup = tbars.contains((QTabBar*)o); + if (tdocks.contains((QDockWidget*)o)) + popup = popup || ((QDockWidget*)o)->titleBarWidget()->geometry().contains(((QMouseEvent*)e)->pos()); + if (popup) { + createPopupMenu()->popup(((QMouseEvent*)e)->globalPos()); + return true; + } + } + } + if (e->type() == QEvent::Show || e->type() == QEvent::Hide /*|| e->type() == QEvent::ChildAdded || e->type() == QEvent::ChildRemoved*/) { + //qDebug() << "filter"; + //QMetaObject::invokeMethod(this, "changedDock", Qt::QueuedConnection); + changedDock(); + } + } + } + return QMainWindow::eventFilter(o, e); +} + + +void EMainWindow::timerEvent(QTimerEvent * e) { + if (e->timerId() == tid) { + changedDock(); + return; + } + QMainWindow::timerEvent(e); +} + + +QMenu * EMainWindow::createPopupMenu() { + QMenu * menuPopup = new QMenu; + QWidgetAction * wa; + QLabel * lbl; + QAction * a; + QFont f; + f.setBold(true); + // Toolbars + QList tools = findChildren(); + if (!tools.isEmpty()) { + wa = new QWidgetAction(menuPopup); + lbl = new QLabel(); + lbl->setFrameShape(QFrame::StyledPanel); + lbl->setFrameShadow(QFrame::Sunken); + lbl->setText(trUtf8("Toolbars")); + lbl->setFont(f); + lbl->setAlignment(Qt::AlignCenter); + wa->setDefaultWidget(lbl); + menuPopup->addAction(wa); + foreach (QToolBar * i, tools) { + if (i->property("ribbon").toBool()) continue; + a = new QAction(i->windowTitle(), menuPopup); + a->setCheckable(true); + a->setChecked(!i->isHidden()); + a->setIcon(i->windowIcon()); + connect(a, SIGNAL(toggled(bool)), i, SLOT(setVisible(bool))); + menuPopup->addAction(a); + }; + menuPopup->addSeparator(); + menuPopup->addAction(&action_show_all_tools); + menuPopup->addAction(&action_hide_all_tools); + } + // Docks + QList docks = findChildren(); + if (!docks.isEmpty()) { + wa = new QWidgetAction(menuPopup); + lbl = new QLabel(); + lbl->setFrameShape(QFrame::StyledPanel); + lbl->setFrameShadow(QFrame::Sunken); + lbl->setText(trUtf8("Docks")); + lbl->setFont(f); + lbl->setAlignment(Qt::AlignCenter); + wa->setDefaultWidget(lbl); + menuPopup->addAction(wa); + foreach (QDockWidget * i, docks) { + if (i->property("ribbon").toBool()) continue; + a = new QAction(i->windowTitle(), menuPopup); + a->setCheckable(true); + a->setChecked(!i->isHidden()); + a->setIcon(i->windowIcon()); + connect(a, SIGNAL(toggled(bool)), i, SLOT(setVisible(bool))); + menuPopup->addAction(a); + }; + menuPopup->addSeparator(); + menuPopup->addAction(&action_show_all_docks); + menuPopup->addAction(&action_hide_all_docks); + } + return menuPopup; +} + + +void EMainWindow::initMenus() { + action_show_all_tools.disconnect(); + action_hide_all_tools.disconnect(); + action_show_all_docks.disconnect(); + action_hide_all_docks.disconnect(); + + QList tools = findChildren(); + foreach (QToolBar * i, tools) { + if (i->property("ribbon").toBool()) continue; + i->toggleViewAction()->setIcon(i->windowIcon()); + connect(&action_show_all_tools, SIGNAL(triggered(bool)), i, SLOT(show())); + connect(&action_hide_all_tools, SIGNAL(triggered(bool)), i, SLOT(hide())); + } + + QList docks = findChildren(); + foreach (QDockWidget * i, docks) { + if (i->property("ribbon").toBool()) continue; + i->toggleViewAction()->setIcon(i->windowIcon()); + connect(&action_show_all_docks, SIGNAL(triggered(bool)), i, SLOT(show())); + connect(&action_hide_all_docks, SIGNAL(triggered(bool)), i, SLOT(hide())); + } + + QList actions = findChildren(); + foreach (QAction * i, actions) + i->setIconVisibleInMenu(true); + addActions(actions); +} + + +void EMainWindow::initSession() { + connect(&session, SIGNAL(loading(QPIConfig & )), this, SLOT(sessionLoading(QPIConfig & ))); + connect(&session, SIGNAL(saving(QPIConfig & )), this, SLOT(sessionSaving(QPIConfig & ))); + session.addEntry("EMainWindow", this); +} + + +void EMainWindow::saveSession() { + session.save(); +} + + +void EMainWindow::loadSession() { + session.load(); +} + + +bool EMainWindow::checkSave() { + if (!isWindowModified()) return true; + return saveFile(true); +} + + +void EMainWindow::changedDock() { + if (isHidden()) return; + QList tabs(findChildren()); + QList docks = findChildren(); + QSet docks_tabs; + QDockWidget * dock; +// qDebug() << "### change"; + foreach (QTabBar * t, tabs) { + if (!t->objectName().isEmpty() || t->isHidden()) continue; + if (!tbars.contains(t)) { + tbars << t; + connect(t, SIGNAL(tabCloseRequested(int)), this, SLOT(closeDock(int))); + t->installEventFilter(this); + t->setIconSize(dockTabsIconSIze()); + t->setTabsClosable(true); + } +// qDebug() << "tab" << t << t->count(); + for (int i = 0; i < t->count(); ++i) { + dock = (QDockWidget * )t->tabData(i).toULongLong(); + //qDebug() << i << t->tabData(i); + if (dock == 0) continue; + t->setTabIcon(i, dock->windowIcon()); + docks_tabs << dock; + } + } + + foreach (QDockWidget * d, docks) { + if (d->titleBarWidget() == 0) continue; + QWidget * ctb = d->titleBarWidget(); + if (!d->property("__titleWidget").isValid()) { + d->setProperty("__titleWidget", qulonglong(ctb)); + QWidget * ntb = new QWidget(); + int m = style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin); + ntb->setLayout(new QBoxLayout(QBoxLayout::BottomToTop)); + ntb->layout()->setContentsMargins(m, m, 0, 0); + d->setProperty("__titleEmptyWidget", qulonglong(ntb)); + } + if (!tdocks.contains(d)) { + tdocks << d; +// qDebug() << "connect" << d; +// connect(d, SIGNAL(destroyed(QObject*)), this, SLOT(changedDockClose(QObject*)), Qt::UniqueConnection); + d->installEventFilter(this); + } + //d->titleBarWidget()->setHidden(docks_tabs.contains(d)); + if (tabifiedDockWidgets(d).isEmpty()) { + if (d->titleBarWidget() != (QWidget * )(d->property("__titleWidget").toULongLong())) + d->setTitleBarWidget((QWidget * )(d->property("__titleWidget").toULongLong())); + } else { + if (d->titleBarWidget() != (QWidget * )(d->property("__titleEmptyWidget").toULongLong())) { + d->setTitleBarWidget((QWidget * )(d->property("__titleEmptyWidget").toULongLong())); + d->layout()->setContentsMargins(0, 20, 0, 0); + } + } + } +} + + +//void EMainWindow::changedDockClose(QObject * dock) { +// qDebug() << "changedDockClose" << dock; +// if (!dock) return; +// foreach (QTabBar * t, tbars) { +// for (int i = 0; i < t->count(); ++i) +// if (t->tabData(i).toULongLong() == (qulonglong)dock) { +// t->removeTab(i); +// break; +// } +// } +//} + + +void EMainWindow::closeDock(int index) { + QDockWidget * dock = (QDockWidget * )((QTabBar*)sender())->tabData(index).toULongLong(); + if (dock == 0) return; + dock->close(); +} + + +void EMainWindow::newFile() { + if (!checkSave()) return; + reset(true); + setWindowModified(false); +} + + +void EMainWindow::openFile() { + if (!checkSave()) return; + QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select file to open"), file_name, loadFilter()); + if (ret.isEmpty()) return; + load(ret); +} + + +bool EMainWindow::saveFile(bool ask) { + if (ask) { + int ret = QMessageBox::question(this, windowTitle(), trUtf8("Save changes%1?").arg(!file_name.isEmpty() ? (trUtf8(" in") + " \"" + file_name + "\"") : ""), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save); + if (ret == QMessageBox::Cancel) return false; + if (ret == QMessageBox::Save) return saveFile(); + return true; + } + if (file_name.isEmpty()) return saveAsFile(); + save(file_name); + return true; +} + + +bool EMainWindow::saveAsFile() { + QString ret = QFileDialog::getSaveFileName(this, trUtf8("Select file to save"), file_name, saveFilter()); + if (ret.isEmpty()) return false; + save(ret); + return true; +} diff --git a/qad/application/emainwindow.h b/qad/application/emainwindow.h new file mode 100644 index 0000000..0d235a2 --- /dev/null +++ b/qad/application/emainwindow.h @@ -0,0 +1,109 @@ +#ifndef EMAINWINDOW_H +#define EMAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "session_manager.h" +#include "ribbon.h" + +class UAction: public QAction { + Q_OBJECT +public: + UAction(int ind,const QString & text, QObject * parent): QAction(text, parent) { + index = ind; + connect(this, SIGNAL(triggered()), this, SLOT(triggered())); + connect(this, SIGNAL(toggled(bool)), this, SLOT(toggled(bool))); + connect(this, SIGNAL(hovered()), this, SLOT(hovered())); + } + UAction(int ind, const QIcon & icon, const QString & text, QObject * parent): QAction(icon, text, parent) { + index = ind; + connect(this, SIGNAL(triggered()), this, SLOT(triggered())); + connect(this, SIGNAL(toggled(bool)), this, SLOT(toggled(bool))); + connect(this, SIGNAL(hovered()), this, SLOT(hovered())); + } +public slots: + void show() {setVisible(true);} + void hide() {setVisible(false);} + void setCheckedTrue() {setChecked(true);} + void setCheckedFalse() {setChecked(false);} +private: + int index; +private slots: + void triggered() {emit itriggered(this, index);} + void toggled(bool t) {emit itoggled(t, this, index);} + void hovered() {emit ihovered(this);} +signals: + void itriggered(QAction *, int); + void itoggled(bool, QAction *, int); + void ihovered(QAction * action); +}; + + +class EMainWindow: public QMainWindow +{ + Q_OBJECT +public: + EMainWindow(QWidget * parent = 0); + ~EMainWindow(); + + virtual void reset(bool full = false) {} + virtual bool load(const QString & path) {return true;} + virtual bool save(const QString & path) {return true;} + + void addSeparator() {} + +protected: + // Qt`s overloaded + void showEvent(QShowEvent * ); + void closeEvent(QCloseEvent * ); + bool eventFilter(QObject * o, QEvent * e); + void timerEvent(QTimerEvent * e); + QMenu * createPopupMenu(); + + void init(const QString & config) {session.setFile(config); initMenus(); initSession(); loadSession();} + void initMenus(); + void initSession(); + virtual void saveSession(); + virtual void loadSession(); + virtual QSize dockTabsIconSIze() const {return iconSize();} + virtual QString loadFilter() {return "All files(*)";} + virtual QString saveFilter() {return "All files(*)";} + + bool checkSave(); + void setChanged(bool yes = true) {isChanged = yes; setWindowModified(yes);} + + QAction action_show_all_tools, action_hide_all_tools, action_show_all_docks, action_hide_all_docks; + QString file_name, title_src; + QList tbars; + QList tdocks; + SessionManager session; + bool isChanged, first_show; + int tid; + +private slots: + void changedDock(); +// void changedDockClose(QObject * dock); + void closeDock(int index); + virtual void sessionLoading(QPIConfig & conf) {} + virtual void sessionSaving(QPIConfig & conf) {} + +public slots: + void changed() {setChanged(true);} + void newFile(); + void openFile(); + bool saveFile(bool ask = false); + bool saveAsFile(); + +signals: + +}; + +#endif // MAINWINDOW_H diff --git a/qad/application/etabwidget.cpp b/qad/application/etabwidget.cpp new file mode 100644 index 0000000..4da9dc3 --- /dev/null +++ b/qad/application/etabwidget.cpp @@ -0,0 +1,104 @@ +#include "etabwidget.h" + + +ETabWidget::ETabWidget(QWidget* parent): QTabWidget(parent) { + tabBar()->setMouseTracking(true); + tabBar()->installEventFilter(this); +} + + +void ETabWidget::retranslate() { + for (int i = 0; i < buttons.size(); ++i) + buttons[i].toolTip = QApplication::translate("MainWindow", buttons[i].srcToolTip.toUtf8(), 0/*, QCoreApplication::UnicodeUTF8*/); + QList bl = findChildren(); + foreach (QToolButton * i, bl) + i->setToolTip(QApplication::translate("MainWindow", i->property("sourceToolTip").toString().toUtf8(), 0/*, QCoreApplication::UnicodeUTF8*/)); +} + + +int ETabWidget::addTab(QWidget * page, const QIcon & icon, const QString & label) { + int ret = QTabWidget::addTab(page, icon, label); + QWidget * w = new QWidget(); + w->setLayout(new QBoxLayout(QBoxLayout::RightToLeft)); + w->layout()->setContentsMargins(0, 0, 0, 0); + w->layout()->setSpacing(2); + QToolButton * b; + foreach (const TabButton & i, buttons) { + b = new QToolButton(); + b->setToolTip(i.toolTip); + b->setIconSize(QSize(16, 16)); + b->setIcon(i.icon); + //b->setFlat(true); + b->setProperty("sourceToolTip", i.toolTip); + b->setProperty("buttonRole", i.role); + connect(b, SIGNAL(clicked(bool)), this, SLOT(buttonClicked())); + w->layout()->addWidget(b); + b->setVisible(i.visible); + } + tabBar()->setTabButton(ret, QTabBar::RightSide, w); + return ret; +} + + +void ETabWidget::setButtonVisible(int role, bool yes) { + QList bl = findChildren(); + foreach (QToolButton * i, bl) + if (i->property("buttonRole").toInt() == role) + i->setVisible(yes); + QWidget * w; + for (int i = 0; i < buttons.size(); ++i) { + if (buttons[i].role == role) + buttons[i].visible = yes; + w = tabBar()->tabButton(i, QTabBar::RightSide); + if (w != 0) w->adjustSize(); + } + tabBar()->adjustSize(); +} + +/* +void ETabWidget::removeTab(int index) { + tbs.removeAll(qobject_cast(tabBar()->tabButton(index, QTabBar::RightSide)->layout()->itemAt(1)->widget())); + tbs.removeAll(qobject_cast(tabBar()->tabButton(index, QTabBar::RightSide)->layout()->itemAt(0)->widget())); + QTabWidget::removeTab(index); +} +*/ + +bool ETabWidget::eventFilter(QObject * o, QEvent * e) { + static int prev = -1; + if (e->type() == QEvent::MouseMove) { + QTabBar * t = qobject_cast(o); + if (t == 0) return QTabWidget::eventFilter(o, e); + for (int i = 0; i < count(); ++i) + if (t->tabRect(i).contains(((QMouseEvent * )e)->pos())) { + if (i != prev) { + prev = i; + emit tabHovered(i); + } + return QTabWidget::eventFilter(o, e); + } + if (-1 != prev) { + prev = -1; + emit tabHovered(-1); + } + } + if (e->type() == QEvent::Leave) { + if (-1 != prev) { + prev = -1; + emit tabHovered(-1); + } + } + return QTabWidget::eventFilter(o, e); +} + + +void ETabWidget::buttonClicked() { + QToolButton * s = qobject_cast(sender()); + if (s == 0) return; + QWidget * pw = s->parentWidget(); + if (pw == 0) return; + for (int i = 0; i < count(); ++i) + if (tabBar()->tabButton(i, QTabBar::RightSide) == pw) { + emit tabButtonClicked(i, s->property("buttonRole").toInt()); + return; + } +} diff --git a/qad/application/etabwidget.h b/qad/application/etabwidget.h new file mode 100644 index 0000000..ad9f304 --- /dev/null +++ b/qad/application/etabwidget.h @@ -0,0 +1,54 @@ +#ifndef ETABWIDGET_H +#define ETABWIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class ETabWidget: public QTabWidget +{ + Q_OBJECT +public: + explicit ETabWidget(QWidget * parent = 0); + + void retranslate(); + void addTabButton(int role, const QIcon & icon, const QString & toolTip = QString()) {buttons << TabButton(role, icon, toolTip);} + int addTab(QWidget * page, const QIcon & icon, const QString & label); + int addTab(QWidget * page, const QString & label) {return addTab(page, QIcon(), label);} + void setButtonVisible(int role, bool yes); + +private: + bool eventFilter(QObject * o, QEvent * e); + void tabInserted(int) {emit countChanged();} + void tabRemoved(int) {emit countChanged();} + + struct TabButton { + TabButton(int r, const QIcon & i, const QString & t) {role = r; icon = i; visible = true; srcToolTip = t; toolTip = QApplication::translate("MainWindow", t.toUtf8(), 0/*, QCoreApplication::UnicodeUTF8*/);} + int role; + bool visible; + QIcon icon; + QString srcToolTip; + QString toolTip; + }; + + QList buttons; + +private slots: + void buttonClicked(); + +signals: + void countChanged(); + void tabHovered(int tab); + void tabButtonClicked(int tab, int role); + +}; + +#endif // ETABWIDGET_H diff --git a/qad/application/historyview.cpp b/qad/application/historyview.cpp new file mode 100644 index 0000000..a0e7c44 --- /dev/null +++ b/qad/application/historyview.cpp @@ -0,0 +1,140 @@ +#include "historyview.h" + + +HistoryView::HistoryView(QWidget* parent): QListWidget(parent) { + setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + setSelectionMode(QAbstractItemView::MultiSelection); + setEditTriggers(NoEditTriggers); + active_ = true; + index = 0; + setLimit(32); + setHistoryColor(palette().color(QPalette::Highlight)); + connect(this, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*))); + connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged())); + registerAction(-1, tr("History cleared"), QImage(":/icons/clear-history.png")); +} + + +HistoryView::~HistoryView() { +} + + +void HistoryView::addEntry(int action, int count_, const QString & suffix) { + if (!active_) return; + int cnt = count(); + for (int i = index; i < cnt; ++i) + if (i >= 0) delete takeItem(index); + addItem(new QListWidgetItem(actions_.value(action).icon, actionText(action, count_) + suffix)); + index = count(); + history_.resize(index); + history_.back() = Entry(action); + checkLimit(); + emit commandRequest(history_.back().command); + scrollToItem(item(index - 1)); + blockSignals(true); + for (int i = 0; i < index; ++i) + item(i)->setSelected(true); + blockSignals(false); + emit redoAvailable(false); + emit undoAvailable((index > 1)); + emit clearAvailable(history_.count() > 1); +} + + +void HistoryView::registerAction(int action, const QString & text, const QImage & icon) { + actions_[action] = HistoryView::Action(action, text, icon); +} + + +QString HistoryView::actionText(int action, int count_) { + return QString(actions_.value(action).text).replace("%count", QString::number(count_)); +} + + +void HistoryView::checkLimit() { + if (count() < limit_ + 1) return; + int c = count() - limit_; + for (int i = 0; i < c; ++i) { + if (i >= index - 1) { + if (count() < 2) break; + delete takeItem(1); + history_.remove(1); + } else { + if (count() < 1) break; + delete takeItem(0); + history_.pop_front(); + index--; + } + } + if (index < 1) index = 1; + if (index > count()) index = count(); +} + + +void HistoryView::itemClicked(QListWidgetItem * item) { + if (!active_) return; + if (index == row(item) + 1) return; + index = row(item) + 1; + //qDebug() << actions[index - 1].command; + emit commandExecute(history_[index - 1].command); + itemSelectionChanged(); +} + + +void HistoryView::itemSelectionChanged() { + if (!active_) return; + if (index < 1) index = 1; + //qDebug() << "changed" << count(); + blockSignals(true); + for (int i = 0; i < index; ++i) + item(i)->setSelected(true); + for (int i = index; i < count(); ++i) + item(i)->setSelected(false); + blockSignals(false); + emit redoAvailable(index < count()); + emit undoAvailable((index > 1)); +} + + +void HistoryView::setLimit(int l) { + limit_ = l; + checkLimit(); + emit redoAvailable(index < count()); + emit undoAvailable((index > 1)); +} + + +void HistoryView::setHistoryColor(const QColor & c) { + color_ = c; + QPalette pal(palette()); + pal.setColor(QPalette::Highlight, color_); + pal.setColor(QPalette::HighlightedText, pal.color(QPalette::Text)); + setPalette(pal); +} + + +void HistoryView::clear(bool silent) { + history_.clear(); + QListWidget::clear(); + if (!silent) addEntry(-1); + emit clearAvailable(false); + emit redoAvailable(index < count()); + emit undoAvailable((index > 1)); +} + + +void HistoryView::undo() { + if (index <= 1) return; + index--; + emit commandExecute(history_[index - 1].command); + itemSelectionChanged(); +} + + +void HistoryView::redo() { + if (index >= count()) return; + index++; + emit commandExecute(history_[index - 1].command); + itemSelectionChanged(); +} diff --git a/qad/application/historyview.h b/qad/application/historyview.h new file mode 100644 index 0000000..6795dc4 --- /dev/null +++ b/qad/application/historyview.h @@ -0,0 +1,74 @@ +#ifndef HISTORYVIEW_H +#define HISTORYVIEW_H + +#include +#include + + +class HistoryView: public QListWidget +{ + Q_OBJECT + Q_PROPERTY(bool active READ isActive WRITE setActive) + Q_PROPERTY(int limit READ limit WRITE setLimit) + Q_PROPERTY(QColor historyColor READ historyColor WRITE setHistoryColor) +public: + explicit HistoryView(QWidget * parent = 0); + ~HistoryView(); + + bool isActive() const {return active_;} + int limit() const {return limit_;} + QColor historyColor() const {return color_;} + + void addEntry(int action, int count = 0, const QString & suffix = QString()); + void registerAction(int action, const QString & text, const QImage & icon = QImage()); + +private: + struct Action { + Action(int i = -1, const QString & t = QString(), const QImage & c = QImage()): id(i), text(t) { + QPixmap px = QPixmap::fromImage(c); + icon.addPixmap(px, QIcon::Active); + icon.addPixmap(px, QIcon::Disabled); + icon.addPixmap(px, QIcon::Normal); + icon.addPixmap(px, QIcon::Selected); + } + int id; + QString text; + QIcon icon; + }; + struct Entry { + Entry(int a = -1, const QByteArray & c = QByteArray()): action(a), command(c) {} + int action; + QByteArray command; + }; + + void checkLimit(); + QString actionText(int action, int count_); + + QMap actions_; + QVector history_; + QColor color_; + bool active_; + int index, limit_; + +public slots: + void setActive(bool yes) {active_ = yes;} + void setLimit(int l); + void setHistoryColor(const QColor & c); + void clear(bool silent = false); + void undo(); + void redo(); + +private slots: + void itemClicked(QListWidgetItem * item); + void itemSelectionChanged(); + +signals: + void undoAvailable(bool); + void redoAvailable(bool); + void clearAvailable(bool); + void commandRequest(QByteArray & s); + void commandExecute(const QByteArray & s); + +}; + +#endif // HISTORYVIEW_H diff --git a/qad/application/lang/qad_application_ru.ts b/qad/application/lang/qad_application_ru.ts new file mode 100644 index 0000000..377960d --- /dev/null +++ b/qad/application/lang/qad_application_ru.ts @@ -0,0 +1,290 @@ + + + + + Graphic + + + Autofit + Автомасштаб + + + + Grid + Сетка + + + + Cursor axis + Плавающие оси + + + + Only expand Y + Только расширять Y + + + + Only expand X + Только расширять X + + + + Border inputs + + + + + Legend + Легенда + + + + Configure ... + Настроить ... + + + + Save image ... + Сохранить изображение ... + + + + Clear + Очистить + + + + Close + Закрыть + + + + Cursor: ( ; ) + Курсор: ( ; ) + + + + + Cursor: + Курсор: + + + + Selection + Выделение + + + + Size + Размер + + + + + Range + Диапазон + + + + + Length + Длина + + + + + Cursor + Курсор + + + + Save Image + Сохранить изображение + + + + y(x) + + + + + Check all + Выбрать все + + + + GraphicConf + + + Graphic parameters + Параметры графика + + + + Appearance + Внешний вид + + + + Border inputs + + + + + Antialiasing + Сглаживание + + + + Status bar + Панель статуса + + + + OpenGL + + + + + Legend + Легенда + + + + Background color: + Цвет фона: + + + + Text color: + Цвет текста: + + + + Graphics + Графики + + + + + Color: + Цвет: + + + + + Style: + Стиль: + + + + Lines width: + Толщина линий: + + + + Points width: + Толщина точек: + + + + Fill: + Заливка: + + + + Grid + Сетка + + + + Width: + Толщина: + + + + Step X: + Шаг X: + + + + Step Y: + Шаг Y: + + + + Auto step + Автоматический шаг + + + + Margins + Поля + + + + + + + + px + пикс + + + + All: + Все: + + + + Right: + Правое: + + + + Left: + Левое: + + + + Bottom: + Нижнее: + + + + Top: + Верхнее: + + + + NoPen + НетЛинии + + + + Solid + Сплошная + + + + Dash + Штриховая + + + + Dot + Пунктирная + + + + Dash-Dot + ШтрихПунктирная + + + + Dash-Dot-Dot + ШтрихПунктирПунктирная + + + diff --git a/qad/application/plugin/CMakeLists.txt b/qad/application/plugin/CMakeLists.txt new file mode 100644 index 0000000..09f97dd --- /dev/null +++ b/qad/application/plugin/CMakeLists.txt @@ -0,0 +1 @@ +qad_plugin(application "") diff --git a/qad/application/plugin/edockwidgetplugin.cpp b/qad/application/plugin/edockwidgetplugin.cpp new file mode 100644 index 0000000..61a5d87 --- /dev/null +++ b/qad/application/plugin/edockwidgetplugin.cpp @@ -0,0 +1,69 @@ +#include "edockwidget.h" +#include "edockwidgetplugin.h" +#include + + +EDockWidgetPlugin::EDockWidgetPlugin(QObject * parent): QObject(parent) { + m_initialized = false; +} + + +void EDockWidgetPlugin::initialize(QDesignerFormEditorInterface * /* core */) { + if (m_initialized) + return; + + // Add extension registrations, etc. here + + m_initialized = true; +} + + +bool EDockWidgetPlugin::isInitialized() const { + return m_initialized; +} + + +QWidget * EDockWidgetPlugin::createWidget(QWidget * parent) { + return new EDockWidget(parent); +} + + +QString EDockWidgetPlugin::name() const { + return QLatin1String("EDockWidget"); +} + + +QString EDockWidgetPlugin::group() const { + return QLatin1String("Containers"); +} + + +QIcon EDockWidgetPlugin::icon() const { + return QIcon(":/icons/edockwidget.png"); +} + + +QString EDockWidgetPlugin::toolTip() const { + return QLatin1String(""); +} + + +QString EDockWidgetPlugin::whatsThis() const { + return QLatin1String(""); +} + + +bool EDockWidgetPlugin::isContainer() const { + return true; +} + + +QString EDockWidgetPlugin::domXml() const { + return QLatin1String("\n\n"); +} + + +QString EDockWidgetPlugin::includeFile() const { + return QLatin1String("edockwidget.h"); +} + diff --git a/qad/application/plugin/edockwidgetplugin.h b/qad/application/plugin/edockwidgetplugin.h new file mode 100644 index 0000000..fed7ce1 --- /dev/null +++ b/qad/application/plugin/edockwidgetplugin.h @@ -0,0 +1,31 @@ +#ifndef EDOCKWIDGETPLUGIN_H +#define EDOCKWIDGETPLUGIN_H + +#include + +class EDockWidgetPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + EDockWidgetPlugin(QObject * parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget * createWidget(QWidget * parent); + void initialize(QDesignerFormEditorInterface * core); + +private: + bool m_initialized; + +}; + +#endif diff --git a/qad/application/plugin/emainwindowplugin.cpp b/qad/application/plugin/emainwindowplugin.cpp new file mode 100644 index 0000000..630d637 --- /dev/null +++ b/qad/application/plugin/emainwindowplugin.cpp @@ -0,0 +1,69 @@ +#include "emainwindow.h" +#include "emainwindowplugin.h" +#include + + +EMainWindowPlugin::EMainWindowPlugin(QObject * parent): QObject(parent) { + m_initialized = false; +} + + +void EMainWindowPlugin::initialize(QDesignerFormEditorInterface * /* core */) { + if (m_initialized) + return; + + // Add extension registrations, etc. here + + m_initialized = true; +} + + +bool EMainWindowPlugin::isInitialized() const { + return m_initialized; +} + + +QWidget * EMainWindowPlugin::createWidget(QWidget * parent) { + return new EMainWindow(parent); +} + + +QString EMainWindowPlugin::name() const { + return QLatin1String("EMainWindow"); +} + + +QString EMainWindowPlugin::group() const { + return QLatin1String("Containers"); +} + + +QIcon EMainWindowPlugin::icon() const { + return QIcon(); +} + + +QString EMainWindowPlugin::toolTip() const { + return QLatin1String(""); +} + + +QString EMainWindowPlugin::whatsThis() const { + return QLatin1String(""); +} + + +bool EMainWindowPlugin::isContainer() const { + return true; +} + + +QString EMainWindowPlugin::domXml() const { + return QLatin1String("\n\n"); +} + + +QString EMainWindowPlugin::includeFile() const { + return QLatin1String("emainwindow.h"); +} + diff --git a/qad/application/plugin/emainwindowplugin.h b/qad/application/plugin/emainwindowplugin.h new file mode 100644 index 0000000..e6da131 --- /dev/null +++ b/qad/application/plugin/emainwindowplugin.h @@ -0,0 +1,31 @@ +#ifndef EMAINWINDOWPLUGIN_H +#define EMAINWINDOWPLUGIN_H + +#include + +class EMainWindowPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + EMainWindowPlugin(QObject * parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget * createWidget(QWidget * parent); + void initialize(QDesignerFormEditorInterface * core); + +private: + bool m_initialized; + +}; + +#endif diff --git a/qad/application/plugin/historyviewplugin.cpp b/qad/application/plugin/historyviewplugin.cpp new file mode 100644 index 0000000..7113e6e --- /dev/null +++ b/qad/application/plugin/historyviewplugin.cpp @@ -0,0 +1,69 @@ +#include "historyview.h" +#include "historyviewplugin.h" +#include + + +HistoryViewPlugin::HistoryViewPlugin(QObject * parent): QObject(parent) { + m_initialized = false; +} + + +void HistoryViewPlugin::initialize(QDesignerFormEditorInterface * /* core */) { + if (m_initialized) + return; + + // Add extension registrations, etc. here + + m_initialized = true; +} + + +bool HistoryViewPlugin::isInitialized() const { + return m_initialized; +} + + +QWidget * HistoryViewPlugin::createWidget(QWidget * parent) { + return new HistoryView(parent); +} + + +QString HistoryViewPlugin::name() const { + return QLatin1String("HistoryView"); +} + + +QString HistoryViewPlugin::group() const { + return QLatin1String("Display Widgets"); +} + + +QIcon HistoryViewPlugin::icon() const { + return QIcon(":/icons/historyview.png"); +} + + +QString HistoryViewPlugin::toolTip() const { + return QLatin1String(""); +} + + +QString HistoryViewPlugin::whatsThis() const { + return QLatin1String(""); +} + + +bool HistoryViewPlugin::isContainer() const { + return true; +} + + +QString HistoryViewPlugin::domXml() const { + return QLatin1String("\n\n"); +} + + +QString HistoryViewPlugin::includeFile() const { + return QLatin1String("historyview.h"); +} + diff --git a/qad/application/plugin/historyviewplugin.h b/qad/application/plugin/historyviewplugin.h new file mode 100644 index 0000000..b3a2fb0 --- /dev/null +++ b/qad/application/plugin/historyviewplugin.h @@ -0,0 +1,31 @@ +#ifndef HISTORYVIEWPLUGIN_H +#define HISTORYVIEWPLUGIN_H + +#include + +class HistoryViewPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + HistoryViewPlugin(QObject * parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget * createWidget(QWidget * parent); + void initialize(QDesignerFormEditorInterface * core); + +private: + bool m_initialized; + +}; + +#endif // HISTORYVIEWPLUGIN_H diff --git a/qad/application/plugin/qad_application.cpp b/qad/application/plugin/qad_application.cpp new file mode 100644 index 0000000..cc2e5c0 --- /dev/null +++ b/qad/application/plugin/qad_application.cpp @@ -0,0 +1,19 @@ +#include "edockwidgetplugin.h" +#include "emainwindowplugin.h" +#include "historyviewplugin.h" +#include "qad_application.h" + + +QADApplication::QADApplication(QObject * parent): QObject(parent) { + //m_widgets.append(new EDockWidgetPlugin(this)); + m_widgets.append(new EMainWindowPlugin(this)); + m_widgets.append(new HistoryViewPlugin(this)); +} + + +QList QADApplication::customWidgets() const { + return m_widgets; +} + + +Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADApplication) diff --git a/qad/application/plugin/qad_application.h b/qad/application/plugin/qad_application.h new file mode 100644 index 0000000..7e8dcef --- /dev/null +++ b/qad/application/plugin/qad_application.h @@ -0,0 +1,21 @@ +#ifndef QAD_APPLICATION_H +#define QAD_APPLICATION_H + +#include +#include + +class QADApplication: public QObject, public QDesignerCustomWidgetCollectionInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) + +public: + explicit QADApplication(QObject * parent = 0); + virtual QList customWidgets() const; + +private: + QList m_widgets; + +}; + +#endif // QAD_APPLICATION_H diff --git a/qad/application/qad_application.qrc b/qad/application/qad_application.qrc new file mode 100644 index 0000000..6a82538 --- /dev/null +++ b/qad/application/qad_application.qrc @@ -0,0 +1,33 @@ + + + lang/qad_application_ru.ts + ../icons/dialog-close.png + ../icons/edit-clear.png + ../icons/edit-guides.png + ../icons/view-grid.png + ../icons/zoom-fit-best.png + ../icons/configure.png + ../icons/document-save.png + ../icons/edit-clear-locationbar-rtl.png + ../icons/edit-find.png + ../icons/list-add.png + ../icons/edit-delete.png + ../icons/item.png + ../icons/node-add.png + ../icons/node.png + ../icons/edit-copy.png + ../icons/edit-paste.png + ../icons/expand_s_x.png + ../icons/expand_s_y.png + ../icons/expand_x.png + ../icons/expand_y.png + ../icons/border-line.png + ../icons/legend.png + ../icons/graphic.png + ../icons/edockwidget.png + ../icons/layer-visible-off.png + ../icons/layer-visible-on.png + ../icons/historyview.png + ../icons/clear-history.png + + diff --git a/qad/application/qsingleapplication.cpp b/qad/application/qsingleapplication.cpp new file mode 100644 index 0000000..428c4bb --- /dev/null +++ b/qad/application/qsingleapplication.cpp @@ -0,0 +1,87 @@ +#include +#include "qsingleapplication.h" + + +#define QSA_SHMSIZE 4096 +#define QSA_MSGSIZE (QSA_SHMSIZE - sizeof(quint32) - sizeof(quint32)) + + +QSingleApplication::QSingleApplication(const QString & app_name): QThread() { + shm.setKey(app_name); + exiting = false; + first = !shm.attach(); + if (!first) { + shm.detach(); + first = !shm.attach(); + if (!first) + return; + } + shm.create(QSA_SHMSIZE); + shm.attach(); + shm.lock(); + void * d = shm.data(); + if (d) memset(d, 0, sizeof(quint32)); + shm.unlock(); + start(); + //qDebug() << "start listen"; +} + + +QSingleApplication::~QSingleApplication() { + if (first) { + exiting = true; + quit(); + if (!wait(100)) + terminate(); + } + if (shm.isAttached()) shm.detach(); +} + + +void QSingleApplication::sendMessage(const QByteArray & m) { + //qDebug() << "send message" << first << shm.isAttached(); + if (first || !shm.isAttached()) return; + if (m.size() > int(QSA_MSGSIZE)) { + qDebug() << "[QSingleApplication] Too large message:" << m.size() << ">" << QSA_MSGSIZE; + return; + } + shm.lock(); + quint32 num(0), size = m.size(); + void * d = shm.data(); + if (d) { + memcpy(&num, d, sizeof(quint32)); + num++; + memcpy(d, &num, sizeof(quint32)); + memcpy((((char*)d) + sizeof(quint32)), &size, sizeof(quint32)); + memcpy((((char*)d) + sizeof(quint32) + sizeof(quint32)), m.constData(), size); + } + shm.unlock(); +} + + +void QSingleApplication::run() { + quint32 num(0), pnum(0), size(0); + while (!exiting) { + shm.lock(); + const void * d = shm.constData(); + if (d) { + memcpy(&num, d, sizeof(quint32)); + if (pnum != num) { + pnum = num; + //qDebug() << "new message" << num; + memcpy(&size, (((const char*)d) + sizeof(quint32)), sizeof(quint32)); + if (size <= int(QSA_MSGSIZE)) { + QByteArray msg; + msg.resize(size); + memcpy(msg.data(), (((const char*)d) + sizeof(quint32) + sizeof(quint32)), size); + emit messageReceived(msg); + } else { + qDebug() << "[QSingleApplication] Invalid message size:" << size; + } + } + } + shm.unlock(); + if (exiting) break; + msleep(10); + } +} diff --git a/qad/application/qsingleapplication.h b/qad/application/qsingleapplication.h new file mode 100644 index 0000000..45a83df --- /dev/null +++ b/qad/application/qsingleapplication.h @@ -0,0 +1,30 @@ +#ifndef QSINGLEAPPLICATION_H +#define QSINGLEAPPLICATION_H + +#include +#include + +class QSingleApplication: public QThread +{ + Q_OBJECT +public: + QSingleApplication(const QString & app_name = QString("qapp")); + ~QSingleApplication(); + + bool isFirst() const {return first;} + +private: + void run(); + + QSharedMemory shm; + bool first, exiting; + +public slots: + void sendMessage(const QByteArray & m); + +signals: + void messageReceived(QByteArray); + +}; + +#endif // QSINGLEAPPLICATION_H diff --git a/qad/application/ribbon.cpp b/qad/application/ribbon.cpp new file mode 100644 index 0000000..05990d7 --- /dev/null +++ b/qad/application/ribbon.cpp @@ -0,0 +1,196 @@ +#include "ribbon.h" +#include + + +Ribbon::Ribbon(QMainWindow * parent_): QToolBar() { + delay_e = true; + delay = 1000; + hovered = -1; + setObjectName("ribbon"); + setProperty("ribbon", true); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + parent = parent_; + if (parent_) + parent_->installEventFilter(this); + init(); +} + + +Ribbon::~Ribbon() { +} + + +bool Ribbon::eventFilter(QObject * o, QEvent * e) { + if (o == parent) { + if (e->type() == QEvent::Resize || e->type() == QEvent::WindowActivate) + _resize(); + return QToolBar::eventFilter(o, e); + } + if (e->type() == QEvent::ActionChanged) { + QToolButton * b = qobject_cast((QObject * )o->property("ribbonButton").toLongLong()); + if (b != 0) + b->setEnabled(qobject_cast(o)->isEnabled()); + } + return QToolBar::eventFilter(o, e); +} + + +void Ribbon::timerEvent(QTimerEvent * e) { + if (hovers.value(e->timerId(), -1) == hovered) + tab->setCurrentIndex(hovered); + hovers.remove(e->timerId()); + killTimer(e->timerId()); +} + + +void Ribbon::_resize() { + return; // WARNING + for (int i = 0; i < tab->count(); ++i) { + int h = ((QScrollArea*)(tab->widget(i)))->sizeHint().height(); + if (((QScrollArea*)(tab->widget(i)))->horizontalScrollBar()->isVisible()) + h += ((QScrollArea*)(tab->widget(i)))->horizontalScrollBar()->height(); + ((QScrollArea*)(tab->widget(i)))->setMinimumHeight(h); + } +} + + +void Ribbon::setVisible(bool yes) { + QToolBar::setVisible(yes); + if (parent == 0) return; + if (parent->menuBar() == 0) return; + parent->menuBar()->setVisible(!yes); +} + + +void Ribbon::init() { + if (parent == 0) return; + if (parent->menuBar() == 0) return; + QList lm = parent->menuBar()->actions(), la; + tab = new ETabWidget(); + tab->setObjectName("ribbon_tab_widget"); + connect(tab, SIGNAL(tabHovered(int)), this, SLOT(tabHovered(int))); + connect(tab, SIGNAL(currentChanged(int)), this, SIGNAL(currentTabChanged(int))); + tab->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + QGroupBox * g; + QBoxLayout * l, * tl; + QToolButton * b; + //tab->setIconSize(QSize(32, 32)); + foreach (QAction * i, lm) { + if (i->menu() == 0) continue; + la = i->menu()->actions(); + tab->addTab(new QWidget(), i->icon(), i->text()); + /*QScrollArea * sa = new QScrollArea(); + sa->setWidget(new QWidget()); + sa->setWidgetResizable(true); + sa->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + sa->setFrameShape(QFrame::NoFrame); + tab->addTab(sa, i->icon(), i->text());*/ + tab->widget(tab->count() - 1)->setProperty("ribbonAction", qlonglong((void * )i)); + i->setIcon(QIcon()); + tl = new QBoxLayout(QBoxLayout::LeftToRight); + tl->setSpacing(2); + tl->setContentsMargins(2, 2, 2, 2); + g = new QGroupBox(); + l = new QBoxLayout(QBoxLayout::LeftToRight); + g->setLayout(l); + l->setSpacing(2); + l->setContentsMargins(2, 2, 2, 2); + foreach (QAction * j, la) { + if (j->isSeparator()) { + if (l->isEmpty()) continue; + tl->addWidget(g); + g = new QGroupBox(); + l = new QBoxLayout(QBoxLayout::LeftToRight); + l->setSpacing(2); + l->setContentsMargins(2, 2, 2, 2); + g->setLayout(l); + continue; + } + if (qobject_cast(j)) { + QWidget * _w = qobject_cast(j)->defaultWidget(); + l->addWidget(_w); + _w->show(); + continue; + } + b = new QToolButton(); + b->setEnabled(j->isEnabled()); + b->setProperty("ribbonAction", qlonglong((void * )j)); + j->setProperty("ribbonButton", qlonglong((void * )b)); + j->installEventFilter(this); + if (j->menu() != 0) { + b->setPopupMode(QToolButton::InstantPopup); + b->setMenu(j->menu()); + } else { + b->setCheckable(j->isCheckable()); + if (b->isCheckable()) { + b->setChecked(j->isChecked()); + connect(b, SIGNAL(toggled(bool)), j, SLOT(setChecked(bool))); + connect(b, SIGNAL(clicked(bool)), j, SIGNAL(triggered(bool))); + connect(j, SIGNAL(toggled(bool)), b, SLOT(setChecked(bool))); + } else + connect(b, SIGNAL(clicked()), j, SLOT(trigger())); + } + //b->setIconSize(QSize(16, 16)); + b->setIcon(j->icon()); + b->setText(j->text()); + //b->setToolTip(j->toolTip()); + //b->addAction(j); + //b->setShortcut(j->shortcut()); + b->setAutoRaise(true); + b->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + buttons << b; + l->addWidget(b); + } + tl->addWidget(g); + tl->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed)); + //sa->widget()->setLayout(tl); + tab->widget(tab->count() - 1)->setLayout(tl); + } + setFloatable(false); + setMovable(false); + scroll_area = new QScrollArea(); + scroll_area->setFrameShape(QFrame::NoFrame); + scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + scroll_area->setWidget(tab); + _resize(); + //addWidget(scroll_area); + addWidget(tab); + parent->addToolBar(Qt::TopToolBarArea, this); + parent->menuBar()->hide(); + tab->setAutoFillBackground(false); +} + + +void Ribbon::retranslate() { + QAction * a; + foreach (QToolButton * i, buttons) { + a = (QAction * )(i->property("ribbonAction").toLongLong()); + if (a == 0) continue; + i->setText(a->text()); + i->setToolTip(a->toolTip()); + //i->setShortcut(a->shortcut()); + } + for (int i = 0; i < tab->count(); ++i) { + a = (QAction * )(tab->widget(i)->property("ribbonAction").toLongLong()); + if (a == 0) continue; + tab->setTabText(i, a->text()); + } + _resize(); +} + + +void Ribbon::setIconSize(const QSize & size) { + foreach (QToolButton * i, buttons) + i->setIconSize(size); + _resize(); +} + + +void Ribbon::setTabIconSize(const QSize & size) { + tab->setIconSize(size); + _resize(); +} diff --git a/qad/application/ribbon.h b/qad/application/ribbon.h new file mode 100644 index 0000000..e59826d --- /dev/null +++ b/qad/application/ribbon.h @@ -0,0 +1,62 @@ +#ifndef RIBBON_H +#define RIBBON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "etabwidget.h" + + +class Ribbon: public QToolBar +{ + Q_OBJECT +public: + explicit Ribbon(QMainWindow * parent = 0); + ~Ribbon(); + + void init(); + void retranslate(); + void setIconSize(const QSize & size); + void setTabIconSize(const QSize & size); + void setButtonStyle(const Qt::ToolButtonStyle & style) {foreach (QToolButton * i, buttons) i->setToolButtonStyle(style);} + void setAutoSwitchEnabled(bool yes) {delay_e = yes;} + void setAutoSwitchDelay(float delay_s) {delay = delay_s * 1000;} + void setCurrentTab(int tab_) {if (tab_ < 0 || tab_ >= tab->count()) return; tab->setCurrentIndex(tab_);} + int currentTab() const {return tab->currentIndex();} + QTabWidget * tabWidget() const {return tab;} + +private: + bool eventFilter(QObject * o, QEvent * e); + void timerEvent(QTimerEvent * e); + void _resize(); + + int hovered, delay; + bool delay_e; + QList buttons; + QMap hovers; + ETabWidget * tab; + QScrollArea * scroll_area; + QMainWindow * parent; + +private slots: + void tabHovered(int tab) {if (!delay_e) return; hovers.clear(); hovered = tab; hovers.insert(startTimer(delay), tab);} + +public slots: + void setVisible(bool yes); + void setHidden(bool yes) {setVisible(!yes);} + void show() {setVisible(true);} + void hide() {setVisible(false);} + +signals: + void currentTabChanged(int); + +}; + +#endif // RIBBON_H diff --git a/qad/blockview/CMakeLists.txt b/qad/blockview/CMakeLists.txt new file mode 100644 index 0000000..9ad84a1 --- /dev/null +++ b/qad/blockview/CMakeLists.txt @@ -0,0 +1,2 @@ +set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} qad_widgets qad_utils) +qad_project(blockview "${LIBS}") diff --git a/qad/blockview/alignedtextitem.cpp b/qad/blockview/alignedtextitem.cpp new file mode 100644 index 0000000..ee7f2b8 --- /dev/null +++ b/qad/blockview/alignedtextitem.cpp @@ -0,0 +1,45 @@ +#include "alignedtextitem.h" +#include +#include + + +AlignedTextItem::AlignedTextItem(QGraphicsItem * parent): QGraphicsItem(parent), text_(this) { + align_ = Qt::AlignTop | Qt::AlignHCenter; + text_.setData(1003, true); + _move(); +} + + +AlignedTextItem::AlignedTextItem(const QString & text, QGraphicsItem * parent): QGraphicsItem(parent), text_(this) { + align_ = Qt::AlignTop | Qt::AlignHCenter; + text_.setData(1003, true); + setText(text); +} + + +QPointF AlignedTextItem::_point(Qt::Alignment a) const { + QRectF br = text_.boundingRect(); + QPointF ret; + switch (Qt::AlignmentFlag(int(align_ & Qt::AlignHorizontal_Mask))) { + case Qt::AlignRight: ret.rx() = br.left(); break; + case Qt::AlignHCenter: ret.rx() = br.center().x(); break; + case Qt::AlignLeft: ret.rx() = br.right(); break; + default: break; + } + switch (Qt::AlignmentFlag(int(align_ & Qt::AlignVertical_Mask))) { + case Qt::AlignBottom: ret.ry() = br.top(); break; + case Qt::AlignVCenter: ret.ry() = br.center().y(); break; + case Qt::AlignTop: ret.ry() = br.bottom(); break; + default: break; + } + return ret; +} + + +void AlignedTextItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { + if (isSelected()) { + painter->setPen(QPen(Qt::DashLine)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(boundingRect()); + } +} diff --git a/qad/blockview/alignedtextitem.h b/qad/blockview/alignedtextitem.h new file mode 100644 index 0000000..89519e0 --- /dev/null +++ b/qad/blockview/alignedtextitem.h @@ -0,0 +1,45 @@ +#ifndef ALIGNEDTEXTITEM_H +#define ALIGNEDTEXTITEM_H + +#include +#include +#include +#include + + +class AlignedTextItem: public QGraphicsItem { +public: + AlignedTextItem(QGraphicsItem * parent = 0); + AlignedTextItem(const QString & text, QGraphicsItem * parent = 0); + + void setText(const QString & t) {text_.setText(t); _move();} + void setFont(const QFont & f) {text_.setFont(f); _move();} + void setPen(const QPen & p) {text_.setPen(p); _move();} + void setBrush(const QBrush & b) {text_.setBrush(b); _move();} + void setAlignment(Qt::Alignment align) {align_ = align; _move();} + + QString text() const {return text_.text();} + QFont font() const {return text_.font();} + QPen pen() const {return text_.pen();} + QBrush brush() const {return text_.brush();} + Qt::Alignment alignment() const {return align_;} + + void clear() {setText(QString());} + + enum {Type = UserType + 0x100}; + +protected: + virtual QRectF boundingRect() const {return text_.boundingRect().translated(text_.pos());} + virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0); + virtual int type() const {return Type;} + + void _move() {text_.setPos(-_point(align_));} + QPointF _point(Qt::Alignment a) const; + + QGraphicsSimpleTextItem text_; + Qt::Alignment align_; + +}; + + +#endif // ALIGNEDTEXTITEM_H diff --git a/qad/blockview/blockbase.cpp b/qad/blockview/blockbase.cpp new file mode 100644 index 0000000..1a2bb13 --- /dev/null +++ b/qad/blockview/blockbase.cpp @@ -0,0 +1,104 @@ +#include "blockbase.h" +#include "alignedtextitem.h" +#include "qvariantedit.h" + + +QDataStream & operator <<(QDataStream & s, const QGraphicsItem * item) { + if (!item) { + s << int(-1); + return s; + } + const QGraphicsRectItem * irect = qgraphicsitem_cast(item); + const QGraphicsEllipseItem * iell = qgraphicsitem_cast(item); + const QGraphicsSimpleTextItem * itext = qgraphicsitem_cast(item); + const AlignedTextItem * iatext = qgraphicsitem_cast(item); + const QGraphicsLineItem * iline = qgraphicsitem_cast(item); + const QGraphicsPathItem * ipath = qgraphicsitem_cast(item); + const QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast(item); + if (irect) { + s << int(0) << (irect->pen()) << (irect->brush()) << (irect->rect()); + } else if (iell) { + s << int(1) << (iell->pen()) << (iell->brush()) << (iell->rect()); + } else if (itext) { + s << int(2) << (itext->pen()) << (itext->brush()) << (itext->font()) << (itext->text()); + } else if (iatext) { + s << int(6) << (iatext->pen()) << (iatext->brush()) << (iatext->font()) << (iatext->text()) << int(iatext->alignment()); + } else if (iline) { + s << int(3) << (iline->pen()) << (iline->line()); + } else if (ipath) { + s << int(4) << (ipath->pen()) << (ipath->path()); + } else if (ipixmap) { + s << int(5) << (ipixmap->pixmap()); + } else { + s << int(-1); + return s; + } + s << (item->pos()) << (item->rotation()) << int(item->flags()); + return s; +} + + +QDataStream & operator >>(QDataStream & s, QGraphicsItem *& item) { + int type_; s >> type_; + if (type_ < 0) { + item = 0; + return s; + } + QGraphicsRectItem * nrect = 0; + QGraphicsEllipseItem * nell = 0; + QGraphicsSimpleTextItem * ntext = 0; + AlignedTextItem * natext = 0; + QGraphicsLineItem * nline = 0; + QGraphicsPathItem * npath = 0; + QGraphicsPixmapItem * npixmap = 0; + item = 0; + switch (type_) { + case 0: + nrect = new QGraphicsRectItem(); item = nrect; + {QPen _v; s >> _v; nrect->setPen(_v);} + {QBrush _v; s >> _v; nrect->setBrush(_v);} + {QRectF _v; s >> _v; nrect->setRect(_v);} + break; + case 1: + nell = new QGraphicsEllipseItem(); item = nell; + {QPen _v; s >> _v; nell->setPen(_v);} + {QBrush _v; s >> _v; nell->setBrush(_v);} + {QRectF _v; s >> _v; nell->setRect(_v);} + break; + case 2: + ntext = new QGraphicsSimpleTextItem(); item = ntext; + {QPen _v; s >> _v; ntext->setPen(_v);} + {QBrush _v; s >> _v; ntext->setBrush(_v);} + {QFont _v; s >> _v; ntext->setFont(_v);} + {QString _v; s >> _v; ntext->setText(_v);} + break; + case 6: + natext = new AlignedTextItem(); item = natext; + {QPen _v; s >> _v; natext->setPen(_v);} + {QBrush _v; s >> _v; natext->setBrush(_v);} + {QFont _v; s >> _v; natext->setFont(_v);} + {QString _v; s >> _v; natext->setText(_v);} + {int _v; s >> _v; natext->setAlignment((Qt::AlignmentFlag)_v);} + break; + case 3: + nline = new QGraphicsLineItem(); item = nline; + {QPen _v; s >> _v; nline->setPen(_v);} + {QLineF _v; s >> _v; nline->setLine(_v);} + break; + case 4: + npath = new QGraphicsPathItem(); item = npath; + {QPen _v; s >> _v; npath->setPen(_v);} + {QPainterPath _v; s >> _v; npath->setPath(_v);} + break; + case 5: + npixmap = new QGraphicsPixmapItem(); item = npixmap; + {QPixmap _v; s >> _v; npixmap->setPixmap(_v);} + break; + } + if (item) { + {QPointF _v; s >> _v; item->setPos(_v);} + {qreal _v; s >> _v; item->setRotation(_v);} + {int _v; s >> _v; item->setFlags((QGraphicsItem::GraphicsItemFlags)_v);} + } + return s; +} diff --git a/qad/blockview/blockbase.h b/qad/blockview/blockbase.h new file mode 100644 index 0000000..7b19ef7 --- /dev/null +++ b/qad/blockview/blockbase.h @@ -0,0 +1,57 @@ +#ifndef BLOCKBASE_H +#define BLOCKBASE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "propertystorage.h" + + +/// data: +/// 1002 - flag for move parent (true) +/// 1003 - flag for visualize selection (true) +/// 1004 - BlockItemPin ("pin") +/// 1005 - BlockBusItem ("connection") +/// 1006 - BlockItem ("item") +/// 1007 - BlockItem selection ("item_selection") +/// 1008 - item is NOT decor, ignore for function decors() (true) +/// 1009 - item is scene decor ("decor") +/// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem) +/// 1011 - item is BlockItem decor ("decor") +/// 1100 - flag for correct move (true) + + +QDataStream & operator <<(QDataStream & s, const QGraphicsItem * item); +QDataStream & operator >>(QDataStream & s, QGraphicsItem *& item); + + +class BlockItemBase: public QObject +{ + Q_OBJECT + Q_ENUMS(Action) +public: + + enum Action { + BlockAdd = 1, + BlockMove, + BlockRemove, + BlockCopy, + BusAdd, + BusRemove, + BusPointAdd, + BusPointMove, + BusPointRemove, + BusSegmentAdd, + BusSegmentMove, + BusSegmentRemove, + Paste + }; + +}; + +#endif // BLOCKBASE_H diff --git a/qad/blockview/blockbusitem.cpp b/qad/blockview/blockbusitem.cpp new file mode 100644 index 0000000..0dcc423 --- /dev/null +++ b/qad/blockview/blockbusitem.cpp @@ -0,0 +1,733 @@ +#include "blockbusitem.h" + + +BlockBusItem::BlockBusItem(bool temp): QGraphicsObject(), PropertyStorage() { + temp_ = temp; + _init(); + if (!temp) setData(1005, "connection"); + else hide(); +} + + +BlockBusItem::BlockBusItem(const BlockBusItem & other): QGraphicsObject(), PropertyStorage() { + temp_ = false; + _init(); + setData(1005, "connection"); + setPen(other.pen()); + setBrush(other.brush()); + setBusType(other.busType()); + max_ep = other.max_ep; + pol = other.pol; + segments = other.segments; + updateGeometry(); +} + + +void BlockBusItem::_init() { + setBusType(-1); + setAcceptHoverEvents(true); + ph.setColor(Qt::blue); ph.setJoinStyle(Qt::MiterJoin); + bh.setColor(Qt::blue); bh.setStyle(Qt::SolidPattern); + pu = pa = pr = ph; bu = ba = br = bh; + grid_step = 10.; + pu.setWidth(1); + pu.setColor(Qt::black); bu.setColor(Qt::black); + pa.setColor(Qt::darkGreen); ba.setColor(Qt::darkGreen); + pr.setColor(Qt::darkRed); br.setColor(Qt::darkRed); + pn.setColor(Qt::gray); pn.setStyle(Qt::DashLine); + if (temp_) { + pu.setStyle(Qt::DashLine); + pu.setColor(Qt::darkGray); + bu.setColor(Qt::darkGray); + } + setPen(pu); setBrush(bu); + max_ep = 0; + selPoint = selSegment = state_ = -1; + pen_width = 2.; + moved = deleted = mark_in = mark_out = new_segment = mm_cancel = lm_point = false; +} + + +void BlockBusItem::reconnect() { + if (temp_) return; + if (!scene()) return; + if (scene()->views().isEmpty()) return; + QMetaObject::invokeMethod(scene()->views().back(), "reconnectAll"); +} + + +bool BlockBusItem::sceneEvent(QEvent * e) { + if (temp_) return QGraphicsObject::sceneEvent(e); + switch (e->type()) { + case QEvent::GraphicsSceneHoverEnter: hoverEnterEvent((QGraphicsSceneHoverEvent * )e); break; + case QEvent::GraphicsSceneHoverMove: hoverMoveEvent((QGraphicsSceneHoverEvent * )e); break; + case QEvent::GraphicsSceneHoverLeave: hoverLeaveEvent((QGraphicsSceneHoverEvent * )e); break; + case QEvent::GraphicsSceneMousePress: mousePressEvent((QGraphicsSceneMouseEvent * )e); break; + case QEvent::GraphicsSceneMouseMove: mouseMoveEvent((QGraphicsSceneMouseEvent * )e); break; + case QEvent::GraphicsSceneMouseRelease: mouseReleaseEvent((QGraphicsSceneMouseEvent * )e); break; + default: break; + } + return QGraphicsObject::sceneEvent(e); +} + + +int BlockBusItem::addPoint(const QPointF & point, bool update) { + int ei = pol.indexOf(point); + if (ei >= 0) return ei; + if (selSegment < 0 || selSegment >= pol.size() - 1) return -1; + pol << quantize(nearestPointOnLine(pol[segments[selSegment].first], pol[segments[selSegment].second], point), grid_step); + selPoint = pol.size() - 1; + segments << QPair(selPoint, segments[selSegment].second); + segments[selSegment].second = selPoint; + selSegment = -1; + updateGeometry(); + if (scene() != 0 && update) scene()->update(); + return pol.size() - 1; +} + + +int BlockBusItem::segmentPointPair(int point, int * seg) const { + for (int i = 0; i < segments.size(); ++i) { + if (segments[i].first == point) { + if (seg) *seg = i; + return segments[i].second; + } + if (segments[i].second == point) { + if (seg) *seg = i; + return segments[i].first; + } + } + if (seg) *seg = -1; + return -1; +} + + +void BlockBusItem::removePoint(int index) { + if (index < 0 || index > pol.size() - 1) return; + int sc = 0, fs = -1, ss = -1; + for (int i = 0; i < segments.size(); ++i) + if (segments[i].first == index || + segments[i].second == index) { + sc++; + if (fs < 0) fs = i; + else ss = i; + } + int ei(0); + switch (sc) { + case 1: + segments.removeAt(fs); + break; + case 2: + if (segments[ss].first == index) ei = segments[ss].second; + else ei = segments[ss].first; + if (segments[fs].first == index) segments[fs].first = ei; + else segments[fs].second = ei; + segments.removeAt(ss); + break; + default: return; + } + pol.remove(index); + for (int i = 0; i < segments.size(); ++i) { + if (segments[i].first >= index) + segments[i].first--; + if (segments[i].second >= index) + segments[i].second--; + } + selPoint = -1; + checkDelete(); + updateGeometry(); + if (scene() != 0) scene()->update(); +} + + +void BlockBusItem::removeSegment(int index) { + if (index < 0 || index > segments.size() - 1) return; + int pif = segments[index].first, pis = segments[index].second; + if (pif > pis) qSwap(pif, pis); + int scf = 0, scs = 0; + for (int i = 0; i < segments.size(); ++i) { + if (segments[i].first == pif || + segments[i].second == pif) + scf++; + if (segments[i].first == pis || + segments[i].second == pis) + scs++; + } + if (scs <= 2) removePoint(pis); + if (scf <= 2) removePoint(pif); + if (scs <= 2 || scf <= 2) selSegment = -1; + if (scene() != 0) scene()->update(); + +} + + +void BlockBusItem::appendPoint(const QPointF & p) { + pol << p; + if (pol.size() > 1) + segments << QPair(pol.size() - 2, pol.size() - 1); + updateGeometry(); +} + + +void BlockBusItem::clear() { + pol.clear(); + segments.clear(); + updateGeometry(); +} + + +void BlockBusItem::markAsInput() { + mark_in = true; + mark_out = false; +} + + +void BlockBusItem::markAsOutput() { + mark_in = false; + mark_out = true; +} + + +void BlockBusItem::unmark() { + mark_in = mark_out = false; +} + + +void BlockBusItem::simplify(bool full) { + int pcnt = pol.size(); + for (int s = 0; s < segments.size(); ++s) { + if (pol[segments[s].first] != pol[segments[s].second]) continue; + int ti = segments[s].first, fi = segments[s].second; + segments.removeAt(s); + pol.remove(fi); + for (int i = 0; i < segments.size(); ++i) { + if (segments[i].first == fi) segments[i].first = ti; + if (segments[i].second == fi) segments[i].second = ti; + if (segments[i].first > fi) segments[i].first--; + if (segments[i].second > fi) segments[i].second--; + } + } + if (full) { + QList segs; + for (int p = 0; p < pol.size(); ++p) { + if (pointSegmentsCount(p, &segs) != 2) continue; + int s0 = segs[0], s1 = segs[1]; + QPointF cp = pol[p], sp[2]; + for (int i = 0; i < 2; ++i) { + if (segments[segs[i]].first == p) sp[i] = pol[segments[segs[i]].second]; + else sp[i] = pol[segments[segs[i]].first]; + } + QLineF l0(sp[0], cp), l1(cp, sp[1]); + if (qAbs(l0.angle() - l1.angle()) > 0.1) continue; + if (segments[s0].first == p) { + if (segments[s1].first == p) segments[s0].first = segments[s1].second; + else segments[s0].first = segments[s1].first; + } else { + if (segments[s1].first == p) segments[s0].second = segments[s1].second; + else segments[s0].second = segments[s1].first; + } + segments.removeAt(s1); + pol.remove(p); + for (int i = 0; i < segments.size(); ++i) { + if (segments[i].first >= p) segments[i].first--; + if (segments[i].second >= p) segments[i].second--; + } + p = -1; + } + } + if (pcnt == pol.size()) return; + updateGeometry(); + //if (scene()) scene()->update(); +} + + +void BlockBusItem::adjustLine() { +} + + +int BlockBusItem::endpointCount() const { + return endpoints().size(); +} + + + +QList BlockBusItem::connectedBlocks() const { + QList pins = connections_.values(); + QSet ret; + foreach (BlockItemPin * p, pins) + ret << p->parent(); + return ret.toList(); +} + + +QList BlockBusItem::connectedPins() const { + return connections_.values(); +} + + +void BlockBusItem::setBusState(bool state) { + int s = state ? 1 : 0; + if (state_ == s) return; + state_ = s; + update(); +} + + +void BlockBusItem::clearBusState() { + if (state_ == -1) return; + state_ = -1; + update(); +} + + +QByteArray BlockBusItem::save() const { + ChunkStream cs; + cs << cs.chunk(1, busType()) << cs.chunk(2, busName()) << cs.chunk(3, width()) << cs.chunk(4, pen()) + << cs.chunk(5, brush()) << cs.chunk(6, pol) << cs.chunk(7, segments) << cs.chunk(8, props); + return cs.data(); +} + + +void BlockBusItem::load(const QByteArray & data) { + clear(); + if (data.isEmpty()) return; + ChunkStream cs(data); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: setBusType(cs.getData()); break; + case 2: setBusName(cs.getData()); break; + case 3: setWidth(cs.getData()); break; + case 4: setPen(cs.getData()); break; + case 5: setBrush(cs.getData()); break; + case 6: pol = cs.getData(); break; + case 7: segments = cs.getData > >(); break; + case 8: props = cs.getData >(); break; + } + } + updateGeometry(); +} + + +BlockBusItem * BlockBusItem::copy() const { + return new BlockBusItem(*this); +} + + +void BlockBusItem::saveState() { + segments_s = segments; + ends_ind_s = ends_ind; + ends_s = ends; + pol_s = pol; +} + + +void BlockBusItem::restoreState() { + segments = segments_s; + ends_ind = ends_ind_s; + ends = ends_s; + pol = pol_s; +} + + +void BlockBusItem::updateGeometry() { + ends = endpoints(); + ends_ind.clear(); + for (int e = 0; e < ends.size(); ++e) { + int ce = ends[e]; + for (int s = 0; s < segments.size(); ++s) { + if (segments[s].first == ce) { + ends_ind << QPair(segments[s].first, segments[s].second); + break; + } + if (segments[s].second == ce) { + ends_ind << QPair(segments[s].second, segments[s].first); + break; + } + } + } + reconnect(); + prepareGeometryChange(); +} + + +void BlockBusItem::checkDelete() { + if (pol.size() < 2 || segments.size() < 1) deleteLater(); +} + + +void BlockBusItem::emitAction(BlockItemBase::Action a) { + QMetaObject::invokeMethod(scene()->views().back(), "actionEvent", Q_ARG(BlockItemBase::Action, a), Q_ARG(QList, QList() << this)); + QMetaObject::invokeMethod(scene()->views().back(), "connectionsChanged"); +} + + +QVector BlockBusItem::endpoints() const { + QVector counts(pol.size(), 0), ret; + for (int i = 0; i < segments.size(); ++i) { + counts[segments[i].first]++; + counts[segments[i].second]++; + } + for (int i = 0; i < counts.size(); ++i) { + if (counts[i] == 1) + ret << i; + } + return ret; +} + + +QVector BlockBusItem::endpointLine(int ep, double angle) const { + QVector ret; + int seg = -1; + int np = segmentPointPair(ep, &seg), pp = np; + if (ep < 0 || np < 0) return ret; + if (pol[np] == pol[ep]) return ret; + //QPointF sp = pol[np] - pol[ep]; + QLineF l(pol[ep], pol[np]); + //qDebug() << "first" << l.angle() << angle << (l.angle() != angle); + if (qAbs(l.angle() - angle) > 0.1) return ret; + //qDebug() << "check next" << segments.size(); + for (int i = 0; i < segments.size(); ++i) { + //qDebug() << i << np << pointSegmentsCount(np); + if (np < 0) break; + if (pointSegmentsCount(np) != 2) break; + if (i > 0) { + QLineF l(pol[pp], pol[np]); + //qDebug() << i << l.angle() << angle; + if (qAbs(l.angle() - angle) > 0.1) break; + } + ret << np; + pp = np; + np = neighborSegmentPoint(np, &seg); + } + return ret; + +} + + +int BlockBusItem::pointSegmentsCount(int point, QList * segs) const { + int ret = 0; + if (segs) segs->clear(); + for (int i = 0; i < segments.size(); ++i) + if (segments[i].first == point || segments[i].second == point) { + ret++; + if (segs) segs->append(i); + } + return ret; +} + + +int BlockBusItem::neighborSegmentPoint(int point, int * seg) const { + if (point < 0 || !seg) return -1; + for (int i = 0; i < segments.size(); ++i) { + if (i == *seg) continue; + if (segments[i].first == point) {*seg = i; return segments[i].second;} + if (segments[i].second == point) {*seg = i; return segments[i].first ;} + } + return -1; +} + + +void BlockBusItem::testPoint(QPointF pos, int * sel_point, int * sel_segment) { + for (int i = 0; i < pol.size(); ++i) { + if ((pol[i] - pos).manhattanLength() <= 10.) { // Point + *sel_point = i; + *sel_segment = -1; + return; + } + } + for (int i = 0; i < segments.size(); ++i) { + if (distPointToLine(pol[segments[i].first], pol[segments[i].second], pos) <= 7.) { // Segment + *sel_point = -1; + *sel_segment = i; + return; + } + } + *sel_point = -1; + *sel_segment = -1; +} + + +void BlockBusItem::hoverEnterEvent(QGraphicsSceneHoverEvent * e) { + tt = bus_name + (bus_name.isEmpty() ? "" : "\n\n") + tr("Add point: Ctrl + LeftClick\nRemove point\\segment: Ctrl + RightClick\nNew branch: Shift + LeftClick\nRemove connection: Shift + RightClick"); +} + + +void BlockBusItem::hoverMoveEvent(QGraphicsSceneHoverEvent * e) { + if (temp_) return; + QPointF sp = e->scenePos(); + testPoint(sp, &selPoint, &selSegment); + if (selPoint >= 0 || selSegment >= 0) { + setToolTip(tt); + update(); + return; + } + setToolTip(QString()); + QList il = scene()->items(sp, Qt::ContainsItemBoundingRect, Qt::DescendingOrder), bil; + bil << this; + for (int i = 0; i < il.size(); ++i) { + QGraphicsItem * b = il[i]; + if (b->data(1005) == "connection" && b != this) { + int tp = -1, ts = -1; + ((BlockBusItem*)b)->testPoint(sp, &tp, &ts); + if (tp >= 0 || ts >= 0) { + foreach (QGraphicsItem * b2, bil) + b2->stackBefore(b); + break; + } + bil << b; + } + } + update(); +} + + +void BlockBusItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) { + if (temp_) return; + selPoint = selSegment = -1; + setPen(pu); setBrush(bu); + setToolTip(QString()); + update(); + QGraphicsObject::hoverLeaveEvent(e); +} + + +void BlockBusItem::mousePressEvent(QGraphicsSceneMouseEvent * e) { + if (temp_) return; + lp = quantize(e->scenePos(), grid_step); + if (new_segment) { + QMetaObject::invokeMethod(scene()->views().back(), "newBranchCancel"); + } + new_segment = false; + if ((selPoint < 0 || selPoint > pol.size() - 1) && (selSegment < 0)) { + QGraphicsObject::mousePressEvent(e); + return; + } + int btncnt = 0; + if (e->buttons().testFlag(Qt::LeftButton)) btncnt++; + if (e->buttons().testFlag(Qt::RightButton)) btncnt++; + if (e->buttons().testFlag(Qt::MidButton)) btncnt++; + if (btncnt > 0) mm_mods = e->modifiers(); + //qDebug() << "press" << e; + if (btncnt >= 2 && e->button() == Qt::RightButton) { + mm_cancel = true; + moved = false; + QPointF lp = qp - press_pos; + //qDebug() << lp; + if (selPoint >= 0 && selPoint <= pol.size() - 1) + pol[selPoint] += lp; + if (selSegment >= 0 && selSegment <= segments.size() - 1) { + pol[segments[selSegment].first] += lp; + pol[segments[selSegment].second] += lp; + } + moved = true; + prepareGeometryChange(); + return; + } + if (e->modifiers().testFlag(Qt::ShiftModifier)) { + if (e->buttons().testFlag(Qt::LeftButton)) { + if (selSegment >= 0) + press_pos = quantize(nearestPointOnLine(pol[segments[selSegment].first], pol[segments[selSegment].second], e->scenePos()), grid_step); + else { + if (selPoint >= 0) + press_pos = pol[selPoint]; + else + return; + } + if (max_ep >= 2) { + if (endpointCount() >= max_ep) + if (pointSegmentsCount(selPoint) >= 2 || selSegment >= 0) + return; + } + QMetaObject::invokeMethod(scene()->views().back(), "newBranch", Q_ARG(BlockBusItem * , this)); + new_segment = true; + return; + } + if (e->buttons().testFlag(Qt::RightButton)) { + deleteLater(); + } + } + if (e->modifiers().testFlag(Qt::ControlModifier)) { + if (e->buttons().testFlag(Qt::RightButton)) { + if (selPoint >= 0 && selPoint <= pol.size() - 1) { + removePoint(selPoint); + simplify(); + emitAction(BlockItemBase::BusPointRemove); + return; + } + if (selSegment >= 0 && selSegment <= segments.size() - 1) { + removeSegment(selSegment); + simplify(); + emitAction(BlockItemBase::BusSegmentRemove); + return; + } + } + if (e->buttons().testFlag(Qt::LeftButton) && selSegment >= 0) { + if (addPoint(e->scenePos()) >= 0) + emitAction(BlockItemBase::BusPointAdd); + return; + } + } + if (e->modifiers().testFlag(Qt::ShiftModifier)) { + if (e->buttons().testFlag(Qt::RightButton)) { + if (deleted) return; + deleted = true; + } + } +} + + +void BlockBusItem::mouseMoveEvent(QGraphicsSceneMouseEvent * e) { + if (temp_ || mm_cancel) return; + if (((selPoint < 0 || selPoint > pol.size() - 1) && (selSegment < 0)) && !new_segment) { + QGraphicsObject::mouseMoveEvent(e); + return; + } + qp = quantize(e->scenePos(), grid_step); + lp = qp - lp; + if (e->buttons().testFlag(Qt::LeftButton) && mm_mods.testFlag(Qt::ShiftModifier) && new_segment) { + QMetaObject::invokeMethod(scene()->views().back(), "newBranchTrace", Q_ARG(BlockBusItem * , this), Q_ARG(QPointF, e->scenePos())); + return; + } + if (new_segment) { + new_end = qp; + prepareGeometryChange(); + } else { + if (e->buttons().testFlag(Qt::LeftButton)) { + lm_point = selPoint >= 0; + if (selPoint >= 0 && selPoint <= pol.size() - 1) + pol[selPoint] += lp; + if (selSegment >= 0 && selSegment <= segments.size() - 1) { + pol[segments[selSegment].first] += lp; + pol[segments[selSegment].second] += lp; + } + moved = true; + prepareGeometryChange(); + } + } + lp = qp; +} + + +void BlockBusItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * e) { + mm_mods = 0; + int btncnt = 0; + if (e->buttons().testFlag(Qt::LeftButton)) btncnt++; + if (e->buttons().testFlag(Qt::RightButton)) btncnt++; + if (e->buttons().testFlag(Qt::MidButton)) btncnt++; + if (btncnt == 0) mm_cancel = false; + if (new_segment) { + QMetaObject::invokeMethod(scene()->views().back(), "newBranchAccept", Q_ARG(BlockBusItem * , this)); + updateGeometry(); + selPoint = selSegment = -1; + } + if (moved) { + simplify(false); + reconnect(); + emitAction(lm_point ? BlockItemBase::BusPointMove : BlockItemBase::BusSegmentMove); + } + moved = new_segment = false; + QGraphicsObject::mouseReleaseEvent(e); +} + + +void BlockBusItem::paint(QPainter * p, const QStyleOptionGraphicsItem * o, QWidget * w) { + ph.setWidthF(pen_width + 1.); + pu.setWidthF(pen_width); + pa.setWidthF(pen_width); + pr.setWidthF(pen_width); + pn.setWidthF(pen_width); + if (pol.size() < 2) return; + if (selPoint >= 0 || selSegment >= 0) { + p->setPen(pa); + p->setBrush(ba); + } else { + p->setPen(pu); + p->setBrush(bu); + } + //if (mark_in) {p->setPen(pa); p->setBrush(ba);} + //if (mark_out) {p->setPen(pr); p->setBrush(br);} + if (im_bus.isNull()) { + for (int i = 0; i < segments.size(); ++i) { + p->drawLine(pol[segments[i].first], pol[segments[i].second]); + } + } else { + QBrush br; + br.setTextureImage(im_bus); + for (int i = 0; i < segments.size(); ++i) { + QPointF sp(pol[segments[i].first]), ep(pol[segments[i].second]); + QTransform tf; + tf.translate(sp.x(), sp.y()); + tf.rotate(-QLineF(sp, ep).angle()); + tf.translate(0., -im_bus.height() / 2.); + /* + br.setTransform(tf); + p->setPen(QPen(br, im_bus.height(), Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin)); + p->drawLine(sp, ep); + */ + p->save(); + p->setTransform(tf, true); + p->setPen(Qt::NoPen); + p->setBrush(br); + //p->drawLine(QPointF(0., 0.), QPointF(QLineF(sp, ep).length(), 0.)); + p->drawRect(QRectF(0., 0., QLineF(sp, ep).length(), im_bus.height())); + p->restore(); + } + } + if (!im_end.isNull()) { + for (int i = 0; i < ends_ind.size(); ++i) { + QPointF sp = pol[ends_ind[i].first], ep = pol[ends_ind[i].second]; + QTransform tf; + tf.translate(sp.x(), sp.y()); + tf.rotate(-QLineF(sp, ep).angle()); + tf.translate(-pen_width, -im_end.height() / 2.); + p->save(); + p->setTransform(tf, true); + p->drawImage(0, 0, im_end); + p->restore(); + } + } + if (state_ >= 0) { + if (state_ == 0) { + pr.setWidthF(pen_width + 1.); + p->setPen(pr); + } else if (state_ == 1) { + pa.setWidthF(pen_width + 1.); + p->setPen(pa); + } + p->setOpacity(0.5); + for (int i = 0; i < segments.size(); ++i) { + p->drawLine(pol[segments[i].first], pol[segments[i].second]); + } + p->setOpacity(1.); + } + if (!im_bus.isNull() && (selPoint >= 0 || selSegment >= 0)) { + p->setPen(pa); + p->setBrush(ba); + for (int i = 0; i < segments.size(); ++i) { + p->drawLine(pol[segments[i].first], pol[segments[i].second]); + } + } + //if (mark_in) {p->setPen(pa); p->setBrush(ba);} + //if (mark_out) {p->setPen(pr); p->setBrush(br);} + if (selPoint >= 0) { + p->save(); + p->setPen(ph); + p->setBrush(bh); + p->translate(pol[selPoint]); + p->drawEllipse(QPointF(0, 0), 3, 3); + p->restore(); + } + if (selSegment >= 0) { + p->save(); + p->setPen(ph); + p->drawLine(pol[segments[selSegment].first], pol[segments[selSegment].second]); + p->restore(); + } +} + + +QRectF BlockBusItem::boundingRect() const { + QPolygonF p(pol); + p << new_end; + return enlargedRect(p.boundingRect(), 0, 0, 10.f); +} diff --git a/qad/blockview/blockbusitem.h b/qad/blockview/blockbusitem.h new file mode 100644 index 0000000..2552418 --- /dev/null +++ b/qad/blockview/blockbusitem.h @@ -0,0 +1,119 @@ +#ifndef BLOCKBUSITEM_H +#define BLOCKBUSITEM_H + +#include "blockitem.h" + + +class BlockBusItem: public QGraphicsObject, public PropertyStorage { + //Q_OBJECT + Q_INTERFACES(QGraphicsItem) + //Q_PROPERTY(double width READ width WRITE setWidth) + friend class BlockView; +public: + BlockBusItem(bool temp = false); + BlockBusItem(const BlockBusItem & other); + ~BlockBusItem() {;} + + void setGridStep(double gs) {grid_step = gs;} + void setEndpointsNumber(int num) {max_ep = num;} + void setImages(const QImage & bus, const QImage & end = QImage()) {im_bus = bus; im_end = end;} + void setBusType(int type_) {bus_type = type_;} + void setBusName(const QString & name) {bus_name = name;} + int busType() const {return bus_type;} + QString busName() const {return bus_name;} + void appendPoint(const QPointF & p); + void appendPoint(qreal x, qreal y) {appendPoint(QPointF(x, y));} + void testPoint(QPointF pos, int * sel_point, int * sel_segment); + void clear(); + /*void setStart(const QPointF & p) {pol[0] = p; scene()->update();} + void setStart(qreal x, qreal y) {setStart(QPointF(x, y));} + void setFinish(const QPointF & p) {pol[pol.size() - 1] = p; scene()->update();} + void setFinish(qreal x, qreal y) {setFinish(QPointF(x, y));} + void setPoint(int index, const QPointF & p) {pol[index] = p; scene()->update();} + void setPoint(int index, qreal x, qreal y) {setPoint(index, QPointF(x, y));}*/ + void setPen(const QPen & p) {p_ = p; update();} + QPen pen() const {return p_;} + void setBrush(const QBrush & b) {b_ = b; update();} + QBrush brush() const {return b_;} + //void disconnectBrick() {BrickBase::disconnect(brickFrom, portFrom, brickTo, portTo);} + void movePolyline(const QPointF & dp) {pol.translate(dp); prepareGeometryChange();} + void movePoint(int index, const QPointF & dp) {pol[index] += dp; prepareGeometryChange();} + double width() const {return pen_width;} + void setWidth(const double & w) {pen_width = w; update();} + void setColor(const QColor & c) {pu.setColor(c); bu.setColor(c); update();} + int addPoint(const QPointF & point, bool update = true); + int segmentPointPair(int point, int * seg = 0) const; + void removePoint(int index); + void removeSegment(int index); + void markAsInput(); + void markAsOutput(); + void unmark(); + void simplify(bool full = true); + void adjustLine(); + int endpointCount() const; + bool isBusSelected() const {return selSegment >= 0 || selPoint >= 0;} + QList connectedBlocks() const; + QList connectedPins() const; + + void setBusState(bool state); + bool busState() const {return state_ > 0;} + void clearBusState(); + + QByteArray save() const; + void load(const QByteArray & data); + BlockBusItem * copy() const; + + void saveState(); + void restoreState(); + + enum {Type = UserType + 2}; + +protected: + void _init(); + void reconnect(); + void updateGeometry(); + void checkDelete(); + void emitAction(BlockItemBase::Action a); + QVector endpoints() const; + QVector endpointLine(int ep, double angle) const; + int pointSegmentsCount(int point, QList * segs = 0) const; + int neighborSegmentPoint(int point, int * seg) const; + int type() const {return Type;} + QRectF boundingRect() const; + bool sceneEvent(QEvent * e); + void hoverEnterEvent(QGraphicsSceneHoverEvent * e); + void hoverMoveEvent(QGraphicsSceneHoverEvent * e); + void hoverLeaveEvent(QGraphicsSceneHoverEvent * e); + void mousePressEvent(QGraphicsSceneMouseEvent * e); + void mouseMoveEvent(QGraphicsSceneMouseEvent * e); + void mouseReleaseEvent(QGraphicsSceneMouseEvent * e); + void paint(QPainter * p, const QStyleOptionGraphicsItem * o, QWidget * w = 0); + + QPointF lp, new_start, new_end, press_pos, qp; + QPen p_, ph, pu, pa, pr, pn; + QBrush b_, bh, bu, ba, br; + QString tt, bus_name; + QList > segments, ends_ind, segments_s, ends_ind_s; + QMap connections_; + QVector ends, ends_s; + QImage im_bus, im_end; + QPolygonF pol, bpol, pol_s; + Qt::KeyboardModifiers mm_mods; + bool temp_; + double pen_width, grid_step; + int selPoint, selSegment, max_ep, bus_type, state_; + bool moved, deleted, mark_in, mark_out, new_segment, mm_cancel, lm_point; + +}; + + +inline QDataStream & operator <<(QDataStream & s, const BlockBusItem * b) {s << b->save(); return s;} +inline QDataStream & operator >>(QDataStream & s, BlockBusItem *& b) { + QByteArray ba; s >> ba; + b = new BlockBusItem(); + b->load(ba); + return s; +} + + +#endif // BLOCKBUSITEM_H diff --git a/qad/blockview/blockeditor.cpp b/qad/blockview/blockeditor.cpp new file mode 100644 index 0000000..2bd4560 --- /dev/null +++ b/qad/blockview/blockeditor.cpp @@ -0,0 +1,347 @@ +#include "blockeditor.h" +#include "ui_blockeditor.h" +#include "drawtools.h" +#include "blockview.h" +#include +#include +#include +#include +#include + + +BlockEditor::BlockEditor(QWidget *parent) : QWidget(parent), ui(new Ui::BlockEditor) { + init = false; + ui->setupUi(this); + connect(ui->blockView->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + block.setFlags(0); + ui->blockView->addItem(&block); + ui->blockView->viewport()->installEventFilter(this); + DrawTools * drawtools = new DrawTools(ui->blockView); + drawtools->setAlignCompact(true); + connect(drawtools, SIGNAL(itemCreated(QGraphicsItem*)), this, SLOT(addItem(QGraphicsItem*))); + drawtools->textEditCombo()->addItems(QStringList() << "%name" << "%value" << "%id"); + ui->layoutProperties->addWidget(drawtools->propertyWidget()); + ui->actionRemove_items->setEnabled(false); + ui->button_color->setColor(Qt::lightGray); + ui->treePins->setItemDelegateForColumn(1, new PinBusDelegate()); + connect(ui->treePins, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(updateBlock())); + ui->treePins->viewport()->installEventFilter(this); + + QToolBar * bar; + bar = new QToolBar(ui->widgetBar); + bar->setOrientation(Qt::Vertical); + bar->addActions(drawtools->actionsForAdd()); + ui->widgetBar->setMinimumSize(bar->sizeHint()); + + bar = new QToolBar(ui->widgetBarZ); + bar->setOrientation(Qt::Vertical); + bar->addActions(drawtools->actionsForZ()); + bar->addSeparator(); + bar->addActions(QList() << ui->actionRemove_items); + ui->widgetBarZ->setMinimumSize(bar->sizeHint()); + init = true; + on_buttonClear_clicked(); +} + + +BlockEditor::~BlockEditor() { + init = false; + delete ui; +} + + +void BlockEditor::loadModel(const QByteArray &model) { + BlockItem b; + b.loadModel(model); + ui->spin_w->setValue(b.width()); + ui->spin_h->setValue(b.height()); + ui->spin_margin->setValue(b.pinsMargin()); + ui->button_color->setColor(b.color()); + block.loadModel(model); + treePinsClear(); + ui->treePins->blockSignals(true); + QVector pins = block.pins(); + foreach (BlockItemPin * p, pins) { + QTreeWidgetItem * ti = new QTreeWidgetItem(QStringList() << p->text() << QString::number(p->busType())); + ti->setData(0, Qt::UserRole, qulonglong(p)); + ti->setData(0, Qt::UserRole + 1, (int)p->alignment()); + ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled); + pin_tli[p->alignment()]->addChild(ti); + } + foreach (QGraphicsItem * i, block.decors()) { + i->setData(1002, false); + i->setData(1100, true); + } + ui->treePins->blockSignals(false); +} + + +QByteArray BlockEditor::saveModel() { + return block.saveModel(); +} + + +void BlockEditor::selectionChanged() { + if (!init) return; + ui->actionRemove_items->setEnabled(!ui->blockView->scene()->selectedItems().isEmpty()); +} + + +void BlockEditor::addItem(QGraphicsItem *item) { + block.addDecor(item); + item->setData(1002, false); + item->setData(1100, true); +} + + +void BlockEditor::updateBlock() { + block.setSize(ui->spin_w->value(), ui->spin_h->value()); + block.setColor(ui->button_color->color()); + block.setPinsMargin(ui->spin_margin->value()); +} + + +void BlockEditor::treePinsClear() { + ui->treePins->blockSignals(true); + ui->treePins->clear(); + QFont bf(font()); bf.setBold(true); + QList al = QList() << Qt::AlignLeft << Qt::AlignRight << Qt::AlignTop << Qt::AlignBottom; + QStringList an = QStringList() << "Left" << "Right" << "Top" << "Bottom"; + pin_tli.clear(); + for (int i = 0; i < al.size(); ++i) { + QTreeWidgetItem * ti = new QTreeWidgetItem(); + ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled); + ti->setData(0, Qt::UserRole, al[i]); + ti->setText(0, an[i]); + ti->setFont(0, bf); + ui->treePins->addTopLevelItem(ti); + ti->setFirstColumnSpanned(true); + ti->setExpanded(true); + pin_tli[al[i]] = ti; + } + ui->treePins->blockSignals(false); +} + + +bool BlockEditor::eventFilter(QObject *o, QEvent *e) { + if (!init) QWidget::eventFilter(o, e); + if (o == ui->treePins->viewport()) { + if (e->type() == QEvent::Drop) { + QTimer::singleShot(0, this, SLOT(arrangePins())); + } + } + if (o == ui->blockView->viewport()) { + if (e->type() == QEvent::Resize) { + ui->blockView->centerOn(&block); + } + } + return QWidget::eventFilter(o, e); +} + + +void BlockEditor::on_actionRemove_items_triggered() { + QList si = ui->blockView->scene()->selectedItems(); + foreach (QGraphicsItem * i, si) + block.removeDecor(i); +} + + +void BlockEditor::on_buttonSave_clicked() { + QString c = QFileDialog::getSaveFileName(this, "Save block model to file", cur_file, "*.blockmodel"); + if (!c.isEmpty()) { + QFile f(c); + if (f.open(QIODevice::WriteOnly)) { + cur_file = c; + f.write(saveModel()); + } + } +} + + +void BlockEditor::on_buttonLoad_clicked() { + QString c = QFileDialog::getOpenFileName(this, "Save block model to file", cur_file, "*.blockmodel"); + if (!c.isEmpty()) { + QFile f(c); + if (f.open(QIODevice::ReadOnly)) { + cur_file = c; + loadModel(f.readAll()); + } + } +} + + +void BlockEditor::on_buttonClear_clicked() { + BlockItem b; + ui->spin_w->setValue(b.width()); + ui->spin_h->setValue(b.height()); + ui->spin_margin->setValue(b.pinsMargin()); + ui->button_color->setColor(b.color()); + block.loadModel(QByteArray()); + treePinsClear(); +} + + + +void BlockEditor::on_buttonPinAdd_clicked() { + ui->treePins->blockSignals(true); + QTreeWidgetItem * ti = new QTreeWidgetItem(QStringList() << "" << "0"); + ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled); + ti->setData(0, Qt::UserRole, qulonglong(block.addPin(Qt::AlignLeft, ti->text(1).toInt(), ti->text(0)))); + ti->setData(0, Qt::UserRole + 1, (int)Qt::AlignLeft); + pin_tli[Qt::AlignLeft]->addChild(ti); + ui->treePins->setCurrentItem(ti); + ui->treePins->blockSignals(false); + updateBlock(); +} + + +void BlockEditor::on_buttonPinDup_clicked() { + QTreeWidgetItem * ci = ui->treePins->currentItem(); + if (ci == 0) return; + ui->treePins->blockSignals(true); + QTreeWidgetItem * ti = ci->clone(); + ti->setText(0, ti->text(0)); + ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled); + Qt::Alignment al = (Qt::Alignment)ci->data(0, Qt::UserRole + 1).toInt(); + ti->setData(0, Qt::UserRole, qulonglong(block.addPin(al, ci->text(1).toInt(), ci->text(0)))); + ti->setData(0, Qt::UserRole + 1, (int)al); + pin_tli[al]->addChild(ti); + ui->treePins->setCurrentItem(ti); + ui->treePins->blockSignals(false); +} + + +void BlockEditor::on_buttonPinDelete_clicked() { + ui->treePins->blockSignals(true); + QList si = ui->treePins->selectedItems(); + foreach (QTreeWidgetItem * i, si) { + if (!i->parent()) continue; + block.removePin((BlockItemPin*)(i->data(0, Qt::UserRole).toLongLong())); + delete i; + } + ui->treePins->blockSignals(false); +} + + +void BlockEditor::on_buttonPinClear_clicked() { + treePinsClear(); + block.clearPins(); +} + + +void BlockEditor::on_treePins_itemChanged(QTreeWidgetItem * item, int column) { + if (!item) return; + BlockItemPin * pin = (BlockItemPin*)item->data(0, Qt::UserRole).toULongLong(); + if (!pin) return; + switch (column) { + case 0: + ui->treePins->blockSignals(true); + item->setText(0, item->text(0)); + pin->setText(item->text(0)); + ui->treePins->blockSignals(false); + break; + case 1: pin->setBusType(item->text(1).toInt()); break; + }; +} + + + +void BlockEditor::arrangePins() { + QVector pins = block.pins(); +// block.clearPins(); + QList tli = pin_tli.values(); + foreach (QTreeWidgetItem * ti, tli) { + for (int i = 0; i < ti->childCount(); ++i) { + foreach (BlockItemPin * p, pins) + if (p == (BlockItemPin*)(ti->child(i)->data(0, Qt::UserRole).toULongLong())) { + p->setAlignment((Qt::Alignment)ti->data(0, Qt::UserRole).toInt()); + BlockItemPin * np = block.addPin(p, false); + ti->child(i)->setData(0, Qt::UserRole, qulonglong(np)); + ti->child(i)->setData(0, Qt::UserRole + 1, ti->data(0, Qt::UserRole).toInt()); + break; + } + } + } + +// for (int i = 0; i < ui->treePins->topLevelItemCount(); ++i) { +// QTreeWidgetItem * ti = ui->treePins->topLevelItem(i); +// if (tli.contains(ti)) continue; +// ti = ui->treePins->takeTopLevelItem(i); +// pin_tli[ti->data(0, Qt::UserRole + 1).toInt()]->addChild(ti); +// foreach (BlockItemPin * p, pins) +// if (p->text() == ti->text(0)) { +// p->setAlignment((Qt::Alignment)ti->data(0, Qt::UserRole + 1).toInt()); +// block.addPin(p, false); +// break; +// } +// } + block.arrangePins(); +} + + +/// *********************************************************** +/// *********************************************************** +/// *********************************************************** +/// *********************************************************** + + +QWidget * PinAlignDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const { + QComboBox * combo = new QComboBox(parent); + int cv = index.data().toInt(); + combo->addItem("Left", int(Qt::AlignLeft)); if (cv == Qt::AlignLeft) combo->setCurrentIndex(0); + combo->addItem("Right", int(Qt::AlignRight)); if (cv == Qt::AlignRight) combo->setCurrentIndex(1); + combo->addItem("Top", int(Qt::AlignTop)); if (cv == Qt::AlignTop) combo->setCurrentIndex(2); + combo->addItem("Bottom", int(Qt::AlignBottom)); if (cv == Qt::AlignBottom) combo->setCurrentIndex(3); + combo->setGeometry(option.rect); + return combo; +} + + +QString PinAlignDelegate::displayText(const QVariant & value, const QLocale & locale) const { + int cv = value.toInt(); + switch (cv) { + case Qt::AlignLeft: return "Left"; break; + case Qt::AlignRight: return "Right"; break; + case Qt::AlignTop: return "Top"; break; + case Qt::AlignBottom: return "Bottom"; break; + } + return "unknown"; +} + + +void PinAlignDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { + model->setData(index, ((QComboBox*)editor)->itemData(((QComboBox*)editor)->currentIndex()).toInt()); +} + + +/// *********************************************************** +/// *********************************************************** +/// *********************************************************** +/// *********************************************************** + + +QWidget * PinBusDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const { + QSpinBox * spin = new QSpinBox(parent); + spin->setMinimum(-2147483648); + spin->setMaximum(2147483647); + spin->setValue(index.data().toInt()); + return spin; +} + + +QString PinBusDelegate::displayText(const QVariant & value, const QLocale & locale) const { + int cv = value.toInt(); + return QString::number(cv); +} + + +void PinBusDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { + model->setData(index, ((QSpinBox*)editor)->value()); +} + + + +//void BlockEditor::on_treePins_itemSelectionChanged() { +// arrangePins(); +// qDebug() << "111111111111111"; +//} diff --git a/qad/blockview/blockeditor.h b/qad/blockview/blockeditor.h new file mode 100644 index 0000000..71388b8 --- /dev/null +++ b/qad/blockview/blockeditor.h @@ -0,0 +1,81 @@ +#ifndef BLOCKEDITOR_H +#define BLOCKEDITOR_H + +#include +#include +#include +#include "blockitem.h" + + +namespace Ui { +class BlockEditor; +} + + +class BlockEditor : public QWidget +{ + Q_OBJECT + +public: + explicit BlockEditor(QWidget *parent = 0); + ~BlockEditor(); + + +public slots: + void loadModel(const QByteArray & model); + QByteArray saveModel(); + +private slots: + void selectionChanged(); + void addItem(QGraphicsItem * item); + void updateBlock(); + void treePinsClear(); + void arrangePins(); + void on_actionRemove_items_triggered(); + void on_buttonSave_clicked(); + void on_buttonLoad_clicked(); + void on_buttonClear_clicked(); + void on_buttonPinAdd_clicked(); + void on_buttonPinDup_clicked(); + void on_buttonPinDelete_clicked(); + void on_buttonPinClear_clicked(); + void on_treePins_itemChanged(QTreeWidgetItem *item, int column); +// void on_treePins_itemSelectionChanged(); + +private: + bool eventFilter(QObject * o, QEvent * e); + + Ui::BlockEditor *ui; + QMap pin_tli; + BlockItem block; + QString cur_file; + bool init; +}; + + + +class PinAlignDelegate: public QStyledItemDelegate { + Q_OBJECT +public: + PinAlignDelegate(QObject * parent = 0): QStyledItemDelegate(parent) {} + QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QString displayText(const QVariant & value, const QLocale & locale) const; + void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const {return QSize(60, 26);} +}; + + +class PinBusDelegate: public QStyledItemDelegate { + Q_OBJECT +public: + PinBusDelegate(QObject * parent = 0): QStyledItemDelegate(parent) {} + QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QString displayText(const QVariant & value, const QLocale & locale) const; + void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const {return QSize(60, 26);} +private: + typedef QPair ISPair; + QVector buses; +}; + +#endif // BLOCKEDITOR_H diff --git a/qad/blockview/blockeditor.ui b/qad/blockview/blockeditor.ui new file mode 100644 index 0000000..a07c7ce --- /dev/null +++ b/qad/blockview/blockeditor.ui @@ -0,0 +1,458 @@ + + + BlockEditor + + + + 0 + 0 + 901 + 861 + + + + Form + + + + + + Qt::Vertical + + + + Qt::Horizontal + + + + Block parameters + + + Qt::AlignCenter + + + + 4 + + + + + Width: + + + + + + + 1000 + + + 20 + + + 100 + + + + + + + Heigth: + + + + + + + 1000 + + + 20 + + + 60 + + + + + + + Pins margin: + + + + + + + 100 + + + 10 + + + 10 + + + + + + + Color: + + + + + + + + + + + Pins + + + Qt::AlignCenter + + + + 2 + + + + + + 0 + 200 + + + + QAbstractItemView::InternalMove + + + Qt::MoveAction + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::ScrollPerPixel + + + false + + + false + + + 200 + + + + Name + + + + + Bus + + + + + + + + + + Add + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + Clone + + + + :/icons/edit-copy.png:/icons/edit-copy.png + + + + + + + Qt::Vertical + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + Remove selected + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + Remove all + + + + :/icons/edit-clear.png:/icons/edit-clear.png + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + Save + + + + :/icons/document-save.png:/icons/document-save.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Load + + + + :/icons/document-open.png:/icons/document-open.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Clear + + + + :/icons/edit-clear.png:/icons/edit-clear.png + + + + + + + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + Remove items + + + + + + BlockView + QGraphicsView +
blockview.h
+
+ + ColorButton + QPushButton +
colorbutton.h
+
+
+ + + + + + spin_w + valueChanged(int) + BlockEditor + updateBlock() + + + 170 + 21 + + + 254 + 1 + + + + + spin_h + valueChanged(int) + BlockEditor + updateBlock() + + + 250 + 49 + + + 373 + 5 + + + + + spin_margin + valueChanged(int) + BlockEditor + updateBlock() + + + 350 + 90 + + + 492 + 8 + + + + + button_color + colorChanged(QColor) + BlockEditor + updateBlock() + + + 561 + 115 + + + 613 + 6 + + + + + + updateBlock() + +
diff --git a/qad/blockview/blockeditor_main.cpp b/qad/blockview/blockeditor_main.cpp new file mode 100644 index 0000000..24a6356 --- /dev/null +++ b/qad/blockview/blockeditor_main.cpp @@ -0,0 +1,10 @@ +#include +#include "blockeditor.h" + + +int main(int argc, char * argv[]) { + QApplication a(argc, argv); + BlockEditor w; + w.show(); + return a.exec(); +} diff --git a/qad/blockview/blockitem.cpp b/qad/blockview/blockitem.cpp new file mode 100644 index 0000000..e5ae0b3 --- /dev/null +++ b/qad/blockview/blockitem.cpp @@ -0,0 +1,448 @@ +#include "blockitem.h" + + + +BlockItemPin::BlockItemPin(Qt::Alignment a, int bus_type_, const QString & text_, QGraphicsItem * _parent): QGraphicsItem(_parent), ell_item(this), text_item(this) { + parent_ = 0; + setData(1004, "pin"); + setAcceptHoverEvents(true); + text_item.setData(1002, true); + ell_item.setData(1003, true); + br[Disconnected] = QBrush(Qt::lightGray); + br[Connected] = QBrush(Qt::darkGreen); + br[Hover] = QBrush(Qt::blue); + br[Drop] = QBrush(Qt::green); + br[Accept] = QBrush(Qt::green); + br[Reject] = QBrush(Qt::red); + setState(Disconnected); + setAlignment(a); + setBusType(bus_type_); + setText(text_); + setZValue(2.); + setDirection(BlockItemPin::InputOutput); + _reparent(); +} + + +void BlockItemPin::resizePin(double r) { + ell_item.setRect(-r, -r, r+r, r+r); +} + + +void BlockItemPin::_init(bool affect_parent) { + QRectF tbr = text_item.boundingRect(); + const double r = 7.; + ell_item.setRect(-r, -r, r+r, r+r); + ell_item.setSpanAngle(16*180); + text_item.resetTransform(); + text_item.setPos(0, -tbr.height() / 2.); + text_item.setTransformOriginPoint(0, tbr.height() / 2.); + switch (align) { + case Qt::AlignBottom: ell_item.setStartAngle(16*0); text_item.setRotation(-90.); text_item.moveBy(0, -r * 1.5); break; + case Qt::AlignRight: ell_item.setStartAngle(16*90); text_item.setRotation(0.); text_item.moveBy(-tbr.width() - r * 1.5, 0); break; + case Qt::AlignTop: ell_item.setStartAngle(16*180); text_item.setRotation(-90.); text_item.moveBy(0, tbr.width() + r * 1.5); break; + case Qt::AlignLeft: ell_item.setStartAngle(16*270); text_item.setRotation(0.); text_item.moveBy(r * 1.5, 0); break; + default: break; + } + if (affect_parent && parent_) + parent_->arrangePins(); +} + + +void BlockItemPin::_reparent() { + if (parentItem() == 0) return; + if (qgraphicsitem_cast(parentItem()) == 0) return; + QPen p = qgraphicsitem_cast(parentItem())->g_main.pen(); + ell_item.setPen(p); +} + + +QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { + if (change == QGraphicsItem::ItemParentChange) + _reparent(); + return QGraphicsItem::itemChange(change, value); +} + + +void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) { + bool m_pin_mc(false); + if (scene()) if (!scene()->views().isEmpty()) + QMetaObject::invokeMethod(scene()->views()[0], "getPinMC", Q_ARG(bool*, &m_pin_mc)); + if ((state() != Disconnected) && !m_pin_mc) return; + saveState(); + setState(BlockItemPin::Hover); + update(); +} + + +void BlockItemPin::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) { + restoreState(); + update(); +} + +#define BLOCKITEM_DEFAULT_PIN_MARGIN 20 + +BlockItem::BlockItem(QGraphicsItem * parent): QGraphicsObject(parent), PropertyStorage(), +g_main(this), g_selection(this) { + setData(1006, "item"); + setZValue(1.); + setAcceptHoverEvents(true); + setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); + g_main.setData(1002, true); + g_selection.setData(1007, "item_selection"); + g_selection.setAcceptedMouseButtons(0); + g_selection.setZValue(10.); + g_selection.hide(); + g_selection.setData(1003, true); + col = Qt::lightGray; + _resize(QSizeF(100., 60.)); + QPen p(QColor(128, 128, 255), 1., Qt::DotLine); + p.setCosmetic(true); + g_selection.setPen(p); + g_selection.setBrush(QColor(128, 128, 255, 32)); + pins_margin = BLOCKITEM_DEFAULT_PIN_MARGIN; + //g_main.setBrush(QColor(128, 128, 128, 64)); + /* + BlockItemPin * pin = new BlockItemPin(Qt::AlignRight, 0, this); + pin->setText("text"); + pin->setBusType(0); + addPin(pin); + pin = new BlockItemPin(Qt::AlignTop, this); + pin->setBusType(0); addPin(pin); + pin = new BlockItemPin(Qt::AlignLeft, this); + pin->setBusType(1); addPin(pin); + pin = new BlockItemPin(Qt::AlignRight, this); + pin->setBusType(1); addPin(pin);*/ +} + + +BlockItem::~BlockItem() { + clearDecors(); +} + + +void BlockItem::_resize(QSizeF s) { + g_main.setRect(QRectF(QPointF(), s)); + g_main.setPos(-g_main.rect().center()); + g_selection.setRect(enlargedRect(g_main.rect(), 0, 0, 8)); + g_selection.setPos(g_main.pos()); + QRadialGradient g(g_main.rect().width() / 2., 0, qMax(g_main.rect().width() / 2., g_main.rect().height())); + g.setSpread(QGradient::PadSpread); + g.setCoordinateMode(QGradient::LogicalMode); + g.setColorAt(0., col.darker(120.)); + g.setColorAt(1., col.lighter(120.)); + g_main.setBrush(QBrush(g)); + prepareGeometryChange(); + arrangePins(); +} + + +BlockItemPin * BlockItem::addPin(BlockItemPin * pin, bool update_) { + pin->setParentItem(this); + if (!pins_[pin->alignment()].contains(pin)) pins_[pin->alignment()] << pin; + pin->parent_ = this; + if (update_) + arrangePins(); + return pin; +} + + +BlockItemPin * BlockItem::addPin(Qt::Alignment align, int bus_type, const QString & text, bool update_) { + BlockItemPin * pin = new BlockItemPin(align, bus_type, text, this); + pin->parent_ = this; + pins_[pin->alignment()] << pin; + if (update_) + arrangePins(); + return pin; +} + + +void BlockItem::removePin(BlockItemPin * pin) { + if (!pin) return; + QMutableMapIterator > it(pins_); + while (it.hasNext()) { + it.next(); + it.value().remove(it.value().indexOf(pin)); + } + delete pin; + arrangePins(); +} + + +void BlockItem::addDecor(QGraphicsItem * item) { + if (decors_.contains(item)) return; + if (qgraphicsitem_cast(item)) + qgraphicsitem_cast(item)->setTransformationMode(Qt::SmoothTransformation); + if (qgraphicsitem_cast(item)) + qgraphicsitem_cast(item)->setData(1010, qgraphicsitem_cast(item)->text()); + if (qgraphicsitem_cast(item)) + qgraphicsitem_cast(item)->setData(1010, qgraphicsitem_cast(item)->text()); + item->setData(1002, true); + item->setData(1011, "decor"); + decors_ << item; + item->setParentItem(this); +} + + +void BlockItem::addDecor(QGraphicsItem & item) { + if (decors_.contains(&item)) return; + if (qgraphicsitem_cast(&item)) + qgraphicsitem_cast(&item)->setTransformationMode(Qt::SmoothTransformation); + if (qgraphicsitem_cast(&item)) + qgraphicsitem_cast(&item)->setData(1010, qgraphicsitem_cast(&item)->text()); + if (qgraphicsitem_cast(&item)) + qgraphicsitem_cast(&item)->setData(1010, qgraphicsitem_cast(&item)->text()); + item.setData(1002, true); + item.setData(1011, "decor"); + //decors_ << &item; + item.setParentItem(this); +} + + +void BlockItem::removeDecor(QGraphicsItem * item) { + if (scene() && item) + scene()->sendEvent(item, new QGraphicsSceneEvent(QEvent::Close)); + decors_.removeAll(item); + delete item; +} + + +QVector BlockItem::takePins() { + QVector ret = pins(); + pins_.clear(); + return ret; +} + + +void BlockItem::clearPins() { + QList > mp = pins_.values(); + for (int i = 0; i < mp.size(); ++i) + qDeleteAll(mp[i]); + pins_.clear(); +} + + +void BlockItem::clearDecors() { + bool pbs = false; + if (scene()) pbs = scene()->blockSignals(true); + if (scene()) + foreach (QGraphicsItem * i, decors_) + scene()->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close)); + qDeleteAll(decors_); + decors_.clear(); + if (scene()) { + scene()->blockSignals(pbs); + QMetaObject::invokeMethod(scene(), "selectionChanged"); + } +} + + +QVector BlockItem::pins() const { + QList > mp = pins_.values(); + QVector ret; + for (int i = 0; i < mp.size(); ++i) + ret << mp[i]; + return ret; +} + + +QByteArray BlockItem::saveModel() { + /*QDataStream s(&ret, QIODevice::ReadWrite); + QVector ps = pins(); + s << pos() << rotation() << size() << color() << ps.size(); + foreach (BlockItemPin * p, ps) + s << int(p->alignment()) << p->busType() << p->text() << p->devices(); + s << decors_.size(); + foreach (QGraphicsItem * i, decors_) + s << i;*/ + ChunkStream cs; + cs << cs.chunk(1, pos()) << cs.chunk(2, rotation()) << cs.chunk(3, size()) << cs.chunk(4, color()) << cs.chunk(5, pins()) << cs.chunk(6, decors_) << cs.chunk(7, pins_margin); + return cs.data(); +} + + +void BlockItem::loadModel(const QByteArray & data) { + //qDebug() << "load from" << data.size() << "bytes"; + clearPins(); + clearDecors(); + col = Qt::lightGray; + _resize(QSizeF(100., 60.)); + if (data.isEmpty()) return; + /*QDataStream s(data); + {QPointF _v; s >> _v;} + {qreal _v; s >> _v;} + {QSizeF _v; s >> _v; setSize(_v);} + {QColor _v; s >> _v; setColor(_v);} + int _s; s >> _s; + for (int i = 0; i < _s; ++i) { + BlockItemPin * pin = new BlockItemPin(); + {int _v; s >> _v; pin->setAlignment((Qt::Alignment)_v);} + {int _v; s >> _v; pin->setBusType(_v);} + {QString _v; s >> _v; pin->setText(_v);} + {QMap _v; s >> _v; pin->setDevices(_v);} + addPin(pin); + } + s >> _s; + for (int i = 0; i < _s; ++i) { + if (s.atEnd()) break; + QGraphicsItem * ni = 0; + s >> ni; + if (ni) { + addDecor(ni); + } + }*/ + ChunkStream cs(data); + QVector tp; + QList dl; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: /*setPos(cs.getData());*/ break; + case 2: /*setRotation(cs.getData());*/ break; + case 3: setSize(cs.getData()); break; + case 4: setColor(cs.getData()); break; + case 5: + tp = cs.getData >(); + foreach (BlockItemPin * p, tp) addPin(p); + break; + case 6: + dl = cs.getData >(); + foreach (QGraphicsItem * d, dl) addDecor(d); + break; + case 7: setPinsMargin(cs.getData()); break; + } + } +} + + +QByteArray BlockItem::save() const { + ChunkStream cs; + QMap > pp; + foreach (BlockItemPin * p, pins()) { + pp[p->text()] = p->properties(); + } + cs << cs.chunk(1, pos()) << cs.chunk(2, rotation()) << cs.chunk(3, props) << cs.chunk(5, pp) << cs.chunk(6, size()); + cs << cs.chunk(10, data(2000)) << cs.chunk(11, data(2001)); + return cs.data(); +} + + +void BlockItem::load(const QByteArray & data) { + if (data.isEmpty()) return; + ChunkStream cs(data); + QMap > _p; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: setPos(cs.getData()); break; + case 2: setRotation(cs.getData()); break; + case 3: props = cs.getData >(); break; + case 5: + _p = cs.getData > >(); + foreach (BlockItemPin * p, pins()) + if (_p.contains(p->text())) + p->properties() = _p[p->text()]; + break; + case 6: setSize(cs.getData()); break; + case 10: setData(2000, cs.getData()); break; + case 11: setData(2001, cs.getData()); break; + } + } +} + + +BlockItem * BlockItem::copy() const { + BlockItem * ret = new BlockItem(); + ret->setPos(pos()); + ret->setSize(size()); + ret->setColor(color()); + ret->setSelected(false); + ret->props = props; + ret->setPinsMargin(pinsMargin()); + QVector mp = pins(); + foreach (BlockItemPin * p, mp) { + BlockItemPin * np = new BlockItemPin(); + np->setBusType(p->busType()); + np->setAlignment(p->alignment()); + np->setText(p->text()); + np->setToolTip(p->toolTip()); + np->properties() = p->properties(); + ret->addPin(np); + } + QByteArray ba; + foreach (QGraphicsItem * i, decors_) { + ba.clear(); + QGraphicsItem * ni = 0; + QDataStream s(&ba, QIODevice::ReadWrite); s << i; + QDataStream s2(ba); s2 >> ni; + if (ni) + ret->addDecor(ni); + } + return ret; +} + + +QList BlockItem::connectedBuses() const { + QList ret; + foreach (BlockItemPin * p, pins()) + ret << p->connectedBuses(); + return ret; +} + + +BlockItemPin * BlockItem::pinByText(const QString & t) const { + foreach (BlockItemPin * p, pins()) + if (p->text() == t) + return p; + return 0; +} + + +BlockItemPin * BlockItem::pinAtBus(BlockBusItem * bus) const { + if (bus == 0) return 0; + foreach (BlockItemPin * p, pins()) + if (p->connectedBuses().contains(bus)) + return p; + return 0; +} + + +QRectF BlockItem::boundingRect() const { + return g_main.mapRectToParent(g_main.boundingRect()); +} + + +void BlockItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { + //QGraphicsItem::mouseMoveEvent(event); +} + +#define _POS(m) (i - ((cp.size() - 1) / 2)) * m + +void BlockItem::arrangePins() { + //double w = g_main.rect().width(), h = g_main.rect().height(); + QVector pl = pins(); +// pl = pl.fromList(pins().toList()); + pins_.clear(); + foreach (BlockItemPin * p, pl) + pins_[p->alignment()] << p; + QVector cp = pins_.value(Qt::AlignBottom); + for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(_POS(pins_margin), bottom()); + cp = pins_.value(Qt::AlignTop); + for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(_POS(pins_margin), top()); + cp = pins_.value(Qt::AlignLeft); + for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(left(), _POS(pins_margin)); + cp = pins_.value(Qt::AlignRight); + for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(right(), _POS(pins_margin)); +} + +#undef _POS + + +void BlockItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { + //if () +} + + +QVariant BlockItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { + if (change == QGraphicsItem::ItemSelectedChange) + g_selection.setVisible(value.toBool()); + return QGraphicsItem::itemChange(change, value); +} diff --git a/qad/blockview/blockitem.h b/qad/blockview/blockitem.h new file mode 100644 index 0000000..aa2e763 --- /dev/null +++ b/qad/blockview/blockitem.h @@ -0,0 +1,207 @@ +#ifndef BLOCKITEM_H +#define BLOCKITEM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "blockbase.h" +#include "alignedtextitem.h" +#include "chunkstream.h" + + +/// data: +/// 1002 - flag for move parent (true) +/// 1003 - flag for visualize selection (true) +/// 1004 - BlockItemPin ("pin") +/// 1005 - BlockBusItem ("connection") +/// 1006 - BlockItem ("item") +/// 1007 - BlockItem selection ("item_selection") +/// 1008 - item is NOT decor, ignore for function decors() (true) +/// 1009 - item is scene decor ("decor") +/// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem) +/// 1011 - item is BlockItem decor ("decor") +/// 1100 - flag for correct move (true) + + +class BlockItem; +class BlockBusItem; + + +class BlockItemPin: public QGraphicsItem, public PropertyStorage +{ + friend class BlockView; + friend class BlockItem; +public: + BlockItemPin(Qt::Alignment a = Qt::AlignLeft, int bus_type = 0, const QString & text_ = QString(), QGraphicsItem * parent_ = 0); + + enum State { + Disconnected, + Connected, + Hover, + Drop, + Accept, + Reject + }; + + enum Direction { + None = 0x0, + Input = 0x1, + Output = 0x2, + InputOutput = 0x3 + }; + + void setPen(const QPen & p) {ell_item.setPen(p);} + QPen pen() const {return ell_item.pen();} + void setBrush(const QBrush & b) {ell_item.setBrush(b);} + QBrush brush() const {return ell_item.brush();} + + int busType() const {return bus_type;} + Qt::Alignment alignment() const {return align;} + Direction direction() const {return dir;} + QString text() const {return text_item.text();} + State state() const {return state_;} + + void setBusType(int type_) {bus_type = type_;} + void setAlignment(Qt::Alignment a) {align = a; _init(true);} + void setDirection(Direction d) {dir = d; _init(true);} + void setText(const QString & t) {text_item.setText(t); _init(true);} + void setState(State s) {state_ = s; setBrush(br[int(state_)]); update();} + + void saveState() {sstate_.push(state_);} + bool restoreState() {if (sstate_.isEmpty()) return false; setState(sstate_.pop()); return true;} + void clearStateStack() {sstate_.clear();} + + void resizePin(double r = 7.); + + BlockItem * parent() const {return parent_;} + QList connectedBuses() const {return buses_;} + + enum {Type = UserType + 3}; + +protected: + void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {} + QRectF boundingRect() const {return ell_item.boundingRect().translated(ell_item.pos()) | text_item.boundingRect().translated(text_item.pos());} + int type() const {return Type;} + QVariant itemChange(GraphicsItemChange change, const QVariant & value); + void hoverEnterEvent(QGraphicsSceneHoverEvent * e); + void hoverLeaveEvent(QGraphicsSceneHoverEvent * e); + void _init(bool affect_parent = false); + void _reparent(); + int bus_type; + State state_; + QGraphicsEllipseItem ell_item; + QGraphicsSimpleTextItem text_item; + QStack sstate_; + QList buses_; + BlockItem * parent_; + Qt::Alignment align; + Direction dir; + QBrush br[6]; + +}; + + + + +class BlockItem: public QGraphicsObject, public PropertyStorage +{ + friend class BlockView; + friend class BlockItemPin; + friend class DrawTools; + Q_OBJECT +public: + BlockItem(QGraphicsItem * parent = 0); + ~BlockItem(); + + BlockItem * copy() const; + BlockItemPin * addPin(BlockItemPin * pin, bool update_ = true); + BlockItemPin * addPin(Qt::Alignment align, int bus_type, const QString & text, bool update_ = true); + void removePin(BlockItemPin * pin); + void addDecor(QGraphicsItem * item); + void addDecor(QGraphicsItem & item); + void removeDecor(QGraphicsItem * item); + QVector takePins(); + void clearPins(); + void clearDecors(); + QVector pins() const; + QList decors() const {return decors_;} + QList connectedBuses() const; + BlockItemPin * pinByText(const QString & t) const; + BlockItemPin * pinAtBus(BlockBusItem * bus) const; + QColor color() const {return col;} + void setColor(QColor c) {col = c; _resize(size());} + QSizeF size() const {return g_main.rect().size();} + qreal width() const {return size().width();} + qreal height() const {return size().height();} + int pinsMargin() const {return pins_margin;} + void setSize(QSizeF s) {_resize(s);} + void setSize(qreal w, qreal h) {setSize(QSizeF(w, h));} + void setWidth(qreal w) {setSize(QSizeF(w, size().height()));} + void setHeight(qreal h) {setSize(QSizeF(size().width(), h));} + void setPinsMargin(int marg) {if (marg > 1 && marg < 256) pins_margin = marg; arrangePins();} + + QByteArray saveModel(); + void loadModel(const QByteArray & data); + QByteArray save() const; + void load(const QByteArray & data); + void arrangePins(); + + enum {Type = UserType + 1}; + +protected: + void _resize(QSizeF s); + int type() const {return Type;} + QRectF boundingRect() const; + void mouseMoveEvent(QGraphicsSceneMouseEvent * event); + double left() const {return boundingRect().left();} + double right() const {return boundingRect().right();} + double top() const {return boundingRect().top();} + double bottom() const {return boundingRect().bottom();} + void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0); + QVariant itemChange(GraphicsItemChange change, const QVariant & value); + + QGraphicsRectItem g_main, g_selection; + int pins_margin; + QColor col; + QMap > pins_; + QList decors_; + +}; + + +inline QDataStream & operator <<(QDataStream & s, const BlockItemPin * p) { + ChunkStream cs; + cs << cs.chunk(1, int(p->alignment())) << cs.chunk(2, p->busType()) << cs.chunk(3, p->text()) << cs.chunk(4, p->toolTip()); + s << cs.data(); return s;} +inline QDataStream & operator >>(QDataStream & s, BlockItemPin *& p) { + ChunkStream cs(s); + p = new BlockItemPin(); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: p->setAlignment((Qt::Alignment)cs.getData()); break; + case 2: p->setBusType(cs.getData()); break; + case 3: p->setText(cs.getData()); break; + case 4: p->setToolTip(cs.getData()); break; + } + } + return s; +} + + +inline QDataStream & operator <<(QDataStream & s, const BlockItem * b) {s << b->save(); return s;} +inline QDataStream & operator >>(QDataStream & s, BlockItem *& b) { + QByteArray ba; s >> ba; + b = new BlockItem(); + b->load(ba); + return s; +} + + +#endif // BLOCKITEM_H diff --git a/qad/blockview/blockview.cpp b/qad/blockview/blockview.cpp new file mode 100644 index 0000000..92b7ac2 --- /dev/null +++ b/qad/blockview/blockview.cpp @@ -0,0 +1,1630 @@ +#include "blockview.h" +#include +#include +#include +#include +#include +#include +#include +#include + +const QString _BlockView_Mime_ = "_BlockView_copypaste_"; + + +BlockView::BlockView(QWidget * parent): QGraphicsView(parent), tmp_bus(true) { + _init(); +} + + +BlockView::BlockView(QGraphicsScene * scene, QWidget * parent): QGraphicsView(scene, parent), tmp_bus(true) { + _init(); +} + + +BlockView::~BlockView() { +} + + +void BlockView::_init() { + if (scene() == 0) { + scene_ = new QGraphicsScene; + setScene(scene_); + } + scene_ = scene(); + scene_->setSceneRect(-2500, -2500, 5000, 5000); + scene_->setItemIndexMethod(QGraphicsScene::NoIndex); + scene_->installEventFilter(this); + scene_->addItem(&tmp_bus); + widget_thumb.setParent(this); + //widget_thumb.setAutoFillBackground(true); + //widget_thumb.setStyleSheet("background-color: rgb(255, 0, 0);"); + widget_thumb.installEventFilter(this); + widget_thumb.setMouseTracking(true); + widget_thumb.show(); + widget_thumb.setWindowOpacity(0.); + thumb_anim.setTargetObject(this); + thumb_anim.setPropertyName("_thumb"); + thumb_anim.setEasingCurve(QEasingCurve::InCubic); + connect(scene_, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(adjustThumb())); + connect(scene_, SIGNAL(selectionChanged()), this, SLOT(sceneSelectionChanged())); + centerOn(scene_->sceneRect().center()); + setCacheMode(CacheBackground); + setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + setResizeAnchor(QGraphicsView::AnchorUnderMouse); + setRenderHint(QPainter::Antialiasing); + setRenderHint(QPainter::SmoothPixmapTransform); + setMouseTracking(true); + grid_visible = grid_snap = pm_connect = navigation = m_connect = m_trace_with_buses = minimap = true; + mm_drag = moved = new_branch = new_bus = mm_cancel = iconnect = mm_copy = m_pin_mc = mm_thumb = false; + match_bus = bus_from = 0; + mm_ci = 0; + hpin = 0; + grid_step = 10.; + grid_points = 1; + grid_pen = QPen(Qt::lightGray, 1, Qt::NoPen); + thumb_hide_delay = 500; + smode = BlockView::MultiSelection; + cur_scl = thumb_scl = 1.; + _talpha = 0.; + ae_enabled = true; + thumb_size = QSizeF(200, 200); + sel_rect.setZValue(999.); + sel_rect.hide(); + QColor sc = palette().color(QPalette::Highlight); + sc.setAlphaF(0.6); + QPen pen(sc.darker(200), 2., Qt::DotLine); + pen.setCosmetic(true); + sel_rect.setPen(pen); + sc.setAlphaF(0.2); + sel_rect.setBrush(QBrush(sc)); + + /*AlignedTextItem * ti = new AlignedTextItem("This is text!"); + ti->setFlag(QGraphicsItem::ItemIsSelectable, true); + ti->setFlag(QGraphicsItem::ItemIsMovable, true); + addItem(ti); + ti->setAlignment(Qt::AlignBottom | Qt::AlignLeft); + ti->setText("text\nt"); + QGraphicsSimpleTextItem * t__ = new QGraphicsSimpleTextItem("TEXT"); + t__->setFlags(QGraphicsItem::ItemIsSelectable); + addItem(t__); + addItem(new QGraphicsLineItem(0, -50, 0, 50)); + addItem(new QGraphicsLineItem(-50, 0, 50, 0)); + + for (int i = 0; i < 5; ++i) { + BlockItem * it = new BlockItem(); + it->setPos(i*150, i*20); + it->addPin(new BlockItemPin()); + if (i == 2) + it->setFlags(QGraphicsItem::ItemIsSelectable); + scene_->addItem(it); + } + QGraphicsItem * it = new QGraphicsRectItem(0, 0, 200, 100); + it->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); + it->setData(1001, true); + scene_->addItem(it); + + BlockBusItem * bus = new BlockBusItem(); + bus->setImages(QImage("icons/bus_twin.png"), QImage("icons/bus_end_rj45.png")); + bus->setEndpointsNumber(3); + bus->setBusType(1); + bus->appendPoint(QPointF(20, 40)); + bus->appendPoint(QPointF(150, -20)); + bus->appendPoint(QPointF(40, -80)); + //bus->setImages(QImage("icons/bus_twin.png"), QImage("icons/bus_end_rj45.png")); + addItem(bus); + bus = new BlockBusItem(); + bus->appendPoint(QPointF(-20, 40)); + bus->appendPoint(QPointF(100, -30)); + bus->appendPoint(QPointF(20, -60)); + addItem(bus);*/ +} + + +void BlockView::_updateBack() { + setCacheMode(CacheNone); + invalidateScene(); + setCacheMode(CacheBackground); +} + + +bool BlockView::eventFilter(QObject * o, QEvent * e) { + if (o == &widget_thumb) { + QMouseEvent * me = (QMouseEvent*)e; + switch (e->type()) { + case QEvent::Paint: + drawThumb(); + return true; + case QEvent::Enter: + thumbShow(); + break; + case QEvent::Leave: + restartTimer(timer_thumb, thumb_hide_delay); + break; + case QEvent::MouseButtonPress: + thumb_press = me->pos(); + widget_thumb.setCursor(Qt::ClosedHandCursor); + if (!thumb_vr.contains(thumb_press)) { + thumb_vr.moveCenter(thumb_press); + scrollFromThumb(); + } + break; + case QEvent::MouseButtonRelease: + widget_thumb.setCursor(Qt::OpenHandCursor); + break; + case QEvent::MouseMove: + if (me->buttons() == 0) + widget_thumb.setCursor(thumb_vr.contains(me->pos()) ? Qt::OpenHandCursor : Qt::CrossCursor); + if (me->buttons().testFlag(Qt::LeftButton)) { + thumb_vr.translate(me->pos() - thumb_press); + scrollFromThumb(); + thumb_press = me->pos(); + } + break; + default: break; + } + return QGraphicsView::eventFilter(o, e); + } + if (o == scene_) { + QGraphicsSceneMouseEvent * me = (QGraphicsSceneMouseEvent*)e; + QList mil; + QPointF mdp; + bool fmm_drag = false; + int btncnt = 0; + switch (e->type()) { + case QEvent::GraphicsSceneMouseDoubleClick: + mil = scene_->items(scene_point); + foreach (QGraphicsItem * i, mil) { + if (i->data(1006) == "item") { + emit blockDoubleClicked((BlockItem * )i); + break; + } + if (i->data(1005) == "connection") { + if (qgraphicsitem_cast(i)->isBusSelected()) { + emit busDoubleClicked(qgraphicsitem_cast(i)); + break; + } + } + } + //return true; + break; + /*case QEvent::GraphicsSceneHoverMove: + mil = scene_->items(scene_point); + mm_ci = (mil.isEmpty() ? 0 : mil.front()); + if (mm_ci != 0) { + while (mm_ci->data(1005).toString() == "connection") { + if (qgraphicsitem_cast(mm_ci)) + if (qgraphicsitem_cast(mm_ci)->isBusSelected()) + break; + if (mil.size() > 1) { + mm_ci = mil[1]; + mil.pop_front(); + } else { + mm_ci = 0; + break; + } + } + } + break;*/ + case QEvent::GraphicsSceneMousePress: + if (mm_ci != 0) + if (mm_ci->data(1008).toBool()) + break; + //qDebug() << "press"; + if (me->buttons().testFlag(Qt::LeftButton)) btncnt++; + if (me->buttons().testFlag(Qt::RightButton)) btncnt++; + if (me->buttons().testFlag(Qt::MidButton)) btncnt++; + mm_cancel = btncnt >= 2; + match_bus = bus_from = 0; + hpin = 0; + copy_dp = QPointF(); + //qDebug() << mm_cancel << mm_copy << mm_drag << new_branch << new_bus; + if (mm_copy && mm_cancel) { + deleteCopyTemp(); + mm_copy = moved = false; + unsetCursor(); + } + if (new_bus && mm_cancel) { + new_bus = false; + unmarkPins(true); + reconnectAll(); + tmp_bus.hide(); + tmp_bus.clear(); + } + if (new_branch && mm_cancel) { + new_branch = false; + tmp_bus.hide(); + tmp_bus.clear(); + } + if (moved && mm_cancel) { + moved = false; + restoreSelState(); + tmp_bus.hide(); + tmp_bus.clear(); + } + if (mm_cancel) return true; + mm_mods = me->modifiers(); + mm_drag = moved = false; + screen_point = me->screenPos(); + scene_point = me->scenePos(); + if (me->button() == Qt::MidButton) { + thumbShow(); + restartTimer(timer_thumb, thumb_hide_delay); + return true; + } + mil = scene_->items(scene_point); + mm_ci = (mil.isEmpty() ? 0 : mil.front()); + if (mil.isEmpty()) return true; + if (mm_ci != 0) { + if (mm_ci->data(1008).toBool()) + break; + while (mm_ci->data(1005).toString() == "connection") { + if (qgraphicsitem_cast(mm_ci)) + if (qgraphicsitem_cast(mm_ci)->isBusSelected()) + break; + if (mil.size() > 1) { + mm_ci = mil[1]; + mil.pop_front(); + } else { + mm_ci = 0; + break; + } + } + if (mm_ci->data(1003).toBool()) { + if (mil.size() > 1) { + mm_ci = mil[1]; + mil.pop_front(); + if (mm_ci->data(1003).toBool()) + if (mil.size() > 1) + mm_ci = mil[1]; + } else + mm_ci = 0; + } + if (mm_ci->data(1002).toBool()) { + while (mm_ci->parentItem() != 0) + mm_ci = mm_ci->parentItem(); + return true; + } + } + if (mm_ci) { + if (mm_ci->data(1004) == "pin" && m_connect) { + if (qgraphicsitem_cast(mm_ci)->state() == BlockItemPin::Hover) { + trace_from = mm_ci->scenePos(); + qgraphicsitem_cast(mm_ci)->clearStateStack(); + tmp_bus.setBusType(qgraphicsitem_cast(mm_ci)->busType()); + tmp_bus.setEndpointsNumber(3); + tmp_bus.clear(); + tmp_bus.show(); + new_bus = true; + newBusStarted(tmp_bus.busType()); + markPins(tmp_bus.busType()); + if (qgraphicsitem_cast(mm_ci)->alignment() == Qt::AlignLeft || + qgraphicsitem_cast(mm_ci)->alignment() == Qt::AlignRight) + wavetrace.setPreferredDirection(BlockViewWavetrace::Horizontal); + else + wavetrace.setPreferredDirection(BlockViewWavetrace::Vertical); + } + } + } + cur_scl = qSqrt(transform().determinant()); + //return true; + break; + case QEvent::GraphicsSceneMouseMove: + //qDebug() << "move" << (mm_ci != 0 ? mm_ci : 0); + if (mm_ci) + if (mm_ci->data(1008).toBool()) + break; + if (mm_cancel) return true; + if (me->buttons().testFlag(Qt::LeftButton)) { + if (!mm_drag) { + if ((screen_point - me->screenPos()).manhattanLength() >= QApplication::startDragDistance()) { + mm_drag = fmm_drag = true; + saveBusesState(); + } + } else { + if (tmp_bus.isVisible()) { + mil = scene_->items(me->scenePos()); + hpin = 0; + foreach (QGraphicsItem * i, mil) + if (i->data(1004) == "pin") { + hpin = qgraphicsitem_cast(i); + break; + } + if (hpin) { + if (hpin->state() == BlockItemPin::Accept) + hoverAcceptedPin(hpin); + else + hpin = 0; + } else + unhoverPins(); + if (new_branch) { + matchBus(); + break; + } + trace(trace_from, me->scenePos(), &tmp_bus); + matchBus(); + } + } + if (mm_mods.testFlag(Qt::ShiftModifier)) { + if (fmm_drag) { + fmm_drag = false; + if (mm_ci) { + if ((mm_ci->data(1006) == "item")) { + if (!mm_ci->isSelected() && sel_items.isEmpty()) { + clearSelection(); + mm_ci->setSelected(true); + } + } else { + mm_ci = 0; + break; + } + } else { + break; + } + sel_items = scene_->selectedItems(); + deleteCopyTemp(); + QList bi; + foreach (QGraphicsItem * i, sel_items) { + if (i->data(1006) == "item") { + //qDebug() << "copy"; + bi << qgraphicsitem_cast(i); + BlockItem * ti = bi.back()->copy(); + ti->g_main.setPen(QPen(ti->g_main.pen().color(), ti->g_main.pen().widthF(), Qt::DashLine)); + QColor bc = ti->g_main.brush().color(); bc.setAlphaF(bc.alphaF() * 0.5); + ti->g_main.setBrush(bc); + copy_items << ti; + scene_->addItem(ti); + } + } + QList ibi = internalBuses(bi); + foreach (BlockBusItem * i, ibi) { + i = i->copy(); + i->setOpacity(i->opacity() * 0.5); + copy_buses << i; + scene_->addItem(i); + } + mm_copy = true; + setCursor(Qt::DragCopyCursor); + } + } else { + if (smode == BlockView::SingleSelection) { + if (fmm_drag) { + clearSelection(); + if (mm_ci != 0) { + mm_ci->setSelected(true); + } + saveSelState(); + } + } + if (smode == BlockView::MultiSelection) { + sel_rect.setRect(QRectF(scene_point, me->scenePos()).normalized()); + if (fmm_drag) { + if (mm_ci == 0) { + scene_->addItem(&sel_rect); + sel_rect.show(); + if (!mm_mods.testFlag(Qt::ControlModifier)) + clearSelection(); + } else { + if (!mm_mods.testFlag(Qt::ControlModifier) && !mm_ci->isSelected()) { + clearSelection(); + mm_ci->setSelected(true); + } + } + saveSelState(); + if (mm_ci != 0) + if (!sel_items.contains(mm_ci)) + mm_ci = 0; + } + } + } + if (sel_rect.isVisible()) + applySelRect(me); + else { + if (mm_drag && mm_ci != 0) { + mdp = (me->scenePos() - scene_point); + if (grid_snap) + mdp = quantize(mdp, grid_step); + if (!mdp.isNull()) { + scene_point += mdp; + copy_dp += mdp; + } + if (mm_copy) { + if (!mdp.isNull()) + moved = true; + foreach (QGraphicsItem * i, copy_items) + i->setPos(i->pos() + mdp); + foreach (BlockBusItem * i, copy_buses) + i->movePolyline(mdp); + } + if (!mm_mods.testFlag(Qt::ControlModifier) && !mm_mods.testFlag(Qt::ShiftModifier)) { + if (!mdp.isNull()) + moved = true; + foreach (QGraphicsItem * i, sel_items) + if (i->flags().testFlag(QGraphicsItem::ItemIsMovable)) + i->setPos(i->pos() + mdp); + moveBuses(sel_items, mdp); + setCursor(Qt::ClosedHandCursor); + } + return true; + } + } + if (mm_ci) + if (mm_ci->data(1100).toBool()) + return true; + } + if (me->modifiers().testFlag(Qt::ControlModifier) && me->buttons() != 0 && mm_ci == 0) + return true; + //qDebug() << "scene mouse"; + //return true; + break; + case QEvent::GraphicsSceneMouseRelease: + if (me->buttons().testFlag(Qt::LeftButton)) btncnt++; + if (me->buttons().testFlag(Qt::RightButton)) btncnt++; + if (me->buttons().testFlag(Qt::MidButton)) btncnt++; + mm_cancel = btncnt > 0; + if (mm_cancel || me->button() == Qt::MidButton) { + mm_ci = 0; + return true; + } + if (mm_ci) + if (mm_ci->data(1008).toBool()) { + mm_ci = 0; + break; + } + if (mm_copy) { + QList ai; + blockSignals(true); + if (moved) { + QList ci; + QList bi; + foreach (QGraphicsItem * b, sel_items) + if (b->data(1006) == "item") { + ci << qgraphicsitem_cast(b); + ai << qgraphicsitem_cast(b); + } + bi = internalBuses(ci); + if (!ci.isEmpty()) copyBlocks(ci, copy_dp); + if (!bi.isEmpty()) copyBuses(bi, copy_dp); + } + deleteCopyTemp(); + blockSignals(false); + if (moved) { + moved = false; + reconnectAll(); + emitActionEvent(BlockItemBase::BlockCopy, ai); + } + } + if (new_branch) { + tmp_bus.hide(); + } + if (moved && pm_connect) { + QList ci; + foreach (QGraphicsItem * b, sel_items) + if (b->data(1006) == "item") + ci << b; + simplifyBuses(); + emitActionEvent(BlockItemBase::BlockMove, ci); + reconnectAll(); + } + moved = mm_copy = false; + if (tmp_bus.isVisible()) { + //qDebug() << "!!!"; + if (match_bus == 0) { + BlockBusItem * nb = new BlockBusItem(tmp_bus); + loadBus(nb); + addItem(nb); + } else { + if (connectTmpToBus(match_bus)) { + emitActionEvent(BlockItemBase::BusAdd, QList() << match_bus); + emit connectionsChanged(); + } + } + unmarkPins(); + tmp_bus.hide(); + tmp_bus.clear(); + reconnectAll(); + } + clearBusStates(); + if (!mm_drag) { + switch (smode) { + case SingleSelection: + clearSelection(); + if (mm_ci) + mm_ci->setSelected(true); + break; + case MultiSelection: + if (mm_ci == 0 || !me->modifiers().testFlag(Qt::ControlModifier)) { + clearSelection(); + if (mm_ci) + mm_ci->setSelected(true); + } else { + if (mm_ci != 0) { + if (me->modifiers().testFlag(Qt::ControlModifier)) { + if (mm_ci->data(1006) == "item") + mm_ci->setSelected(!mm_ci->isSelected()); + } else + mm_ci->setSelected(true); + } + } + break; + default: + clearSelection(); + break; + } + } + sel_rect.hide(); + if (sel_rect.scene()) + scene_->removeItem(&sel_rect); + mm_drag = false; + mm_ci = 0; + unsetCursor(); + break; + default: break; + } + } + return QGraphicsView::eventFilter(o, e); +} + + +void BlockView::stopTimer(int & tid) { + if (tid > 0) killTimer(tid); + tid = 0; +} + + +void BlockView::restartTimer(int & tid, int msecs) { + stopTimer(tid); + tid = startTimer(msecs); +} + + +void BlockView::timerEvent(QTimerEvent * e) { + if (e->timerId() == timer_thumb) { + thumbHide(); + stopTimer(timer_thumb); + return; + } + QGraphicsView::timerEvent(e); +} + + +void BlockView::wheelEvent(QWheelEvent * event) { + if (!navigation) return; + if (event->modifiers().testFlag(Qt::ControlModifier)) { + double scl = 1. + event->delta() / 500.; + scale(scl, scl); + return; + } + QGraphicsView::wheelEvent(event); +} + + +void BlockView::mousePressEvent(QMouseEvent * event) { + press_point = event->pos(); + QGraphicsView::mousePressEvent(event); +} + + +void BlockView::mouseMoveEvent(QMouseEvent * event) { + if (navigation) { + if (event->buttons().testFlag(Qt::MidButton)) { + QPoint dp = (press_point - event->pos()); + horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dp.x()); + verticalScrollBar()->setValue(verticalScrollBar()->value() + dp.y()); + press_point = event->pos(); + return; + } + } + QGraphicsView::mouseMoveEvent(event); +} + + +void BlockView::keyPressEvent(QKeyEvent * e) { + if (e->key() == Qt::Key_Shift) { + if (tmp_bus.isVisible()) { + wavetrace.setPreferredDirection((BlockViewWavetrace::Direction)(1 - wavetrace.preferredDirection())); + trace(last_trace_from, trace_to, &tmp_bus); + } + return; + } + QGraphicsView::keyPressEvent(e); +} + + +void BlockView::resizeEvent(QResizeEvent * event) { + QGraphicsView::resizeEvent(event); + adjustThumb(); +} + + +void BlockView::scrollContentsBy(int dx, int dy) { + QGraphicsView::scrollContentsBy(dx, dy); + if (isHidden()) return; + thumbShow(); + restartTimer(timer_thumb, thumb_hide_delay); + QMetaObject::invokeMethod(&widget_thumb, "repaint", Qt::QueuedConnection); +} + + +void BlockView::drawBackground(QPainter * painter, const QRectF & rect) { + QGraphicsView::drawBackground(painter, rect); + if (mm_thumb) return; + float rx, ry, sx = grid_step, sy = grid_step; + double scl = qRound(1. / qSqrt(transform().determinant())); + painter->eraseRect(rect); + painter->setRenderHint(QPainter::Antialiasing, false); + if (scl > 0.) { + sx *= scl; + sy *= scl; + } + if (!grid_visible) return; + rx = quantize(rect.left(), sx); + ry = quantize(rect.top(), sy); + bool gp = grid_points > 0.5; + if (gp) { + QPen pp(grid_pen.color(), grid_points, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + pp.setCosmetic(true); + painter->setPen(pp); + for(int i = 0; i < qCeil(rect.width() / sx) + 1; ++i) + for(int j = 0; j < qCeil(rect.height() / sy) + 1; ++j) + painter->drawPoint(rx + i * sx, ry + j * sy); + } + if (grid_pen.style() == Qt::NoPen) return; + painter->setPen(grid_pen); + for(int i = 0; i < qCeil(rect.width() / sx) + 1; ++i) { + double cx = rx + i * sx; + painter->drawLine(cx, ry, cx, ry + rect.height()); + } + for(int j = 0; j < qCeil(rect.height() / sy) + 1; ++j) { + double cy = ry + j * sy; + painter->drawLine(rx, cy, rx + rect.width(), cy); + } +} + + +void BlockView::scrollFromThumb() { + QRect r(thumb_vr); + double scl(thumb_scl); + horizontalScrollBar()->setValue(r.x() / scl + horizontalScrollBar()->minimum()); + verticalScrollBar()->setValue(r.y() / scl + verticalScrollBar()->minimum()); +} + + +void BlockView::deleteCopyTemp() { + qDeleteAll(copy_items); + copy_items.clear(); + qDeleteAll(copy_buses); + copy_buses.clear(); +} + + +void BlockView::emitActionEvent(BlockItemBase::Action action, QList items) { + if (!ae_enabled) return; + emit actionEvent(action, items); +} + + +void BlockView::drawThumb() { + if (!minimap) return; + QPainter p(&widget_thumb); + QRect wr = widget_thumb.rect().adjusted(0, 0, -1, -1); + QSizeF sr = sceneRect().size(), tr; + if (sr.width() >= sr.height()) + thumb_scl = thumb_size.width() / sr.width(); + else + thumb_scl = thumb_size.height() / sr.height(); + tr = sr * thumb_scl; + cur_scl = qSqrt(transform().determinant()); + thumb_scl /= cur_scl; + QSizeF vs(size().width() - verticalScrollBar()->width(), size().height() - horizontalScrollBar()->height()); + QRectF vr(QPointF(horizontalScrollBar()->value() - horizontalScrollBar()->minimum(), + verticalScrollBar()->value() - verticalScrollBar()->minimum()) * thumb_scl, vs * thumb_scl); + vr.adjust(0, 0, -1, -1); + + p.setBrush(Qt::lightGray); + p.setOpacity(0.5 * _talpha); + p.drawRect(wr); + p.drawImage(0, 0, im_scene); + p.setBrush(Qt::NoBrush); + p.drawRect(wr); + p.setBrush(Qt::white); + p.setRenderHint(QPainter::Antialiasing); + p.drawRect(vr); + thumb_sr = wr; + thumb_vr = vr.toRect(); +} + + +void BlockView::drawSceneThumb() { + if (!minimap) return; + QRect wr = widget_thumb.rect().adjusted(0, 0, -1, -1); + im_scene = QImage(wr.size(), QImage::Format_ARGB32); + im_scene.fill(Qt::transparent); + QPainter p(&im_scene); + p.setRenderHint(QPainter::Antialiasing); + mm_thumb = true; + scene_->render(&p, im_scene.rect()); + mm_thumb = false; +} + + +void BlockView::thumbHide() { + if (!minimap) { + widget_thumb.hide(); + return; + } + if (QApplication::widgetAt(QCursor::pos()) == &widget_thumb) return; + thumb_anim.stop(); + thumb_anim.setDuration(1000); + thumb_anim.setStartValue(_thumb()); + thumb_anim.setEndValue(0.); + thumb_anim.start(); + //qDebug() << "hide" << thumb_anim.startValue() << thumb_anim.endValue(); + //widget_thumb.hide(); +} + + +void BlockView::thumbShow() { + if (!minimap) return; + if (widget_thumb.isHidden() || (_talpha < 0.1)) drawSceneThumb(); + thumb_anim.stop(); + /*thumb_anim.setDuration(100); + thumb_anim.setStartValue(_thumb()); + thumb_anim.setEndValue(1.); + thumb_anim.start();*/ + _setThumb(1.); + //qDebug() << "show" << thumb_anim.startValue() << thumb_anim.endValue(); + //widget_thumb.show(); +} + + +void BlockView::clearSelection() { + sel_items.clear(); + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + i->setSelected(false); +} + + +void BlockView::addItem(QGraphicsItem * item) { + scene_->addItem(item); + applyGridStep(); + if (item->data(1005) == "connection") { + loadBus(qgraphicsitem_cast(item)); + connect((BlockBusItem*)item, SIGNAL(destroyed(QObject*)), this, SLOT(removedBus(QObject*)), Qt::UniqueConnection); + emitActionEvent(BlockItemBase::BusAdd, QList() << item); + emit connectionsChanged(); + return; + } + if (item->data(1006) == "item") { + connect((BlockItem*)item, SIGNAL(destroyed(QObject*)), this, SLOT(removedBlock(QObject*)), Qt::UniqueConnection); + emitActionEvent(BlockItemBase::BlockAdd, QList() << item); + return; + } + item->setData(1009, "decor"); +} + + +QList BlockView::buses() const { + QList ret; + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->data(1005) == "connection") + if (!copy_buses.contains((BlockBusItem*)i)) + ret << qgraphicsitem_cast(i); + return ret; +} + + +QList BlockView::wrongConnectedBuses() const { + QList sl = buses(), ret; + QList bl = blocks(); + foreach (BlockItem * b, bl) { + QVector pins = b->pins(); + foreach (BlockItemPin * p, pins) + if (p->state() == BlockItemPin::Reject) { + QPointF pp = p->scenePos(); + foreach (BlockBusItem * s, sl) + if (s->pol.contains(pp)) + if (!ret.contains(s)) + ret << s; + } + } + return ret; +} + + +QList BlockView::blocks() const { + QList ret; + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->data(1006) == "item") + ret << qgraphicsitem_cast(i); + return ret; +} + + +QList BlockView::decors() const { + QList ret, gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if ((i->data(1009) == "decor") && !i->data(1008).toBool() && (i->parentItem() == 0) && (i != &sel_rect) && (i != &tmp_bus)) + ret << i; + return ret; +} + + +BlockBusItem * BlockView::connectionBus(BlockItem * b0, BlockItem * b1) const { + QList cbl = connectionBuses(b0, b1); + if (cbl.isEmpty()) return 0; + return cbl.front(); +} + + +QList BlockView::connectionBuses(BlockItem * b0, BlockItem * b1) const { + if (!b0 || !b1) return QList(); + QSet bs0 = b0->connectedBuses().toSet(), bs1 = b1->connectedBuses().toSet(); + return (bs0 & bs1).values(); +} + + +bool BlockView::connectPins(BlockItemPin * p0, BlockItemPin * p1) { + if (!p0 || !p1) return false; + if (p0 == p1) return false; + if (p0->busType() != p1->busType()) return false; + QList bl0 = p0->connectedBuses(), bl1 = p1->connectedBuses(); + if (!(bl0.toSet() & bl1.toSet()).isEmpty()) return true; + BlockBusItem * nb = new BlockBusItem(); + nb->setBusType(p0->busType()); + //nb->setEndpointsNumber(3); + loadBus(nb); + if (!bl0.isEmpty() && !bl1.isEmpty()) { // connect two existing buses + } else { + if ((bl0.isEmpty() && !bl1.isEmpty()) || (bl1.isEmpty() && !bl0.isEmpty())) { // connect empty pin to existing bus + BlockItemPin * ep = 0; + BlockBusItem * eb = 0; + if (bl0.isEmpty()) {ep = p0; eb = bl1[0];} + else {ep = p1; eb = bl0[0];} + double md = -1; int mi = -1; + QPointF sp = ep->scenePos(); + if (eb->pol.size() == 2) { + eb->selSegment = 0; + eb->addPoint((eb->pol[0] + eb->pol[1]) / 2.); + eb->selPoint = -1; + mi = 2; + } else { + for (int i = 0; i < eb->pol.size(); ++i) { + if (eb->ends.contains(i)) continue; + double cd = QVector2D(sp - eb->pol[i]).lengthSquared(); + if (md < 0 || md > cd) { + md = cd; + mi = i; + } + } + } + if (mi < 0) { + return false; + } + trace(ep->scenePos(), eb->pol[mi], nb); + if (nb->pol.size() < 2) { + delete nb; + return false; + } + nb->pol.pop_back(); + int lp = eb->pol.size(); + eb->pol << nb->pol; + for (int i = 0; i < nb->pol.size() - 1; ++i) + eb->segments << QPair(lp + i, lp + i + 1); + eb->segments << QPair(mi, lp + nb->pol.size() - 1); + eb->updateGeometry(); + delete nb; + } else { // connect two empty pins + trace(p0->scenePos(), p1->scenePos(), nb); + if (nb->pol.isEmpty()) { + delete nb; + return false; + } + addItem(nb); + } + } + reconnectAll(); + emitActionEvent(BlockItemBase::BusAdd, QList() << nb); + emit connectionsChanged(); + return true; +} + + +void BlockView::restoreSelState() { + foreach (QGraphicsItem * i, sel_items) { + i->setPos(i->data(1001).toPointF()); + } + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->data(1005) == "connection") { + BlockBusItem * bi = qgraphicsitem_cast(i); + bi->pol = bi->bpol; + bi->prepareGeometryChange(); + } +} + + +void BlockView::saveSelState() { + QList gi = scene_->items(); + sel_items = scene_->selectedItems(); + foreach (QGraphicsItem * i, gi) { + i->setData(1000, i->isSelected()); + i->setData(1001, i->pos()); + if (i->data(1005) == "connection") + qgraphicsitem_cast(i)->bpol = qgraphicsitem_cast(i)->pol; + } +} + + +void BlockView::saveBusesState() { + QList bl = buses(); + foreach (BlockBusItem * b, bl) + b->saveState(); +} + + +void BlockView::restoreBusesState() { + QList bl = buses(); + foreach (BlockBusItem * b, bl) + b->restoreState(); +} + + +void BlockView::applySelRect(QGraphicsSceneMouseEvent * me) { + QList ci = sel_rect.collidingItems(Qt::IntersectsItemBoundingRect); + QList gi = scene_->items(); + bool add = me->modifiers().testFlag(Qt::ControlModifier); + if (!add) clearSelection(); + else { + foreach (QGraphicsItem * i, gi) + i->setSelected(i->data(1000).toBool()); + } + foreach (QGraphicsItem * i, ci) { + i->setSelected(!i->isSelected()); + } +} + + +void BlockView::applyGridStep() { + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->type() == QGraphicsItem::UserType + 2) + qgraphicsitem_cast(i)->setGridStep(grid_step); +} + + +void BlockView::trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus) { + if (hpin) + scene_pos_to = hpin->scenePos(); + last_trace_from = scene_pos_from; + trace_to = scene_pos_to; + QRect sr = scene_->sceneRect().toRect(); + int dx = sr.left() / grid_step, dy = sr.top() / grid_step; + //qDebug() << dp; + QPoint dp(-dx, -dy), qpt = quantize(scene_pos_to, grid_step).toPoint() / grid_step + dp; + QTime tm; + tm.restart(); + wavetrace.resize(sr.size() / grid_step); + wavetrace.fill(BlockViewWavetrace::Empty); + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->data(1006) == "item") { + QRect ir = i->mapRectToScene(i->boundingRect()).toRect().normalized(); + wavetrace.fill(QRect(ir.topLeft() / grid_step + dp, ir.bottomRight() / grid_step + dp), BlockViewWavetrace::Blocked); + QVector pins = qgraphicsitem_cast(i)->pins(); + foreach (BlockItemPin * p, pins) { + if (p->busType() == bus->busType()) + wavetrace.fill(quantize(p->scenePos(), grid_step).toPoint() / grid_step + dp, BlockViewWavetrace::Empty); + } + } + if (m_trace_with_buses) { + foreach (QGraphicsItem * i, gi) + if (i->data(1005) == "connection") { + BlockBusItem * b = qgraphicsitem_cast(i); + if (!b) continue; + for (int s = 0; s < b->segments.size(); ++s) { + QPointF p0 = b->pol[b->segments[s].first], p1 = b->pol[b->segments[s].second], cp = p0; + double sx(0.), sy(0.), dx = qAbs(p1.x() - p0.x()), dy = qAbs(p1.y() - p0.y()); + double signx = (p1.x() >= p0.x() ? 1. : -1.), signy = (p1.y() >= p0.y() ? 1. : -1.); + int steps(0); + if ((dx + dy) < grid_step) continue; + if (dx >= dy) { // by x + sx = grid_step; + sy = sx * dy / dx; + steps = qRound(dx / grid_step); + } else { + sy = grid_step; + sx = sy * dx / dy; + steps = qRound(dy / grid_step); + } + sx *= signx; + sy *= signy; + //qDebug() << "fill" << p0 << "->" << p1 << "in" << steps << sx << sy; + for (int j = 0; j < steps; ++j) { + QPoint tp = quantize(cp, grid_step).toPoint() / grid_step + dp; + if (tp != qpt) + wavetrace.fill(tp, BlockViewWavetrace::Blocked); + //qDebug() << " set" << cp; + cp += QPointF(sx, sy); + } + } + } + } + bus->clear(); + if (wavetrace.trace(quantize(scene_pos_from, grid_step).toPoint() / grid_step + dp, qpt)) { + wavetrace.gatherPath(); + foreach (const QPoint & p, wavetrace.path()) { + bus->appendPoint((p - dp) * grid_step); + } + } + //qDebug() << quantize(scene_pos_from, grid_step).toPoint() / grid_step + dp << qpt; + scene_->update(); +} + + +void BlockView::clearBusStates() { + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->data(1005) == "connection") { + BlockBusItem * b = qgraphicsitem_cast(i); + b->clearBusState(); + if (i != bus_from && i != match_bus) + b->selPoint = b->selSegment = -1; + } +} + + +void BlockView::matchBus() { + match_bus = 0; + bool bv = tmp_bus.isVisible(); + QList gi = scene_->items(); + QList buses; + QList blockl; + int sp = -1, ss = -1; + QPointF point; + iconnect = false; + if (!tmp_bus.pol.isEmpty()) + point = tmp_bus.pol.back(); + foreach (QGraphicsItem * i, gi) { + if (i != bus_from) { + if (i->data(1005) == "connection") + buses << qgraphicsitem_cast(i); + if (i->data(1006) == "item") + blockl << qgraphicsitem_cast(i); + } + } + foreach (BlockBusItem * b, buses) { + b->clearBusState(); + b->selPoint = b->selSegment = -1; + } + if (!bv) return; + BlockBusItem * b(0); + if (m_pin_mc) { + foreach (BlockItem * b_, blockl) + foreach (BlockItemPin * p_, b_->pins()) + if (p_->scenePos() == point) { + + return; + } + } + //qDebug() << "1" << buses.size() << tmp_bus.pol; + for (int i = 0; i < buses.size(); ++i) { + b = buses[i]; + b->testPoint(point, &sp, &ss); + //qDebug() << i << sp << ss; + if (sp >= 0 || ss >= 0) break; + } + if ((sp < 0 && ss < 0) || b == 0) return; + //qDebug("2"); + match_bus = b; + if ((b->busType() != tmp_bus.busType()) || b->connections_.value(sp, 0) != 0) { + b->setBusState(false); + } else { + if (b->max_ep >= 2) { + if (bus_from == 0) { + if (ss >= 0) { + if (b->endpointCount() >= b->max_ep) { + b->setBusState(false); + return; + } + } + if (sp >= 0) { + if (b->endpointCount() + b->pointSegmentsCount(sp) - 2 >= b->max_ep) { + b->setBusState(false); + return; + } + } + } else { + int sep = b->endpointCount() + bus_from->endpointCount(); + if (b->pointSegmentsCount(sp) == 1) sep--; + if (bus_from->selPoint >= 0) + if (bus_from->pointSegmentsCount(bus_from->selPoint) == 1) sep--; + if (sep > b->max_ep) { + b->setBusState(false); + return; + } + } + } + //b->press_point = point; + iconnect = true; + b->setBusState(true); + b->selPoint = sp; + b->selSegment = ss; + } +} + + +bool BlockView::connectTmpToBus(BlockBusItem * bus) { + if (bus == 0) return false; + if (!bus->busState()) return false; + if (tmp_bus.pol.size() < 2) return false; + int np = bus->selPoint; + if (np < 0) + np = bus->addPoint(tmp_bus.pol.back()); + if (np < 0) return false; + tmp_bus.pol.pop_back(); + int lp = bus->pol.size(); + bus->pol << tmp_bus.pol; + for (int i = 0; i < tmp_bus.pol.size() - 1; ++i) + bus->segments << QPair(lp + i, lp + i + 1); + bus->segments << QPair(np, lp + tmp_bus.pol.size() - 1); + bus->updateGeometry(); + tmp_bus.clear(); + return true; +} + + +void BlockView::markPins(int bus_type) { + unhoverPins(); + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) { + if (i->data(1004) == "pin") { + BlockItemPin * p = qgraphicsitem_cast(i); + p->saveState(); + if (m_pin_mc) { + if (p->busType() == tmp_bus.busType()) + p->setState(BlockItemPin::Accept); + } else { + if (p->busType() == tmp_bus.busType() && p->state() == BlockItemPin::Disconnected) + p->setState(BlockItemPin::Accept); + } + } + } +} + + +void BlockView::unmarkPins(bool to_normal) { + unhoverPins(); + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) { + if (i->data(1004) == "pin") { + qgraphicsitem_cast(i)->restoreState(); + if (to_normal) + while (qgraphicsitem_cast(i)->restoreState()); + } + } +} + + +void BlockView::hoverAcceptedPin(BlockItemPin * pin) { + if (!pin) return; + pin->resizePin(12.); +} + + +void BlockView::unhoverPins() { + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->data(1004) == "pin") + ((BlockItemPin*)i)->resizePin(); +} + + +void BlockView::simplifyBuses() { + QList bl = buses(); + foreach (BlockBusItem * b, bl) + b->simplify(); +} + + +void BlockView::moveBuses(const QList & items, QPointF dp) { + if (dp.isNull()) return; + QList gi = scene_->items(); + QVector pins; + QList buses; + //qDebug() << "move" << dp; + foreach (QGraphicsItem * i, items) + if (i->data(1006) == "item" && i->flags().testFlag(QGraphicsItem::ItemIsMovable)) + pins << qgraphicsitem_cast(i)->pins(); + foreach (QGraphicsItem * i, gi) + if (i->data(1005) == "connection") + buses << qgraphicsitem_cast(i); + foreach (BlockBusItem * b, buses) { + QList bpins = b->connections_.values(); + if (!bpins.isEmpty()) { + foreach (BlockItemPin * p, pins) + bpins.removeAll(p); + if (bpins.isEmpty()) { + b->movePolyline(dp); + continue; + } + } + foreach (BlockItemPin * p, pins) { + QList ends = b->connections_.keys(p); + for (int i = 0; i < ends.size(); ++i) { + /*int isp = b->segmentPointPair(ends[i]); + QPointF sdp; + if (isp >= 0 && b->pol.size() > 2) { + sdp = b->pol[isp] - b->pol[ends[i]]; + if (!sdp.isNull()) { + if (sdp.x() == 0. && dp.x() != 0.) + b->movePoint(isp, QPointF(dp.x(), 0.)); + if (sdp.y() == 0. && dp.y() != 0.) + b->movePoint(isp, QPointF(0., dp.y())); + } else { + if (p->alignment() == Qt::AlignTop || p->alignment() == Qt::AlignBottom) + b->movePoint(isp, QPointF(dp.x(), 0.)); + if (p->alignment() == Qt::AlignLeft || p->alignment() == Qt::AlignRight) + b->movePoint(isp, QPointF(0., dp.y())); + } + }*/ + QPointF pdp = dp; + double ang = 0.; + switch (p->alignment()) { + case Qt::AlignRight : pdp.setX(0.); ang = 0.; break; + case Qt::AlignTop : pdp.setY(0.); ang = 90.; break; + case Qt::AlignLeft : pdp.setX(0.); ang = 180.; break; + case Qt::AlignBottom: pdp.setY(0.); ang = 270.; break; + default: break; + } + QVector epl = b->endpointLine(ends[i], ang); + foreach (int e, epl) + b->movePoint(e, pdp); + b->movePoint(ends[i], dp); + } + } + } +} + + +QList BlockView::internalBuses(const QList & items) { + QList ret; + if (items.isEmpty()) return ret; + QList sbl = buses(); + QSet sis = QSet::fromList(items); + foreach (BlockBusItem * bi, sbl) { + QSet bis = QSet::fromList(bi->connectedBlocks()); + if ((bis - sis).isEmpty()) + ret << bi; + } + return ret; +} + + +QList BlockView::selectedBlocks() const { + QList ret; + QList sil = scene()->selectedItems(); + foreach (QGraphicsItem * b, sil) + if (b->data(1006) == "item") + ret << qgraphicsitem_cast(b); + return ret; +} + + +QList BlockView::selectedDecors() const { + QList ret, sil = decors(); + foreach (QGraphicsItem * b, sil) + if (b->isSelected()) + ret << b; + return ret; +} + + +void BlockView::adjustThumb() { + if (!scene()) return; + QSizeF sr = sceneRect().size(), tr; + double scl; + if (sr.width() >= sr.height()) + scl = thumb_size.width() / sr.width(); + else + scl = thumb_size.height() / sr.height(); + tr = sr * scl; + widget_thumb.setGeometry(QRect(QPoint(width() - tr.width() - 10 - verticalScrollBar()->width(), + height() - tr.height() - 10 - horizontalScrollBar()->height()), tr.toSize())); +} + + +void BlockView::newBranch(BlockBusItem * item) { + bus_from = item; + newBusStarted(item->busType()); + markPins(item->busType()); + new_branch = true; + tmp_bus.setBusType(item->busType()); + if (item->selSegment >= 0) { + QPointF ds(item->pol[item->segments[item->selSegment].first] - item->pol[item->segments[item->selSegment].second]); + if (ds.x() == 0.) wavetrace.setPreferredDirection(BlockViewWavetrace::Horizontal); + if (ds.y() == 0.) wavetrace.setPreferredDirection(BlockViewWavetrace::Vertical); + } +} + + +void BlockView::newBranchTrace(BlockBusItem * item, QPointF to) { + trace(item->press_pos, to, &tmp_bus); + tmp_bus.show(); +} + + +void BlockView::newBranchAccept(BlockBusItem * item) { + unmarkPins(); + if (!new_branch) return; + new_branch = false; + tmp_bus.hide(); + if (tmp_bus.pol.size() < 2) return; + tmp_bus.pol.pop_front(); + int np = item->addPoint(item->press_pos); + if (np < 0) return; + if (match_bus) { + if (iconnect) tmp_bus.pol.pop_back(); + else return; + } + if (item == match_bus) return; + int snp = np; + int lp = item->pol.size(); + if (!tmp_bus.pol.isEmpty()) { + item->pol << tmp_bus.pol; + item->segments << QPair(np, lp); + for (int i = 0; i < tmp_bus.pol.size() - 1; ++i) + item->segments << QPair(lp + i, lp + i + 1); + } + if (match_bus != 0) { + if (!iconnect) return; + np = match_bus->selPoint; + if (np < 0) + np = match_bus->addPoint(trace_to); + if (np < 0) return; + lp = item->pol.size(); + item->pol << match_bus->pol; + for (int i = 0; i < match_bus->segments.size(); ++i) + item->segments << QPair(match_bus->segments[i].first + lp, match_bus->segments[i].second + lp); + if (tmp_bus.pol.isEmpty()) + item->segments << QPair(lp + np, snp); + else + item->segments << QPair(lp + np, lp - 1); + match_bus->setProperty("_nodelete_", true); + match_bus->deleteLater(); + match_bus = 0; + } + item->updateGeometry(); + emitActionEvent(BlockItemBase::BusAdd, QList() << item); + emit connectionsChanged(); + tmp_bus.clear(); +} + + +void BlockView::newBranchCancel() { + unmarkPins(); + //qDebug() << "cancel"; + new_branch = false; + tmp_bus.hide(); + tmp_bus.clear(); +} + + +void BlockView::removedBus(QObject * o) { + mm_ci = 0; + reconnectAll(); + BlockBusItem * bus = (BlockBusItem*)o; + if (bus->property("_nodelete_").toBool()) return; + emitActionEvent(BlockItemBase::BusRemove, QList() << bus); + emit connectionsChanged(); +} + + +void BlockView::removedBlock(QObject * o) { + emit blockRemoved((BlockItem*)o); + emitActionEvent(BlockItemBase::BlockRemove, QList() << qgraphicsitem_cast((BlockItem*)o)); +} + + +void BlockView::removeJunk() { + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) { + if (i->data(1005) != "connection") continue; + BlockBusItem * b = qgraphicsitem_cast(i); + if (b->pol.size() <= 1) { + b->deleteLater(); + } + } +} + + +void BlockView::sceneSelectionChanged() { + bool ie = scene()->selectedItems().isEmpty(); + emit copyEnabledChanged(!ie); +} + + +void BlockView::_setThumb(double v) { + _talpha = v; + QMetaObject::invokeMethod(&widget_thumb, "repaint", Qt::QueuedConnection); + if (_talpha <= 0.01) widget_thumb.hide(); + else widget_thumb.show(); +} + + +void BlockView::reconnectAll() { + //qDebug() << "reconnect"; + removeJunk(); + QList gi = scene_->items(); + QList pins; + QList buses; + foreach (QGraphicsItem * i, gi) { + if (i->data(1004) == "pin") + pins << qgraphicsitem_cast(i); + if (i->data(1005) == "connection") + buses << qgraphicsitem_cast(i); + } + foreach (BlockItemPin * p, pins) { + p->setState(BlockItemPin::Disconnected); + p->buses_.clear(); + } + foreach (BlockBusItem * b, buses) { + b->connections_.clear(); + QVector conns(b->endpoints()); + for (int c = 0; c < conns.size(); ++c) { + QPointF cp = b->pol[conns[c]]; + for (int j = 0; j < pins.size(); ++j) { + if (!pins[j]->isVisible()) continue; + QPointF pp = pins[j]->scenePos(); + if (cp == pp) { + //qDebug() << "found"; + if (b->busType() == pins[j]->busType()) { + b->connections_[conns[c]] = pins[j]; + if (!pins[j]->buses_.contains(b)) + pins[j]->buses_ << b; + pins[j]->setState(BlockItemPin::Connected); + } else + pins[j]->setState(BlockItemPin::Reject); + break; + } + } + } + } + //qDebug() << pins.size() << buses.size(); +} + + +void BlockView::zoom(double factor) { + scale(factor, factor); +} + + +void BlockView::zoomReset() { + cur_scl = qSqrt(transform().determinant()); + zoom(1. / cur_scl); +} + + +void BlockView::copyToClipboard() { + QList bll = selectedBlocks(); + QList del = selectedDecors(); + //qDebug() << "copy" << bll.size() << del.size(); + if (bll.isEmpty() && del.isEmpty()) return; + QList bul = internalBuses(bll); + QByteArray ba; + QDataStream s(&ba, QIODevice::ReadWrite); + s << uint(0x89abcdef) << bll << bul << del; + QMimeData * mime = new QMimeData(); + mime->setData(_BlockView_Mime_, ba); + QApplication::clipboard()->setMimeData(mime); +} + + +void BlockView::pasteFromClipboard() { + const QMimeData * mime = QApplication::clipboard()->mimeData(); + if (!mime) return; + if (!mime->hasFormat(_BlockView_Mime_)) return; + QByteArray ba = mime->data(_BlockView_Mime_); + //qDebug() << "paste" << ba.size(); + if (ba.isEmpty()) return; + QList bll; + QList bul; + QList del, gl; + uint hdr = 0; + QDataStream s(ba); + s >> hdr; + if (hdr != 0x89abcdef) return; + s >> bll >> bul >> del; + int all = bll.size() + bul.size() + del.size(); + if (all == 0) return; + QRectF br; + foreach (BlockItem * b, bll) { + br |= b->boundingRect().translated(b->pos()); + gl << b; + } + foreach (BlockBusItem * b, bul) + gl << b; + foreach (QGraphicsItem * b, del) + br |= b->boundingRect().translated(b->pos()); + gl << del; + QPointF copy_dp; + if (underMouse()) copy_dp = mapToScene(mapFromGlobal(QCursor::pos())); + else copy_dp = mapToScene(rect().center()); + copy_dp -= br.center(); + copy_dp = quantize(copy_dp, grid_step); + ae_enabled = false; + if (!bll.isEmpty()) copyBlocks(bll, copy_dp); + if (!bul.isEmpty()) copyBuses(bul, copy_dp); + foreach (QGraphicsItem * i, del) + i->setPos(i->pos() + copy_dp); + addItems(del); + ae_enabled = true; + emitActionEvent(BlockItemBase::Paste, gl); +} + + +void BlockView::selectNone() { + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + i->setSelected(false); +} + + +void BlockView::selectAll() { + QList gi = scene_->items(); + foreach (QGraphicsItem * i, gi) + if (i->flags().testFlag(QGraphicsItem::ItemIsSelectable)) + i->setSelected(true); +} + + +void BlockView::removeSelected() { + QList gi = scene_->selectedItems(), ai; + blockSignals(true); + QList sbuses = buses(), dbuses, wbuses = wrongConnectedBuses(); + //foreach (BlockBusItem * i, wbuses) + // sbuses.removeOne(i); + foreach (BlockBusItem * i, sbuses) + if (i->connectedBlocks().isEmpty()) + dbuses << i; + foreach (QGraphicsItem * i, gi) { + if (i->data(1006) == "item") + ai << qgraphicsitem_cast(i); + if ((i->data(1006) == "item") || (i->data(1005) == "connection") || (i->data(1009) == "decor")) { + scene_->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close)); + delete i; + } + } + reconnectAll(); + foreach (BlockBusItem * i, sbuses) + if (i->connectedBlocks().isEmpty()) + if (!dbuses.contains(i)) + delete i; + + blockSignals(false); + foreach (QGraphicsItem * i, ai) + emit blockRemoved((BlockItem*)i); + emitActionEvent(BlockItemBase::BlockRemove, ai); +} + + +void BlockView::removeAll() { + QList gi = scene_->items(), ai; + blockSignals(true); + foreach (QGraphicsItem * i, gi) { + if (i->data(1006) == "item") + ai << qgraphicsitem_cast(i); + if ((i->data(1006) == "item") || (i->data(1005) == "connection") || (i->data(1009) == "decor")) { + if ((i != &sel_rect) && (i != &tmp_bus) && (i->parentItem() == 0) && !(i->data(1008).toBool())) { + //qDebug() << "delete" << i->data(1004); + scene_->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close)); + delete i; + } + } + } + blockSignals(false); + foreach (QGraphicsItem * i, ai) + emit blockRemoved((BlockItem*)i); +} diff --git a/qad/blockview/blockview.h b/qad/blockview/blockview.h new file mode 100644 index 0000000..db0078a --- /dev/null +++ b/qad/blockview/blockview.h @@ -0,0 +1,200 @@ +#ifndef BLOCKVIEW_H +#define BLOCKVIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "blockviewwavetrace.h" +#include "blockbusitem.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class BlockView: public QGraphicsView +{ + Q_OBJECT + Q_ENUMS(SelectionMode) + + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool snapToGrid READ isSnapToGrid WRITE setSnapToGrid) + Q_PROPERTY(QPen gridPen READ gridPen WRITE setGridPen) + Q_PROPERTY(double gridStep READ gridStep WRITE setGridStep) + Q_PROPERTY(double gridPointsWidth READ gridPointsWidth WRITE setGridPointsWidth) + Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(bool postMoveConnect READ isPostMoveConnectEnabled WRITE setPostMoveConnectEnabled) + Q_PROPERTY(bool connectByMouse READ isConnectByMouseEnabled WRITE setConnectByMouseEnabled) + Q_PROPERTY(bool navigationEnabled READ isNavigationEnabled WRITE setNavigationEnabled) + Q_PROPERTY(bool traceConsiderBuses READ isTraceConsiderBuses WRITE setTraceConsiderBuses) + Q_PROPERTY(bool pinMulticonnect READ isPinMulticonnectEnabled WRITE setPinMulticonnectEnabled) + Q_PROPERTY(bool miniMap READ isMiniMapEnabled WRITE setMiniMapEnabled) + + Q_PROPERTY(double _thumb READ _thumb WRITE _setThumb DESIGNABLE false SCRIPTABLE false) + +public: + BlockView(QWidget * parent = 0); + BlockView(QGraphicsScene * scene, QWidget * parent = 0); + ~BlockView(); + + enum SelectionMode { + NoSelection, + SingleSelection, + MultiSelection + }; + + QPen gridPen() const {return grid_pen;} + bool isGridVisible() const {return grid_visible;} + bool isSnapToGrid() const {return grid_snap;} + bool isPostMoveConnectEnabled() const {return pm_connect;} + bool isNavigationEnabled() const {return navigation;} + bool isConnectByMouseEnabled() const {return m_connect;} + bool isTraceConsiderBuses() const {return m_trace_with_buses;} + bool isPinMulticonnectEnabled() const {return m_pin_mc;} + bool isMiniMapEnabled() const {return minimap;} + double gridStep() const {return grid_step;} + double gridPointsWidth() const {return grid_points;} + SelectionMode selectionMode() const {return smode;} + void setSelectionMode(SelectionMode mode) {smode = mode;} + + void addItems(QList items) {foreach (QGraphicsItem * i, items) addItem(i);} + QList buses() const; + QList wrongConnectedBuses() const; + QList blocks() const; + QList decors() const; + BlockBusItem * connectionBus(BlockItem * b0, BlockItem * b1) const; + QList connectionBuses(BlockItem * b0, BlockItem * b1) const; + bool connectPins(BlockItemPin * p0, BlockItemPin * p1); + +protected: + void _init(); + void _updateBack(); + bool eventFilter(QObject * o, QEvent * e); + void stopTimer(int & tid); + void restartTimer(int & tid, int msecs); + void timerEvent(QTimerEvent * e); + void wheelEvent(QWheelEvent * event); + void mousePressEvent(QMouseEvent * event); + void mouseMoveEvent(QMouseEvent * event); + void keyPressEvent(QKeyEvent * event); + void resizeEvent(QResizeEvent * event); + void scrollContentsBy(int dx, int dy); + void drawBackground(QPainter * painter, const QRectF & rect); + void drawThumb(); + void drawSceneThumb(); + void thumbHide(); + void thumbShow(); + void restoreSelState(); + void saveSelState(); + void saveBusesState(); + void restoreBusesState(); + void applySelRect(QGraphicsSceneMouseEvent * me); + void applyGridStep(); + void trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus); + void clearBusStates(); + void matchBus(); + bool connectTmpToBus(BlockBusItem* bus); + void markPins(int bus_type); + void unmarkPins(bool to_normal = false); + void hoverAcceptedPin(BlockItemPin * pin); + void unhoverPins(); + void simplifyBuses(); + void moveBuses(const QList & items, QPointF dp); + QList internalBuses(const QList & items); + QList selectedBlocks() const; + QList selectedDecors() const; + double _thumb() const {return _talpha;} + void scrollFromThumb(); + void deleteCopyTemp(); + void emitActionEvent(BlockItemBase::Action action, QList items); + + virtual void loadBus(BlockBusItem * bus) {} + virtual void copyBlocks(QList items, QPointF offset) {} + virtual void copyBuses(QList items, QPointF offset) {} + virtual void newBusStarted(int bus_type) {} + + QGraphicsScene * scene_; + QGraphicsRectItem sel_rect; + QGraphicsItem * mm_ci; + QList sel_items; + QList copy_items; + QList copy_buses; + BlockBusItem tmp_bus, * match_bus, * bus_from; + BlockItemPin * hpin; + BlockViewWavetrace wavetrace; + QPoint press_point, screen_point, thumb_press; + QPointF scene_point, trace_from, last_trace_from, trace_to, copy_dp; + QRect thumb_sr, thumb_vr; + QSizeF thumb_size; + QPen grid_pen; + SelectionMode smode; + QImage im_scene; + QWidget widget_thumb; + Qt::KeyboardModifiers mm_mods; + QPropertyAnimation thumb_anim; + int timer_thumb, thumb_hide_delay; + bool mm_drag, new_bus, new_branch, moved, mm_cancel, iconnect, mm_copy, mm_thumb, ae_enabled; + bool grid_visible, grid_snap, pm_connect, navigation, m_connect, m_trace_with_buses, m_pin_mc, minimap; + double grid_step, grid_points, cur_scl, _talpha, thumb_scl; + +protected slots: + void getPinMC(bool * v) {if (v) *v = m_pin_mc;} + void adjustThumb(); + void newBranch(BlockBusItem * item); + void newBranchTrace(BlockBusItem * item, QPointF to); + void newBranchAccept(BlockBusItem * item); + void newBranchCancel(); + void removedBus(QObject * o); + void removedBlock(QObject * o); + void removeJunk(); + void sceneSelectionChanged(); + void _setThumb(double v); + +public slots: + void setGridPen(const QPen & pen) {grid_pen = pen; _updateBack();} + void setGridVisible(bool yes) {grid_visible = yes; _updateBack();} + void setSnapToGrid(bool yes) {grid_snap = yes;} + void setGridStep(double step) {grid_step = step; applyGridStep(); _updateBack();} + void setGridPointsWidth(double width_) {grid_points = width_; _updateBack();} + void setPostMoveConnectEnabled(bool on) {pm_connect = on;} + void setNavigationEnabled(bool on) {navigation = on;} + void setConnectByMouseEnabled(bool on) {m_connect = on;} + void setTraceConsiderBuses(bool on) {m_trace_with_buses = on;} + void setPinMulticonnectEnabled(bool on) {m_pin_mc = on;} + void setMiniMapEnabled(bool on) {minimap = on;} + + void zoom(double factor); + void zoomIn() {zoom(1.2);} + void zoomOut() {zoom(1. / 1.2);} + void zoomReset(); + + void copyToClipboard(); + void pasteFromClipboard(); + + void reconnectAll(); + void selectNone(); + void selectAll(); + void removeSelected(); + void removeAll(); + void clearSelection(); + void addItem(QGraphicsItem * item); + +signals: + void blockDoubleClicked(BlockItem * ); + void busDoubleClicked(BlockBusItem * ); + void actionEvent(BlockItemBase::Action action, QList items); + void blockRemoved(BlockItem * item); + void connectionsChanged(); + void copyEnabledChanged(bool); + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // BLOCKVIEW_H diff --git a/qad/blockview/blockviewwavetrace.cpp b/qad/blockview/blockviewwavetrace.cpp new file mode 100644 index 0000000..c070555 --- /dev/null +++ b/qad/blockview/blockviewwavetrace.cpp @@ -0,0 +1,197 @@ +#include "blockviewwavetrace.h" +#include + + +BlockViewWavetrace::BlockViewWavetrace(int width, int height) { + max_steps = 512; + resize(width, height); + setPreferredDirection(BlockViewWavetrace::Horizontal); +} + + +void BlockViewWavetrace::resize(int width, int height) { + wid = width; + hei = height; + if (field.size() != wid) + field.resize(wid); + for (int i = 0; i < wid; ++i) { + if (field[i].size() != hei) { + field[i].resize(hei); + field[i].fill(-1); + } + } +} + + +void BlockViewWavetrace::fill(short val) { + QTime tm; tm.restart(); + for (int i = 0; i < wid; ++i) { + if (i == 0) + field[i].fill(val); + else + memcpy(field[i].data(), field[0].constData(), hei * sizeof(field[0][0])); + } +} + + +void BlockViewWavetrace::fill(const QRect & rect, short val) { + for (int i = rect.left(); i <= rect.right(); ++i) + for (int j = rect.top(); j <= rect.bottom(); ++j) + field[i][j] = val; +} + + +bool BlockViewWavetrace::trace(const QPoint & start, const QPoint & finish) { + st = start; + fn = finish; + //qDebug() << "trace" << start << finish; + //return true; + int cx, cy; + short cl = 0, empty = (short)BlockViewWavetrace::Empty; + QRect frect(0, 0, wid - 1, hei - 1); + QVector cpnts, npnts; + fill(st, cl); + cpnts.push_back(st); + if (field[fn.x()][fn.y()] == (short)BlockViewWavetrace::Blocked) + return false; + while (cpnts.size() > 0) { + npnts.clear(); + cl++; + if (cl >= max_steps) return false; + for (int i = 0; i < cpnts.size(); ++i) { + if (cpnts[i] == fn) { + return true; + } + cx = cpnts[i].x() - 1; + cy = cpnts[i].y(); + if (frect.contains(cx, cy)) { + if (field[cx][cy] == empty) { + npnts.push_back(QPoint(cx, cy)); + fill(cx, cy, cl); + } + } + cx = cpnts[i].x() + 1; + if (frect.contains(cx, cy)) { + if (field[cx][cy] == empty) { + npnts.push_back(QPoint(cx, cy)); + fill(cx, cy, cl); + } + } + cx = cpnts[i].x(); + cy = cpnts[i].y() - 1; + if (frect.contains(cx, cy)) { + if (field[cx][cy] == empty) { + npnts.push_back(QPoint(cx, cy)); + fill(cx, cy, cl); + } + } + cy = cpnts[i].y() + 1; + if (frect.contains(cx, cy)) { + if (field[cx][cy] == empty) { + npnts.push_back(QPoint(cx, cy)); + fill(cx, cy, cl); + } + } + } + cpnts = npnts; + //qDebug() << cl << ": " << cpnts.size(); + } + return false; +} + + +void BlockViewWavetrace::gatherPath() { + path_.clear(); + path_.push_back(fn); + int cx, cy; + int pa = -1, ca = -1; + bool first = true; + short cl = field[fn.x()][fn.y()]; + QRect frect(0, 0, wid, hei); + QPoint cpnt = fn; + //cout << "start from " << cl << endl; + while (cl > 0) { + cl--; + pa = ca; + int dir = 0; + cx = cpnt.x() + dps[dir].x(); + cy = cpnt.y() + dps[dir].y(); + dir++; + if (frect.contains(cx, cy)) { + if (field[cx][cy] == cl) { + ca = QLineF(QPointF(cx, cy), cpnt).angle(); + if (ca != pa && !first) + path_.push_front(cpnt); + cpnt = QPoint(cx, cy); + first = false; + continue; + } + } + cx = cpnt.x() + dps[dir].x(); + cy = cpnt.y() + dps[dir].y(); + dir++; + if (frect.contains(cx, cy)) { + if (field[cx][cy] == cl) { + ca = QLineF(QPointF(cx, cy), cpnt).angle(); + if (ca != pa && !first) + path_.push_front(cpnt); + cpnt = QPoint(cx, cy); + first = false; + continue; + } + } + cx = cpnt.x() + dps[dir].x(); + cy = cpnt.y() + dps[dir].y(); + dir++; + if (frect.contains(cx, cy)) { + if (field[cx][cy] == cl) { + ca = QLineF(QPointF(cx, cy), cpnt).angle(); + if (ca != pa && !first) + path_.push_front(cpnt); + cpnt = QPoint(cx, cy); + first = false; + continue; + } + } + cx = cpnt.x() + dps[dir].x(); + cy = cpnt.y() + dps[dir].y(); + if (frect.contains(cx, cy)) { + if (field[cx][cy] == cl) { + ca = QLineF(QPointF(cx, cy), cpnt).angle(); + if (ca != pa && !first) + path_.push_front(cpnt); + cpnt = QPoint(cx, cy); + first = false; + continue; + } + } + } + path_.push_front(st); + //cout << path_.size() << endl; +} + + +void BlockViewWavetrace::setPreferredDirection(BlockViewWavetrace::Direction dir) { + dir_ = dir; + if (dir == BlockViewWavetrace::Horizontal) { + dps[0] = QPoint(0, -1); + dps[1] = QPoint(0, 1); + dps[2] = QPoint(-1, 0); + dps[3] = QPoint(1, 0); + } + if (dir == BlockViewWavetrace::Vertical) { + dps[2] = QPoint(0, -1); + dps[3] = QPoint(0, 1); + dps[0] = QPoint(-1, 0); + dps[1] = QPoint(1, 0); + } +} + + +const QVector & BlockViewWavetrace::path() const { + /*path_.resize(3); + path_[0] = st; + path_[1] = (st + fn) / 2; + path_[2] = fn;*/ + return path_; +} diff --git a/qad/blockview/blockviewwavetrace.h b/qad/blockview/blockviewwavetrace.h new file mode 100644 index 0000000..41f453e --- /dev/null +++ b/qad/blockview/blockviewwavetrace.h @@ -0,0 +1,43 @@ +#ifndef BLOCKVIEWWAVETRACE_H +#define BLOCKVIEWWAVETRACE_H + +#include "blockitem.h" + +class BlockViewWavetrace { +public: + BlockViewWavetrace(int width = 1, int height = 1); + + enum CellState {Empty = -1, Blocked = -2}; + enum Direction {Horizontal = 0, Vertical = 1}; + + int width() const {return wid;} + int height() const {return hei;} + void resize(int width, int height); + void resize(const QSize & sz) {resize(sz.width(), sz.height());} + void fill(short val = -1); + void fill(const QRect & rect, short val = -1); + void fill(const QPoint & point, short val = -1) {field[point.x()][point.y()] = val;} + void fill(int px, int py, short val = -1) {field[px][py] = val;} + void fill(BlockViewWavetrace::CellState val = Empty) {fill((short)val);} + void fill(const QRect & rect, BlockViewWavetrace::CellState val = Empty) {fill(rect, (short)val);} + void fill(const QPoint & point, BlockViewWavetrace::CellState val = Empty) {fill(point, (short)val);} + void fill(int px, int py, BlockViewWavetrace::CellState val = Empty) {fill(px, py, (short)val);} + void clear() {fill(-1);} + bool trace(const QPoint & start, const QPoint & finish); + Direction preferredDirection() const {return dir_;} + void setPreferredDirection(Direction dir); + void setMaximumSteps(int steps) {max_steps = steps;} + int maximumSteps() const {return max_steps;} + void gatherPath(); + const QVector & path() const; + +private: + int wid, hei, max_steps; + Direction dir_; + QVector > field; + QVector path_; + QPoint dps[4], st, fn; + +}; + +#endif // BLOCKVIEWWAVETRACE_H diff --git a/qad/blockview/drawtools.cpp b/qad/blockview/drawtools.cpp new file mode 100644 index 0000000..2e01120 --- /dev/null +++ b/qad/blockview/drawtools.cpp @@ -0,0 +1,791 @@ +#include "drawtools.h" +#include "ui_drawtools.h" +#include "alignedtextitem.h" +#include +#include +#include +#include +#include +#include +#include + + +_DTSizeItem::_DTSizeItem(): QGraphicsObject() { + cur_item = 0; + grid = 10.; + in_process = can_drag = false; + setData(1008, true); + for (int i = 0; i < 8; ++i) { + //qDebug() << &(rects[i]); + rects[i].setData(1008, true); + rects[i].setFlag(QGraphicsItem::ItemIgnoresTransformations); + rects[i].setZValue(10.); + rects[i].setAcceptHoverEvents(true); + rects[i].setRect(-5, -5, 10, 10); + rects[i].setPen(QPen(Qt::darkBlue)); + rects[i].setBrush(QBrush(QColor(64, 64, 255, 128))); + //rects[i].setData(1100, true); + } +} + + +_DTSizeItem::~_DTSizeItem() { + assignObject(0); + //qDebug() << "!!!"; +} + + +void _DTSizeItem::assignObject(QGraphicsItem * item) { + if (cur_item) + if (qgraphicsitem_cast(cur_item)) + cur_item->removeSceneEventFilter(this); + cur_item = item; + if (!cur_item) { + for (int i = 0; i < 8; ++i) { + rects[i].hide(); + rects[i].setParentItem(0); + rects[i].removeSceneEventFilter(this); + } + return; + } + if (item) + if (item->scene()) + if (!item->scene()->views().isEmpty()) + grid = ((BlockView*)(item->scene()->views()[0]))->gridStep(); + QGraphicsRectItem * irect = qgraphicsitem_cast(cur_item); + QGraphicsEllipseItem * iell = qgraphicsitem_cast(cur_item); + QGraphicsLineItem * iline = qgraphicsitem_cast(cur_item); + if (irect || iell || iline) { + is_line = qgraphicsitem_cast(item); + for (int i = 0; i < (is_line ? 2 : 8); ++i) { + rects[i].setParentItem(item); + rects[i].installSceneEventFilter(this); + rects[i].show(); + } + } + item->installSceneEventFilter(this); + moveRects(); +} + + +void _DTSizeItem::moveRects() { + if (!cur_item) return; + QRectF rect = itemRect(cur_item); + QPointF tl = rect.topLeft(), tr = rect.topRight(), bl = rect.bottomLeft(), br = rect.bottomRight(); + if (is_line) { + rects[0].setPos(tl); rects[0].setData(2001, int(Qt::SizeAllCursor)); + rects[1].setPos(br); rects[1].setData(2001, int(Qt::SizeAllCursor)); + } else { + rects[0].setPos(tl); rects[0].setData(2001, int(Qt::SizeFDiagCursor)); + rects[1].setPos((tl + tr) / 2.); rects[1].setData(2001, int(Qt::SizeVerCursor)); + rects[2].setPos(tr); rects[2].setData(2001, int(Qt::SizeBDiagCursor)); + rects[3].setPos((tr + br) / 2.); rects[3].setData(2001, int(Qt::SizeHorCursor)); + rects[4].setPos(br); rects[4].setData(2001, int(Qt::SizeFDiagCursor)); + rects[5].setPos((br + bl) / 2.); rects[5].setData(2001, int(Qt::SizeVerCursor)); + rects[6].setPos(bl); rects[6].setData(2001, int(Qt::SizeBDiagCursor)); + rects[7].setPos((bl + tl) / 2.); rects[7].setData(2001, int(Qt::SizeHorCursor)); + } +} + + +void _DTSizeItem::applyRect() { + if (!cur_item) return; + QGraphicsRectItem * irect = qgraphicsitem_cast(cur_item); + QGraphicsEllipseItem * iell = qgraphicsitem_cast(cur_item); + QGraphicsLineItem * iline = qgraphicsitem_cast(cur_item); + if (irect) + irect->setRect(nrect); + if (iell) + iell->setRect(nrect); + if (iline) + iline->setLine(QLineF(nrect.topLeft(), nrect.bottomRight())); +} + + +void _DTSizeItem::doubleClick() { + QGraphicsSimpleTextItem * itext = qgraphicsitem_cast(cur_item); + AlignedTextItem * iatext = qgraphicsitem_cast(cur_item); + QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast(cur_item); + if (itext || iatext) { + emit textEditRequest(); + } + if (ipixmap) { + emit pixmapEditRequest(); + } +} + + +QRectF _DTSizeItem::itemRect(const QGraphicsItem * item) const { + if (!cur_item) return QRectF(); + QGraphicsRectItem * irect = qgraphicsitem_cast(cur_item); + QGraphicsEllipseItem * iell = qgraphicsitem_cast(cur_item); + QGraphicsLineItem * iline = qgraphicsitem_cast(cur_item); + if (irect) + return irect->rect(); + if (iell) + return iell->rect(); + if (iline) + return QRectF(iline->line().p1(), iline->line().p2()); + return QRectF(); +} + + +QRectF _DTSizeItem::boundingRect() const { + QRectF ret = rects[0].boundingRect().translated(rects[0].pos()); + for (int i = 1; i < 8; ++i) + ret |= rects[i].boundingRect().translated(rects[i].pos()); + return ret; +} + + +bool _DTSizeItem::sceneEventFilter(QGraphicsItem * watched, QEvent * event) { + QGraphicsSceneMouseEvent * me = (QGraphicsSceneMouseEvent * )event; + if (watched == cur_item) { + if (event->type() == QEvent::Close) + assignObject(0); + if (event->type() == QEvent::GraphicsSceneMouseDoubleClick) { + doubleClick(); + return true; + } + return QGraphicsItem::sceneEventFilter(watched, event); + } + if (!cur_item) + return QGraphicsItem::sceneEventFilter(watched, event); + view_ = 0; + switch (event->type()) { + case QEvent::GraphicsSceneHoverEnter: + if (watched->scene()) if (!watched->scene()->views().isEmpty()) view_ = watched->scene()->views()[0]; + if (view_) view_->setCursor(Qt::CursorShape(watched->data(2001).toInt())); + break; + case QEvent::GraphicsSceneHoverLeave: + if (watched->scene()) if (!watched->scene()->views().isEmpty()) view_ = watched->scene()->views()[0]; + if (view_) view_->unsetCursor(); + break; + case QEvent::GraphicsSceneMousePress: + can_drag = (me->buttons() == Qt::LeftButton); + if (in_process) { + nrect = cur_item->data(2000).toRectF(); + applyRect(); + moveRects(); + } + in_process = false; + pp = quantize(me->scenePos(), grid); + cur_item->setData(2000, itemRect(cur_item)); + return true; + case QEvent::GraphicsSceneMouseMove: + if (me->buttons().testFlag(Qt::LeftButton)) { + sp = quantize(me->scenePos(), grid); + if (pp != sp && can_drag) { + in_process = true; + nrect = itemRect(cur_item); + if (is_line) { + if (watched == &(rects[0])) nrect.setTopLeft(rects[0].pos() + (sp - pp)); + if (watched == &(rects[1])) nrect.setBottomRight(rects[1].pos() + (sp - pp)); + } else { + if (watched == &(rects[0])) nrect.setTopLeft(rects[0].pos() + (sp - pp)); + if (watched == &(rects[1])) nrect.setTop(rects[1].pos().y() + (sp - pp).y()); + if (watched == &(rects[2])) nrect.setTopRight(rects[2].pos() + (sp - pp)); + if (watched == &(rects[3])) nrect.setRight(rects[3].pos().x() + (sp - pp).x()); + if (watched == &(rects[4])) nrect.setBottomRight(rects[4].pos() + (sp - pp)); + if (watched == &(rects[5])) nrect.setBottom(rects[5].pos().y() + (sp - pp).y()); + if (watched == &(rects[6])) nrect.setBottomLeft(rects[6].pos() + (sp - pp)); + if (watched == &(rects[7])) nrect.setLeft(rects[7].pos().x() + (sp - pp).x()); + nrect = nrect.normalized(); + } + pp = sp; + applyRect(); + moveRects(); + } + } + return true; + case QEvent::GraphicsSceneMouseRelease: + if (in_process) + emit sizeChanged(); + in_process = false; + can_drag = false; + return true; + default: break; + } + return QGraphicsItem::sceneEventFilter(watched, event); +} + + + + +DrawTools::DrawTools(BlockView * parent): QObject(parent), +actions_Z_up(this), actions_Z_top(this), actions_Z_down(this), actions_Z_bottom(this) { + widget_props = new QWidget(); + ui = new Ui::DrawTools(); + ui->setupUi(widget_props); + widget_props->setEnabled(false); + setAlignCompact(false); + menu_hor.addActions(QList() << ui->actionLeft << ui->actionHCenter << ui->actionRight); + menu_ver.addActions(QList() << ui->actionTop << ui->actionVCenter << ui->actionBottom); + ui->buttonAlignHor->setMenu(&menu_hor); + ui->buttonAlignVer->setMenu(&menu_ver); + new_type = -1; + new_item = cur_item = 0; + view_ = 0; + resize_enabled = true; + text_dlg.setWindowTitle(trUtf8("Edit text")); + text_dlg.setLayout(new QBoxLayout(QBoxLayout::TopToBottom)); + QDialogButtonBox * bbox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel); + connect(bbox, SIGNAL(accepted()), &text_dlg, SLOT(accept())); + connect(bbox, SIGNAL(rejected()), &text_dlg, SLOT(reject())); + text_dlg.layout()->addWidget(&text_edit); + text_dlg.layout()->addWidget(bbox); + actions_Z_up.setText(trUtf8("Bring\nforward")); actions_Z_up.setIcon(QIcon(":/icons/z-up.png")); actions_Z_up.setEnabled(false); + actions_Z_top.setText(trUtf8("Bring\nto front")); actions_Z_top.setIcon(QIcon(":/icons/z-top.png")); actions_Z_top.setEnabled(false); + actions_Z_down.setText(trUtf8("Send\nbackward")); actions_Z_down.setIcon(QIcon(":/icons/z-down.png")); actions_Z_down.setEnabled(false); + actions_Z_bottom.setText(trUtf8("Send\nto back")); actions_Z_bottom.setIcon(QIcon(":/icons/z-bottom.png")); actions_Z_bottom.setEnabled(false); + actions_add << newAction(trUtf8("Draw\nRectangle"), QIcon(":/icons/draw-rectangle.png"), 1) + << newAction(trUtf8("Draw\nEllipse"), QIcon(":/icons/draw-ellipse.png"), 2) + << newAction(trUtf8("Draw\nLine"), QIcon(":/icons/draw-line.png"), 4) + << newAction(trUtf8("Draw\nText"), QIcon(":/icons/draw-text.png"), 0) + << newAction(trUtf8("Draw\nImage"), QIcon(":/icons/view-preview.png"), 3); + buttons_align << ui->buttonAlignTL << ui->buttonAlignTC << ui->buttonAlignTR + << ui->buttonAlignCL << ui->buttonAlignCC << ui->buttonAlignCR + << ui->buttonAlignBL << ui->buttonAlignBC << ui->buttonAlignBR; + foreach (QAction * a, actions_add) + connect(a, SIGNAL(toggled(bool)), this, SLOT(toggleNewItem(bool))); + foreach (QToolButton * b, buttons_align) + connect(b, SIGNAL(clicked(bool)), this, SLOT(alignClicked())); + connect(ui->buttonImage, SIGNAL(clicked(bool)), this, SLOT(buttonImage_clicked())); + connect(ui->buttonFont, SIGNAL(clicked(bool)), this, SLOT(buttonFont_clicked())); + connect(ui->buttonTextEdit, SIGNAL(clicked(bool)), this, SLOT(buttonTextEdit_clicked())); + connect(ui->spinWidth, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged())); + connect(ui->spinWidth, SIGNAL(editingFinished()), this, SLOT(changeFinished())); + connect(ui->spinHeight, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged())); + connect(ui->spinHeight, SIGNAL(editingFinished()), this, SLOT(changeFinished())); + connect(ui->spinThick, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged())); + connect(ui->spinThick, SIGNAL(editingFinished()), this, SLOT(changeFinished())); + connect(ui->comboText, SIGNAL(editTextChanged(QString)), this, SLOT(propertyChanged())); + connect(ui->comboText->lineEdit(), SIGNAL(editingFinished()), this, SLOT(changeFinished())); + connect(ui->colorButtonPen, SIGNAL(colorChanged(QColor)), this, SLOT(propertyChanged())); + connect(ui->colorButtonPen, SIGNAL(colorChanged(QColor)), this, SLOT(changeFinished())); + connect(ui->colorButtonBrush, SIGNAL(colorChanged(QColor)), this, SLOT(propertyChanged())); + connect(ui->colorButtonBrush, SIGNAL(colorChanged(QColor)), this, SLOT(changeFinished())); + connect(ui->actionTop, SIGNAL(triggered(bool)), this, SLOT(actionTop_triggered(bool))); + connect(ui->actionVCenter, SIGNAL(triggered(bool)), this, SLOT(actionVCenter_triggered(bool))); + connect(ui->actionBottom, SIGNAL(triggered(bool)), this, SLOT(actionBottom_triggered(bool))); + connect(ui->actionLeft, SIGNAL(triggered(bool)), this, SLOT(actionLeft_triggered(bool))); + connect(ui->actionHCenter, SIGNAL(triggered(bool)), this, SLOT(actionHCenter_triggered(bool))); + connect(ui->actionRight, SIGNAL(triggered(bool)), this, SLOT(actionRight_triggered(bool))); + connect(&font_dlg, SIGNAL(currentFontChanged(QFont)), this, SLOT(propertyChanged())); + connect(&size_item, SIGNAL(sizeChanged()), this, SLOT(sizeChanged())); + connect(&size_item, SIGNAL(textEditRequest()), this, SLOT(buttonTextEdit_clicked())); + connect(&size_item, SIGNAL(pixmapEditRequest()), this, SLOT(buttonImage_clicked())); + connect(&actions_Z_up, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered())); + connect(&actions_Z_top, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered())); + connect(&actions_Z_down, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered())); + connect(&actions_Z_bottom, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered())); + setBlockView(parent); +} + + +DrawTools::~DrawTools() { + size_item.assignObject(0); + //delete ui; + //delete widget_props; +} + + +void DrawTools::setBlockView(BlockView * v) { + if (view_) view_->viewport()->removeEventFilter(this); + disconnect(this, SLOT(selectionChanged())); + view_ = v; + if (!view_) return; + view_->addItem(&size_item); + view_->viewport()->installEventFilter(this); + connect(view_->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); +} + + +void DrawTools::setAlignCompact(bool yes) { + ui->widgetAlign2->setVisible(yes); + ui->widgetAlign9->setVisible(!yes); +} + + +bool DrawTools::eventFilter(QObject * o, QEvent * e) { + QMouseEvent * me = (QMouseEvent*)e; + QPointF sp; + if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseMove) + sp = quantize(view_->mapToScene(me->pos()), view_->gridStep()); + QRectF mr; + switch (e->type()) { + case QEvent::MouseButtonPress: + if (new_type < 0) break; + if (new_item) { + delete new_item; + new_item = 0; + if (!me->modifiers().testFlag(Qt::ControlModifier)) { + foreach (QAction * a, actions_add) + a->setChecked(false); + new_type = -1; + //view_->setCursor(Qt::ArrowCursor); + return true; + } + } + new_item = 0; + pp = sp; + switch (new_type) { + case 0: + new_item = new AlignedTextItem(); + ((AlignedTextItem*)new_item)->setText("Text"); + ((AlignedTextItem*)new_item)->setPos(sp); + break; + case 1: + new_item = new QGraphicsRectItem(); + break; + case 2: + new_item = new QGraphicsEllipseItem(); + break; + case 3: + new_item = new QGraphicsPixmapItem(QPixmap(":/icons/view-preview.png")); + ((QGraphicsPixmapItem*)new_item)->setPos(sp - QPointF(new_item->boundingRect().width() / 2, new_item->boundingRect().height() / 2)); + break; + case 4: + new_item = new QGraphicsLineItem(QLineF(sp, sp)); + break; + }; + if (new_item) { + if (new_type == 1 || new_type == 2) + ((QAbstractGraphicsShapeItem*)new_item)->setBrush(Qt::white); + new_item->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); + new_item->setData(1100, true); + emit itemCreated(new_item); + return true; + } + break; + case QEvent::MouseMove: + if (me->buttons().testFlag(Qt::LeftButton)) { + if (new_item) { + mr = new_item->mapRectFromScene(QRectF(pp, sp).normalized()); + //mr = QRectF(pp, sp).normalized(); + switch (new_type) { + case 0: + ((AlignedTextItem*)new_item)->setPos(sp); + break; + case 1: + ((QGraphicsRectItem*)new_item)->setRect(mr); + break; + case 2: + ((QGraphicsEllipseItem*)new_item)->setRect(mr); + break; + case 3: + ((QGraphicsPixmapItem*)new_item)->setPos(sp - QPointF(new_item->boundingRect().width() / 2, new_item->boundingRect().height() / 2)); + break; + case 4: + ((QGraphicsLineItem*)new_item)->setLine(QLineF(pp, sp)); + break; + }; + return true; + } + } + break; + case QEvent::MouseButtonRelease: + if (new_item) { + if (new_item->boundingRect().isEmpty()) + delete new_item; + else + emit itemAddConfirm(new_item); + new_item = 0; + if (!me->modifiers().testFlag(Qt::ControlModifier)) { + foreach (QAction * a, actions_add) + a->setChecked(false); + new_type = -1; + //view_->setCursor(Qt::ArrowCursor); + } + return true; + } + break; + default: break; + } + return QObject::eventFilter(o, e); +} + + +QComboBox * DrawTools::textEditCombo() const { + return ui->comboText; +} + + +QAction * DrawTools::newAction(const QString & text, const QIcon & icon, int type) { + QAction * ret = new QAction(icon, text, this); + ret->setCheckable(true); + ret->setData(type); + return ret; +} + + +void DrawTools::toggleNewItem(bool on) { + QAction * sa = (QAction * )sender(); + foreach (QAction * a, actions_add) + if (a != sa) + a->setChecked(false); + if (!on) { + new_type = -1; + view_->unsetCursor(); + return; + } + new_type = sa->data().toInt(); + view_->setCursor(Qt::CrossCursor); +} + + +void DrawTools::alignClicked() { + QToolButton * sb = (QToolButton * )sender(); + foreach (QToolButton * b, buttons_align) + if (b != sb) + b->setChecked(false); + sb->setChecked(true); + align = 0; + QString als = sb->objectName().right(2).toLower(); + if (als[0] == 't') align |= Qt::AlignTop; + if (als[0] == 'c') align |= Qt::AlignVCenter; + if (als[0] == 'b') align |= Qt::AlignBottom; + if (als[1] == 'l') align |= Qt::AlignLeft; + if (als[1] == 'c') align |= Qt::AlignHCenter; + if (als[1] == 'r') align |= Qt::AlignRight; + propertyChanged(); +} + + +void DrawTools::setPenBrushEnabled(bool pen, bool brush) { + ui->labelPen->setEnabled(pen); + ui->colorButtonPen->setEnabled(pen); + ui->labelBrush->setEnabled(brush); + ui->colorButtonBrush->setEnabled(brush); +} + + +void DrawTools::blockPropSignals(bool block_) { + ui->spinWidth->blockSignals(block_); + ui->spinHeight->blockSignals(block_); + ui->spinThick->blockSignals(block_); + ui->comboText->blockSignals(block_); + ui->colorButtonPen->blockSignals(block_); + ui->colorButtonBrush->blockSignals(block_); + ui->actionTop->blockSignals(block_); + ui->actionVCenter->blockSignals(block_); + ui->actionBottom->blockSignals(block_); + ui->actionHCenter->blockSignals(block_); + ui->actionLeft->blockSignals(block_); + ui->actionRight->blockSignals(block_); + foreach (QToolButton * b, buttons_align) + b->blockSignals(block_); +} + + +void DrawTools::actionAlignTrigger(bool vert, Qt::AlignmentFlag value) { + blockPropSignals(true); + if (vert) foreach (QAction * a, menu_ver.actions()) a->setChecked(false); + else foreach (QAction * a, menu_hor.actions()) a->setChecked(false); + align = align & (vert ? Qt::AlignHorizontal_Mask : Qt::AlignVertical_Mask); + align |= value; + ((QAction*)sender())->setChecked(true); + blockPropSignals(false); + propertyChanged(); +} + + +void DrawTools::emitZAvailabe(QGraphicsItem * item) { + BlockView * view = 0; + if (item) if (item->scene()) if (!item->scene()->views().isEmpty()) view = qobject_cast(item->scene()->views()[0]); + if (view == 0) { + moveZUpAvailable(false); + moveZDownAvailable(false); + return; + } + QList dl; + if (item->parentItem() == 0) dl = view->decors(); + else if (item->parentItem()->data(1006) == "item") dl = ((BlockItem*)(item->parentItem()))->decors_; + if (dl.size() <= 1) { + moveZUpAvailable(false); + moveZDownAvailable(false); + return; + } + int ind = dl.indexOf(item); + if (ind < 0) { + moveZUpAvailable(false); + moveZDownAvailable(false); + } else { + moveZUpAvailable(ind < dl.size() - 1); + moveZDownAvailable(ind > 0); + } +} + + +void DrawTools::selectionChanged() { + cur_item = 0; + size_item.assignObject(0); + if (!view_) { + emitZAvailabe(); + return; + } + QList sil = view_->scene()->selectedItems(); + if (sil.size() != 1) { + emitZAvailabe(); + widget_props->setEnabled(false); + return; + } + widget_props->setEnabled(true); + cur_item = sil[0]; + if (!cur_item) { + emitZAvailabe(); + return; + } + QGraphicsSimpleTextItem * itext = qgraphicsitem_cast(cur_item); + AlignedTextItem * iatext = qgraphicsitem_cast(cur_item); + QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast(cur_item); + QGraphicsRectItem * irect = qgraphicsitem_cast(cur_item); + QGraphicsEllipseItem * iell = qgraphicsitem_cast(cur_item); + QGraphicsLineItem * iline = qgraphicsitem_cast(cur_item); + blockPropSignals(true); + if (itext) { + ui->stackedProperties->setCurrentIndex(0); + ui->comboText->setEditText(itext->text()); + ui->colorButtonPen->setColor(itext->brush().color()); + font_dlg.blockSignals(true); + font_dlg.setCurrentFont(itext->font()); + font_dlg.blockSignals(false); + setPenBrushEnabled(true, false); + ui->widgetAlign2->setEnabled(false); + ui->widgetAlign9->setEnabled(false); + size_item.assignObject(itext); + } else if (iatext) { + ui->stackedProperties->setCurrentIndex(0); + ui->comboText->setEditText(iatext->text()); + ui->colorButtonPen->setColor(iatext->brush().color()); + font_dlg.blockSignals(true); + font_dlg.setCurrentFont(iatext->font()); + font_dlg.blockSignals(false); + setPenBrushEnabled(true, false); + foreach (QAction * a, menu_hor.actions()) a->setChecked(false); + foreach (QAction * a, menu_ver.actions()) a->setChecked(false); + align = iatext->alignment(); + QString als; + if (align.testFlag(Qt::AlignTop)) {als += "T"; ui->actionTop->setChecked(true);} + if (align.testFlag(Qt::AlignVCenter)) {als += "C"; ui->actionVCenter->setChecked(true);} + if (align.testFlag(Qt::AlignBottom)) {als += "B"; ui->actionBottom->setChecked(true);} + if (align.testFlag(Qt::AlignLeft)) {als += "L"; ui->actionLeft->setChecked(true);} + if (align.testFlag(Qt::AlignHCenter)) {als += "C"; ui->actionHCenter->setChecked(true);} + if (align.testFlag(Qt::AlignRight)) {als += "R"; ui->actionRight->setChecked(true);} + foreach (QToolButton * b, buttons_align) + b->setChecked(false); + foreach (QToolButton * b, buttons_align) + if (b->objectName().endsWith(als)) { + b->setChecked(true); + break; + } + ui->widgetAlign2->setEnabled(true); + ui->widgetAlign9->setEnabled(true); + size_item.assignObject(iatext); + } else if (ipixmap) { + ui->stackedProperties->setCurrentIndex(2); + setPenBrushEnabled(false, false); + size_item.assignObject(ipixmap); + } else if (irect || iell) { + ui->stackedProperties->setCurrentIndex(1); + QAbstractGraphicsShapeItem * ishape(0); + if (irect) { + ishape = irect; + ui->spinWidth->setValue(irect->rect().width()); + ui->spinHeight->setValue(irect->rect().height()); + } + if (iell) { + ishape = iell; + ui->spinWidth->setValue(iell->rect().width()); + ui->spinHeight->setValue(iell->rect().height()); + } + if (ishape) { + ui->colorButtonPen->setColor(ishape->pen().color()); + ui->colorButtonBrush->setColor(ishape->brush().color()); + ui->spinThick->setValue(ishape->pen().widthF()); + setPenBrushEnabled(true, true); + if (resize_enabled) + size_item.assignObject(ishape); + } + } else if (iline) { + ui->stackedProperties->setCurrentIndex(1); + ui->colorButtonPen->setColor(iline->pen().color()); + ui->spinThick->setValue(iline->pen().widthF()); + setPenBrushEnabled(true, false); + if (resize_enabled) + size_item.assignObject(iline); + } else { + ui->stackedProperties->setCurrentIndex(3); + widget_props->setEnabled(false); + } + emitZAvailabe(cur_item); + blockPropSignals(false); +} + + +void DrawTools::sizeChanged() { + blockPropSignals(true); + QGraphicsRectItem * irect = qgraphicsitem_cast(cur_item); + QGraphicsEllipseItem * iell = qgraphicsitem_cast(cur_item); + if (irect || iell) { + if (irect) { + ui->spinWidth->setValue(irect->rect().width()); + ui->spinHeight->setValue(irect->rect().height()); + } + if (iell) { + ui->spinWidth->setValue(iell->rect().width()); + ui->spinHeight->setValue(iell->rect().height()); + } + } + blockPropSignals(false); + changeFinished(); +} + + +void DrawTools::propertyChanged() { + if (!cur_item) return; + QGraphicsSimpleTextItem * itext = qgraphicsitem_cast(cur_item); + AlignedTextItem * iatext = qgraphicsitem_cast(cur_item); + QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast(cur_item); + QGraphicsRectItem * irect = qgraphicsitem_cast(cur_item); + QGraphicsEllipseItem * iell = qgraphicsitem_cast(cur_item); + QGraphicsLineItem * iline = qgraphicsitem_cast(cur_item); + if (itext) { + QRectF obr = itext->boundingRect(); + itext->setFont(font_dlg.currentFont()); + itext->setText(ui->comboText->currentText()); + QRectF nbr = itext->boundingRect(); + QSizeF ds = (obr.size() - nbr.size()) / 2.; + itext->setPos(itext->pos() + QPointF(ds.width(), ds.height())); + itext->setBrush(ui->colorButtonPen->color()); + } else if (iatext) { + iatext->setFont(font_dlg.currentFont()); + iatext->setText(ui->comboText->currentText()); + iatext->setBrush(ui->colorButtonPen->color()); + iatext->setAlignment(align); + } else if (ipixmap) { + } else if (irect || iell) { + QAbstractGraphicsShapeItem * ishape(0); + if (irect) { + ishape = irect; + irect->setRect(QRectF(irect->rect().topLeft(), QSizeF(ui->spinWidth->value(), ui->spinHeight->value()))); + } + if (iell) { + ishape = iell; + iell->setRect(QRectF(iell->rect().topLeft(), QSizeF(ui->spinWidth->value(), ui->spinHeight->value()))); + } + if (ishape) { + ishape->setPen(QPen(ui->colorButtonPen->color(), ui->spinThick->value())); + ishape->setBrush(ui->colorButtonBrush->color()); + if (resize_enabled) + size_item.assignObject(ishape); + } + } else if (iline) { + iline->setPen(QPen(ui->colorButtonPen->color(), ui->spinThick->value())); + if (resize_enabled) + size_item.assignObject(iline); + } +} + + +void DrawTools::buttonImage_clicked() { + QGraphicsPixmapItem * pi = qgraphicsitem_cast(cur_item); + if (!pi) return; + QList sif(QImageReader::supportedImageFormats()); + QString f; + foreach (const QByteArray & i, sif) { + if (!f.isEmpty()) f += " "; + f += "*."; + f += i; + } + QString ret = QFileDialog::getOpenFileName(0, trUtf8("Select image"), pi->data(1101).toString(), QString("Images(%1)").arg(f)); + if (ret.isEmpty()) return; + QImage im(ret); + if (im.isNull()) return; + pi->setData(1101, ret); + QRectF obr = pi->boundingRect(); + pi->setPixmap(QPixmap::fromImage(im)); + QRectF nbr = pi->boundingRect(); + QSizeF ds = (obr.size() - nbr.size()) / 2.; + pi->setPos(pi->pos() + QPointF(ds.width(), ds.height())); + changeFinished(); +} + + +void DrawTools::buttonFont_clicked() { + if (!cur_item) return; + QGraphicsSimpleTextItem * ti = qgraphicsitem_cast(cur_item); + AlignedTextItem * ati = qgraphicsitem_cast(cur_item); + if (!ti && !ati) return; + QFont font_prev; + if (ti) font_prev = ti->font(); + if (ati) font_prev = ati->font(); + font_dlg.blockSignals(true); + font_dlg.setCurrentFont(font_prev); + font_dlg.blockSignals(false); + if (font_dlg.exec() == QDialog::Rejected) + font_dlg.setCurrentFont(font_prev); + else + changeFinished(); +} + + +void DrawTools::buttonTextEdit_clicked() { + text_edit.setPlainText(ui->comboText->lineEdit()->text()); + if (text_dlg.exec() == QDialog::Rejected) + return; + ui->comboText->lineEdit()->setText(text_edit.toPlainText()); + propertyChanged(); + changeFinished(); +} + + +void DrawTools::actionZ_triggered() { + if (!cur_item) return; + if (cur_item->data(1009) == "decor") { + BlockView * view = 0; + if (cur_item) if (cur_item->scene()) if (!cur_item->scene()->views().isEmpty()) + view = qobject_cast(cur_item->scene()->views()[0]); + if (!view) return; + QGraphicsScene * scene = view->scene(); + QList dl = view->decors(); + scene->blockSignals(true); + foreach (QGraphicsItem * d, dl) scene->removeItem(d); + int ind = dl.indexOf(cur_item); + dl.removeAt(ind); + if (sender() == &actions_Z_up) dl.insert(ind + 1, cur_item); + if (sender() == &actions_Z_top) dl.append(cur_item); + if (sender() == &actions_Z_down) dl.insert(ind - 1, cur_item); + if (sender() == &actions_Z_bottom) dl.prepend(cur_item); + foreach (QGraphicsItem * d, dl) scene->addItem(d); + scene->blockSignals(false); + } + if (cur_item->data(1011) == "decor") { + BlockItem * bi = qgraphicsitem_cast(cur_item->parentItem()); + if (!bi) return; + QList dl = bi->decors_; + foreach (QGraphicsItem * d, dl) d->setParentItem(0); + int ind = dl.indexOf(cur_item); + dl.removeAt(ind); + if (sender() == &actions_Z_up) dl.insert(ind + 1, cur_item); + if (sender() == &actions_Z_top) dl.append(cur_item); + if (sender() == &actions_Z_down) dl.insert(ind - 1, cur_item); + if (sender() == &actions_Z_bottom) dl.prepend(cur_item); + bi->decors_ = dl; + foreach (QGraphicsItem * d, dl) d->setParentItem(bi); + } + size_item.assignObject(cur_item); + emitZAvailabe(cur_item); + emit itemZChanged(cur_item); +} + + +void DrawTools::setResizeHandlesEnabled(bool on) { + resize_enabled = on; + if (!on) { + size_item.assignObject(0); + return; + } + if (cur_item && on) + propertyChanged(); +} diff --git a/qad/blockview/drawtools.h b/qad/blockview/drawtools.h new file mode 100644 index 0000000..fd5d546 --- /dev/null +++ b/qad/blockview/drawtools.h @@ -0,0 +1,129 @@ +#ifndef DRAWTOOLS_H +#define DRAWTOOLS_H + +#include +#include +#include +#include +#include +#include +#include "blockview.h" + +class QComboBox; + +class _DTSizeItem: public QGraphicsObject +{ + Q_OBJECT +public: + _DTSizeItem(); + ~_DTSizeItem(); + + void assignObject(QGraphicsItem * item); + +protected: + void moveRects(); + void applyRect(); + void doubleClick(); + QRectF itemRect(const QGraphicsItem * item) const; + QRectF boundingRect() const; + void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {} + bool sceneEventFilter(QGraphicsItem * watched, QEvent * event); + + QGraphicsItem * cur_item; + QGraphicsView * view_; + QGraphicsRectItem rects[8]; + QPointF pp, sp; + QRectF nrect; + qreal grid; + bool in_process, can_drag, is_line; + +signals: + void sizeChanged(); + void textEditRequest(); + void pixmapEditRequest(); + +}; + +namespace Ui { + class DrawTools; +}; + +class DrawTools: public QObject +{ + Q_OBJECT + Q_PROPERTY(bool resizeHandlesEnabled READ isResizeHandlesEnabled WRITE setResizeHandlesEnabled) +public: + explicit DrawTools(BlockView * parent = 0); + ~DrawTools(); + + void setBlockView(BlockView * v); + void resetSizeTool() {size_item.assignObject(0);} + bool isResizeHandlesEnabled() const {return resize_enabled;} + void setAlignCompact(bool yes); + + QComboBox * textEditCombo() const; + QList actionsForAdd() const {return actions_add;} + QList actionsForZ() const {return QList() << &actions_Z_bottom << &actions_Z_down << &actions_Z_up << &actions_Z_top;} + QWidget * propertyWidget() const {return widget_props;} + +protected: + bool eventFilter(QObject * o, QEvent * e); + + QAction * newAction(const QString & text, const QIcon & icon, int type); + void setPenBrushEnabled(bool pen, bool brush); + void blockPropSignals(bool block_); + void actionAlignTrigger(bool vert, Qt::AlignmentFlag value); + void emitZAvailabe(QGraphicsItem * item = 0); + + QWidget * widget_props; + Ui::DrawTools * ui; + BlockView * view_; + QList actions_add; + mutable QAction actions_Z_up, actions_Z_top, actions_Z_down, actions_Z_bottom; + QList buttons_align; + QGraphicsItem * new_item, * cur_item; + QFontDialog font_dlg; + QPointF pp; + QDialog text_dlg; + QPlainTextEdit text_edit; + QMenu menu_hor, menu_ver; + _DTSizeItem size_item; + Qt::Alignment align; + int new_type; + bool resize_enabled; + +private slots: + void toggleNewItem(bool on); + void alignClicked(); + void selectionChanged(); + void sizeChanged(); + void propertyChanged(); + void changeFinished() {if (cur_item) emit itemEdited(cur_item);} + void moveZUpAvailable(bool yes) {actions_Z_up.setEnabled(yes); actions_Z_top.setEnabled(yes);} + void moveZDownAvailable(bool yes) {actions_Z_down.setEnabled(yes); actions_Z_bottom.setEnabled(yes);} + + void buttonImage_clicked(); + void buttonFont_clicked(); + void buttonTextEdit_clicked(); + + void actionTop_triggered(bool on) {actionAlignTrigger(true, Qt::AlignTop);} + void actionVCenter_triggered(bool on) {actionAlignTrigger(true, Qt::AlignVCenter);} + void actionBottom_triggered(bool on) {actionAlignTrigger(true, Qt::AlignBottom);} + void actionLeft_triggered(bool on) {actionAlignTrigger(false, Qt::AlignLeft);} + void actionHCenter_triggered(bool on) {actionAlignTrigger(false, Qt::AlignHCenter);} + void actionRight_triggered(bool on) {actionAlignTrigger(false, Qt::AlignRight);} + void actionZ_triggered(); + +public slots: + void setResizeHandlesEnabled(bool on); + +signals: + void itemCreated(QGraphicsItem * item); + void itemAddConfirm(QGraphicsItem * item); + void itemEdited(QGraphicsItem * item); + void itemZChanged(QGraphicsItem * item); + +}; + + +#endif // DRAWTOOLS_H diff --git a/qad/blockview/drawtools.ui b/qad/blockview/drawtools.ui new file mode 100644 index 0000000..7449dcf --- /dev/null +++ b/qad/blockview/drawtools.ui @@ -0,0 +1,666 @@ + + + DrawTools + + + + 0 + 0 + 656 + 111 + + + + Form + + + + 0 + + + + + 3 + + + + + 0 + + + + + Font ... + + + + :/icons/draw-text.png:/icons/draw-text.png + + + + + + + Text: + + + + + + + + 0 + 0 + + + + true + + + -1 + + + 32 + + + QComboBox::NoInsert + + + + + + + Edit text ... + + + Edit text ... + + + + :/icons/document-edit-.png:/icons/document-edit-.png + + + Qt::ToolButtonIconOnly + + + + + + + + 0 + + + + + Align center left + + + + :/icons/align-hor.png:/icons/align-hor.png + + + + 27 + 22 + + + + QToolButton::InstantPopup + + + + + + + Align center left + + + + :/icons/align-ver.png:/icons/align-ver.png + + + + 27 + 22 + + + + QToolButton::InstantPopup + + + + + + + + + + + 0 + + + 2 + + + + + + 0 + 0 + + + + Align center + + + + :/icons/align-center-center.png:/icons/align-center-center.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align center right + + + + :/icons/align-center-right.png:/icons/align-center-right.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align center left + + + + :/icons/align-center-left.png:/icons/align-center-left.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align top right + + + + :/icons/align-top-right.png:/icons/align-top-right.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align bottom right + + + + :/icons/align-bottom-right.png:/icons/align-bottom-right.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align bottom center + + + + :/icons/align-bottom-center.png:/icons/align-bottom-center.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align top left + + + + :/icons/align-top-left.png:/icons/align-top-left.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align top center + + + + :/icons/align-top-center.png:/icons/align-top-center.png + + + + 27 + 16 + + + + true + + + + + + + + 0 + 0 + + + + Align bottom left + + + + :/icons/align-bottom-left.png:/icons/align-bottom-left.png + + + + 27 + 16 + + + + true + + + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + Size: + + + + + + + + 0 + 0 + + + + 0 + + + 1000.000000000000000 + + + 10.000000000000000 + + + + + + + + 0 + 0 + + + + X + + + + + + + + 0 + 0 + + + + 0 + + + 1000.000000000000000 + + + 10.000000000000000 + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + Width: + + + + + + + + 0 + 0 + + + + 1 + + + 999.000000000000000 + + + 0.500000000000000 + + + + + + + + + 0 + + + + + Load image ... + + + + :/icons/document-open.png:/icons/document-open.png + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 16 + 20 + + + + + + + + :/icons/format-stroke-color.png + + + + + + + true + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 16 + 20 + + + + + + + + :/icons/format-fill-color.png + + + + + + + true + + + true + + + + + + + true + + + Top + + + + + true + + + Center + + + Center + + + + + true + + + Bottom + + + Bottom + + + + + true + + + Center + + + Center + + + + + true + + + Left + + + Left + + + + + true + + + Right + + + Right + + + + + + ColorButton + QPushButton +
colorbutton.h
+
+
+ + + + +
diff --git a/qad/blockview/lang/qad_blockview_ru.qm b/qad/blockview/lang/qad_blockview_ru.qm new file mode 100644 index 0000000000000000000000000000000000000000..a863ce121e11d9494fb9b2b22260b99f3e83a016 GIT binary patch literal 3377 zcmbVOTWl0%6h7>p*?Y@UDv)v;2+Gyc3$4qRUUs)oprsHNLrWxK*bdtX%g$zZs)fV{ zK?xxmeZiQbB*bV)B>E&VO%S6dB5L#j-!$Om!QcZXULhg){j+6u?94XAG}D>gJ>PfE z`Tld6O&^RbxOV&XGhZ!RbmhSL%ikx7X1zkRa-4|w6ZMY}`Mt!)@8a`m;tQ`4`PLKv z@(1khmGAyLB%PP=doxLw;zZ#vZC`twhz#1^eg^lqXom-Qf1Gw-K1LK+Nl$M1kSOS- zq36FP@-C)*2f-J7pRW8ciF?d5`S&?|f7f&SuUoKx(R=Eq7x(M@cKbde={{eaI0*mq zrM2Jn5_wjZ?|~s{-QWd$-YdO)1AcK>A zn|I>){i^S$vm5dKr0-{X7x7;A_rLcD{0|292iCyf3xSirrV#%pfwN0LMgD5wi~aBm z4{g6)g})QHe~$Y%!NZrf!~R<6;-eGb&ESssLrvlNKf+pyguj;!WJd3Eqn5 zCT+xg-JTDtjQA8pWUGsV1f8 z4{6!4qAE8wHaaLG+`uWo6CmiZK)%#iv7|fWYv85a0hcYf26-D?wn2|Bpko#`T*k`E zxK?twi`v~$oMa0YD8u5i1Jf`aL#vQw2d>o?y5<3TmE0k(c2Ifm0%%b`^V4%=q4&k6k-fd zJH>e;r6DW6nw|OFQCS@?DESe2=zoz7yORw&$fC$1hG@ERJ%JcIEugep$!DFFw+4cC z@n$oHPC(0z5i`N%R%tgSM1fdTp|tX}DsMZYxbU?+JfEY&YfWBF@Vb_G9g7CufOt9_ zF$L3VPR$sao_A;xVcAq;6F`;D;IwwkDMtvW*$o-uoUqdM%7t-38lD;^q7Ti15f8_n?*;|-SY zP@+)4C{pqnGc8B7EB-S##T@GcTLP(;*|s94R*Nktrl?#p)Pid;_52u;Kqn%MUQuV< zWRqb|Qpp_77WFX{d`8ddMR!eVG4*2HZf0dy(Vx@}LqFmU3R#{jvinlioz(Fv6m<_A zZAP3z_?=dg+^dw#?skZ^#D-dmx!MVtgk(J;QyW7-Fg)I?o7=|0vaTx2Oq`JioK<=2 zF}&@gVv~DA|uQZ#BQ^1(kgg*G+YZTtFQj zQ4O_dE)It-wLI5`uWX#a6y6;**VEHx7!4g3eVzP;qY|GQ1#%Pm=+>fII z8FoO1t3j3_vX~iZ<>Y;7<7iHGM=Y=gnG7UOp`4%1VR(-^Zp<`5qgX)LX_#z6Bzv9n k9=+i1Hae|jZNct!FVIuieKm7t-CG^LU+>|2>q2w?1;33x^Z)<= literal 0 HcmV?d00001 diff --git a/qad/blockview/lang/qad_blockview_ru.ts b/qad/blockview/lang/qad_blockview_ru.ts new file mode 100644 index 0000000..377960d --- /dev/null +++ b/qad/blockview/lang/qad_blockview_ru.ts @@ -0,0 +1,290 @@ + + + + + Graphic + + + Autofit + Автомасштаб + + + + Grid + Сетка + + + + Cursor axis + Плавающие оси + + + + Only expand Y + Только расширять Y + + + + Only expand X + Только расширять X + + + + Border inputs + + + + + Legend + Легенда + + + + Configure ... + Настроить ... + + + + Save image ... + Сохранить изображение ... + + + + Clear + Очистить + + + + Close + Закрыть + + + + Cursor: ( ; ) + Курсор: ( ; ) + + + + + Cursor: + Курсор: + + + + Selection + Выделение + + + + Size + Размер + + + + + Range + Диапазон + + + + + Length + Длина + + + + + Cursor + Курсор + + + + Save Image + Сохранить изображение + + + + y(x) + + + + + Check all + Выбрать все + + + + GraphicConf + + + Graphic parameters + Параметры графика + + + + Appearance + Внешний вид + + + + Border inputs + + + + + Antialiasing + Сглаживание + + + + Status bar + Панель статуса + + + + OpenGL + + + + + Legend + Легенда + + + + Background color: + Цвет фона: + + + + Text color: + Цвет текста: + + + + Graphics + Графики + + + + + Color: + Цвет: + + + + + Style: + Стиль: + + + + Lines width: + Толщина линий: + + + + Points width: + Толщина точек: + + + + Fill: + Заливка: + + + + Grid + Сетка + + + + Width: + Толщина: + + + + Step X: + Шаг X: + + + + Step Y: + Шаг Y: + + + + Auto step + Автоматический шаг + + + + Margins + Поля + + + + + + + + px + пикс + + + + All: + Все: + + + + Right: + Правое: + + + + Left: + Левое: + + + + Bottom: + Нижнее: + + + + Top: + Верхнее: + + + + NoPen + НетЛинии + + + + Solid + Сплошная + + + + Dash + Штриховая + + + + Dot + Пунктирная + + + + Dash-Dot + ШтрихПунктирная + + + + Dash-Dot-Dot + ШтрихПунктирПунктирная + + + diff --git a/qad/blockview/plugin/CMakeLists.txt b/qad/blockview/plugin/CMakeLists.txt new file mode 100644 index 0000000..15ccc7a --- /dev/null +++ b/qad/blockview/plugin/CMakeLists.txt @@ -0,0 +1 @@ +qad_plugin(blockview "") diff --git a/qad/blockview/plugin/blockviewplugin.cpp b/qad/blockview/plugin/blockviewplugin.cpp new file mode 100644 index 0000000..4bd2d2a --- /dev/null +++ b/qad/blockview/plugin/blockviewplugin.cpp @@ -0,0 +1,69 @@ +#include "blockview.h" +#include "blockviewplugin.h" +#include + + +BlockViewPlugin::BlockViewPlugin(QObject * parent): QObject(parent) { + m_initialized = false; +} + + +void BlockViewPlugin::initialize(QDesignerFormEditorInterface * /* core */) { + if (m_initialized) + return; + + // Add extension registrations, etc. here + + m_initialized = true; +} + + +bool BlockViewPlugin::isInitialized() const { + return m_initialized; +} + + +QWidget * BlockViewPlugin::createWidget(QWidget * parent) { + return new BlockView(parent); +} + + +QString BlockViewPlugin::name() const { + return QLatin1String("BlockView"); +} + + +QString BlockViewPlugin::group() const { + return QLatin1String("Display Widgets"); +} + + +QIcon BlockViewPlugin::icon() const { + return QIcon(":/icons/blockview.png"); +} + + +QString BlockViewPlugin::toolTip() const { + return QLatin1String(""); +} + + +QString BlockViewPlugin::whatsThis() const { + return QLatin1String(""); +} + + +bool BlockViewPlugin::isContainer() const { + return false; +} + + +QString BlockViewPlugin::domXml() const { + return QLatin1String("\n\n"); +} + + +QString BlockViewPlugin::includeFile() const { + return QLatin1String("blockview.h"); +} + diff --git a/qad/blockview/plugin/blockviewplugin.h b/qad/blockview/plugin/blockviewplugin.h new file mode 100644 index 0000000..798c154 --- /dev/null +++ b/qad/blockview/plugin/blockviewplugin.h @@ -0,0 +1,31 @@ +#ifndef BLOCKVIEWPLUGIN_H +#define BLOCKVIEWPLUGIN_H + +#include + +class BlockViewPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + BlockViewPlugin(QObject * parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget * createWidget(QWidget * parent); + void initialize(QDesignerFormEditorInterface * core); + +private: + bool m_initialized; + +}; + +#endif // BLOCKVIEWPLUGIN_H diff --git a/qad/blockview/plugin/qad_blockview.cpp b/qad/blockview/plugin/qad_blockview.cpp new file mode 100644 index 0000000..b479558 --- /dev/null +++ b/qad/blockview/plugin/qad_blockview.cpp @@ -0,0 +1,14 @@ +#include "blockviewplugin.h" +#include "qad_blockview.h" + +QADBlockView::QADBlockView(QObject * parent): QObject(parent) +{ + m_widgets.append(new BlockViewPlugin(this)); +} + + +QList QADBlockView::customWidgets() const { + return m_widgets; +} + +Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADBlockView) diff --git a/qad/blockview/plugin/qad_blockview.h b/qad/blockview/plugin/qad_blockview.h new file mode 100644 index 0000000..5063596 --- /dev/null +++ b/qad/blockview/plugin/qad_blockview.h @@ -0,0 +1,21 @@ +#ifndef QAD_BLOCKVIEW_H +#define QAD_BLOCKVIEW_H + +#include +#include + +class QADBlockView: public QObject, public QDesignerCustomWidgetCollectionInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) + +public: + explicit QADBlockView(QObject * parent = 0); + virtual QList customWidgets() const; + +private: + QList m_widgets; + +}; + +#endif // QAD_BLOCKVIEW_H diff --git a/qad/blockview/qad_blockview.qrc b/qad/blockview/qad_blockview.qrc new file mode 100644 index 0000000..8a1aa10 --- /dev/null +++ b/qad/blockview/qad_blockview.qrc @@ -0,0 +1,53 @@ + + + lang/qad_blockview_ru.qm + ../icons/draw-line.png + ../icons/align-hor.png + ../icons/align-ver.png + ../icons/dialog-close.png + ../icons/edit-clear.png + ../icons/edit-guides.png + ../icons/view-grid.png + ../icons/zoom-fit-best.png + ../icons/configure.png + ../icons/document-save.png + ../icons/edit-clear-locationbar-rtl.png + ../icons/edit-find.png + ../icons/list-add.png + ../icons/edit-delete.png + ../icons/item.png + ../icons/node-add.png + ../icons/node.png + ../icons/edit-copy.png + ../icons/edit-paste.png + ../icons/expand_s_x.png + ../icons/expand_s_y.png + ../icons/expand_x.png + ../icons/expand_y.png + ../icons/border-line.png + ../icons/legend.png + ../icons/blockview.png + ../icons/view-fullscreen.png + ../icons/draw-ellipse.png + ../icons/draw-rectangle.png + ../icons/draw-text.png + ../icons/view-preview.png + ../icons/format-fill-color.png + ../icons/format-stroke-color.png + ../icons/document-open.png + ../icons/document-edit-.png + ../icons/align-bottom-center.png + ../icons/align-bottom-left.png + ../icons/align-bottom-right.png + ../icons/align-center-center.png + ../icons/align-center-left.png + ../icons/align-center-right.png + ../icons/align-top-center.png + ../icons/align-top-left.png + ../icons/align-top-right.png + ../icons/z-bottom.png + ../icons/z-down.png + ../icons/z-top.png + ../icons/z-up.png + + diff --git a/qad/graphic/CMakeLists.txt b/qad/graphic/CMakeLists.txt new file mode 100644 index 0000000..2fcdf87 --- /dev/null +++ b/qad/graphic/CMakeLists.txt @@ -0,0 +1,2 @@ +set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} qad_widgets qad_utils) +qad_project(graphic "${LIBS}") diff --git a/qad/graphic/graphic.cpp b/qad/graphic/graphic.cpp new file mode 100644 index 0000000..29318f0 --- /dev/null +++ b/qad/graphic/graphic.cpp @@ -0,0 +1,1522 @@ +#include "graphic.h" +#include "ui_graphic.h" +#include "ui_graphic_conf.h" + + +__GraphicRegistrator__ __graphic_registrator__; + + +ELineEdit::ELineEdit(QWidget * parent): CLineEdit(parent) { + last_ret = complexd_0; + is_auto = false; + is_reset = true; + connect(this, SIGNAL(editingFinished()), this, SLOT(calculate())); + connect(this, SIGNAL(cleared()), this, SLOT(toDefaultClicked())); +} + + +void ELineEdit::wheelEvent(QWheelEvent * e) { + double mul = 1.1; + if (e->delta() < 0) mul = 0.9; + CLineEdit::setText(QString::number(last_ret.real() * mul).toUpper()); + calculate(); +} + + +void ELineEdit::calculate() { + evaluator.check(text().replace(",", ".")); + if (!evaluator.isCorrect()) return; + is_reset = false; + last_ret = evaluator.evaluate(); + CLineEdit::setText(QString::number(last_ret.real()).toUpper()); + emit valueChanged(last_ret.real()); +} + + + +Graphic::Graphic(QWidget * parent): QFrame(parent), line_x_min(this), line_x_max(this), line_y_min(this), line_y_max(this) { + QTranslator * trans = new QTranslator(); + trans->load(":/lang/qad_graphic_" + QLocale::system().name().left(2)); + if (trans->isEmpty()) + trans->load("lang/qad_graphic_" + QLocale::system().name().left(2)); + qApp->installTranslator(trans); + leg_update = true; + visible_update = fullscr = false; + ui = new Ui::Graphic(); + ui->setupUi(this); + /*line_x_min.resize(70, 22); + line_x_max.resize(70, 22); + line_y_min.resize(70, 22); + line_y_max.resize(70, 22);*/ + line_x_min.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + line_x_max.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + ((QBoxLayout * )ui->widgetLY->layout())->insertWidget(0, &line_y_min); + ((QBoxLayout * )ui->widgetLY->layout())->addWidget(&line_y_max); + ((QBoxLayout * )ui->widgetLX->layout())->insertWidget(0, &line_x_min); + ((QBoxLayout * )ui->widgetLX->layout())->addWidget(&line_x_max); + tm.restart(); + grid_numbers_x = grid_numbers_y = 1; + LN2 = qLn(2.); + LN5 = qLn(5.); + LN10 = qLn(10.); + connect(&line_x_min, SIGNAL(valueChanged(double)), this, SLOT(lineXMinChanged(double))); + connect(&line_x_max, SIGNAL(valueChanged(double)), this, SLOT(lineXMaxChanged(double))); + connect(&line_y_min, SIGNAL(valueChanged(double)), this, SLOT(lineYMinChanged(double))); + connect(&line_y_max, SIGNAL(valueChanged(double)), this, SLOT(lineYMaxChanged(double))); + connect(ui->canvas_raster, SIGNAL(paintEvent(QPaintEvent * )), this, SLOT(canvasPaintEvent(QPaintEvent * ))); + connect(ui->canvas_raster, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * ))); + connect(ui->canvas_raster, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * ))); + connect(ui->canvas_raster, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * ))); + connect(ui->canvas_raster, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * ))); + connect(ui->canvas_raster, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * ))); + connect(ui->canvas_raster, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * ))); + connect(ui->canvas_raster, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * ))); + connect(ui->canvas_gl, SIGNAL(paintEvent(QPaintEvent * )), this, SLOT(canvasPaintEvent(QPaintEvent * ))); + connect(ui->canvas_gl, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * ))); + connect(ui->canvas_gl, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * ))); + connect(ui->canvas_gl, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * ))); + connect(ui->canvas_gl, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * ))); + connect(ui->canvas_gl, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * ))); + connect(ui->canvas_gl, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * ))); + connect(ui->canvas_gl, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * ))); + ui->canvas_raster->grabGesture(Qt::PinchGesture); + ui->canvas_raster->grabGesture(Qt::PanGesture); + ui->canvas_raster->installEventFilter(this); + ui->canvas_gl->grabGesture(Qt::PinchGesture); + ui->canvas_gl->grabGesture(Qt::PanGesture); + ui->canvas_gl->installEventFilter(this); + icon_exp_x = QIcon(":/icons/expand_x.png"); + icon_exp_y = QIcon(":/icons/expand_y.png"); + icon_exp_sx = QIcon(":/icons/expand_s_x.png"); + icon_exp_sy = QIcon(":/icons/expand_s_y.png"); + icon_pause_b = QImage(":/icons/pause-back.png"); + icon_pause_f = QImage(":/icons/pause-front.png"); + aupdate = grid = isFit = isEmpty = navigation = true; + aalias = mupdate = bufferActive = isOGL = cancel = isPrinting = guides = hasLblX = hasLblY = isHover = false; + pause_ = only_expand_x = only_expand_y = false; + //qDebug() << -DBL_MAX/2. << DBL_MAX/2. << DBL_MIN; + limit_.setCoords(-DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX); + eminx = eminy = DBL_MAX; + emaxx = emaxy = DBL_MIN; + grad_x = grad_y = Auto; + axis_type_x = Numeric; + min_repaint_int = 25; + inc_x = 1.; + legy = 0; + buffer = 0; + gridx = gridy = 1.; + history = 5.; + min_int = 1; + max_int = 200; + mdm = 10.; + visible_time = -1.; + pause_phase = 0.; + selrect.setRect(0., 0., 1., 1.); + def_rect = selrect; + margins_.setRect(4, 4, 4, 4); + curaction = gaMove; + selbrush.setStyle(Qt::SolidPattern); + selbrush.setColor(QColor(60, 175, 255, 100)); + text_color = Qt::black; + grid_pen = QPen(Qt::gray, 0., Qt::DotLine); + //graph_pen = QPen(Qt::red); + //graph_pen.setCosmetic(true); + graphics.append(GraphicType()); + curGraphic = 0; + selpen = QPen(Qt::black); + selpen.setStyle(Qt::DashLine); + back_color = Qt::white; + buttons_ = AllButtons; + setButtonsPosition(Graphic::Left); + setOpenGL(false); + setAntialiasing(false); + setCaption(""); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + ui->layoutButtons->update(); + updateLegend(); + setRectToLines(); + conf = new GraphicConf(graphics, this); +} + + +Graphic::~Graphic() { + delete conf; + if (buffer != 0) delete buffer; +} + + +void Graphic::changeEvent(QEvent * e) { + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + return; + } + QFrame::changeEvent(e); +} + + +void Graphic::timerEvent(QTimerEvent * ) { + pause_phase += 0.02; + if (pause_phase > 1.) + pause_phase -= 1.; + update(); +} + + +bool Graphic::eventFilter(QObject * o, QEvent * e) { + //qDebug() << "event" << o << e; + if (o == canvas) { + switch (e->type()) { + case QEvent::Gesture: + foreach (QGesture * g, ((QGestureEvent*)e)->gestures()) + procGesture(g); + break; + default: break; + } + } + return QFrame::eventFilter(o, e); +} + + +void Graphic::procGesture(QGesture * g) { + if (!g) return; + qDebug() << g; +} + + +void Graphic::canvasPaintEvent(QPaintEvent * ) { + if (is_lines_update) return; + QMutexLocker ml(&mutex_); + //static int pwid = 0, phei = 0; + int wid = canvas->width(), hei = canvas->height(); + lastw = wid; + lasth = hei; + font_sz = fontMetrics().size(0, "0"); + font_sz.setHeight(font_sz.height() * 1.); + font_sz.setWidth(font_sz.width() * 8); + thick = qMax(qRound(font_sz.height() / 15.), 1); + if (buffer != 0) if (buffer->width() != wid || buffer->height() != hei) {delete buffer; buffer = 0;} + if (buffer == 0) buffer = new QImage(wid, hei, QImage::Format_RGB32); + if (bufferActive) { + QPainter p(canvas); + p.drawImage(0, 0, *buffer); + painter = &p; + if (curpos != startpos) drawAction(); + drawGuides(); + return; + } + //if (!aupdate && !mupdate && pwid == wid && phei == hei) return; + /*if (pwid != wid || phei != hei) { + line_x_min.move(0, hei - 35); + line_x_max.move(0, 0); + line_y_min.move(70, hei - line_x_min.height()); + line_y_max.move(wid - line_y_max.width(), hei - line_x_min.height()); + } + line_x_min.setVisible(grid); + line_x_max.setVisible(grid); + line_y_min.setVisible(grid); + line_y_max.setVisible(grid);*/ + //pwid = wid; + //phei = hei; + QPainter p; + if (isOGL) { + glClearColor(0.f, 0.f, 0.f, 0.f); + p.begin(canvas); + } else p.begin(buffer); + p.fillRect(canvas->rect(), back_color); + painter = &p; + p.setFont(font()); + gridborder = QPoint(5, 5); + if (grid) { + gridborder += QPoint(font_sz.width(), font_sz.height()); + if (hasLblY) gridborder += QPoint(font_sz.height(), 0); + if (hasLblX) gridborder += QPoint(0, font_sz.height()); + drawGrid(); + } + p.setRenderHint(QPainter::Antialiasing, aalias); + if (isOGL) { + if (aalias) glEnable(GL_MULTISAMPLE); + else glDisable(GL_MULTISAMPLE); + } + //p.setRenderHint(QPainter::HighQualityAntialiasing, aalias); + if (!aalias) p.translate(-0.5, -0.5); + drawGraphics(); + drawGuides(); + if (pause_) drawPause(); + emit graphicPaintEvent(&p); + p.end(); + if (isOGL) return; + p.begin(canvas); + p.drawImage(0, 0, *buffer); + p.end(); +} + + +void Graphic::canvasMouseMoveEvent(QMouseEvent * e) { + isHover = true; + curpos = e->pos(); + QPointF rp = canvas2real(QPointF(e->pos())), srp = canvas2real(startpos), crp = canvas2real(curpos), dp; + QString cursorstr = tr("Cursor: ") + pointCoords(rp); + emit graphicMouseMoveEvent(rp, e->buttons()); + if (e->buttons() == Qt::NoButton) { + ui->status->setText(cursorstr); + if (guides) update(); + return; + } + if (!navigation) return; + if (curaction != gaMove && (e->buttons() & Qt::RightButton) == Qt::RightButton) return; + switch (curaction) { + case gaZoomInRect: + ui->status->setText(tr("Selection") + ": " + pointCoords(srp) + " -> " + + pointCoords(crp) + ", " + tr("Size") + ": " + pointCoords(absPoint(crp - srp))); + repaintCanvas(true); + break; + case gaZoomRangeX: + ui->status->setText(tr("Range") + ": " + QString::number(srp.x(), 'f', 3) + + " -> " + QString::number(crp.x(), 'f', 3) + ", " + tr("Length") + ": " + + QString::number(qAbs(crp.x() - srp.x()), 'f', 3)); + repaintCanvas(true); + break; + case gaZoomRangeY: + ui->status->setText(tr("Range") + ": " + QString::number(srp.y(), 'f', 3) + + " -> " + QString::number(crp.y(), 'f', 3) + ", " + tr("Length") + ": " + + QString::number(qAbs(crp.y() - srp.y()), 'f', 3)); + repaintCanvas(true); + break; + case gaMove: + dp = e->pos() - prevpos; + dp.rx() *= selrect.width() / double(gridborder.x() + 5 - lastw); + dp.ry() *= selrect.height() / double(lasth - legy - gridborder.y() - 5); + selrect.translate(dp); + isFit = false; + emit visualRectChanged(); + update(true); + setRectToLines(); + break; + default: break; + } + prevpos = e->pos(); +} + + +void Graphic::canvasMousePressEvent(QMouseEvent * e) { + emit graphicMousePressEvent(canvas2real(QPointF(e->pos())), e->buttons()); + if (!navigation) return; + ui->canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor); + ui->canvas_raster->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor); + prevpos = e->pos(); + startpos = prevpos; + if (cancel) return; + if (e->button() == Qt::MidButton) curaction = gaMove; + if (e->button() == Qt::RightButton) { + if (bufferActive) { + curpos = startpos; + repaintCanvas(true); + swapToNormal(); + cancel = true; + return; + } else { + prevaction = curaction; + curaction = gaMove; + return; + } + } + if (e->button() == Qt::LeftButton) { + if (e->modifiers() == Qt::ControlModifier) curaction = gaZoomRangeX; + else if (e->modifiers() == Qt::ShiftModifier) curaction = gaZoomRangeY; + else curaction = gaZoomInRect; + switch (curaction) { + case gaZoomInRect: + case gaZoomRangeX: + case gaZoomRangeY: + swapToBuffer(); + break; + default: break; + } + } + setCurrentAction(curaction); +} + + +void Graphic::canvasMouseReleaseEvent(QMouseEvent * e) { + emit graphicMouseReleaseEvent(canvas2real(QPointF(e->pos())), e->buttons()); + if (!navigation) return; + ui->canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor); + ui->canvas_raster->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor); + QPointF tlp, brp; + QRect sr; + sr = QRect(startpos, curpos).normalized(); + if (cancel) { + if (e->buttons() == Qt::NoButton) cancel = false; + return; + } + if (e->button() == Qt::RightButton && curaction == gaMove) { + curaction = prevaction; + return; + } + if (e->button() == Qt::LeftButton && (e->buttons() & Qt::RightButton) != Qt::RightButton) { + if (curpos != startpos) { + tlp = canvas2real(sr.topLeft()); + brp = canvas2real(sr.bottomRight()); + isFit = false; + switch (curaction) { + case gaZoomInRect: + if (sr.width() <= 1 || sr.height() <= 1) break; + selrect.setCoords(tlp.x(), brp.y(), brp.x(), tlp.y()); + setRectToLines(); + break; + case gaZoomRangeX: + if (sr.width() <= 1) break; + findGraphicsRect(tlp.x(), brp.x()); + break; + case gaZoomRangeY: + if (sr.height() <= 1) break; + findGraphicsRect(0., 0., brp.y(), tlp.y()); + break; + default: return; + } + } + swapToNormal(); + update(true); + } + QPointF rp = canvas2real(QPointF(e->pos())); + ui->status->setText(tr("Cursor") + ": " + pointCoords(rp)); + emit visualRectChanged(); +} + + +void Graphic::canvasMouseDoubleClickEvent(QMouseEvent * ) { + autofit(); +} + + +void Graphic::canvasWheelEvent(QWheelEvent * e) { + //if (curaction != gaMove) return; + emit graphicWheelEvent(canvas2real(QPointF(e->pos())), e->delta()); + if (!navigation) return; + double scl, wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top(); + double px = e->pos().x() - gridborder.x() - margins_.left(), py = hei - e->pos().y() + margins_.height(); + px = px / wid * selrect.width() + selrect.x(); + py = py / hei * selrect.height() + selrect.y(); + if (e->delta() > 0) scl = 1. / 1.2; + else scl = 1.2; + if (e->modifiers() == Qt::NoModifier) + selrect.setRect(px - (px - selrect.x()) * scl, py - (py - selrect.y()) * scl, selrect.width() * scl, selrect.height() * scl); + else { + if (e->modifiers() == Qt::ControlModifier) + selrect.setRect(px - (px - selrect.x()) * scl, selrect.y(), selrect.width() * scl, selrect.height()); + if (e->modifiers() == Qt::ShiftModifier) + selrect.setRect(selrect.x(), py - (py - selrect.y()) * scl, selrect.width(), selrect.height() * scl); + } + isFit = false; + update(true); + setRectToLines(); + emit visualRectChanged(); +} + + +void Graphic::zoom(float factor) { + double wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top(); + double px = wid / 2, py = hei / 2; + px = px / wid * selrect.width() + selrect.x(); + py = py / hei * selrect.height() + selrect.y(); + selrect.setRect(px - (px - selrect.x()) * factor, py - (py - selrect.y()) * factor, selrect.width() * factor, selrect.height() * factor); + isFit = false; + update(true); + setRectToLines(); +} + + +void Graphic::fullscreen() { + if (fullscr) leaveFullscreen(); + else enterFullscreen(); +} + + +void Graphic::canvasLeaveEvent(QEvent * ) { + isHover = false; + if (guides) update(true); + ui->status->setText(tr("Cursor") + ": ( ; )"); + leaveFullscreen(); +} + + +void Graphic::canvasKeyPressEvent(QKeyEvent * e) { + switch (e->key()) { + case Qt::Key_Escape: leaveFullscreen(); + default: break; + }; +} + + +void Graphic::clear() { + //cout << "clear" << endl; + for (int i = 0; i < graphics.size(); ++i) { + graphics[i].polyline.clear(); + graphics[i].polyline_pause.clear(); + graphics[i].max_x = 0.; + } + on_buttonAutofit_clicked(); +} + + +void Graphic::setAntialiasing(bool enabled) { + if (aalias == enabled) return; + aalias = enabled; + /*QGLFormat f = ui->canvas_gl->format(); + f.setSampleBuffers(enabled); + ui->canvas_gl->setFormat(f);*/ + update(); +} + + +void Graphic::setPaused(bool yes) { + pause_ = yes; + ui->checkPause->blockSignals(true); + ui->checkPause->setChecked(yes); + ui->checkPause->blockSignals(false); + if (!pause_) { + killTimer(timer_pause); + timer_pause = 0; + update(true); + return; + } + for (int i = 0; i < graphics.size(); ++i) { + graphics[i].polyline_pause = graphics[i].polyline; + graphics[i].polyline_pause.detach(); + graphics[i].max_x_pause = graphics[i].max_x; + } + timer_pause = startTimer(40); +} + + +void Graphic::setHistorySize(double val) { + history = val; + double x; + for (int i = 0; i < graphics.size(); ++i) { + QPolygonF & pol(graphics[i].polyline); + if (pol.isEmpty() || history <= 0.) continue; + x = pol.back().x() - history; + for (int j = pol.size() - 2; j >= 0 ; --j) + if (pol[j].x() < x) { + //qDebug() << pol.size() << j; + pol.erase(pol.begin(), pol.begin() + j); + break; + } + } +} + + +void Graphic::setOnlyExpandY(bool yes) { + only_expand_y = yes; + ui->checkExpandY->blockSignals(true); + ui->checkExpandY->setCheckable(yes); + ui->checkExpandY->blockSignals(false); +} + + +void Graphic::setOnlyExpandX(bool yes) { + only_expand_x = yes; + ui->checkExpandX->blockSignals(true); + ui->checkExpandX->setCheckable(yes); + ui->checkExpandX->blockSignals(false); +} + + +Graphic::GraphicsData Graphic::graphicsData() const { + GraphicsData ret; + ret.resize(graphics.size()); + for (int i = 0; i < graphics.size(); ++i) + ret[i] = graphics[i].polyline; + return ret; +} + + +void Graphic::setGraphicsData(const Graphic::GraphicsData & gd) { + setGraphicsCount(gd.size()); + for (int i = 0; i < gd.size(); ++i) + setGraphicData(gd[i], i, false); + updateGraphics(); +} + + +void Graphic::setButtons(Graphic::Buttons b) { + buttons_ = b; + ui->buttonAutofit->setVisible(b.testFlag(Autofit)); + ui->checkGrid->setVisible(b.testFlag(Grid)); + ui->checkGuides->setVisible(b.testFlag(CursorAxis)); + ui->checkExpandY->setVisible(b.testFlag(OnlyExpandY)); + ui->checkExpandX->setVisible(b.testFlag(OnlyExpandX)); + ui->buttonFullscreen->setVisible(b.testFlag(Fullscreen)); + ui->checkBorderInputs->setVisible(b.testFlag(BorderInputs)); + ui->checkLegend->setVisible(b.testFlag(Legend)); + ui->buttonClear->setVisible(b.testFlag(Clear)); + ui->buttonConfigure->setVisible(b.testFlag(Configure)); + ui->buttonSave->setVisible(b.testFlag(Save)); + ui->buttonClose->setVisible(b.testFlag(Close)); + ui->checkPause->setVisible(b.testFlag(Pause)); + if (ui->buttonAutofit->isVisible() || ui->checkGrid->isVisible() || ui->checkGuides->isVisible() || + ui->buttonConfigure->isVisible() || ui->buttonSave->isVisible() || ui->checkPause->isVisible()) + ui->verticalSpacer->changeSize(0, 30, QSizePolicy::Preferred, QSizePolicy::Preferred); + else + ui->verticalSpacer->changeSize(0, 0, QSizePolicy::Preferred, QSizePolicy::Preferred); + ui->layoutButtons->update(); +} + + +void Graphic::setButtonsPosition(Graphic::Alignment a) { + align = a; + ui->widgetLeft->hide(); + ui->widgetRight->hide(); + switch (a) { + case Graphic::Left: + ui->widgetLeft->setLayout(ui->layoutButtons); + ui->widgetLeft->show(); + break; + case Graphic::Right: + ui->widgetRight->setLayout(ui->layoutButtons); + ui->widgetRight->show(); + break; + } +} + + +void Graphic::addPoint(const QPointF & p, int graphic, bool update_) { + if (graphic >= graphics.size() || graphic < 0) return; + if (graphics.at(graphic).polyline.size() == 0) graphics[graphic].max_x = p.x(); + graphics[graphic].polyline << p; + if (graphics.at(graphic).max_x < p.x()) graphics[graphic].max_x = p.x(); + tick(graphic, true, update_); +} + + +void Graphic::setGraphicData(const QVector & g, int graphic, bool update_) { + if (graphic >= graphics.size() || graphic < 0) return; + graphics[graphic].polyline.clear(); + graphics[graphic].polyline = g; + if (graphics.at(graphic).polyline.size() == 0) { + graphics[graphic].max_x = 0.; + tick(graphic, false, update_); + return; + } + graphics[graphic].max_x = graphics.at(graphic).polyline[0].x(); + for (int i = 1; i < graphics.at(graphic).polyline.size(); ++i) + if (graphics.at(graphic).max_x < graphics.at(graphic).polyline[i].x()) + graphics[graphic].max_x = graphics.at(graphic).polyline[i].x(); + tick(graphic, false, update_); +} + + +void Graphic::setGraphicProperties(int graphic, const QString & name, const QColor& color, Qt::PenStyle style, double width, bool visible) { + if (graphic < 0 || graphic >= graphics.size()) return; + graphics[graphic].name = name; + graphics[graphic].pen.setColor(color); + graphics[graphic].pen.setStyle(style); + graphics[graphic].pen.setWidth(width); + graphics[graphic].visible = visible; + updateLegend(); +} + + +void Graphic::addGraphic(const QString & name, const QColor & color, Qt::PenStyle style, double width, bool visible) { + graphics << GraphicType(name, color, style, width, visible); + updateLegend(); +} + + +void Graphic::setVisualRect(const QRectF & rect) { + selrect = rect; + isFit = false; + update(); +} + + +void Graphic::setDefaultRect(const QRectF & rect) { + def_rect = rect; + if (isFit) autofit(); +} + + +void Graphic::saveImage() { + QString str = QFileDialog::getSaveFileName(this, tr("Save Image"), ppath, "PNG(*.png);;JPEG(*.jpg *.jpeg);;BMP(*.bmp);;TIFF(*.tiff *.tif);;PPM(*.ppm)"); + if (str == "") return; + ppath = str; + QPixmap im(canvas->size()); + mupdate = true; + canvas->render(&im); + mupdate = false; + im.save(ppath); + update(true); +} + + +void Graphic::setOpenGL(bool on) { + isOGL = on; + if (on) { + ui->canvas_raster->hide(); + ui->canvas_gl->show(); + canvas = ui->canvas_gl; + } else { + ui->canvas_gl->hide(); + ui->canvas_raster->show(); + canvas = ui->canvas_raster; + } + /*line_x_min.setParent(canvas); + line_x_max.setParent(canvas); + line_y_min.setParent(canvas); + line_y_max.setParent(canvas); + line_x_min.show(); + line_x_max.show(); + line_y_min.show(); + line_y_max.show();*/ + update(); +} + + +void Graphic::update(bool force) { + mupdate = true; + repaintCanvas(force); + mupdate = false; +} + + +void Graphic::setGraphicsCount(int arg, bool update) { + if (arg < 0) return; + while (graphics.size() < arg) + graphics.append(GraphicType(tr("y(x)"), QColor::fromHsv((graphics.size() * 55) % 360, 255, 255 - qrand() % 115))); + while (graphics.size() > arg) { + delete graphics.back().pb; + graphics.pop_back(); + } + if (update) updateLegend(); +} + + +void Graphic::setHistogramData(const QVector & g, int graphic) { + graphics[graphic].polyline.clear(); + if (g.isEmpty()) { + return; + } + QVector data = g; + QVector hist; + int ic = max_int, ci; + double md, cd, min, max, range, cx; + qSort(data); + md = DBL_MAX; + min = max = data[0]; + for (int i = 1; i < data.size(); ++i) { + if (min > data[i]) min = data[i]; + if (max < data[i]) max = data[i]; + cd = qAbs(data[i] - data[i - 1]); + if (md > cd && cd != 0.) md = cd; + } + range = max - min; + md = mdm; + //qDebug() << md << range << ic; + if (md != 0.) + ic = qRound(qMax(qMin(double(ic), range / md), double(min_int))); + md = range / ic; + hist.resize(ic); + foreach (const float & i, data) { + ci = qRound((i - min) / range * double(ic - 1)); + //if (ci < 0) ci = 0; + //if (ci >= ic) ci = ic - 1; + hist[ci]++; + } + QPolygonF & cpol(graphics[graphic].polyline); + if (hist.size() == 1 || range == 0.) { + cpol << QPointF(min - 0.5, 0.) << QPointF(min - 0.25, 0.); + cpol << QPointF(min - 0.25, hist[0]) << QPointF(min + 0.25, hist[0]); + cpol << QPointF(min + 0.25, 0.) << QPointF(min + 0.5, 0.); + } else { + cpol << QPointF(min, 0.); + for (int i = 0; i < hist.size(); ++i) { + cx = i * range / ic + min; + cpol << QPointF(cx, hist[i]) << QPointF(cx + md, hist[i]); + } + cpol << QPointF(range + min, 0.); + } + updateGraphics(); +} + + +void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, double end_y) { + double cx, cy, maxX, minX, maxY, minY, vx = DBL_MIN; + bool isRangeX = (start_x != end_x), isRangeY = (start_y != end_y); + bool isEmpty = true, anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY); + foreach (const GraphicType & t, graphics) { + const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline); + if (!pol.isEmpty()) { + isEmpty = false; + break; + } + } + if (isEmpty) { + grect = def_rect; + setRectToLines(); + return; + } + minY = minX = DBL_MAX; + maxY = maxX = -DBL_MAX; + foreach (const GraphicType & t, graphics) { + if (!t.visible) continue; + if (vx < (pause_ ? t.max_x_pause : t.max_x)) vx = (pause_ ? t.max_x_pause : t.max_x); + } + vx -= visible_time; + foreach (const GraphicType & t, graphics) { + if (!t.visible) continue; + const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline); + for (int i = 0; i < pol.size(); i++) { + cx = pol[i].x(); + cy = pol[i].y(); + if ((start_x > cx || end_x < cx) && isRangeX) continue; + if ((start_y > cy || end_y < cy) && isRangeY) continue; + if ((cx < vx) && isTimeLimit) continue; + if (maxY < cy) maxY = cy; + if (minY > cy) minY = cy; + if (maxX < cx) maxX = cx; + if (minX > cx) minX = cx; + } + if (!pol.isEmpty()) anyVisible = true; + } + if (!anyVisible) { + grect.setRect(0., 0., 1., 1.); + setRectToLines(); + return; + } + if (maxX > limit_.right()) maxX = limit_.right(); + if (minX > limit_.right()) minX = limit_.right(); + if (minX < limit_.left()) minX = limit_.left(); + if (maxX < limit_.left()) maxX = limit_.left(); + if (maxY > limit_.bottom()) maxY = limit_.bottom(); + if (minY > limit_.bottom()) minY = limit_.bottom(); + if (minY < limit_.top()) minY = limit_.top(); + if (maxY < limit_.top()) maxY = limit_.top(); + if (minX > maxX) qSwap(minX, maxX); + if (minY > maxY) qSwap(minY, maxY); + if (qAbs(minX - maxX) < 1E-60) {minX -= 1E-20; maxX += 1E-20;} + if (qAbs(minY - maxY) < 1E-60) {minY -= 1E-20; maxY += 1E-20;} + if (only_expand_x) { + if (minX > eminx) minX = eminx; + if (maxX < emaxx) maxX = emaxx; + } + if (only_expand_y) { + if (minY > eminy) minY = eminy; + if (maxY < emaxy) maxY = emaxy; + } + eminx = minX; emaxx = maxX; + eminy = minY; emaxy = maxY; + if (isRangeX) selrect.setRect(start_x, minY, end_x - start_x, maxY - minY); + else if (isRangeY) selrect.setRect(minX, start_y, maxX - minX, end_y - start_y); + else grect.setRect(minX, minY, maxX - minX, maxY - minY); + grect = grect.normalized(); + if (isFit)/* || isRangeX || isRangeY)*/ selrect = grect; + setRectToLines(); +} + + +void Graphic::drawAction() { + //qDebug() << "draw action"; + int wid = canvas->width(), hei = canvas->height() - gridborder.y(), sx = startpos.x(), sy = startpos.y(), cx = curpos.x(), cy = curpos.y(); + painter->setPen(selpen); + painter->setBrush(selbrush); + switch (curaction) { + case gaZoomInRect: + painter->drawRect(QRect(startpos, curpos)); + break; + case gaZoomRangeX: + painter->drawLine(sx, hei, sx, 0); + painter->drawLine(cx, hei, cx, 0); + painter->fillRect(sx, 0, cx - sx, hei, selbrush); + break; + case gaZoomRangeY: + painter->drawLine(gridborder.x(), sy, wid, sy); + painter->drawLine(gridborder.x(), cy, wid, cy); + painter->fillRect(gridborder.x(), sy, wid - gridborder.x(), cy - sy, selbrush); + break; + default: break; + } +} + + +void Graphic::drawGrid() { + int gbx = gridborder.x(), gby = gridborder.y(), cwid = painter->viewport().width(), chei = painter->viewport().height() - legy; + double px, py, range, step, start; + int wid = cwid - gbx - 5, hei = chei - gby - 5, cx, cy, cnt; + QRect rect; + QPair str; + + range = selrect.bottom() - selrect.top(); + if (grad_y == Graphic::Auto) step = splitRange(range, hei / gridy / font_sz.height() / 1.4); + else step = gridy;//range / hei * gridy; + start = roundTo(canvas2realY(-hei), step) - step; + py = start + step; + cy = 0; + cx = gbx - 5; + grid_pen.setWidth(qMax(qRound(thick / 1.4), 1)); + QFont sf = font(); + QFont nf = sf; + sf.setPointSizeF(qMax(sf.pointSizeF() / 1.6, 7.)); + QFontMetrics fm(nf), sfm(sf); + if (step > 0.) { + cnt = 1000; + while (cnt-- > 0) { + py -= step; + if (fabs(py) < step * .5) py = 0.; + cy = real2canvasY(py); + if (cy < 0) continue; + if (cy > hei + 5) break; + painter->setPen(grid_pen); + painter->drawLine(gbx, cy, cwid, cy); + str = gridMark(py * grid_numbers_y); + painter->setPen(text_color); + cy += font_sz.height() / 4.; + int dx = font_sz.height() / 8.; + if (!str.second.isEmpty()) { + rect = sfm.boundingRect(str.second); + painter->setFont(sf); + painter->drawText(cx - rect.width() - dx, cy - font_sz.height() / 2.5, str.second); + dx += rect.width() + font_sz.height() / 6.; + } + rect = fm.boundingRect(str.first); + painter->setFont(nf); + painter->drawText(cx - rect.width() - dx, cy, str.first); + } + } + cy = real2canvasY(0.); + if (cy >= 0 && cy <= (hei + 5)) { + QPen _p(grid_pen); + _p.setStyle(Qt::SolidLine); + painter->setPen(_p); + painter->drawLine(gbx, cy, cwid, cy); + } + if (hasLblY) { + painter->setPen(text_color); + painter->save(); + painter->translate(5, hei); + painter->rotate(-90.); + painter->drawText(0, 0, hei, font_sz.height(), Qt::AlignCenter, label_y); + painter->restore(); + } + + cy = chei - font_sz.height() / 4; + if (hasLblX) cy -= font_sz.height(); + range = selrect.right() - selrect.left(); + QString df; + if (axis_type_x == Graphic::Numeric) { + if (grad_x == Graphic::Auto) step = splitRange(range, wid / gridx / font_sz.width() * 1.4); + else step = gridx;//range / wid * gridx; + start = roundTo(canvas2realX(wid), step) + step; + px = start + step; + if (step > 0.) { + cnt = 1000; + while (cnt-- > 0) { + px -= step; + if (fabs(px) < step * .5) px = 0.; + cx = real2canvasX(px); + if (cx > cwid) continue; + if (cx < gbx) break; + painter->setPen(grid_pen); + painter->drawLine(cx, hei + 5, cx, 0); + painter->setPen(text_color); + int dx = -font_sz.height() / 4.; + painter->setFont(nf); + str = gridMark(px * grid_numbers_x); + rect = fm.boundingRect(str.first); + painter->drawText(cx + dx, cy, str.first); + dx += rect.width() + font_sz.height() / 6.; + if (!str.second.isEmpty()) { + rect = sfm.boundingRect(str.second); + painter->setFont(sf); + painter->drawText(cx + dx, cy - font_sz.height() / 2.5, str.second); + } + } + } + cx = real2canvasX(0.); + if (cx <= cwid && cx >= gbx) { + QPen _p(grid_pen); + _p.setStyle(Qt::SolidLine); + painter->setPen(_p); + painter->drawLine(cx, hei + 5, cx, 0); + } + } else { + int cur_scl[7] = {0,0,0,0,0,0,0}; + step = splitRangeDate(range, wid / gridx / font_sz.width() * 1.4, &df, cur_scl); + start = roundTo(canvas2realX(wid), step) + step; + px = start + step; + QDateTime cd = QDateTime::fromMSecsSinceEpoch(px * grid_numbers_x); + //qDebug() << "*** start" << cd << step; + roundDateTime(cd, cur_scl); + //qDebug() << "*** round" << cd; + addDateTime(cd, cur_scl); + //qDebug() << "*** add" << cd; + //qDebug() << "*** cur" << cur_scl[0] << cur_scl[1] << cur_scl[2] << cur_scl[3] << cur_scl[4] << cur_scl[5] << cur_scl[6]; + if (step > 0.) { + cnt = 1000; + while (cnt-- > 0) { + addDateTime(cd, cur_scl, -1); + //roundDateTime(cd, cur_scl); + //qDebug() << "next" << cd; + cx = real2canvasX(cd.toMSecsSinceEpoch() / grid_numbers_x); + if (cx > cwid) continue; + if (cx < gbx) {/*qDebug() << cx << "<" << gbx;*/ break;} + painter->setPen(grid_pen); + painter->drawLine(cx, hei + 5, cx, 0); + painter->setPen(text_color); + int dx = -font_sz.height() / 4.; + painter->setFont(nf); + str.first = cd.toString(df); + painter->drawText(cx + dx, cy, str.first); + } + } + } + painter->setPen(text_color); + painter->setFont(nf); + if (hasLblX) { + painter->setPen(text_color); + painter->drawText(gbx, chei - font_sz.height(), wid, font_sz.height(), Qt::AlignCenter, label_x); + } + + painter->setPen(QPen(grid_pen.color(), thick)); + painter->drawRect(gbx, -1, wid + 6, hei + 6); +} + + +QPair Graphic::gridMark(double v) const { + QPair ret; + if ((qAbs(v) >= 1E+4 || qAbs(v) <= 1E-4) && v != 0.) { + int p = qFloor(qLn(qAbs(v)) / LN10); + v /= qPow(10., p); + if (v == 10.) { + v = 1.; + p += 1; + } + ret.first = QString::fromUtf8("%1·10").arg(v); + ret.second = QString::number(p); + } else + ret.first = QString::number(v); + return ret; +} + + +void Graphic::drawGraphics() { + if (isHover) + ui->status->setText(tr("Cursor: ") + pointCoords(canvas2real(QPointF(curpos)))); + QPointF srp = -selrect.topLeft(), cp; + double sclx, scly, wid = painter->viewport().width(), hei = painter->viewport().height() - legy, pw; + sclx = (wid - gridborder.x() - margins_.left() - margins_.width()) / selrect.width(); + scly = (hei - gridborder.y() - margins_.top() - margins_.height()) / selrect.height(); + painter->setClipping(true); + painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y())); + painter->translate(gridborder.x() + margins_.left(), hei - gridborder.y() - margins_.top()); + //if (isOGL && aalias) pen.setWidthF(1.5f); + painter->scale(sclx, -scly); + painter->translate(srp); + QTransform mat = painter->transform(); + painter->resetTransform(); + painter->setWorldMatrixEnabled(false); + QPolygonF cpol; + for (int i = 0; i < graphics.size(); ++i) { + GraphicType & t(graphics[i]); + QPolygonF & rpol(pause_ ? t.polyline_pause : t.polyline); + if (t.visible && !rpol.isEmpty()) { + pw = t.pen.widthF(); + if (t.lines) { + t.pen.setCosmetic(true); + painter->setPen(t.pen); + if (t.fill) { + cpol = rpol; + painter->setBrush(t.fill_color); + //cpol.push_front(QPointF(cpol.front().x(), 0.)); + //cpol.push_back(QPointF(cpol.back().x(), 0.)); + painter->drawPolygon(mat.map(cpol)); + } else + painter->drawPolyline(mat.map(rpol)); + } + if (t.points) { + if (qRound(t.pointWidth) == t.pointWidth) t.pen.setWidth(qRound(t.pointWidth)); + else t.pen.setWidthF(t.pointWidth); + t.pen.setCosmetic(true); + painter->setPen(t.pen); + painter->drawPoints(mat.map(rpol)); + if (qRound(pw) == pw) t.pen.setWidth(qRound(pw)); + else t.pen.setWidthF(pw); + } + } + } + painter->setWorldMatrixEnabled(true); +} + + +QString Graphic::pointCoords(QPointF point) { + if (axis_type_x == Numeric) + return "(" + QString::number(point.x(), 'f', 3) + " ; " + QString::number(point.y(), 'f', 3) + ")"; + return "(" + QDateTime::fromMSecsSinceEpoch(point.x()).toString() + " ; " + QString::number(point.y(), 'f', 3) + ")"; +} + + +void Graphic::drawGuides() { + if (!guides || !isHover) return; + int wid = canvas->width(), hei = canvas->height(); + painter->setRenderHint(QPainter::Antialiasing, false); + painter->setPen(QPen(grid_pen.color(), qMax(qRound(thick / 1.4), 1))); + painter->resetTransform(); + painter->setClipping(true); + painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y())); + painter->drawLine(0, curpos.y(), wid, curpos.y()); + painter->drawLine(curpos.x(), 0, curpos.x(), hei); + QString str = pointCoords(canvas2real(curpos)); + QFontMetrics fm(font()); + QRect r = fm.boundingRect(str); + QPoint p = curpos + QPoint(font_sz.height() / 4., -font_sz.height() / 4.); + if (r.width() + curpos.x() > wid - font_sz.height() / 2.) p.setX(curpos.x() - r.width() - font_sz.height() / 4.); + if (curpos.y() - r.height() < font_sz.height() / 8.) p.setY(curpos.y() + r.height() - font_sz.height() / 8.); + painter->setPen(text_color); + painter->drawText(p, str); +} + + +void Graphic::drawPause() { + painter->setClipping(false); + painter->save(); + painter->resetMatrix(); + painter->translate(canvas->width() - icon_pause_b.width() - 6, 6); + double o = (0.5 - pause_phase) * 2; + painter->setOpacity(o*o); + painter->drawImage(0, 0, icon_pause_b); + painter->setOpacity(1.); + painter->drawImage(0, 0, icon_pause_f); + painter->restore(); + painter->setClipping(true); +} + + +double Graphic::splitRange(double range, int count) { + double digits, step, tln; + range = qAbs(range); + tln = qFloor(qLn(range) / LN10); + for (int i = 0; i <= 5; ++i) { + digits = qPow(10., tln - i); + step = qRound(range / count / digits); + if (step > 0.) { + digits = qPow(10., tln - i - 1); + step = qRound(range / count / digits); + break; + } + } + double step5 = qRound(step / 5.) * 5., step10 = qRound(step / 10.) * 10.; + double err5 = qAbs(step - step5), err10 = qAbs(step - step10); + step = (err5 < err10 ? step5 : step10) * digits; + return step; +} + + +double Graphic::splitRangeDate(double range, int count, QString * format, int step[7]) { + double ret = splitRange(range, count); + //qDebug() << "ret =" << ret << getScaleX(); + if (ret < 1000. * 1) {*format = "ss.zzz"; step[0] = ret;} + else if (ret < 1000. * 60) {*format = "h:m:ss"; step[1] = qRound(ret / 1000);} + else if (ret < 1000. * 60 * 60) {*format = "h:mm"; step[2] = qRound(ret / 1000 / 60);} + else if (ret < 1000. * 60 * 60 * 24) {*format = "dd(ddd) hh"; step[3] = qRound(ret / 1000 / 60 / 60);} + else if (ret < 1000. * 60 * 60 * 24 * 30) {*format = "MMM dd"; step[4] = qRound(ret / 1000 / 60 / 60 / 24);} + else if (ret < 1000. * 60 * 60 * 24 * 30 * 12) {*format = "yyyy MMM"; step[5] = qRound(ret / 1000 / 60 / 60 / 24 / 30);} + else {*format = "yyyy"; step[6] = qRound(ret / 1000 / 60 / 60 / 24 / 30 / 12);} + return ret; +} + + +double Graphic::roundTo(double value, double round_to) { + if (round_to == 0.) return value; + return qRound(value / round_to) * round_to; +} + + +void Graphic::roundDateTime(QDateTime & dt, int c[7]) { + QDate d(dt.date()); QTime t(dt.time()); + //if (c[0] != 0) t.setHMS(t.hour(), t.minute(), t.second(), 0); + if (c[1] != 0) t.setHMS(t.hour(), t.minute(), t.second()); + if (c[2] != 0) t.setHMS(t.hour(), t.minute(), 0); + if (c[3] != 0) t.setHMS(t.hour(), 0, 0); + if (c[4] != 0) {t.setHMS(0, 0, 0); d.setDate(d.year(), d.month(), d.day());} + if (c[5] != 0) {t.setHMS(0, 0, 0); d.setDate(d.year(), d.month(), 1);} + if (c[6] != 0) {t.setHMS(0, 0, 0); d.setDate(d.year(), 1, 1);} + dt = QDateTime(d, t); +} + + +void Graphic::addDateTime(QDateTime & dt, int c[7], int mul) { + if (c[0] != 0) dt = dt.addMSecs(mul * c[0]); + if (c[1] != 0) dt = dt.addSecs(mul * c[1]); + if (c[2] != 0) dt = dt.addSecs(mul * c[2] * 60); + if (c[3] != 0) dt = dt.addSecs(mul * c[3] * 60 * 60); + if (c[4] != 0) dt = dt.addDays(mul * c[4]); + if (c[5] != 0) dt = dt.addMonths(mul * c[5]); + if (c[6] != 0) dt = dt.addYears(mul * c[6]); +} + + +double Graphic::canvas2realX(double px) const { + int gbx = gridborder.x() + margins_.left(), cwid = lastw, wid = cwid - gbx - margins_.width(); + double cx = px - gbx, sclx = selrect.width() / (double)wid; + return cx * sclx + selrect.x(); +} + + +double Graphic::canvas2realY(double py) const { + int gby = gridborder.y() + margins_.top(), chei = lasth - legy, hei = chei - gby - margins_.height(); + double cy = chei - py - gby, scly = selrect.height() / (double)hei; + return cy * scly + selrect.y(); +} + + +double Graphic::real2canvasX(double px) const { + int gbx = gridborder.x() + margins_.left(), cwid = lastw, wid = cwid - gbx - margins_.width(); + double sclx = selrect.width() / (double)wid; + return (px - selrect.x()) / sclx + gbx; +} + + +double Graphic::real2canvasY(double py) const { + int gby = gridborder.y() + margins_.top(), chei = lasth - legy, hei = chei - gby - margins_.height(); + double scly = selrect.height() / (double)hei; + return chei - gby - (py - selrect.y()) / scly; +} + + +void Graphic::setCurrentAction(GraphicAction action) { + curaction = action; + switch (action) { + case gaNone: + if (guides) setCanvasCursor(Qt::BlankCursor); + else setCanvasCursor(Qt::ArrowCursor); + break; + case gaZoomInRect: + setCanvasCursor(Qt::CrossCursor); + break; + case gaZoomRangeX: + setCanvasCursor(Qt::SplitHCursor); + break; + case gaZoomRangeY: + setCanvasCursor(Qt::SplitVCursor); + break; + case gaMove: + setCanvasCursor(Qt::SizeAllCursor); + break; + } +} + + +void Graphic::setCanvasCursor(QCursor cursor) { + ui->canvas_raster->setCursor(cursor); + ui->canvas_gl->setCursor(cursor); +} + + +void Graphic::swapToBuffer() { + QImage timg; + //qDebug() << "render start"; + if (isOGL) { + timg = ui->canvas_gl->grabFrameBuffer(); + QPainter p(buffer); + p.drawImage(0, 0, timg); + p.end(); + } + //qDebug() << "render finish"; + bufferActive = true; +} + + +void Graphic::setRectToLines() { + is_lines_update = true; + line_x_min.is_auto = line_x_max.is_auto = line_y_min.is_auto = line_y_max.is_auto = true; + //qDebug() << "set to lines" << selrect; + line_x_min.is_reset = line_x_max.is_reset = line_y_min.is_reset = line_y_max.is_reset = isFit; + if (!line_x_min.hasFocus()) line_x_min.setValue(selrect.left()); + if (!line_x_max.hasFocus()) line_x_max.setValue(selrect.right()); + if (!line_y_min.hasFocus()) line_y_min.setValue(selrect.bottom()); + if (!line_y_max.hasFocus()) line_y_max.setValue(selrect.top()); + if (!isFit) { + line_x_min.setDefaultText(QString::number(grect.left()).toUpper()); + line_x_max.setDefaultText(QString::number(grect.right()).toUpper()); + line_y_min.setDefaultText(QString::number(grect.bottom()).toUpper()); + line_y_max.setDefaultText(QString::number(grect.top()).toUpper()); + } + line_x_min.is_auto = line_x_max.is_auto = line_y_min.is_auto = line_y_max.is_auto = false; + is_lines_update = false; +} + + +void Graphic::checkLines() { + isFit = (line_x_min.isDefault() && line_x_max.isDefault() && line_y_min.isDefault() && line_y_max.isDefault()); + update(true); +} + + +void Graphic::tick(int index, bool slide, bool update_) { + if (slide) { + mutex.lock(); + GraphicType & t(graphics[index]); + if (history > 0.) + while (t.polyline.size() > 1) { + if (fabs(t.polyline.back().x() - t.polyline.front().x()) <= history) break; + t.polyline.pop_front(); + } + } + if (!update_) { + if (isFit) findGraphicsRect(); + mutex.unlock(); + return; + } + //polyline.push_back(QPointF(brick->time_, brick->output(port))); + //cout << polyline.size() << endl; + if (isFit) findGraphicsRect(); + if (!slide) { + if (aupdate) update(); + return; + } + mutex.unlock(); + if (aupdate) update(); +} + + +void Graphic::on_buttonAutofit_clicked() { + isFit = true; + bool isEmpty = true; + foreach (const GraphicType & t, graphics) { + const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline); + if (!pol.isEmpty()) { + isEmpty = false; + break; + } + } + if (isEmpty) grect = def_rect; + selrect = grect; + findGraphicsRect(); + update(); +} + + +void Graphic::on_buttonConfigure_clicked() { + conf->graphicItems.clear(); + for (int i = 0; i < graphics.size(); i++) { + GraphicConf::GraphicItem item; + item.icon = graphics[i].icon; + item.name = graphics[i].name; + conf->graphicItems.append(item); + } + conf->ui->colorGrid->setColor(grid_pen.color()); + conf->ui->comboStyleGrid->setCurrentIndex((int)grid_pen.style()); + conf->ui->spinWidthGrid->setValue(grid_pen.widthF()); + conf->ui->checkOGL->setChecked(isOGL); + conf->ui->checkAAlias->setChecked(aalias); + conf->ui->checkInputs->setChecked(borderInputsVisible()); + conf->ui->checkStatus->setChecked(statusVisible()); + conf->ui->checkLegend->setChecked(legendVisible()); + conf->ui->checkGridAutoX->setChecked(grad_x == Auto); + conf->ui->checkGridAutoY->setChecked(grad_y == Auto); + conf->ui->colorBackground->setColor(back_color); + conf->ui->colorText->setColor(text_color); + conf->ui->spinGridStepX->setValue(gridx); + conf->ui->spinGridStepY->setValue(gridy); + conf->ui->spinMarginL->setValue(margins_.left()); + conf->ui->spinMarginT->setValue(margins_.height()); + conf->ui->spinMarginR->setValue(margins_.width()); + conf->ui->spinMarginB->setValue(margins_.top()); + conf->readParams(); + if (conf->exec() == QDialog::Rejected) return; + grid_pen = QPen(conf->ui->colorGrid->color(), conf->ui->spinWidthGrid->value(), (Qt::PenStyle)conf->ui->comboStyleGrid->currentIndex()); + back_color = conf->ui->colorBackground->color(); + text_color = conf->ui->colorText->color(); + grad_x = conf->ui->checkGridAutoX->isChecked() ? Auto : Fixed; + grad_y = conf->ui->checkGridAutoY->isChecked() ? Auto : Fixed; + gridx = conf->ui->spinGridStepX->value(); + gridy = conf->ui->spinGridStepY->value(); + setOpenGL(conf->ui->checkOGL->isChecked()); + setAntialiasing(conf->ui->checkAAlias->isChecked()); + setBorderInputsVisible(conf->ui->checkInputs->isChecked()); + setStatusVisible(conf->ui->checkStatus->isChecked()); + setLegendVisible(conf->ui->checkLegend->isChecked()); + setMargins(conf->ui->spinMarginL->value(), conf->ui->spinMarginR->value(), conf->ui->spinMarginT->value(), conf->ui->spinMarginB->value()); + updateLegend(); + update(); +} + + +void Graphic::on_checkGuides_toggled(bool checked) { + guides = checked; + if (guides) setCanvasCursor(Qt::BlankCursor); + else setCanvasCursor(Qt::ArrowCursor); + update(); +} + + +void Graphic::updateLegend() { + if (!ui->widgetLegend->isVisible()) return; + leg_update = false; + int ps = 100; + for (int i = 0; i < graphics.size(); i++) { + while (!graphics[i].pb->actions().isEmpty()) graphics[i].pb->removeAction(graphics[i].pb->actions()[0]); + delete graphics[i].pb; + QPixmap pix(60, 22); + pix.fill(back_color); + QPainter p(&pix); + p.setPen(graphics[i].pen); + p.drawLine(0, pix.height() / 2, pix.width(), pix.height() / 2); + p.end(); + graphics[i].icon = QIcon(pix); + graphics[i].pb = new QCheckBox(graphics[i].name); + graphics[i].pb->setIconSize(pix.size()); + //graphics[i].pb->setFlat(true); + graphics[i].pb->setIcon(graphics[i].icon); + graphics[i].pb->setChecked(graphics[i].visible); + graphics[i].pb->setProperty("graphic_num", i); + graphics[i].pb->setContextMenuPolicy(Qt::ActionsContextMenu); + //qDebug() << graphics[i].pb->actions(); + QAction * act = new QAction(trUtf8("Check all"), 0); + act->setCheckable(true); + act->setChecked(true); + graphics[i].pb->addAction(act); + connect(act, SIGNAL(triggered(bool)), this, SLOT(graphicAllVisibleChange(bool))); + connect(graphics[i].pb, SIGNAL(toggled(bool)), this, SLOT(graphicVisibleChange(bool))); + int cps = graphics[i].pb->sizeHint().width() + 4; + if (cps > ps) ps = cps; + } + int maxcol = qMax(ui->widgetLegend->width() / ps - 1, 1); + int row = 0, col = 0; + bool lv = ui->widgetLegend->isVisible(); + ui->widgetLegend->hide(); + for (int i = 0; i < graphics.size(); i++) { + ui->layoutLegend->addWidget(graphics[i].pb,row,col); + col++; + if (col > maxcol) {col = 0; row++;} + } + ui->widgetLegend->setVisible(lv); + leg_update = true; +} + + +void Graphic::graphicVisibleChange(bool checked) { + if (visible_update) return; + QCheckBox * cb = qobject_cast(sender()); + int i = cb->property("graphic_num").toInt(); + graphics[i].visible = checked; + if (isFit) on_buttonAutofit_clicked(); + else update(); +// update(); +} + + +void Graphic::graphicAllVisibleChange(bool checked) { + visible_update = true; + for (int i=0; isetChecked(checked); + } + visible_update = false; + if (isFit) on_buttonAutofit_clicked(); + else update(); +} + + +void Graphic::enterFullscreen() { + if (fullscr) return; + ui->layoutCanvas->removeWidget(canvas); + canvas->setParent(0); + canvas->showFullScreen(); + canvas->setFocus(); + canvas->raise(); + fullscr = true; +} + + +void Graphic::leaveFullscreen() { + if (!fullscr) return; + canvas->setWindowFlags(canvas->windowFlags() & ~Qt::WindowFullScreen); + ui->layoutCanvas->addWidget(canvas); + canvas->show(); + fullscr = false; +} + + +QString Graphic::caption() const { + return ui->labelCaption->text(); +} + + +bool Graphic::borderInputsVisible() const { + return ui->widgetLX->isVisible(); +} + + +bool Graphic::statusVisible() const { + return ui->status->isVisible(); +} + + +bool Graphic::legendVisible() const { + return ui->widgetLegend->isVisible(); +} + + +QByteArray Graphic::save() { + QByteArray ba; + QDataStream s(&ba, QIODevice::ReadWrite); + s << openGL() << antialiasing() << borderInputsVisible() << statusVisible() << legendVisible(); + s << graphics; + return ba; +} + + +void Graphic::load(QByteArray ba) { + if (ba.isEmpty()) return; + QDataStream s(ba); + bool a; + s >> a; setOpenGL(a); + s >> a; setAntialiasing(a); + s >> a; setBorderInputsVisible(a); + s >> a; setStatusVisible(a); + s >> a; setLegendVisible(a); + s >> graphics; +} + + +void Graphic::setCaption(const QString & str) { + ui->labelCaption->setText(str); + ui->labelCaption->setVisible(str.length() > 0); + if (aupdate) update(); +} + + +void Graphic::setGridEnabled(bool enabled) { + ui->checkGrid->setChecked(enabled); +} + + +void Graphic::setBorderInputsVisible(bool visible) { + ui->widgetLX->setVisible(visible); + ui->widgetLY->setVisible(visible); + ui->checkBorderInputs->setChecked(visible); +} + + +void Graphic::setStatusVisible(bool visible) { + ui->status->setVisible(visible); +} + + +void Graphic::setLegendVisible(bool visible) { + ui->widgetLegend->setVisible(visible); + ui->checkLegend->setChecked(visible); + updateLegend(); +} + + +void Graphic::on_checkExpandY_toggled(bool checked) { + only_expand_y = checked; + ui->checkExpandY->setIcon(checked ? icon_exp_y : icon_exp_sy); +} + + +void Graphic::on_checkExpandX_toggled(bool checked) { + only_expand_x = checked; + ui->checkExpandX->setIcon(checked ? icon_exp_x : icon_exp_sx); +} diff --git a/qad/graphic/graphic.h b/qad/graphic/graphic.h new file mode 100644 index 0000000..8a1688f --- /dev/null +++ b/qad/graphic/graphic.h @@ -0,0 +1,459 @@ +#ifndef GRAPHIC_H +#define GRAPHIC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "graphic_conf.h" +#include "clineedit.h" +#include "qpievaluator.h" +#if QT_VERSION >= 0x050100 +# include +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class ELineEdit: public CLineEdit { + Q_OBJECT +public: + explicit ELineEdit(QWidget * parent = 0); + //void setText(const QString & v) {if (!is_auto) is_reset = false; CLineEdit::setText(v); setDefaultText(v, is_reset); last_ret = complexd(v.toDouble(), 0.); emit valueChanged(last_ret.real());} + void setValue(const int & v) {if (is_reset) setDefaultText(QString::number(v).toUpper(), is_reset); else setText(QString::number(v).toUpper()); last_ret = complexd(v, 0.); if (!is_auto) emit valueChanged(last_ret.real());} + void setValue(const double & v) {if (is_reset) setDefaultText(QString::number(v).toUpper(), is_reset); else setText(QString::number(v).toUpper()); last_ret = complexd(v, 0.); if (!is_auto) emit valueChanged(last_ret.real());} + double value() const {return last_ret.real();} + bool isDefault() const {return !cw->isVisible();} + bool is_reset, is_auto; +protected: + void wheelEvent(QWheelEvent * e); + QPIEvaluator evaluator; + complexd last_ret; +private slots: + void toDefaultClicked() {is_reset = true; calculate();} + void calculate(); +signals: + void valueChanged(double value); +}; + + +namespace Ui { + class Graphic; +}; + + +class Graphic: public QFrame +{ + Q_OBJECT + Q_FLAGS(Buttons) + Q_ENUMS(Alignment Graduation AxisType) + + Q_PROPERTY(QString caption READ caption WRITE setCaption) + Q_PROPERTY(QString labelX READ labelX WRITE setLabelX) + Q_PROPERTY(QString labelY READ labelY WRITE setLabelY) + Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor) + Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) + + Q_PROPERTY(int currentGraphic READ currentGraphic WRITE setCurrentGraphic) + Q_PROPERTY(int graphicsCount READ graphicsCount WRITE setGraphicsCount) + Q_PROPERTY(QString graphicName READ graphicName WRITE setGraphicName) + Q_PROPERTY(QPen graphicPen READ graphicPen WRITE setGraphicPen) + Q_PROPERTY(QColor graphicColor READ graphicColor WRITE setGraphicColor) + Q_PROPERTY(Qt::PenStyle graphicStyle READ graphicStyle WRITE setGraphicStyle) + Q_PROPERTY(double graphicLineWidth READ graphicLineWidth WRITE setGraphicLineWidth) + Q_PROPERTY(double graphicPointWidth READ graphicPointWidth WRITE setGraphicPointWidth) + Q_PROPERTY(QColor graphicFillColor READ graphicFillColor WRITE setGraphicFillColor) + Q_PROPERTY(bool graphicLinesEnabled READ graphicLinesEnabled WRITE setGraphicLinesEnabled) + Q_PROPERTY(bool graphicPointsEnabled READ graphicPointsEnabled WRITE setGraphicPointsEnabled) + Q_PROPERTY(bool graphicFillEnabled READ graphicFillEnabled WRITE setGraphicFillEnabled) + + Q_PROPERTY(bool gridEnabled READ gridEnabled WRITE setGridEnabled) + Q_PROPERTY(QPen gridPen READ gridPen WRITE setGridPen) + Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor) + Q_PROPERTY(Qt::PenStyle gridStyle READ gridStyle WRITE setGridStyle) + + Q_PROPERTY(QPen selectionPen READ selectionPen WRITE setSelectionPen) + Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor) + Q_PROPERTY(Qt::PenStyle selectionStyle READ selectionStyle WRITE setSelectionStyle) + Q_PROPERTY(QBrush selectionBrush READ selectionBrush WRITE setSelectionBrush) + + Q_PROPERTY(Alignment buttonsPosition READ buttonsPosition WRITE setButtonsPosition) + Q_PROPERTY(Buttons buttons READ buttons WRITE setButtons) + Q_PROPERTY(bool navigationEnabled READ navigationEnabled WRITE setNavigationEnabled) + Q_PROPERTY(bool openGL READ openGL WRITE setOpenGL) + Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing) + Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate) + Q_PROPERTY(bool borderInputsVisible READ borderInputsVisible WRITE setBorderInputsVisible) + Q_PROPERTY(bool statusVisible READ statusVisible WRITE setStatusVisible) + Q_PROPERTY(bool legendVisible READ legendVisible WRITE setLegendVisible) + Q_PROPERTY(bool paused READ paused WRITE setPaused) + Q_PROPERTY(bool onlyExpandY READ onlyExpandY WRITE setOnlyExpandY) + Q_PROPERTY(bool onlyExpandX READ onlyExpandX WRITE setOnlyExpandX) + Q_PROPERTY(double historySize READ historySize WRITE setHistorySize) + Q_PROPERTY(double maxVisibleTime READ maxVisibleTime WRITE setMaxVisibleTime) + Q_PROPERTY(double autoXIncrement READ autoXIncrement WRITE setAutoXIncrement) + Q_PROPERTY(QRectF limit READ limit WRITE setLimit) + Q_PROPERTY(QRect margins READ margins WRITE setMargins) + Q_PROPERTY(QRectF visualRect READ visualRect WRITE setVisualRect) + Q_PROPERTY(QRectF defaultRect READ defaultRect WRITE setDefaultRect) + Q_PROPERTY(int minimumRepaintInterval READ minimumRepaintInterval WRITE setMinimumRepaintInterval) + + Q_PROPERTY(double gridNumbersMultiplierX READ gridNumbersMultiplierX WRITE setGridNumbersMultiplierX) + Q_PROPERTY(double gridNumbersMultiplierY READ gridNumbersMultiplierY WRITE setGridNumbersMultiplierY) + Q_PROPERTY(Graduation graduationX READ graduationX WRITE setGraduationX) + Q_PROPERTY(Graduation graduationY READ graduationY WRITE setGraduationY) + Q_PROPERTY(double graduationStepX READ graduationStepX WRITE setGraduationStepX) + Q_PROPERTY(double graduationStepY READ graduationStepY WRITE setGraduationStepY) + Q_PROPERTY(AxisType axisType READ axisType WRITE setAxisType) + + Q_PROPERTY(int histogramMinIntervals READ histogramMinIntervals WRITE setHistogramMinIntervals) + Q_PROPERTY(int histogramMaxIntervals READ histogramMaxIntervals WRITE setHistogramMaxIntervals) + Q_PROPERTY(double histogramMinDeltaMultiplier READ histogramMinDeltaMultiplier WRITE setHistogramMinDeltaMultiplier) + + Q_PROPERTY(Graphic::GraphicsData graphicsData READ graphicsData WRITE setGraphicsData) + +public: + Graphic(QWidget * parent = 0); + ~Graphic(); + + typedef QVector > GraphicsData; + enum GraphicAction {gaNone, gaZoomInRect, gaZoomRangeX, gaZoomRangeY, gaMove}; + enum Button {NoButtons = 0x0, + AllButtons = 0xFFFFFFFF, + Autofit = 0x01, + Grid = 0x02, + CursorAxis = 0x04, + OnlyExpandY = 0x08, + OnlyExpandX = 0x10, + Fullscreen = 0x20, + BorderInputs = 0x40, + Legend = 0x80, + Configure = 0x100, + Save = 0x200, + Clear = 0x800, + Close = 0x1000, + Pause = 0x2000 + }; + enum Alignment {Left, Right}; + enum Graduation {Auto, Fixed}; + enum AxisType {Numeric, DateTime}; + Q_DECLARE_FLAGS(Buttons, Button) + + QString caption() const; + QString labelX() const {return label_x;} + QString labelY() const {return label_y;} + QString graphicName() const {return graphics[curGraphic].name;} + QColor backgroundColor() const {return back_color;} + QColor textColor() const {return text_color;} + QColor graphicColor() const {return graphics[curGraphic].pen.color();} + QColor gridColor() const {return grid_pen.color();} + QColor selectionColor() const {return selpen.color();} + Qt::PenStyle graphicStyle() const {return graphics[curGraphic].pen.style();} + Qt::PenStyle gridStyle() const {return grid_pen.style();} + Qt::PenStyle selectionStyle() const {return selpen.style();} + double graphicLineWidth() const {return graphics[curGraphic].pen.widthF();} + double graphicPointWidth() const {return graphics[curGraphic].pointWidth;} + QColor graphicFillColor() const {return graphics[curGraphic].fill_color;} + bool graphicVisible() const {return graphics[curGraphic].visible;} + bool graphicLinesEnabled() const {return graphics[curGraphic].lines;} + bool graphicPointsEnabled() const {return graphics[curGraphic].points;} + bool graphicFillEnabled() const {return graphics[curGraphic].fill;} + QPen graphicPen() const {return graphics[curGraphic].pen;} + QPen gridPen() const {return grid_pen;} + QPen selectionPen() const {return selpen;} + QBrush selectionBrush() const {return selbrush;} + bool navigationEnabled() const {return navigation;} + bool openGL() const {return isOGL;} + bool antialiasing() const {return aalias;} + bool autoUpdate() const {return aupdate;} + bool gridEnabled() const {return grid;} + bool borderInputsVisible() const; + bool statusVisible() const; + bool legendVisible() const; + bool paused() const {return pause_;} + bool onlyExpandY() const {return only_expand_y;} + bool onlyExpandX() const {return only_expand_x;} + int currentGraphic() const {return curGraphic;} + int graphicsCount() const {return graphics.size();} + Graphic::Buttons buttons() const {return buttons_;} + Graphic::Alignment buttonsPosition() const {return align;} + double historySize() const {return history;} + double maxVisibleTime() const {return visible_time;} + double autoXIncrement() const {return inc_x;} + QRectF visualRect() const {return selrect;} + QRectF defaultRect() const {return def_rect;} + QRectF limit() const {return limit_;} + QRect margins() const {return margins_;} + int minimumRepaintInterval() const {return min_repaint_int;} + int histogramMinIntervals() const {return min_int;} + int histogramMaxIntervals() const {return max_int;} + double histogramMinDeltaMultiplier() const {return mdm;} + double gridNumbersMultiplierX() const {return grid_numbers_x;} + double gridNumbersMultiplierY() const {return grid_numbers_y;} + Graduation graduationX() const {return grad_x;} + Graduation graduationY() const {return grad_y;} + double graduationStepX() const {return gridx;} + double graduationStepY() const {return gridy;} + AxisType axisType() const {return axis_type_x;} + QVector graphicData(const int index = 0) const {return graphics[index].polyline;} + GraphicsData graphicsData() const; + QWidget * viewport() const {return canvas;} + QByteArray save(); + void load(QByteArray ba); + void lock() {mutex_.lock();} + void unlock() {mutex_.unlock();} + + void reset() {mutex.lock(); clear(); mutex.unlock();} + + GraphicType graphic(int arg) {if (arg < 0 || arg >= graphics.size()) return GraphicType(); return graphics[arg];} + const QVector & allGraphics() const {return graphics;} + void setAllGraphics(const QVector & g, bool update = true) {graphics = g; if (update) updateLegend();} + void setHistogramData(const QVector & g, int graphic); + void setHistogramData(const QVector & g) {setHistogramData(g, curGraphic);} + + double canvas2realX(double px) const; + double canvas2realY(double py) const; + double real2canvasX(double px) const; + double real2canvasY(double py) const; + QPointF canvas2real(QPointF canvas_point) const {return QPointF(canvas2realX(canvas_point.x()), canvas2realY(canvas_point.y()));} + QPointF real2canvas(QPointF real_point) const {return QPointF(real2canvasX(real_point.x()), real2canvasY(real_point.y()));} + double getScaleX() const {return real2canvasX(1.) - real2canvasX(0.);} + double getScaleY() const {return real2canvasY(1.) - real2canvasY(0.);} + QPointF getScale() const {return QPointF(getScaleX(), getScaleY());} + +public slots: + void setCaption(const QString & str); + void setLabelX(const QString & str) {label_x = str; hasLblX = (str.length() > 0); if (aupdate) update();} + void setLabelY(const QString & str) {label_y = str; hasLblY = (str.length() > 0); if (aupdate) update();} + void setGraphicName(const QString & str, int index) {graphics[index].name = str; updateLegend(); if (aupdate) update();} + void setGraphicName(const QString & str) {graphics[curGraphic].name = str; updateLegend(); if (aupdate) update();} + void setBackgroundColor(const QColor & color) {back_color = color; if (aupdate) update(); updateLegend();} + void setTextColor(const QColor & color) {text_color = color; if (aupdate) update();} + void setGraphicColor(const QColor & color, int index) {graphics[index].pen.setColor(color); updateLegend(); if (aupdate) update();} + void setGraphicColor(const QColor & color) {setGraphicColor(color, curGraphic);} + void setGridColor(const QColor & color) {grid_pen.setColor(color); if (aupdate) update();} + void setSelectionColor(const QColor & color) {selpen.setColor(color);} + void setGraphicStyle(const Qt::PenStyle & style) {graphics[curGraphic].pen.setStyle(style); updateLegend(); if (aupdate) update();} + void setGridStyle(const Qt::PenStyle & style) {grid_pen.setStyle(style); if (aupdate) update();} + void setSelectionStyle(const Qt::PenStyle & style) {selpen.setStyle(style);} + void setGraphicVisible(bool visible, int index) {graphics[index].visible = visible; updateLegend(); if (aupdate) update();} + void setGraphicVisible(bool visible) {setGraphicVisible(visible, curGraphic);} + void setGraphicLineWidth(double w, int index) {if (qRound(w) == w) graphics[index].pen.setWidth(qRound(w)); else graphics[index].pen.setWidthF(w); updateLegend(); if (aupdate) update();} + void setGraphicLineWidth(double w) {setGraphicLineWidth(w, curGraphic);} + void setGraphicPointWidth(double w, int index) {graphics[index].pointWidth = w; updateLegend(); if (aupdate) update();} + void setGraphicPointWidth(double w) {setGraphicPointWidth(w, curGraphic);} + void setGraphicFillColor(const QColor & w, int index) {graphics[index].fill_color = w; updateLegend(); if (aupdate) update();} + void setGraphicFillColor(const QColor & w) {setGraphicFillColor(w, curGraphic);} + void setGraphicLinesEnabled(bool w, int index) {graphics[index].lines = w; updateLegend(); if (aupdate) update();} + void setGraphicLinesEnabled(bool w) {setGraphicLinesEnabled(w, curGraphic);} + void setGraphicPointsEnabled(bool w, int index) {graphics[index].points = w; updateLegend(); if (aupdate) update();} + void setGraphicPointsEnabled(bool w) {setGraphicPointsEnabled(w, curGraphic);} + void setGraphicFillEnabled(bool w, int index) {graphics[index].fill = w; updateLegend(); if (aupdate) update();} + void setGraphicFillEnabled(bool w) {setGraphicFillEnabled(w, curGraphic);} + void setGraphicPen(const QPen & pen, int index) {graphics[index].pen = pen; updateLegend(); if (aupdate) update();} + void setGraphicPen(const QPen & pen) {setGraphicPen(pen, curGraphic);} + void setGridPen(const QPen & pen) {grid_pen = pen; if (aupdate) update();} + void setSelectionPen(const QPen & pen) {selpen = pen;} + void setSelectionBrush(const QBrush & brush) {selbrush = brush;} + void setNavigationEnabled(bool on) {navigation = on;} + void setOpenGL(bool on); + void setAntialiasing(bool enabled); + void setAutoUpdate(bool enabled) {aupdate = enabled;} + void setGridEnabled(bool enabled); + void setBorderInputsVisible(bool visible); + void setStatusVisible(bool visible); + void setLegendVisible(bool visible); + void setPaused(bool yes); + void setButtons(Graphic::Buttons b); + void setButtonsPosition(Graphic::Alignment a); + void setHistorySize(double val); + void setMaxVisibleTime(double val) {visible_time = val;} + void setAutoXIncrement(double val) {inc_x = val;} + void setLimit(const QRectF & val) {limit_ = val;} + void setMargins(const QRect & val) {margins_ = val; update();} + void setMargins(int left_, int right_, int top_, int bottom_) {setMargins(QRect(left_, bottom_, right_, top_));} + void setLeftMargin(int value) {margins_.moveLeft(value); setMargins(margins_);} + void setRightMargin(int value) {margins_.setWidth(value); setMargins(margins_);} + void setTopMargin(int value) {margins_.setHeight(value); setMargins(margins_);} + void setBottomMargin(int value) {margins_.moveTop(value); setMargins(margins_);} + void setMinimumRepaintInterval(const int & val) {min_repaint_int = val;} + void setOnlyExpandY(bool yes); + void setOnlyExpandX(bool yes); + void setHistogramMinIntervals(int value) {min_int = value; updateGraphics();} + void setHistogramMaxIntervals(int value) {max_int = value; updateGraphics();} + void setHistogramMinDeltaMultiplier(double value) {mdm = value; updateGraphics();} + void setGraphicsData(const GraphicsData & gd); + + void setGridNumbersMultiplierX(double value) {grid_numbers_x = value; updateGraphics();} + void setGridNumbersMultiplierY(double value) {grid_numbers_y = value; updateGraphics();} + void setGraduationX(Graduation value) {grad_x = value; if (aupdate) update();;} + void setGraduationY(Graduation value) {grad_y = value; if (aupdate) update();;} + void setGraduationStepX(double sx) {gridx = sx; if (aupdate) update();} + void setGraduationStepY(double sy) {gridy = sy; if (aupdate) update();} + void setGraduationSteps(double sx, double sy) {gridx = sx; gridy = sy; if (aupdate) update();} + void setAxisType(AxisType t) {axis_type_x = t; if (aupdate) update();} + + void addPoint(const QPointF & p, int graphic, bool update_ = true); + void addPoint(const QPointF & p, bool update = true) {addPoint(p, curGraphic, update);} + void addPoint(double x, double y, int graphic, bool update = true) {addPoint(QPointF(x, y), graphic, update);} + void addPoint(double x, double y, bool update = true) {addPoint(QPointF(x, y), update);} + void addPoint(double y, int graphic, bool update = true) {addPoint(QPointF(graphics.at(graphic).max_x + inc_x, y), graphic, update);} + void addPoint(double y, bool update = true) {addPoint(QPointF(graphics[curGraphic].max_x + inc_x, y), update);} + void setGraphicData(const QVector & g, int graphic, bool update_ = true); + void setGraphicData(const QVector & g) {setGraphicData(g, curGraphic);} + void setGraphicProperties(const QString & name, const QColor & color = Qt::darkRed, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible = true) {setGraphicProperties(curGraphic, name, color, style, width, visible);} + void setGraphicProperties(int graphic, const QString & name, const QColor & color = Qt::darkRed, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible = true); + void addGraphic(const QString & name, const QColor & color = Qt::darkRed, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible = true); + void addGraphic(const GraphicType & gd, bool update = true) {graphics << gd; if (update) updateLegend();} + void setVisualRect(const QRectF & rect); + void setDefaultRect(const QRectF & rect); + void autofit() {on_buttonAutofit_clicked();} + void saveImage(); + void clear(); + void update(bool force = false); + void updateGraphics() {findGraphicsRect(); update();} + void setCurrentGraphic(int arg) {if (arg < 0 || arg >= graphics.size()) return; curGraphic = arg;} + void setGraphicsCount(int arg, bool update = true); + + void zoom(float factor); + void zoomIn() {zoom(1. / 1.2);} + void zoomOut() {zoom(1.2);} + void fullscreen(); + +protected: + virtual void changeEvent(QEvent * e); + virtual void resizeEvent(QResizeEvent * ) {if (leg_update) updateLegend();} + virtual QSize sizeHint() const {return QSize(400, 300);} + virtual void timerEvent(QTimerEvent * ); + virtual bool eventFilter(QObject * o, QEvent * e); + + void procGesture(QGesture * g); + void setCurrentAction(GraphicAction action); + void findGraphicsRect(double start_x = 0., double end_x = 0., double start_y = 0., double end_y = 0.); + void tick(int index, bool slide = true, bool update = true); + void repaintCanvas(bool force = false) {if (tm.elapsed() < min_repaint_int && !force) return; tm.restart(); canvas->update();} + void drawGraphics(); + void drawGrid(); + void drawGuides(); + void drawPause(); + void drawAction(); + void updateLegend(); + void setCanvasCursor(QCursor cursor); + void swapToBuffer(); + void swapToNormal() {bufferActive = false;} + void setRectToLines(); + void checkLines(); + double splitRange(double range, int count = 1); + double splitRangeDate(double range, int count = 1, QString * format = 0, int step[7] = 0); + double roundTo(double value, double round_to); + void roundDateTime(QDateTime & dt, int c[7]); + void addDateTime(QDateTime & dt, int c[7], int mul = 1); + QPointF absPoint(QPointF point) {return QPointF(qAbs(point.x()), qAbs(point.y()));} + QString pointCoords(QPointF point); + QPair gridMark(double v) const; + + Ui::Graphic * ui; + QMutex mutex, mutex_; + QWidget * canvas; + QImage * buffer; + QPainter * painter; + QBrush selbrush; + QPen grid_pen, selpen; + QColor back_color, text_color; + QVector graphics; + int curGraphic; + GraphicAction curaction, prevaction; + QRectF grect, rrect, selrect, limit_, def_rect; + QRect margins_; + QSize font_sz; + QPoint startpos, curpos, prevpos, gridborder; + QString label_x, label_y, ppath; + Graphic::Buttons buttons_; + Graphic::Alignment align; + GraphicConf * conf; + ELineEdit line_x_min, line_x_max, line_y_min, line_y_max; + QTime tm; + QIcon icon_exp_x, icon_exp_y, icon_exp_sx, icon_exp_sy; + QImage icon_pause_b, icon_pause_f; + Graduation grad_x, grad_y; + AxisType axis_type_x; + double gridx, gridy, history, visible_time, inc_x, mdm, grid_numbers_x, grid_numbers_y, LN2, LN5, LN10; + double eminx, eminy, emaxx, emaxy, pause_phase; + int legy, lastw, lasth, min_repaint_int, min_int, max_int, timer_pause, thick; + bool aalias, aupdate, mupdate, grid, guides, isFit, isEmpty, isOGL, isHover, bufferActive, cancel, pause_, isPrinting; + bool hasLblX, hasLblY, navigation, only_expand_y, only_expand_x, is_lines_update, leg_update, visible_update, fullscr; + +protected slots: + void canvasPaintEvent(QPaintEvent * ); + void canvasMouseMoveEvent(QMouseEvent * ); + void canvasMousePressEvent(QMouseEvent * ); + void canvasMouseReleaseEvent(QMouseEvent * ); + void canvasMouseDoubleClickEvent(QMouseEvent * ); + void canvasWheelEvent(QWheelEvent * ); + void canvasLeaveEvent(QEvent * ); + void canvasKeyPressEvent(QKeyEvent * ); + void graphicVisibleChange(bool checked); + void graphicAllVisibleChange(bool checked); + void lineXMinChanged(double value) {selrect.setLeft(value); checkLines();} + void lineXMaxChanged(double value) {selrect.setRight(value); checkLines();} + void lineYMinChanged(double value) {selrect.setBottom(value); checkLines();} + void lineYMaxChanged(double value) {selrect.setTop(value); checkLines();} + void on_buttonClose_clicked() {emit closeRequest(this);} + void on_buttonClear_clicked() {reset(); emit cleared();} + void on_buttonAutofit_clicked(); + void on_buttonConfigure_clicked(); + void on_buttonFullscreen_clicked() {fullscreen();} + void on_buttonSave_clicked() {saveImage();} + void on_checkGrid_toggled(bool checked) {grid = checked; update();} + void on_checkGuides_toggled(bool checked); + void on_checkExpandY_toggled(bool checked); + void on_checkExpandX_toggled(bool checked); + void on_checkBorderInputs_toggled(bool checked) {setBorderInputsVisible(checked);} + void on_checkLegend_toggled(bool checked) {setLegendVisible(checked);} + void on_checkPause_toggled(bool checked) {setPaused(checked);} + void enterFullscreen(); + void leaveFullscreen(); + +signals: + void graphicPaintEvent(QPainter * ); + void graphicMouseMoveEvent(QPointF point, int buttons); + void graphicMousePressEvent(QPointF point, int buttons); + void graphicMouseReleaseEvent(QPointF point, int buttons); + void graphicWheelEvent(QPointF point, int delta); + void closeRequest(QWidget * ); + void cleared(); + void visualRectChanged(); + +}; + +Q_DECLARE_METATYPE(Graphic::GraphicsData) + +Q_DECLARE_OPERATORS_FOR_FLAGS(Graphic::Buttons) + +//inline QDataStream & operator <<(QDataStream & s, const Graphic::GraphicsData & v) {s << v; return s;} +//inline QDataStream & operator >>(QDataStream & s, Graphic::GraphicsData & v) {s >> v; return s;} + +class __GraphicRegistrator__ { +public: + __GraphicRegistrator__() { + qRegisterMetaType("Graphic::GraphicsData"); + qRegisterMetaTypeStreamOperators("Graphic::GraphicsData"); + } +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // GRAPHIC_H diff --git a/qad/graphic/graphic.ui b/qad/graphic/graphic.ui new file mode 100644 index 0000000..b86c538 --- /dev/null +++ b/qad/graphic/graphic.ui @@ -0,0 +1,485 @@ + + + Graphic + + + + 0 + 0 + 564 + 433 + + + + + 150 + 150 + + + + + 0 + + + 2 + + + + + + + -10 + 0 + 28 + 361 + + + + + 2 + + + + + Autofit + + + + :/icons/zoom-fit-best.png:/icons/zoom-fit-best.png + + + + 16 + 16 + + + + + + + + Grid + + + + :/icons/view-grid.png:/icons/view-grid.png + + + + 16 + 16 + + + + true + + + true + + + + + + + Cursor axis + + + + :/icons/edit-guides.png:/icons/edit-guides.png + + + + 16 + 16 + + + + true + + + + + + + Only expand Y + + + + :/icons/expand_s_y.png:/icons/expand_s_y.png + + + + 16 + 16 + + + + true + + + + + + + Only expand X + + + + :/icons/expand_s_x.png:/icons/expand_s_x.png + + + + 16 + 16 + + + + true + + + + + + + Fullscreen + + + + :/icons/view-fullscreen.png:/icons/view-fullscreen.png + + + + 16 + 16 + + + + + + + + Border inputs + + + + :/icons/border-line.png:/icons/border-line.png + + + + 16 + 16 + + + + true + + + true + + + + + + + Legend + + + + :/icons/legend.png:/icons/legend.png + + + + 16 + 16 + + + + true + + + false + + + + + + + Pause + + + + :/icons/media-playback-pause.png:/icons/media-playback-pause.png + + + + 16 + 16 + + + + true + + + + + + + Configure ... + + + + :/icons/configure.png:/icons/configure.png + + + + 16 + 16 + + + + + + + + Save image ... + + + + :/icons/document-save.png:/icons/document-save.png + + + + 16 + 16 + + + + + + + + Qt::Vertical + + + QSizePolicy::Preferred + + + + 0 + 30 + + + + + + + + Clear + + + + :/icons/edit-clear.png:/icons/edit-clear.png + + + + 16 + 16 + + + + + + + + Close + + + + :/icons/dialog-close.png:/icons/dialog-close.png + + + + 16 + 16 + + + + + + + + Qt::Vertical + + + + 0 + 79 + + + + + + + + + + + + Qt::RichText + + + Qt::AlignCenter + + + + + + + + + + + 0 + 0 + + + + QFrame::Box + + + QFrame::Sunken + + + + 0 + + + + + + 0 + 0 + + + + + 0 + + + 2 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + + + + + true + + + + + + + true + + + + + + + + + + 0 + 0 + + + + + 0 + + + 2 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Cursor: ( ; ) + + + + + + + + 0 + 0 + + + + + 4 + + + 1 + + + + + + + + + UWidget + QWidget +
uwidget.h
+
+ + UGLWidget + QWidget +
uglwidget.h
+
+
+ + + + +
diff --git a/qad/graphic/graphic_conf.cpp b/qad/graphic/graphic_conf.cpp new file mode 100644 index 0000000..1fe4421 --- /dev/null +++ b/qad/graphic/graphic_conf.cpp @@ -0,0 +1,103 @@ +#include "graphic_conf.h" +#include "ui_graphic_conf.h" + + +GraphicConf::GraphicConf(QVector & graphics_, QWidget * parent): QDialog(parent), graphics(graphics_) { + ui = new Ui::GraphicConf(); + ui->setupUi(this); + QStringList styles; + styles << tr("NoPen") << tr("Solid") << tr("Dash") + << tr("Dot") << tr("Dash-Dot") << tr("Dash-Dot-Dot"); + ui->comboStyleGrid->setIconSize(QSize(60, 22)); + ui->comboStyleGraphic->setIconSize(QSize(60, 22)); + ui->cbGraphicNames->setIconSize(QSize(60, 22)); + for (int i = 0; i < 6; i++) { + QPixmap pix(60, 22); + pix.fill(); + QPainter p(&pix); + p.setPen(QPen(Qt::black, 1, (Qt::PenStyle)i)); + p.drawLine(0, pix.height() / 2, pix.width(), pix.height() / 2); + p.end(); + ui->comboStyleGraphic->addItem(QIcon(pix), styles[i]); + ui->comboStyleGrid->addItem(QIcon(pix), styles[i]); + } +} + + +void GraphicConf::changeEvent(QEvent * e) { + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + return; + } + QDialog::changeEvent(e); +} + + +void GraphicConf::readParams() { + ui->cbGraphicNames->clear(); + for (int i = 0; i < graphicItems.size(); i++) + ui->cbGraphicNames->addItem(graphicItems[i].icon, graphicItems[i].name); +} + + +void GraphicConf::on_cbGraphicNames_currentIndexChanged(int i) { + if (i < 0) return; + if (graphicItems.isEmpty()) return; + ui->comboStyleGraphic->setCurrentIndex((int)graphics[i].pen.style()); + ui->colorGraphic->setColor(graphics[i].pen.color()); + ui->colorFill->setColor(graphics[i].fill_color); + ui->spinLineWidthGraphic->setValue(graphics[i].pen.widthF()); + ui->spinPointWidthGraphic->setValue(graphics[i].pointWidth); + ui->checkLines->setChecked(graphics[i].lines); + ui->checkPoints->setChecked(graphics[i].points); + ui->checkFill->setChecked(graphics[i].fill); +} + + +void GraphicConf::on_colorGraphic_colorChanged(const QColor & c) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].pen.setColor(c); +} + + +void GraphicConf::on_comboStyleGraphic_currentIndexChanged(int index) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].pen.setStyle((Qt::PenStyle)index); +} + + +void GraphicConf::on_spinLineWidthGraphic_valueChanged(double value) { + if (graphicItems.isEmpty()) return; + if (qRound(value) == value) graphics[ui->cbGraphicNames->currentIndex()].pen.setWidth(qRound(value)); + else graphics[ui->cbGraphicNames->currentIndex()].pen.setWidthF(value); +} + + +void GraphicConf::on_spinPointWidthGraphic_valueChanged(double value) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].pointWidth = value; +} + + +void GraphicConf::on_checkLines_toggled(bool on) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].lines = on; +} + + +void GraphicConf::on_checkPoints_toggled(bool on) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].points = on; +} + + +void GraphicConf::on_checkFill_toggled(bool on) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].fill = on; +} + + +void GraphicConf::on_colorFill_colorChanged(const QColor & color) { + if (graphicItems.isEmpty()) return; + graphics[ui->cbGraphicNames->currentIndex()].fill_color = color; +} diff --git a/qad/graphic/graphic_conf.h b/qad/graphic/graphic_conf.h new file mode 100644 index 0000000..6d926a6 --- /dev/null +++ b/qad/graphic/graphic_conf.h @@ -0,0 +1,90 @@ +#ifndef GRAPHIC_CONF_H +#define GRAPHIC_CONF_H + +#include +#include +#include +#include + + +namespace Ui { + class GraphicConf; +}; + + +struct GraphicType { + GraphicType(QString name_ = "y(x)", QColor color = Qt::red, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible_ = true) { + pen.setColor(color); + pen.setStyle(style); + lines = true; + points = false; + fill = false; + fill_color = Qt::yellow; + if (qRound(width) == width) pen.setWidth(qRound(width)); + else pen.setWidthF(width); + pen.setWidth(1); + pen.setCosmetic(true); + max_x = 0.; + name = name_; + visible = visible_; + pointWidth = 2.; + pb = new QCheckBox(name); + } + //~GraphicType() {delete pb;} + QString name; + QPolygonF polyline; + QPolygonF polyline_pause; + QPen pen; + QColor fill_color; + bool lines; + bool points; + bool fill; + double pointWidth; + double max_x; + double max_x_pause; + QCheckBox * pb; + QIcon icon; + bool visible; +}; + + +inline QDataStream & operator <<(QDataStream & s, const GraphicType & v) {s << v.name << v.pen << v.fill_color << v.lines << v.points << v.fill << v.pointWidth << v.visible; return s;} +inline QDataStream & operator >>(QDataStream & s, GraphicType & v) {s >> v.name >> v.pen >> v.fill_color >> v.lines >> v.points >> v.fill >> v.pointWidth >> v.visible; return s;} + + +class GraphicConf: public QDialog +{ + Q_OBJECT + friend class Graphic; +public: + explicit GraphicConf(QVector & graphics_, QWidget * parent = 0); + + struct GraphicItem { + QString name; + QIcon icon; + }; + + void readParams(); + + QVector & graphics; + QVector graphicItems; + +protected: + void changeEvent(QEvent * e); + + Ui::GraphicConf * ui; + +private slots: + void on_cbGraphicNames_currentIndexChanged(int index); + void on_colorGraphic_colorChanged(const QColor &); + void on_colorFill_colorChanged(const QColor &); + void on_comboStyleGraphic_currentIndexChanged(int index); + void on_spinLineWidthGraphic_valueChanged(double value); + void on_spinPointWidthGraphic_valueChanged(double value); + void on_checkLines_toggled(bool on); + void on_checkPoints_toggled(bool on); + void on_checkFill_toggled(bool on); + +}; + +#endif // GRAPHIC_CONF_H diff --git a/qad/graphic/graphic_conf.ui b/qad/graphic/graphic_conf.ui new file mode 100644 index 0000000..de95034 --- /dev/null +++ b/qad/graphic/graphic_conf.ui @@ -0,0 +1,678 @@ + + + GraphicConf + + + Qt::WindowModal + + + + 0 + 0 + 448 + 513 + + + + Graphic parameters + + + true + + + + 2 + + + 2 + + + + + Appearance + + + + 2 + + + 2 + + + + + + + Border inputs + + + + + + + Antialiasing + + + + + + + Status bar + + + + + + + OpenGL + + + + + + + Legend + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + 0 + 0 + + + + Background color: + + + + + + + true + + + + + + + + 0 + 0 + + + + Text color: + + + + + + + true + + + + + + + + + + + + Graphics + + + + QFormLayout::AllNonFixedFieldsGrow + + + 2 + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + + + + Color: + + + + + + + true + + + + + + + Style: + + + + + + + + + + Lines width: + + + true + + + + + + + 2 + + + 1.000000000000000 + + + + + + + Points width: + + + true + + + + + + + 2 + + + 1.000000000000000 + + + + + + + Fill: + + + true + + + + + + + true + + + + + + + + + + Grid + + + + QFormLayout::AllNonFixedFieldsGrow + + + 2 + + + 2 + + + 2 + + + + + Color: + + + + + + + true + + + + + + + Style: + + + + + + + + + + Width: + + + + + + + 2 + + + + + + + 3 + + + 0.001000000000000 + + + 9999999.000000000000000 + + + 50.000000000000000 + + + + + + + Step X: + + + + + + + Step Y: + + + + + + + 3 + + + 0.001000000000000 + + + 9999999.000000000000000 + + + 30.000000000000000 + + + + + + + Auto X + + + true + + + + + + + Auto Y + + + true + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Margins + + + + 2 + + + 2 + + + + + px + + + 100 + + + + + + + px + + + 100 + + + + + + + All: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + px + + + 100 + + + + + + + Right: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Left: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Bottom: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + px + + + 100 + + + + + + + Top: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + px + + + 100 + + + + + + + + + + + ColorButton + QPushButton +
colorbutton.h
+ + colorChanged(QColor) + +
+
+ + checkAAlias + checkOGL + colorBackground + colorText + colorGrid + comboStyleGrid + spinWidthGrid + cbGraphicNames + colorGraphic + comboStyleGraphic + checkLines + spinLineWidthGraphic + checkPoints + spinPointWidthGraphic + buttonBox + + + + + buttonBox + rejected() + GraphicConf + reject() + + + 255 + 641 + + + 245 + 207 + + + + + checkLines + toggled(bool) + spinLineWidthGraphic + setEnabled(bool) + + + 322 + 410 + + + 415 + 411 + + + + + checkPoints + toggled(bool) + spinPointWidthGraphic + setEnabled(bool) + + + 322 + 434 + + + 415 + 435 + + + + + buttonBox + accepted() + GraphicConf + accept() + + + 294 + 641 + + + 288 + 268 + + + + + checkFill + toggled(bool) + colorFill + setEnabled(bool) + + + 322 + 458 + + + 415 + 460 + + + + + spinMarginT_2 + valueChanged(int) + spinMarginT + setValue(int) + + + 259 + 221 + + + 249 + 191 + + + + + spinMarginT_2 + valueChanged(int) + spinMarginR + setValue(int) + + + 268 + 220 + + + 371 + 220 + + + + + spinMarginT_2 + valueChanged(int) + spinMarginB + setValue(int) + + + 233 + 230 + + + 234 + 252 + + + + + spinMarginT_2 + valueChanged(int) + spinMarginL + setValue(int) + + + 213 + 230 + + + 133 + 229 + + + + +
diff --git a/qad/graphic/lang/qad_graphic_ru.qm b/qad/graphic/lang/qad_graphic_ru.qm new file mode 100644 index 0000000000000000000000000000000000000000..8ed99a43cab02aa620cb50ddf72cbd4449489d12 GIT binary patch literal 3662 zcmb_eTWl0n7(VR&v%B3(SxQAx5C#HTpp>PhW!aW(cehZWr6nwcmPo>MJ8UN`JDc69 z77~3xV*nK&48{~CAtr_g#9KlL2||bj@e=jH_@V)$i9{1IQ88YKerKl44xQPC7}HG8 zK+pI6-}%menf7zTvp>A`%CS!t%)Pk#Se~f4UBI7%9!h@vHET^;iP~~mzi)j##qqDHZ42I7`wtYwI0KIn{9Rh?_15bUO2#5 z)grci{d%yJp1?^itE9$y1o!1EnDgTF8K_PqH3 z^j`Pv@-0QY<-TWrOyOLYe8=a%4_}6SAMHY1C~f)q1MI8CdJU^owfF2M?7!+iy?7kF zyRqV2f#rec-M=B;;lQgaJ_hVa;L>Fm^nD*3mv$rGm!YSUzkokCJ^U!*(~9YDeD*H( ztuaLnkY$eYNrS#Xan9Ov=TRn@OZq5QBB>WXkPx_U6cwV zN@f}d*3(St#MZSGrEdK0p%x}m2Z-9JA8$?giPI{Im{g&pS{#;(qLMF+Y9$-tEUE#? zN}V)Gy*fpLT1n%|>jM~kx9*w|>J2vQxT08fCR(*$`^qs5YH*H=gL zVPgaqMyQWAA|y9A4s_JS1`MnyjVX3B!`5&t#zYh5Ghi{%Cb4cZhSlSgZFrWL=+Iqs zz1Su$aiFN7xPEgj(8}*{v+gp|#H8@AAI;@TnW8M`ZFoN|pcdRn%#t?LT~vl`JF969 zb~fW#dry*idgZK~x9|5;EgX$vcR3-kH=or;Y}|`zA-ry*Ug+Sb;c3n*BZ{|vo-eRu zz&uZ=KcCw#%3}p7KP(RXC$d3jvOybJ7^jFrO$VOU&{%d=*ed0-_RL)hL*ukgKLW2* zqp+en*eJDD-9jXosllI?9+Sn5`y>axru*l!RY~{EZn;ozrMhWw{Zm}@NjSft7H(tkjhx0)X8W4+_TPcyt z#T@s}f-lW_$+m)?mo0a@>}fEO*AywINF^not-w$NObgPCBiHCf6s1*WY=5FqKr55- z8U0u`wZXfM{GR0W@b+zF<&=nW1{w%G^=yb*dKhOzfkIsuPd|!S+?kP-GJCT{brf}w zQFCh1*{c6zaM+YpqeDljRd>*OW8S2yY3e>_C4TcbT0ufu%^9Bx4vKl| z@&1aj4sZFFVgyeLZ{-gHe_E5Y(ULf1d@|Ztf+)fWHS-Q@Ij1+R$pvx1`8vvwK^tVS z5@Z3CMRld+oA;!({W;kgG23ipB9OQR<9wEYfo<}bHdR*+W7uJSqO)<6ta(n`)Pi%^ f@T8Qrh~43wpocJLLo=q`SrYiC) + + + + Graphic + + + + Autofit + Автомасштаб + + + + + Grid + Сетка + + + + + Cursor axis + Плавающие оси + + + + + Only expand Y + Только расширять Y + + + + + Only expand X + Только расширять X + + + + + Fullscreen + Во весь экран + + + + + Border inputs + Граничные поля ввода + + + + + Legend + Легенда + + + + + Configure ... + Настроить ... + + + + + Save image ... + Сохранить изображение ... + + + + + Clear + Очистить + + + + + Close + Закрыть + + + + + Cursor: ( ; ) + Курсор: ( ; ) + + + + + Cursor: + Курсор: + + + + Selection + Выделение + + + + Size + Размер + + + + + Range + Диапазон + + + + + Length + Длина + + + + + Cursor + Курсор + + + + Save Image + Сохранить изображение + + + + y(x) + + + + + Check all + Выбрать все + + + + GraphicConf + + + + Graphic parameters + Параметры графика + + + + + Appearance + Внешний вид + + + + + Border inputs + Граничные поля ввода + + + + + Antialiasing + Сглаживание + + + + + Status bar + Панель статуса + + + + + OpenGL + + + + + + Legend + Легенда + + + + + Background color: + Цвет фона: + + + + + Text color: + Цвет текста: + + + + + Graphics + Графики + + + + + + + Color: + Цвет: + + + + + + + Style: + Стиль: + + + + + Lines width: + Толщина линий: + + + + + Points width: + Толщина точек: + + + + + Fill: + Заливка: + + + + + Grid + Сетка + + + + + Width: + Толщина: + + + + + Step X: + Шаг X: + + + + + Step Y: + Шаг Y: + + + + + Auto X + Авто X + + + + + Auto Y + Авто Y + + + Auto step + Автоматический шаг + + + + + Margins + Поля + + + + + + + + + + + + + px + пикс + + + + + All: + Все: + + + + + Right: + Правое: + + + + + Left: + Левое: + + + + + Bottom: + Нижнее: + + + + + Top: + Верхнее: + + + + NoPen + НетЛинии + + + + Solid + Сплошная + + + + Dash + Штриховая + + + + Dot + Пунктирная + + + + Dash-Dot + ШтрихПунктирная + + + + Dash-Dot-Dot + ШтрихПунктирПунктирная + + + diff --git a/qad/graphic/plugin/CMakeLists.txt b/qad/graphic/plugin/CMakeLists.txt new file mode 100644 index 0000000..61032be --- /dev/null +++ b/qad/graphic/plugin/CMakeLists.txt @@ -0,0 +1 @@ +qad_plugin(graphic "") diff --git a/qad/graphic/plugin/graphicplugin.cpp b/qad/graphic/plugin/graphicplugin.cpp new file mode 100644 index 0000000..c4ff495 --- /dev/null +++ b/qad/graphic/plugin/graphicplugin.cpp @@ -0,0 +1,69 @@ +#include "graphic.h" +#include "graphicplugin.h" +#include + + +GraphicPlugin::GraphicPlugin(QObject * parent): QObject(parent) { + m_initialized = false; +} + + +void GraphicPlugin::initialize(QDesignerFormEditorInterface * /* core */) { + if (m_initialized) + return; + + // Add extension registrations, etc. here + + m_initialized = true; +} + + +bool GraphicPlugin::isInitialized() const { + return m_initialized; +} + + +QWidget * GraphicPlugin::createWidget(QWidget * parent) { + return new Graphic(parent); +} + + +QString GraphicPlugin::name() const { + return QLatin1String("Graphic"); +} + + +QString GraphicPlugin::group() const { + return QLatin1String("Display Widgets"); +} + + +QIcon GraphicPlugin::icon() const { + return QIcon(":/icons/graphic.png"); +} + + +QString GraphicPlugin::toolTip() const { + return QLatin1String("");//QLatin1String("Widget for display any math graphics with grid and navigation"); +} + + +QString GraphicPlugin::whatsThis() const { + return QLatin1String(""); +} + + +bool GraphicPlugin::isContainer() const { + return false; +} + + +QString GraphicPlugin::domXml() const { + return QLatin1String("\n\n"); +} + + +QString GraphicPlugin::includeFile() const { + return QLatin1String("graphic.h"); +} + diff --git a/qad/graphic/plugin/graphicplugin.h b/qad/graphic/plugin/graphicplugin.h new file mode 100644 index 0000000..9d1bc2e --- /dev/null +++ b/qad/graphic/plugin/graphicplugin.h @@ -0,0 +1,31 @@ +#ifndef GRAPHICPLUGIN_H +#define GRAPHICPLUGIN_H + +#include + +class GraphicPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + GraphicPlugin(QObject * parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget * createWidget(QWidget * parent); + void initialize(QDesignerFormEditorInterface * core); + +private: + bool m_initialized; + +}; + +#endif diff --git a/qad/graphic/plugin/qad_graphic.cpp b/qad/graphic/plugin/qad_graphic.cpp new file mode 100644 index 0000000..391255c --- /dev/null +++ b/qad/graphic/plugin/qad_graphic.cpp @@ -0,0 +1,14 @@ +#include "graphicplugin.h" +#include "qad_graphic.h" + +QADGraphic::QADGraphic(QObject * parent): QObject(parent) +{ + m_widgets.append(new GraphicPlugin(this)); +} + + +QList QADGraphic::customWidgets() const { + return m_widgets; +} + +Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADGraphic) diff --git a/qad/graphic/plugin/qad_graphic.h b/qad/graphic/plugin/qad_graphic.h new file mode 100644 index 0000000..0bda0bb --- /dev/null +++ b/qad/graphic/plugin/qad_graphic.h @@ -0,0 +1,21 @@ +#ifndef QAD_GRAPHIC_H +#define QAD_GRAPHIC_H + +#include +#include + +class QADGraphic: public QObject, public QDesignerCustomWidgetCollectionInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) + +public: + explicit QADGraphic(QObject * parent = 0); + virtual QList customWidgets() const; + +private: + QList m_widgets; + +}; + +#endif // QAD_GRAPHIC_H diff --git a/qad/graphic/qad_graphic.qrc b/qad/graphic/qad_graphic.qrc new file mode 100644 index 0000000..4deb98b --- /dev/null +++ b/qad/graphic/qad_graphic.qrc @@ -0,0 +1,32 @@ + + + lang/qad_graphic_ru.qm + ../icons/media-playback-pause.png + ../icons/dialog-close.png + ../icons/edit-clear.png + ../icons/edit-guides.png + ../icons/view-grid.png + ../icons/zoom-fit-best.png + ../icons/configure.png + ../icons/document-save.png + ../icons/edit-clear-locationbar-rtl.png + ../icons/edit-find.png + ../icons/list-add.png + ../icons/edit-delete.png + ../icons/item.png + ../icons/node-add.png + ../icons/node.png + ../icons/edit-copy.png + ../icons/edit-paste.png + ../icons/expand_s_x.png + ../icons/expand_s_y.png + ../icons/expand_x.png + ../icons/expand_y.png + ../icons/border-line.png + ../icons/legend.png + ../icons/graphic.png + ../icons/view-fullscreen.png + ../icons/pause-back.png + ../icons/pause-front.png + + diff --git a/qad/graphic/uglwidget.h b/qad/graphic/uglwidget.h new file mode 100644 index 0000000..c3391eb --- /dev/null +++ b/qad/graphic/uglwidget.h @@ -0,0 +1,48 @@ +#ifndef UGLWIDGET_H +#define UGLWIDGET_H + +#include +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809D +#endif + + +class UGLWidget: public QGLWidget +{ + Q_OBJECT +public: + UGLWidget(QWidget * parent = 0): QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::AlphaChannel | QGL::DirectRendering | QGL::SampleBuffers), parent) {}; + UGLWidget(QGLContext * context, QWidget * parent = 0): QGLWidget(context, parent) {}; + +signals: + void closeEvent(QCloseEvent * e); + void dragEnterEvent(QDragEnterEvent * e); + void dragLeaveEvent(QDragLeaveEvent * e); + void dragMoveEvent(QDragMoveEvent * e); + void dropEvent(QDropEvent * e); + void enterEvent(QEvent * e); + void hideEvent(QHideEvent * e); + void keyPressEvent(QKeyEvent * e); + void keyReleaseEvent(QKeyEvent * e); + void leaveEvent(QEvent * e); + void mouseDoubleClickEvent(QMouseEvent * e); + void mouseMoveEvent(QMouseEvent * e); + void mousePressEvent(QMouseEvent * e); + void mouseReleaseEvent(QMouseEvent * e); + void moveEvent(QMoveEvent * e); + void resizeEvent(QResizeEvent * e); + void showEvent(QShowEvent * e); + void wheelEvent(QWheelEvent * e); + void paintEvent(QPaintEvent * e); + void glDraw(); + void glInit(); + void initializeGL(); + void initializeOverlayGL(); + void paintGL(); + void paintOverlayGL(); + void resizeGL(int width, int height); + void resizeOverlayGL(int width, int height); + +}; + +#endif diff --git a/qad/graphic/uwidget.h b/qad/graphic/uwidget.h new file mode 100644 index 0000000..1d7f3bc --- /dev/null +++ b/qad/graphic/uwidget.h @@ -0,0 +1,52 @@ +#ifndef UWIDGET_H +#define UWIDGET_H + +#include +#include +#include +#include +#include + + +class UWidget: public QWidget +{ + Q_OBJECT +public: + UWidget(QWidget * parent = 0): QWidget(parent) {}; + +private: + virtual bool event(QEvent * e) { + if (e->type() != QEvent::Paint) return QWidget::event(e); + e->accept(); + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); + emit paintEvent((QPaintEvent * )e); + return true; + } + +signals: + void closeEvent(QCloseEvent * e); + void dragEnterEvent(QDragEnterEvent * e); + void dragLeaveEvent(QDragLeaveEvent * e); + void dragMoveEvent(QDragMoveEvent * e); + void dropEvent(QDropEvent * e); + void enterEvent(QEvent * e); + void hideEvent(QHideEvent * e); + void keyPressEvent(QKeyEvent * e); + void keyReleaseEvent(QKeyEvent * e); + void leaveEvent(QEvent * e); + void mouseDoubleClickEvent(QMouseEvent * e); + void mouseMoveEvent(QMouseEvent * e); + void mousePressEvent(QMouseEvent * e); + void mouseReleaseEvent(QMouseEvent * e); + void moveEvent(QMoveEvent * e); + void resizeEvent(QResizeEvent * e); + void showEvent(QShowEvent * e); + void wheelEvent(QWheelEvent * e); + void paintEvent(QPaintEvent * e); + +}; + +#endif diff --git a/qad/icons/align-bottom-center.png b/qad/icons/align-bottom-center.png new file mode 100644 index 0000000000000000000000000000000000000000..8678b5d91749731427f6ad948fafc8804b6731db GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^;y}#B!3HGbla4+GQfx`y?k)`fL2$v|<&%LToCO|{ z#S9GG!XV7ZFl&wkP>{XE)7O>#9+w7#3x{Z~CYOnS{-~tpoYwwObi9n| zSasuW_5<^mXI6P>K73cwmFFa+ zFyU2T#+2NM;1C_l^gI(k`@dO1GuO&XHSS`Fu5FRN!R@VGx5!CE!uiOf?CVL>IIoGg izWx1==g)Bm{dhmkmYkBV*4;qwGI+ZBxvXb*ed=yD2jgH)V>21+DaZjn16d8^E$aJ(BL z(ycAap5OPLZDZN-4D9a2Uh~3W!|8N-NGaj&cuFL9+?~y4^RqM<6OcP8Iqrsg0$_2l zrl_i#6$03PzkfHg?b4uK*Rk6@k#oj9v0AOZ@;Hv$RFm|LL3e+jALQFUQfzWDdi6%$v|MJ+9o6c0%_VRt-1`G4b?~~1vA5wlicsUnQrSQ z5;6ltb6`_$n}E$VecyjdjT&$HAFPWCtIgDETU$e%FS&-K)*Gffi5bSu9XfVLdRzT76>%PYhMhz5!dk|qnIAdc1 zR7QnWV>mVp_}K6FcOFi7uv)FyZns&CdFd$eCwrWQOf5|-}fi!NCpB!MK>V{5J+_^X%#W7DJnO8-{Zhr*LCaJ^=y4L zov#0~*ZIGigv^c&Eup%GMjZ{v%OK4==bAu{XE)7O>#9+w3?!3H9ywIl#3wj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQOOBmIYYE@ir9h$go-U3d8t1o8G7LImz~ee!Cx7=F zpIKLSo(mIsIjwDy-tvU}4Wj7_8Yde*zOcamVa}!lOSnH}VHNxJJR`xNcQ#9VH;-(HQd#EJnutDW|8L8 xz3+dYWnc2z>W-|x->iRU{w02SAHLyw{ypjT-qU3@r-5E)@O1TaS?83{1OSO+k&yrZ literal 0 HcmV?d00001 diff --git a/qad/icons/align-center-right.png b/qad/icons/align-center-right.png new file mode 100644 index 0000000000000000000000000000000000000000..0e9335c39fc41b51452e46b2c67549c8ebf294e3 GIT binary patch literal 348 zcmeAS@N?(olHy`uVBq!ia0vp^(m>3?!3H9ywIl#3wj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQOOBmI$2T`%0#N9sr;B5V#`&$2_69OL^0eA}UO#yC zfmlc8BPoR?f-#KZfsDpwoJRy6i^PjcH_mI0y)XIfM9$lcvai2Y*78)a$VDs{Pk7>$ za^SX!@Ar3pE*tK@{b41yld-mhA$>u|gUrU2;$C}#1E(+AX0(zRk)78&qol`;+0QWG6p8x;= literal 0 HcmV?d00001 diff --git a/qad/icons/align-hor.png b/qad/icons/align-hor.png new file mode 100644 index 0000000000000000000000000000000000000000..a477a99b41a5c13a90070fd273187c7c3ed4671a GIT binary patch literal 992 zcmV<610Vc}P)^zRk%9mK18qq} zK~!ko?UqeUTvZgufA8Km@67-M$OJU8in!@Cropzh2n*~KZ~<*nV{l>H)HG~t*x{y< zCf!sMqe&CL5@K*=O~ZywU08+Kg{h*c)Fy2V1gu~w6TS+=%=?<_VhF>BR0kKhxWD8i zFE96=d(S!df9?g1Mx)VaG#ZUYqtWaP^6!2cuSVo!4bfLh4wZaHZD`cH>HNMEn=3j~ z_EOoQ=wDWh+BimRn$>36$_Y-@@2>7?+8b|h(|*-XW!FvnRZV;24fVUL zdz2HLqRp}&9YBi+lkq!S>S`{XY_5w{M5FkbpwM;C0zYkGZx-Un&jeINqnvE6i?!6% zTq5Il(jvlZ$C#^MM+_S$+u59`Id{6XzRb1-spUlovLDOWirx!FOza|w6$xQSOhjl? z@xH%zVd4bPK0ZEvKnQ`95-9{iN~Dy;VzEWw)2A=&`T}TJJ2~rRane3++QV56@X|g( z#xG7SFJjw*)2;Po%6H%XW^l~li18r<%E<@NWY`Gf%!@BP-hJ$Fyxj8_@Rk-x?5`xT zzpWCe{HJVvFgW}SZ~|a;^HL&&L`nlG^8uHJt=GE}wg0*j50|C@ICeN*v6N1C-?%xQ zqKRInwx$BUa+#c)*w#98^N?{jYQQ&! zXCA2TTX%Wqcq`?lWraKbVR}t(UfF!^2nnPV>ndPMsIDn|jfV^H-3{hv9?*?p41-z; zU_d!E(mQsW;(=1mb-Y1Ev;?kRgT8(KQ>DJkLChbdg|-HVQCEhL`0>Lqp71 z;o$vfDKQa|WD5)6lNI~Vh=^oj3hrECW@t#hMVK%7I&dESlo(Y3&so3DE?J|KN$V+P znEk;m_ufw2#MXgG?0(XW-=8+SJ>R&(SDvR|e;SQOqtR$I8jVKtf8j3~pfvF2#7}1c O0000{XE)7O>#9+w~0DgvSpFfS&p_!e+TCSHQS|T=jptzdv?`?Z0b37&~NIp7B1-D+GF&!PC{xWt~$(69BVWhO__x literal 0 HcmV?d00001 diff --git a/qad/icons/align-top-left.png b/qad/icons/align-top-left.png new file mode 100644 index 0000000000000000000000000000000000000000..38b22a14888edf979bb044d51f2a358a0b7ea2c0 GIT binary patch literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^(m>3`!3HE<<5aVO6kC$Fy9>jA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS#w$0f(kVtgPqHkE;aQNh#2F~s8Z)=9R0M;v%s=f7=H zyJR+TMKP0?iq)^R-xYQ`T76?%X~7tE(ZTWPHJQYn4pmEXR1Wkf)otQst zb=N#@Z{t_mbnMgX)U8pmrLoU717!M-m)`%bZrWn~@g?7`WgTe~DWM4f{rj6s literal 0 HcmV?d00001 diff --git a/qad/icons/align-top-right.png b/qad/icons/align-top-right.png new file mode 100644 index 0000000000000000000000000000000000000000..2232cacc82ca169c07559c49873ce8a949c141ed GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^(m>3`!3HE<<5aVO6kC$Fy9>jA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS#w$0f(kVzz;Qwr9aNZt^njIvX)ka}`rF4` z*Ia)sZX9h`TVpbP=Hrh$UhR6Pqil3ET&5rroePWLNAcCWHf-|endEv+AoBXHlR2Ey6BtY!7uO7(ZFx%FPF~4=8sX-of`K({6tK fzu@|LLf?4T#Z5B&V*gGI7+egVu6{1-oD!MaN`Ef7zPK5ITqN& z1b?C$AD~}Eu)TMl-@fj>7q^?qRR_FkpnS-9tNfv>n~kza{B< zOW0(1=4m2Dk8QIvlxdga{NbsF1JL%E66Njh?|tI^H+S_Wb*Z?MO_MEUShpT}dobto zblv<*+@Qml;EMA6=r`mSKq3*@{X+YrClBoGiig7jJGWR>A6o@)y+PcFsFRnj7`Z%r z-cSHCB#*?Rt5O#xu9Gih>FZouRsZ$35KlsEH7TiUhiNo`f^8oi`RQV-Q&OPZ(|w%- zRRqIdhHfFmL19Yth)ny{uYUkTi{~q9?2CQ?Q~_wFp7%zI!!F=wKoIo^1G-r|FGe&} zkFM$i5RTUV+`?vn01Q*F1!&O&q`-q*C`bwjy|!6th~NOMq%{HlYYWw>-O*D&Ty9g! z#_?MDWp25Qrmf78@@-)7A$1=EA2qrQ?VX;UepU#9loBZfLQ15Rq*AGD5CEtQUP^?J zNU0&E2+ktDH}lK0e_x3}0SGA&Lf-#^rGU8WI`XbNiC`&kZ^kPNIA974r&6hh-Ti#g zj9e=a$k=r3kxy4gjMtU2a6F5UgnZdJd;QqV{-A8;x{vg2<+Z1DdN$0luWJsVySW=} z0{mY9T-&WFQka9!i%#$zEtI09`-vO6QjDHL)1^Lbmpt`Kq%vp5(Kc zG>l$~j+K3i%)S9AN1e(Ra_zgjJ5u4WU@2GqhB43&mV(K1+*Y>tp>Jmo-xluU+V5AV z=4O`)i+vrBt&g~Fx$?-DNJ2=5GiO=+c}yO*9qpW7k9__;vral5o8{!xwfWLgF|)00 zW5Udr=E;^a2mvEsac6v#<47^YH@4ky3IK3bDW23WPF-8DGNs&eiC8&uYoWmTF*3jX z$_Wfk^PRsb2ldI7sH7Tr$4i#S?OEPMF~pDfo-YyjWRJkx-+3=XJp;C|B>(^b07*qo IM6N<$f*1Pm5C8xG literal 0 HcmV?d00001 diff --git a/qad/icons/alpha.png b/qad/icons/alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..543566938cf5681db007530efc6b64c4ae67c096 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPaBR`)C--V~^b^?X8JzX3_G|ngA*^(*DZ1&*w>+aAw xosBLAs~RN^{P_RBevQy<^L#m8)nAzm45u$~80FZyPX%gY@O1TaS?83{1ONw+E@}V( literal 0 HcmV?d00001 diff --git a/qad/icons/archive-extract.png b/qad/icons/archive-extract.png new file mode 100644 index 0000000000000000000000000000000000000000..aa7b1fa1743f1bfbfdcab8a9dc2531208234c799 GIT binary patch literal 626 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~&H|6fVxZ#d zAk65bF}ngN$X?><>&kwUNlZvidizCNPoN&w0G|+7pcH-(6B82~8=H}tk)DyBUywgx z!i0&FKwvTuOqnus)~q>m=FDHPU?C7JTC{la;w4L#EC+%WD^>%+nl&3XY}mYc^R{i< z_JF`%AUJT~z~RG(Pn^4W^5n@=r%s)}eD%`h%h#@7zj+G;?%cU^_wL>M_wPS=@Zj;| z$4{R=efI3x^A{lS^3|)CuU@|bg4eHKzX5}{Z{NNHgZCit2?#y|0f_kW<;&NvU%!3( z_Wk?!A3*RE41WLl_3PK~-@pI-`STYD{(->%|NoncRxJjGfy*VR{6VV@&dPcM0R-ec1`*obq&W43UszJ$TUTu!Bh3#rOAqD&O=lKc>|o zUAUM-?}*qhF1x(=MQ*!-HM*KKLIs_JWTK_gY}|J+OwKjFpdNVd!12GL<UVN*UyPkIYsOQzD2TA{GuZShC zui~BV&0@v-E0p8#DHf(DaT;$T3LF|(*LzuinZm;|V(W2OTNt;_msIW!n2rPbRim<2O<%;x#PU*+N!kT6X;9h3+>UHx3vIVCg!0ObWW Ay#N3J literal 0 HcmV?d00001 diff --git a/qad/icons/archive-insert-directory.png b/qad/icons/archive-insert-directory.png new file mode 100644 index 0000000000000000000000000000000000000000..06722056a99c86b7011621051bacfac6797d666d GIT binary patch literal 588 zcmV-S0<-;zP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L0Nr%}0Nr%~tcSyc00007bV*G`2iXD^ z5D63^X>cF_00GQNL_t(|+NG1fOB_KQ#ou>kc5X+{sCP;HdFH?$Tp2;${D@?d6) zna|_R8wUR?GSlFD#|I!T?R^F?^6_&SS{tRFyfiV4oiRh-!3rz6xNC7D@VAqCNczD6YKIcm|~NeLUyA&HnE zl7ivKpCWV(&37g&7*-gVGeX?1p5VM>tx;wSTfTy{7~<;RaQ7_>{T%{E-+%kaorEx~ zF@PNzpvnu}O-U?mzlqLT810(Ex>JB*qYfA;$szdF4WyGCT?r12sI;9mG}hH)ECmc@ zY@B+koS>v)jN7_Wbb;rqW7s)%aHq8mMIB;t?J-jEZoJ4$Yauy(%e($Sd%^}?(Kcg* z&8!1A$V1tHQXE^kT?DtaDSns6->%$GcJ$1thUPRy!X;(eY}`xR&lq?4V+omX|mX$dS6{%PE2D<;ickfNXOv5~p6lPl4rDN&$