From 642813f6b3938ef06901c37bec2f425bc7f024bc Mon Sep 17 00:00:00 2001 From: methylDragon Date: Fri, 6 May 2022 15:05:34 -0700 Subject: [PATCH 1/4] Move header files with git mv (#395) Signed-off-by: methylDragon --- include/{ignition => gz}/CMakeLists.txt | 0 include/{ignition => gz}/gui/Application.hh | 0 include/{ignition => gz}/gui/CMakeLists.txt | 0 include/{ignition => gz}/gui/Conversions.hh | 0 include/{ignition => gz}/gui/Dialog.hh | 0 include/{ignition => gz}/gui/DragDropModel.hh | 0 include/{ignition => gz}/gui/Enums.hh | 0 include/{ignition => gz}/gui/GuiEvents.hh | 0 include/{ignition => gz}/gui/Helpers.hh | 0 include/{ignition => gz}/gui/MainWindow.hh | 0 include/{ignition => gz}/gui/PlottingInterface.hh | 0 include/{ignition => gz}/gui/Plugin.hh | 0 include/{ignition => gz}/gui/SearchModel.hh | 0 include/{ignition => gz}/gui/config.hh.in | 0 include/{ignition/gui/ign.hh => gz/gui/gz.hh} | 0 .../gui/gz_auto_headers.hh.in} | 0 include/{ignition => gz}/gui/qml/Chart.qml | 0 .../gui/qml/IgnCard.qml => gz/gui/qml/GzCard.qml} | 0 .../gui/qml/GzCardSettings.qml} | 0 .../qml/IgnHelpers.qml => gz/gui/qml/GzHelpers.qml} | 0 .../qml/IgnRulers.qml => gz/gui/qml/GzRulers.qml} | 0 .../IgnSnackBar.qml => gz/gui/qml/GzSnackBar.qml} | 0 .../gui/qml/GzSortFilterModel.qml} | 0 .../qml/IgnSpinBox.qml => gz/gui/qml/GzSpinBox.qml} | 0 .../gui/qml/IgnSplit.qml => gz/gui/qml/GzSplit.qml} | 0 include/{ignition => gz}/gui/qml/Main.qml | 0 .../{ignition => gz}/gui/qml/PlottingInterface.qml | 0 include/{ignition => gz}/gui/qml/PluginMenu.qml | 0 include/{ignition => gz}/gui/qml/SideDrawer.qml | 0 .../{ignition => gz}/gui/qml/StandaloneDialog.qml | 0 include/{ignition => gz}/gui/qml/StyleDialog.qml | 0 include/{ignition => gz}/gui/qml/images/drawer.png | Bin .../{ignition => gz}/gui/qml/images/export_icon.png | Bin .../gui/qml/images/gz_logo_50x50.png} | Bin include/{ignition => gz}/gui/qml/images/menu.png | Bin include/{ignition => gz}/gui/qml/images/search.svg | 0 include/{ignition => gz}/gui/qml/qmldir | 0 include/{ignition => gz}/gui/qt.h | 0 include/{ignition => gz}/gui/qtquickcontrols2.conf | 0 include/{ignition => gz}/gui/resources.qrc | 0 40 files changed, 0 insertions(+), 0 deletions(-) rename include/{ignition => gz}/CMakeLists.txt (100%) rename include/{ignition => gz}/gui/Application.hh (100%) rename include/{ignition => gz}/gui/CMakeLists.txt (100%) rename include/{ignition => gz}/gui/Conversions.hh (100%) rename include/{ignition => gz}/gui/Dialog.hh (100%) rename include/{ignition => gz}/gui/DragDropModel.hh (100%) rename include/{ignition => gz}/gui/Enums.hh (100%) rename include/{ignition => gz}/gui/GuiEvents.hh (100%) rename include/{ignition => gz}/gui/Helpers.hh (100%) rename include/{ignition => gz}/gui/MainWindow.hh (100%) rename include/{ignition => gz}/gui/PlottingInterface.hh (100%) rename include/{ignition => gz}/gui/Plugin.hh (100%) rename include/{ignition => gz}/gui/SearchModel.hh (100%) rename include/{ignition => gz}/gui/config.hh.in (100%) rename include/{ignition/gui/ign.hh => gz/gui/gz.hh} (100%) rename include/{ignition/gui/ign_auto_headers.hh.in => gz/gui/gz_auto_headers.hh.in} (100%) rename include/{ignition => gz}/gui/qml/Chart.qml (100%) rename include/{ignition/gui/qml/IgnCard.qml => gz/gui/qml/GzCard.qml} (100%) rename include/{ignition/gui/qml/IgnCardSettings.qml => gz/gui/qml/GzCardSettings.qml} (100%) rename include/{ignition/gui/qml/IgnHelpers.qml => gz/gui/qml/GzHelpers.qml} (100%) rename include/{ignition/gui/qml/IgnRulers.qml => gz/gui/qml/GzRulers.qml} (100%) rename include/{ignition/gui/qml/IgnSnackBar.qml => gz/gui/qml/GzSnackBar.qml} (100%) rename include/{ignition/gui/qml/IgnSortFilterModel.qml => gz/gui/qml/GzSortFilterModel.qml} (100%) rename include/{ignition/gui/qml/IgnSpinBox.qml => gz/gui/qml/GzSpinBox.qml} (100%) rename include/{ignition/gui/qml/IgnSplit.qml => gz/gui/qml/GzSplit.qml} (100%) rename include/{ignition => gz}/gui/qml/Main.qml (100%) rename include/{ignition => gz}/gui/qml/PlottingInterface.qml (100%) rename include/{ignition => gz}/gui/qml/PluginMenu.qml (100%) rename include/{ignition => gz}/gui/qml/SideDrawer.qml (100%) rename include/{ignition => gz}/gui/qml/StandaloneDialog.qml (100%) rename include/{ignition => gz}/gui/qml/StyleDialog.qml (100%) rename include/{ignition => gz}/gui/qml/images/drawer.png (100%) rename include/{ignition => gz}/gui/qml/images/export_icon.png (100%) rename include/{ignition/gui/qml/images/ignition_logo_50x50.png => gz/gui/qml/images/gz_logo_50x50.png} (100%) rename include/{ignition => gz}/gui/qml/images/menu.png (100%) rename include/{ignition => gz}/gui/qml/images/search.svg (100%) rename include/{ignition => gz}/gui/qml/qmldir (100%) rename include/{ignition => gz}/gui/qt.h (100%) rename include/{ignition => gz}/gui/qtquickcontrols2.conf (100%) rename include/{ignition => gz}/gui/resources.qrc (100%) diff --git a/include/ignition/CMakeLists.txt b/include/gz/CMakeLists.txt similarity index 100% rename from include/ignition/CMakeLists.txt rename to include/gz/CMakeLists.txt diff --git a/include/ignition/gui/Application.hh b/include/gz/gui/Application.hh similarity index 100% rename from include/ignition/gui/Application.hh rename to include/gz/gui/Application.hh diff --git a/include/ignition/gui/CMakeLists.txt b/include/gz/gui/CMakeLists.txt similarity index 100% rename from include/ignition/gui/CMakeLists.txt rename to include/gz/gui/CMakeLists.txt diff --git a/include/ignition/gui/Conversions.hh b/include/gz/gui/Conversions.hh similarity index 100% rename from include/ignition/gui/Conversions.hh rename to include/gz/gui/Conversions.hh diff --git a/include/ignition/gui/Dialog.hh b/include/gz/gui/Dialog.hh similarity index 100% rename from include/ignition/gui/Dialog.hh rename to include/gz/gui/Dialog.hh diff --git a/include/ignition/gui/DragDropModel.hh b/include/gz/gui/DragDropModel.hh similarity index 100% rename from include/ignition/gui/DragDropModel.hh rename to include/gz/gui/DragDropModel.hh diff --git a/include/ignition/gui/Enums.hh b/include/gz/gui/Enums.hh similarity index 100% rename from include/ignition/gui/Enums.hh rename to include/gz/gui/Enums.hh diff --git a/include/ignition/gui/GuiEvents.hh b/include/gz/gui/GuiEvents.hh similarity index 100% rename from include/ignition/gui/GuiEvents.hh rename to include/gz/gui/GuiEvents.hh diff --git a/include/ignition/gui/Helpers.hh b/include/gz/gui/Helpers.hh similarity index 100% rename from include/ignition/gui/Helpers.hh rename to include/gz/gui/Helpers.hh diff --git a/include/ignition/gui/MainWindow.hh b/include/gz/gui/MainWindow.hh similarity index 100% rename from include/ignition/gui/MainWindow.hh rename to include/gz/gui/MainWindow.hh diff --git a/include/ignition/gui/PlottingInterface.hh b/include/gz/gui/PlottingInterface.hh similarity index 100% rename from include/ignition/gui/PlottingInterface.hh rename to include/gz/gui/PlottingInterface.hh diff --git a/include/ignition/gui/Plugin.hh b/include/gz/gui/Plugin.hh similarity index 100% rename from include/ignition/gui/Plugin.hh rename to include/gz/gui/Plugin.hh diff --git a/include/ignition/gui/SearchModel.hh b/include/gz/gui/SearchModel.hh similarity index 100% rename from include/ignition/gui/SearchModel.hh rename to include/gz/gui/SearchModel.hh diff --git a/include/ignition/gui/config.hh.in b/include/gz/gui/config.hh.in similarity index 100% rename from include/ignition/gui/config.hh.in rename to include/gz/gui/config.hh.in diff --git a/include/ignition/gui/ign.hh b/include/gz/gui/gz.hh similarity index 100% rename from include/ignition/gui/ign.hh rename to include/gz/gui/gz.hh diff --git a/include/ignition/gui/ign_auto_headers.hh.in b/include/gz/gui/gz_auto_headers.hh.in similarity index 100% rename from include/ignition/gui/ign_auto_headers.hh.in rename to include/gz/gui/gz_auto_headers.hh.in diff --git a/include/ignition/gui/qml/Chart.qml b/include/gz/gui/qml/Chart.qml similarity index 100% rename from include/ignition/gui/qml/Chart.qml rename to include/gz/gui/qml/Chart.qml diff --git a/include/ignition/gui/qml/IgnCard.qml b/include/gz/gui/qml/GzCard.qml similarity index 100% rename from include/ignition/gui/qml/IgnCard.qml rename to include/gz/gui/qml/GzCard.qml diff --git a/include/ignition/gui/qml/IgnCardSettings.qml b/include/gz/gui/qml/GzCardSettings.qml similarity index 100% rename from include/ignition/gui/qml/IgnCardSettings.qml rename to include/gz/gui/qml/GzCardSettings.qml diff --git a/include/ignition/gui/qml/IgnHelpers.qml b/include/gz/gui/qml/GzHelpers.qml similarity index 100% rename from include/ignition/gui/qml/IgnHelpers.qml rename to include/gz/gui/qml/GzHelpers.qml diff --git a/include/ignition/gui/qml/IgnRulers.qml b/include/gz/gui/qml/GzRulers.qml similarity index 100% rename from include/ignition/gui/qml/IgnRulers.qml rename to include/gz/gui/qml/GzRulers.qml diff --git a/include/ignition/gui/qml/IgnSnackBar.qml b/include/gz/gui/qml/GzSnackBar.qml similarity index 100% rename from include/ignition/gui/qml/IgnSnackBar.qml rename to include/gz/gui/qml/GzSnackBar.qml diff --git a/include/ignition/gui/qml/IgnSortFilterModel.qml b/include/gz/gui/qml/GzSortFilterModel.qml similarity index 100% rename from include/ignition/gui/qml/IgnSortFilterModel.qml rename to include/gz/gui/qml/GzSortFilterModel.qml diff --git a/include/ignition/gui/qml/IgnSpinBox.qml b/include/gz/gui/qml/GzSpinBox.qml similarity index 100% rename from include/ignition/gui/qml/IgnSpinBox.qml rename to include/gz/gui/qml/GzSpinBox.qml diff --git a/include/ignition/gui/qml/IgnSplit.qml b/include/gz/gui/qml/GzSplit.qml similarity index 100% rename from include/ignition/gui/qml/IgnSplit.qml rename to include/gz/gui/qml/GzSplit.qml diff --git a/include/ignition/gui/qml/Main.qml b/include/gz/gui/qml/Main.qml similarity index 100% rename from include/ignition/gui/qml/Main.qml rename to include/gz/gui/qml/Main.qml diff --git a/include/ignition/gui/qml/PlottingInterface.qml b/include/gz/gui/qml/PlottingInterface.qml similarity index 100% rename from include/ignition/gui/qml/PlottingInterface.qml rename to include/gz/gui/qml/PlottingInterface.qml diff --git a/include/ignition/gui/qml/PluginMenu.qml b/include/gz/gui/qml/PluginMenu.qml similarity index 100% rename from include/ignition/gui/qml/PluginMenu.qml rename to include/gz/gui/qml/PluginMenu.qml diff --git a/include/ignition/gui/qml/SideDrawer.qml b/include/gz/gui/qml/SideDrawer.qml similarity index 100% rename from include/ignition/gui/qml/SideDrawer.qml rename to include/gz/gui/qml/SideDrawer.qml diff --git a/include/ignition/gui/qml/StandaloneDialog.qml b/include/gz/gui/qml/StandaloneDialog.qml similarity index 100% rename from include/ignition/gui/qml/StandaloneDialog.qml rename to include/gz/gui/qml/StandaloneDialog.qml diff --git a/include/ignition/gui/qml/StyleDialog.qml b/include/gz/gui/qml/StyleDialog.qml similarity index 100% rename from include/ignition/gui/qml/StyleDialog.qml rename to include/gz/gui/qml/StyleDialog.qml diff --git a/include/ignition/gui/qml/images/drawer.png b/include/gz/gui/qml/images/drawer.png similarity index 100% rename from include/ignition/gui/qml/images/drawer.png rename to include/gz/gui/qml/images/drawer.png diff --git a/include/ignition/gui/qml/images/export_icon.png b/include/gz/gui/qml/images/export_icon.png similarity index 100% rename from include/ignition/gui/qml/images/export_icon.png rename to include/gz/gui/qml/images/export_icon.png diff --git a/include/ignition/gui/qml/images/ignition_logo_50x50.png b/include/gz/gui/qml/images/gz_logo_50x50.png similarity index 100% rename from include/ignition/gui/qml/images/ignition_logo_50x50.png rename to include/gz/gui/qml/images/gz_logo_50x50.png diff --git a/include/ignition/gui/qml/images/menu.png b/include/gz/gui/qml/images/menu.png similarity index 100% rename from include/ignition/gui/qml/images/menu.png rename to include/gz/gui/qml/images/menu.png diff --git a/include/ignition/gui/qml/images/search.svg b/include/gz/gui/qml/images/search.svg similarity index 100% rename from include/ignition/gui/qml/images/search.svg rename to include/gz/gui/qml/images/search.svg diff --git a/include/ignition/gui/qml/qmldir b/include/gz/gui/qml/qmldir similarity index 100% rename from include/ignition/gui/qml/qmldir rename to include/gz/gui/qml/qmldir diff --git a/include/ignition/gui/qt.h b/include/gz/gui/qt.h similarity index 100% rename from include/ignition/gui/qt.h rename to include/gz/gui/qt.h diff --git a/include/ignition/gui/qtquickcontrols2.conf b/include/gz/gui/qtquickcontrols2.conf similarity index 100% rename from include/ignition/gui/qtquickcontrols2.conf rename to include/gz/gui/qtquickcontrols2.conf diff --git a/include/ignition/gui/resources.qrc b/include/gz/gui/resources.qrc similarity index 100% rename from include/ignition/gui/resources.qrc rename to include/gz/gui/resources.qrc From d2caef860b5482d7a9797afc5f9a1c2c2db7c69b Mon Sep 17 00:00:00 2001 From: methylDragon Date: Fri, 6 May 2022 15:05:38 -0700 Subject: [PATCH 2/4] Create redirection aliases (#395) Signed-off-by: methylDragon --- include/ignition/gui.hh | 18 + include/ignition/gui/Application.hh | 18 + include/ignition/gui/Conversions.hh | 18 + include/ignition/gui/Dialog.hh | 18 + include/ignition/gui/DragDropModel.hh | 18 + include/ignition/gui/Enums.hh | 18 + include/ignition/gui/Export.hh | 18 + include/ignition/gui/GuiEvents.hh | 18 + include/ignition/gui/Helpers.hh | 18 + include/ignition/gui/MainWindow.hh | 18 + include/ignition/gui/PlottingInterface.hh | 18 + include/ignition/gui/Plugin.hh | 18 + include/ignition/gui/SearchModel.hh | 18 + include/ignition/gui/config.hh | 18 + include/ignition/gui/ign.hh | 18 + include/ignition/gui/ign_auto_headers.hh | 18 + include/ignition/gui/qml/Chart.qml | 740 ++++++++++++++++++ include/ignition/gui/qml/IgnCard.qml | 704 +++++++++++++++++ include/ignition/gui/qml/IgnCardSettings.qml | 222 ++++++ include/ignition/gui/qml/IgnHelpers.qml | 42 + include/ignition/gui/qml/IgnRulers.qml | 270 +++++++ include/ignition/gui/qml/IgnSnackBar.qml | 169 ++++ .../ignition/gui/qml/IgnSortFilterModel.qml | 86 ++ include/ignition/gui/qml/IgnSpinBox.qml | 29 + include/ignition/gui/qml/IgnSplit.qml | 385 +++++++++ include/ignition/gui/qml/Main.qml | 382 +++++++++ .../ignition/gui/qml/PlottingInterface.qml | 625 +++++++++++++++ include/ignition/gui/qml/PluginMenu.qml | 118 +++ include/ignition/gui/qml/SideDrawer.qml | 110 +++ include/ignition/gui/qml/StandaloneDialog.qml | 23 + include/ignition/gui/qml/StyleDialog.qml | 409 ++++++++++ include/ignition/gui/qml/images/drawer.png | Bin 0 -> 97 bytes .../ignition/gui/qml/images/export_icon.png | Bin 0 -> 5572 bytes .../gui/qml/images/ignition_logo_50x50.png | Bin 0 -> 4336 bytes include/ignition/gui/qml/images/menu.png | Bin 0 -> 123 bytes include/ignition/gui/qml/images/search.svg | 63 ++ include/ignition/gui/qml/qmldir | 3 + include/ignition/gui/qt.h | 18 + include/ignition/gui/qtquickcontrols2.conf | 7 + include/ignition/gui/resources.qrc | 47 ++ 40 files changed, 4740 insertions(+) create mode 100644 include/ignition/gui.hh create mode 100644 include/ignition/gui/Application.hh create mode 100644 include/ignition/gui/Conversions.hh create mode 100644 include/ignition/gui/Dialog.hh create mode 100644 include/ignition/gui/DragDropModel.hh create mode 100644 include/ignition/gui/Enums.hh create mode 100644 include/ignition/gui/Export.hh create mode 100644 include/ignition/gui/GuiEvents.hh create mode 100644 include/ignition/gui/Helpers.hh create mode 100644 include/ignition/gui/MainWindow.hh create mode 100644 include/ignition/gui/PlottingInterface.hh create mode 100644 include/ignition/gui/Plugin.hh create mode 100644 include/ignition/gui/SearchModel.hh create mode 100644 include/ignition/gui/config.hh create mode 100644 include/ignition/gui/ign.hh create mode 100644 include/ignition/gui/ign_auto_headers.hh create mode 100644 include/ignition/gui/qml/Chart.qml create mode 100644 include/ignition/gui/qml/IgnCard.qml create mode 100644 include/ignition/gui/qml/IgnCardSettings.qml create mode 100644 include/ignition/gui/qml/IgnHelpers.qml create mode 100644 include/ignition/gui/qml/IgnRulers.qml create mode 100644 include/ignition/gui/qml/IgnSnackBar.qml create mode 100644 include/ignition/gui/qml/IgnSortFilterModel.qml create mode 100644 include/ignition/gui/qml/IgnSpinBox.qml create mode 100644 include/ignition/gui/qml/IgnSplit.qml create mode 100644 include/ignition/gui/qml/Main.qml create mode 100644 include/ignition/gui/qml/PlottingInterface.qml create mode 100644 include/ignition/gui/qml/PluginMenu.qml create mode 100644 include/ignition/gui/qml/SideDrawer.qml create mode 100644 include/ignition/gui/qml/StandaloneDialog.qml create mode 100644 include/ignition/gui/qml/StyleDialog.qml create mode 100644 include/ignition/gui/qml/images/drawer.png create mode 100644 include/ignition/gui/qml/images/export_icon.png create mode 100644 include/ignition/gui/qml/images/ignition_logo_50x50.png create mode 100644 include/ignition/gui/qml/images/menu.png create mode 100644 include/ignition/gui/qml/images/search.svg create mode 100644 include/ignition/gui/qml/qmldir create mode 100644 include/ignition/gui/qt.h create mode 100644 include/ignition/gui/qtquickcontrols2.conf create mode 100644 include/ignition/gui/resources.qrc diff --git a/include/ignition/gui.hh b/include/ignition/gui.hh new file mode 100644 index 000000000..93bc53865 --- /dev/null +++ b/include/ignition/gui.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Application.hh b/include/ignition/gui/Application.hh new file mode 100644 index 000000000..212530eb8 --- /dev/null +++ b/include/ignition/gui/Application.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Conversions.hh b/include/ignition/gui/Conversions.hh new file mode 100644 index 000000000..bef1ed03f --- /dev/null +++ b/include/ignition/gui/Conversions.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Dialog.hh b/include/ignition/gui/Dialog.hh new file mode 100644 index 000000000..c3ae6e816 --- /dev/null +++ b/include/ignition/gui/Dialog.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/DragDropModel.hh b/include/ignition/gui/DragDropModel.hh new file mode 100644 index 000000000..dca307f4f --- /dev/null +++ b/include/ignition/gui/DragDropModel.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Enums.hh b/include/ignition/gui/Enums.hh new file mode 100644 index 000000000..998c59bd3 --- /dev/null +++ b/include/ignition/gui/Enums.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Export.hh b/include/ignition/gui/Export.hh new file mode 100644 index 000000000..968a92aed --- /dev/null +++ b/include/ignition/gui/Export.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/GuiEvents.hh b/include/ignition/gui/GuiEvents.hh new file mode 100644 index 000000000..ab3bee6dd --- /dev/null +++ b/include/ignition/gui/GuiEvents.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Helpers.hh b/include/ignition/gui/Helpers.hh new file mode 100644 index 000000000..95c589be9 --- /dev/null +++ b/include/ignition/gui/Helpers.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/MainWindow.hh b/include/ignition/gui/MainWindow.hh new file mode 100644 index 000000000..14d96ba33 --- /dev/null +++ b/include/ignition/gui/MainWindow.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/PlottingInterface.hh b/include/ignition/gui/PlottingInterface.hh new file mode 100644 index 000000000..46b8ce427 --- /dev/null +++ b/include/ignition/gui/PlottingInterface.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/Plugin.hh b/include/ignition/gui/Plugin.hh new file mode 100644 index 000000000..49a95eef7 --- /dev/null +++ b/include/ignition/gui/Plugin.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/SearchModel.hh b/include/ignition/gui/SearchModel.hh new file mode 100644 index 000000000..1bd7afe24 --- /dev/null +++ b/include/ignition/gui/SearchModel.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/config.hh b/include/ignition/gui/config.hh new file mode 100644 index 000000000..75005186e --- /dev/null +++ b/include/ignition/gui/config.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/ign.hh b/include/ignition/gui/ign.hh new file mode 100644 index 000000000..5231fcac5 --- /dev/null +++ b/include/ignition/gui/ign.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/ign_auto_headers.hh b/include/ignition/gui/ign_auto_headers.hh new file mode 100644 index 000000000..45d9db296 --- /dev/null +++ b/include/ignition/gui/ign_auto_headers.hh @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/qml/Chart.qml b/include/ignition/gui/qml/Chart.qml new file mode 100644 index 000000000..cd3a259d7 --- /dev/null +++ b/include/ignition/gui/qml/Chart.qml @@ -0,0 +1,740 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtCharts 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 + +Rectangle { + id: main + + /** + subscribe to a field || register the chart to the subscribed field + */ + signal subscribe(real Id, string topic, string path); + /** + unsubscribe from a field || unregister the chart from the subscribed field + */ + signal unSubscribe(real Id, string topic, string path); + /** + register the chart to the component attribute + */ + signal componentSubscribe(string entity, string typeId, string type, string attribute, real Id); + /** + unregister the chart from the component attribute + */ + signal componentUnSubscribe(string entity, string typeId, string attribute, real Id); + /** + chart is clicked to swap the chart mode + from small chart to the main chart in multi charts mode + Id: chartID + */ + signal clicked(real Id); + + /** + Points Limitation: max points of each series + When points exceed that limit, some points from begining are deleted + */ + property int maxPoints: 10000 + /** + Chart ID + */ + property int chartID: -1 + /** + True if the chart is a small chart in the multi charts mode + */ + property bool multiChartsMode: false + + /** + add point to a field graph + _fieldID field key or path + _x x coordinate of the point + _y y coordinate of the point + */ + function appendPoint(_fieldID, _x, _y) + { + chart.appendPoint(_fieldID, _x, _y); + } + /** + set the chart opacity + _opacity opacity value + */ + function setChartOpacity(_opacity) + { + chart.opacity = _opacity; + } + /** + move chart to the right + */ + function moveChart() + { + chart.scrollRight(chart.width * shiftAmount.value); + } + /** + change the PlotArea size to fill the chart or the reverse case + */ + function fillPlotInOrOut() + { + if (multiChartsMode) + { + chart.legend.visible = false + chart.margins.top = 0 + chart.margins.bottom = 0 + chart.margins.right = 0 + chart.margins.left = 0 + } + else + { + chart.legend.visible = true + chart.margins.top = 20 + chart.margins.bottom = 20 + chart.margins.right = 20 + chart.margins.left = 20 + } + } + + /** + get the chart object + */ + function getChart() + { + return chart; + } + + /** + fix OpenGL Disappear problem when the plugin is docked + */ + function fixOpenGL() + { + lineSeries.useOpenGL = false; + lineSeries.useOpenGL = true; + } + + + color: "transparent" + + // =============== Fields info Rectangle ================ + Rectangle { + id: infoRect + + /** + Handle Dropping Plot Data (Fields or Components) + text dropped text of the dragged item + */ + function onDrop(text) + { + // topic and path is separated with ',' + if (text.search(",") === -1) + return; + + // check if the dropped item is component + if (infoRect.isComponentDrop(text)) + { + var textList = text.split(","); + var entity = textList[1]; + var typeId = textList[2]; + var type = textList[3]; + var attribute = textList[4]; + var typeName = textList[5]; + + var componentID = entity + "," + typeId + "," + attribute; + var displayText = entity + "," + typeName + "," + attribute; + + componentSubscribe(entity, typeId, type, attribute, chartID); + + // if the field is already attached + if (componentID in chart.serieses) + return; + + chart.addSeries(componentID, displayText); + infoRect.addComponent(entity, typeId, type, attribute, typeName, displayText); + } + // the dropped item is a field + else + { + var topic_path = text.split(","); + var topic = topic_path[0]; + var path = topic_path[1]; + + // Field Full Path ID + var ID = topic + "-" + path; + + // attach the chart to the subscribed field + subscribe(chartID, topic, path); + + // if the field is already attached + if (ID in chart.serieses) + return; + + // add axis series to plot the field + chart.addSeries(ID, ""); + + // add field info component + infoRect.addField(ID, topic, path); + } + guideText.visible = false; + } + + /** + add field to the fields layout + ID Chart ID + topic topic name + path field key or path + */ + function addField(ID, topic, path) + { + var field = fieldInfo.createObject(row); + field.width = 150; + field.height = Qt.binding( function() {return infoRect.height * 0.8} ); + field.y = Qt.binding( function() + { + if (infoRect.height) + return (infoRect.height - field.height)/2; + else + return 0; + } + ); + + // update field data + field.topic = topic; + field.path = path; + field.type = "Field" + } + /** + add component to the chart + entity entity ID + typeId type ID + type type of the component attribute (Pose3d, Vector3d .. etc) + */ + function addComponent(entity, typeId, type, attribute, typeName, displayText) + { + var _component = fieldInfo.createObject(row); + _component.width = 150; + _component.height = Qt.binding( function() {return infoRect.height * 0.8} ); + _component.y = Qt.binding( function() + { + if (infoRect.height) + return (infoRect.height - _component.height)/2; + else + return 0; + } + ); + + _component.entity = entity; + _component.typeId = typeId; + _component.componentType = type; + _component.attribute = attribute; + _component.typeName = typeName; + _component.displayText = displayText; + + _component.type = "Component"; + } + + /** + True if the dropped text has the component format + dropText the text dropped in the field info rect + */ + function isComponentDrop(dropText) + { + var textList = dropText.split(","); + if (textList.length < 6) + return false; + if (textList[0] !== "Component") + return false; + + return true; + } + + width: parent.width + height: (multiChartsMode) ? 0 : 50 + color: (Material.theme == Material.Light) ? Material.color(Material.Grey,Material.Shade200) + : Material.color(Material.BlueGrey, Material.Shade800) + + Text { + id: guideText + text: qsTr("Drag & Drop Plottable Fields | Components") + anchors.centerIn: parent + color: (Material.theme == Material.Light) ? "gray" : "white" + opacity: 0.3 + visible: (multiChartsMode) ? false : true + } + + // make it scrolable + ScrollView { + anchors.fill: parent + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AlwaysOff + clip: true + // Horizontal Layout for the fields + Row { + anchors.fill: parent + id:row + spacing: 10 + } + } + + DropArea { + anchors.fill: parent + onDropped: + { + var text = drop.getDataAsString("text/plain"); + infoRect.onDrop(text); + } + } + } + + // ================ Field / Component ==================== + Component { + id: fieldInfo + Rectangle { + id: component + + /** + Field or Component + */ + property string type: "" + + /** + field data: + topic name + path field key + */ + property string topic: "" + property string path: "" + + /** + component data: + entity entity ID + typeId type ID + type type of the component attribute (Pose3d, Vector3d .. etc) + attribute (X, Y, Z, Roll, ... etc) + */ + property string entity: "" + property string typeId: "" + property string componentType: "" + property string attribute: "" + property string typeName: "" + property string componentId: entity + "," + typeId + "," + attribute; + property string displayText: "" + + /** + set the field name text + */ + function setText(text) { + fieldname.text = text; + } + signal unsubscribe(string topic, string path); + + radius: width/4 + Rectangle { + height: parent.height + width: parent.width + radius: width/4 + color: Material.accentColor + clip: true + + MouseArea { + id : fieldInfoMouse + anchors.fill: parent + hoverEnabled: true + onEntered: enterAnimation.start(); + onExited: exitAnimation.start(); + } + + Text { + id: fieldname + text: (component.type === "Field") ? component.topic + "/"+ component.path : + (component.type === "Component") ? component.entity + "," + component.typeName + + "," + component.attribute : "" + color: "white" + elide: Text.ElideRight + width: parent.width * 0.9 + anchors.verticalCenter: parent.verticalCenter + leftPadding: 20; + } + + ToolTip { + delay: 1000 + timeout: 2000 + text: (component.type === "Field" ) ? component.topic + "-"+ component.path : + (component.type === "Component") ? "entity: " + component.entity + "\n" + + "typeId: " + component.typeId + "\n" + + "typeName: " + component.typeName + "\n" + + "dataType: " + component.componentType + "\n" + + "attribute: " + component.attribute : "" + visible: fieldInfoMouse.containsMouse + y: fieldInfoMouse.mouseY + x: fieldInfoMouse.mouseX + enter: null + exit: null + } + } + + Rectangle { + id: exitBtn + radius: width / 2 + height: parent.height * 0.8; + width: height + color: "red" + opacity: 0 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: parent.width * 0.05 + Text { anchors.centerIn: parent; text: "x"; color: "white"} + + MouseArea { + anchors.fill: parent + onClicked: { + exitAnimation.start(); + + // unSubscribe from the transport / Component + if (component.type === "Field") + main.unSubscribe(main.chartID, component.topic, component.path); + + else if (component.type === "Component") + main.componentUnSubscribe(component.entity, component.typeId, + component.attribute, main.chartID) + + + // delete the series points and deattache it from the chart + if (component.type === "Field") + chart.deleteSeries(component.topic + "-" + component.path) + + else if (component.type === "Component") + chart.deleteSeries(component.componentId); + + // delete the field info component + component.destroy(); + } + } + NumberAnimation { + id: enterAnimation + target: exitBtn; property: "opacity"; duration: 100 + easing.type: Easing.InOutQuad; from: 0; to: 1; + } + NumberAnimation { + id: exitAnimation + target: exitBtn; property: "opacity"; duration: 100; + easing.type: Easing.InOutQuad; from: 0.85; to: 0; + } + } + } + } + + // ================== Chart ============================ + ChartView { + id : chart + /** + all serieses, field path is the key, series is the value + */ + property var serieses: ({}) + /** + colors to give the fields different colors + */ + property var colors: (Material.theme == Material.Light) ? + ["red", "#004c6d", "#FF5D8C","#903f5c", "#7ec92a", "#a88f31", "#ff7c43" , "#62efff"] : + ["#ffa600", "#7aa6c2", "#f04c6d", "#bc5090", "#a88f31", "#7a5195", "#ffbcc3", "#7ec92a"]; + /** + current index of colors array + */ + property int indexColor: 0 + + /** + get sereieses + return: map of serieses + */ + function getAllSerieses() + { + return serieses; + } + + /** + update the text that shows the hover point value (x,y) on the mouse cursor + */ + function updateHoverText() + { + if (!hoverText.visible) + return; + + var axisWidth = xAxis.max - xAxis.min; + var axisHeight = yAxis.max - yAxis.min; + var xPos = xAxis.min + ( (chartMouse.mouseX - chart.plotArea.x) / chart.plotArea.width ) * axisWidth; + var yPos = yAxis.max - ( (chartMouse.mouseY - chart.plotArea.y) / chart.plotArea.height) * axisHeight; + hoverText.text = "(" + xPos.toFixed(2).toString() + ", " + yPos.toFixed(2).toString() + ")"; + hoverText.x = chartMouse.mouseX + 12; + hoverText.y = chartMouse.mouseY; + } + + /** + add new series + ID key of the series: path of the field of the series + */ + function addSeries(ID, seriesDisplayText) { + var seriesName = (seriesDisplayText) ? seriesDisplayText : ID + var newSeries = createSeries(ChartView.SeriesTypeLine, seriesName, xAxis, yAxis); + newSeries.useOpenGL = true; + newSeries.width = 2; + newSeries.color = chart.colors[chart.indexColor % chart.colors.length] + serieses[ID] = newSeries; + + chart.indexColor = (chart.indexColor + 1) % chart.colors.length; + } + + /** + delete a field series by its ID + ID field path + */ + function deleteSeries(ID) { + // remove the points of the series from the chart + removeSeries(serieses[ID]); + // remove the series key from the serieses map + delete serieses[ID]; + } + + /** + add point to a specific TextField + _fieldID field ID or Path + _x x of the point + _y y of the point + */ + function appendPoint(_fieldID, _x, _y) + { + if (!chart.serieses[_fieldID]) + return; + + // if this is the first point (if the chart is empty): + // set the min/max according to that point's coordinates + // note: count == 2: because chart has 1 series by default to show plotting grid + if (chart.count === 2 && chart.serieses[_fieldID].count === 0) + { + xAxis.min = _x; + xAxis.max = _x + 10; + chart.serieses[_fieldID].append(_x, _y); + return; + } + + // expand the chart boundries if needed + if (xAxis.max < _x) + { + xAxis.max = _x; + chart.scrollRight(chart.width * 0.0012); + } + + if (yAxis.max < _y) + yAxis.max = _y ; + if (yAxis.min > _y) + yAxis.min = _y ; + if (xAxis.min > _x) + xAxis.min = _x ; + + // add the point + chart.serieses[_fieldID].append(_x, _y); + + // delete the oldest point to limit the points size + if (chart.serieses[_fieldID].count > maxPoints) + chart.serieses[_fieldID].removePoints(0,1) + + chart.updateHoverText(); + } + + width: parent.width + anchors.bottom: parent.bottom + anchors.top: infoRect.bottom + + // animations + antialiasing: true + opacity: 1 + backgroundRoundness: 10 + animationOptions: ChartView.NoAnimation + + theme: (Material.theme == Material.Light) ? ChartView.ChartThemeLight: ChartView.ChartThemeDark + + Text { + id:hoverText + visible: (chartMouse.flag && !multiChartsMode && chartMouse.containsMouse) ? true : false + color: (Material.theme == Material.Light) ? "black" : Material.color(Material.Grey,Material.Shade200) + } + + MouseArea { + id:chartMouse + /** + flag to show the hover text + True if the user clicked on the CheckBox + */ + property bool flag: (hoverCheckBox.checkState === Qt.Checked) ? true : false + /** + xHold is the value of x when the user press and hold the mouse to move the plot view + */ + property double xHold: 0 + /** + xHold is the value of y when the user press and hold the mouse to move the plot view + */ + property double yHold: 0 + + anchors.fill:parent + hoverEnabled: true + cursorShape: (multiChartsMode) ? Qt.PointingHandCursor : Qt.ArrowCursor + + onEntered: { + if (multiChartsMode) + chart.opacity = 0.7; + } + onExited: { + if (multiChartsMode) + chart.opacity = 1; + } + onPressed: { + xHold = mouseX; + yHold = mouseY; + } + + /** + Drag/Move the plot view + */ + onPositionChanged: { + if (multiChartsMode) + return + + if (pressed) + { + chart.scrollLeft(mouseX - xHold) + chart.scrollUp(mouseY - yHold) + + xHold = mouseX + yHold = mouseY + } + else + chart.updateHoverText(); + + } + + onClicked: { + main.clicked(chartID); + } + + /** + zoom shift amount + */ + property double shift: 15 + + /** + Zoom + */ + onWheel:{ + if (multiChartsMode) + return + + // the center of the plot + var centerX = chart.plotArea.x + chart.plotArea.width/2 + var centerY = chart.plotArea.y + chart.plotArea.height/2 + + // the percentage of the mouseX = how it moves far away from the plot center + // ex: if the the plot width = 100 & mouseX = 75, so it moves the 50% away from the center (75-50)/50 + var factorX = (wheel.x - centerX) / (chart.plotArea.width/2); // % + // same for y but with mouseY, centerY and Height + var factorY = (wheel.y - centerY) / (chart.plotArea.height/2); // % + + + var zoomType; + if( wheel.angleDelta.y > 0) + // zoomIn + zoomType = 1; + else + // zoomOut + zoomType = -1; + + + // plot size (width & height) will always increase/decrese by 2*shift + // (imagine the size is centered with shift distance at both sides of width (same of height) ) + + // the location of zooming is determine by changing the x,y (top left corner) of the zoom rect + // x,y increase/decrease + var rect = Qt.rect(chart.plotArea.x + (factorX + 1) * shift * zoomType, + chart.plotArea.y + (factorY + 1) * shift * zoomType, + chart.plotArea.width - 2 * shift * zoomType, + chart.plotArea.height - 2 * shift * zoomType + ); + + chart.zoomIn(rect); + } + } + + DropArea { + anchors.fill: parent + onDropped: + { + var text = drop.getDataAsString("text/plain"); + infoRect.onDrop(text); + } + } + + ValueAxis { + id : yAxis + min: 0; + max: 3; + tickCount: 9 + } + + ValueAxis { + id : xAxis + min: 0 + max: 3 + tickCount: 9 + } + + // to just show the plot at begining + LineSeries { + id: lineSeries + axisX: xAxis + axisY: yAxis + visible: false + useOpenGL: true + } + + Text { + id: plotName + text: "Plot " + chartID.toString() + font.pointSize: 15 + anchors.left: parent.left + anchors.top: parent.top + anchors.margins: 20 + color: Material.color(Material.Grey, Material.Shade500) + visible: (multiChartsMode) ? false : true + } + + Text { + id: hoverName + anchors.centerIn: parent + visible: (multiChartsMode && chartMouse.containsMouse) + text: plotName.text + color: plotName.color + font.pointSize: plotName.font.pointSize + } + } + + CheckBox { + id: hoverCheckBox; + visible: (main.multiChartsMode) ? false : true + checkState: Qt.Unchecked + anchors.right: chart.right + anchors.top: chart.top + anchors.margins: 20 + text: "hover" + } +} diff --git a/include/ignition/gui/qml/IgnCard.qml b/include/ignition/gui/qml/IgnCard.qml new file mode 100644 index 000000000..c9b5031fa --- /dev/null +++ b/include/ignition/gui/qml/IgnCard.qml @@ -0,0 +1,704 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 1.4 as QQC1 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 +import QtQuick.Window 2.2 +import "qrc:/qml" + +// TODO: don't use "parent" +Pane { + /** + * Minimum length of each dimension + */ + property int minSize: 50 + + /** + * True to have a dock button + */ + property bool showDockButton: true + + /** + * True to have a close button + */ + property bool showCloseButton: true + + /** + * True to have a collapse button + */ + property bool showCollapseButton: true + + /** + * True to have a title bar + */ + property bool showTitleBar: true + + /** + * True to have draggable rulers for resizing + */ + property bool resizable: true + + /** + * True if plugin is in a standalone dialog + */ + property bool standalone: false + + /** + * The plugin name, which goes on the toolbar + */ + property alias pluginName: titleLabel.text + + /** + * ▁ + */ + property string dockIcon: "\u2581" + + /** + * ▼ + */ + property string collapseIcon: "\u25B4" + + /** + * ▲ + */ + property string expandIcon: "\u25BE" + + /** + * □ + */ + property string floatIcon: "\u25A1" + + /** + * ✕ + */ + property string closeIcon: "\u2715" + + /** + * The plugin backgroung color. Default: transparent + */ + property string cardBackground: "#00000000" + + /** + * + */ + property var backgroundItem: null + + /** + * Stores last height of plugin to expand to. + */ + property int lastHeight: 50 + + /** + * True if there's at least one anchor set for the card. + * There's no way to check the anchors themselves, so we need + * to keep track of this ourselves. + */ + property bool anchored: false + + /** + * Minimum width of the card pane + */ + property int cardMinimumWidth: 250; + + /** + * Minimum height of the card pane + */ + property int cardMinimumHeight: 250; + + /** + * Tool bar background color + */ + property string pluginToolBarColor: + typeof MainWindow === "undefined" || + MainWindow.pluginToolBarColorLight === "" || + MainWindow.pluginToolBarColorDark === "" ? + Material.accent : + (Material.theme === Material.Light) ? + MainWindow.pluginToolBarColorLight : MainWindow.pluginToolBarColorDark + + /** + * Tool bar text color + */ + property string pluginToolBarTextColor: + typeof MainWindow === "undefined" || + MainWindow.pluginToolBarTextColorLight === "" || + MainWindow.pluginToolBarTextColorDark === "" ? + Material.background : + (Material.theme === Material.Light) ? + MainWindow.pluginToolBarTextColorLight : MainWindow.pluginToolBarTextColorDark + + /** + * Close signal + */ + signal close() + + /** + * ID within QML + */ + id: cardPane + + /** + * Object name accessible from C++ + */ + objectName: "plugin" + Math.floor(Math.random() * 100000); + + // Stop scroll propagation to widgets below + MouseArea { + anchors.fill: parent + onWheel: { + wheel.accepted = true + } + } + + /** + * Callback when the parent has changed. + */ + onParentChanged: { + if (undefined === parent || null === parent) + return; + + // Bind anchors + anchors.fill = Qt.binding(function() {return parent}) + parent.height = Qt.binding(function() {return height}) + parent.width = Qt.binding(function() {return width}) + + // Keep a reference to the background + // TODO(louise) This feels hacky, the card shouldn't care about the background, + // but I haven't figured out yet how the card can tell IgnSplit to create + // a new split and add the card to it. There must be a way using signals, events + // or global functions...? + var bgItemTemp = helpers.ancestorByName(cardPane, "background") + if (bgItemTemp) + backgroundItem = bgItemTemp; + + this.syncTheFamily(); + } + + /** + * Forward the child content's size preferences to the parent split's layout + * TODO(louise) This looks really clunky, ideally the card shouldn't need + * any knowledge of splits + */ + function syncTheFamily() { + var parentSplit = helpers.ancestorByName(cardPane, /^split_item/); + + if (undefined == parentSplit) + return; + + if (content.children.length != 1) + return; + + parentSplit.Layout.minimumWidth = content.children[0].Layout.minimumWidth; + parentSplit.Layout.minimumHeight = content.children[0].Layout.minimumHeight; + } + + /** + * Clear all anchors + */ + function clearAnchors() { + cardPane.anchors.right = undefined + cardPane.anchors.left = undefined + cardPane.anchors.top = undefined + cardPane.anchors.bottom = undefined + cardPane.anchors.fill = undefined + cardPane.anchors.horizontalCenter = undefined + cardPane.anchors.verticalCenter = undefined + cardPane.anchors.baseline = undefined + + anchored = false + } + + IgnHelpers { + id: helpers + } + + // TODO(louise) Support choosing between: + // * a transparent background + // * a custom color, in which case there will be elevation + // Elevation only works if background is not transparent. +// Material.elevation: 6 + background: Rectangle { + color: "transparent" + } + + padding: 0 + + state: "docked" + + states: [ +// State { +// name: "cardWindow" +// ParentChange { +// target: cardPane; +// parent: cardWindowContent; +// x: 0 +// y: 0 +// width: cardWindowContent.width +// height: cardWindowContent.height +// } +// }, + // Floating and Docked state are the expanded states + State { + name: "docked" + }, + State { + name: "floating" + }, + // Docked collapsed state + State { + name: "docked_collapsed" + }, + // Floating collapsed state + State { + name: "floating_collapsed" + } + ] + + transitions: [ + Transition { + from: "docked" + to: "floating" + SequentialAnimation { + ScriptAction {script: leaveDockedState()} + ScriptAction {script: enterFloatingState()} + } + }, + Transition { + from: "floating" + to: "docked" + SequentialAnimation { + ScriptAction {script: leaveFloatingState()} + ScriptAction {script: enterDockedState()} + } + }, + Transition { + from: "floating" + to: "floating_collapsed" + NumberAnimation { + target: cardPane + property: "height" + duration: 200 + easing.type: Easing.OutCubic + from: cardPane.height + to: 50 + } + }, + Transition { + from: "floating_collapsed" + to: "floating" + NumberAnimation { + target: cardPane + property: "height" + duration: 200 + easing.type: Easing.InCubic + from: 50 + to: lastHeight + } + }, + Transition { + from: "floating_collapsed" + to: "docked" + SequentialAnimation { + ScriptAction {script: leaveFloatingState()} + ScriptAction {script: enterDockedState()} + } + }, + Transition { + from: "docked" + to: "docked_collapsed" + SequentialAnimation { + NumberAnimation { + target: cardPane + property: "parent.Layout.maximumHeight" + duration: 200 + easing.type: Easing.OutCubic + from: cardPane.height + to: 50 + } + ScriptAction {script: recalculateSplitSizes()} + } + }, + Transition { + from: "docked_collapsed" + to: "docked" + SequentialAnimation { + NumberAnimation { + target: cardPane + property: "parent.Layout.maximumHeight" + duration: 200 + easing.type: Easing.InCubic + from: 50 + to: backgroundItem.height + } + ScriptAction {script: recalculateSplitSizes()} + } + }, + Transition { + from: "docked_collapsed" + to: "floating" + SequentialAnimation { + ScriptAction {script: leaveDockedState()} + ScriptAction {script: enterFloatingState()} + } + }, + Transition { + from: "docked" + to: "floating_collapsed" + SequentialAnimation { + ScriptAction {script: leaveDockedState()} + ScriptAction {script: enterFloatingState()} + NumberAnimation { + target: cardPane + property: "height" + duration: 200 + easing.type: Easing.OutCubic + from: cardPane.height + to: 50 + } + } + }, + Transition { + from: "docked_collapsed" + to: "floating_collapsed" + SequentialAnimation { + ScriptAction {script: leaveDockedState()} + ScriptAction {script: enterFloatingState()} + } + }, + Transition { + from: "floating_collapsed" + to: "docked_collapsed" + SequentialAnimation { + ScriptAction {script: leaveFloatingState()} + ScriptAction {script: enterDockedState()} + } + } + ] + + /** + * Called when the docked state is entered. + */ + function enterDockedState() + { + // Add new split + var splitName = backgroundItem.addSplitItem(); + var splitItem = backgroundItem.childItems[splitName]; + + const collapsed = cardPane.height === 50 + + // Reparent to split + cardPane.parent = splitItem; + + // Retain collapsed or expanded state + cardPane.parent.Layout.minimumHeight = collapsed ? 50 : content.children[0].Layout.minimumHeight; + } + + /** + * Called when the floating state is entered. + */ + function enterFloatingState() + { + const collapsed = cardPane.parent.Layout.minimumHeight === 50; + // Reparent to main window's background + cardPane.parent = backgroundItem + + // Resize to minimum size + cardPane.clearAnchors(); + cardPane.width = content.children[0].Layout.minimumWidth; + + // Retain collapsed or expanded state + cardPane.height = collapsed ? 50 : content.children[0].Layout.minimumHeight; + lastHeight = content.children[0].Layout.minimumHeight; + } + + /** + * Called when the docked state is left. + */ + function leaveDockedState() + { + // Remove from split (delete split if needed) + backgroundItem.removeSplitItem(helpers.ancestorByName(cardPane, + /^split_item/).objectName) + } + + /** + * Called when the floating state is left. + */ + function leaveFloatingState() + { + // Do nothing + } + + /** + * Recalculate split sizes + */ + function recalculateSplitSizes() + { + backgroundItem.recalculateMinimumSizes(); + } + +// TODO(louise): re-enable window state support +// /** +// * Window for undocking +// */ +// Window { +// // TODO: resize +// width: cardPane.width; +// height: cardPane.height; +// visible: false; +// id: cardWindow +// +// Rectangle { +// id: cardWindowContent +// anchors.fill: parent +// } +// +// onClosing: { +// cardPane.state = "docked" +// } +// } + + /** + * Top toolbar + */ + ToolBar { + id: cardToolbar + objectName: "cardToolbar" + visible: cardPane.showTitleBar + Material.foreground: Material.foreground + Material.background: pluginToolBarColor + width: cardPane.width + height: cardPane.showTitleBar ? 50 : 0 + x: 0 + z: 100 + + // For drag + MouseArea { + anchors.fill: parent + drag { + target: cardPane + minimumX: 0 + minimumY: 0 + maximumX: cardPane.parent ? cardPane.parent.width - cardPane.width : cardPane.width + maximumY: cardPane.parent ? cardPane.parent.height - cardPane.height : cardPane.height + smoothed: true + } + } + + /** + * The toolbar contents + */ + RowLayout { + spacing: 0 + anchors.fill: parent + anchors.leftMargin: 10 + + Label { + id: titleLabel + font.pixelSize: 16 + color: pluginToolBarTextColor + elide: Label.ElideRight + horizontalAlignment: Qt.AlignHLeft + verticalAlignment: Qt.AlignVCenter + Layout.fillWidth: true + } + + // Dock / floating button + // TODO(louise) support window state + ToolButton { + id: dockButton + text: (cardPane.state === "docked" || cardPane.state === "docked_collapsed") ? floatIcon : dockIcon + contentItem: Text { + text: dockButton.text + font: dockButton.font + opacity: enabled ? 1.0 : 0.3 + color: cardPane.Material.background + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + visible: cardPane.showDockButton && !cardPane.standalone + onClicked: { + switch(cardPane.state) { + case "floating_collapsed": { + cardPane.state = "docked_collapsed" + break; + } + case "floating": { + cardPane.state = "docked" + break; + } + case "docked": { + cardPane.state = "floating" + break; + } + case "docked_collapsed": { + cardPane.state = "floating_collapsed" + break; + } + } + } + } + + // Collapse button + ToolButton { + id: collapseButton + visible: cardPane.showCollapseButton && !cardPane.standalone + text: cardPane.height <= 50.5 ? expandIcon : collapseIcon; + contentItem: Text { + text: collapseButton.text + font: collapseButton.font + opacity: enabled ? 1.0 : 0.3 + color: cardPane.Material.background + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + onClicked: { + switch(cardPane.state) { + case "floating_collapsed": { + cardPane.state = "floating" + break; + } + case "floating": { + // When user manually minimized the plugin using resize + if(cardPane.height === 50) { + // Handles the case when a floating plugin is loaded using config + if(lastHeight === 50) { + lastHeight = content.children[0].Layout.minimumHeight; + } + // Set state to floating collapsed and then expand for animation + cardPane.state = "floating_collapsed" + cardPane.state = "floating" + } else { + lastHeight = cardPane.height + // Set card state to collapsed + cardPane.state = "floating_collapsed" + } + break; + } + case "docked": { + cardPane.state = "docked_collapsed" + break; + } + case "docked_collapsed": { + cardPane.state = "docked" + break; + } + } + } + } + + // Close button + ToolButton { + id: closeButton + visible: cardPane.showCloseButton && !cardPane.standalone + text: closeIcon + contentItem: Text { + text: closeButton.text + font: closeButton.font + opacity: enabled ? 1.0 : 0.3 + color: cardPane.Material.background + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + onClicked: { + cardPane.close(); + } + } + } + } + + // For context menu + MouseArea { + anchors.fill: content + acceptedButtons: Qt.RightButton + onClicked: { + contextMenu.x = mouseX + contextMenu.y = mouseY + contextMenu.open() + } + } + + Menu { + id: contextMenu + transformOrigin: Menu.TopRight + MenuItem { + text: "Settings" + onTriggered: cardPane.showSettingsDialog(); + } + MenuItem { + text: "Close" + onTriggered: cardPane.close(); + } + } + + /** + * Show settings dialog + */ + function showSettingsDialog() { + settingsDialog.open() + } + + IgnCardSettings { + id: settingsDialog + modal: false + focus: true + title: pluginName + " settings" + parent: cardPane.parent + x: parent ? (parent.width - width) / 2 : 0 + y: parent ? (parent.height - height) / 2 : 0 + } + + /** + * Card contents + */ + Rectangle { + objectName: "content" + id: content + anchors.fill: parent + anchors.topMargin: cardPane.showTitleBar ? 50 : 0 + clip: true + color: cardBackground + + onChildrenChanged: { + // Set the height and width of the cardPane when child plugin is attached + if (children.length > 0) { + cardMinimumWidth = content.children[0].Layout.minimumWidth; + cardMinimumHeight = content.children[0].Layout.minimumHeight; + cardPane.width = cardMinimumWidth + cardPane.height = cardMinimumHeight + } + + cardPane.syncTheFamily() + } + + /** + * Conveniently expose card to children + */ + function card() { + return cardPane; + } + } + + IgnRulers { + anchors.fill: parent + enabled: cardPane.state === "floating" && resizable + minSize: cardPane.minSize + target: cardPane + } +} diff --git a/include/ignition/gui/qml/IgnCardSettings.qml b/include/ignition/gui/qml/IgnCardSettings.qml new file mode 100644 index 000000000..313fcf82e --- /dev/null +++ b/include/ignition/gui/qml/IgnCardSettings.qml @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import QtQuick.Window 2.2 +import QtQuick.Dialogs 1.0 +import "qrc:/qml" + +Dialog { + id: settingsDialog + + Column { + id: settingsColumn + anchors.horizontalCenter: settingsDialog.horizontalCenter + width: settingsDialog.width * 0.6 + + Switch { + id: titleSwitch + text: "Show title bar" + checked: cardPane.showTitleBar + onToggled: { + cardPane.showTitleBar = checked + // why is binding not working? + closeSwitch.enabled = checked + dockSwitch.enabled = checked + } + } + + Switch { + id: closeSwitch + text: "Show close button" + visible: !cardPane.standalone + enabled: cardPane.showTitleBar + checked: cardPane.showCloseButton + onToggled: { + cardPane.showCloseButton = checked + } + } + + Switch { + id: dockSwitch + text: "Show dock button" + visible: !cardPane.standalone + enabled: cardPane.showTitleBar + checked: cardPane.showDockButton + onToggled: { + cardPane.showDockButton = checked + } + } + + Switch { + id: collapseSwitch + text: "Show collapse button" + visible: !cardPane.standalone + enabled: cardPane.showTitleBar + checked: cardPane.showCollapseButton + onToggled: { + cardPane.showCollapseButton = checked + } + } + + Switch { + id: resizableSwitch + text: "Resizable" + visible: cardPane.state === "floating" + checked: cardPane.resizable + onToggled: { + cardPane.resizable = checked + } + } + + GridLayout { + width: parent.width + columns: 3 + visible: !cardPane.standalone + + Label { + text: "Background Color " + } + + Button { + Layout.preferredWidth: parent.width * 0.4 + onClicked: colorDialog.open() + background: Rectangle { + y: 8 + width: 50 + height: 30 + id: "bgColor" + color: cardBackground + border.color: "#000000" + border.width: 2 + } + } + } + + + GridLayout { + width: parent.width + columns: 2 + visible: cardPane.state === "floating" + + Label { + text: "Position" + font.weight: Font.DemiBold + } + + Text { + text: "" + } + + // TODO(louise) Support setting anchors from the dialog + Button { + visible: cardPane.anchored + text: "Clear anchors" + Layout.columnSpan: 2 + onClicked: { + cardPane.clearAnchors() + } + } + + IgnSpinBox { + visible: !cardPane.anchored + maximumValue: cardPane.parent ? cardPane.parent.width - cardPane.width : minSize + onVisibleChanged: value = cardPane.x + onValueChanged: { + cardPane.x = value; + } + } + Label { + visible: !cardPane.anchored + text: "X" + } + IgnSpinBox { + visible: !cardPane.anchored + maximumValue: cardPane.parent ? cardPane.parent.height - cardPane.height : minSize + onVisibleChanged: value = cardPane.y + onValueChanged: { + cardPane.y = value; + } + } + Label { + visible: !cardPane.anchored + text: "Y" + } + IgnSpinBox { + visible: !cardPane.anchored + maximumValue: 10000 + onVisibleChanged: value = cardPane.z + onValueChanged: { + cardPane.z = value; + } + } + Label { + visible: !cardPane.anchored + text: "Z" + } + Label { + text: "Size" + font.weight: Font.DemiBold + } + Text { + text: "" + } + IgnSpinBox { + maximumValue: cardPane.parent ? cardPane.parent.width : minSize + onVisibleChanged: { + if (cardPane) + value = cardPane.width + } + onValueChanged: { + cardPane.width = value; + } + } + Label { + text: "Width" + } + IgnSpinBox { + maximumValue: cardPane.parent ? cardPane.parent.height : minSize + onVisibleChanged: { + if (cardPane) + value = cardPane.height + } + onValueChanged: { + cardPane.height = value; + } + } + Label { + text: "Height" + } + } + } + + ColorDialog { + id: colorDialog + title: "Please choose a color" + showAlphaChannel : true + onAccepted: { + content.color = colorDialog.color + bgColor.color = colorDialog.color + cardBackground = colorDialog.color + } + onRejected: { + console.log("Canceled") + } + Component.onCompleted: visible = false + } +} diff --git a/include/ignition/gui/qml/IgnHelpers.qml b/include/ignition/gui/qml/IgnHelpers.qml new file mode 100644 index 000000000..57c0619b3 --- /dev/null +++ b/include/ignition/gui/qml/IgnHelpers.qml @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 + +Item { + /** + * Helper function to get an item's ancestor by name. + * @param _item Item whose parent we're looking for. + * @param _name Name to look for, accepts regex. + * @returns The ancestor, or undefined if not found. + */ + function ancestorByName(_item, _name) + { + if (_item === undefined) + return undefined; + + var result = _item.parent; + while (result) + { + if (result.objectName.match(_name) !== null) + break; + + result = result.parent; + } + + return result; + } +} diff --git a/include/ignition/gui/qml/IgnRulers.qml b/include/ignition/gui/qml/IgnRulers.qml new file mode 100644 index 000000000..1595389cd --- /dev/null +++ b/include/ignition/gui/qml/IgnRulers.qml @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 2.2 + +/** + * Rulers which can be dragged to resize a target. + */ +Rectangle { + id: rulersRect + color: "transparent" + + /** + * Thickness of rulers + */ + property int rulersThickness: 25 + + /** + * Set to false so rulers disappear. + */ + property bool enabled: true + + /** + * Minimum length of each dimension + */ + property int minSize: 50 + + /** + * Target item to be resized by the rulers. + */ + property var target: null + + // Left ruler + Rectangle { + width: rulersThickness + height: parent.height - 20 + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.left + anchors.verticalCenter: parent.verticalCenter + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SplitHCursor + drag { target: parent; axis: Drag.XAxis } + onMouseXChanged: { + if (drag.active) + { + resizeLeft(target, mouseX); + } + } + } + } + + // Right ruler + Rectangle { + width: rulersThickness + height: parent.height - 20 + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.right + anchors.verticalCenter: parent.verticalCenter + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SplitHCursor + drag { target: parent; axis: Drag.XAxis } + onMouseXChanged: { + if (drag.active) + { + resizeRight(target, mouseX); + } + } + } + } + + // Top ruler + Rectangle { + width: parent.width - 20 + height: rulersThickness + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.top + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SplitVCursor + drag { target: parent; axis: Drag.YAxis } + onMouseYChanged: { + if (drag.active) + { + resizeTop(target, mouseY); + } + } + } + } + + // Bottom ruler + Rectangle { + width: parent.width - 20 + height: rulersThickness + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.bottom + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SplitVCursor + drag { target: parent; axis: Drag.YAxis } + onMouseYChanged: { + if (drag.active) + { + resizeBottom(target, mouseY); + } + } + } + } + + // Top-Left Ruler + Rectangle { + width: 25 + height: 25 + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.left + anchors.verticalCenter: parent.top + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SizeFDiagCursor + drag { target: parent; axis: Drag.XAndYAxis } + onMouseYChanged: { + if (drag.active) + { + resizeTop(target, mouseY); + resizeLeft(target, mouseX); + } + } + } + } + + // Top-Right Ruler + Rectangle { + width: 25 + height: 25 + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.right + anchors.verticalCenter: parent.top + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SizeBDiagCursor + drag { target: parent; axis: Drag.XAndYAxis } + onMouseYChanged: { + if (drag.active) + { + resizeTop(target, mouseY); + resizeRight(target, mouseX); + } + } + } + } + + // Bottom-Left Ruler + Rectangle { + width: 25 + height: 25 + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.left + anchors.verticalCenter: parent.bottom + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SizeBDiagCursor + drag { target: parent; axis: Drag.XAndYAxis } + onMouseYChanged: { + if (drag.active) + { + resizeBottom(target, mouseY); + resizeLeft(target, mouseX); + } + } + } + } + + // Bottom-Right Ruler + Rectangle { + width: 25 + height: 25 + visible: rulersRect.enabled + color: "transparent" + anchors.horizontalCenter: parent.right + anchors.verticalCenter: parent.bottom + + MouseArea { + anchors.fill: parent + cursorShape: Qt.SizeFDiagCursor + drag { target: parent; axis: Drag.XAndYAxis } + onMouseYChanged: { + if (drag.active) + { + resizeBottom(target, mouseY); + resizeRight(target, mouseX); + } + } + } + } + + function resizeLeft(target, mouseX) + { + var newCardX = Math.max(target.x + mouseX, 0) + var newCardWidth = Math.max(target.width + (target.x - newCardX), + rulersRect.minSize, target.cardMinimumWidth) + + if (newCardWidth === target.width) + return; + + target.x = newCardX + target.width = newCardWidth + } + + function resizeRight(target, mouseX) + { + target.width = Math.max(target.width + mouseX, rulersRect.minSize, + target.cardMinimumWidth) + + if (target.width + target.x > target.parent.width) + target.width = target.parent.width - target.x + } + + function resizeTop(target, mouseY) + { + var newCardY = Math.max(target.y + mouseY, 0) + var newCardHeight = Math.max(target.height + (target.y - newCardY), + rulersRect.minSize, target.cardMinimumHeight) + + if (newCardHeight === target.height) + return; + + target.y = newCardY + target.height = newCardHeight + } + + function resizeBottom(target, mouseY) + { + target.height = Math.max(target.height + mouseY, rulersRect.minSize, + target.cardMinimumHeight) + + if (target.height + target.y > target.parent.height) + target.height = target.parent.height - target.y + } +} diff --git a/include/ignition/gui/qml/IgnSnackBar.qml b/include/ignition/gui/qml/IgnSnackBar.qml new file mode 100644 index 000000000..f4f2dc3c8 --- /dev/null +++ b/include/ignition/gui/qml/IgnSnackBar.qml @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +import QtGraphicalEffects 1.0 +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.2 +import QtQuick.Dialogs 1.0 +import QtQuick.Layouts 1.3 +import QtQuick.Window 2.2 + +/* + To use the snackbar you need to call the methods in the MainWindow class: + - notify(message) + - notifyWithDuration(message, duration) + +For example: + // This code will show the message "Message" during one second + App()->findChild()->notifyWithDuration("Message", 1000); + + // This code will show the message "Message2" but the dialog will be there + // until you press the button "Dismiss" + App()->findChild()->notifyWithDuration("Message2"); +*/ + +Popup { + id: snackbar + modal: duration == 0 + focus: duration == 0 + x: (window.width - width) / 2 + y: window.height - window.height / 6 + width: window.width - window.width / 6 + contentHeight: Math.max(dismissButton.height, notificationText.height) + padding: 10 + + // If the popup has a Dismiss button, only close by pressing that. + // Otherwise, use the default behavior. + closePolicy: duration == 0 ? Popup.NoAutoClose : + Popup.CloseOnEscape | Popup.CloseOnPressOutside + + // Array that contains a dictionary with two keys "text" and "duration" + // This structure keeps the message to show using FIFO + property var popupArray: [] + + // Duration of the snackbar. If duration is equal to zero then + // you should click on the button "Dismiss" to close the dialog", + // otherwise you need to wait the duration defined. + property int duration: 0 + + // This method is called when the dialog is closed + onClosed: { + timer.stop() + checkArray(); + } + + background: Rectangle { + color: Material.background + layer.enabled: true + layer.effect: DropShadow { + color: "#aa000000" + samples: 9 + spread: 0 + radius: 8.0 + } + } + + // this function is called when notify() or notifyWithDuration() are called + function setTextDuration(_message, _duration) { + popupArray.push({"text": _message, "duration": _duration}) + checkArray(); + } + + // This method check if the popupArray has remaining messages to show. + function checkArray() + { + if (popupArray.length == 0) + { + return + } + + if(!timer.running) + { + if (popupArray.length > 0) + { + var values = popupArray[0] + notificationText.text = values.text + duration = values.duration + snackbar.open() + + // Note that objects cannot be individually added to or removed from + // the list once created; to modify the contents of a list, it must be + // reassigned to a new list. + var newpopupArray = [] + for (var i = 1; i < popupArray.length; i++) + { + newpopupArray.push(popupArray[i]) + } + + if (newpopupArray != undefined) + { + popupArray = newpopupArray + } + else + { + popupArray = [] + } + if (duration > 0) + { + timer.restart() + } + } + } + } + + contentItem: RowLayout { + id: contentLayout + height: dismissButton.height + anchors.verticalCenter: snackbar.verticalCenter + + Text { + id: notificationText + color: Material.theme == Material.Light ? "black" : "white" + wrapMode: Text.Wrap + font.pixelSize: 15 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + } + Button { + id: dismissButton + visible: duration == 0 + flat: true + Layout.margins: 0 + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + background: Rectangle { + color: parent.down ? Material.color(Material.accent, Material.Shade400) : + (parent.hovered ? Material.color(Material.accent, Material.Shade200) : + "transparent") + } + font.pixelSize: 12 + text: "Dismiss" + onClicked: snackbar.close() + } + } + Timer { + id: timer + interval: snackbar.duration + onTriggered: { + if (!running) { + snackbar.close(); + } + checkArray(); + } + } + +} diff --git a/include/ignition/gui/qml/IgnSortFilterModel.qml b/include/ignition/gui/qml/IgnSortFilterModel.qml new file mode 100644 index 000000000..f127d27ab --- /dev/null +++ b/include/ignition/gui/qml/IgnSortFilterModel.qml @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +// Borrowed from +// https://martin.rpdev.net/2019/01/15/using-delegatemodel-in-qml-for-sorting-and-filtering.html + +import QtQuick 2.9 +import QtQml.Models 2.3 + +DelegateModel { + /** + * Used by sorting. Override it to create custom sort behaviour. + */ + property var lessThan: function(_left, _right) + { + return true; + } + + /** + * Override this function to define what items should be accepted or not. + */ + property var filterAcceptsItem: function(_item) + { + return true; + } + + /** + * Update the item list + */ + function update() { + if (items.count > 0) { + items.setGroups(0, items.count, "items"); + } + + // Step 1: Filter items + var visible = []; + for (var i = 0; i < items.count; ++i) { + var item = items.get(i); + if (filterAcceptsItem(item.model)) { + visible.push(item); + } + } + + // Step 2: Sort the list of visible items + visible.sort(function(_a, _b) { + return lessThan(_a.model, _b.model) ? -1 : 1; + }); + + // Step 3: Add all items to the visible group: + for (i = 0; i < visible.length; ++i) { + item = visible[i]; + item.inVisible = true; + if (item.visibleIndex !== i) { + visibleItems.move(item.visibleIndex, i, 1); + } + } + } + + items.onChanged: update() + onLessThanChanged: update() + onFilterAcceptsItemChanged: update() + + groups: DelegateModelGroup { + id: visibleItems + + name: "visible" + includeByDefault: false + } + + filterOnGroup: "visible" +} + diff --git a/include/ignition/gui/qml/IgnSpinBox.qml b/include/ignition/gui/qml/IgnSpinBox.qml new file mode 100644 index 000000000..800db5e11 --- /dev/null +++ b/include/ignition/gui/qml/IgnSpinBox.qml @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +SpinBox { + style: SpinBoxStyle{ + background: Rectangle { + implicitWidth: 70 + implicitHeight: 40 + border.color: "gray" + } + } +} diff --git a/include/ignition/gui/qml/IgnSplit.qml b/include/ignition/gui/qml/IgnSplit.qml new file mode 100644 index 000000000..d41ca0a45 --- /dev/null +++ b/include/ignition/gui/qml/IgnSplit.qml @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 1.1 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 + +/** + * Main split view, which provides functions to add and remove child items + * and splits. + */ +SplitView { + + id: background + objectName: "background" + + IgnHelpers { + id: helpers + } + + /** + * Dictionary of all split items contained in this split. + */ + property variant childItems: new Object() + + /** + * Dictionary of all splits nested into this split. + */ + property variant childSplits: new Object() + + /** + * Callback when the height changed. + */ + onHeightChanged: + { + background.recalculateMinimumSizes(); + } + + Rectangle { + id: startLabel; + visible: MainWindow.pluginCount === 0 + anchors.fill: parent + color: Material.background + Label { + text: "Insert plugins to start!" + anchors.fill: parent + font.pointSize: 24 + horizontalAlignment: Label.AlignHCenter + verticalAlignment: Label.AlignVCenter + wrapMode: Label.Wrap + } + } + + /** + * Recalculate minimum size for all splits + */ + function recalculateMinimumSizes() + { + for (var name in childSplits) + { + childSplits[name].split.recalculateMinimumSize() + } + } + + /** + * This function will appropriately create new items and splits according to + * the current main window state. + * @return Name of added item, which is prefixed by `split_item_`. The item + * is empty, so the caller can add content to it. + * TODO(louise) Accept configuration, so we know how to add the item + * (orientation, size) + * TODO(louise) Make this more flexible so we can have different window + * arrangements + */ + function addSplitItem() + { + var itemName = ""; + + // First section goes in the top level SplitView, which is Qt.Horizontal + // 2 for helpers and startLabel + if (background.__items.length <= 2) + { + itemName = _addNewItem(background); + } + // The next one adds a Qt.Vertical split to the right + else if (Object.keys(childSplits).length === 0) + { + // Add the split + var split = _addNewSplit(background); + split.split.orientation = Qt.Vertical; + + // Then add a new item to the newly created split + itemName = _addNewItem(split); + } + // All subsequent ones are added to the vertical child split on the right + else + { + // Get desired split (for now we have only one) + var firstChildSplit = childSplits[Object.keys(childSplits)[0]]; + + // Then add a new item to it + itemName = _addNewItem(firstChildSplit); + } + + return itemName + } + + /** + * Remove a split item according to its name. + * @param Name of item, which must start with `split_item_`. + */ + function removeSplitItem(_name) + { + // Remove from split + _removeFromSplits(childItems[_name]); + + // Remove from dictionary and destroy + delete childItems[_name]; + } + + /** + * Create a new item and add it to a split. + * Meant for internal use. + * @param _split Split to add item to + * @return Unique name of newly created item; starts with `split_item_`. + */ + function _addNewItem(_split) + { + // Create item + var item = newItem.createObject(_split); + + // Unique name + var itemName = "split_item_" + Math.floor(Math.random() * 100000) + item.objectName = itemName; + + // Add to dictionary + childItems[itemName] = item; + + // Add to parent + if (_split === background) + { + _split.addItem(item); + } + else + { + _split.split.addItem(item); + + // Make sure that changes to the item's minimum size get propagated to the + // split. + item.minimumSizeChanged.connect(function(){ + _split.split.recalculateMinimumSize() + }); + } + + return itemName; + } + + /** + * Create a new split and add it to the parent split. + * Meant for internal use. + * @param _parentSplit Parent split. + * @returns Newly created split. + */ + function _addNewSplit(_parentSplit) + { + // Create split + var splitWrapper = newSplit.createObject(_parentSplit); + + // Unique name + var splitName = "split_" + Math.floor(Math.random() * 100000) + splitWrapper.objectName = splitName; + + // Add to dictionary + childSplits[splitName] = splitWrapper; + + // Add to parent + _parentSplit.addItem(splitWrapper); + + return splitWrapper; + } + + /** + * Removes item from its parent split and removes the split if that was + * the last item in it. + * Meant for internal use. + * @param _item Item who is supposed to be removed from its parent split. + */ + function _removeFromSplits(_item) + { + if (_item === undefined) + return; + + var split = helpers.ancestorByName(_item, /^split_|^background$/); + + if (!split) + { + console.error("Failed to find parent split for [", _item.objectName, "]") + return; + } + + if (split === background) + { + split.removeItem(_item); + } + else + { + split.split.removeItem(_item); + + // If split is now empty, remove split + if (split.split.__items.length === 0) + { + // Remove from array + delete childSplits[split.objectName] + + // Remove from parent split + _removeFromSplits(split); + + // Destroy + split.destroy(); + } + else + { + split.split.recalculateMinimumSize(); + } + } + } + + /** + * Component for creating new items + */ + Component { + id: newItem + + Rectangle { + Layout.minimumWidth: 100 + Layout.minimumHeight: 100 + Layout.fillHeight: false + Layout.fillWidth: true + color: Material.background + + /** + * Notifies that its minimum size has changed. + */ + signal minimumSizeChanged(); + + /** + * Callback when the layout's minimum width changes. + */ + Layout.onMinimumWidthChanged: { + minimumSizeChanged(); + } + + /** + * Callback when the layout's minimum height changes. + */ + Layout.onMinimumHeightChanged: { + minimumSizeChanged(); + } + + /** + * Callback when the children array has been changed. + */ + onChildrenChanged: { + // Propagate child's minimum size changes to the item. + newItem.Layout.minimumWidth = Qt.binding(function() { + if (children.length === 0 || children[0] === undefined) + return 0; + return children[0].Layout.minimumWidth + }); + newItem.Layout.minimumHeight = Qt.binding(function() { + if (children.length === 0 || children[0] === undefined) + return 0; + return children[0].Layout.minimumHeight + }); + } + } + } + + /** + * Component for creating new splits + */ + Component { + id: newSplit + + /** + * For some reason, the scroll view doesn't work well within a split view, + * so we wrap it in a rectangle. + */ + Rectangle { + id: splitWrapper + color: "transparent" + + /** + * Expose the split view. + */ + property var split: split + + /** + * Offset of 17 to accommodate for ScrollView scroll bar + */ + property var scrollBarWidth: 17 + + Layout.minimumWidth: split.Layout.minimumWidth + scrollBarWidth + Layout.minimumHeight: split.Layout.minimumHeight + + ScrollView { + contentHeight: split.height + contentWidth: split.width + scrollBarWidth + + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + + // TODO(louise) This only works for a very specific split + height: window.height - window.header.height + + SplitView { + id: split + width: splitWrapper.width - scrollBarWidth + height: Math.max(childItems[Object.keys(childItems)[0]].height, + split.Layout.minimumHeight) + + /** + * Iterate over all current child items and update the split's minimum + * width accordingly. + */ + function recalculateMinimumSize() + { + // TODO(louise): generalize to support horizontal splits + if (orientation === Qt.Horizontal) + { + return; + } + + // Sync minimum sizes + var heightSum = 0; + var minHeightSum = 0; + for (var i = 0; i < __items.length; i++) + { + var child = __items[i]; + + // Minimum width matches the largest minimum width among children + if (child.Layout.minimumWidth > Layout.minimumWidth) + { + Layout.minimumWidth = child.Layout.minimumWidth; + } + heightSum += child.height; + + var collapsed = child.Layout.maximumHeight == 50 + minHeightSum += collapsed ? child.height : child.Layout.minimumHeight + } + + // Minimum height to show all children + Layout.minimumHeight = minHeightSum; + split.height = Math.max(minHeightSum, background.height); + + // Squish all children if there's no slack + if (heightSum > background.height) + { + for (var i = 0; i < __items.length; i++) + { + var child = __items[i]; + child.height = child.Layout.minimumHeight; + } + } + } + } + } + } + } +} + diff --git a/include/ignition/gui/qml/Main.qml b/include/ignition/gui/qml/Main.qml new file mode 100644 index 000000000..67aa99e87 --- /dev/null +++ b/include/ignition/gui/qml/Main.qml @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Dialogs 1.0 +import QtQuick.Layouts 1.3 +import ExitAction 1.0 +import "qrc:/qml" + +ApplicationWindow +{ + title: qsTr("Ignition GUI") + width: 1200 + height: 1000 + minimumWidth: 300 + minimumHeight: 300 + visible: true + id: window + objectName: "window" + font.family: "Roboto" + + // Expose material properties to C++ + property string materialTheme: window.Material.theme + property string materialPrimary: window.Material.primary + property string materialAccent: window.Material.accent + property string toolBarColorLight: MainWindow.toolBarColorLight + property string toolBarTextColorLight: MainWindow.toolBarTextColorLight + property string toolBarColorDark: MainWindow.toolBarColorDark + property string toolBarTextColorDark: MainWindow.toolBarTextColorDark + property string pluginToolBarColorLight: MainWindow.pluginToolBarColorLight + property string pluginToolBarTextColorLight: MainWindow.pluginToolBarTextColorLight + property string pluginToolBarColorDark: MainWindow.pluginToolBarColorDark + property string pluginToolBarTextColorDark: MainWindow.pluginToolBarTextColorDark + // Expose config properties to C++ + property int defaultExitAction: MainWindow.defaultExitAction + property bool showDialogOnExit: MainWindow.showDialogOnExit + property string dialogOnExitText: MainWindow.dialogOnExitText + property bool exitDialogShowShutdown: MainWindow.exitDialogShowShutdown + property bool exitDialogShowCloseGui: MainWindow.exitDialogShowCloseGui + property string exitDialogShutdownText: MainWindow.exitDialogShutdownText + property string exitDialogCloseGuiText: MainWindow.exitDialogCloseGuiText + /** + * Flag to indicate if the close event was triggered by the close dialog. + */ + property bool closingFromDialog: false + + /** + * Tool bar background color + */ + property string toolBarColor: + MainWindow.toolBarColorLight === "" || + MainWindow.toolBarColorDark === "" ? + Material.primary : + (Material.theme === Material.Light) ? + MainWindow.toolBarColorLight : MainWindow.toolBarColorDark + + /** + * Tool bar text color + */ + property string toolBarTextColor: + MainWindow.toolBarTextColorLight === "" || + MainWindow.toolBarTextColorDark === "" ? + Material.background : + (Material.theme === Material.Light) ? + MainWindow.toolBarTextColorLight : MainWindow.toolBarTextColorDark + + // Not sure why the binding doesn't take care of this + onTitleChanged: { + titleLabel.text = window.title + } + + // Handler for window closing + onClosing: { + close.accepted = !showDialogOnExit + if(showDialogOnExit){ + if (closingFromDialog) { + close.accepted = true; + } else { + confirmationDialogOnExit.open() + } + } else if (defaultExitAction == ExitAction.SHUTDOWN_SERVER) { + MainWindow.OnStopServer() + } + } + + // C++ signals to QML slots + Connections { + target: MainWindow + onNotify: { + notificationDialog.setTextDuration(_message, 0) + } + onNotifyWithDuration: { + notificationDialog.setTextDuration(_message, _duration) + } + } + + /** + * Load a configuration file + */ + function loadConfig() { + loadFileDialog.open() + } + + /** + * Save a configuration file + */ + function saveConfig() { + MainWindow.OnSaveConfig() + } + + /** + * Save a configuration file to a given file + */ + function saveConfigAs() { + saveFileDialog.open() + } + + // Shortcuts (why not working on menu?) + Shortcut { + sequence: "Ctrl+O" + onActivated: loadConfig() + } + + Shortcut { + sequence: "Ctrl+S" + onActivated: saveConfig() + } + + Shortcut { + sequence: "Ctrl+Shift+S" + onActivated: saveConfigAs() + } + + Shortcut { + sequence: "Ctrl+Q" + onActivated: close() + } + + /** + * Top toolbar + */ + header: ToolBar { + Material.background: toolBarColor + Material.foreground: Material.foreground + + MouseArea { + anchors.fill: parent; + property variant clickPos: "1,1" + onPressed: { + clickPos = Qt.point(mouse.x,mouse.y) + } + onPositionChanged: { + var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y) + window.x += delta.x; + window.y += delta.y; + } + onDoubleClicked: { + window.showMaximized() + } + } + + RowLayout { + spacing: 20 + anchors.fill: parent + + ToolButton { + highlighted: true + visible: MainWindow.showDrawer + contentItem: Image { + fillMode: Image.Pad + horizontalAlignment: Image.AlignHCenter + verticalAlignment: Image.AlignVCenter + source: "images/drawer.png" + } + onClicked: drawer.open() + } + + // Padding for title + Rectangle { + height: 1 + width: 1 + visible: !MainWindow.showDrawer + color: "transparent" + } + + Label { + id: titleLabel + text: window.title + font.pixelSize: 18 + color: toolBarTextColor + elide: Label.ElideRight + horizontalAlignment: Qt.AlignHLeft + verticalAlignment: Qt.AlignVCenter + Layout.fillWidth: true + } + + ToolButton { + highlighted: true + visible: MainWindow.showPluginMenu + contentItem: Image { + fillMode: Image.Pad + horizontalAlignment: Image.AlignHCenter + verticalAlignment: Image.AlignVCenter + source: "images/menu.png" + } + onClicked: pluginMenu.open() + + PluginMenu { + id: pluginMenu + width: 200 + x: parent.width - width + height: window.height * 0.3 + transformOrigin: Popup.TopRight + } + } + } + } + + /** + * Background + */ + IgnSplit { + anchors.fill: parent + } + + /** + * Left menu + */ + SideDrawer { + id: drawer + interactive: MainWindow.showDrawer + width: Math.min(window.width * 0.3, 500) + height: window.height + } + + /** + * About dialog + */ + Dialog { + id: aboutDialog + modal: true + focus: true + title: "Ignition GUI" + x: (window.width - width) / 2 + y: window.height / 6 + width: Math.min(window.width, window.height) / 3 * 2 + contentHeight: aboutColumn.height + + Column { + id: aboutColumn + spacing: 20 + + Label { + width: aboutDialog.availableWidth + text: "Gorgeous robotic interfaces since 2018." + wrapMode: Label.Wrap + font.pixelSize: 12 + } + } + } + + /** + * Style dialog + */ + StyleDialog { + id: styleDialog + x: (window.width - width) / 2 + y: window.height / 6 + width: Math.min(window.width, window.height) * 0.5 + } + + /** + * Load file dialog + */ + FileDialog { + id: loadFileDialog + title: "Load configuration" + folder: shortcuts.home + nameFilters: [ "Config files (*.config)" ] + selectMultiple: false + selectExisting: true + onAccepted: { + MainWindow.OnLoadConfig(fileUrl) + } + } + + /** + * Save file dialog + */ + FileDialog { + id: saveFileDialog + title: "Save configuration" + folder: shortcuts.home + nameFilters: [ "Config files (*.config)" ] + selectMultiple: false + selectExisting: false + onAccepted: { + var selected = fileUrl.toString(); + + if (!selected.endsWith(".config")) + { + selected += ".config"; + } + + MainWindow.OnSaveConfigAs(selected); + } + } + + IgnSnackBar { + id: notificationDialog + } + + Timer { + id: timer + } + + /** + * Confirmation dialog on close button + */ + Dialog { + id: confirmationDialogOnExit + title: (dialogOnExitText ? dialogOnExitText : "Do you really want to exit?") + objectName: "confirmationDialogOnExit" + + modal: true + focus: true + parent: ApplicationWindow.overlay + width: 500 + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + closePolicy: Popup.CloseOnEscape + standardButtons: + (exitDialogShowCloseGui ? Dialog.Ok : Dialog.NoButton) | + (exitDialogShowShutdown ? Dialog.Discard : Dialog.NoButton) | + Dialog.Cancel + + // The button texts need to be changed later than in onCompleted as standardButtons change later + onAboutToShow: function () { + if (exitDialogShowCloseGui && exitDialogCloseGuiText) + footer.standardButton(Dialog.Ok).text = exitDialogCloseGuiText + if (exitDialogShowShutdown) + footer.standardButton(Dialog.Discard).text = + (exitDialogShutdownText ? exitDialogShutdownText : "Shutdown server and GUI") + } + + footer: + DialogButtonBox { + onClicked: function (btn) { + if (btn == this.standardButton(Dialog.Ok)) { + closingFromDialog = true; + window.close(); + } + else if (btn == this.standardButton(Dialog.Discard)) { + MainWindow.OnStopServer() + // if GUI and server run in the same process, give server opportunity to kill the GUI + timer.interval = 100; + timer.repeat = false; + timer.triggered.connect(function() { + closingFromDialog = true; + window.close(); + }); + timer.start(); + } + } + } + } +} diff --git a/include/ignition/gui/qml/PlottingInterface.qml b/include/ignition/gui/qml/PlottingInterface.qml new file mode 100644 index 000000000..168d3a862 --- /dev/null +++ b/include/ignition/gui/qml/PlottingInterface.qml @@ -0,0 +1,625 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtCharts 2.2 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.0 +import "qrc:/qml" + +Rectangle +{ + id : main + /** + charts map < chart id, chart object> + */ + property var charts: ({}) + /** + id of the main chart of the view (the one with biggest size) + */ + property int mainChartID: 1 + + /** + variable to create thd IDs of the charts + */ + property int idIncrementor: 0 + + /** + True if the user has many charts (more than 2) + False if it has one chart or 2 + used to customize some UI features based on the mode + */ + property bool multiChartsMode: false + /** + export window + */ + property var window: null + + /** + add new chart to the view + */ + function addChart() + { + main.idIncrementor++; + + var chartComponent = Qt.createComponent("Chart.qml"); + var chartObject; + // if the mode is many charts that are organized in horizontal layout + if (multiChartsMode) + { + // add it to the horizontal layout + chartObject = chartComponent.createObject(rowChartsLayout); + chartObject.width = 200; + chartObject.height = Qt.binding( function() {return rowCharts.height * 0.9} ); + chartObject.y = Qt.binding( function() {return (rowCharts.height - chartObject.height)/2} ); + chartObject.multiChartsMode = true; + chartObject.fillPlotInOrOut() + } + else + { + // if normal mode, add the chart to the normal vertical layout + chartObject = chartComponent.createObject(chartsLayout); + chartObject.height = Qt.binding( function() {return chartsLayout.height / chartsLayout.heightFactor}); + chartObject.width = Qt.binding( function() {return chartsLayout.width}); + // to change the height of each vertical chart + chartsLayout.heightFactor ++ ; + } + + // Chart ID + chartObject.chartID = main.idIncrementor; + charts[idIncrementor] = chartObject; + // Signals and Slots + chartObject.subscribe.connect(main.onSubscribe); + chartObject.unSubscribe.connect(main.onUnSubscribe); + chartObject.componentSubscribe.connect(main.onComponentSubscribe); + chartObject.componentUnSubscribe.connect(main.onComponentUnSubscribe); + chartObject.clicked.connect(main.onClicked); + } + + /** + reallocate charts position, called at moving to multi charts mode + */ + function reallocateChart(_chart) + { + // new attributes to fit in the horizontal layout + _chart.width = 200; + _chart.height = Qt.binding( function() {return rowCharts.height * 0.9} ); + _chart.y = Qt.binding( function() {return (rowCharts.height - _chart.height)/2} ); + // enable that to enable the some UI features in the chart + _chart.multiChartsMode = true; + _chart.fillPlotInOrOut(); + + // change the layout from the vertical layout to the top horizontal one + _chart.parent = rowChartsLayout; + } + + function onSubscribe(_Id, _topic, _path) + { + PlottingIface.subscribe(_Id, _topic, _path); + } + function onUnSubscribe(_Id, _topic, _path) + { + PlottingIface.unsubscribe(_Id, _topic, _path); + } + function onComponentSubscribe(entity, typeId, type, attribute, Id) + { + PlottingIface.onComponentSubscribe(entity, typeId, type, attribute, Id); + } + function onComponentUnSubscribe(entity, typeId, attribute, Id) + { + PlottingIface.onComponentUnSubscribe(entity, typeId, attribute, Id); + } + + /** + on chart onClicked: + change the main chart to be the clicked chart + and swap it with the prev main chart + Id: id of the clicked chart + */ + function onClicked(Id) + { + // if many charts mode & the selected chart is in the horizontal layout + if (multiChartsMode && charts[Id].multiChartsMode) + { + // ======= main chart ========= + // change the main charts properties to fit in the horizontal layout + charts[mainChartID].width = 200; + charts[mainChartID].height = Qt.binding( function() {return rowCharts.height * 0.9} ); + charts[mainChartID].y = (rowCharts.height - charts[mainChartID].height)/2; + charts[mainChartID].multiChartsMode = true; + charts[mainChartID].fillPlotInOrOut(); + + // swap the main chart with the position of the clicked chart + charts[mainChartID].parent = rowChartsLayout; + + // ======= swapped chart ======= + charts[Id].parent = chartsLayout; + charts[Id].x = charts[mainChartID].x; + charts[Id].y = 0; + charts[Id].height = Qt.binding( function() {return chartsLayout.height / chartsLayout.heightFactor}); + charts[Id].width = Qt.binding( function() {return chartsLayout.width}); + charts[Id].multiChartsMode = false; + charts[Id].fillPlotInOrOut(); + charts[Id].setChartOpacity(1); + + mainChartID = Id; + } + } + + /** + fix the OpenGL disappear problem when the plugin is docked + */ + function fixOpenGL() + { + Object.keys(main.charts).forEach(function(key) { + main.charts[key].fixOpenGL(); + }); + } + + /** + plot point to a chart + _chart: chart id + _fieldID: field path or id + _x: x coordinates of the point + _y: y coordinates of the point + */ + function handlePlot(_chart, _fieldID, _x, _y) + { + charts[_chart].appendPoint(_fieldID, _x, _y); + } + + Connections { + target: PlottingIface + onPlot : handlePlot(_chart, _fieldID, _x, _y); + } + + + Layout.minimumWidth: 600 + Layout.minimumHeight: 600 + anchors.fill: parent + color: (Material.theme == Material.Light) ? Material.color(Material.Grey,Material.Shade100) : Material.background + + // when the chart is docked fix the OpenGL Disappear problem + onWidthChanged: { + main.fixOpenGL(); + } + + // Horizonal Layout to hold multi charts (small charts) + Rectangle { + id: rowCharts + width: parent.width + height: (multiChartsMode) ? 150 : 0 + color: (Material.theme == Material.Light) ? Material.color(Material.Grey,Material.Shade200) + : Material.color(Material.BlueGrey, Material.Shade800) + // Make it Scrolable + ScrollView { + anchors.fill: parent + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AlwaysOff + clip: true + // Horizontal Layout for the Charts + Row { + id:rowChartsLayout + anchors.fill: parent + spacing: 10 + } + } + } + + // Vertical Layout to hold Main Charts (1 or 2 charts) + Column { + id : chartsLayout + + /** + factor to customize the height of the Charts based on their number + */ + property int heightFactor: 0 + + width: parent.width + anchors.topMargin: 10 + anchors.top: rowCharts.bottom + anchors.bottom: parent.bottom + } + + Rectangle { + id : addBtn + + anchors.right: openExport.left + anchors.top: parent.top + anchors.margins: 15 + + width: 40 + height: 40 + radius: width/2 + color: Material.accentColor + Text { + text: "+" + font.weight: Font.Bold + font.pixelSize: parent.width/2 + color: "white" + anchors.centerIn: parent + } + + MouseArea { + id: mouseAddBtn + anchors.fill: parent + hoverEnabled: true + onEntered: { addBtn.opacity = 0.8; cursorShape = Qt.PointingHandCursor; } + onExited: { addBtn.opacity = 1; cursorShape = Qt.ArrowCursor; } + + onClicked: { + if (Object.keys(charts).length == 2) + { + multiChartsMode = true; + var firstChart = true; + for (var i = 0; i < chartsLayout.children.length; i++) + { + // skip the first one + if (firstChart) + { + firstChart = false; + // make that chart has a full size + chartsLayout.heightFactor = 1 + continue; + } + var chart = chartsLayout.children[i]; + reallocateChart(chart); + } + } // end if + + addChart(); + } + } + + ToolTip.text: "Add Chart" + ToolTip.delay: 500 + ToolTip.timeout: 1000 + ToolTip.visible: mouseAddBtn.containsMouse + } + + Component.onCompleted: { + addChart(); + } + + ToolButton { + id: openExport + width: 40; + height: 40; + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 15 + onHoveredChanged: (opacity === 1) ? opacity = 0.8 : opacity = 1; + + background: Rectangle{ + id: background + anchors.fill: parent + radius: width/2 // circle + + color: "transparent" + border.width: 1 + border.color: Material.color(Material.Grey, Material.Shade500) + } + + Image { + id: exportIcon + /** + size factor + */ + property double factor: 0.65 + width: background.width * factor; + height: background.height * factor; + anchors.centerIn: background + sourceSize.width: background.width * factor; + sourceSize.height: background.height * factor; + source: "images/export_icon.png" + } + + ToolTip.text: "Export"; + ToolTip.visible: openExport.hovered + ToolTip.delay: 500 + ToolTip.timeout: 1000 + + onClicked: { + if (main.window) + main.window.destroy() + + main.window = exportWindow.createObject(); + main.window.setCharts(main.charts); + main.window.setBackgroundColor(main.color); + main.window.setPrimaryColor(Material.primaryColor) + main.window.show(); + } + } + + Component { + id : exportWindow + ApplicationWindow { + id: exportApp + + /** + flag indicated if the chart is in small mode + */ + property bool isSmallChart: false + /** + charts objects that is loaded in the export window + */ + property var charts: [] + /** + index of the selected chart + */ + property int index: 0 + + /** + charts images that is displayed in the export window + */ + property var chartImages: [] + + /** + add chart copy/image to the export window + */ + function addChartCopy(result) + { + var imageObject = chartCopy.createObject(grid); + imageObject.setSource(result.url); + + imageObject.setChartName("Plot" + charts[index].chartID.toString()); + imageObject.chartIndex = index; + + chartImages.push(imageObject); + + index++; + continueCopy(); + } + + /** + set/add all the charts in the PlottingInterface to the export window + */ + function setCharts(_charts) + { + // clear + charts = [] + chartImages = [] + + Object.keys(_charts).forEach(function(key) { + charts.push(_charts[key]); + }); + + continueCopy(); + } + + /** + continue the process of the copy + Grabbing image takes time and we should continue after the image callback + */ + function continueCopy() + { + if (index < charts.length) + charts[index].getChart().grabToImage(addChartCopy); + } + + /** + export all selected charts in the export window to that path + */ + function exportCSV(path) + { + for (var i = 0; i < chartImages.length; i++) + { + if (!chartImages[i].isSelected()) + continue; + + var chart = charts[chartImages[i].chartIndex]; + var serieses = chart.getChart().getAllSerieses(); + var chart_id = chart.chartID; + + if (Object.keys(serieses).length === 0) + continue; + + + // convert Serieses to Map of {series_name : points list} + // slots in cpp accepts QMap + // QVariant could be a list instead of series object + + var chartSerieses = {}; + var seriesArray = []; + Object.keys(serieses).forEach(function(key) { + + seriesArray = [] + + // convert Series to QList + for (var j =0; j < serieses[key].count; j++) + seriesArray.push(serieses[key].at(j)); + + // add series + chartSerieses[key] = seriesArray; + }); + + return PlottingIface.exportCSV(path, chart_id, chartSerieses); + } + } + + /** + set the background color of the export widget + */ + function setBackgroundColor(_color) + { + exportWidget.color = _color; + } + + /** + set color of the export button + */ + function setPrimaryColor(_color) + { + exportBtn.color = _color; + } + + width: 1000; height: 600 + title: "Plotting Export" + + Rectangle { + color: (Material.theme === Material.Light) ? Material.color(Material.Grey, Material.Shade200) : + Material.color(Material.Grey, Material.Shade900) + anchors.fill: parent + id: exportWidget + + // make it scrolable + ScrollView { + width: parent.width + height: parent.height - exportBtn.height * 1.5 + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + clip: true + + Grid { + id: grid + anchors.fill: parent + spacing: 10 + padding: 30 + columns: (exportWidget.width)/ 300 + } + } + + ComboBox { + id: exportBtn + + property string color: Material.primaryColor + + displayText: "Export to" + model: ["CSV"] + + background: Rectangle { + implicitWidth: 120 + implicitHeight: 40 + radius: 10 + color: parent.color; + } + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.margins: 10 + + onActivated: { + fileDialog.open(); + } + } + Rectangle { + id: cancelBtn + color: Material.color(Material.Grey, Material.Shade600); + implicitWidth: 120 + implicitHeight: 40 + radius: 10 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.margins: 10 + Text { + text: "Cancel" + anchors.centerIn: parent + color: "white" + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: parent.opacity = 0.9; cursorShape: Qt.PointingHandCursor + onExited: parent.opacity = 1; + onClicked: exportApp.close() + } + } + } + + FolderDialog { + id: fileDialog + title: "Choose a folder" + visible: false + options: FolderDialog.ShowDirsOnly + + onAccepted: { + if (exportBtn.currentText == "CSV") + { + var success = exportApp.exportCSV(folder); + if (success) + exportApp.close(); + } + } + onRejected: fileDialog.close(); + } + + /** + Image/Copy of the Chart + */ + Component { + id: chartCopy + Column + { + /** + set the image source + */ + function setSource(url) + { + image.source = url; + } + /** + get the source of the grapped image + */ + function getSource() + { + return image.source + } + /** + set displayed name of the chart + */ + function setChartName(name) + { + checkboxText.text = name; + } + /** + check if the chart is selected to export + True if selected + */ + function isSelected() + { + return checkbox.checked; + } + + /** + index of the assosiated chart object in the charts array + */ + property int chartIndex: 0 + + width: 300 + height: 250 + Image { + id: image + width: parent.width + height: parent.height - 50 + } + CheckBox { + id: checkbox + x: image.width / 2 - 50 + checkState: Qt.Unchecked + Text { + id: checkboxText + anchors.left: parent.right + anchors.verticalCenter: parent.verticalCenter + color: Material.color(Material.Grey, Material.Shade500) + leftPadding: 5 + } + } + } + } + } + } +} diff --git a/include/ignition/gui/qml/PluginMenu.qml b/include/ignition/gui/qml/PluginMenu.qml new file mode 100644 index 000000000..68de63a7c --- /dev/null +++ b/include/ignition/gui/qml/PluginMenu.qml @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.2 +import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Layouts 1.3 + +Popup { + id: pluginMenu + padding: 0 + + Connections { + target: MainWindow + onConfigChanged: { + filteredModel.model = MainWindow.PluginListModel() + } + } + + /** + * Color for search bar + */ + property color searchColor: (Material.theme == Material.Light) ? + Material.color(Material.Grey, Material.Shade200): + Material.color(Material.Grey, Material.Shade900); + + onOpened: searchField.forceActiveFocus() + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Rectangle { + id: searchSortBar + color: searchColor + height: 50 + width: parent.width + RowLayout { + id: rowLayout + anchors.fill: parent + spacing: 0 + Rectangle { + color: "transparent" + height: 25 + width: 25 + Layout.leftMargin: 5 + Image { + id: searchIcon + source: "images/search.svg" + anchors.verticalCenter: parent.verticalCenter + } + } + TextField { + id: searchField + Layout.fillHeight: true + Layout.preferredWidth: parent.width - 50 + selectByMouse: true + onTextEdited: { + filteredModel.update(); + } + } + } + } + + ListView { + id: pluginMenuListView + Layout.fillHeight: true + width: parent.width + clip: true + + model: filteredModel + + ScrollBar.vertical: ScrollBar { + active: true + width: 8 + policy: ScrollBar.AlwaysOn + } + } + } + + IgnSortFilterModel { + id: filteredModel + + filterAcceptsItem: function(item) { + var itemStr = item.modelData.toLowerCase(); + var filterStr = searchField.text.toLowerCase(); + return itemStr.includes(filterStr); + } + + model: MainWindow.PluginListModel() + + delegate: ItemDelegate { + width: parent.width + text: modelData + highlighted: ListView.isCurrentItem + onClicked: { + MainWindow.OnAddPlugin(modelData); + drawer.close() + pluginMenu.close() + } + } + } +} + diff --git a/include/ignition/gui/qml/SideDrawer.qml b/include/ignition/gui/qml/SideDrawer.qml new file mode 100644 index 000000000..3b6c63c9f --- /dev/null +++ b/include/ignition/gui/qml/SideDrawer.qml @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 + +/** + * Side menu + */ +Drawer { + + Rectangle { + objectName: "sideDrawer" + id: sideDrawer + anchors.fill: parent + color: Material.background + + function closeDrawer() { + drawer.close(); + } + + function onAction(action) { + switch(action) { + case "loadConfig": + loadConfig() + break + case "saveConfig": + saveConfig() + break + case "saveConfigAs": + saveConfigAs() + break + case "styleSettings": + styleDialog.open() + break + case "aboutDialog": + aboutDialog.open() + break + case "close": + window.close() + break + default: + break + } + } + + ListModel { + id: drawerModel + + ListElement { + title: "Load configuration" + actionElement: "loadConfig" + } + ListElement { + title: "Save configuration" + actionElement: "saveConfig" + } + ListElement { + title: "Save configuration as" + actionElement: "saveConfigAs" + } + ListElement { + title: "Style settings" + actionElement: "styleSettings" + } + ListElement { + title: "About" + actionElement: "aboutDialog" + } + ListElement { + title: "Quit" + actionElement: "close" + } + } + + ListView { + id: listView + anchors.fill: parent + visible: MainWindow.showDefaultDrawerOpts + + delegate: ItemDelegate { + width: parent.width + text: title + highlighted: ListView.isCurrentItem + onClicked: { + sideDrawer.onAction(actionElement) + sideDrawer.closeDrawer(); + } + } + + model: drawerModel + + ScrollIndicator.vertical: ScrollIndicator { } + } + } +} diff --git a/include/ignition/gui/qml/StandaloneDialog.qml b/include/ignition/gui/qml/StandaloneDialog.qml new file mode 100644 index 000000000..a55864499 --- /dev/null +++ b/include/ignition/gui/qml/StandaloneDialog.qml @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +ApplicationWindow { + id: dialog + visible: true +} diff --git a/include/ignition/gui/qml/StyleDialog.qml b/include/ignition/gui/qml/StyleDialog.qml new file mode 100644 index 000000000..7845f2ed2 --- /dev/null +++ b/include/ignition/gui/qml/StyleDialog.qml @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Dialogs 1.0 + +/** + * Style dialog + */ +Dialog { + + // Inherited properties + id: styleDialog + modal: false + focus: true + title: "Style settings" + contentHeight: styleColumn.height + + // Custom properties + property int initialPrimary: -1 + property int initialAccent: -1 + property int initialTheme: -1 + property int foregroundShade: Material.Shade500 + + /** + * ✎ + */ + property string editIcon: "\u270E" + + /** + * Array with all pre-defined material colors. + * Must match materialColorEnums + */ + property var materialColorStrs: [ + "Red", + "Pink", + "Purple", + "DeepPurple", + "Indigo", + "Blue", + "LightBlue", + "Cyan", + "Teal", + "Green", + "LightGreen", + "Lime", + "Yellow", + "Amber", + "Orange", + "DeepOrange", + "Brown", + "Grey", + "BlueGrey", + ] + + /** + * Array with all pre-defined material colors + * Must match materialColorStrs + */ + property var materialColorEnums: [ + Material.Red, + Material.Pink, + Material.Purple, + Material.DeepPurple, + Material.Indigo, + Material.Blue, + Material.LightBlue, + Material.Cyan, + Material.Teal, + Material.Green, + Material.LightGreen, + Material.Lime, + Material.Yellow, + Material.Amber, + Material.Orange, + Material.DeepOrange, + Material.Brown, + Material.Grey, + Material.BlueGrey, + ] + + // Connections (C++ signal to QML slot) + Connections { + target: MainWindow + onMaterialThemeChanged: { + updateTheme(MainWindow.materialTheme); + } + } + + Connections { + target: MainWindow + onMaterialPrimaryChanged: { + updatePrimary(MainWindow.materialPrimary); + } + } + + Connections { + target: MainWindow + onMaterialAccentChanged: { + updateAccent(MainWindow.materialAccent); + } + } + + /** + * Convert a color component (R/G/B/A) to hex + * @param type:int _c Color in the 0~1 range + */ + function componentToHex(_c) { + _c = (_c * 255) | 0; + var hex = _c.toString(16); + return hex.length == 1 ? "0" + hex : hex; + } + + /** + * Convert a color object to a hex string + * @param type:color _color Color object + */ + function colorToHex(_color) { + return "#" + componentToHex(_color.r) + + componentToHex(_color.g) + + componentToHex(_color.b); + } + + /** + * Update primary color + * @param type:string _primary Optional color name + */ + function updatePrimary(_primary) { + + var index = -1; + + // When setting from MainWindow / ColorDialog + if (typeof _primary === "string") + { + index = materialColorStrs.indexOf(_primary) + } + // When setting from combo box + else if (materialPrimaryCombo.currentIndex !== -1) + { + index = materialPrimaryCombo.currentIndex + } + else + { + return; + } + + var c; + + // One of the material colors + if (index !== -1) + { + c = Material.color(materialColorEnums[index], foregroundShade); + materialPrimaryCombo.currentIndex = index; + } + // Custom color + else if (_primary.length !== 0) + { + c = _primary; + materialPrimaryCombo.currentIndex = -1; + materialPrimaryCombo.editText = _primary; + } + else + { + return; + } + window.Material.primary = c + } + + /** + * Update accent color + * @param type:string _accent Optional color name + */ + function updateAccent(_accent) { + + var index = -1; + + // When setting from MainWindow / ColorDialog + if (typeof _accent === "string") + { + index = materialColorStrs.indexOf(_accent) + } + // When setting from combo box + else if (materialAccentCombo.currentIndex !== -1) + { + index = materialAccentCombo.currentIndex + } + else + { + return; + } + + var c; + + // One of the material colors + if (index !== -1) + { + c = Material.color(materialColorEnums[index], foregroundShade); + materialAccentCombo.currentIndex = index; + } + // Custom color + else if (_accent.length !== 0) + { + c = _accent; + materialAccentCombo.currentIndex = -1; + materialAccentCombo.editText = _accent; + } + else + { + return; + } + window.Material.accent = c + } + + /** + * Update theme + * @param type:string _theme Optional theme name + */ + function updateTheme(_theme) { + + // Change theme + if (typeof _theme === "string" && _theme.length !== 0) + { + + materialThemeCombo.currentIndex = _theme === "Light" ? 0 : 1; + } + else if (materialThemeCombo.currentIndex !== -1) + { + _theme = materialThemeCombo.currentText + } + else + return; + + if (_theme === "Light") + { + window.Material.theme = Material.Light + foregroundShade = Material.Shade500 + } + else + { + window.Material.theme = Material.Dark + foregroundShade = Material.Shade200 + } + + // Update all colors according to new shade + updatePrimary(); + updateAccent(); + } + + /** + * Lifecycle hook + */ + Component.onCompleted: { + + // Get initial values + for (var i = 0; i < materialColorEnums.length; ++i) + { + var hex = colorToHex(Material.color(materialColorEnums[i])) + if (hex == window.Material.primary) + { + initialPrimary = i; + } + if (hex == window.Material.accent) + { + initialAccent = i; + } + } + + initialTheme = window.Material.theme + } + + Column { + id: styleColumn + anchors.horizontalCenter: styleDialog.horizontalCenter + width: styleDialog.width * 0.6 + + // TODO(anyone) extend to universal / default styles, beware that + // changing style at runtime doesn't seem to be supported, but we could save + // and prompt the user to restart + Label { + text: "Material style" + font.weight: Font.Bold + } + + Label { + text: "Theme" + } + + ComboBox { + id: materialThemeCombo + width: styleColumn.width + currentIndex: initialTheme + model: ["Light", "Dark"] + delegate: ItemDelegate { + text: modelData + width: parent.width + } + onCurrentTextChanged: { + updateTheme(); + } + } + + Label { + text: "Primary" + } + + ColorDialog { + id: materialPrimaryDialog + title: "Primary color" + // options: ColorDialog.NoButtons + onCurrentColorChanged: { + + // Avoiding pure black because for some reason it is set to that as the + // dialog opens + if (currentColor == "#000000") + return; + + updatePrimary(colorToHex(currentColor)) + } + } + + Row { + ComboBox { + id: materialPrimaryCombo + width: styleColumn.width + editable: true + // selectByMouse: true + currentIndex: initialPrimary + displayText: currentText + model: materialColorStrs + delegate: ItemDelegate { + text: materialColorStrs[index] + width: parent.width + } + onCurrentTextChanged: { + updatePrimary() + } + } + + ToolButton { + text: "\u270E" + font.pixelSize: 20 + onClicked: { + materialPrimaryDialog.open() + } + } + } + + Label { + text: "Accent" + } + + ColorDialog { + id: materialAccentDialog + title: "Accent color" + // options: ColorDialog.NoButtons + onCurrentColorChanged: { + + // Avoiding pure black because for some reason it is set to that as the + // dialog opens + if (currentColor == "#000000") + return; + + updateAccent(colorToHex(currentColor)) + } + } + + Row { + ComboBox { + id: materialAccentCombo + width: styleColumn.width + editable: true + // selectByMouse: true + currentIndex: initialAccent + displayText: currentText + model: materialColorStrs + delegate: ItemDelegate { + text: materialColorStrs[index] + width: parent.width + } + onCurrentIndexChanged: { + updateAccent() + } + } + + ToolButton { + text: "\u270E" + font.pixelSize: 20 + onClicked: { + materialAccentDialog.open() + } + } + } + } +} diff --git a/include/ignition/gui/qml/images/drawer.png b/include/ignition/gui/qml/images/drawer.png new file mode 100644 index 0000000000000000000000000000000000000000..bb1cd2fe4d1097a40c0174ddb0b013f1a8e5c54c GIT binary patch literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=hNp{TNX4z>AOHW`hkg_=oWST2 u$b9*nLsp|;_Ja%^{ymM0H`*|9M=+$;sDA&KdomQLhr!d;&t;ucLK6UsP#m!U literal 0 HcmV?d00001 diff --git a/include/ignition/gui/qml/images/export_icon.png b/include/ignition/gui/qml/images/export_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..50ef4e445c4ca76e2f556f0034aa986ede45baec GIT binary patch literal 5572 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 PpfUzeS3j3^P6 + + + + + image/svg+xml + + + + + + + + + + + diff --git a/include/ignition/gui/qml/qmldir b/include/ignition/gui/qml/qmldir new file mode 100644 index 000000000..f4f66ebc1 --- /dev/null +++ b/include/ignition/gui/qml/qmldir @@ -0,0 +1,3 @@ +module ignition.gui + +IgnSpinBox 1.0 IgnSpinBox.qml \ No newline at end of file diff --git a/include/ignition/gui/qt.h b/include/ignition/gui/qt.h new file mode 100644 index 000000000..1ec9c44b5 --- /dev/null +++ b/include/ignition/gui/qt.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include diff --git a/include/ignition/gui/qtquickcontrols2.conf b/include/ignition/gui/qtquickcontrols2.conf new file mode 100644 index 000000000..7fc23bec9 --- /dev/null +++ b/include/ignition/gui/qtquickcontrols2.conf @@ -0,0 +1,7 @@ +[Controls] +Style=Material + +[Material] +Theme=Light +Accent=LightBlue +Primary=DeepOrange diff --git a/include/ignition/gui/resources.qrc b/include/ignition/gui/resources.qrc new file mode 100644 index 000000000..2f749a6bd --- /dev/null +++ b/include/ignition/gui/resources.qrc @@ -0,0 +1,47 @@ + + + qtquickcontrols2.conf + + qml/Chart.qml + qml/IgnCard.qml + qml/IgnCardSettings.qml + qml/IgnHelpers.qml + qml/IgnRulers.qml + qml/IgnSnackBar.qml + qml/IgnSortFilterModel.qml + qml/IgnSpinBox.qml + qml/IgnSplit.qml + qml/Main.qml + qml/PlottingInterface.qml + qml/PluginMenu.qml + qml/SideDrawer.qml + qml/StandaloneDialog.qml + qml/StyleDialog.qml + + qml/images/ignition_logo_50x50.png + qml/images/drawer.png + qml/images/menu.png + qml/images/export_icon.png + qml/images/search.svg + + qml/IgnCard.qml + qml/IgnCardSettings.qml + qml/IgnHelpers.qml + qml/IgnRulers.qml + qml/IgnSnackBar.qml + qml/IgnSortFilterModel.qml + qml/IgnSpinBox.qml + qml/IgnSplit.qml + qml/IgnSnackBar.qml + qml/IgnSpinBox.qml + + + + qml/qmldir + + qml/IgnSnackBar.qml + qml/IgnSpinBox.qml + qml/IgnSnackBar.qml + qml/IgnSpinBox.qml + + From d9f235fd89c903170216e8814aeb2e6c067dd945 Mon Sep 17 00:00:00 2001 From: methylDragon Date: Fri, 6 May 2022 15:07:23 -0700 Subject: [PATCH 3/4] Migrate sources in src, test, examples, and include (#395) Signed-off-by: methylDragon --- .../custom_context_menu/CustomContext.cc | 2 +- .../custom_context_menu/CustomContext.hh | 8 ++--- .../dialog_from_plugin/DialogFromPlugin.cc | 2 +- .../dialog_from_plugin/DialogFromPlugin.hh | 8 ++--- examples/plugin/hello_plugin/HelloPlugin.cc | 2 +- examples/plugin/hello_plugin/HelloPlugin.hh | 8 ++--- .../plugin/ign_components/IgnComponents.cc | 2 +- .../plugin/ign_components/IgnComponents.hh | 6 ++-- examples/plugin/multiple_qml/MultipleQml.cc | 2 +- examples/plugin/multiple_qml/MultipleQml.hh | 8 ++--- .../standalone/custom_drawer/custom_drawer.cc | 8 ++--- .../standalone/custom_drawer/custom_drawer.hh | 6 ++-- examples/standalone/dialogs/dialogs.cc | 8 ++--- examples/standalone/marker/marker.cc | 6 ++-- .../standalone/point_cloud/point_cloud.cc | 6 ++-- .../scene_provider/scene_provider.cc | 12 +++---- examples/standalone/window/window.cc | 6 ++-- include/gz/gui/Application.hh | 10 +++--- include/gz/gui/Conversions.hh | 20 +++++------ include/gz/gui/Dialog.hh | 8 ++--- include/gz/gui/DragDropModel.hh | 8 ++--- include/gz/gui/Enums.hh | 6 ++-- include/gz/gui/GuiEvents.hh | 20 +++++------ include/gz/gui/Helpers.hh | 8 ++--- include/gz/gui/MainWindow.hh | 10 +++--- include/gz/gui/PlottingInterface.hh | 6 ++-- include/gz/gui/Plugin.hh | 8 ++--- include/gz/gui/SearchModel.hh | 8 ++--- include/gz/gui/gz.hh | 6 ++-- include/gz/gui/gz_auto_headers.hh.in | 2 +- include/gz/gui/qml/GzCard.qml | 8 ++--- include/gz/gui/qml/GzCardSettings.qml | 10 +++--- include/gz/gui/qml/GzSplit.qml | 2 +- include/gz/gui/qml/Main.qml | 4 +-- include/gz/gui/qml/PluginMenu.qml | 2 +- ...logo_50x50.png => ignition_logo_50x50.png} | Bin include/gz/gui/qml/qmldir | 4 +-- include/gz/gui/qt.h | 6 ++-- include/gz/gui/resources.qrc | 33 ++++++++++++------ src/plugins/teleop/Teleop.qml | 10 +++--- 40 files changed, 156 insertions(+), 143 deletions(-) rename include/gz/gui/qml/images/{gz_logo_50x50.png => ignition_logo_50x50.png} (100%) diff --git a/examples/plugin/custom_context_menu/CustomContext.cc b/examples/plugin/custom_context_menu/CustomContext.cc index e16fc98dd..5cba53224 100644 --- a/examples/plugin/custom_context_menu/CustomContext.cc +++ b/examples/plugin/custom_context_menu/CustomContext.cc @@ -16,7 +16,7 @@ */ #include -#include +#include #include "CustomContext.hh" diff --git a/examples/plugin/custom_context_menu/CustomContext.hh b/examples/plugin/custom_context_menu/CustomContext.hh index 88ff67541..fa229eb57 100644 --- a/examples/plugin/custom_context_menu/CustomContext.hh +++ b/examples/plugin/custom_context_menu/CustomContext.hh @@ -15,12 +15,12 @@ * */ -#ifndef IGNITION_GUI_CUSTOMCONTEXTPLUGIN_HH_ -#define IGNITION_GUI_CUSTOMCONTEXTPLUGIN_HH_ +#ifndef GZ_GUI_CUSTOMCONTEXTPLUGIN_HH_ +#define GZ_GUI_CUSTOMCONTEXTPLUGIN_HH_ #ifndef Q_MOC_RUN - #include - #include + #include + #include #endif namespace ignition diff --git a/examples/plugin/dialog_from_plugin/DialogFromPlugin.cc b/examples/plugin/dialog_from_plugin/DialogFromPlugin.cc index 891ddd846..2bbf5d381 100644 --- a/examples/plugin/dialog_from_plugin/DialogFromPlugin.cc +++ b/examples/plugin/dialog_from_plugin/DialogFromPlugin.cc @@ -16,7 +16,7 @@ */ #include -#include +#include #include "DialogFromPlugin.hh" diff --git a/examples/plugin/dialog_from_plugin/DialogFromPlugin.hh b/examples/plugin/dialog_from_plugin/DialogFromPlugin.hh index 35d048094..60d98120d 100644 --- a/examples/plugin/dialog_from_plugin/DialogFromPlugin.hh +++ b/examples/plugin/dialog_from_plugin/DialogFromPlugin.hh @@ -15,12 +15,12 @@ * */ -#ifndef IGNITION_GUI_DIALOGFROMPLUGIN_HH_ -#define IGNITION_GUI_DIALOGFROMPLUGIN_HH_ +#ifndef GZ_GUI_DIALOGFROMPLUGIN_HH_ +#define GZ_GUI_DIALOGFROMPLUGIN_HH_ #ifndef Q_MOC_RUN - #include - #include + #include + #include #endif namespace ignition diff --git a/examples/plugin/hello_plugin/HelloPlugin.cc b/examples/plugin/hello_plugin/HelloPlugin.cc index 4a980a45d..c49cb886d 100644 --- a/examples/plugin/hello_plugin/HelloPlugin.cc +++ b/examples/plugin/hello_plugin/HelloPlugin.cc @@ -16,7 +16,7 @@ */ #include -#include +#include #include "HelloPlugin.hh" diff --git a/examples/plugin/hello_plugin/HelloPlugin.hh b/examples/plugin/hello_plugin/HelloPlugin.hh index 588ec4fa5..144937d75 100644 --- a/examples/plugin/hello_plugin/HelloPlugin.hh +++ b/examples/plugin/hello_plugin/HelloPlugin.hh @@ -15,13 +15,13 @@ * */ -#ifndef IGNITION_GUI_HELLOPLUGIN_HH_ -#define IGNITION_GUI_HELLOPLUGIN_HH_ +#ifndef GZ_GUI_HELLOPLUGIN_HH_ +#define GZ_GUI_HELLOPLUGIN_HH_ #include -#include -#include +#include +#include namespace ignition { diff --git a/examples/plugin/ign_components/IgnComponents.cc b/examples/plugin/ign_components/IgnComponents.cc index ea2a010ae..f52a5f09e 100644 --- a/examples/plugin/ign_components/IgnComponents.cc +++ b/examples/plugin/ign_components/IgnComponents.cc @@ -15,7 +15,7 @@ * */ -#include +#include #include "IgnComponents.hh" // Register this plugin diff --git a/examples/plugin/ign_components/IgnComponents.hh b/examples/plugin/ign_components/IgnComponents.hh index 9130a936e..6c72e5b0a 100644 --- a/examples/plugin/ign_components/IgnComponents.hh +++ b/examples/plugin/ign_components/IgnComponents.hh @@ -15,10 +15,10 @@ * */ -#ifndef IGNITION_GUI_EXAMPLES_PLUGIN_IGNCOMPONENTS_HH_ -#define IGNITION_GUI_EXAMPLES_PLUGIN_IGNCOMPONENTS_HH_ +#ifndef GZ_GUI_EXAMPLES_PLUGIN_GZCOMPONENTS_HH_ +#define GZ_GUI_EXAMPLES_PLUGIN_GZCOMPONENTS_HH_ -#include +#include namespace ignition { diff --git a/examples/plugin/multiple_qml/MultipleQml.cc b/examples/plugin/multiple_qml/MultipleQml.cc index 0a82868b2..8869c9820 100644 --- a/examples/plugin/multiple_qml/MultipleQml.cc +++ b/examples/plugin/multiple_qml/MultipleQml.cc @@ -16,7 +16,7 @@ */ #include -#include +#include #include "MultipleQml.hh" diff --git a/examples/plugin/multiple_qml/MultipleQml.hh b/examples/plugin/multiple_qml/MultipleQml.hh index dad17e517..489b53b2f 100644 --- a/examples/plugin/multiple_qml/MultipleQml.hh +++ b/examples/plugin/multiple_qml/MultipleQml.hh @@ -15,12 +15,12 @@ * */ -#ifndef IGNITION_GUI_EXAMPLES_PLUGINS_MULTIPLEQML_HH_ -#define IGNITION_GUI_EXAMPLES_PLUGINS_MULTIPLEQML_HH_ +#ifndef GZ_GUI_EXAMPLES_PLUGINS_MULTIPLEQML_HH_ +#define GZ_GUI_EXAMPLES_PLUGINS_MULTIPLEQML_HH_ #ifndef Q_MOC_RUN - #include - #include + #include + #include #endif namespace ignition diff --git a/examples/standalone/custom_drawer/custom_drawer.cc b/examples/standalone/custom_drawer/custom_drawer.cc index 0ac1f02fb..64bbc2fa7 100644 --- a/examples/standalone/custom_drawer/custom_drawer.cc +++ b/examples/standalone/custom_drawer/custom_drawer.cc @@ -15,12 +15,12 @@ * */ -#include +#include #ifndef Q_MOC_RUN - #include - #include - #include + #include + #include + #include #include "custom_drawer.hh" #endif diff --git a/examples/standalone/custom_drawer/custom_drawer.hh b/examples/standalone/custom_drawer/custom_drawer.hh index 5f4d678a7..64a7edd25 100644 --- a/examples/standalone/custom_drawer/custom_drawer.hh +++ b/examples/standalone/custom_drawer/custom_drawer.hh @@ -15,13 +15,13 @@ * */ -#ifndef IGNITION_GUI_EXAMPLES_STANDALONE_CUSTOMDRAWER_HH_ -#define IGNITION_GUI_EXAMPLES_STANDALONE_CUSTOMDRAWER_HH_ +#ifndef GZ_GUI_EXAMPLES_STANDALONE_CUSTOMDRAWER_HH_ +#define GZ_GUI_EXAMPLES_STANDALONE_CUSTOMDRAWER_HH_ #include #ifndef Q_MOC_RUN - #include + #include #endif namespace ignition diff --git a/examples/standalone/dialogs/dialogs.cc b/examples/standalone/dialogs/dialogs.cc index 1d7c665c3..07ee0c3d9 100644 --- a/examples/standalone/dialogs/dialogs.cc +++ b/examples/standalone/dialogs/dialogs.cc @@ -17,12 +17,12 @@ #include -#include +#include #ifndef Q_MOC_RUN - #include - #include - #include + #include + #include + #include #endif ////////////////////////////////////////////////// diff --git a/examples/standalone/marker/marker.cc b/examples/standalone/marker/marker.cc index 8d16b5c70..0ad086b80 100644 --- a/examples/standalone/marker/marker.cc +++ b/examples/standalone/marker/marker.cc @@ -15,9 +15,9 @@ * */ -#include -#include -#include +#include +#include +#include #include diff --git a/examples/standalone/point_cloud/point_cloud.cc b/examples/standalone/point_cloud/point_cloud.cc index b2d036839..34d86e5f7 100644 --- a/examples/standalone/point_cloud/point_cloud.cc +++ b/examples/standalone/point_cloud/point_cloud.cc @@ -15,10 +15,10 @@ * */ -#include -#include +#include +#include -#include +#include #include #include diff --git a/examples/standalone/scene_provider/scene_provider.cc b/examples/standalone/scene_provider/scene_provider.cc index 2bb4a9ab1..830b0c9df 100644 --- a/examples/standalone/scene_provider/scene_provider.cc +++ b/examples/standalone/scene_provider/scene_provider.cc @@ -18,12 +18,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include using namespace std::chrono_literals; diff --git a/examples/standalone/window/window.cc b/examples/standalone/window/window.cc index 8986216a1..5c67481e0 100644 --- a/examples/standalone/window/window.cc +++ b/examples/standalone/window/window.cc @@ -18,9 +18,9 @@ #include #ifndef Q_MOC_RUN - #include - #include - #include + #include + #include + #include #endif ////////////////////////////////////////////////// diff --git a/include/gz/gui/Application.hh b/include/gz/gui/Application.hh index db9fd4513..c947abeef 100644 --- a/include/gz/gui/Application.hh +++ b/include/gz/gui/Application.hh @@ -14,16 +14,16 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_APPLICATION_HH_ -#define IGNITION_GUI_APPLICATION_HH_ +#ifndef GZ_GUI_APPLICATION_HH_ +#define GZ_GUI_APPLICATION_HH_ #include #include #include #include -#include "ignition/gui/qt.h" -#include "ignition/gui/Export.hh" +#include "gz/gui/qt.h" +#include "gz/gui/Export.hh" #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -138,7 +138,7 @@ namespace ignition /// /// 1. Paths given by the environment variable /// 2. Paths added by calling addPluginPath - /// 3. Path ~/.ignition/gui/plugins + /// 3. Path ~/.gz/gui/plugins /// 4. The path where Ignition GUI plugins are installed /// /// \return A vector of pairs, where each pair contains: diff --git a/include/gz/gui/Conversions.hh b/include/gz/gui/Conversions.hh index 6904e366f..2b566237f 100644 --- a/include/gz/gui/Conversions.hh +++ b/include/gz/gui/Conversions.hh @@ -15,24 +15,24 @@ * */ -#ifndef IGNITION_GUI_CONVERSIONS_HH_ -#define IGNITION_GUI_CONVERSIONS_HH_ +#ifndef GZ_GUI_CONVERSIONS_HH_ +#define GZ_GUI_CONVERSIONS_HH_ #ifdef _MSC_VER #pragma warning(push, 0) #endif -#include +#include #ifdef _MSC_VER #pragma warning(pop) #endif -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "ignition/gui/qt.h" -#include "ignition/gui/Export.hh" +#include "gz/gui/qt.h" +#include "gz/gui/Export.hh" namespace ignition { diff --git a/include/gz/gui/Dialog.hh b/include/gz/gui/Dialog.hh index 5da748d42..6572cc4c2 100644 --- a/include/gz/gui/Dialog.hh +++ b/include/gz/gui/Dialog.hh @@ -15,13 +15,13 @@ * */ -#ifndef IGNITION_GUI_DIALOG_HH_ -#define IGNITION_GUI_DIALOG_HH_ +#ifndef GZ_GUI_DIALOG_HH_ +#define GZ_GUI_DIALOG_HH_ #include -#include "ignition/gui/qt.h" -#include "ignition/gui/Export.hh" +#include "gz/gui/qt.h" +#include "gz/gui/Export.hh" #ifdef _WIN32 // Disable warning C4251 which is triggered by diff --git a/include/gz/gui/DragDropModel.hh b/include/gz/gui/DragDropModel.hh index 397a0e6f5..cffe3be44 100644 --- a/include/gz/gui/DragDropModel.hh +++ b/include/gz/gui/DragDropModel.hh @@ -14,11 +14,11 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_DRAGDROPMODEL_HH_ -#define IGNITION_GUI_DRAGDROPMODEL_HH_ +#ifndef GZ_GUI_DRAGDROPMODEL_HH_ +#define GZ_GUI_DRAGDROPMODEL_HH_ -#include "ignition/gui/Export.hh" -#include "ignition/gui/qt.h" +#include "gz/gui/Export.hh" +#include "gz/gui/qt.h" namespace ignition { diff --git a/include/gz/gui/Enums.hh b/include/gz/gui/Enums.hh index 911b929e1..9fc2ab9ab 100644 --- a/include/gz/gui/Enums.hh +++ b/include/gz/gui/Enums.hh @@ -15,10 +15,10 @@ * */ -#ifndef IGNITION_GUI_ENUMS_HH_ -#define IGNITION_GUI_ENUMS_HH_ +#ifndef GZ_GUI_ENUMS_HH_ +#define GZ_GUI_ENUMS_HH_ -#include "ignition/gui/qt.h" +#include "gz/gui/qt.h" namespace ignition { diff --git a/include/gz/gui/GuiEvents.hh b/include/gz/gui/GuiEvents.hh index df1a7e50d..aa9be8541 100644 --- a/include/gz/gui/GuiEvents.hh +++ b/include/gz/gui/GuiEvents.hh @@ -14,8 +14,8 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_GUIEVENTS_HH_ -#define IGNITION_GUI_GUIEVENTS_HH_ +#ifndef GZ_GUI_GUIEVENTS_HH_ +#define GZ_GUI_GUIEVENTS_HH_ #include #include @@ -23,14 +23,14 @@ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include "ignition/gui/Export.hh" +#include "gz/gui/Export.hh" namespace ignition { @@ -490,4 +490,4 @@ namespace ignition } } -#endif // IGNITION_GUI_GUIEVENTS_HH_ +#endif // GZ_GUI_GUIEVENTS_HH_ diff --git a/include/gz/gui/Helpers.hh b/include/gz/gui/Helpers.hh index 7ca3efe09..d25b5c759 100644 --- a/include/gz/gui/Helpers.hh +++ b/include/gz/gui/Helpers.hh @@ -14,13 +14,13 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_HELPERS_HH_ -#define IGNITION_GUI_HELPERS_HH_ +#ifndef GZ_GUI_HELPERS_HH_ +#define GZ_GUI_HELPERS_HH_ #include -#include "ignition/gui/Enums.hh" -#include "ignition/gui/Export.hh" +#include "gz/gui/Enums.hh" +#include "gz/gui/Export.hh" namespace ignition { diff --git a/include/gz/gui/MainWindow.hh b/include/gz/gui/MainWindow.hh index 6c5241430..ddece5981 100644 --- a/include/gz/gui/MainWindow.hh +++ b/include/gz/gui/MainWindow.hh @@ -14,8 +14,8 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_MAINWINDOW_HH_ -#define IGNITION_GUI_MAINWINDOW_HH_ +#ifndef GZ_GUI_MAINWINDOW_HH_ +#define GZ_GUI_MAINWINDOW_HH_ #include #include @@ -23,10 +23,10 @@ #include #include -#include +#include -#include "ignition/gui/qt.h" -#include "ignition/gui/Export.hh" +#include "gz/gui/qt.h" +#include "gz/gui/Export.hh" #ifdef _WIN32 // Disable warning C4251 which is triggered by diff --git a/include/gz/gui/PlottingInterface.hh b/include/gz/gui/PlottingInterface.hh index 9f463202f..f67a7cda1 100644 --- a/include/gz/gui/PlottingInterface.hh +++ b/include/gz/gui/PlottingInterface.hh @@ -14,8 +14,8 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_PLOTTINGINTERFACE_HH_ -#define IGNITION_GUI_PLOTTINGINTERFACE_HH_ +#ifndef GZ_GUI_PLOTTINGINTERFACE_HH_ +#define GZ_GUI_PLOTTINGINTERFACE_HH_ #include #include @@ -35,7 +35,7 @@ #include #include -#include "ignition/gui/Export.hh" +#include "gz/gui/Export.hh" namespace ignition { diff --git a/include/gz/gui/Plugin.hh b/include/gz/gui/Plugin.hh index b943b1e0d..dc96bc56e 100644 --- a/include/gz/gui/Plugin.hh +++ b/include/gz/gui/Plugin.hh @@ -14,15 +14,15 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_PLUGIN_HH_ -#define IGNITION_GUI_PLUGIN_HH_ +#ifndef GZ_GUI_PLUGIN_HH_ +#define GZ_GUI_PLUGIN_HH_ #include #include #include -#include "ignition/gui/qt.h" -#include "ignition/gui/Export.hh" +#include "gz/gui/qt.h" +#include "gz/gui/Export.hh" #ifdef _WIN32 // Disable warning C4251 which is triggered by diff --git a/include/gz/gui/SearchModel.hh b/include/gz/gui/SearchModel.hh index 563063f10..df75295fb 100644 --- a/include/gz/gui/SearchModel.hh +++ b/include/gz/gui/SearchModel.hh @@ -14,11 +14,11 @@ * limitations under the License. * */ -#ifndef IGNITION_GUI_SEARCHMODEL_HH_ -#define IGNITION_GUI_SEARCHMODEL_HH_ +#ifndef GZ_GUI_SEARCHMODEL_HH_ +#define GZ_GUI_SEARCHMODEL_HH_ -#include "ignition/gui/Export.hh" -#include "ignition/gui/qt.h" +#include "gz/gui/Export.hh" +#include "gz/gui/qt.h" namespace ignition { diff --git a/include/gz/gui/gz.hh b/include/gz/gui/gz.hh index f5541359c..397d94542 100644 --- a/include/gz/gui/gz.hh +++ b/include/gz/gui/gz.hh @@ -15,10 +15,10 @@ * */ -#ifndef IGNITION_GUI_IGN_HH_ -#define IGNITION_GUI_IGN_HH_ +#ifndef GZ_GUI_GZ_HH_ +#define GZ_GUI_GZ_HH_ -#include "ignition/gui/Export.hh" +#include "gz/gui/Export.hh" /// \brief External hook to read the library version. /// \return C-string representing the version. Ex.: 0.1.2 diff --git a/include/gz/gui/gz_auto_headers.hh.in b/include/gz/gui/gz_auto_headers.hh.in index 62156f5f5..6a6849cf3 100644 --- a/include/gz/gui/gz_auto_headers.hh.in +++ b/include/gz/gui/gz_auto_headers.hh.in @@ -1,3 +1,3 @@ // Automatically generated -#include +#include ${ign_headers} diff --git a/include/gz/gui/qml/GzCard.qml b/include/gz/gui/qml/GzCard.qml index c9b5031fa..c6c4464e6 100644 --- a/include/gz/gui/qml/GzCard.qml +++ b/include/gz/gui/qml/GzCard.qml @@ -180,7 +180,7 @@ Pane { // Keep a reference to the background // TODO(louise) This feels hacky, the card shouldn't care about the background, - // but I haven't figured out yet how the card can tell IgnSplit to create + // but I haven't figured out yet how the card can tell GzSplit to create // a new split and add the card to it. There must be a way using signals, events // or global functions...? var bgItemTemp = helpers.ancestorByName(cardPane, "background") @@ -224,7 +224,7 @@ Pane { anchored = false } - IgnHelpers { + GzHelpers { id: helpers } @@ -654,7 +654,7 @@ Pane { settingsDialog.open() } - IgnCardSettings { + GzCardSettings { id: settingsDialog modal: false focus: true @@ -695,7 +695,7 @@ Pane { } } - IgnRulers { + GzRulers { anchors.fill: parent enabled: cardPane.state === "floating" && resizable minSize: cardPane.minSize diff --git a/include/gz/gui/qml/GzCardSettings.qml b/include/gz/gui/qml/GzCardSettings.qml index 313fcf82e..0bf9423d9 100644 --- a/include/gz/gui/qml/GzCardSettings.qml +++ b/include/gz/gui/qml/GzCardSettings.qml @@ -133,7 +133,7 @@ Dialog { } } - IgnSpinBox { + GzSpinBox { visible: !cardPane.anchored maximumValue: cardPane.parent ? cardPane.parent.width - cardPane.width : minSize onVisibleChanged: value = cardPane.x @@ -145,7 +145,7 @@ Dialog { visible: !cardPane.anchored text: "X" } - IgnSpinBox { + GzSpinBox { visible: !cardPane.anchored maximumValue: cardPane.parent ? cardPane.parent.height - cardPane.height : minSize onVisibleChanged: value = cardPane.y @@ -157,7 +157,7 @@ Dialog { visible: !cardPane.anchored text: "Y" } - IgnSpinBox { + GzSpinBox { visible: !cardPane.anchored maximumValue: 10000 onVisibleChanged: value = cardPane.z @@ -176,7 +176,7 @@ Dialog { Text { text: "" } - IgnSpinBox { + GzSpinBox { maximumValue: cardPane.parent ? cardPane.parent.width : minSize onVisibleChanged: { if (cardPane) @@ -189,7 +189,7 @@ Dialog { Label { text: "Width" } - IgnSpinBox { + GzSpinBox { maximumValue: cardPane.parent ? cardPane.parent.height : minSize onVisibleChanged: { if (cardPane) diff --git a/include/gz/gui/qml/GzSplit.qml b/include/gz/gui/qml/GzSplit.qml index d41ca0a45..87e521a71 100644 --- a/include/gz/gui/qml/GzSplit.qml +++ b/include/gz/gui/qml/GzSplit.qml @@ -29,7 +29,7 @@ SplitView { id: background objectName: "background" - IgnHelpers { + GzHelpers { id: helpers } diff --git a/include/gz/gui/qml/Main.qml b/include/gz/gui/qml/Main.qml index 67aa99e87..a1401bab8 100644 --- a/include/gz/gui/qml/Main.qml +++ b/include/gz/gui/qml/Main.qml @@ -234,7 +234,7 @@ ApplicationWindow /** * Background */ - IgnSplit { + GzSplit { anchors.fill: parent } @@ -321,7 +321,7 @@ ApplicationWindow } } - IgnSnackBar { + GzSnackBar { id: notificationDialog } diff --git a/include/gz/gui/qml/PluginMenu.qml b/include/gz/gui/qml/PluginMenu.qml index 68de63a7c..7c7f52bd5 100644 --- a/include/gz/gui/qml/PluginMenu.qml +++ b/include/gz/gui/qml/PluginMenu.qml @@ -92,7 +92,7 @@ Popup { } } - IgnSortFilterModel { + GzSortFilterModel { id: filteredModel filterAcceptsItem: function(item) { diff --git a/include/gz/gui/qml/images/gz_logo_50x50.png b/include/gz/gui/qml/images/ignition_logo_50x50.png similarity index 100% rename from include/gz/gui/qml/images/gz_logo_50x50.png rename to include/gz/gui/qml/images/ignition_logo_50x50.png diff --git a/include/gz/gui/qml/qmldir b/include/gz/gui/qml/qmldir index f4f66ebc1..486b6c7aa 100644 --- a/include/gz/gui/qml/qmldir +++ b/include/gz/gui/qml/qmldir @@ -1,3 +1,3 @@ -module ignition.gui +module gz.gui -IgnSpinBox 1.0 IgnSpinBox.qml \ No newline at end of file +GzSpinBox 1.0 GzSpinBox.qml diff --git a/include/gz/gui/qt.h b/include/gz/gui/qt.h index b87be6d29..3da834cec 100644 --- a/include/gz/gui/qt.h +++ b/include/gz/gui/qt.h @@ -15,8 +15,8 @@ * */ -#ifndef IGNITION_GUI_QT_H_ -#define IGNITION_GUI_QT_H_ +#ifndef GZ_GUI_QT_H_ +#define GZ_GUI_QT_H_ #ifndef _MSC_VER #pragma GCC system_header @@ -43,4 +43,4 @@ #include -#endif // IGNITION_GUI_QT_H_ +#endif // GZ_GUI_QT_H_ diff --git a/include/gz/gui/resources.qrc b/include/gz/gui/resources.qrc index 71026a326..823ec03bc 100644 --- a/include/gz/gui/resources.qrc +++ b/include/gz/gui/resources.qrc @@ -3,14 +3,14 @@ qtquickcontrols2.conf qml/Chart.qml - qml/IgnCard.qml - qml/IgnCardSettings.qml - qml/IgnHelpers.qml - qml/IgnRulers.qml - qml/IgnSnackBar.qml - qml/IgnSortFilterModel.qml - qml/IgnSpinBox.qml - qml/IgnSplit.qml + qml/GzCard.qml + qml/GzCardSettings.qml + qml/GzHelpers.qml + qml/GzRulers.qml + qml/GzSnackBar.qml + qml/GzSortFilterModel.qml + qml/GzSpinBox.qml + qml/GzSplit.qml qml/Main.qml qml/PlottingInterface.qml qml/PluginMenu.qml @@ -23,12 +23,25 @@ qml/images/menu.png qml/images/export_icon.png qml/images/search.svg + + qml/GzCard.qml + qml/GzCardSettings.qml + qml/GzHelpers.qml + qml/GzRulers.qml + qml/GzSnackBar.qml + qml/GzSortFilterModel.qml + qml/GzSpinBox.qml + qml/GzSplit.qml + qml/GzSnackBar.qml + qml/GzSpinBox.qml qml/qmldir - qml/IgnSnackBar.qml - qml/IgnSpinBox.qml + qml/GzSnackBar.qml + qml/GzSpinBox.qml + qml/GzSnackBar.qml + qml/GzSpinBox.qml diff --git a/src/plugins/teleop/Teleop.qml b/src/plugins/teleop/Teleop.qml index f4001a578..c0caf1415 100644 --- a/src/plugins/teleop/Teleop.qml +++ b/src/plugins/teleop/Teleop.qml @@ -71,7 +71,7 @@ Rectangle { anchors.left: parent.left anchors.leftMargin: 5 } - IgnSpinBox { + GzSpinBox { id: linearVelField anchors.top: velocityLabel.bottom anchors.topMargin: 5 @@ -85,9 +85,9 @@ Rectangle { stepSize: 0.10 onEditingFinished:{ Teleop.OnLinearVelSelection(value) - } + } } - + // Angular velocity input Label { id: angularVelLabel @@ -98,7 +98,7 @@ Rectangle { anchors.left: linearVelField.right anchors.leftMargin: 10 } - IgnSpinBox { + GzSpinBox { id: angularVelField anchors.top: velocityLabel.bottom anchors.topMargin: 5 @@ -112,7 +112,7 @@ Rectangle { stepSize: 0.10 onEditingFinished:{ Teleop.OnAngularVelSelection(value) - } + } } // Button grid From 589074bb42ac9d71bff5d42057e5bb377875fd0d Mon Sep 17 00:00:00 2001 From: methylDragon Date: Fri, 6 May 2022 15:16:05 -0700 Subject: [PATCH 4/4] Migrate CMake files (#395) Signed-off-by: methylDragon --- CMakeLists.txt | 4 +- doc/CMakeLists.txt | 2 +- include/CMakeLists.txt | 3 +- src/plugins/CMakeLists.txt | 40 +++++++++---------- src/plugins/camera_tracking/CMakeLists.txt | 2 +- src/plugins/grid_config/CMakeLists.txt | 2 +- src/plugins/image_display/CMakeLists.txt | 2 +- .../interactive_view_control/CMakeLists.txt | 2 +- src/plugins/key_publisher/CMakeLists.txt | 2 +- src/plugins/marker_manager/CMakeLists.txt | 2 +- src/plugins/minimal_scene/CMakeLists.txt | 2 +- src/plugins/navsat_map/CMakeLists.txt | 2 +- src/plugins/plotting/CMakeLists.txt | 2 +- src/plugins/point_cloud/CMakeLists.txt | 2 +- src/plugins/publisher/CMakeLists.txt | 2 +- src/plugins/scene3d/CMakeLists.txt | 2 +- src/plugins/screenshot/CMakeLists.txt | 2 +- src/plugins/shutdown_button/CMakeLists.txt | 2 +- src/plugins/tape_measure/CMakeLists.txt | 2 +- src/plugins/teleop/CMakeLists.txt | 2 +- src/plugins/topic_echo/CMakeLists.txt | 2 +- src/plugins/topic_viewer/CMakeLists.txt | 2 +- .../transport_scene_manager/CMakeLists.txt | 2 +- src/plugins/world_control/CMakeLists.txt | 4 +- src/plugins/world_stats/CMakeLists.txt | 2 +- 25 files changed, 47 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fbda7e553..aa5637b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,9 @@ find_package(ignition-cmake3 REQUIRED) #============================================================================ # Configure the project #============================================================================ -ign_configure_project(VERSION_SUFFIX pre1) +ign_configure_project( + REPLACE_IGNITION_INCLUDE_PATH gz/gui + VERSION_SUFFIX pre1) #============================================================================ # Set project-specific options diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 4e8d4520b..344dc638a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -25,5 +25,5 @@ if (DOXYGEN_FOUND) COMMENT "Generating API documentation with Doxygen" VERBATIM) install(FILES ${CMAKE_BINARY_DIR}/doc/${PROJECT_NAME_LOWER}.tag.xml - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/ignition/${PROJECT_NAME_LOWER}_${PROJECT_VERSION_MINOR}) + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/gz/${PROJECT_NAME_LOWER}_${PROJECT_VERSION_MINOR}) endif() diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 25ec89762..4b2bdd7bb 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(ignition) +add_subdirectory(gz) +install(DIRECTORY ignition DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index c32824ad9..d6a9efb7e 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -1,5 +1,5 @@ ################################################# -# ign_gui_add_library ( +# gz_gui_add_library ( # SOURCES # [PUBLIC_LINK_LIBS ] # [PRIVATE_LINK_LIBS ]) @@ -16,18 +16,17 @@ # # [PRIVATE_LINK_LIBS]: Specify a list of libraries to be privately linked. # -function(ign_gui_add_library library_name) +function(gz_gui_add_library library_name) set(options) set(oneValueArgs) set(multiValueArgs SOURCES QT_HEADERS PUBLIC_LINK_LIBS PRIVATE_LINK_LIBS) + cmake_parse_arguments(gz_gui_add_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - cmake_parse_arguments(ign_gui_add_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - QT5_WRAP_CPP(${library_name}_headers_MOC ${ign_gui_add_library_QT_HEADERS}) + QT5_WRAP_CPP(${library_name}_headers_MOC ${gz_gui_add_library_QT_HEADERS}) QT5_ADD_RESOURCES(${library_name}_RCC ${library_name}.qrc) add_library(${library_name} SHARED - ${ign_gui_add_library_SOURCES} + ${gz_gui_add_library_SOURCES} ${${library_name}_headers_MOC} ${${library_name}_RCC} ) @@ -35,14 +34,14 @@ function(ign_gui_add_library library_name) PUBLIC ${PROJECT_LIBRARY_TARGET_NAME} TINYXML2::TINYXML2 - ${ign_gui_add_library_PUBLIC_LINK_LIBS} + ${gz_gui_add_library_PUBLIC_LINK_LIBS} PRIVATE - ${ign_gui_add_library_PRIVATE_LINK_LIBS} + ${gz_gui_add_library_PRIVATE_LINK_LIBS} ) endfunction() ################################################# -# ign_gui_add_plugin( +# gz_gui_add_plugin( # SOURCES # [PUBLIC_LINK_LIBS ] # [PRIVATE_LINK_LIBS ]) @@ -61,7 +60,7 @@ endfunction() # # [PRIVATE_LINK_LIBS]: Specify a list of libraries to be privately linked. # -function(ign_gui_add_plugin plugin_name) +function(gz_gui_add_plugin plugin_name) set(options) set(oneValueArgs) set(multiValueArgs @@ -71,20 +70,19 @@ function(ign_gui_add_plugin plugin_name) PUBLIC_LINK_LIBS PRIVATE_LINK_LIBS ) + cmake_parse_arguments(gz_gui_add_plugin "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - cmake_parse_arguments(ign_gui_add_plugin "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - ign_gui_add_library(${plugin_name} - SOURCES ${ign_gui_add_plugin_SOURCES} - QT_HEADERS ${ign_gui_add_plugin_QT_HEADERS} - PUBLIC_LINK_LIBS ${ign_gui_add_plugin_PUBLIC_LINK_LIBS} - PRIVATE_LINK_LIBS ${ign_gui_add_plugin_PRIVATE_LINK_LIBS} ignition-plugin${IGN_PLUGIN_VER}::register + gz_gui_add_library(${plugin_name} + SOURCES ${gz_gui_add_plugin_SOURCES} + QT_HEADERS ${gz_gui_add_plugin_QT_HEADERS} + PUBLIC_LINK_LIBS ${gz_gui_add_plugin_PUBLIC_LINK_LIBS} + PRIVATE_LINK_LIBS ${gz_gui_add_plugin_PRIVATE_LINK_LIBS} ignition-plugin${IGN_PLUGIN_VER}::register ) - if(ign_gui_add_plugin_TEST_SOURCES) + if(gz_gui_add_plugin_TEST_SOURCES) ign_build_tests(TYPE UNIT SOURCES - ${ign_gui_add_plugin_TEST_SOURCES} + ${gz_gui_add_plugin_TEST_SOURCES} LIB_DEPS ${IGNITION-GUI_LIBRARIES} TINYXML2::TINYXML2 @@ -105,8 +103,8 @@ function(ign_gui_add_plugin plugin_name) # warning is not important since those members do not need to be interfaced # with. set_source_files_properties( - ${ign_gui_add_plugin_SOURCES} - ${ign_gui_add_plugin_TEST_SOURCES} + ${gz_gui_add_plugin_SOURCES} + ${gz_gui_add_plugin_TEST_SOURCES} COMPILE_FLAGS "/wd4251") endif() diff --git a/src/plugins/camera_tracking/CMakeLists.txt b/src/plugins/camera_tracking/CMakeLists.txt index f235b22f3..9a5239f10 100644 --- a/src/plugins/camera_tracking/CMakeLists.txt +++ b/src/plugins/camera_tracking/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(CameraTracking +gz_gui_add_plugin(CameraTracking SOURCES CameraTracking.cc QT_HEADERS diff --git a/src/plugins/grid_config/CMakeLists.txt b/src/plugins/grid_config/CMakeLists.txt index a17616363..99f52d057 100644 --- a/src/plugins/grid_config/CMakeLists.txt +++ b/src/plugins/grid_config/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(GridConfig +gz_gui_add_plugin(GridConfig SOURCES GridConfig.cc QT_HEADERS diff --git a/src/plugins/image_display/CMakeLists.txt b/src/plugins/image_display/CMakeLists.txt index 85da0c34a..c7cb5df6f 100644 --- a/src/plugins/image_display/CMakeLists.txt +++ b/src/plugins/image_display/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(ImageDisplay +gz_gui_add_plugin(ImageDisplay SOURCES ImageDisplay.cc QT_HEADERS diff --git a/src/plugins/interactive_view_control/CMakeLists.txt b/src/plugins/interactive_view_control/CMakeLists.txt index c1dd0ba76..e9aae7cd9 100644 --- a/src/plugins/interactive_view_control/CMakeLists.txt +++ b/src/plugins/interactive_view_control/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(InteractiveViewControl +gz_gui_add_plugin(InteractiveViewControl SOURCES InteractiveViewControl.cc QT_HEADERS diff --git a/src/plugins/key_publisher/CMakeLists.txt b/src/plugins/key_publisher/CMakeLists.txt index b4b77d4d1..c737d680f 100644 --- a/src/plugins/key_publisher/CMakeLists.txt +++ b/src/plugins/key_publisher/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(KeyPublisher +gz_gui_add_plugin(KeyPublisher SOURCES KeyPublisher.cc QT_HEADERS diff --git a/src/plugins/marker_manager/CMakeLists.txt b/src/plugins/marker_manager/CMakeLists.txt index 42713a762..eddb7a621 100644 --- a/src/plugins/marker_manager/CMakeLists.txt +++ b/src/plugins/marker_manager/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(MarkerManager +gz_gui_add_plugin(MarkerManager SOURCES MarkerManager.cc QT_HEADERS diff --git a/src/plugins/minimal_scene/CMakeLists.txt b/src/plugins/minimal_scene/CMakeLists.txt index a5ac7cd4b..4d938d58e 100644 --- a/src/plugins/minimal_scene/CMakeLists.txt +++ b/src/plugins/minimal_scene/CMakeLists.txt @@ -19,7 +19,7 @@ if (APPLE) ) endif() -ign_gui_add_plugin(MinimalScene +gz_gui_add_plugin(MinimalScene SOURCES ${SOURCES} QT_HEADERS diff --git a/src/plugins/navsat_map/CMakeLists.txt b/src/plugins/navsat_map/CMakeLists.txt index 4738f999d..887601742 100644 --- a/src/plugins/navsat_map/CMakeLists.txt +++ b/src/plugins/navsat_map/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(NavSatMap +gz_gui_add_plugin(NavSatMap SOURCES NavSatMap.cc QT_HEADERS diff --git a/src/plugins/plotting/CMakeLists.txt b/src/plugins/plotting/CMakeLists.txt index 74469b587..91c66ee89 100644 --- a/src/plugins/plotting/CMakeLists.txt +++ b/src/plugins/plotting/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(TransportPlotting +gz_gui_add_plugin(TransportPlotting SOURCES TransportPlotting.cc QT_HEADERS diff --git a/src/plugins/point_cloud/CMakeLists.txt b/src/plugins/point_cloud/CMakeLists.txt index 0f9f2119a..a21f23dc1 100644 --- a/src/plugins/point_cloud/CMakeLists.txt +++ b/src/plugins/point_cloud/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(PointCloud +gz_gui_add_plugin(PointCloud SOURCES PointCloud.cc QT_HEADERS diff --git a/src/plugins/publisher/CMakeLists.txt b/src/plugins/publisher/CMakeLists.txt index be3d01892..b1c9df011 100644 --- a/src/plugins/publisher/CMakeLists.txt +++ b/src/plugins/publisher/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(Publisher +gz_gui_add_plugin(Publisher SOURCES Publisher.cc QT_HEADERS diff --git a/src/plugins/scene3d/CMakeLists.txt b/src/plugins/scene3d/CMakeLists.txt index 5679bfcf7..e15ba04a2 100644 --- a/src/plugins/scene3d/CMakeLists.txt +++ b/src/plugins/scene3d/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(Scene3D +gz_gui_add_plugin(Scene3D SOURCES Scene3D.cc QT_HEADERS diff --git a/src/plugins/screenshot/CMakeLists.txt b/src/plugins/screenshot/CMakeLists.txt index 9c536da26..0e1c731dd 100644 --- a/src/plugins/screenshot/CMakeLists.txt +++ b/src/plugins/screenshot/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(Screenshot +gz_gui_add_plugin(Screenshot SOURCES Screenshot.cc QT_HEADERS diff --git a/src/plugins/shutdown_button/CMakeLists.txt b/src/plugins/shutdown_button/CMakeLists.txt index 5aae18144..e4fc601c8 100644 --- a/src/plugins/shutdown_button/CMakeLists.txt +++ b/src/plugins/shutdown_button/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(ShutdownButton +gz_gui_add_plugin(ShutdownButton SOURCES ShutdownButton.cc QT_HEADERS diff --git a/src/plugins/tape_measure/CMakeLists.txt b/src/plugins/tape_measure/CMakeLists.txt index bffb62b10..fdc875adb 100644 --- a/src/plugins/tape_measure/CMakeLists.txt +++ b/src/plugins/tape_measure/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(TapeMeasure +gz_gui_add_plugin(TapeMeasure SOURCES TapeMeasure.cc QT_HEADERS TapeMeasure.hh PRIVATE_LINK_LIBS diff --git a/src/plugins/teleop/CMakeLists.txt b/src/plugins/teleop/CMakeLists.txt index a8ebc5bcc..775fbbf99 100644 --- a/src/plugins/teleop/CMakeLists.txt +++ b/src/plugins/teleop/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(Teleop +gz_gui_add_plugin(Teleop SOURCES Teleop.cc QT_HEADERS diff --git a/src/plugins/topic_echo/CMakeLists.txt b/src/plugins/topic_echo/CMakeLists.txt index 2073e501a..6e0d2ca69 100644 --- a/src/plugins/topic_echo/CMakeLists.txt +++ b/src/plugins/topic_echo/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(TopicEcho +gz_gui_add_plugin(TopicEcho SOURCES TopicEcho.cc QT_HEADERS diff --git a/src/plugins/topic_viewer/CMakeLists.txt b/src/plugins/topic_viewer/CMakeLists.txt index 60318d9db..bdb5e564a 100644 --- a/src/plugins/topic_viewer/CMakeLists.txt +++ b/src/plugins/topic_viewer/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(TopicViewer +gz_gui_add_plugin(TopicViewer SOURCES TopicViewer.cc QT_HEADERS diff --git a/src/plugins/transport_scene_manager/CMakeLists.txt b/src/plugins/transport_scene_manager/CMakeLists.txt index 46aa1af1e..b16ae4005 100644 --- a/src/plugins/transport_scene_manager/CMakeLists.txt +++ b/src/plugins/transport_scene_manager/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(TransportSceneManager +gz_gui_add_plugin(TransportSceneManager SOURCES TransportSceneManager.cc QT_HEADERS diff --git a/src/plugins/world_control/CMakeLists.txt b/src/plugins/world_control/CMakeLists.txt index 036f2ea61..5d64eae5d 100644 --- a/src/plugins/world_control/CMakeLists.txt +++ b/src/plugins/world_control/CMakeLists.txt @@ -1,5 +1,5 @@ if (NOT MSVC) - ign_gui_add_plugin(WorldControl + gz_gui_add_plugin(WorldControl SOURCES WorldControl.cc WorldControlEventListener.cc @@ -10,7 +10,7 @@ if (NOT MSVC) WorldControl_TEST.cc ) else() - ign_gui_add_plugin(WorldControl + gz_gui_add_plugin(WorldControl SOURCES WorldControl.cc QT_HEADERS diff --git a/src/plugins/world_stats/CMakeLists.txt b/src/plugins/world_stats/CMakeLists.txt index ad5c4e2ff..d4de14064 100644 --- a/src/plugins/world_stats/CMakeLists.txt +++ b/src/plugins/world_stats/CMakeLists.txt @@ -1,4 +1,4 @@ -ign_gui_add_plugin(WorldStats +gz_gui_add_plugin(WorldStats SOURCES WorldStats.cc QT_HEADERS