summaryrefslogtreecommitdiff
path: root/src/main/python/utils/custom.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/python/utils/custom.py')
-rw-r--r--src/main/python/utils/custom.py289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/main/python/utils/custom.py b/src/main/python/utils/custom.py
new file mode 100644
index 0000000..2c8ffc6
--- /dev/null
+++ b/src/main/python/utils/custom.py
@@ -0,0 +1,289 @@
+"""
+Holds the custom window to generate new symbols, can be called while running or throught the build interface.
+"""
+from PyQt5.QtCore import QRectF, Qt, QSize
+from PyQt5.QtGui import (QBrush, QIcon, QImage, QPainter, QPainterPath, QPen,
+ QPixmap, QTransform)
+from PyQt5.QtSvg import QGraphicsSvgItem
+from PyQt5.QtWidgets import (QBoxLayout, QDialog, QFileDialog,
+ QGraphicsEllipseItem, QGraphicsItem,
+ QGraphicsScene, QGraphicsView, QGridLayout,
+ QInputDialog, QLabel, QLineEdit, QPushButton,
+ QTextEdit)
+
+from shapes import SizeGripItem, directionsEnum
+
+from .app import fileImporter
+
+class ShapeDialog(QDialog):
+ """
+ The main dialog box for the custom symbol window.
+ """
+ def __init__(self, parent=None):
+ super(ShapeDialog, self).__init__(parent)
+ self.resize(500, 300) # resize to a fixed dim
+ self.setWindowTitle("Add New Shapes")
+ self.createLayout()
+ self.graphic = None
+
+ def createLayout(self):
+ #build layout for the dialog box
+ importButton = QPushButton("Import", self)
+ importButton.clicked.connect(self.importSVG)
+
+ saveButton = QPushButton("Save", self)
+ saveButton.clicked.connect(self.saveEvent)
+
+ self.symbolName = QLineEdit(self)
+ self.symbolName.setPlaceholderText("Enter Symbol Name")
+ symbolNameLabel = QLabel("Symbol Name")
+ symbolNameLabel.setBuddy(self.symbolName)
+
+ self.symbolClass = QLineEdit(self)
+ self.symbolClass.setPlaceholderText("Enter Symbol Class Name")
+ symbolClassLabel = QLabel("Symbol Class Name")
+ symbolClassLabel.setBuddy(self.symbolClass)
+
+ self.symbolCategory = QLineEdit(self)
+ self.symbolCategory.setPlaceholderText("Enter Symbol Category")
+ symbolCategoryLabel = QLabel("Symbol Category")
+ symbolCategoryLabel.setBuddy(self.symbolCategory)
+
+ addGripItem = QPushButton("Add Grip Item", self)
+ addGripItem.clicked.connect(self.addGrip)
+ addLineGripItem = QPushButton("Add Line Grip Item", self)
+ addLineGripItem.clicked.connect(self.addLineGrip)
+
+ self.painter = QGraphicsScene()
+ view = QGraphicsView(self.painter)
+
+ layout = QGridLayout(self)
+
+ subLayout = QBoxLayout(QBoxLayout.LeftToRight)
+ subLayout.addWidget(importButton)
+ subLayout.addWidget(saveButton)
+ subLayout.addStretch(1)
+
+ layout.addLayout(subLayout, 0, 0, 1, -1)
+
+ subLayout2 = QBoxLayout(QBoxLayout.LeftToRight)
+ subLayout2.addWidget(view, stretch=1)
+
+ subLayout3 = QBoxLayout(QBoxLayout.TopToBottom)
+ subLayout3.addWidget(symbolNameLabel)
+ subLayout3.addWidget(self.symbolName)
+ subLayout3.addWidget(symbolClassLabel)
+ subLayout3.addWidget(self.symbolClass)
+ subLayout3.addWidget(symbolCategoryLabel)
+ subLayout3.addWidget(self.symbolCategory)
+ subLayout3.addStretch(1)
+ subLayout3.addWidget(addGripItem)
+ subLayout3.addWidget(addLineGripItem)
+ subLayout2.addLayout(subLayout3)
+
+ layout.addLayout(subLayout2, 1, 0, -1, -1)
+ self.setLayout(layout)
+
+ def importSVG(self):
+ # Imports svg file through user input, adds it to the scene and stores it as a reference
+ self.name = QFileDialog.getOpenFileName(self, 'Open SVG File', '', 'Scalable Vector Graphics (*svg)')
+ if self.name:
+ self.graphic = QGraphicsSvgItem(self.name[0])
+ self.graphic.setZValue(-1)
+ self.painter.addItem(self.graphic)
+
+ def saveEvent(self):
+ # executes the build procedure
+
+ #check if all necessary values are there, each is seperate to show qalerts later on
+ if self.graphic is None:
+ return
+
+ itemName = self.symbolName.text()
+ if itemName is '':
+ return
+
+ className = self.symbolClass.text()
+ if className is '':
+ return
+
+ category = self.symbolCategory.text()
+ if category == "":
+ category = "misc"
+
+ # get rect for calculating grip positions
+ graphicRect = self.graphic.boundingRect()
+
+ #save file
+ name = QFileDialog.getSaveFileName(self, 'Save Icon', className, 'PNG (*.png)')
+ if name:
+ QIcon(self.name[0]).pixmap(QSize(64, 64)).toImage().save(name[0])
+ else:
+ return
+
+ #calculate grip positions and build a list
+ gripList = []
+ x, y, w, h = graphicRect.getRect()
+ for i in self.grips:
+ pos = i.pos()
+ entry = [abs((x-pos.x())/w)*100, abs((y-pos.y())/h)*100, i.location]
+ if isinstance(i, gripRect):
+ if i.location in ["top", "bottom"]:
+ entry.append(i.height)
+ else:
+ entry.append(i.width)
+ gripList.append(entry)
+
+ # format list in class definition flavor
+ grips = ",\n ".join([str(i) for i in gripList]) if gripList else ""
+ if grips:
+ grips = "self.grips = [" + grips + "]\n"
+
+ # build output dialog box
+ temp = QDialog(self)
+ tempLayout = QBoxLayout(QBoxLayout.TopToBottom)
+ output = OutputBox(temp, f"""
+<b> Class Definition:</b>
+<pre>
+class {className}(NodeItem):
+ def __init__(self):
+ super({className}, self).__init__("svg/{category}/{str.split(name[0], "/")[-1][:-4]}")
+ {grips}
+</pre>
+<b> Items.json entry:</b>
+<pre>
+"{category}": {{
+ "{itemName}": {{
+ "name": "{itemName}",
+ "icon": ".\\{category}\\{str.split(name[0], "/")[-1]}",
+ "class": "{category}",
+ "object": "{className}",
+ "args": []
+ }}
+}}</pre>""")
+ tempLayout.addWidget(output)
+ temp.setLayout(tempLayout)
+ temp.exec()
+
+ @property
+ def grips(self):
+ return [i for i in self.painter.items() if isinstance(i, gripAbstract)]
+
+ def addGrip(self):
+ #adds a grip dot to the scene
+ grip = gripDot()
+ self.painter.addItem(grip)
+
+ def addLineGrip(self):
+ #adds a line grip item
+ rect = gripRect()
+ self.painter.addItem(rect)
+
+class gripAbstract(QGraphicsItem):
+ """
+ Abstract class for mouse click behaviour
+ """
+ def __init__(self):
+ super(gripAbstract, self).__init__()
+ self.location = "top"
+ self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
+
+ def mouseDoubleClickEvent(self, event):
+ self.location, _ = QInputDialog.getItem(None, "Change location", "Select location", directionsEnum,
+ directionsEnum.index(self.location), False)
+
+class gripRect(gripAbstract):
+ """
+ simulates line grip item with resizeablity
+ (Haha grip items on grip items. Progress)
+ """
+ def __init__(self, x=0, y=0, w=80, h=10 ):
+ super(gripRect, self).__init__()
+ self.rotation = 0
+ self.sizeGripItems = []
+ self.width = w
+ self.height = h
+ self.setFlag(QGraphicsItem.ItemSendsGeometryChanges)
+
+ #bounding rect and paint need to be implemented
+ def boundingRect(self):
+ return QRectF(-self.width / 2, -self.height / 2, self.width, self.height)
+
+ def paint(self, painter, option, index):
+ painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
+ painter.setBrush(QBrush(Qt.red))
+ painter.drawRect(self.boundingRect())
+
+ def addGripItems(self):
+ # adds the resizeable line grip items from the shape file :D
+ for i, (direction) in enumerate((Qt.Vertical,
+ Qt.Horizontal,
+ Qt.Vertical,
+ Qt.Horizontal)):
+ self.sizeGripItems.append(SizeGripItem(i, direction, parent=self))
+
+ def updateSizeGripItem(self, index_no_updates=None):
+ #update positions for existing grip items
+ index_no_updates = index_no_updates or []
+ for i, item in enumerate(self.sizeGripItems):
+ if i not in index_no_updates:
+ item.updatePosition()
+
+ def itemChange(self, change, value):
+ #do the needful when item is updated
+ if change == QGraphicsItem.ItemPositionHasChanged:
+ # update grips
+ self.updateSizeGripItem()
+ return
+ # check if item is add on scene
+ if change == QGraphicsItem.ItemSceneHasChanged and self.scene():
+ # add grips and update them
+ self.addGripItems()
+ self.updateSizeGripItem()
+ return
+ return super(gripRect, self).itemChange(change, value)
+
+ def resize(self, index, movement):
+ #resize method
+ self.prepareGeometryChange()
+ if index in [0, 1]:
+ self.width -= movement.x()
+ self.height -= movement.y()
+ else:
+ self.width += movement.x()
+ self.height += movement.y()
+ transform = QTransform()
+ transform.translate(movement.x() / 2, movement.y() / 2)
+ self.setTransform(transform, True)
+ self.updateSizeGripItem([index])
+
+class gripDot(gripAbstract):
+ """
+ class for circular grips
+ """
+ def boundingRect(self):
+ return QRectF(0, 0, 10, 10)
+
+ def paint(self, painter, option, index):
+ painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
+ painter.setBrush(QBrush(Qt.red))
+ painter.drawEllipse(self.boundingRect())
+
+class OutputBox(QTextEdit):
+ """
+ Defines a read only text box for class output
+ """
+ def __init__(self, parent, text):
+ super(OutputBox, self).__init__(parent)
+ self.setReadOnly(True)
+ self.setFontWeight(10)
+ self.setHtml(text)
+
+def main(): # 1. Instantiate ApplicationContext
+ #if app is launched directly
+ from .app import app
+ import sys
+ main = ShapeDialog()
+ main.show()
+ exit_code = app.app.exec_() # 2. Invoke app.app.exec_()
+ sys.exit(exit_code) \ No newline at end of file