Skip to content

Commit

Permalink
Merge pull request #3364 from AbdelbakiBoukerche/feature_rounded_rect…
Browse files Browse the repository at this point in the history
…angle

Rounded Rectangle
  • Loading branch information
grossmj committed Aug 1, 2023
2 parents 354f3ee + eae9eec commit aa9b9d3
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 11 deletions.
16 changes: 15 additions & 1 deletion gns3/dialogs/style_editor_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ..qt import QtCore, QtWidgets, QtGui
from ..ui.style_editor_dialog_ui import Ui_StyleEditorDialog
from ..items.shape_item import ShapeItem
from ..items.rectangle_item import RectangleItem


class StyleEditorDialog(QtWidgets.QDialog, Ui_StyleEditorDialog):
Expand Down Expand Up @@ -70,6 +71,13 @@ def __init__(self, parent, items):
self._border_color.green(),
self._border_color.blue(),
self._border_color.alpha()))
if isinstance(first_item, RectangleItem):
# use the horizontal corner radius first and then the vertical one if it's not set
# maybe we allow configuring them separately in the future
corner_radius = first_item.horizontalCornerRadius()
if not corner_radius:
corner_radius = first_item.verticalCornerRadius()
self.uiCornerRadiusSpinBox.setValue(corner_radius)
self.uiRotationSpinBox.setValue(int(first_item.rotation()))
self.uiBorderWidthSpinBox.setValue(pen.width())
index = self.uiBorderStyleComboBox.findData(pen.style())
Expand Down Expand Up @@ -116,10 +124,16 @@ def _applyPreferencesSlot(self):

for item in self._items:
item.setPen(pen)
# on multiselection it's possible to select many type of items
# on multi-selection it's possible to select many type of items
# but brush can be applied only on ShapeItem,
if brush and isinstance(item, ShapeItem):
item.setBrush(brush)
if isinstance(item, RectangleItem):
corner_radius = self.uiCornerRadiusSpinBox.value()
# use the corner radius for both horizontal (rx) and vertical (ry)
# maybe we support setting them separately in the future
item.setHorizontalCornerRadius(corner_radius)
item.setVerticalCornerRadius(corner_radius)
item.setRotation(self.uiRotationSpinBox.value())

def done(self, result):
Expand Down
4 changes: 3 additions & 1 deletion gns3/dialogs/style_editor_dialog_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ def __init__(self, link, parent):
self.uiColorLabel.hide()
self.uiColorPushButton.hide()
self._color = None


self.uiCornerRadiusLabel.hide()
self.uiCornerRadiusSpinBox.hide()
self.uiRotationLabel.hide()
self.uiRotationSpinBox.hide()

Expand Down
38 changes: 37 additions & 1 deletion gns3/items/rectangle_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,22 @@ class RectangleItem(QtWidgets.QGraphicsRectItem, ShapeItem):
"""

def __init__(self, width=200, height=100, **kws):
self._rx = 0
self._ry = 0
super().__init__(width=width, height=height, **kws)

def setHorizontalCornerRadius(self, radius: int):
self._rx = radius

def horizontalCornerRadius(self):
return self._rx

def setVerticalCornerRadius(self, radius: int):
self._ry = radius

def verticalCornerRadius(self):
return self._ry

def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
Expand All @@ -43,7 +57,9 @@ def paint(self, painter, option, widget=None):
:param widget: QWidget instance
"""

super().paint(painter, option, widget)
painter.setPen(self.pen())
painter.setBrush(self.brush())
painter.drawRoundedRect(self.rect(), self._rx, self._ry)
self.drawLayerInfo(painter)

def toSvg(self):
Expand All @@ -57,7 +73,27 @@ def toSvg(self):
rect = ET.SubElement(svg, "rect")
rect.set("width", str(int(self.rect().width())))
rect.set("height", str(int(self.rect().height())))
if self._rx:
rect.set("rx", str(self._rx))
if self._ry:
rect.set("ry", str(self._ry))

rect = self._styleSvg(rect)

return ET.tostring(svg, encoding="utf-8").decode("utf-8")

def fromSvg(self, svg):
svg_elem = ET.fromstring(svg)
if len(svg_elem):
# handle horizontal corner radius and vertical corner radius (specific to rectangles)
rx = svg_elem[0].get("rx")
ry = svg_elem[0].get("ry")
if rx:
self._rx = int(rx)
elif ry:
self._rx = int(ry) # defaults to ry if it is specified
if ry:
self._ry = int(ry)
elif rx:
self._ry = int(rx) # defaults to rx if it is specified
super().fromSvg(svg)
2 changes: 1 addition & 1 deletion gns3/items/shape_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def hoverLeaveEvent(self, event):

