Пример #1
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(600, 400)
        self.view = QMyGraphicsView()  # 创建视图窗口
        self.setCentralWidget(self.view)  # 设置中央控件
        self.statusbar = self.statusBar()  # 添加状态栏
        self.labviewcorrd = QLabel('view坐标:')
        self.labviewcorrd.setMinimumWidth(150)
        self.statusbar.addWidget(self.labviewcorrd)
        self.labscenecorrd = QLabel('scene坐标:')
        self.labscenecorrd.setMinimumWidth(150)
        self.statusbar.addWidget(self.labscenecorrd)
        self.labitemcorrd = QLabel('item坐标:')
        self.labitemcorrd.setMinimumWidth(150)
        self.statusbar.addWidget(self.labitemcorrd)
        rect = QRectF(-200, -100, 400, 200)
        self.scene = QGraphicsScene(rect)  # 创建场景
        # 参数:场景区域
        # 场景坐标原点默认在场景中心---场景中心位于界面中心
        self.view.setScene(self.scene)  # 给视图窗口设置场景
        item1 = QGraphicsRectItem(rect)  # 创建矩形---以场景为坐标
        item1.setFlags(QGraphicsItem.ItemIsSelectable
                       | QGraphicsItem.ItemIsFocusable
                       | QGraphicsItem.ItemIsMovable)  # 给图元设置标志
        # QGraphicsItem.ItemIsSelectable---可选择
        # QGraphicsItem.ItemIsFocusable---可设置焦点
        # QGraphicsItem.ItemIsMovable---可移动
        # QGraphicsItem.ItemIsPanel---
        self.scene.addItem(item1)  # 给场景添加图元
        for pos, color in zip([rect.left(), 0, rect.right()],
                              [Qt.red, Qt.yellow, Qt.blue]):
            item = QGraphicsEllipseItem(-50, -50, 100, 100)  # 创建椭圆--场景坐标
            # 参数1 参数2  矩形左上角坐标
            # 参数3 参数4 矩形的宽和高
            item.setPos(pos, 0)  # 给图元设置在场景中的坐标(移动图元)--图元中心坐标
            item.setBrush(color)  # 设置画刷
            item.setFlags(QGraphicsItem.ItemIsSelectable
                          | QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsMovable)
            self.scene.addItem(item)
        self.scene.clearSelection()  # 【清除选择】
        self.view.sigMouseMovePoint.connect(self.slotMouseMovePoint)

    def slotMouseMovePoint(self, pt):
        self.labviewcorrd.setText('view坐标:{},{}'.format(pt.x(), pt.y()))
        ptscene = self.view.mapToScene(pt)  # 把view坐标转换为场景坐标
        self.labscenecorrd.setText('scene坐标:{:.0f},{:.0f}'.format(
            ptscene.x(), ptscene.y()))
        item = self.scene.itemAt(ptscene,
                                 self.view.transform())  # 在场景某点寻找图元--最上面的图元
        # 返回值:图元地址
        # 参数1 场景点坐标
        # 参数2 ????
        if item is not None:
            ptitem = item.mapFromScene(ptscene)  # 把场景坐标转换为图元坐标
            self.labitemcorrd.setText('item坐标:{:.0f},{:.0f}'.format(
                ptitem.x(), ptitem.y()))
Пример #2
0
class QmyMainWindow(QMainWindow): 

   def __init__(self, parent=None):
      super().__init__(parent)    #调用父类构造函数,创建窗体
      self.ui=Ui_MainWindow()     #创建UI对象
      self.ui.setupUi(self)       #构造UI界面
      
      self.setWindowTitle("Demo8_6, Graphics View绘图")

      self.__buildStatusBar()    #构造状态栏
      self.__iniGraphicsSystem() #初始化 graphics View系统
      
      self.__ItemId=1   #绘图项自定义数据的key
      self.__ItemDesc=2 #绘图项自定义数据的key

      self.__seqNum=0  #每个图形项设置一个序号
      self.__backZ=0   #后置序号
      self.__frontZ=0  #前置序号

##  ==============自定义功能函数============
   def __buildStatusBar(self):   ##构造状态栏
      self.__labViewCord=QLabel("View 坐标:")
      self.__labViewCord.setMinimumWidth(150)
      self.ui.statusBar.addWidget(self.__labViewCord)

      self.__labSceneCord=QLabel("Scene 坐标:")
      self.__labSceneCord.setMinimumWidth(150)
      self.ui.statusBar.addWidget(self.__labSceneCord)

      self.__labItemCord=QLabel("Item 坐标:")
      self.__labItemCord.setMinimumWidth(150)
      self.ui.statusBar.addWidget(self.__labItemCord)

      self.__labItemInfo=QLabel("ItemInfo: ")
      self.ui.statusBar.addPermanentWidget(self.__labItemInfo)
      

   def __iniGraphicsSystem(self):   ##初始化 Graphics View系统
      self.view=QmyGraphicsView(self)   #创建图形视图组件
      self.setCentralWidget(self.view)

      self.scene=QGraphicsScene(-300,-200,600,200) #创建QGraphicsScene
      self.view.setScene(self.scene)   #与view关联

      self.view.setCursor(Qt.CrossCursor)     #设置鼠标
      self.view.setMouseTracking(True)
      self.view.setDragMode(QGraphicsView.RubberBandDrag)

      ##  4个信号与槽函数的关联
      self.view.mouseMove.connect(self.do_mouseMove)     #鼠标移动
      self.view.mouseClicked.connect(self.do_mouseClicked)   #左键按下
      self.view.mouseDoubleClick.connect(self.do_mouseDoubleClick) #鼠标双击
      self.view.keyPress.connect(self.do_keyPress)    #左键按下

   def __setItemProperties(self,item,desc):   ##item是具体类型的QGraphicsItem
      item.setFlag(QGraphicsItem.ItemIsFocusable)
      item.setFlag(QGraphicsItem.ItemIsMovable)
      item.setFlag(QGraphicsItem.ItemIsSelectable)

      self.__frontZ=1+self.__frontZ   
      item.setZValue(self.__frontZ)  #叠放次序
      item.setPos(-150+random.randint(1,200),-200+random.randint(1,200))

      self.__seqNum=1+self.__seqNum  
      item.setData(self.__ItemId,self.__seqNum) #图件编号
      item.setData(self.__ItemDesc,desc)        #图件描述

      self.scene.addItem(item)
      self.scene.clearSelection()
      item.setSelected(True)

   def __setBrushColor(self,item):  ##设置填充颜色
      color=item.brush().color()
      color=QColorDialog.getColor(color,self,"选择填充颜色")
      if color.isValid():
         item.setBrush(QBrush(color))
      
##==============event 处理函数=======================

        
##  ==========由connectSlotsByName() 自动连接的槽函数==================        
##==============创建基本图件==============
   @pyqtSlot()    ##添加一个矩形
   def on_actItem_Rect_triggered(self):
      item=QGraphicsRectItem(-50,-25,100,50)
      item.setBrush(QBrush(Qt.yellow)) #设置填充颜色
      self.__setItemProperties(item,"矩形")

   @pyqtSlot()    ##添加一个椭圆
   def on_actItem_Ellipse_triggered(self):
      item=QGraphicsEllipseItem(-50,-30,100,60) 
      item.setBrush(QBrush(Qt.blue))  #设置填充颜色
      self.__setItemProperties(item,"椭圆")

   @pyqtSlot()    ##添加一个圆
   def on_actItem_Circle_triggered(self):
      item=QGraphicsEllipseItem(-50,-50,100,100) 
      item.setBrush(QBrush(Qt.cyan))  #设置填充颜色
      self.__setItemProperties(item,"圆形")

   @pyqtSlot()    ##添加三角形
   def on_actItem_Triangle_triggered(self):
      item=QGraphicsPolygonItem()
      points=[QPointF(0,-40), QPointF(60,40), QPointF(-60,40)]
      item.setPolygon(QPolygonF(points))
      item.setBrush(QBrush(Qt.magenta))  #设置填充颜色
      self.__setItemProperties(item,"三角形")

   @pyqtSlot()    ##添加梯形
   def on_actItem_Polygon_triggered(self):
      item=QGraphicsPolygonItem()
      points=[QPointF(-40,-40), QPointF(40,-40), QPointF(100,40),QPointF(-100,40)]
      item.setPolygon(QPolygonF(points))
      item.setBrush(QBrush(Qt.green))  #设置填充颜色
      self.__setItemProperties(item,"梯形")
      
   @pyqtSlot()    ##添加直线
   def on_actItem_Line_triggered(self):
      item=QGraphicsLineItem(-100,0,100,0)
      pen=QPen(Qt.red)
      pen.setWidth(4)
      item.setPen(pen)    #设置线条属性
      self.__setItemProperties(item,"直线")
      
   @pyqtSlot()    ##添加文字
   def on_actItem_Text_triggered(self):
      strText,OK=QInputDialog.getText(self,"输入","请输入文字")
      if (not OK):
         return
      item=QGraphicsTextItem(strText)
      font=self.font()
      font.setPointSize(20)
      font.setBold(True)
      item.setFont(font)   #设置字体
      item.setDefaultTextColor(Qt.black)  #设置颜色
      self.__setItemProperties(item,"文字")

##=============图件的编辑操作===================
   @pyqtSlot()    ##放大
   def on_actZoomIn_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)  #选中的图形项的个数
      if cnt==1:  #只有一个图形项
         item=items[0]
         item.setScale(0.1+item.scale())
      else:
         self.view.scale(1.1,1.1)

   @pyqtSlot()    ##缩小
   def on_actZoomOut_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)    #选中的图形项的个数
      if cnt==1:        #只有一个图形项
         item=items[0]
         item.setScale(item.scale()-0.1)
      else:
         self.view.scale(0.9,0.9)   
      
   @pyqtSlot()    ##"恢复"取消所有缩放和旋转变换
   def on_actRestore_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)
      if cnt==1:  #单个图形项
         item=items[0]
         item.setScale(1)        #缩放还原
         item.setRotation(0)     #旋转还原
##         item.resetTransform()   #不起作用,BUG, PyQt 5.12
      else:
         self.view.resetTransform()
      
   @pyqtSlot()    ##左旋转
   def on_actRotateLeft_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)
      if cnt==1:
         item=items[0]
         item.setRotation(-30+item.rotation())
      else:
         self.view.rotate(-30)

   @pyqtSlot()    ##右旋转
   def on_actRotateRight_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)
      if cnt==1:
         item=items[0]
         item.setRotation(30+item.rotation())
      else:
         self.view.rotate(30)

   @pyqtSlot()    ##前置
   def on_actEdit_Front_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)
      if cnt>0 :
         item=items[0]
         self.__frontZ=1+self.__frontZ
         item.setZValue(self.__frontZ)
      
   @pyqtSlot()    ##后置
   def on_actEdit_Back_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)
      if cnt>0 :
         item=items[0]
         self.__backZ=self.__backZ-1
         item.setZValue(self.__backZ)

   @pyqtSlot()    ##组合
   def on_actGroup_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)  #选中的图形项个数
      if (cnt<=1):
        return 

      group =QGraphicsItemGroup() #创建组合
      self.scene.addItem(group)   #组合添加到场景中
      for i in range(cnt):
         item=items[i]
         item.setSelected(False)    #清除选择虚线框
         item.clearFocus()
         group.addToGroup(item)     #添加到组合

      group.setFlag(QGraphicsItem.ItemIsFocusable)
      group.setFlag(QGraphicsItem.ItemIsMovable)
      group.setFlag(QGraphicsItem.ItemIsSelectable)

      self.__frontZ=1+self.__frontZ
      group.setZValue(self.__frontZ)
      self.scene.clearSelection()
      group.setSelected(True)

   @pyqtSlot()    ##打散组合
   def on_actGroupBreak_triggered(self):
      items=self.scene.selectedItems()   
      cnt=len(items)
      if (cnt==1):  #假设选中的是QGraphicsItemGroup
         group=items[0]
         self.scene.destroyItemGroup(group)

   @pyqtSlot()    ##删除所有选中的绘图项
   def on_actEdit_Delete_triggered(self):
      items=self.scene.selectedItems()   
      cnt=len(items)
      for i in range(cnt):
         item=items[i]
         self.scene.removeItem(item)   #删除绘图项

        
##  =============自定义槽函数===============================        
   def  do_mouseMove(self,point):      ##鼠标移动
   ##鼠标移动事件,point是 GraphicsView的坐标,物理坐标
      self.__labViewCord.setText("View 坐标:%d,%d" %(point.x(),point.y()))
      pt=self.view.mapToScene(point)  #转换到Scene坐标
      self.__labSceneCord.setText("Scene 坐标:%.0f,%.0f"%(pt.x(),pt.y()))
   
   def  do_mouseClicked(self,point):   ##鼠标单击
      pt=self.view.mapToScene(point)  #转换到Scene坐标
      item=self.scene.itemAt(pt,self.view.transform())  #获取光标下的图形项
      if (item == None): 
         return
      pm=item.mapFromScene(pt)   #转换为绘图项的局部坐标
      self.__labItemCord.setText("Item 坐标:%.0f,%.0f"%(pm.x(),pm.y()))
      self.__labItemInfo.setText(str(item.data(self.__ItemDesc))
                    +", ItemId="+str(item.data(self.__ItemId)))

   def do_mouseDoubleClick(self,point):  ##鼠标双击
      pt=self.view.mapToScene(point)   #转换到Scene坐标,QPointF
      item=self.scene.itemAt(pt,self.view.transform())    #获取光标下的绘图项
      if (item == None): 
         return

      className=str(type(item))  #将类名称转换为字符串
   ##      print(className)
      
      if (className.find("QGraphicsRectItem") >=0):      #矩形框
         self.__setBrushColor(item)
      elif (className.find("QGraphicsEllipseItem")>=0):  #椭圆和圆都是 QGraphicsEllipseItem
         self.__setBrushColor(item)
      elif (className.find("QGraphicsPolygonItem")>=0):  #梯形和三角形
         self.__setBrushColor(item)
      elif (className.find("QGraphicsLineItem")>=0):     #直线,设置线条颜色
         pen=item.pen()
         color=item.pen().color()
         color=QColorDialog.getColor(color,self,"选择线条颜色")
         if color.isValid():
            pen.setColor(color)
            item.setPen(pen)
      elif (className.find("QGraphicsTextItem")>=0):     #文字,设置字体
         font=item.font()
         font,OK=QFontDialog.getFont(font)
         if OK:
            item.setFont(font)

   def do_keyPress(self,event):     ##按键操作
      items=self.scene.selectedItems() 
      cnt=len(items)
      if (cnt!=1):  
         return

      item=items[0]
      key=event.key()
      if (key==Qt.Key_Delete):       #删除
         self.scene.removeItem(item)
      elif (key==Qt.Key_Space):      #顺时针旋转90度
         item.setRotation(90+item.rotation())
      elif (key==Qt.Key_PageUp):     #放大
         item.setScale(0.1+item.scale())
      elif (key==Qt.Key_PageDown):  #缩小
         item.setScale(-0.1+item.scale())
      elif (key==Qt.Key_Left):      #左移
         item.setX(-1+item.x())
      elif (key==Qt.Key_Right):     #右移
         item.setX(1+item.x())
      elif (key==Qt.Key_Up):        #上移
         item.setY(-1+item.y())
      elif (key==Qt.Key_Down):      #下移
         item.setY(1+item.y())
