diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/python/main.py | 20 | ||||
-rw-r--r-- | src/main/python/shapes/shapes.py | 41 | ||||
-rw-r--r-- | src/main/python/utils/graphics.py | 109 | ||||
-rw-r--r-- | src/main/resources/base/config/items.json | 4 |
4 files changed, 154 insertions, 20 deletions
diff --git a/src/main/python/main.py b/src/main/python/main.py index 5af252d..de8a12b 100644 --- a/src/main/python/main.py +++ b/src/main/python/main.py @@ -26,7 +26,10 @@ class appWindow(QMainWindow): #create the menu bar self.createMenuBar() - + + #used for file name + self.counterr = 0 + self.mdi = QMdiArea(self) #create area for files to be displayed self.mdi.setObjectName('mdi area') @@ -139,8 +142,19 @@ class appWindow(QMainWindow): return True def saveImage(self): - #place holder for future implementaion - pass + #save the scene as png or jpg + if self.mdi.currentSubWindow(): + currentDiagram = self.mdi.currentSubWindow().tabber.currentWidget().painter + if currentDiagram: + name = QFileDialog.getSaveFileName(self, 'Save File', f'New Image {self.counterr}', 'PNG (*.png);;JPEG (*.jpg)') + if name[0]: + image = QImage(currentDiagram.sceneRect().size().toSize(), QImage.Format_ARGB32) + image.fill(Qt.transparent) + painter = QPainter(image) + currentDiagram.render(painter) + image.save(name[0]) + self.counterr += 1 + painter.end() def generateReport(self): #place holder for future implementaion diff --git a/src/main/python/shapes/shapes.py b/src/main/python/shapes/shapes.py index a67e8dc..55d1751 100644 --- a/src/main/python/shapes/shapes.py +++ b/src/main/python/shapes/shapes.py @@ -767,7 +767,7 @@ class NodeItem(QGraphicsSvgItem): class InflowLine(NodeItem): def __init__(self): - super(InflowLine, self).__init__("svg/piping/Inflow Line") + super(InflowLine, self).__init__("svg/Piping/Inflow Line") self.grips = [ [100, 50, "right"] ] @@ -931,14 +931,34 @@ class SolidFuelFurnace(NodeItem): ] +class Exchanger905(NodeItem): + def __init__(self): + super(Exchanger905, self).__init__("svg/Heating or Cooling Arrangements/905Exchanger") + self.grips = [ + [15.85, 13.5, "bottom", 11.21], + [60.5, 13.5, "bottom", 55.33], + [15.85, 88.88, "top", 11.21], + [60.5, 88.88, "top", 55.33] + ] + +class KettleReboiler907(NodeItem): + def __init__(self): + super(KettleReboiler907, self).__init__("svg/Heating or Cooling Arrangements/907Kettle Reboiler") + self.grips = [ + [18, 20.33, "bottom", 18], + [70, 20.33, "bottom", 40.33], + [18, 75, "top", 18], + [70, 96, "top", 40.33] + ] + class Exchanger(NodeItem): def __init__(self): super(Exchanger, self).__init__("svg/Heating or Cooling Arrangements/Exchanger") self.grips = [ [100, 31.74474612706027, "right"], [100, 62.70549343934227, "right"], - [33.68240920045628, 100, "top"], - [33.68240920045628, 0, "bottom"] + [35.66, 100, "top"], + [36.66, 0, "bottom"] ] @@ -961,6 +981,15 @@ class ImmersionCoil(NodeItem): [88.232463407718, 100, "top"] ] +class KettleReboiler(NodeItem): + def __init__(self): + super(KettleReboiler, self).__init__("svg/Heating or Cooling Arrangements/Kettle Reboiler") + self.grips = [ + [100, 26.3, "right"], + [0, 26.3, "left"], + [50, 100, "top"], + [50, 0, "bottom"] + ] class HorizontalVessel(NodeItem): def __init__(self): @@ -1066,11 +1095,11 @@ class OneCellFiredHeaterFurnace(NodeItem): super(OneCellFiredHeaterFurnace, self).__init__("svg/Furnaces and Boilers/One Cell Fired Heater, Furnace") self.grips = [ [50, 100, "top"], - [0-7, 25, "left", 50], + [0, 28, "left", 45], [25, 87.5, "left", 25], - [100+7, 25, "right", 50], + [100, 28, "right", 45], [75, 87.5, "right", 25], - [50, 0-10, "bottom", 100] + [50, 0-5, "bottom", 100] ] diff --git a/src/main/python/utils/graphics.py b/src/main/python/utils/graphics.py index 80eb5e7..a4b3916 100644 --- a/src/main/python/utils/graphics.py +++ b/src/main/python/utils/graphics.py @@ -1,4 +1,7 @@ +from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt5.QtCore import Qt, QRectF, QPointF from PyQt5.QtCore import Qt, QPointF, pyqtSignal +from PyQt5.QtWidgets import QGraphicsScene, QApplication from PyQt5.QtGui import QPen, QKeySequence, QTransform, QCursor from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsProxyWidget, QGraphicsItem, QUndoStack, QAction, QUndoView @@ -73,16 +76,18 @@ class CustomView(QGraphicsView): temp = self.zoom self._zoom = value self.scale(self.zoom / temp, self.zoom / temp) - + class CustomScene(QGraphicsScene): """ Extends QGraphicsScene with undo-redo functionality """ labelAdded = pyqtSignal(shapes.QGraphicsItem) - + itemMoved = QtCore.pyqtSignal(QtWidgets.QGraphicsItem, QtCore.QPointF) + def __init__(self, *args, parent=None): super(CustomScene, self).__init__(*args, parent=parent) - + self.movingItems = [] # List to store selected items for moving + self.oldPositions = {} # Dictionary to store old positions of moved items self.undoStack = QUndoStack(self) #Used to store undo-redo moves self.createActions() #creates necessary actions that need to be called for undo-redo @@ -91,12 +96,12 @@ class CustomScene(QGraphicsScene): self.deleteAction = QAction("Delete Item", self) self.deleteAction.setShortcut(Qt.Key_Delete) self.deleteAction.triggered.connect(self.deleteItem) - + self.undoAction = self.undoStack.createUndoAction(self, "Undo") self.undoAction.setShortcut(QKeySequence.Undo) self.redoAction = self.undoStack.createRedoAction(self, "Redo") self.redoAction.setShortcut(QKeySequence.Redo) - + def createUndoView(self, parent): # creates an undo stack view for current QGraphicsScene undoView = QUndoView(self.undoStack, parent) @@ -115,17 +120,101 @@ class CustomScene(QGraphicsScene): self.count+=1 self.undoStack.push(deleteCommand(j, self)) self.undoStack.push(deleteCommand(itemToDelete, self)) - + def itemMoved(self, movedItem, lastPos): #item move event, checks if item is moved self.undoStack.push(moveCommand(movedItem, lastPos)) self.advance() - + def addItemPlus(self, item): # extended add item method, so that a corresponding undo action is also pushed self.undoStack.push(addCommand(item, self)) - + def mousePressEvent(self, event): + bdsp = event.buttonDownScenePos(Qt.LeftButton) # Get click position + point = QPointF(bdsp.x(), bdsp.y()) # Create a QPointF from click position + itemList = self.items(point) # Get items at the specified point + if itemList: + item = itemList[0] # Select the first item in the list + if event.button() == Qt.LeftButton: + modifiers = QApplication.keyboardModifiers() + if modifiers == Qt.ControlModifier: + # Ctrl key is pressed, add item to the moving items list + if item not in self.movingItems: + self.movingItems.append(item) + self.oldPositions[item] = item.pos() + else: + # Ctrl key is not pressed, clear the moving items list and selection + self.movingItems.clear() + self.clearSelection() + item.setSelected(True) + + return super(CustomScene, self).mousePressEvent(event) + + + def mouseReleaseEvent(self, event): + if event.button() == QtCore.Qt.LeftButton: + for item in self.movingItems: + if self.oldPositions[item] != item.pos(): + # Item position has changed, invoke the callback function + self.itemMoved(item, self.oldPositions[item]) + self.movingItems.clear() # Clear the moving items list + self.oldPositions.clear() # Clear the old positions dictionary + + return super(CustomScene, self).mouseReleaseEvent(event) + + + def mouseMoveEvent(self, mouseEvent): + if self.movingItems: + # Move all selected items together + for item in self.movingItems: + newPos = item.pos() + mouseEvent.scenePos() - mouseEvent.lastScenePos() + item.setPos(newPos) + + item = self.itemAt(mouseEvent.scenePos().x(), mouseEvent.scenePos().y(), QTransform()) + if isinstance(item, shapes.SizeGripItem): + item.parentItem().showLineGripItem() + + return super(CustomScene, self).mouseMoveEvent(mouseEvent) + + # The above is the mouse events for moving multiple images at once. + + """def mousePressEvent(self, event): + bdsp = event.buttonDownScenePos(Qt.LeftButton) # get click pos + point = QPointF(bdsp.x(), bdsp.y()) # create a QPointF from click pos + itemList = self.items(point) # get items at said point + if event.button() == Qt.LeftButton: + if itemList: + self.movingItems = itemList + self.initialPositions = {} + for item in self.movingItems: + self.initialPositions[item] = item.pos() + else: + self.movingItems = [] + self.clearSelection() + return super(CustomScene, self).mousePressEvent(event) + + def mouseMoveEvent(self, event): + if event.buttons() == Qt.LeftButton and self.movingItems: + modifiers = QApplication.keyboardModifiers() + if modifiers == Qt.ControlModifier: + for item in self.movingItems: + item.setPos(item.pos() + event.scenePos() - event.lastScenePos()) + else: + super(CustomScene, self).mouseMoveEvent(event) + + def mouseReleaseEvent(self, event): + if event.button() == Qt.LeftButton and self.movingItems: + for item in self.movingItems: + if item.pos() != self.initialPositions[item]: + self.itemMoved(item, self.initialPositions[item]) + self.movingItems = [] + self.initialPositions = {} + return super(CustomScene, self).mouseReleaseEvent(event)""" + + # The above mouse events are for moving items on top of each other. + + """def mousePressEvent(self, event): # overloaded mouse press event to check if an item was moved bdsp = event.buttonDownScenePos(Qt.LeftButton) #get click pos point = QPointF(bdsp.x(), bdsp.y()) #create a Qpoint from click pos @@ -150,7 +239,9 @@ class CustomScene(QGraphicsScene): QTransform()) if isinstance(item,shapes.SizeGripItem): item.parentItem().showLineGripItem() - super(CustomScene,self).mouseMoveEvent(mouseEvent) + super(CustomScene,self).mouseMoveEvent(mouseEvent)""" + + # The above is the original mouse events def reInsertLines(self): currentIndex = self.undoStack.index() diff --git a/src/main/resources/base/config/items.json b/src/main/resources/base/config/items.json index b1972a1..2815ad0 100644 --- a/src/main/resources/base/config/items.json +++ b/src/main/resources/base/config/items.json @@ -78,14 +78,14 @@ "name": "Exchanger", "icon": "./Heating or Cooling Arrangements/905Exchanger.png", "class": "Heating or Cooling Arrangements", - "object": "Exchanger", + "object": "Exchanger905", "args": [] }, "907Kettle Reboiler": { "name": "Kettle Reboiler", "icon": "./Heating or Cooling Arrangements/907Kettle Reboiler.png", "class": "Heating or Cooling Arrangements", - "object": "KettleReboiler", + "object": "KettleReboiler907", "args": [] }, "Exchanger": { |