def fromSvg(self, svg):
"""
Import element informations from an SVG
Import element information from SVG
"""
svg = ET.fromstring(svg)
width = float(svg.get("width", self.rect().width()))
Expand Down
29 changes: 27 additions & 2 deletions gns3/ui/style_editor_dialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
<ui version="4.0">
<class>StyleEditorDialog</class>
<widget class="QDialog" name="StyleEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>270</width>
<height>294</height>
</rect>
</property>
<property name="windowTitle">
<string>Style editor</string>
</property>
Expand Down Expand Up @@ -76,14 +84,14 @@
<item row="3" column="1">
<widget class="QComboBox" name="uiBorderStyleComboBox"/>
</item>
<item row="4" column="0">
<item row="5" column="0">
<widget class="QLabel" name="uiRotationLabel">
<property name="text">
<string>Rotation:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QSpinBox" name="uiRotationSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
Expand All @@ -106,6 +114,23 @@ editing (notes only) with ALT and '+' (or P) / ALT and '-' (or M)</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="uiCornerRadiusLabel">
<property name="text">
<string>Corner radius:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="uiCornerRadiusSpinBox">
<property name="suffix">
<string>°</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down
20 changes: 15 additions & 5 deletions gns3/ui/style_editor_dialog_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/style_editor_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
Expand All @@ -14,6 +14,7 @@
class Ui_StyleEditorDialog(object):
def setupUi(self, StyleEditorDialog):
StyleEditorDialog.setObjectName("StyleEditorDialog")
StyleEditorDialog.resize(270, 294)
StyleEditorDialog.setModal(True)
self.verticalLayout = QtWidgets.QVBoxLayout(StyleEditorDialog)
self.verticalLayout.setObjectName("verticalLayout")
Expand Down Expand Up @@ -52,7 +53,7 @@ def setupUi(self, StyleEditorDialog):
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.uiBorderStyleComboBox)
self.uiRotationLabel = QtWidgets.QLabel(self.uiStyleSettingsGroupBox)
self.uiRotationLabel.setObjectName("uiRotationLabel")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.uiRotationLabel)
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.uiRotationLabel)
self.uiRotationSpinBox = QtWidgets.QSpinBox(self.uiStyleSettingsGroupBox)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
Expand All @@ -62,7 +63,14 @@ def setupUi(self, StyleEditorDialog):
self.uiRotationSpinBox.setMinimum(-360)
self.uiRotationSpinBox.setMaximum(360)
self.uiRotationSpinBox.setObjectName("uiRotationSpinBox")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.uiRotationSpinBox)
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.uiRotationSpinBox)
self.uiCornerRadiusLabel = QtWidgets.QLabel(self.uiStyleSettingsGroupBox)
self.uiCornerRadiusLabel.setObjectName("uiCornerRadiusLabel")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.uiCornerRadiusLabel)
self.uiCornerRadiusSpinBox = QtWidgets.QSpinBox(self.uiStyleSettingsGroupBox)
self.uiCornerRadiusSpinBox.setMaximum(100)
self.uiCornerRadiusSpinBox.setObjectName("uiCornerRadiusSpinBox")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.uiCornerRadiusSpinBox)
self.verticalLayout.addWidget(self.uiStyleSettingsGroupBox)
self.uiButtonBox = QtWidgets.QDialogButtonBox(StyleEditorDialog)
self.uiButtonBox.setOrientation(QtCore.Qt.Horizontal)
Expand All @@ -73,8 +81,8 @@ def setupUi(self, StyleEditorDialog):
self.verticalLayout.addItem(spacerItem)

self.retranslateUi(StyleEditorDialog)
self.uiButtonBox.accepted.connect(StyleEditorDialog.accept)
self.uiButtonBox.rejected.connect(StyleEditorDialog.reject)
self.uiButtonBox.accepted.connect(StyleEditorDialog.accept) # type: ignore
self.uiButtonBox.rejected.connect(StyleEditorDialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(StyleEditorDialog)

def retranslateUi(self, StyleEditorDialog):
Expand All @@ -90,4 +98,6 @@ def retranslateUi(self, StyleEditorDialog):
self.uiRotationSpinBox.setToolTip(_translate("StyleEditorDialog", "Rotation can be ajusted on the scene for a selected item while\n"
"editing (notes only) with ALT and \'+\' (or P) / ALT and \'-\' (or M)"))
self.uiRotationSpinBox.setSuffix(_translate("StyleEditorDialog", "°"))
self.uiCornerRadiusLabel.setText(_translate("StyleEditorDialog", "Corner radius:"))
self.uiCornerRadiusSpinBox.setSuffix(_translate("StyleEditorDialog", "°"))
from . import resources_rc

0 comments on commit aa9b9d3

Please sign in to comment.