Пример #3
0
class MainForm(QDialog):

    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.filename = ""
        self.copiedItem = QByteArray()
        self.pasteOffset = 5
        self.prevPoint = QPoint()
        self.addOffset = 5
        self.borders = []

        self.printer = QPrinter(QPrinter.HighResolution)
        self.printer.setPageSize(QPrinter.Letter)

        self.view = GraphicsView()
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, PageSize[0], PageSize[1])
        self.addBorders()
        self.view.setScene(self.scene)

        self.wrapped = [] # Needed to keep wrappers alive
        buttonLayout = QVBoxLayout()
        for text, slot in (
                ("Add &Text", self.addText),
                ("Add &Box", self.addBox),
                ("Add Pi&xmap", self.addPixmap),
                ("&Align", None),
                ("&Copy", self.copy),
                ("C&ut", self.cut),
                ("&Paste", self.paste),
                ("&Delete...", self.delete),
                ("&Rotate", self.rotate),
                ("Pri&nt...", self.print_),
                ("&Open...", self.open),
                ("&Save", self.save),
                ("&Quit", self.accept)):
            button = QPushButton(text)
            if not MAC:
                button.setFocusPolicy(Qt.NoFocus)
            if slot is not None:
                button.clicked.connect(slot)
            if text == "&Align":
                menu = QMenu(self)
                for text, arg in (
                        ("Align &Left", Qt.AlignLeft),
                        ("Align &Right", Qt.AlignRight),
                        ("Align &Top", Qt.AlignTop),
                        ("Align &Bottom", Qt.AlignBottom)):
                    wrapper = functools.partial(self.setAlignment, arg)
                    self.wrapped.append(wrapper)
                    menu.addAction(text, wrapper)
                button.setMenu(menu)
            if text == "Pri&nt...":
                buttonLayout.addStretch(5)
            if text == "&Quit":
                buttonLayout.addStretch(1)
            buttonLayout.addWidget(button)
        buttonLayout.addStretch()

        layout = QHBoxLayout()
        layout.addWidget(self.view, 1)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)

        fm = QFontMetrics(self.font())
        self.resize(self.scene.width() + fm.width(" Delete... ") + 50,
                    self.scene.height() + 50)
        self.setWindowTitle("Page Designer")


    def addBorders(self):
        self.borders = []
        rect = QRectF(0, 0, PageSize[0], PageSize[1])
        self.borders.append(self.scene.addRect(rect, Qt.yellow))
        margin = 5.25 * PointSize
        self.borders.append(self.scene.addRect(
                rect.adjusted(margin, margin, -margin, -margin),
                Qt.yellow))


    def removeBorders(self):
        while self.borders:
            item = self.borders.pop()
            self.scene.removeItem(item)
            del item


    def reject(self):
        self.accept()


    def accept(self):
        self.offerSave()
        QDialog.accept(self)


    def offerSave(self):
        if (Dirty and QMessageBox.question(self,
                            "Page Designer - Unsaved Changes",
                            "Save unsaved changes?",
                            QMessageBox.Yes|QMessageBox.No) == 
           QMessageBox.Yes):
            self.save()


    def position(self):
        point = self.mapFromGlobal(QCursor.pos())
        if not self.view.geometry().contains(point):
            coord = random.randint(36, 144)
            point = QPoint(coord, coord)
        else:
            if point == self.prevPoint:
                point += QPoint(self.addOffset, self.addOffset)
                self.addOffset += 5
            else:
                self.addOffset = 5
                self.prevPoint = point
        return self.view.mapToScene(point)


    def addText(self):
        dialog = TextItemDlg(position=self.position(),
                             scene=self.scene, parent=self)
        dialog.exec_()


    def addBox(self):
        BoxItem(self.position(), self.scene)


    def addPixmap(self):
        path = (QFileInfo(self.filename).path()
            if self.filename else ".")
        fname,filetype = QFileDialog.getOpenFileName(self,
                "Page Designer - Add Pixmap", path,
                "Pixmap Files (*.bmp *.jpg *.png *.xpm)")
        if not fname:
            return
        self.createPixmapItem(QPixmap(fname), self.position())


    def createPixmapItem(self, pixmap, position, matrix=QTransform()):
        item = GraphicsPixmapItem(pixmap)
        item.setFlags(QGraphicsItem.ItemIsSelectable|
                      QGraphicsItem.ItemIsMovable)
        item.setPos(position)
        item.setTransform(matrix)
        self.scene.clearSelection()
        self.scene.addItem(item)
        item.setSelected(True)
        global Dirty
        Dirty = True
        return item


    def selectedItem(self):
        items = self.scene.selectedItems()
        if len(items) == 1:
            return items[0]
        return None


    def copy(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copiedItem.clear()
        self.pasteOffset = 5
        stream = QDataStream(self.copiedItem, QIODevice.WriteOnly)
        self.writeItemToStream(stream, item)


    def cut(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copy()
        self.scene.removeItem(item)
        del item


    def paste(self):
        if self.copiedItem.isEmpty():
            return
        stream = QDataStream(self.copiedItem, QIODevice.ReadOnly)
        self.readItemFromStream(stream, self.pasteOffset)
        self.pasteOffset += 5


    def setAlignment(self, alignment):
        # Items are returned in arbitrary order
        items = self.scene.selectedItems()
        if len(items) <= 1:
            return
        # Gather coordinate data
        leftXs, rightXs, topYs, bottomYs = [], [], [], []
        for item in items:
            rect = item.sceneBoundingRect()
            leftXs.append(rect.x())
            rightXs.append(rect.x() + rect.width())
            topYs.append(rect.y())
            bottomYs.append(rect.y() + rect.height())
        # Perform alignment
        if alignment == Qt.AlignLeft:
            xAlignment = min(leftXs)
            for i, item in enumerate(items):
                item.moveBy(xAlignment - leftXs[i], 0)
        elif alignment == Qt.AlignRight:
            xAlignment = max(rightXs)
            for i, item in enumerate(items):
                item.moveBy(xAlignment - rightXs[i], 0)
        elif alignment == Qt.AlignTop:
            yAlignment = min(topYs)
            for i, item in enumerate(items):
                item.moveBy(0, yAlignment - topYs[i])
        elif alignment == Qt.AlignBottom:
            yAlignment = max(bottomYs)
            for i, item in enumerate(items):
                item.moveBy(0, yAlignment - bottomYs[i])
        global Dirty
        Dirty = True


    def rotate(self):
        for item in self.scene.selectedItems():
            item.setRotation(item.rotation()+30)

    def delete(self):
        items = self.scene.selectedItems()
        if (len(items) and QMessageBox.question(self,
                "Page Designer - Delete",
                "Delete {0} item{1}?".format(len(items),
                "s" if len(items) != 1 else ""),
                QMessageBox.Yes|QMessageBox.No) ==
                QMessageBox.Yes):
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
            global Dirty
            Dirty = True


    def print_(self):
        dialog = QPrintDialog(self.printer)
        if dialog.exec_():
            painter = QPainter(self.printer)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setRenderHint(QPainter.TextAntialiasing)
            self.scene.clearSelection()
            self.removeBorders()
            self.scene.render(painter)
            self.addBorders()


    def open(self):
        self.offerSave()
        path = (QFileInfo(self.filename).path()
                if self.filename else ".")
        fname,filetype = QFileDialog.getOpenFileName(self,
                "Page Designer - Open", path,
                "Page Designer Files (*.pgd)")
        if not fname:
            return
        self.filename = fname
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(str(fh.errorString()))
            items = self.scene.items()
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
            self.addBorders()
            stream = QDataStream(fh)
            stream.setVersion(QDataStream.Qt_5_7)
            magic = stream.readInt32()
            if magic != MagicNumber:
                raise IOError("not a valid .pgd file")
            fileVersion = stream.readInt16()
            if fileVersion != FileVersion:
                raise IOError("unrecognised .pgd file version")
            while not fh.atEnd():
                self.readItemFromStream(stream)
        except IOError as e:
            QMessageBox.warning(self, "Page Designer -- Open Error",
                    "Failed to open {0}: {1}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()
        global Dirty
        Dirty = False


    def save(self):
        if not self.filename:
            path = "."
            fname,filetype = QFileDialog.getSaveFileName(self,
                    "Page Designer - Save As", path,
                    "Page Designer Files (*.pgd)")
            if not fname:
                return
            self.filename = fname
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(str(fh.errorString()))
            self.scene.clearSelection()
            stream = QDataStream(fh)
            stream.setVersion(QDataStream.Qt_5_7)
            stream.writeInt32(MagicNumber)
            stream.writeInt16(FileVersion)
            for item in self.scene.items():
                self.writeItemToStream(stream, item)
        except IOError as e:
            QMessageBox.warning(self, "Page Designer -- Save Error",
                    "Failed to save {0}: {1}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()
        global Dirty
        Dirty = False


    def readItemFromStream(self, stream, offset=0):
        type = ""
        position = QPointF()
        matrix = QTransform()
        rotateangle=0#add by yangrongdong
        type=stream.readQString()
        stream >> position >> matrix
        if offset:
            position += QPointF(offset, offset)
        if type == "Text":
            text = ""
            font = QFont()
            text=stream.readQString()
            stream >> font
            rotateangle=stream.readFloat()
            tx=TextItem(text, position, self.scene, font, matrix)
            tx.setRotation(rotateangle)
        elif type == "Box":
            rect = QRectF()
            stream >> rect
            style = Qt.PenStyle(stream.readInt16())
            rotateangle=stream.readFloat()
            bx=BoxItem(position, self.scene, style, rect, matrix)
            bx.setRotation(rotateangle)
        elif type == "Pixmap":
            pixmap = QPixmap()
            stream >> pixmap
            rotateangle=stream.readFloat()
            px=self.createPixmapItem(pixmap, position, matrix)
            px.setRotation(rotateangle)


    def writeItemToStream(self, stream, item):
        if isinstance(item, TextItem):
            stream.writeQString("Text")
            stream<<item.pos()<< item.transform() 
            stream.writeQString(item.toPlainText())
            stream<< item.font()
            stream.writeFloat(item.rotation())#add by yangrongdong
        elif isinstance(item, GraphicsPixmapItem):
            stream.writeQString("Pixmap")
            stream << item.pos() << item.transform() << item.pixmap()
            stream.writeFloat(item.rotation())#add by yangrongdong
        elif isinstance(item, BoxItem):
            stream.writeQString("Box")
            stream<< item.pos() << item.transform() << item.rect
            stream.writeInt16(item.style)
            stream.writeFloat(item.rotation())#add by yangrongdong
Пример #4
0
class QMyGraphicsview(QGraphicsView):
    sigMouseMovePoint = pyqtSignal(QPoint)
    sigNetDeviceItemPress = pyqtSignal(list)
    paths = [[[0], [1, 4, 3, 2], [1, 4, 3], [1, 4], [0], [1, 6]],
             [[2, 1], [0], [2, 4, 3], [2, 4], [0], [2, 6]], [], [], [], []]
    devices = []
    line_items = []

    def __init__(self, parent=None):
        super(QMyGraphicsview, self).__init__(parent)
        self.rect = QRectF(-200, -200, 400, 400)
        self.myScene = QGraphicsScene(self.rect)
        self.setScene(self.myScene)
        self.initPoints()
        self.initGraphicSystem()

    def initPoints(self):
        # 准备6个节点圆形
        for i in range(1, 7):
            item = NetDeviceItem(self, NetNodeInfo(i, "green"))
            x = 150 * math.sin(math.radians(60 * i))
            y = 150 * math.cos(math.radians(60 * i))
            item.setPos(x, y)
            item.setBrush(Qt.green)
            item.setRect(-15, -15, 30, 30)
            item.setFlags(QGraphicsItem.ItemIsMovable
                          | QGraphicsItem.ItemIsSelectable
                          | QGraphicsItem.ItemIsFocusable)
            self.devices.append(item)

    def initGraphicSystem(self):
        # 清除所有item
        self.myScene.clear()
        # 显示scene边框
        item1 = WholeDeviceItem(self.rect, self, ["whole", "white"])
        item1.setFlags(QGraphicsItem.ItemIsSelectable
                       | QGraphicsItem.ItemIsFocusable)
        self.myScene.addItem(item1)
        # 显示节点
        for item in self.devices:
            self.myScene.addItem(item)
            text_item = self.myScene.addSimpleText(str(item.infos.id))
            text_item.setPos(item.pos().x() + 20, item.pos().y())
        self.myScene.clearSelection()

    def mouseMoveEvent(self, evt):
        self.sigMouseMovePoint.emit(evt.pos())

    def emitItemPressEvent(self, infos):
        self.sigNetDeviceItemPress.emit(infos)

    def removeAllLines(self):
        for item in self.line_items:
            self.myScene.removeItem(item)
        self.line_items.clear()

    def drawAllLines(self):
        self.removeAllLines()
        for path in self.paths:
            if len(path) == 6:
                for line in path:
                    if len(line) > 1:
                        for i in range(len(line) - 1):
                            p1 = self.devices[line[i] - 1]
                            p2 = self.devices[line[i + 1] - 1]
                            line_item = self.myScene.addLine(
                                p1.pos().x(),
                                p1.pos().y(),
                                p2.pos().x(),
                                p2.pos().y())
                            self.line_items.append(line_item)

    def drawLines(self, id):
        self.removeAllLines()
        """画出id节点的连接线"""
        for line in self.paths[id - 1]:
            if len(line) > 1:
                for i in range(len(line) - 1):
                    p1 = self.devices[line[i] - 1]
                    p2 = self.devices[line[i + 1] - 1]
                    line_item = self.myScene.addLine(p1.pos().x(),
                                                     p1.pos().y(),
                                                     p2.pos().x(),
                                                     p2.pos().y())
                    self.line_items.append(line_item)
Пример #5
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体

        self.__buildUI()  #构造界面
        self.__iniGraphicsSystem()  #初始化 graphics View系统

        self.view.mouseMove.connect(self.do_mouseMovePoint)  #鼠标移动
        self.view.mouseClicked.connect(self.do_mouseClicked)  #左键按下

##  ==============自定义功能函数============

    def __buildUI(self):  ##构造界面
        self.resize(600, 450)
        self.setWindowTitle("Demo8_5, View/Scene/Item关系和坐标变换")

        font = self.font()
        font.setPointSize(11)
        self.setFont(font)

        centralWidget = QWidget(self)  #中间工作区组件
        vLayoutMain = QVBoxLayout(centralWidget)  #垂直布局

        groupBox = QGroupBox(centralWidget)  #显示两个Label的groupBox
        vLayoutGroup = QVBoxLayout(groupBox)
        self.__labViewSize = QLabel(groupBox)
        self.__labViewSize.setText("view坐标,左上角(0,0),宽度=,长度=")

        vLayoutGroup.addWidget(self.__labViewSize)
        self.__labSceneRect = QLabel(groupBox)
        self.__labSceneRect.setText("view.sceneRect=()")
        vLayoutGroup.addWidget(self.__labSceneRect)

        vLayoutMain.addWidget(groupBox)  #主布局添加groupBox

        self.view = QmyGraphicsView(centralWidget)  #绘图视图
        self.view.setCursor(Qt.CrossCursor)
        self.view.setMouseTracking(True)
        ##      self.view.setDragMode(QGraphicsView.RubberBandDrag)
        vLayoutMain.addWidget(self.view)  #添加到主布局

        self.setCentralWidget(centralWidget)  #设置工作区中间组件

        statusBar = QStatusBar(self)  #状态栏
        self.setStatusBar(statusBar)

        self.__labViewCord = QLabel("View 坐标:")
        self.__labViewCord.setMinimumWidth(150)
        statusBar.addWidget(self.__labViewCord)

        self.__labSceneCord = QLabel("Scene 坐标:")
        self.__labSceneCord.setMinimumWidth(150)
        statusBar.addWidget(self.__labSceneCord)

        self.__labItemCord = QLabel("Item 坐标:")
        self.__labItemCord.setMinimumWidth(150)
        statusBar.addWidget(self.__labItemCord)

    def __iniGraphicsSystem(self):  ##初始化 graphics View系统
        rect = QRectF(-200, -100, 400, 200)
        self.scene = QGraphicsScene(rect)  #scene逻辑坐标系定义
        self.view.setScene(self.scene)

        ## 画一个矩形框,大小等于scene
        item = QGraphicsRectItem(rect)  #矩形框正好等于scene的大小
        item.setFlag(QGraphicsItem.ItemIsSelectable)  #可选,
        item.setFlag(QGraphicsItem.ItemIsFocusable)  #可以有焦点
        pen = QPen()
        pen.setWidth(2)
        item.setPen(pen)
        self.scene.addItem(item)

        ##一个位于scene中心的椭圆,测试局部坐标
        #矩形框内创建椭圆,绘图项的局部坐标,左上角(-100,-50),宽200,高100
        item2 = QGraphicsEllipseItem(-100, -50, 200, 100)
        item2.setPos(0, 0)
        item2.setBrush(QBrush(Qt.blue))
        item2.setFlag(QGraphicsItem.ItemIsSelectable)  #可选,
        item2.setFlag(QGraphicsItem.ItemIsFocusable)  #可以有焦点
        item2.setFlag(QGraphicsItem.ItemIsMovable)  #可移动

        self.scene.addItem(item2)

        ##一个圆,中心位于scene的边缘
        item3 = QGraphicsEllipseItem(-50, -50, 100, 100)  #矩形框内创建椭圆,绘图项的局部坐标
        item3.setPos(rect.right(), rect.bottom())
        item3.setBrush(QBrush(Qt.red))
        item3.setFlag(QGraphicsItem.ItemIsSelectable)  #可选,
        item3.setFlag(QGraphicsItem.ItemIsFocusable)  #可以有焦点
        item3.setFlag(QGraphicsItem.ItemIsMovable)  #可移动
        self.scene.addItem(item3)

        self.scene.clearSelection()

##==============event 处理函数=======================

    def resizeEvent(self, event):
        self.__labViewSize.setText('view坐标,左上角(0,0),宽度=%d,高度=%d' %
                                   (self.view.width(), self.view.height()))

        rectF = self.view.sceneRect()  #Scene的矩形区,QRectF
        self.__labSceneRect.setText(
            'view.sceneRect=(%.0f,%.0f,%.0f,%.0f)' %
            (rectF.left(), rectF.top(), rectF.width(), rectF.height()))

##  ==========由connectSlotsByName() 自动连接的槽函数==================

##  =============自定义槽函数===============================

    def do_mouseMovePoint(self, point):
        ##鼠标移动事件,point是 GraphicsView的坐标,物理坐标
        self.__labViewCord.setText("View坐标:%d,%d" % (point.x(), point.y()))
        pt = self.view.mapToScene(point)  #转换到Scene坐标
        self.__labSceneCord.setText("Scene坐标:%.0f,%.0f" % (pt.x(), pt.y()))

    def do_mouseClicked(self, point):
        pt = self.view.mapToScene(point)  #转换到Scene坐标
        item = None
        item = self.scene.itemAt(pt, self.view.transform())  #获取光标下的绘图项
        if (item != None):  #有绘图项
            pm = item.mapFromScene(pt)  #转换为绘图项的局部坐标
            self.__labItemCord.setText("Item坐标:%.0f,%.0f" % (pm.x(), pm.y()))
Пример #6
0
class MainForm(QDialog):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.filename = ""
        self.copiedItem = QByteArray()
        self.pasteOffset = 5
        self.prevPoint = QPoint()
        self.addOffset = 5
        self.borders = []

        self.printer = QPrinter(QPrinter.HighResolution)
        # enum QPrinter::PrinterMode
        # HighRes是一个高分辨率模式,是PrinterMode组成
        self.printer.setPageSize(QPrinter.A4)
        self.view = GraphicsView()
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, PageSize[0], PageSize[1])
        self.addBorders()
        self.view.setScene(self.scene)
        # 不用写 view.show?
        self.wrapped = []  # Needed to keep wrappers alive
        buttonLayout = QVBoxLayout()
        for text, slot in (("Add &Text", self.addText), ("Add &Box",
                                                         self.addBox),
                           ("Add Pi&xmap", self.addPixmap), ("&Align", None),
                           ("&Copy", self.copy), ("C&ut", self.cut),
                           ("&Paste", self.paste), ("&Delete...", self.delete),
                           ("&Rotate", self.rotate),
                           ("Pri&nt...", self.print_), ("&Open...", self.open),
                           ("&Save", self.save), ("&Quit", self.accept)):
            button = QPushButton(text)
            if not MAC:
                button.setFocusPolicy(Qt.NoFocus)
            if slot is not None:
                button.clicked.connect(slot)
            if text == "&Align":
                menu = QMenu(self)
                for text, arg in (("Align &Left", Qt.AlignLeft),
                                  ("Align &Right",
                                   Qt.AlignRight), ("Align &Top", Qt.AlignTop),
                                  ("Align &Bottom", Qt.AlignBottom)):
                    wrapper = functools.partial(self.setAlignment, arg)
                    # ?????
                    self.wrapped.append(wrapper)
                    menu.addAction(text, wrapper)
                button.setMenu(menu)
            if text == "Pri&nt...":
                buttonLayout.addStretch(5)
            if text == "&Quit":
                buttonLayout.addStretch(1)
            buttonLayout.addWidget(button)
        buttonLayout.addStretch()

        layout = QHBoxLayout()
        layout.addWidget(self.view, 1)
        # QBoxLayout::addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = Qt::Alignment())
        layout.addLayout(buttonLayout)
        self.setLayout(layout)

        fm = QFontMetrics(self.font())
        self.resize(self.scene.width() + fm.width(" Delete... ") + 50,
                    self.scene.height() + 50)
        self.setWindowTitle("Page Designer 页面设计器")

    def addBorders(self):
        '''添加出血框和打印边界框,对scene进行操作同时添加到self.borders这一列表中'''
        self.borders = []
        rect = QRectF(0, 0, PageSize[0], PageSize[1])
        self.borders.append(self.scene.addRect(
            rect,
            Qt.black))  # addRect px,py,x,y,QPen,QBrush or QRectF,QPen,QBrush
        # scene.addRect(): Return QGraphicsRectItem;Inherits: QGraphicsItem

        margin = 5.25 * PointSize
        self.borders.append(
            self.scene.addRect(rect.adjusted(margin, margin, -margin, -margin),
                               Qt.red))

    def removeBorders(self):
        '''从列表删除边框,从scene删除边框'''
        while self.borders:
            item = self.borders.pop()
            self.scene.removeItem(
                item
            )  #Removes the item item and all its children from the scene. 接受参数为QGraphicsItem
            del item

    def reject(self):
        self.accept()

    def accept(self):
        self.offerSave()
        QDialog.accept(
            self
        )  # 完成提示保存之后传递给QDialog的accept命令,之前几章好像讲过为什么要直接调用QDialog这个父类,这里的MWindow是QDialog

    def offerSave(self):
        '''根据Dirty判断是否更改,如果更改则弹出保存对话框,调用save()函数进行保存。'''
        if (Dirty and QMessageBox.question(
                self, "Page Designer - Unsaved Changes",
                "Save unsaved changes?", QMessageBox.Yes | QMessageBox.No)
                == QMessageBox.Yes):
            self.save()

    def position(self):
        point = self.mapFromGlobal(QCursor.pos(
        ))  # mFG接受一个QPoint参数,包含两个元素的元组 此函数转换QPoint到map,返回依旧是QPoint
        # Translates the global screen coordinate pos to widget coordinates.
        if not self.view.geometry().contains(
                point):  #??????????????????????????????????????????????
            coord = random.randint(36, 144)
            point = QPoint(coord, coord)
        else:
            if point == self.prevPoint:
                point += QPoint(self.addOffset, self.addOffset)
                self.addOffset += 5
            else:
                self.addOffset = 5
                self.prevPoint = point
        return self.view.mapToScene(
            point)  # 将Widght的点左边转换成为Scene坐标,调用对象是QGView

    def addText(self):
        dialog = TextItemDlg(position=self.position(),
                             scene=self.scene,
                             parent=self)
        dialog.exec_()

    def addBox(self):
        BoxItem(self.position(), self.scene)

    def addPixmap(self):
        path = (QFileInfo(self.filename).path() if self.filename else "."
                )  # 获取filename定义的正确地址,或者返回此程序根目录
        fname, filetype = QFileDialog.getOpenFileName(
            self, "Page Designer - Add Pixmap", path,
            "Pixmap Files (*.bmp *.jpg *.png *.xpm)")
        if not fname:
            return
        self.createPixmapItem(
            QPixmap(fname),
            self.position())  # 插入时候要将地址传递给QPixmap生成对象,并且还需要位置参数

    def createPixmapItem(self, pixmap, position,
                         matrix=QTransform()):  # 传递参数为:文件、位置和变换
        item = GraphicsPixmapItem(pixmap)  # 第一步,将QPixmap转换成为GPItem
        item.setFlags(QGraphicsItem.ItemIsSelectable
                      | QGraphicsItem.ItemIsMovable)  # 设置一些属性
        item.setPos(position)  # 设置位置
        item.setTransform(matrix)  # 将变换参数应用到GPItem之中
        self.scene.clearSelection()  # 选择清空
        self.scene.addItem(item)  # 添加项目
        item.setSelected(True)  # 并且选中
        global Dirty
        Dirty = True  # 全局变量Dirty设置为True
        return item  # 为什么需要返回这个???

    def selectedItem(
            self):  # 默认的scene选择的是一个列表,如果只有一个则返回index=0的item,如果多选则不返回任何一个
        items = self.scene.selectedItems()
        if len(items) == 1:
            return items[0]
        return None

    def copy(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copiedItem.clear()
        self.pasteOffset = 5
        stream = QDataStream(self.copiedItem, QIODevice.WriteOnly)
        self.writeItemToStream(stream, item)  # 写入到流

    def cut(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copy()
        self.scene.removeItem(item)
        del item

    def paste(self):
        if self.copiedItem.isEmpty():
            return
        stream = QDataStream(self.copiedItem, QIODevice.ReadOnly)
        self.readItemFromStream(
            stream, self.pasteOffset)  # 从数据流中读入信息,并且输出到self.pasteOffset中
        self.pasteOffset += 5

    def setAlignment(self, alignment):
        # Items are returned in arbitrary order
        items = self.scene.selectedItems()
        if len(items) <= 1:
            return
        # Gather coordinate data
        leftXs, rightXs, topYs, bottomYs = [], [], [], []
        for item in items:
            rect = item.sceneBoundingRect()
            # Returns the bounding rect of this item in scene coordinates : Return QRectF
            leftXs.append(rect.x())
            rightXs.append(rect.x() + rect.width())
            topYs.append(rect.y())
            bottomYs.append(rect.y() + rect.height())
        # Perform alignment
        if alignment == Qt.AlignLeft:
            xAlignment = min(leftXs)
            for i, item in enumerate(items):
                item.moveBy(xAlignment - leftXs[i], 0)
                # void QGraphicsItem::moveBy(qreal dx, qreal dy)
                # Moves the item by dx points horizontally, and dy point vertically.
        elif alignment == Qt.AlignRight:
            xAlignment = max(rightXs)
            for i, item in enumerate(items):
                item.moveBy(xAlignment - rightXs[i], 0)
        elif alignment == Qt.AlignTop:
            yAlignment = min(topYs)
            for i, item in enumerate(items):
                item.moveBy(0, yAlignment - topYs[i])
        elif alignment == Qt.AlignBottom:
            yAlignment = max(bottomYs)
            for i, item in enumerate(items):
                item.moveBy(0, yAlignment - bottomYs[i])
        global Dirty
        Dirty = True

    def rotate(self):
        for item in self.scene.selectedItems():
            item.setRotation(item.rotation() + 30)

    def delete(self):  # 从基本scene属性中选取选择的多个,弹出对话框,如果允许,则迭代进行删除,并且设置Dirty为True
        items = self.scene.selectedItems()
        if (len(items) and QMessageBox.question(
                self, "Page Designer - Delete", "Delete {0} item{1}?".format(
                    len(items), "s" if len(items) != 1 else ""),
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes):
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
            global Dirty
            Dirty = True

    def print_(self):
        # dialog = QPrintDialog(self.printer) # 在此已经设置好了self.printer 也就是QPrinter对象,QPDlg直接传递回了Printer对象,之后重新由
        # # printer对象声称心的QPrinter就可以继续使用在这句话中设置好的参数了。
        # if dialog.exec_():
        painter = QPainter(self.printer)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.TextAntialiasing)
        self.scene.clearSelection()
        self.removeBorders()
        self.scene.render(painter)
        # [void] Renders the source rect from scene into target, using painter. This function is useful for capturing the contents
        # of the scene onto a paint device, such as a QImage (e.g., to take a screenshot), or for printing with QPrinter. For example:
        self.addBorders()

    def open(self):
        self.offerSave()
        path = (QFileInfo(self.filename).path() if self.filename else ".")
        fname, filetype = QFileDialog.getOpenFileName(
            self, "Page Designer - Open", path,
            "cmPage Designer Files (*.cmpd *.pgd *.cmd)")
        if not fname:
            return
        self.filename = fname
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(str(fh.errorString()))
            items = self.scene.items()  # 返回所有的QGitem List形式
            while items:
                item = items.pop()  # 从列表中删除一个,从scene中删除一个,迭代到全部删除
                self.scene.removeItem(item)
                del item
            self.addBorders()
            stream = QDataStream(fh)
            stream.setVersion(QDataStream.Qt_5_7)
            magic = stream.readInt32()
            if magic != MagicNumber:
                raise IOError("not a valid .cmpd file")
            fileVersion = stream.readInt16()
            if fileVersion != FileVersion:
                raise IOError("unrecognised .cmpd file version")
            while not fh.atEnd():
                self.readItemFromStream(stream)
        except IOError as e:
            QMessageBox.warning(
                self, "Page Designer -- Open Error",
                "Failed to open {0}: {1}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()
        global Dirty
        Dirty = False

    def save(self):
        if not self.filename:
            path = "."
            fname, filetype = QFileDialog.getSaveFileName(
                self, "Page Designer - Save As", path,
                "cmPage Designer Files (*.cmpd *.pgd *.cmd)")
            if not fname:
                return
            self.filename = fname
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(str(fh.errorString()))
            self.scene.clearSelection()
            stream = QDataStream(fh)
            stream.setVersion(QDataStream.Qt_5_7)
            stream.writeInt32(MagicNumber)
            stream.writeInt16(FileVersion)
            for item in self.scene.items():
                self.writeItemToStream(stream, item)
        except IOError as e:
            QMessageBox.warning(
                self, "Page Designer -- Save Error",
                "Failed to save {0}: {1}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()
        global Dirty
        Dirty = False

    def readItemFromStream(self, stream, offset=0):
        type = ""
        position = QPointF()
        matrix = QTransform()
        rotateangle = 0  #add by yangrongdong
        type = stream.readQString()
        stream >> position >> matrix
        if offset:
            position += QPointF(offset, offset)
        if type == "Text":
            text = ""
            font = QFont()
            text = stream.readQString()
            stream >> font
            rotateangle = stream.readFloat()
            tx = TextItem(text, position, self.scene, font, matrix)
            tx.setRotation(rotateangle)
        elif type == "Box":
            rect = QRectF()
            stream >> rect
            style = Qt.PenStyle(stream.readInt16())
            rotateangle = stream.readFloat()
            bx = BoxItem(position, self.scene, style, rect, matrix)
            bx.setRotation(rotateangle)
        elif type == "Pixmap":
            pixmap = QPixmap()
            stream >> pixmap
            rotateangle = stream.readFloat()
            px = self.createPixmapItem(pixmap, position, matrix)
            px.setRotation(rotateangle)

    def writeItemToStream(self, stream, item):
        if isinstance(item, TextItem):
            stream.writeQString("Text")
            stream << item.pos() << item.transform()
            stream.writeQString(item.toPlainText())
            stream << item.font()
            stream.writeFloat(item.rotation())  #add by yangrongdong
        elif isinstance(item, GraphicsPixmapItem):
            stream.writeQString("Pixmap")
            stream << item.pos() << item.transform() << item.pixmap()
            stream.writeFloat(item.rotation())  #add by yangrongdong
        elif isinstance(item, BoxItem):
            stream.writeQString("Box")
            stream << item.pos() << item.transform() << item.rect
            stream.writeInt16(item.style)
            stream.writeFloat(item.rotation())  #add by yangrongdong
class Ui_MainWindow():
    
    def __init__(self):
        self.a =-1
        self.nom=""
        self.op=""
        self.Nomserie=""
        self.step=0
        self.time=False
        self.type_graph=""
        
        
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(10,10,556,392))
        self.graphicsView.setObjectName("graphicsView")
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0,0,673,125))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menufile")
        MainWindow.setMenuBar(self.menubar)
        self.actionOpen = QtWidgets.QAction(MainWindow)
        self.actionOpen.setObjectName("actionOpen")
        self.actionOpen.triggered.connect(self.showDialog)
        self.actionExit = QtWidgets.QAction(MainWindow)
        self.actionExit.setObjectName("actionExit")
        self.actionExit.triggered.connect(QApplication.quit)
        
        self.actionAbout = QtWidgets.QAction(MainWindow)
        self.actionAbout.setObjectName("actionAbout")
        self.actionAbout.triggered.connect(self.showAbout)
        
        self.menuFile.addAction(self.actionOpen)
        self.menuFile.addAction(self.actionAbout)  #<------
        self.menuFile.addAction(self.actionExit)
        self.menubar.addAction(self.menuFile.menuAction())
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
      

        
                
        # Create textbox
        self.textbox = QLineEdit(MainWindow)
        self.textbox.move(580,280)
        self.textbox.resize(280,40)
 
        # Create a button in the window
        self.button = QPushButton('Ok', MainWindow)
        self.button.move(580,320)
        
        #Create a button 2 in the window
        self.button2 = QPushButton('Drawing graphs',MainWindow)
        self.button2.move(580,165)
 
        # connect button to function on_click
        self.button.clicked.connect(self.on_click)
        self.button2.clicked.connect(self.on_click2)
        
        #Getchoice
        self.cb = QComboBox(MainWindow)
        self.cb.move(580,250)
        self.cb.addItem("")
        self.cb.addItem("Degree")
        self.cb.addItem("Closeness")
        self.cb.addItems(["Pagerank", "Betweeness"])
        self.cb.currentIndexChanged.connect(self.selectionchange)
        
        
        
        #object presents the user with a integer
        self.l1 = QLabel("current value:")
        self.l1.move(650,250)
        self.sp = QSpinBox(MainWindow)
        self.sp.setMaximum(1049)
        self.sp.move(700,250)
        self.sp.valueChanged.connect(self.valuechange)
        
        #Getchoice 2
        self.cb2 = QComboBox(MainWindow)
        self.cb2.move(580,50)
        self.cb2.addItem("")
        self.cb2.addItem("Game of Thrones")
        self.cb2.addItem("Breaking Bad")
        self.cb2.addItem("House of Card")
        self.cb2.currentIndexChanged.connect(self.selectionchange2)
        
        
        #Radiobutton for graph
        
        self.b0 = QRadioButton("Classical",MainWindow)
        self.b0.move(580,140)
        self.b0.setChecked(True)
        self.b0.toggled.connect(lambda:self.btnstate(self.b0))
        self.b1 = QRadioButton("Random",MainWindow)
        self.b1.move(580,80)
        self.b1.setChecked(True)
        self.b1.toggled.connect(lambda:self.btnstate(self.b1))
        self.b2 = QRadioButton("Circular",MainWindow)
        self.b2.move(580,95)
        self.b2.setChecked(True)
        self.b2.toggled.connect(lambda:self.btnstate(self.b2))
        self.b3 = QRadioButton("Spectral",MainWindow)
        self.b3.move(580,110)
        self.b3.setChecked(True)
        self.b3.toggled.connect(lambda:self.btnstate(self.b3))
        self.b4 = QRadioButton("Shell",MainWindow)
        self.b4.move(580,125)
        self.b4.setChecked(True)
        self.b4.toggled.connect(lambda:self.btnstate(self.b4))
        
        
        
        if self.time == False :
            #ProgressBar
            self.bar = QProgressBar(MainWindow)
            self.bar.setGeometry(50, 80, 500, 39)
            self.bar.move(140,650)
            self.bar.setMaximum(50)
            self.bar.setMinimum(0)
            
        
 
   
    def showDialog(self): #permetde charger l'image avec la bar du menu
        fileName = QFileDialog.getOpenFileName(MainWindow, 'Open file')[0]
        print(fileName)
        self.scene = QGraphicsScene()
        self.scene.addPixmap(QPixmap(fileName))
        self.graphicsView.setScene(self.scene)
        
    def showAbout(self):#permet d'afficher le about du menu
        QMessageBox.question(MainWindow,'About',"Authors of the program: Yannis Hutt and Julien Cadier", QMessageBox.Ok, QMessageBox.Ok)

        
    def retranslateUi(self, MainWindow):#permet de faire le menu déroulant
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Mainwindow"))
        self.menuFile.setTitle(_translate("MainWindow","F&ile"))
        self.actionOpen.setText(_translate("MainWindow","Open"))
        self.actionAbout.setText(_translate("MainWindow","About"))
        self.actionExit.setText(_translate("MainWindow","Exit"))
        
        
    def on_click(self): #permet de faire l'évenement pour faire le graph
        self.bar.setMaximum(0)
        textboxValue = self.textbox.text()
        QMessageBox.question(MainWindow, 'result', "You typed: " + textboxValue, QMessageBox.Ok, QMessageBox.Ok)
        self.nom = self.textbox.text()

        print(self.nom)
        print(self.op)
        lireGraph2.start_main(self.Nomserie,self.a,self.nom,self.op)
        self.scene = QGraphicsScene()
        self.scene.clearSelection()
        self.scene.addPixmap(QPixmap("images/" + self.nom +self.op+ ".jpg"))
        self.graphicsView.setScene(self.scene)
        self.bar.setMaximum(50)
    
    def on_click2(self):
        self.bar.setMaximum(0)
        test_lireGraph.start_graph(self.Nomserie,self.type_graph)
        self.scene = QGraphicsScene()
        self.scene.clearSelection()
        self.scene.addPixmap(QPixmap("images/" + self.Nomserie+"_"+self.type_graph+ ".jpg"))
        self.graphicsView.setScene(self.scene)
        self.bar.setMaximum(50)
        
    def selectionchange(self,i): # permet de faire la selection des opérations
        print ("Items in the list are :")
        for count in range(self.cb.count()):
            print (self.cb.itemText(count))
        print ("Current index",i,"selection changed ",self.cb.currentText())
        self.op = self.cb.currentText()
        def f(x):
            return {
                    "" : 'essai',
                    "Degree" : 'd',
                    "Closeness" : 'c',
                    "Pagerank" : 'p',
                    "Betweeness" : 'b'
                    }[x]
        self.op=f(self.op)
        print(self.op)
        
        
    def selectionchange2(self,i):
        print("Items in the second list are :")
        for count in range(self.cb2.count()):
            print (self.cb2.itemText(count))
        print ("current index", i,"selection changed ", self.cb.currentText())
        self.Nomserie = self.cb2.currentText()
        print(self.Nomserie)
        
        
        
        
    def valuechange(self):
      self.l1.setText("current value:"+str(self.sp.value()))
      print(self.sp.value())
      self.a = self.sp.value() #affectation valeur int
      
    def text_changed(self):
        """ updates the list of possible completions each time a key is 
            pressed """
        pattern = str(self.le.text())
        self.new_list = [item for item in lireGraph2.dicoNomToNum if item.find(pattern) == 0]
        self.lm.setAllData(self.new_list)
        
    def btnstate(self,b): #permet de savoir quelle graph faire
        if b.text() == "Random":
            if b.isChecked() == True:
                print(b.text()+" is selected")
                self.type_graph = "Random"
            else:
                print(b.text()+" is deselcted")
       
        if b.text() == "Circular":
            if b.isChecked() == True:
                print(b.text()+" is selected")
                self.type_graph = "Circular"
            else:
                print(b.text()+" is deselcted")
            
        if b.text() == "Spectral":
            if b.isChecked() == True:
                print(b.text()+" is selected")
                self.type_graph = "Spectral"
            else:
                print(b.text()+" is deselcted")	
  
        if b.text() == "Shell":
            if b.isChecked() == True:
                print(b.text()+" is selected")
                self.type_graph = "Shell"
            else:
                print(b.text()+" is deselcted")       

        if b.text() == "Classical":
            if b.isChecked() == True:
                print(b.text()+" is selected")
                self.type_graph = "Classical"
            else:
                print(b.text()+" is deselcted")       
Пример #8
0
class WorldFrame(QGraphicsView):
    msg2Statusbar = pyqtSignal(str)

    def __init__(self, parent, world):
        super().__init__(parent)
        self._zoom = 0
        self._scene = QGraphicsScene(self)
        self._world = world
        self._worldview = WorldView(self, world)
        self._scene.addItem(self._worldview)
        self.setScene(self._scene)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
        self.setBackgroundBrush(QBrush(QColor(30, 30, 30)))
        self.setFrameShape(QFrame.NoFrame)
        self.pointerMode = PointerMode.Normal
        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setDragMode(QGraphicsView.NoDrag)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setMouseTracking(True)

        self.logger = parent.logger

    def fitInView(self, scale=True):
        rect = QRectF(self._worldview.boundingRect())
        if not rect.isNull():
            self.setSceneRect(rect)
            unity = self.transform().mapRect(QRectF(0, 0, 1, 1))
            self.scale(1 / unity.width(), 1 / unity.height())
            viewrect = self.viewport().rect()
            scenerect = self.transform().mapRect(rect)
            factor = min(viewrect.width() / scenerect.width(),
                         viewrect.height() / scenerect.height())
            self.scale(factor, factor)
            self._zoom = 0

    def resetViewport(self):
        self.fitInView()
        self.update()

    def mouseMoveEvent(self, event):
        point = self.mapToScene(event.x(), event.y())
        ex, ey = point.x(), point.y()
        try:
            self.currentGridPoint = self._worldview.pixToGrid(ex, ey)
        except IndexError:
            self.currentGridPoint = Space(0, 0, Terrain())
        gridx, gridy = self.currentGridPoint
        landmark = " "
        players = " "
        if 0 < gridx < self._world.Width and 0 < gridy < self._world.Height:
            space = self._world.Map[gridy][gridx]
            if space in self._world.Towns or space in self._world.Wilds:
                landmark += space.Name
            for p in self._world.Players:
                if p.Location == space:
                    players += p.Name + " "
        self.msg2Statusbar.emit("({}, {}) {} [{}]".format(int(gridx), int(gridy), landmark, players))
        super().mouseMoveEvent(event)
        self.update()

    def wheelEvent(self, event):
        if event.angleDelta().y() > 0:
            factor = 1.25
            self._zoom += 1
        else:
            factor = 0.8
            self._zoom -= 1
        if self._zoom > 0:
            self.scale(factor, factor)
        elif self._zoom == 0:
            self.fitInView()
        else:
            self._zoom = 0

    def update(self):
        super().update()
        self._worldview.update()

    def changePointerMode(self, mode):
        self.pointerMode = mode

    def mousePressEvent(self, event):
        if event.buttons() & Qt.MiddleButton:
            self.middleClickEvent(event)
        elif event.buttons() & Qt.LeftButton:
            self.leftClickEvent(event)
        elif event.buttons() & Qt.RightButton:
            self.rightClickEvent(event)
        super().mousePressEvent(event)

    def middleClickEvent(self, event):
        if self.dragMode() == QGraphicsView.ScrollHandDrag:
            self.setDragMode(QGraphicsView.NoDrag)
            self.pointerMode = PointerMode.Normal
        else:
            self.setDragMode(QGraphicsView.ScrollHandDrag)
            self.pointerMode = PointerMode.Drag

    def leftClickEvent(self, event):
        if self.pointerMode == PointerMode.AddTown:
            dialog = AddTownDialog(self, self.currentGridPoint)
            if dialog.exec_():
                town = dialog.returnData
                self._world.addTown(town)
                if dialog.isStartingTown:
                    self._world.StartingTown = town
            self.pointerMode = PointerMode.Normal
        if self.pointerMode == PointerMode.AddWilds:
            dialog = AddWildsDialog(self, self.currentGridPoint)
            if dialog.exec_():
                self._world.addWilds(dialog.returnData)
            self.pointerMode = PointerMode.Normal

    def rightClickEvent(self, event):
        if self.pointerMode != PointerMode.Normal:
            self.pointerMode = PointerMode.Normal
        self.update()

    def mouseReleaseEvent(self, event):
        if self.dragMode() == QGraphicsView.ScrollHandDrag:
            self.setDragMode(QGraphicsView.NoDrag)
            self.pointerMode = PointerMode.Normal
        super().mouseReleaseEvent(event)

    def getBoundingSubrectangle(self, spaces: [Space]) -> QRectF:
        def getTopLeftSpace(spaces):
            minX = min([s.X for s in spaces])
            minY = min([s.Y for s in spaces])
            topLeft = [s for s in spaces if s.X == minX and s.Y == minY][0]
            return topLeft

        def getBottomRightSpace(spaces):
            maxX = max([s.X for s in spaces])
            maxY = max([s.Y for s in spaces])
            botRight = [s for s in spaces if s.X == maxX and s.Y == maxY][0]
            return botRight

        topLeftSpace = getTopLeftSpace(spaces)
        topLeftPix = self.mapFromParent(self._worldview.gridToPix(topLeftSpace.X, topLeftSpace.Y))
        bottomRightSpace = getBottomRightSpace(spaces)
        bottomRightPix = self.mapFromParent(self._worldview.gridToPix(bottomRightSpace.X, bottomRightSpace.Y)) + \
                         QPoint(self._worldview.squareWidth, self._worldview.squareHeight)
        subBoundingRect = QRectF(topLeftPix, bottomRightPix)
        return subBoundingRect

    def saveSubimage(self, spaces: [Space], filename="capture.png"):
        self._scene.clearSelection()
        boundingRect = self.getBoundingSubrectangle(spaces)
        self._scene.setSceneRect(boundingRect)
        pix = QImage(self._scene.sceneRect().size().toSize(), QImage.Format_ARGB32)
        pix.fill(Qt.TransparentMode)
        painter = QPainter(pix)
        painter.setRenderHint(QPainter.Antialiasing)
        self._scene.render(painter)
        painter.end()  # Removing will cause silent crash
        pix.save(filename)
Пример #9
0
class GraphDigitGraphicsView(QGraphicsView):
    sigMouseMovePoint = pyqtSignal(QPoint, QPointF)
    sigModified = pyqtSignal(bool)
    sigNewCurveAdded = pyqtSignal()

    # 自定义信号sigMouseMovePoint,当鼠标移动时,在mouseMoveEvent事件中,将当前的鼠标位置发送出去
    # QPoint--传递的是view坐标
    def __init__(self, parent=None):
        super(GraphDigitGraphicsView, self).__init__(parent)
        # scene
        rect = QRectF(0, 0, 300, 400)
        self.scene = QGraphicsScene(rect)  # 创建场景 参数:场景区域
        self.setScene(self.scene)  # 给视图窗口设置场景
        # image
        self.graphicsPixmapItem = QGraphicsPixmapItem()  # chart image
        self.scene.addItem(self.graphicsPixmapItem)
        # setAntialias
        self.setRenderHint(QPainter.Antialiasing)
        # image object stored in project data
        # item objects storage
        self.axesxObjs = {}
        self.axesyObjs = {}
        self.gridObjs = []
        self.curveObjs = {}
        self.pointObjs = {}
        # axis coord stored in project data
        # grid setting stored in project data
        # grid position
        self.gridxpos = []
        self.gridypos = []
        # axes curve and point datamodel
        self.axesxModel = QStandardItemModel()
        self.axesyModel = QStandardItemModel()
        self.axesxSelectModel = QItemSelectionModel(self.axesxModel)
        self.axesySelectModel = QItemSelectionModel(self.axesyModel)
        self.curveModel = QStandardItemModel()
        self.pointsModel = QStandardItemModel()

        self.curveModel.setHorizontalHeaderLabels(
            ["current", "name", "visible"])
        self.pointsModel.setHorizontalHeaderLabels(["order", "x", "y"])
        self.axesxModel.setHorizontalHeaderLabels(["position", "x"])
        self.axesyModel.setHorizontalHeaderLabels(["position", "y"])

        ###
        self.xNo = 0
        self.yNo = 0

        ###
        self.mode = OpMode.default
        # data manage
        self.proj = Digi()

        # init
        self.currentCurve = None
        self.pointsModel.itemChanged.connect(self.changePointOrder)
        self.curveModel.itemChanged.connect(self.changeCurveVisible)
        self.scene.selectionChanged.connect(self.slotSceneSeletChanged)

        # state
        self._lastCurve = None

    def load(self, proj):
        # image # only for load
        self.scaleGraphImage(proj.imgScale)
        # axes
        xadded = []
        yadded = []
        for xpos, xcoord in proj.data["axesxObjs"].items():
            if xpos in xadded:
                continue
            else:
                xadded.append(xpos)
            item = QGraphicsAxesItem(
                0,
                self.scene.sceneRect().y(), 0,
                self.scene.sceneRect().y() + self.scene.sceneRect().height())
            item.setFlags(QGraphicsItem.ItemIsSelectable
                          | QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsMovable)
            item.setPos(xpos, 0)
            item.axis = "x"
            item.setPen(QPen(Qt.red, 1, Qt.DashLine))
            self.scene.addItem(item)
            self.axesxObjs[item] = xcoord
            labelitem = QStandardItem("x:{}".format(xpos))
            labelitem.setData(item)
            self.axesxModel.appendRow([labelitem, QStandardItem(str(xcoord))])
            self.xNo += 1
            self.axesxModel.setVerticalHeaderItem(
                self.axesxModel.rowCount() - 1,
                QStandardItem("x{}".format(self.xNo)))
        for ypos, ycoord in proj.data["axesyObjs"].items():
            if ypos in yadded:
                continue
            else:
                yadded.append(ypos)
            item = QGraphicsAxesItem(
                self.scene.sceneRect().x(), 0,
                self.scene.sceneRect().x() + self.scene.sceneRect().width(), 0)
            item.setFlags(QGraphicsItem.ItemIsSelectable
                          | QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsMovable)
            item.setPos(0, ypos)
            item.axis = "y"
            item.setPen(QPen(Qt.red, 1, Qt.DashLine))
            self.scene.addItem(item)
            self.axesyObjs[item] = ycoord
            labelitem = QStandardItem("y:{}".format(ypos))
            labelitem.setData(item)
            self.axesyModel.appendRow([labelitem, QStandardItem(str(ycoord))])
        # curve
        for curve in proj.data["curves"]:
            self.pointObjs[curve] = []
            self.addCurve(curve)
            clr = RandItem.nextColor()
            for x, y in proj.data["curves"][curve]:
                ptitem = QGraphicsPointItem()
                ptitem.pointColor = clr
                ptitem.linewidth = 1
                ptitem.setPos(x, y)
                ptitem.parentCurve = curve
                ptitem.setFlags(QGraphicsItem.ItemIsSelectable
                                | QGraphicsItem.ItemIsFocusable
                                | QGraphicsItem.ItemIsMovable)
                i = pointInsertPosition(ptitem,
                                        self.pointObjs[self.currentCurve])
                self.pointObjs[self.currentCurve].insert(i, ptitem)
                self.scene.addItem(ptitem)
            self.updateCurve(curve)
        # grid
        self.calGridCoord()
        self.updateGrid()
        self.sigModified.emit(True)
        self.mode = OpMode.select

    def resetview(self):
        self.setGraphImage(None)
        self.scaleGraphImage(1)
        for obj in self.axesxObjs:
            self.scene.removeItem(obj)
        self.axesxObjs = {}
        for obj in self.axesyObjs:
            self.scene.removeItem(obj)
        self.axesyObjs = {}
        for obj in self.gridObjs:
            self.scene.removeItem(obj)
        self.gridObjs = []
        for curve in self.curveObjs:
            for obj in self.curveObjs[curve]:
                self.scene.removeItem(obj)
        self.curveObjs = {}
        for curve in self.pointObjs:
            for obj in self.pointObjs[curve]:
                self.scene.removeItem(obj)
        self.pointObjs = {}
        self.axesxModel.clear()
        self.axesyModel.clear()
        self.curveModel.clear()
        self.pointsModel.clear()
        self.axesxSelectModel.clear()
        self.axesySelectModel.clear()
        self.curveModel.setHorizontalHeaderLabels(
            ["current", "name", "visible"])
        self.pointsModel.setHorizontalHeaderLabels(["order", "x", "y"])
        self.axesxModel.setHorizontalHeaderLabels(["position", "x"])
        self.axesyModel.setHorizontalHeaderLabels(["position", "y"])

        self.xNo = 0
        self.yNo = 0

        ###
        self.mode = OpMode.default
        # data manage
        self.proj.resetData(True)
        # init
        self.currentCurve = None
        self._lastCurve = None

    def dump(self):
        proj = self.proj
        proj.data["axesxObjs"] = {}  # [x1,x2,x3]
        proj.data["axesyObjs"] = {}  # [y1,y2,y3]
        proj.data["curves"] = {}  # {'default':(x1,y1),(x2,y2)}
        # axes
        for item, xcoord in self.axesxObjs.items():
            proj.data["axesxObjs"][item.pos().x()] = xcoord
        for item, ycoord in self.axesyObjs.items():
            proj.data["axesyObjs"][item.pos().y()] = ycoord
        # curve
        for curve in self.pointObjs:
            proj.data["curves"][curve] = []
            for item in self.pointObjs[curve]:
                proj.data["curves"][curve].append((item.x(), item.y()))

    def mouseMoveEvent(self, evt):
        pt = evt.pos()  # 获取鼠标坐标--view坐标
        self.sigMouseMovePoint.emit(pt, self.mapToScene(pt))  # 发送鼠标位置
        QGraphicsView.mouseMoveEvent(self, evt)
        item = self.scene.focusItem()
        if not item:
            items = self.scene.selectedItems()
            if len(items) != 1:
                return
            else:
                item = items[0]
        if item:
            if isinstance(item, QGraphicsPointItem) and item.parentCurve:
                # self.changeCurrentCurve(item.parentCurve)
                self.updateCurve(self.currentCurve, Qt.red)
                self.updateCurvePoints(self.currentCurve)
                self.sigModified.emit(True)
            elif isinstance(item, QGraphicsAxesItem):
                if item.axis == "x":
                    if self.mode != OpMode.axesx:
                        self.scene.clearSelection()
                        return
                    self.axesxSelectModel.clearSelection()
                    self.axesySelectModel.clearSelection()
                    for i in range(self.axesxModel.rowCount()):
                        if self.axesxModel.item(i, 0).data() is item:
                            parent = QModelIndex()
                            topleftindex = self.axesxModel.index(
                                i, 0,
                                parent)  # self.axesxModel.item(i,0).index()
                            rightbottomindex = self.axesxModel.index(
                                i, 1, parent)
                            self.axesxSelectModel.select(
                                QItemSelection(topleftindex, rightbottomindex),
                                QItemSelectionModel.Select)
                            self.axesxModel.item(i, 0).setText("x:{}".format(
                                evt.pos().x()))
                            break

                    item.setLine(
                        0,
                        self.scene.sceneRect().y(), 0,
                        self.scene.sceneRect().y() +
                        self.scene.sceneRect().height())
                    item.setPos(self.mapToScene(evt.pos()).x(), 0)
                    self.sigModified.emit(True)
                    self.calGridCoord()
                    self.updateGrid()

                elif item.axis == "y":
                    if self.mode != OpMode.axesy:
                        self.scene.clearSelection()
                        return
                    self.axesxSelectModel.clearSelection()
                    self.axesySelectModel.clearSelection()
                    for i in range(self.axesyModel.rowCount()):
                        if self.axesyModel.item(i, 0).data() is item:
                            topleftindex = self.axesyModel.index(
                                i, 0)  # self.axesxModel.item(i,0).index()
                            rightbottomindex = self.axesyModel.index(i, 1)
                            self.axesySelectModel.select(
                                QItemSelection(topleftindex, rightbottomindex),
                                QItemSelectionModel.Select)
                            self.axesyModel.item(i, 0).setText("y:{}".format(
                                evt.pos().y()))
                            break

                    item.setLine(
                        self.scene.sceneRect().x(), 0,
                        self.scene.sceneRect().x() +
                        self.scene.sceneRect().width(), 0)
                    item.setPos(0, self.mapToScene(evt.pos()).y())
                    self.sigModified.emit(True)
                    self.calGridCoord()
                    self.updateGrid()

        # self.updateCurve(self.currentCurve)
        # self.repaint()
        # self.setDragMode(QGraphicsView.NoDrag) #(RubberBandDrag) #ScrollHandDrag) #NoDrag)

    def mousePressEvent(self, event):
        super().mousePressEvent(event)
        self.__pressPt = event.pos()
        ptscene = self.mapToScene(event.pos())
        if self.mode is OpMode.axesx:
            for axisitem in self.axesxObjs:
                if abs(ptscene.x() - axisitem.pos().x()) < 5:
                    self.scene.clearSelection()
                    axisitem.setSelected(True)
                    return
        elif self.mode is OpMode.axesy:
            for axisitem in self.axesyObjs:
                if abs(ptscene.y() - axisitem.pos().y()) < 5:
                    self.scene.clearSelection()
                    axisitem.setSelected(True)
                    return

    def keyPressEvent(self, event: QKeyEvent) -> None:
        # super().keyPressEvent(event)
        item = self.scene.focusItem()
        if not item:
            items = self.scene.selectedItems()
            if len(items) != 1:
                return
            else:
                item = items[0]
        if item:
            if isinstance(item, QGraphicsPointItem) and item.parentCurve:
                if event.key() == Qt.Key_Up:
                    item.setPos(item.pos().x(), item.pos().y() - 1)
                elif event.key() == Qt.Key_Down:
                    item.setPos(item.pos().x(), item.pos().y() + 1)
                elif event.key() == Qt.Key_Left:
                    item.setPos(item.pos().x() - 1, item.pos().y())
                elif event.key() == Qt.Key_Right:
                    item.setPos(item.pos().x() + 1, item.pos().y())
                else:
                    return
                self.updateCurve(self.currentCurve, Qt.red)
                self.updateCurvePoints(self.currentCurve)
                self.sigModified.emit(True)
            elif isinstance(item, QGraphicsAxesItem):
                if item.axis == "x":
                    if event.key() == Qt.Key_Left:
                        item.moveBy(-1, 0)
                    elif event.key() == Qt.Key_Right:
                        item.moveBy(1, 0)
                    else:
                        return
                    self.sigModified.emit(True)
                    self.calGridCoord()
                    self.updateGrid()

                    self.axesxSelectModel.clearSelection()
                    self.axesySelectModel.clearSelection()
                    for i in range(self.axesxModel.rowCount()):
                        if self.axesxModel.item(i, 0).data() is item:
                            parent = QModelIndex()
                            topleftindex = self.axesxModel.index(
                                i, 0,
                                parent)  # self.axesxModel.item(i,0).index()
                            rightbottomindex = self.axesxModel.index(
                                i, 1, parent)
                            self.axesxSelectModel.select(
                                QItemSelection(topleftindex, rightbottomindex),
                                QItemSelectionModel.Select)
                            self.axesxModel.item(i, 0).setText("x:{}".format(
                                item.pos().x()))
                            break

                elif item.axis == "y":
                    if event.key() == Qt.Key_Up:
                        item.setPos(0, item.pos().y() - 1)
                    elif event.key() == Qt.Key_Down:
                        item.setPos(0, item.pos().y() + 1)
                    else:
                        return
                    self.sigModified.emit(True)
                    self.calGridCoord()
                    self.updateGrid()

                    self.axesxSelectModel.clearSelection()
                    self.axesySelectModel.clearSelection()
                    for i in range(self.axesyModel.rowCount()):
                        if self.axesyModel.item(i, 0).data() is item:
                            topleftindex = self.axesyModel.index(
                                i, 0)  # self.axesxModel.item(i,0).index()
                            rightbottomindex = self.axesyModel.index(i, 1)
                            self.axesySelectModel.select(
                                QItemSelection(topleftindex, rightbottomindex),
                                QItemSelectionModel.Select)
                            self.axesyModel.item(i, 0).setText("y:{}".format(
                                item.pos().y()))
                            break

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        ptscene = self.mapToScene(event.pos())
        # item = self.scene.itemAt(ptscene, self.transform())
        clicked = True if event.pos() == self.__pressPt else False
        if self.mode is OpMode.select:
            pass
            # super().mousePressEvent(event)
        elif self.mode is OpMode.axesx and clicked:
            self.axesxSelectModel.clear()
            self.axesySelectModel.clear()
            for axisitem in self.axesxObjs:
                if abs(ptscene.x() - axisitem.pos().x()) < 5:
                    self.scene.clearSelection()
                    axisitem.setSelected(True)
                    return
            item = QGraphicsAxesItem(
                0,
                self.scene.sceneRect().y(), 0,
                self.scene.sceneRect().y() + self.scene.sceneRect().height())
            item.setPos(ptscene.x(), 0)
            item.axis = "x"
            item.setPen(QPen(Qt.red, 1, Qt.DashLine))
            self.scene.addItem(item)
            item.setFlags(QGraphicsItem.ItemIsSelectable
                          | QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsMovable)

            xs = list(self.axesxObjs.values())
            if not self.axesxObjs:
                nextx = 0
            elif len(self.axesxObjs) == 1:
                nextx = xs[0] + 0.1
            else:
                nextx = 2 * xs[-1] - xs[-2]
            x, okPressed = QInputDialog.getDouble(
                self,
                self.tr("set x coordiniate"),
                self.tr("set the x coord for axis"),
                nextx,
                decimals=3)
            if okPressed and x not in self.axesxObjs.values():
                self.axesxObjs[item] = x
                labelItem = QStandardItem("x:{}".format(item.pos().x()))
                labelItem.setData(item)
                self.axesxModel.appendRow([labelItem, QStandardItem(str(x))])
                self.calGridCoord("x")
                self.updateGrid()
                # item.setSelected(True)
                for i in range(self.axesxModel.rowCount()):
                    if self.axesxModel.item(i, 0).data() is item:
                        topleftindex = self.axesxModel.index(
                            i, 0)  # self.axesxModel.item(i,0).index()
                        rightbottomindex = self.axesxModel.index(i, 1)
                        self.axesxSelectModel.select(
                            QItemSelection(topleftindex, rightbottomindex),
                            QItemSelectionModel.Select)
                        break
                self.sigModified.emit(True)
                self.scene.clearSelection()
            else:
                self.scene.removeItem(item)
        elif self.mode is OpMode.axesy and clicked:
            self.axesxSelectModel.clear()
            self.axesySelectModel.clear()
            for axisitem in self.axesyObjs:
                if abs(ptscene.y() - axisitem.pos().y()) < 5:
                    self.scene.clearSelection()
                    axisitem.setSelected(True)
                    return
            item = QGraphicsAxesItem(
                self.scene.sceneRect().x(), 0,
                self.scene.sceneRect().x() + self.scene.sceneRect().width(), 0)
            item.setPos(0, ptscene.y())
            item.axis = "y"
            item.setPen(QPen(Qt.red, 1, Qt.DashLine))
            self.scene.addItem(item)
            item.setFlags(QGraphicsItem.ItemIsSelectable
                          | QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsMovable)

            ys = list(self.axesyObjs.values())
            if not self.axesyObjs:
                nexty = 0
            elif len(self.axesyObjs) == 1:
                nexty = ys[0] + 0.1
            else:
                nexty = 2 * ys[-1] - ys[-2]
            y, okPressed = QInputDialog.getDouble(
                self,
                self.tr("set y coordiniate"),
                self.tr("set the y coord for axis"),
                nexty,
                decimals=3)
            if okPressed and y not in self.axesyObjs.values():
                self.axesyObjs[item] = y
                labelItem = QStandardItem("y:{}".format(item.pos().y()))
                labelItem.setData(item)
                self.axesyModel.appendRow([labelItem, QStandardItem(str(y))])
                self.calGridCoord("y")
                self.updateGrid()
                # item.setSelected(True)

                for i in range(self.axesyModel.rowCount()):
                    if self.axesyModel.item(i, 0).data() is item:
                        topleftindex = self.axesyModel.index(
                            i, 0)  # self.axesxModel.item(i,0).index()
                        rightbottomindex = self.axesyModel.index(i, 1)
                        self.axesySelectModel.select(
                            QItemSelection(topleftindex, rightbottomindex),
                            QItemSelectionModel.Select)
                        break
                self.sigModified.emit(True)
            else:
                self.scene.removeItem(item)
        elif self.mode is OpMode.curve and clicked:
            self.sigMouseMovePoint.emit(event.pos(), ptscene)
            if len(self.curveObjs) == 0:
                self.addCurve('curve1')
            if self.currentCurve not in self.pointObjs:
                self.pointObjs[self.currentCurve] = []

            ptitem = QGraphicsPointItem()
            ptitem.pointColor = Qt.blue
            ptitem.linewidth = 1
            ptitem.setPos(ptscene)
            ptitem.parentCurve = self.currentCurve
            ptitem.setFlags(QGraphicsItem.ItemIsSelectable
                            | QGraphicsItem.ItemIsFocusable
                            | QGraphicsItem.ItemIsMovable)
            self.scene.addItem(ptitem)

            i = pointInsertPosition(ptitem, self.pointObjs[self.currentCurve])
            self.pointObjs[self.currentCurve].insert(i, ptitem)
            self.updateCurve(self.currentCurve, Qt.red)
            self.sigModified.emit(True)
            ptitem.setSelected(True)

            # item1=QGraphicsRectItem(rect)  #创建矩形---以场景为坐标
            # item1.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable|QGraphicsItem.ItemIsMovable)  #给图元设置标志
            # QGraphicsItem.ItemIsSelectable---可选择
            # QGraphicsItem.ItemIsFocusable---可设置焦点
            # QGraphicsItem.ItemIsMovable---可移动
            # QGraphicsItem.ItemIsPanel---
            # self.scene.addItem(item1)  #给场景添加图元

    def slotSceneSeletChanged(self):
        items = self.scene.selectedItems()
        if len(items) != 1:  # ony allow select one item
            self.scene.clearSelection()
            return
        # item = items[0]
        item = self.scene.focusItem()
        if not item:
            items = self.scene.selectedItems()
            if len(items) != 1:
                return
            else:
                item = items[0]
        if item:
            if isinstance(item, QGraphicsPointItem) and item.parentCurve:
                self.changeCurrentCurve(item.parentCurve)

    def deleteItem(self, item):
        """delete point on curve or axis object"""
        curvechange = None
        if isinstance(item, QGraphicsPointItem):
            for curvename, pointitems in self.pointObjs.items():
                for ptitem in pointitems:
                    if ptitem is item:
                        curvechange = curvename
                        pointitems.remove(ptitem)
                        self.scene.removeItem(item)
                        self.sigModified.emit(True)
                        break
        if curvechange:
            self.updateCurve(curvechange)

        if isinstance(item, QGraphicsAxesItem):
            if item.axis == "x":
                for line in self.axesxObjs:
                    if line is item:
                        for i in range(self.axesxModel.rowCount()):
                            if self.axesxModel.item(i, 0).data(
                            ) is item:  # float(self.axesxModel.item(i, 0).text().strip("x:")) == line.pos().x():
                                self.axesxModel.removeRow(i)
                                break
                        self.axesxObjs.pop(line)
                        self.scene.removeItem(line)
                        self.sigModified.emit(True)
                        break
            elif item.axis == "y":
                for line in self.axesyObjs:
                    if line is item:
                        for i in range(self.axesyModel.rowCount()):
                            if float(
                                    self.axesyModel.item(i, 0).text().strip(
                                        "y:")) == line.pos().y():
                                self.axesyModel.removeRow(i)
                                break
                        self.axesyObjs.pop(line)
                        self.scene.removeItem(line)
                        self.sigModified.emit(True)
                        break
            self.calGridCoord()
            self.updateGrid()

    def deleteSelectedItem(self):
        pointitems = self.scene.selectedItems()
        if len(pointitems) == 1:
            self.deleteItem(pointitems[0])

    def setGraphImage(self, imgfile):
        if not isinstance(imgfile, str):
            img = QPixmap(300, 400)
            img.fill(QColor("#EEE"))
            self.graphicsPixmapItem.setPixmap(img)
            self.scene.setSceneRect(0, 0, 300, 400)
        elif os.path.exists(imgfile):
            img = QPixmap(imgfile)
            self.graphicsPixmapItem.setPixmap(img)
            self.scene.setSceneRect(0, 0, img.width(), img.height())
            self.scene.clearSelection()  # 【清除选择】
            self.sigModified.emit(True)
            return True
        else:
            return False

    def scaleGraphImage(self, scale=1):
        if scale and scale > 0:
            self.proj.imgScale = scale
        self.graphicsPixmapItem.setScale(scale)
        if self.graphicsPixmapItem.pixmap().width(
        ) > 0 and self.graphicsPixmapItem.pixmap().height() > 0:
            self.scene.setSceneRect(
                0, 0,
                self.graphicsPixmapItem.pixmap().width() * scale,
                self.graphicsPixmapItem.pixmap().height() * scale)
        self.scene.clearSelection()  # 【清除选择】
        self.sigModified.emit(True)

    def addCurve(self, name=None):
        if not name:
            name = nextName(self.currentCurve)
        while (name in self.curveObjs):
            name = nextName(name)
        self.curveObjs[name] = []
        self.pointObjs[name] = []
        item1 = IconItem()
        item2 = QStandardItem(name)
        item3 = QStandardItem()
        item1.setEditable(False)
        item3.setCheckable(True)
        item3.setAutoTristate(False)
        item3.setEditable(False)
        item3.setCheckState(Qt.Checked)
        item1.setTextAlignment(Qt.AlignCenter)
        item2.setTextAlignment(Qt.AlignCenter)
        item3.setTextAlignment(Qt.AlignCenter)
        self.curveModel.appendRow([item1, item2, item3])
        self.changeCurrentCurve(name)
        self.sigModified.emit(True)
        self.sigNewCurveAdded.emit()

    def renameCurve(self, newname=None, name=None):
        if name not in self.curveObjs:
            name = self.currentCurve
        if not newname:
            newname, okPressed = QInputDialog.getText(
                self, self.tr("change curve name"),
                self.tr("Curve to be renamed:{}".format(name)),
                QLineEdit.Normal, name)
        if okPressed and newname != '':
            if newname != name:
                self.curveObjs[newname] = self.curveObjs.pop(name)
                self.pointObjs[newname] = self.pointObjs.pop(name)
                for i in range(self.curveModel.rowCount()):
                    item = self.curveModel.item(i, 1)
                    if item.text() == name:
                        item.setText(newname)
                        self.sigModified.emit(True)
                self.changeCurrentCurve(newname)

    def delCurve(self, name=None):
        if name is None:
            name = self.currentCurve
        if name not in self.curveObjs:
            return
        try:
            self.curveObjs.pop(name)
            self.pointObjs.pop(name)

            for i in range(self.curveModel.rowCount()):
                item = self.curveModel.item(i, 1)
                if item.text() == name:
                    self.curveModel.removeRows(i, 1)
                    self.sigModified.emit(True)
            if len(self.curveObjs) > 0:
                self.changeCurrentCurve(list(self.curveObjs.keys())[0])
            else:
                self.currentCurve = None
        except:
            pass

    def showCurve(self, curvename, visible=True):
        for pts in self.pointObjs[curvename]:
            pts.setVisible(visible)
        for line in self.curveObjs[curvename]:
            line.setVisible(visible)

    def updateCurve(self, name, color=Qt.black):
        # if name in self.curveObjs:
        #     curveitem = self.curveObjs[name]
        # else:
        #     curveitem = QGraphicsPathItem()
        #     self.scene.addItem(curveitem)
        # # path=curveitem.path()
        # path = QPainterPath()
        #
        # pointItems = self.curvePointObjs[name]
        # if len(pointItems) > 0:
        #     path.moveTo(pointItems[0].pos())
        # for pointitem in pointItems[1:]:
        #     path.lineTo(pointitem.pos())
        # curveitem.setPath(path)
        # curveitem.update(curveitem.boundingRect())
        # curveitem.prepareGeometryChange()
        # self.scene.update()
        # self.viewport().repaint()
        # self.viewport().update()

        if not isinstance(name, str):
            return
        if name not in self.pointObjs:
            return

        lastitems = []
        if name in self.curveObjs:
            lastitems = self.curveObjs[name]
            if not isinstance(lastitems, list):
                lastitems = []

        if name in self.pointObjs:
            pointItems = self.pointObjs[name]
        else:
            pointItems = []
        points = []
        for ptitem in pointItems:
            points.append(ptitem.pos())

        self.curveObjs[name] = []
        if len(points) > 1:
            for i in range(1, len(points)):
                l = QGraphicsLineItem(points[i - 1].x(), points[i - 1].y(),
                                      points[i].x(), points[i].y())
                l.setPen(color)
                l.setZValue(10)
                # l.setFlag(QGraphicsItem.ItemIsSelectable)
                self.curveObjs[name].append(l)
                self.scene.addItem(l)

        for line in lastitems:
            self.scene.removeItem(line)

        self.updateCurvePoints(name)

    def showAxes(self, visible=True):
        if visible:
            for line in self.axesxObjs:
                line.setVisible(True)
            for line in self.axesyObjs:
                line.setVisible(True)
        else:
            for line in self.axesxObjs:
                line.setVisible(False)
            for line in self.axesyObjs:
                line.setVisible(False)

    def showGrid(self, visible=True):
        if visible:
            for line in self.gridObjs:
                line.setVisible(True)
        else:
            for line in self.gridObjs:
                line.setVisible(False)

    def calGridCoord(self, mode="all"):
        """calc the coord and pixel position of gridx list and gridy list"""

        if mode in ("x", "all") and len(self.axesxObjs) >= 2:
            axesxcoord = list(self.axesxObjs.values())
            xmin = min(axesxcoord) if self.proj.gridx[0] is None else min(
                self.proj.gridx[0], min(axesxcoord))
            xmax = max(axesxcoord) if self.proj.gridx[1] is None else max(
                self.proj.gridx[1], max(axesxcoord))
            if self.proj.gridx[2] is None:
                if len(self.axesxObjs) == 2:
                    xstep = (xmax - xmin) / 5
                else:
                    axesStep = round(abs(axesxcoord[1] - axesxcoord[0]), 5)
                    for i in range(2, len(axesxcoord)):
                        st = round(abs(axesxcoord[i] - axesxcoord[i - 1]), 5)
                        if axesStep > st:
                            axesStep = st
                    xstep = axesStep
            else:
                xstep = self.proj.gridx[2]
            n = int(round((xmax - xmin) / xstep, 0)) + 1
            gridxcoord = list(np.linspace(xmin, xmax, n))
        else:
            gridxcoord = []

        if mode in ("y", "all") and len(self.axesyObjs) >= 2:
            axesycoord = list(self.axesyObjs.values())
            ymin = min(axesycoord) if self.proj.gridy[0] is None else min(
                self.proj.gridy[0], min(axesycoord))
            ymax = max(axesycoord) if self.proj.gridy[1] is None else max(
                self.proj.gridy[1], max(axesycoord))
            if self.proj.gridy[2] is None:
                if len(self.axesyObjs) == 2:
                    ystep = (ymax - ymin) / 5
                else:
                    axesStep = round(abs(axesycoord[1] - axesycoord[0]), 5)
                    for i in range(2, len(axesycoord)):
                        st = round(axesycoord[i] - axesycoord[i - 1], 5)
                        if axesStep > st:
                            axesStep = st
                    ystep = axesStep
            else:
                ystep = self.proj.gridy[2]

            n = int(round((ymax - ymin) / ystep, 0)) + 1
            gridycoord = list(np.linspace(ymin, ymax, n))
            # gridycoord = list(np.arange(ymin, ymax, ystep)) + [ymax]
        else:
            gridycoord = []

        xpos, ypos = self.coordToPoint(gridxcoord, gridycoord)
        if mode in ["x", "all"]:
            self.gridxpos = xpos
        if mode in ["y", "all"]:
            self.gridypos = ypos
        return

    def updateGrid(self):
        for line in self.gridObjs:
            self.scene.removeItem(line)

        if self.gridxpos and self.gridypos:
            clr = QColor(self.proj.gridColor)
            clr.setAlphaF(self.proj.gridOpacity)
            for x in self.gridxpos:
                line = QGraphicsLineItem(x, self.gridypos[0], x,
                                         self.gridypos[-1])
                line.setZValue(5)
                line.setPen(
                    QPen(clr, self.proj.gridLineWidth, self.proj.gridLineType))
                self.gridObjs.append(line)
                self.scene.addItem(line)
            for y in self.gridypos:
                line = QGraphicsLineItem(self.gridxpos[0], y,
                                         self.gridxpos[-1], y)
                line.setZValue(5)
                line.setPen(
                    QPen(clr, self.proj.gridLineWidth, self.proj.gridLineType))
                self.gridObjs.append(line)
                self.scene.addItem(line)

    def updateCurvePoints(self, name):
        extra = len(self.pointObjs[name]) - self.pointsModel.rowCount()
        if extra > 0:
            for i in range(extra):
                item1 = QStandardItem()
                item2 = QStandardItem()
                item3 = QStandardItem()
                item2.setEditable(False)
                item3.setEditable(False)
                self.pointsModel.appendRow([item1, item2, item3])
        elif extra < 0:
            j = self.pointsModel.rowCount()
            i = j + extra
            self.pointsModel.removeRows(i, -extra)

        for i in range(self.pointsModel.rowCount()):
            pt = self.pointObjs[name][i]
            self.pointsModel.item(i, 0).setText(str(i + 1))
            xlist, ylist = self.pointToCoord([pt.x()], [pt.y()])
            self.pointsModel.item(i, 1).setText(str(round(xlist[0], 6)))
            self.pointsModel.item(i, 2).setText(str(round(ylist[0], 6)))

    def calcCurveCoords(self):
        """calculate datas for export"""
        data = {}
        for curve in self.pointObjs:
            data[curve] = ([], [])
            for item in self.pointObjs[curve]:
                data[curve][0].append(item.x())
                data[curve][1].append(item.y())
            data[curve] = self.pointToCoord(data[curve][0], data[curve][1])
        return data

    def axisvalid(self):
        """if there are axes with same coord value,
        or if there are axes at the save position,
        return False"""
        a = len(self.axesxObjs)
        b = len(set(self.axesxObjs.values()))
        if a != b:
            return False
        a = len(self.axesyObjs)
        b = len(set(self.axesyObjs.values()))
        if a != b:
            return False
        xs = []
        for item in self.axesxObjs:
            xs.append(item.pos().x())
        ys = []
        for item in self.axesyObjs:
            ys.append(item.pos().y())
        a = len(xs)
        b = len(set(xs))
        if a != b:
            return False
        a = len(ys)
        b = len(set(ys))
        if a != b:
            return False
        return True

    def exportToCSVtext(self):
        """return text in csv format, like following:
        curve1
        x,1,2,3
        y,2,3,4
        """
        text = ""
        data = self.calcCurveCoords()
        for curve in data:
            text += curve
            text += "\nx,"
            for x in data[curve][0]:
                text += str(x) + ','
            text += "\ny,"
            for y in data[curve][1]:
                text += str(y) + ','
            text += "\n"
        return text

    def changeCurrentCurve(self, name=None):
        self._lastCurve = self.currentCurve
        if name is None:
            name = self.currentCurve
            if name is None:
                return
        for i in range(self.curveModel.rowCount()):
            if self.curveModel.item(i, 1).text() == name:
                self.curveModel.item(i, 0).switch(True)
            else:
                self.curveModel.item(i, 0).switch(False)

        self.currentCurve = name
        self.updateCurve(self._lastCurve)
        self.updateCurve(self.currentCurve, Qt.red)
        self.updateCurvePoints(name)

    def changeCurveVisible(self, item):
        if item.index().column() == 2:
            visible = item.checkState()
            curvename = self.curveModel.item(item.index().row(), 1).text()
            self.showCurve(curvename, visible)

    def changePointOrder(self, item):
        row = item.row()
        if item.column() != 0:
            return
        newindex = item.text()
        if not newindex.isdigit():
            return
        newindex = int(newindex)
        if newindex == row + 1:
            return
        if newindex > self.pointsModel.rowCount():
            newindex = self.pointsModel.rowCount()
        newindex -= 1

        self.pointObjs[self.currentCurve].insert(
            newindex, self.pointObjs[self.currentCurve].pop(row))
        self.updateCurve(self.currentCurve)
        self.updateCurvePoints(self.currentCurve)

    # def curvetabChanged(self, item):
    #     i = item.row()
    #     j = item.column()
    #     if j == 0:
    #         if item.checkState() is Qt.Checked:
    #             self.curveModel.item(i,0).setCheckState(Qt.Checked)
    #             return
    #         else:
    #             for k in range(self.curveModel.rowCount()):
    #                 if k == i:
    #                     #self.curveModel.item(k,0).setCheckState(Qt.Checked)
    #                     newcurrent = self.curveModel.item(k,1).text()
    #                     print(self.curveModel.item(k,0).checkState())
    #                 else:
    #                     self.curveModel.item(k,0).setCheckState(Qt.Unchecked)
    #     if newcurrent and newcurrent != self.currentCurve:
    #         self.changeCurrentCurve(newcurrent)

    def pointToCoord(self, xlist, ylist):
        if len(self.axesxObjs) >= 2:
            gridxs = []
            for item in self.axesxObjs:
                gridxs.append(item.pos().x())
            coordx = list(self.axesxObjs.values())
            xCoords = interp(gridxs, coordx, xlist)
        else:
            xCoords = xlist

        if len(self.axesyObjs) >= 2:
            gridys = []
            for item in self.axesyObjs:
                gridys.append(item.pos().y())
            coordy = list(self.axesyObjs.values())
            yCoords = interp(gridys, coordy, ylist)
        else:
            yCoords = ylist

        return (xCoords, yCoords)

    def coordToPoint(self, xlist, ylist):
        if len(self.axesxObjs) >= 2:
            gridxpos = []
            for item in self.axesxObjs:
                gridxpos.append(item.pos().x())
            coordx = list(self.axesxObjs.values())
            xposs = interp(coordx, gridxpos, xlist)
        else:
            xposs = xlist

        if len(self.axesyObjs) >= 2:
            gridypos = []
            for item in self.axesyObjs:
                gridypos.append(item.pos().y())
            coordy = list(self.axesyObjs.values())
            yposs = interp(coordy, gridypos, ylist)
        else:
            yposs = ylist

        return (xposs, yposs)
Пример #10
0
class QmyMainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.__buildStatusBar()
        self.__iniGraphicsSystem()

        self.__ItemId = 1
        self.__ItemDesc = 2
        self.__seqNum = 0
        self.__backZ = 0
        self.__frontZ = 0

    def __buildStatusBar(self):
        self.__labViewCord = QLabel("View 坐标:")
        self.__labViewCord.setMinimumWidth(150)
        self.ui.qStatusBar.addWidget(self.__labViewCord)

        self.__labSceneCord = QLabel("Scene 坐标:")
        self.__labSceneCord.setMinimumWidth(150)
        self.ui.qStatusBar.addWidget(self.__labSceneCord)

        self.__labItemCord = QLabel("Item 坐标:")
        self.__labItemCord.setMinimumWidth(150)
        self.ui.qStatusBar.addWidget(self.__labItemCord)

        self.__labItemInfo = QLabel("ItemInfo: ")
        self.ui.qStatusBar.addWidget(self.__labItemInfo)

    def __iniGraphicsSystem(self):
        self.view = QmyGraphicsView(self)
        self.setCentralWidget(self.view)

        self.scene = QGraphicsScene(-300, -200, 600, 200)
        self.view.setScene(self.scene)
        self.view.setCursor(Qt.CrossCursor)
        self.view.setMouseTracking(True)
        self.view.setDragMode(QGraphicsView.RubberBandDrag)

        self.view.mouseMove.connect(self.do_mouseMove)
        self.view.mouseClicked.connect(self.do_mouseClicked)
        self.view.mouseDoubleClick.connect(self.do_mouseDoubleClick)
        self.view.keyPress.connect(self.do_keyPress)

    def __setItemProperties(self, item, desc):
        item.setFlag(QGraphicsItem.ItemIsFocusable)
        item.setFlag(QGraphicsItem.ItemIsMovable)
        item.setFlag(QGraphicsItem.ItemIsSelectable)

        self.__frontZ += 1
        item.setZValue(self.__frontZ)
        item.setPos(-150 + random.randint(1, 200),
                    -200 + random.randint(1, 200))

        self.__seqNum += 1
        item.setData(self.__ItemId, self.__seqNum)
        item.setData(self.__ItemDesc, desc)

        self.scene.addItem(item)
        self.scene.clearSelection()
        item.setSelected(True)

    def __setBrushColor(self, item):
        color = item.brush().color()
        color = QColorDialog.getColor(color, self, "选择填充颜色")
        if color.isValid():
            item.setBrush(QBrush(color))

    @pyqtSlot()
    def on_qAction12_triggered(self):
        item = QGraphicsRectItem(-50, -25, 100, 50)
        item.setBrush(QBrush(Qt.yellow))
        self.__setItemProperties(item, "矩形")

    @pyqtSlot()
    def on_qAction13_triggered(self):
        item = QGraphicsEllipseItem(-50, -30, 100, 60)
        item.setBrush(QBrush(Qt.blue))
        self.__setItemProperties(item, "椭圆")

    @pyqtSlot()
    def on_qAction14_triggered(self):
        item = QGraphicsEllipseItem(-50, -50, 100, 100)
        item.setBrush(QBrush(Qt.cyan))
        self.__setItemProperties(item, "圆形")

    @pyqtSlot()
    def on_qAction15_triggered(self):
        item = QGraphicsPolygonItem()
        points = [QPointF(0, -40), QPointF(60, 40), QPointF(-60, 40)]
        item.setPolygon(QPolygonF(points))
        item.setBrush(QBrush(Qt.magenta))
        self.__setItemProperties(item, "三角形")

    @pyqtSlot()
    def on_qAction16_triggered(self):
        item = QGraphicsPolygonItem()
        points = [
            QPointF(-40, -40),
            QPointF(40, -40),
            QPointF(100, 40),
            QPointF(-100, 40)
        ]
        item.setPolygon(QPolygonF(points))
        item.setBrush(QBrush(Qt.green))
        self.__setItemProperties(item, "梯形")

    @pyqtSlot()
    def on_qAction17_triggered(self):
        item = QGraphicsLineItem(-100, 0, 100, 0)
        pen = QPen(Qt.red)
        pen.setWidth(4)
        item.setPen(pen)
        self.__setItemProperties(item, "直线")

    @pyqtSlot()
    def on_qAction18_triggered(self):
        strText, OK = QInputDialog.getText(self, "输入", "请输入文字")
        if (not OK):
            return
        item = QGraphicsTextItem(strText)
        font = self.font()
        font.setPointSize(20)
        font.setBold(True)
        item.setFont(font)
        item.setDefaultTextColor(Qt.black)
        self.__setItemProperties(item, "文字")

    @pyqtSlot()
    def on_qAction1_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt == 1:
            item = items[0]
            item.setScale(0.1 + item.scale())
        else:
            self.view.scale(1.1, 1.1)

    @pyqtSlot()
    def on_qAction2_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt == 1:
            item = items[0]
            item.setScale(item.scale() - 0.1)
        else:
            self.view.scale(0.9, 0.9)

    @pyqtSlot()
    def on_qAction3_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt == 1:
            item = items[0]
            item.setScale(1)
            item.setRotation(0)
        else:
            self.view.resetTransform()

    @pyqtSlot()
    def on_qAction4_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt == 1:
            item = items[0]
            item.setRotation(-30 + item.rotation())
        else:
            self.view.rotate(-30)

    @pyqtSlot()
    def on_qAction5_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt == 1:
            item = items[0]
            item.setRotation(30 + item.rotation())
        else:
            self.view.rotate(30)

    @pyqtSlot()
    def on_qAction6_triggered(self):  # 前置
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt > 0:
            item = items[0]
            self.__frontZ += 1
            item.setZValue(self.__frontZ)

    @pyqtSlot()
    def on_qAction7_triggered(self):  # 后置
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt > 0:
            item = items[0]
            self.__backZ -= 1
            item.setZValue(self.__backZ)

    @pyqtSlot()
    def on_qAction8_triggered(self):  # 组合
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt <= 1:
            return
        group = QGraphicsItemGroup()
        self.scene.addItem(group)
        for i in range(cnt):
            item = items[i]
            item.setSelected(False)
            item.clearFocus()
            group.addToGroup(item)

        group.setFlag(QGraphicsItem.ItemIsFocusable)
        group.setFlag(QGraphicsItem.ItemIsMovable)
        group.setFlag(QGraphicsItem.ItemIsSelectable)

        self.__frontZ += 1
        group.setZValue(self.__frontZ)
        self.scene.clearSelection()
        group.setSelected(True)

    @pyqtSlot()
    def on_qAction9_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        if (cnt == 1):
            group = items[0]
            self.scene.destroyItemGroup(group)

    @pyqtSlot()
    def on_qAction10_triggered(self):
        items = self.scene.selectedItems()
        cnt = len(items)
        for i in range(cnt):
            item = items[i]
            self.scene.removeItem(item)

    def do_mouseMove(self, point):
        self.__labViewCord.setText("View 坐标:%d, %d" % (point.x(), point.y()))
        pt = self.view.mapToScene(point)
        self.__labSceneCord.setText("Scene 坐标:%.0f, %.0f" % (pt.x(), pt.y()))

    def do_mouseClicked(self, point):
        pt = self.view.mapToScene(point)
        item = self.scene.itemAt(pt, self.view.transform())
        if (item == None):
            return
        pm = item.mapFromScene(pt)
        self.__labItemCord.setText("item 坐标:%.0f, %.0f" % (pm.x(), pm.y()))
        self.__labItemInfo.setText(
            str(item.data(self.__ItemDesc)) + ", ItemId=" +
            str(item.data(self.__ItemId)))

    def do_mouseDoubleClick(self, point):
        pt = self.view.mapToScene(point)
        item = self.scene.itemAt(pt, self.view.transform())
        if (item == None):
            return
        className = str(type(item))
        if (className.find("QGraphicsRectItem") >= 0):
            self.__setBrushColor(item)
        elif (className.find("QGraphicsEllipseItem") >= 0):
            self.__setBrushColor(item)
        elif (className.find("QGraphicsEllipseItem") >= 0):
            self.__setBrushColor(item)
        elif (className.find("QGraphicsLineItem") >= 0):
            pen = item.pen()
            color = item.pen().color()
            color = QColorDialog.getColor(color, self, "选择线条颜色")
            if color.isValid():
                pen.setColor(color)
                item.setPen(pen)
        elif (className.find("QGraphicsTextItem") >= 0):
            font = item.font()
            font, OK = QFontDialog.getFont(font)
            if OK:
                item.setfont(font)

    def do_keyPress(self, event):
        items = self.scene.selectedItems()
        cnt = len(items)
        if (cnt != 1):
            return
        item = items[0]
        key = event.key()
        if (key == Qt.Key_Delete):
            self.scene.removeItem(item)
        elif (key == Qt.Key_Space):
            item.setRotation(90 + item.rotation())
        elif (key == Qt.Key_PageUp):
            item.setScale(0.1 + item.scale())
        elif (key == Qt.Key_PageDown):
            item.setScale(-0.1 + item.scale())
        elif (key == Qt.Key_Left):
            item.setX(-1 + item.x())
        elif (key == Qt.Key_Right):
            item.setX(1 + item.x())
        elif (key == Qt.Key_Up):
            item.setY(-1 + item.y())
        elif (key == Qt.Key_Down):
            item.setY(1 + item.y())
Пример #11
0
class MainForm(QDialog):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.filename = ""
        self.copiedItem = QByteArray()
        self.pasteOffset = 5
        self.prevPoint = QPoint()
        self.addOffset = 5
        self.borders = []

        self.printer = QPrinter(QPrinter.HighResolution)
        self.printer.setPageSize(QPrinter.Letter)

        self.view = GraphicsView(self)

        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, PageSize[0], PageSize[1])
        #   self.addBorders()
        self.view.setScene(self.scene)

        self.wrapped = []  # Needed to keep wrappers alive
        buttonLayout = QVBoxLayout()
        for text, slot in (
            ("Add &Location", self.addLocation),
            ("Add &Edge", self.addEdge),
            ("Add &Variable", self.addVariable),
                # ("List &TextName", self.listTextName),
            ("&Open...", self.open),
            ("&Save", self.save),
            ("&RePaint", self.RePaintLine),
            ("&Quit", self.accept),
                #("&SameX", self.SameX),
            ("&New Black HA", self.newHA),
            ("QLineEdit", "Current HA Name"),
            ("QComboBox", "HA Name List"),
            ("QLineEdit", "Current Model Name"),
            ("S&witch HA", self.switchHA),
            ("&Delete HA", self.deleteHA),
            ("&Copy And New HA", self.copyHA)):
            if text in ['QLineEdit', 'QComboBox']:
                lbl = QLabel(slot)
                buttonLayout.addWidget(lbl)
                if slot == 'Current HA Name':
                    self.txtHAName = QLineEdit()
                    self.txtHAName.setText("NoName")
                    buttonLayout.addWidget(self.txtHAName)
                    #self.txtHAName.textChanged.connect(self.txtChanged)
                if slot == 'Current Model Name':
                    self.txtModelName = QLineEdit()
                    self.txtModelName.setText("NoName")
                    buttonLayout.addWidget(self.txtModelName)
                    self.txtModelName.hide()
                    #self.txtModelName.textChanged.connect(self.txtChanged)
                    lbl.hide()
                if slot == 'HA Name List':
                    self.cmbHANameList = QComboBox()
                    buttonLayout.addWidget(self.cmbHANameList)

            else:
                button = QPushButton(text)
                if not MAC:
                    button.setFocusPolicy(Qt.NoFocus)
                if slot is not None:
                    button.clicked.connect(slot)
                #if shortcutKey:
                #    shortcut = QShortcut(QKeySequence(shortcutKey), self)
                #   shortcut.activated.connect(slot)
                if text == "&Align":
                    menu = QMenu(self)
                    for text, arg in (("Align &Left", Qt.AlignLeft),
                                      ("Align &Right", Qt.AlignRight),
                                      ("Align &Top", Qt.AlignTop),
                                      ("Align &Bottom", Qt.AlignBottom)):
                        wrapper = functools.partial(self.setAlignment, arg)
                        self.wrapped.append(wrapper)
                        menu.addAction(text, wrapper)
                    button.setMenu(menu)
                if text == "Pri&nt...":
                    buttonLayout.addStretch(5)
                if text == "&Quit":
                    buttonLayout.addStretch(1)
                buttonLayout.addWidget(button)
        buttonLayout.addStretch()

        layout = QHBoxLayout()
        layout.addWidget(
            self.view,
            1,
        )
        layout.addLayout(buttonLayout)

        layoutTable = QVBoxLayout()  #BoxLayout()

        self.EdgeWidget = QTableWidget()
        layoutTable.addWidget(self.EdgeWidget)
        # setup table widget
        self.EdgeWidget.itemDoubleClicked.connect(self.EdgeWidgetDoubleClicked)
        self.EdgeWidget.setColumnCount(3)
        self.EdgeWidget.setHorizontalHeaderLabels(
            ['EdgeName', 'Guard', 'Reset'])
        self.EdgeWidget.setColumnWidth(0, 40)
        self.EdgeWidget.setColumnWidth(1, 200)
        self.EdgeWidget.setColumnWidth(2, 200)

        self.EdgeWidget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.EdgeWidget.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.EdgeWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)

        #self.EdgeWidget.resizeColumnsToContents()
        self.VariablesWidget = QTableWidget()
        layoutTable.addWidget(self.VariablesWidget)
        # setup table widget
        self.VariablesWidget.itemDoubleClicked.connect(
            self.VariablesWidgetDoubleClicked)
        self.VariablesWidget.setColumnCount(5)
        self.VariablesWidget.setHorizontalHeaderLabels(
            ['Name', 'Initial Value', 'Input', 'Output', "IsConstant"])

        #self.VariablesWidget.hideColumn(0)
        self.VariablesWidget.setColumnWidth(0, 100)
        self.VariablesWidget.setColumnWidth(1, 200)
        self.VariablesWidget.setColumnWidth(2, 100)
        self.VariablesWidget.setColumnWidth(3, 100)
        self.VariablesWidget.setColumnWidth(4, 100)
        self.VariablesWidget.setSelectionMode(
            QAbstractItemView.SingleSelection)
        #self.VariablesWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.VariablesWidget.setSelectionBehavior(
            QAbstractItemView.SelectItems)
        self.VariablesWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        #self.VariablesWidget.resizeColumnsToContents()
        layoutMain = QVBoxLayout()
        layoutMain.addLayout(layout)
        layoutMain.addLayout(layoutTable)
        layoutMain.setStretchFactor(layout, 8)
        layoutMain.setStretchFactor(layoutTable, 2)
        self.setLayout(layoutMain)

        fm = QFontMetrics(self.font())
        self.resize(self.scene.width() + fm.width(" Delete... ") + 50,
                    self.scene.height() + 50)
        self.setWindowTitle("Simulation of HA Designer")
        self.setWindowFlags(Qt.Window | Qt.WindowMinimizeButtonHint
                            | Qt.WindowMaximizeButtonHint
                            | Qt.WindowCloseButtonHint)
        self.dicText = {}
        self.dicLine = {}
        self.dicVariable = {}
        self.dicHA = {}
        self.dicModel = {}
        #self.dicModel["HAs"]={}
        self.currentProject = {}
        #self.currentProject["Models"]={}

        #self.currentProject["Models"]["NoName"]=self.dicModel
        self.currentHA = None

    def txtChanged(self):
        self.setDirty()

    def setDirty(self, newDirty=None):
        if newDirty is None:
            newDirty = True
        global Dirty
        Dirty = newDirty

    #create a blank HA
    def newHA(self):
        if self.txtHAName.text() == "NoName":
            if (Dirty):
                QMessageBox.question(
                    self, "Please Input HA Name",
                    "Fail to New HA,Please Change the HA Name from 'NoName' to a new name you want!",
                    QMessageBox.Ok)
                return
        self.offerSave()
        if (Dirty):
            QMessageBox.question(
                self, "Please Save or Discard Current Editing",
                "Fail to new HA,Please Save or Discard current editing first!",
                QMessageBox.Ok)
            return
        self.clearCurrent()
        self.txtHAName.setText("NoName")
        self.currentHA = None

    # create a new HA who has locations, edges and variables as same as the selected HA
    def copyHA(self):
        global Dirty
        if self.txtHAName.text() == "NoName":
            if (Dirty):
                QMessageBox.question(
                    self, "Please Input HA Name",
                    "Fail to copy HA,Please Change the HA Name from 'NoName' to a new name you want!",
                    QMessageBox.Ok)
                return
        self.offerSave()
        if (Dirty):
            QMessageBox.question(
                self, "Please Save or Discard Current Editing",
                "Fail to copy HA,Please Save or Discard current editing first!",
                QMessageBox.Ok)
            return
        '''if (self.cmbHANameList.currentText()==""):
            QMessageBox.question(self,
                            "Please Select HA Name",
                            "Fail to copy HA,Please select a HA Name in HA Name List!",
                            QMessageBox.Ok )  
            return
        '''
        self.currentHA = self.currentProject["Models"][
            self.txtModelName.text()]["HAs"][self.txtHAName.text()]
        self.clearCurrent()
        self.DrawHA(self.currentHA)
        self.txtHAName.setText("NoName")
        self.currentHA = None
        self.setDirty()

    # change to current designed HA by select another HA name in “HA Name List”
    def switchHA(self):
        if self.txtHAName.text() == "NoName":
            if (Dirty):
                QMessageBox.question(
                    self, "Please Input HA Name",
                    "Fail to switch HA,Please Change the HA Name from 'NoName' to a new name you want!",
                    QMessageBox.Ok)
                return
        NewHAName = self.cmbHANameList.currentText()
        self.offerSave()
        if (Dirty):
            QMessageBox.question(
                self, "Please Save or Discard Current Editing",
                "Fail to switch HA,Please Save or Discard current editing first!",
                QMessageBox.Ok)
            return
        if (self.cmbHANameList.currentText() == ""):
            QMessageBox.question(
                self, "Please Select HA Name",
                "Fail to switch HA,Please select a HA Name in HA Name List!",
                QMessageBox.Ok)
            return
        self.clearCurrent()
        self.cmbHANameList.setEditText(NewHAName)
        self.txtHAName.setText(self.cmbHANameList.currentText())
        self.DrawHA()
        #delete an HA whose name is selected in “Ha Name List”.
    def deleteHA(self):
        strHAName = self.txtHAName.text()
        if (strHAName in self.currentProject["Models"][
                self.txtModelName.text()]["HAs"].keys()):
            self.currentProject["Models"][self.txtModelName.text()]["HAs"].pop(
                strHAName)
        self.clearCurrent()
        if not self.filename:
            pass
        else:
            with open(self.filename, 'w') as fh:
                json.dump(self.currentProject, fh)
        self.setDirty(False)
        self.DrawDefaultHA()
        #edit selected edge
    def EdgeWidgetDoubleClicked(self, item):
        selectItemText = self.EdgeWidget.item(item.row(), 0).text()
        if selectItemText in self.dicLine:
            dialog = EdgeItemDlg(self.dicLine[selectItemText], None,
                                 self.scene, self)
            dialog.exec_()

    #edit selected Variable
    def VariablesWidgetDoubleClicked(self, item):
        selectItemText = self.VariablesWidget.item(item.row(), 0).text()
        if selectItemText in self.dicVariable:
            dialog = VariableItemDlg(self.dicVariable[selectItemText], self)
            dialog.exec_()

    #delete location
    def deleteText(self, LocationItem):
        if LocationItem.boxName in self.dicText:
            self.dicText.pop(LocationItem.boxName)
        self.scene.removeItem(LocationItem)
        self.scene.update()

    #delete edge
    def deleteLine(self, lineItem):
        self.dicLine.pop(lineItem.boxName)
        self.scene.removeItem(lineItem)
        self.scene.update()
        rowCount = self.EdgeWidget.rowCount()
        for row_index in range(rowCount):
            if self.EdgeWidget.item(row_index, 0).text() == lineItem.boxName:
                self.EdgeWidget.removeRow(row_index)
                return

    #rename edge
    def renameLine(self, OldName, NewName):
        rowCount = self.EdgeWidget.rowCount()
        for row_index in range(rowCount):
            if self.EdgeWidget.item(row_index, 0).text() == OldName:
                self.EdgeWidget.setItem(row_index, 0,
                                        QTableWidgetItem(NewName, 0))
                return

    #delete variable
    def deleteVariable(self, VariableItem):
        self.dicVariable.pop(VariableItem.boxName)
        rowCount = self.VariablesWidget.rowCount()
        for row_index in range(rowCount):
            if self.VariablesWidget.item(row_index,
                                         0).text() == VariableItem.boxName:
                self.VariablesWidget.removeRow(row_index)
                return

    #rename variable
    def renameVariable(self, OldName, NewName):
        rowCount = self.VariablesWidget.rowCount()
        for row_index in range(rowCount):
            if self.VariablesWidget.item(row_index, 0).text() == OldName:
                self.VariablesWidget.setItem(row_index, 0,
                                             QTableWidgetItem(NewName, 0))
                return

    # add a variable
    def addVariableInTable(self, variableItem):
        row_index = self.VariablesWidget.rowCount()
        self.VariablesWidget.insertRow(row_index)
        row_index = row_index
        self.VariablesWidget.setItem(row_index, 0,
                                     QTableWidgetItem(variableItem.boxName, 0))
        self.VariablesWidget.setItem(
            row_index, 1, QTableWidgetItem(variableItem.initialValue, 0))
        self.VariablesWidget.setItem(
            row_index, 2, QTableWidgetItem(str(variableItem.isInput), 0))
        self.VariablesWidget.setItem(
            row_index, 3, QTableWidgetItem(str(variableItem.isOutput), 0))
        self.VariablesWidget.setItem(
            row_index, 4, QTableWidgetItem(str(variableItem.isConstant), 0))
        self.VariablesWidget.resizeRowToContents(row_index)
        self.VariablesWidget.resizeRowsToContents()
        self.VariablesWidget.resizeColumnsToContents()

    #update variable
    def setVariableInTable(self, variableItem):
        rowCount = self.VariablesWidget.rowCount()
        for row_index in range(rowCount):
            if self.VariablesWidget.item(row_index,
                                         0).text() == variableItem.boxName:

                self.VariablesWidget.setItem(
                    row_index, 1, QTableWidgetItem(variableItem.initialValue,
                                                   0))
                self.VariablesWidget.setItem(
                    row_index, 2, QTableWidgetItem(str(variableItem.isInput),
                                                   0))
                self.VariablesWidget.setItem(
                    row_index, 3,
                    QTableWidgetItem(str(variableItem.isOutput), 0))
                self.VariablesWidget.setItem(
                    row_index, 4,
                    QTableWidgetItem(str(variableItem.isConstant), 0))
                self.VariablesWidget.resizeRowToContents(row_index)
                self.VariablesWidget.resizeColumnsToContents()
                return

    #add an Edge
    def addEdgeInTable(self, edgeItem):
        row_index = self.EdgeWidget.rowCount()
        self.EdgeWidget.insertRow(row_index)
        row_index = row_index
        self.EdgeWidget.setItem(row_index, 0,
                                QTableWidgetItem(edgeItem.boxName, 0))
        self.EdgeWidget.setItem(row_index, 1,
                                QTableWidgetItem(edgeItem.guard, 0))
        self.EdgeWidget.setItem(row_index, 2,
                                QTableWidgetItem(edgeItem.reset, 0))
        self.EdgeWidget.resizeRowToContents(row_index)
        self.EdgeWidget.resizeRowsToContents()
        self.EdgeWidget.resizeColumnsToContents()

    #update an Edge
    def setEdgeInTable(self, edgeItem):
        rowCount = self.EdgeWidget.rowCount()
        for row_index in range(rowCount):
            if self.EdgeWidget.item(row_index, 0).text() == edgeItem.boxName:
                self.EdgeWidget.setItem(row_index, 1,
                                        QTableWidgetItem(edgeItem.guard, 0))
                self.EdgeWidget.setItem(row_index, 2,
                                        QTableWidgetItem(edgeItem.reset, 0))
                self.EdgeWidget.resizeRowToContents(row_index)
                self.EdgeWidget.resizeColumnsToContents()
                return

    #add a new location
    def addLocation(self):
        dialog = LocationItemDlg(position=self.position(),
                                 scene=self.scene,
                                 parent=self)
        dialog.exec_()

    def listTextName(self):
        buttonReply = QMessageBox.question(self, 'PyQt5 message',
                                           str(self.dicText),
                                           QMessageBox.Yes | QMessageBox.No,
                                           QMessageBox.No)
        buttonReply = QMessageBox.question(self, 'PyQt5 message',
                                           str(self.dicLine.keys()),
                                           QMessageBox.Yes | QMessageBox.No,
                                           QMessageBox.No)

    #add a new Variable
    def addVariable(self):
        dialog = VariableItemDlg(parent=self)
        dialog.exec_()

    def addPicture(self):
        fig, ax = plt.subplots(figsize=(8, 5))
        X, Y = fig.get_dpi() * fig.get_size_inches()
        h = Y
        i = 2
        if i == 2:
            name = 'aa'
            formula = r'$x=\frac{3}{100}$'
            ax.text(0.5,
                    2.5,
                    name + formula,
                    fontsize=(h),
                    horizontalalignment='left',
                    verticalalignment='center')

        ax.set_xlim(1, X)
        ax.set_ylim(1, Y)
        ax.set_axis_off()

        #fig.subplots_adjust(left=0, right=1,                    top=1, bottom=0,                    hspace=0, wspace=0)
        plt.show()

    #add a new Edge
    def addEdge(self):
        dialog = EdgeItemDlg(position=self.position(),
                             scene=self.scene,
                             parent=self)
        dialog.exec_()

    #to refresh the design file
    def RePaintLine(self):
        for line in self.dicLine.values():
            line.resetLine()
        for item in self.dicText.values():
            item.rePaint()
            item.update()

    # self.scene.update()
    def position(self):
        point = self.mapFromGlobal(QCursor.pos())
        if not self.view.geometry().contains(point):
            coord = random.randint(36, 144)
            point = QPoint(coord, coord)
        else:
            if point == self.prevPoint:
                point += QPoint(self.addOffset, self.addOffset)
                self.addOffset += 5
            else:
                self.addOffset = 5
                self.prevPoint = point
        return self.view.mapToScene(point)

    #clear the screen and ready to draw a new HA
    def clearCurrent(self):

        self.EdgeWidget.clearContents()
        self.EdgeWidget.setRowCount(0)
        self.VariablesWidget.clearContents()
        self.VariablesWidget.setRowCount(0)

        items = self.scene.items()
        while items:
            item = items.pop()
            self.scene.removeItem(item)
            del item
            #self.addBorders()         dictItemJson={}
        self.dicItem = {}
        self.dicLine = {}
        self.dicText = {}
        self.dicVariable = {}

    #show a HA on screen
    def DrawHA(self, currentHA=None):
        if (currentHA is None):
            if not self.txtModelName.text(
            ) in self.currentProject["Models"].keys():
                return
            if not self.txtHAName.text() in self.currentProject["Models"][
                    self.txtModelName.text()]["HAs"].keys():
                return
            self.currentHA = self.currentProject["Models"][
                self.txtModelName.text()]["HAs"][self.txtHAName.text()]
        else:
            self.currentHA = currentHA
        for key, item in self.currentHA["boxes"].items():
            self.readItemFrom(item)
        self.DrawLine(self.currentHA["lines"])
        self.DrawVariable(self.currentHA["variables"])

    #show Default HA on screen
    def DrawDefaultHA(self):
        if ("NoName" in self.currentProject["Models"].keys()) or len(
                self.currentProject["Models"]) == 0:
            self.txtModelName.setText("NoName")
        else:
            self.txtModelName.setText(
                next(iter(self.currentProject["Models"].keys())))
        if ("NoName" in self.currentProject["Models"][self.txtModelName.text()]
            ["HAs"].keys()) or len(self.currentProject["Models"][
                self.txtModelName.text()]["HAs"]) == 0:
            self.txtHAName.setText("NoName")
        else:
            self.txtHAName.setText(
                next(
                    iter(self.currentProject["Models"][
                        self.txtModelName.text()]["HAs"].keys())))
        self.cmbHANameList.clear()
        self.cmbHANameList.addItems([
            key for key in self.currentProject["Models"][
                self.txtModelName.text()]["HAs"].keys()
        ])
        self.DrawHA()

    # load a exists HA file to edit
    def open(self):
        self.offerSave()
        path = "."  # (QFileInfo(self.filename).path()
        #if self.filename else ".")
        fname, filetype = QFileDialog.getOpenFileName(
            self, "Designer - Open", path, "Designer Files (*.json)")
        if not fname:
            return
        self.filename = fname
        self.clearCurrent()
        fh = None
        try:
            #if 1==1:

            with open(self.filename, 'r') as fh:
                self.currentProject = json.load(fh)
            self.DrawDefaultHA()

        except IOError as e:
            QMessageBox.warning(
                self, "Designer -- Open Error",
                "Failed to open {0}: {1}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()

        global Dirty
        Dirty = False

    def reject(self):
        self.accept()

    def accept(self):
        self.offerSave()
        QDialog.accept(self)

    #save the current HA
    def offerSave(self):
        if self.currentHA is not None:
            if not self.currentHA["name"] == self.txtHAName.text():
                self.setDirty()
        if (Dirty and QMessageBox.question(
                self, "Page Designer - Unsaved Changes",
                "Save unsaved changes?", QMessageBox.Yes | QMessageBox.No)
                == QMessageBox.Yes):

            self.save()

    def SameX(self):
        if self.scene.selectedItems() == None:
            return
        if len(self.scene.selectedItems()) == 0:
            return
        x = self.scene.selectedItems()[0].x()
        for box in self.scene.selectedItems():
            box.setPos(x, box.y())
            lines = [
                line for line in self.dicLine.values()
                if (line.fromBox.boxName == box.boxName
                    or line.toBox.boxName == box.boxName)
            ]
            for line in lines:
                line.resetLine()
        self.scene.update()

    def SameY(self):
        if self.scene.selectedItems() == None:
            return
        y = self.scene.selectedItems()[0].y()
        for box in self.scene.selectedItems():
            box.setPos(box.x(), y)
        self.scene.update()

    #save the current HA
    def save(self):
        if not self.filename:
            path = "."
            fname, filetype = QFileDialog.getSaveFileName(
                self, "Page Designer - Save As", path,
                "Page Designer Files (*.json)")
            if not fname:
                return
            self.filename = fname
        fh = None
        #try:
        if 1 == 1:
            self.scene.clearSelection()
            dicBoxSave = {}
            dicLineSave = {}
            dicVariableSave = {}
            for item in self.dicText.values():
                dicBoxSave[item.boxName] = item.toSaveJson()
            for item in self.dicLine.values():
                dicLineSave[item.boxName] = item.toSaveJson()
            for item in self.dicVariable.values():
                dicVariableSave[item.boxName] = item.toSaveJson()
            if self.currentHA is not None:
                if not self.currentHA["name"] == self.txtHAName.text():
                    self.currentProject["Models"][
                        self.txtModelName.text()]["HAs"].pop(
                            self.currentHA["name"])
            HASave = {}
            HASave["boxes"] = dicBoxSave
            HASave["lines"] = dicLineSave
            HASave["variables"] = dicVariableSave
            HASave["type"] = "HA"
            HASave["name"] = self.txtHAName.text()
            #self.dicHA[self.txtHAName.text()]=HASave
            if (len(dicBoxSave) > 0):
                if not "Models" in self.currentProject.keys():
                    self.currentProject["Models"] = {}
                if not self.txtModelName.text(
                ) in self.currentProject["Models"].keys():
                    self.currentProject["Models"][
                        self.txtModelName.text()] = {}
                if not "HAs" in self.currentProject["Models"][
                        self.txtModelName.text()].keys():
                    self.currentProject["Models"][
                        self.txtModelName.text()]["HAs"] = {}
                self.currentProject["Models"][self.txtModelName.text()]["HAs"][
                    self.txtHAName.text()] = HASave
            CurrentModel = {}
            CurrentModel["HAs"] = self.dicHA
            CurrentModel["type"] = "Model"
            CurrentModel["name"] = self.txtModelName.text()
            #self.dicModel[self.txtModelName.text()]=CurrentModel
            self.currentHA = HASave
            #self.currentProject["Models"]=self.dicModel
            self.cmbHANameList.clear()
            self.cmbHANameList.addItems([
                key for key in self.currentProject["Models"][
                    self.txtModelName.text()]["HAs"].keys()
            ])

            with open(self.filename, 'w') as fh:
                json.dump(self.currentProject, fh)

        global Dirty
        Dirty = False

    #show current variables in screen
    def DrawVariable(self, Variables):
        #draw lines between diffenent Loaation
        for key, ln in Variables.items():
            if ln["type"] == "Variable":
                if not "isConstant" in ln.keys():
                    ln["isConstant"] = False
                if not "initialValue" in ln.keys():
                    ln["initialValue"] = "0"
                v = VariableItem(ln["boxName"], ln["isInput"], ln["isOutput"],
                                 ln["isConstant"], ln["initialValue"], self)
                self.dicVariable[v.boxName] = v
                self.addVariableInTable(v)

    #show current edges in screen
    def DrawLine(self, Lines):
        #draw lines between diffenent Loaation
        for key, ln in Lines.items():
            if ln["type"] == "Edge":
                str1 = ln["strFromLocation"]
                str2 = ln["strToLocation"]
                if not (str1 == str2):
                    n = EdgeItem(ln["boxName"],
                                 self.dicText[ln["strFromLocation"]],
                                 self.dicText[ln["strToLocation"]],
                                 ln["guard"], ln["reset"], self.scene, self,
                                 ln["style"])
                    self.dicLine[ln["boxName"]] = n
                    n.setRotation(ln["rotation"])
                    self.addEdgeInTable(n)
        #draw lines in a Loaation self
        for key, ln in Lines.items():
            if ln["type"] == "Edge":
                str1 = ln["strFromLocation"]
                str2 = ln["strToLocation"]
                if (str1 == str2):
                    n = EdgeItem(ln["boxName"],
                                 self.dicText[ln["strFromLocation"]],
                                 self.dicText[ln["strToLocation"]],
                                 ln["guard"], ln["reset"], self.scene, self,
                                 ln["style"])
                    self.dicLine[ln["boxName"]] = n
                    n.setRotation(ln["rotation"])
                    self.addEdgeInTable(n)

    #show current edges in screen
    def DrawLineFromRead(self):
        #draw lines between diffenent Loaation
        for key, ln in self.dicItem.items():
            if ln["type"] == "Edge":
                str1 = ln["strFromLocation"]
                str2 = ln["strToLocation"]
                if not (str1 == str2):
                    n = EdgeItem(ln["boxName"],
                                 self.dicText[ln["strFromLocation"]],
                                 self.dicText[ln["strToLocation"]],
                                 ln["guard"], ln["reset"], self.scene, self,
                                 ln["style"])
                    self.dicLine[ln["boxName"]] = n
                    n.setRotation(ln["rotation"])
                    self.addEdgeInTable(n)
        #draw lines in a Loaation self
        for key, ln in self.dicItem.items():
            if ln["type"] == "Edge":
                str1 = ln["strFromLocation"]
                str2 = ln["strToLocation"]
                if (str1 == str2):
                    n = EdgeItem(ln["boxName"],
                                 self.dicText[ln["strFromLocation"]],
                                 self.dicText[ln["strToLocation"]],
                                 ln["guard"], ln["reset"], self.scene, self,
                                 ln["style"])
                    self.dicLine[ln["boxName"]] = n
                    n.setRotation(ln["rotation"])
                    self.addEdgeInTable(n)

    #get a HA from file
    def readItemFrom(self, item):
        if item["type"] == "Text":
            tx = TextItem(item, '', '', self.scene, self)
            self.dicText[tx.boxName] = tx
            tx.setRotation(item["rotation"])
        elif item["type"] == "Location":
            #        def __init__(self, boxName, equation, guard, position, isInitial, isNameAbove, scene,parentForm, style=Qt.SolidLine,

            tx = LocationItem(item, '', '', '', '', '', '', '', self.scene,
                              self)
            self.dicText[tx.boxName] = tx
            tx.setRotation(item["rotation"])
            pass
        elif type == "Pixmap":
            pass
        elif type == "Line":
            pass

    def writeItemToStream(
        self,
        item,
    ):
        #if isinstance(item, TextItem):
        data = item.toSaveJson()
        self.dictItemJson[item.boxName] = data
Пример #12
0
class MapWidget(QtWidgets.QFrame):
    """
    Custom tab widget with function for editing templates
    """

    mapItem_delete_signal = QtCore.pyqtSignal(object)


    def __init__(self, parent, mainWindow):
        super().__init__(parent)

        self.mainWindow = mainWindow
        self.mapManager = MapManager()

        self.map = None

        self.init_bar()
        self.init_ui()

        self.mapItem_delete_signal.connect(self.item_delete_slot)


    def init_ui(self):
        """
        Init map widget UI
        :return: 
        """
        self.setFrameShape(QtWidgets.QFrame.NoFrame)

        self.frameLayout = QtWidgets.QVBoxLayout(self)
        self.frameLayout.setObjectName("Frame layout")

        self.grview = QGraphicsView()
        self.grview.setRenderHints(self.grview.renderHints() | QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
        self.scene = QGraphicsScene()

        # scene.setSceneRect(0, 0, 1500, 459)

        self.grview.setScene(self.scene)

        noMap = QPixmap('resources/icons/no_map.png')
        self.scene.addPixmap(noMap)
        self.grview.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)

        self.frameLayout.addWidget(self.grview)


    def init_bar(self) -> None:
        """
        Init function bar, set to right side of widget
        :return: 
        """
        toolbar = QToolBar()
        toolbar.setObjectName('MapToolbar')
        self.mainWindow.addToolBar(Qt.RightToolBarArea, toolbar)

        # ------------------------------- Open map ----------------------------------
        self.openMap_action = QAction(QIcon('resources/icons/openMap.png'), TR().tr('Open_map'), self.mainWindow,
                                      triggered=self.open_map_action, enabled=False)
        toolbar.addAction(self.openMap_action)

        # ------------------------------- Zoom in ----------------------------------
        self.zoomIn_action = QAction(QIcon('resources/icons/zoomIn.png'), TR().tr('Zoom_in'), self.mainWindow,
                                     triggered=self.zoom_in_action, shortcut='Ctrl++', enabled=False)
        toolbar.addAction(self.zoomIn_action)

        # ------------------------------- Zoom out ----------------------------------
        self.zoomOut_action = QAction(QIcon('resources/icons/zoomOut.png'), TR().tr('Zoom_out'), self.mainWindow,
                                      triggered=self.zoom_out_action, shortcut='Ctrl++', enabled=False)
        toolbar.addAction(self.zoomOut_action)

        # ------------------------------- Edit info  ----------------------------------
        self.info_action = QAction(QIcon('resources/icons/scroll.png'), TR().tr('Edit_info'), self.mainWindow,
                                   triggered=self.edit_info_action, shortcut='Ctrl+P', enabled=False)
        toolbar.addAction(self.info_action)

        toolbar.addSeparator()

        # ------------------------------- Add monster ----------------------------------
        self.addMonster_action = QAction(QIcon('resources/icons/addMonster.png'), TR().tr('Add_monster'), self.mainWindow,
                                         triggered=self.add_monster_action, shortcut='Ctrl+M', enabled=False)
        toolbar.addAction(self.addMonster_action)

        # ------------------------------- Add item ----------------------------------
        self.addItem_action = QAction(QIcon('resources/icons/addItem.png'), TR().tr('Add_item'), self.mainWindow,
                                      triggered=self.add_item_action, enabled=False)
        toolbar.addAction(self.addItem_action)

        # ------------------------------- Add room ----------------------------------
        self.addRoom_action = QAction(QIcon('resources/icons/addRoom.png'), TR().tr('Add_room'), self.mainWindow,
                                      triggered=self.add_room_action, enabled=False)
        toolbar.addAction(self.addRoom_action)

        # ------------------------------- Add object ----------------------------------
        self.addObject_action = QAction(QIcon('resources/icons/addObject.png'), TR().tr('Add_object_map'), self.mainWindow,
                                        triggered=self.add_object_action, enabled=False)
        toolbar.addAction(self.addObject_action)


    def enable_tool_bar(self) -> None:
        """
        Enable tool bar actions
        """
        self.openMap_action.setEnabled(True)
        self.zoomIn_action.setEnabled(True)
        self.zoomOut_action.setEnabled(True)
        self.info_action.setEnabled(True)

        self.addItem_action.setEnabled(True)
        self.addRoom_action.setEnabled(True)
        self.addMonster_action.setEnabled(True)
        self.addObject_action.setEnabled(True)


    def tree_item_doubleclick_action(self, item) -> None:
        """
        Slot for double click on map at tree widget
        :param item: item in tree widget
        """

        if self.map:
            self.save_map()

        if item:
            if item.data(0, 11).object_type is not ObjectType.MAP:
                self.mainWindow.redraw_context_widget(item.data(0, 11).object_type, item)
            else:

                self.enable_tool_bar()
                map = MapDAO().get(item.data(0, 11).id)

                if self.map and self.map.id == map.id:
                    map = MapDAO().get(item.data(0, 11).id)
                self.map = map
                self.redraw()


    def item_delete_slot(self, mapItem) -> None:
        """
        Slot for deleting map item from map. Deleted from map and updated in database
        :param mapItem: map item, that you want to delete
        :return: 
        """
        # mapItem.number
        self.map.mapItemDraws.remove(self.map.mapItemDraws[mapItem.number - 1])
        MapItemDAO().delete(mapItem.mapItem.id)
        # self.redraw()


    def save_map(self) -> None:
        """
        Save image of map
        :return:
        """
        self.mapManager.update(self.map)
        self.save_map_action()


    def redraw(self) -> None:
        """
        Redraw scene in widget
        Whole scene is cleared and new map and map items is draw 
        """
        self.scene.clear()
        if self.map.mapFile:
            pixMap = QPixmap(self.map.mapFile)
            sceneMap = self.scene.addPixmap(pixMap)
            self.map.mapPixMap = sceneMap
            self.grview.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio)

        for num, mapItem in enumerate(self.map.mapItems):
            mapItem.number = num + 1
            item = MapItemDraw(mapItem, self.mapItem_delete_signal)
            self.scene.addItem(item)
            self.map.addMapItemDraws(item)


    def open_map_action(self) -> None:
        """
        Open image with map slot, if some map is here, old one is deleted
        """
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self.mainWindow, "Open File",
                                                            QtCore.QDir.currentPath())

        if fileName:
            if self.map.mapPixMap:
                self.scene.removeItem(self.map.mapPixMap)

            fileName = self.mapManager.copy_map(fileName, self.map)
            self.map.mapFile = fileName
            self.map.mapPixMap = self.scene.addPixmap(QPixmap(fileName))
            self.grview.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio)


    def zoom_in_action(self) -> None:
        """
        Zoom in whole map widget
        """
        self.grview.scale(1.2, 1.2)


    def zoom_out_action(self) -> None:
        """
        Zoom out whole map widget
        """
        self.grview.scale(0.8, 0.8)


    def add_item_action(self) -> None:
        """
        Add item to map
        :return:
        """
        data, choice = NewMapItem.get_data()

        if choice:
            number = len(self.map.mapItemDraws) + 1
            mapItem = MapItem(None, data.get('name', ''), data.get('description', ''), QPointF(), 0, number, None, self.map.id,
                              MapItemType.ITEM)
            id = MapItemDAO().create(mapItem)
            mapItem.id = id
            item = MapItemDraw(mapItem, self.mapItem_delete_signal)
            self.scene.addItem(item)

            self.map.addMapItemDraws(item)


    def add_monster_action(self) -> None:
        """
        Add monster to map
        :return:
        """
        data, choice = NewMapItem.get_data()

        if choice:
            number = len(self.map.mapItemDraws) + 1
            mapItem = MapItem(None, data.get('name', ''), data.get('description', ''), QPointF(), 0, number, None, self.map.id,
                              MapItemType.MONSTER)
            id = MapItemDAO().create(mapItem)
            mapItem.id = id
            item = MapItemDraw(mapItem, self.mapItem_delete_signal)
            self.scene.addItem(item)

            self.map.addMapItemDraws(item)


    def add_room_action(self) -> None:
        """
        Add room to map
        :return:
        """
        data, choice = NewMapItem.get_data()

        if choice:
            number = len(self.map.mapItemDraws) + 1
            mapItem = MapItem(None, data.get('name', ''), data.get('description', ''), QPointF(), 0, number, None, self.map.id,
                              MapItemType.ROOM)
            id = MapItemDAO().create(mapItem)
            mapItem.id = id
            item = MapItemDraw(mapItem, self.mapItem_delete_signal)
            self.scene.addItem(item)

            self.map.addMapItemDraws(item)


    def add_object_action(self) -> None:
        """
        Add object to map
        :return:
        """
        data, choice = NewMapItem.get_data()

        if choice:
            number = len(self.map.mapItemDraws) + 1
            mapItem = MapItem(None, data.get('name', ''), data.get('description', ''), QPointF(), 0, number, None, self.map.id,
                              MapItemType.OBJECT)
            id = MapItemDAO().create(mapItem)
            mapItem.id = id
            item = MapItemDraw(mapItem, self.mapItem_delete_signal)
            self.scene.addItem(item)

            self.map.addMapItemDraws(item)


    def edit_info_action(self) -> None:
        """
        Edit map info, when click on edit button        
        """
        data, choice = EditMapItem.get_data(None, self.map)
        if choice:
            self.map.name = data['name']
            self.map.description = data['description']


    def save_map_action(self):
        """
        Save whole map action. This action create image from map
        :return: 
        """
        self.scene.clearSelection()
        self.scene.setSceneRect(self.scene.itemsBoundingRect())

        img = QImage(self.scene.sceneRect().size().toSize(), QImage.Format_ARGB32)
        img.fill(Qt.transparent)

        painter = QPainter(img)
        self.scene.render(painter)

        name = 'resources/maps/exportedMap-{}.png'.format(self.map.id)
        img.save(name)

        del painter


    def drawItems(self, painter, items, options, widget=None):
        pass