from functools import partial from collections import defaultdict import sys import numpy as np from OMChem.Flowsheet import Flowsheet from OMChem.MatStm import MatStm import pandas as pd from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import QTextDocument ,QTextCursor ,QTextCharFormat ,QFont ,QPixmap from PyQt5.uic import loadUiType from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QGraphicsProxyWidget, QGraphicsObject, QGraphicsEllipseItem ,QGraphicsPixmapItem,QApplication, QGraphicsView, QGraphicsScene, QHBoxLayout, QWidget, QLabel from PyQt5.QtGui import QBrush ,QTransform ,QMouseEvent import PyQt5.QtGui as QtGui import PyQt5.QtCore as QtCore import PyQt5.QtWidgets as QtWidgets from component_selector import componentSelector from component_selector import * from dockWidget import dockWidget from resDockWidget import resdockWidget import datetime from container import Container class Graphics(QDialog): def __init__(self): QDialog.__init__(self) self.scene = QGraphicsScene() self.scene.setItemIndexMethod(QGraphicsScene.BspTreeIndex) def getScene(self): return self.scene def getComponentSelector(self): return componentSelector(self) def createNodeItem(self,unitOpr): return NodeItem(unitOpr) class NodeLine(QtWidgets.QGraphicsPathItem): def __init__(self, pointA, pointB , socket): super(NodeLine, self).__init__() self._pointA = pointA self._pointB = pointB self.socket = socket self._source = None self._target = None self.setZValue(-1) self.setBrush(QtGui.QColor(0,0,255,255)) self.pen = QtGui.QPen() self.pen.setStyle(QtCore.Qt.SolidLine) self.pen.setWidth(1) self.pen.setColor(QtGui.QColor(0,0,255,255)) self.setPen(self.pen) def updatePath(self): path = QtGui.QPainterPath() path.moveTo(self.pointA) midptx = 0.5*(self.pointA.x() + self.pointB.x()) ctrl1_1 = QtCore.QPointF(self.pointA.x(), self.pointA.y()) ctrl2_1 = QtCore.QPointF(self.pointA.x(), self.pointA.y()) pt1 = QtCore.QPointF(midptx , self.pointA.y()) path.cubicTo(ctrl1_1, ctrl2_1, pt1) path.moveTo(pt1) ctrl1_2 = QtCore.QPointF(midptx, self.pointB.y()) ctrl2_2 = QtCore.QPointF(midptx, self.pointB.y()) pt2 = QtCore.QPointF(midptx , self.pointB.y()) path.cubicTo(ctrl1_2, ctrl2_2, pt2) path.moveTo(pt2) ctrl1_3 = QtCore.QPointF(midptx, self.pointB.y()) ctrl2_3 = QtCore.QPointF(midptx, self.pointB.y()) path.cubicTo(ctrl1_3, ctrl2_3, self.pointB) self.setPath(path) def paint(self, painter, option, widget): painter.setPen(self.pen) painter.drawPath(self.path()) @property def pointA(self): #print('a') return self._pointA @pointA.setter def pointA(self, point): #print('seta') self._pointA = point self.updatePath() @property def pointB(self): #print('b') return self._pointB @pointB.setter def pointB(self, point): #print('set b') self._pointB = point self.updatePath() @property def source(self): #print('source') return self._source @source.setter def source(self, widget): #print('set source') self._source = widget @property def target(self): #print('target') return self._target @target.setter def target(self, widget): #print('set target') self._target = widget def __delete__(self,instance): del self._source del self._target del self._pointA del self._pointB class NodeSocket(QtWidgets.QGraphicsItem): def __init__(self, rect, parent, socketType): super(NodeSocket, self).__init__(parent) self.rect = rect self.type = socketType self.parent=parent self.newLine=None self.otherLine=None # Brush. self.brush = QtGui.QBrush() self.brush.setStyle(QtCore.Qt.SolidPattern) self.brush.setColor(QtGui.QColor(180,20,90,255)) # Pen. self.pen = QtGui.QPen() self.pen.setStyle(QtCore.Qt.SolidLine) self.pen.setWidth(1) self.pen.setColor(QtGui.QColor(20,20,20,255)) # Lines. self.outLines = [] self.inLines = [] def shape(self): path = QtGui.QPainterPath() path.addEllipse(self.boundingRect()) return path def boundingRect(self): return QtCore.QRectF(self.rect) def paint(self, painter, option, widget): painter.setBrush(self.brush) painter.setPen(self.pen) painter.drawEllipse(self.rect) def mousePressEvent(self, event): if self.type == 'op': rect = self.boundingRect() pointA = QtCore.QPointF(rect.x() + rect.width()/2, rect.y() + rect.height()/2) pointA = self.mapToScene(pointA) pointB = self.mapToScene(event.pos()) self.newLine = NodeLine(pointA, pointB ,'op') self.outLines.append(self.newLine) self.scene().addItem(self.newLine) elif self.type == 'in': rect = self.boundingRect() pointA = self.mapToScene(event.pos()) pointB = QtCore.QPointF(rect.x() + rect.width()/2, rect.y() + rect.height()/2) pointB = self.mapToScene(pointB) self.newLine = NodeLine(pointA, pointB, 'in') self.inLines.append(self.newLine) self.scene().addItem(self.newLine) else: super(NodeSocket, self).mousePressEvent(event) def mouseMoveEvent(self, event): if self.type == 'op': pointB = self.mapToScene(event.pos()) self.newLine.pointB = pointB if self.otherLine: self.otherLine.pointB=pointB elif self.type == 'in': pointA = self.mapToScene(event.pos()) self.newLine.pointA = pointA if self.otherLine: self.otherLine.pointA=pointA else: super(NodeSocket, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): item = self.scene().itemAt(event.scenePos().toPoint(),QtGui.QTransform()) stm = ['MatStm','EngStm'] item.otherLine=self.newLine if (self.type == 'op') and (item.type == 'in'): self.newLine.source = self self.newLine.target = item item.inLines.append(self.newLine) self.newLine.pointB = item.getCenter() if self.newLine.source.parent.obj.type not in stm: self.newLine.source.parent.obj.add_connection(0,self.newLine.target.parent.obj) if self.newLine.target.parent.obj.type not in stm: self.newLine.target.parent.obj.add_connection(1,self.newLine.source.parent.obj) elif (self.type =='in') and (item.type == 'op'): self.newLine.source = item self.newLine.target = self item.outLines.append(self.newLine) self.newLine.pointA = item.getCenter() if self.newLine.source.parent.obj.type not in stm: self.newLine.source.parent.obj.add_connection(0,self.newLine.target.parent.obj) if self.newLine.target.parent.obj.type not in stm: self.newLine.target.parent.obj.add_connection(1,self.newLine.source.parent.obj) else: self.scene().removeItem(self.newLine) if(self.newLine in self.inLines): self.inLines.remove(self.newLine) if(self.newLine in self.outLines): self.outLines.remove(self.newLine) del self.newLine super(NodeSocket, self).mouseReleaseEvent(event) def getCenter(self): rect = self.boundingRect() center = QtCore.QPointF(rect.x() + rect.width()/2, rect.y() + rect.height()/2) center = self.mapToScene(center) return center class NodeItem(QtWidgets.QGraphicsItem): def __init__(self,unitOpr): l = ['Mixer','Splitter'] super(NodeItem, self).__init__() self.obj = unitOpr self.name = self.obj.name self.type = self.obj.type self.setToolTip(self.name) self.nin = self.obj.no_of_inputs self.nop = self.obj.no_of_outputs self.dockWidget = None if(self.obj.type not in l): self.dockWidget = dockWidget(self.obj.name,self.obj.type,self.obj) self.mainwindow= findMainWindow(self) self.mainwindow.addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget) self.dockWidget.hide() self.pic=QtGui.QPixmap("icons/"+self.type+".png") self.rect = QtCore.QRect(0,0,self.pic.width(),self.pic.height()) self.text = QGraphicsTextItem(self) f = QFont() f.setPointSize(8) self.text.setFont(f) self.text.setDefaultTextColor(QtGui.QColor(73,36,73,255)) self.text.setParentItem(self) self.text.setPos(-2.5, self.rect.height()-15) self.text.setPlainText(self.name) self.setFlag(QtWidgets.QGraphicsPixmapItem.ItemIsMovable) self.setFlag(QtWidgets.QGraphicsPixmapItem.ItemIsSelectable) self.initUi() # Brush self.brush = QtGui.QBrush() self.brush.setStyle(QtCore.Qt.SolidPattern) self.brush.setColor(QtGui.QColor(80,0,90,255)) # Pen. self.pen = QtGui.QPen() self.pen.setStyle(QtCore.Qt.SolidLine) self.pen.setWidth(1) self.pen.setColor(QtGui.QColor(20,20,20,255)) self.selPen = QtGui.QPen() self.selPen.setStyle(QtCore.Qt.SolidLine) self.selPen.setWidth(2) self.selPen.setColor(QtGui.QColor(222,192,222)) def initUi(self): self.Input , self.Output = self.initializeSockets(self.type) def shape(self): path = QtGui.QPainterPath() path.addRect(self.boundingRect()) return path def boundingRect(self): return QtCore.QRectF(self.rect) def paint(self, painter, option, widget): if self.isSelected(): painter.setPen(self.selPen) painter.drawRect(QtCore.QRectF(self.rect)) else: painter.setPen(self.pen) painter.drawPixmap(self.rect,self.pic) def initializeSockets(self,type): if(self.type=="Flash" or self.type=="CompSep"): Input = [NodeSocket(QtCore.QRect(-2.5+5.5,(self.rect.height()*x/(self.nin+1))-8,4,4), self, 'in') for x in range(1,self.nin+1) ] Output = [NodeSocket(QtCore.QRect(self.rect.width()-7.5,(self.rect.height()*x*0.90/(self.nop+1))-4,4,4), self, 'op') for x in range(1,self.nop+1)] return Input,Output elif(self.type=="AdiaComp" or self.type=="AdiaExp" or self.type =="Mixer" or self.type =="Splitter" or self.type =="Valve" ): Input = [NodeSocket(QtCore.QRect(-3.5,(self.rect.height()*x/(self.nin+1))-6,4,4), self, 'in') for x in range(1,self.nin+1) ] Output = [NodeSocket(QtCore.QRect(self.rect.width()-2.5,(self.rect.height()*x/(self.nop+1))-6,4,4), self, 'op') for x in range(1,self.nop+1)] return Input,Output elif(self.type=="Cooler" or self.type=="Heater"): Input = [NodeSocket(QtCore.QRect(3.5,(self.rect.height()*x/(self.nin+1))-4,4,4), self, 'in') for x in range(1,self.nin+1) ] Output = [NodeSocket(QtCore.QRect(self.rect.width()-8.0,(self.rect.height()*x/(self.nop+1))-4,4,4), self, 'op') for x in range(1,self.nop+1)] return Input,Output elif(self.type=="Pump"): Input = [NodeSocket(QtCore.QRect(-2.5,(self.rect.height()*x/(self.nin+1))-10,4,4), self, 'in') for x in range(1,self.nin+1) ] Output = [NodeSocket(QtCore.QRect(self.rect.width()-2.5,-2.5,4,4), self, 'op') for x in range(1,self.nop+1)] return Input,Output elif(self.type=="DistCol" or self.type=="ShortCol"): Input = [NodeSocket(QtCore.QRect(-2.5,(self.rect.height()*x/(self.nin+1))-12,5,5), self, 'in') for x in range(1,self.nin+1) ] Output = [NodeSocket(QtCore.QRect(self.rect.width()-5.5,(self.rect.height()*1.44*x/(self.nop+1))-67,5,5), self, 'op') for x in range(1,self.nop+1)] return Input,Output elif(self.type=="MatStm"): Input = [NodeSocket(QtCore.QRect(-2.5,(self.rect.height()*x/(self.nin+1))-1,4,4), self, 'in') for x in range(1,self.nin+1) ] Output = [NodeSocket(QtCore.QRect(self.rect.width()-2.5,(self.rect.height()*x/(self.nin+1))-1,4,4), self, 'op') for x in range(1,self.nop+1)] return Input,Output def mouseMoveEvent(self, event): super(NodeItem, self).mouseMoveEvent(event) for output in self.Output: for line in output.outLines: line.pointA = line.source.getCenter() line.pointB = line.target.getCenter() for input in self.Input: for line in input.inLines: line.pointA = line.source.getCenter() line.pointB = line.target.getCenter() def mouseDoubleClickEvent(self, event): #self.setPos(event.scenePos().x()-250,event.scenePos().y()) self.dockWidget.show() def findMainWindow(self): ''' Global function to find the (open) QMainWindow in application ''' app = QApplication.instance() for widget in app.topLevelWidgets(): if isinstance(widget, QMainWindow): return widget return None