diff --git a/Migration.md b/Migration.md
index 7d5d01111..a41cb56c6 100644
--- a/Migration.md
+++ b/Migration.md
@@ -26,6 +26,8 @@ release will remove the deprecated code.
* CMake `-config` files
* Paths that depend on the project name
+* QML `import ignition.gui 1.0` is deprecated, use `import gz.gui 1.0` instead.
+
## Gazebo GUI 6.2 to 6.3
* New QML dependencies, only needed for the NavSatMap plugin: `qml-module-qtlocation`, `qml-module-qtpositioning`
diff --git a/examples/config/plugin_params.config b/examples/config/plugin_params.config
index 4e68df600..aa11951d5 100644
--- a/examples/config/plugin_params.config
+++ b/examples/config/plugin_params.config
@@ -16,7 +16,7 @@
Properties passed directly to the QML card.
It includes:
* All Pane properties: https://doc.qt.io/qt-5/qml-qtquick-controls2-pane-members.html
- * All custom properties within IgnCard.qml
+ * All custom properties within GzCard.qml
-->
false
350
diff --git a/examples/plugin/gz_components/GzComponents.qml b/examples/plugin/gz_components/GzComponents.qml
index 8e516d93b..d1d921be9 100644
--- a/examples/plugin/gz_components/GzComponents.qml
+++ b/examples/plugin/gz_components/GzComponents.qml
@@ -16,7 +16,7 @@
*/
import QtQuick 2.9
import QtQuick.Controls 2.0
-import "qrc:/qml"
+import gz.gui 1.0
Column {
anchors.fill: parent
@@ -40,4 +40,13 @@ Column {
value: 5.8
width: 300
}
+
+ // Deprecated spin box
+ IgnSpinBox {
+ minimumValue: -2
+ maximumValue: 19
+ decimals: 0
+ stepSize: 3
+ value: 5
+ }
}
diff --git a/include/gz/gui/qml/qmldir b/include/gz/gui/qml/qmldir
index 486b6c7aa..ff97d847b 100644
--- a/include/gz/gui/qml/qmldir
+++ b/include/gz/gui/qml/qmldir
@@ -1,3 +1,8 @@
module gz.gui
+GzSnackBar 1.0 GzSnackBar.qml
GzSpinBox 1.0 GzSpinBox.qml
+
+# Deprecated components, remove on tock
+IgnSnackBar 1.0 GzSnackBar.qml
+IgnSpinBox 1.0 GzSpinBox.qml
diff --git a/include/gz/gui/qml/qmldir_deprecated b/include/gz/gui/qml/qmldir_deprecated
new file mode 100644
index 000000000..4bd7fa37b
--- /dev/null
+++ b/include/gz/gui/qml/qmldir_deprecated
@@ -0,0 +1,8 @@
+# Deprecated module, remove on tock
+module ignition.gui
+
+GzSnackBar 1.0 GzSnackBar.qml
+GzSpinBox 1.0 GzSpinBox.qml
+
+IgnSnackBar 1.0 GzSnackBar.qml
+IgnSpinBox 1.0 GzSpinBox.qml
diff --git a/include/gz/gui/resources.qrc b/include/gz/gui/resources.qrc
index 325a5485f..eaebd40a6 100644
--- a/include/gz/gui/resources.qrc
+++ b/include/gz/gui/resources.qrc
@@ -23,25 +23,21 @@
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/GzSnackBar.qml
qml/GzSpinBox.qml
- qml/GzSnackBar.qml
- qml/GzSpinBox.qml
+
+
+
+
+ qml/qmldir_deprecated
+ qml/GzSnackBar.qml
+ qml/GzSpinBox.qml
diff --git a/include/ignition/gui/qml/Chart.qml b/include/ignition/gui/qml/Chart.qml
deleted file mode 100644
index cd3a259d7..000000000
--- a/include/ignition/gui/qml/Chart.qml
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * 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
deleted file mode 100644
index c9b5031fa..000000000
--- a/include/ignition/gui/qml/IgnCard.qml
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 313fcf82e..000000000
--- a/include/ignition/gui/qml/IgnCardSettings.qml
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 57c0619b3..000000000
--- a/include/ignition/gui/qml/IgnHelpers.qml
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 1595389cd..000000000
--- a/include/ignition/gui/qml/IgnRulers.qml
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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
deleted file mode 100644
index f4f2dc3c8..000000000
--- a/include/ignition/gui/qml/IgnSnackBar.qml
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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
deleted file mode 100644
index f127d27ab..000000000
--- a/include/ignition/gui/qml/IgnSortFilterModel.qml
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 800db5e11..000000000
--- a/include/ignition/gui/qml/IgnSpinBox.qml
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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
deleted file mode 100644
index d41ca0a45..000000000
--- a/include/ignition/gui/qml/IgnSplit.qml
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 15d5ba89e..000000000
--- a/include/ignition/gui/qml/Main.qml
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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("Gazebo 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: "Gazebo 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
deleted file mode 100644
index 168d3a862..000000000
--- a/include/ignition/gui/qml/PlottingInterface.qml
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 68de63a7c..000000000
--- a/include/ignition/gui/qml/PluginMenu.qml
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 3b6c63c9f..000000000
--- a/include/ignition/gui/qml/SideDrawer.qml
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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
deleted file mode 100644
index a55864499..000000000
--- a/include/ignition/gui/qml/StandaloneDialog.qml
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 7845f2ed2..000000000
--- a/include/ignition/gui/qml/StyleDialog.qml
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * 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
deleted file mode 100644
index bb1cd2fe4..000000000
Binary files a/include/ignition/gui/qml/images/drawer.png and /dev/null differ
diff --git a/include/ignition/gui/qml/images/export_icon.png b/include/ignition/gui/qml/images/export_icon.png
deleted file mode 100644
index 50ef4e445..000000000
Binary files a/include/ignition/gui/qml/images/export_icon.png and /dev/null differ
diff --git a/include/ignition/gui/qml/images/menu.png b/include/ignition/gui/qml/images/menu.png
deleted file mode 100644
index a10473d9e..000000000
Binary files a/include/ignition/gui/qml/images/menu.png and /dev/null differ
diff --git a/include/ignition/gui/qml/images/search.svg b/include/ignition/gui/qml/images/search.svg
deleted file mode 100644
index 40ab947b2..000000000
--- a/include/ignition/gui/qml/images/search.svg
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
diff --git a/include/ignition/gui/qml/qmldir b/include/ignition/gui/qml/qmldir
deleted file mode 100644
index f4f66ebc1..000000000
--- a/include/ignition/gui/qml/qmldir
+++ /dev/null
@@ -1,3 +0,0 @@
-module ignition.gui
-
-IgnSpinBox 1.0 IgnSpinBox.qml
\ No newline at end of file
diff --git a/include/ignition/gui/qtquickcontrols2.conf b/include/ignition/gui/qtquickcontrols2.conf
deleted file mode 100644
index 7fc23bec9..000000000
--- a/include/ignition/gui/qtquickcontrols2.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-[Controls]
-Style=Material
-
-[Material]
-Theme=Light
-Accent=LightBlue
-Primary=DeepOrange
diff --git a/include/ignition/gui/resources.qrc b/include/ignition/gui/resources.qrc
deleted file mode 100644
index cb9fb5683..000000000
--- a/include/ignition/gui/resources.qrc
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
- 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/gazebo_logo.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
-
-
diff --git a/src/Plugin.cc b/src/Plugin.cc
index 7c9a07ebc..fb53e5b09 100644
--- a/src/Plugin.cc
+++ b/src/Plugin.cc
@@ -424,7 +424,7 @@ QQuickItem *Plugin::CardItem() const
return this->dataPtr->cardItem;
// Instantiate a card
- std::string qmlFile(":qml/IgnCard.qml");
+ std::string qmlFile(":qml/GzCard.qml");
QQmlComponent cardComp(App()->Engine(),
QString(QString::fromStdString(qmlFile)));
auto cardItem = qobject_cast(cardComp.create());