Пример #1
0
class CadWindowMdi(QtWidgets.QMainWindow):
    def __init__(self):
        super(CadWindowMdi, self).__init__()
        self.mdiArea = QtWidgets.QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)
        self.mdiArea.subWindowActivated.connect(self.subWindowActivatedEvent)
        self.oldSubWin=None
    #        self.readSettings() #now works for position and size, support for toolbars is still missing(http://www.opendocs.net/pyqt/pyqt4/html/qsettings.html)
        self.setWindowTitle("PythonCAD")
        qIcon=self._getIcon('pythoncad')
        if qIcon:
            self.setWindowIcon(qIcon)
        self.setUnifiedTitleAndToolBarOnMac(True)
        #pythoncad kernel
        self.__application = Application()
        self.__cmd_intf = CmdIntf(self)
        #self.__cmd_intf.FunctionHandler.commandExecuted+=self.commandExecuted
        # create all dock windows
        self._createDockWindows()
        # create status bar
        self._createStatusBar()
        self.setUnifiedTitleAndToolBarOnMac(True)
        self._registerCommands()
        self.updateMenus()
        self.lastDirectory=os.getenv('USERPROFILE') or os.getenv('HOME')

        self.readSettings() #now works for position and size and ismaximized, and finally toolbar position
        return
    @property
    def scene(self):
        if self.mdiArea.activeSubWindow():
            return self.mdiArea.activeSubWindow().scene
    @property
    def view(self):
        if self.mdiArea.activeSubWindow():
            return self.mdiArea.activeSubWindow().view
    @property
    def Application(self):
        """
            get the kernel application object
        """
        return self.__application
    @property
    def LayerDock(self):
        """
            get the layer tree dockable window
        """
        return self.__layer_dock
    # ###############################################STATUSBAR
    # ##########################################################

    def _createStatusBar(self):
        '''
            Creates the statusbar object.
        '''

        self.statusBar().showMessage("Ready")

        #------------------------------------------------------------------------------------Create status buttons

        #Force Direction
        self.forceDirectionStatus=statusButton('SForceDir.png', 'Orthogonal Mode [right click will in the future set increment constrain angle]')
        self.forceDirectionStatus.clicked.connect(self.setForceDirection)
        self.forceDirectionStatus.setMenu(getPolarMenu())
        self.statusBar().addPermanentWidget(self.forceDirectionStatus)


        #Snap
        self.SnapStatus=statusButton('SSnap.png', 'Snap [right click displays snap list]\n for future implementation it should be a checkist')
        self.SnapStatus.clicked.connect(self.setSnapStatus)
        self.SnapStatus.setMenu(self.__cmd_intf.Category.getMenu(6))
        self.SnapStatus.setChecked(True)
        self.statusBar().addPermanentWidget(self.SnapStatus)


        #Grid
        self.GridStatus=statusButton('SGrid.png', 'Grid Mode [not available yet]')
        self.GridStatus.clicked.connect(self.setGrid)
        self.statusBar().addPermanentWidget(self.GridStatus)

        #------------------------------------------------------------------------------------Set coordinates label on statusbar (updated by idocumet)
        self.coordLabel=QtWidgets.QLabel("x=0.000\ny=0.000")
        self.coordLabel.setAlignment(QtCore.Qt.AlignVCenter)
        self.coordLabel.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken)
        self.coordLabel.setMinimumWidth(80)
        self.coordLabel.setMaximumHeight(20)
        self.coordLabel.setFont(QtGui.QFont("Sans", 6))
        self.statusBar().addPermanentWidget(self.coordLabel)
    def setForceDirection(self):
        if self.forceDirectionStatus.isChecked():
            self.scene.forceDirectionEnabled=True
            self.forceDirectionStatus.setFocus(False)
            if self.scene.activeICommand!=None and self.scene.fromPoint!=None:
                self.scene.GuideHandler.show()
        else:
            self.scene.forceDirectionEnabled=False
            self.scene.GuideHandler.hide()
    def setSnapStatus(self):
        if self.SnapStatus.isChecked():
            self.scene.snappingPoint.activeSnap=SNAP_POINT_ARRAY['LIST']
        else:
            self.scene.snappingPoint.activeSnap=SNAP_POINT_ARRAY['NONE']
    def setGrid(self):
        pass
    # ###############################################END STATUSBAR
    # ##########################################################

    def commandExecuted(self):
        self.resetCommand()
    def _createDockWindows(self):
        '''
            Creates all dockable windows for the application
        '''
        # commandline
        command_dock = self.__cmd_intf.commandLine
        # if the commandline exists, add it
        if not command_dock is None:
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, command_dock)
        return
    def closeEvent(self, event):
        """
            manage close event
        """
        self.mdiArea.closeAllSubWindows()
        if self.activeMdiChild():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()
    
    def writeSettings(self):
        settings = QtCore.QSettings('PythonCAD', 'MDI Settings')

    def subWindowActivatedEvent(self):
        """
            Sub windows activation
        """
        if self.mdiArea.activeSubWindow():
            if (self.mdiArea.activeSubWindow().document!=
                        self.__application.ActiveDocument):
                self.resetCommand()
                self.__application.ActiveDocument=self.mdiArea.activeSubWindow().document
        self.updateMenus()
    def resetCommand(self):
        """
            Resect the active command
        """
        self.__cmd_intf.resetCommand()
        if self.scene!=None:
            self.scene.cancelCommand()
        self.statusBar().showMessage("Ready")
    # ################################# SET if ICON AND MENU are ENABLED
    # ##########################################################
    def updateMenus(self):
        """
            update menu status
        """
        hasMdiChild = (self.activeMdiChild() is not None)
        #File
        self.__cmd_intf.setVisible('import', hasMdiChild)
        self.__cmd_intf.setVisible('saveas', hasMdiChild)
        self.__cmd_intf.setVisible('close', hasMdiChild)
        self.__cmd_intf.setVisible('print', hasMdiChild)
        #Edit
        self.__cmd_intf.setVisible('undo', hasMdiChild)
        self.__cmd_intf.setVisible('redo', hasMdiChild)
        self.__cmd_intf.setVisible('copy', hasMdiChild)
        self.__cmd_intf.setVisible('move', hasMdiChild)
        self.__cmd_intf.setVisible('delete', hasMdiChild)
        self.__cmd_intf.setVisible('mirror', hasMdiChild)
        self.__cmd_intf.setVisible('rotate', hasMdiChild)
        self.__cmd_intf.setVisible('trim', hasMdiChild)
        self.__cmd_intf.setVisible('property', hasMdiChild)
        #Draw
        self.__cmd_intf.setVisible('point', hasMdiChild)
        self.__cmd_intf.setVisible('segment', hasMdiChild)
        self.__cmd_intf.setVisible('rectangle', hasMdiChild)
        self.__cmd_intf.setVisible('polyline', hasMdiChild)
        self.__cmd_intf.setVisible('circle', hasMdiChild)
        self.__cmd_intf.setVisible('arc', hasMdiChild)
        self.__cmd_intf.setVisible('ellipse', hasMdiChild)
        self.__cmd_intf.setVisible('polygon', hasMdiChild)
        self.__cmd_intf.setVisible('fillet', hasMdiChild)
        self.__cmd_intf.setVisible('chamfer', hasMdiChild)
        self.__cmd_intf.setVisible('bisect', hasMdiChild)
        self.__cmd_intf.setVisible('text', hasMdiChild)
        #Dimension
        self.__cmd_intf.setVisible('dimension', hasMdiChild)
        #View
        self.__cmd_intf.setVisible('fit', hasMdiChild)
        self.__cmd_intf.setVisible('zoomwindow', hasMdiChild)
        self.__cmd_intf.setVisible('zoomitem', hasMdiChild)
        #snap
        self.__cmd_intf.setVisible('snapauto', hasMdiChild)
        self.__cmd_intf.setVisible('snapend', hasMdiChild)
        self.__cmd_intf.setVisible('snapmid', hasMdiChild)
        self.__cmd_intf.setVisible('snapcen', hasMdiChild)
        self.__cmd_intf.setVisible('snapper', hasMdiChild)
        self.__cmd_intf.setVisible('snaptan', False)
        self.__cmd_intf.setVisible('snapqua', hasMdiChild)
        self.__cmd_intf.setVisible('snap00', hasMdiChild)
        self.__cmd_intf.setVisible('snapint', hasMdiChild)
        #Tools
        self.__cmd_intf.setVisible('info2p', hasMdiChild)
        #window
        self.__cmd_intf.setVisible('tile', hasMdiChild)
        self.__cmd_intf.setVisible('cascade', hasMdiChild)
        self.__cmd_intf.setVisible('next', hasMdiChild)
        self.__cmd_intf.setVisible('previous', hasMdiChild)
        #hasSelection = (self.activeMdiChild() is not None and
        #                self.activeMdiChild().textCursor().hasSelection())
        #self.cutAct.setEnabled(hasSelection)
        #self.copyAct.setEnabled(hasSelection)

        #StatusBAR Satus Tools
        self.forceDirectionStatus.setEnabled(hasMdiChild)
        self.GridStatus.setEnabled(hasMdiChild)
        self.SnapStatus.setEnabled(hasMdiChild)
    def createMdiChild(self, file=None):
        """
            Create new IDocument
        """
        if file:
            newDoc=self.__application.openDocument(file)
        else:
            newDoc=self.__application.newDocument()
        for mdiwind in self.mdiArea.subWindowList():
            if mdiwind._IDocument__document.dbPath==file:
                child=mdiwind
                break
        else:
            child = IDocument(newDoc,self.__cmd_intf, self)
            self.mdiArea.addSubWindow(child)

        #child.copyAvailable.connect(self.cutAct.setEnabled)
        #child.copyAvailable.connect(self.copyAct.setEnabled)
        return child
    #def setAppDocActiveOnUi(self, doc):
    #    self.mdiArea.

    def _registerCommands(self):
        '''
            Register all commands that are handed by this object
        '''
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'new', '&New Drawing', self._onNewDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'open', '&Open Drawing...', self._onOpenDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'import', '&Import Drawing...', self._onImportDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'saveas', '&Save As...', self._onSaveAsDrawing)
        #
        # Create recentFile structure
        #
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')

        i=0
        for file in self.Application.getRecentFiles:
            fileName=self.strippedName(file)
            self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'file_'+str(i), fileName, self._onOpenRecent)
            i+=1
        #
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'close', '&Close', self._onCloseDrawing)
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'print', '&Print', self._onPrint)
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'quit', '&Quit', self.close)
        # Edit
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'undo', '&Undo', self._onUndo)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'redo', '&Redo', self._onRedo)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'property', '&Property', self._onProperty)

        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'preferences', '&User Preferences', self.preferences)
        #Modify
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'copy', '&Copy', self._onCopy)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'move', '&Move', self._onMove)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'rotate', '&Rotate', self._onRotate)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'mirror', '&Mirror', self._onMirror)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'delete', '&Delete', self._onDelete)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'trim', '&Trim', self._onTrim)
        # Draw
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'point', '&Point', self._onPoint)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'segment', '&Segment', self._onSegment)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'rectangle', '&Rectangle', self._onRectangle)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'polyline', '&Polyline', self._onPolyline)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'circle', '&Circle', self._onCircle)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'arc', '&Arc', self._onArc)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'ellipse', '&Ellipse', self._onEllipse)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'polygon', '&Polygon', self._onPolygon)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'fillet', '&Fillet', self._onFillet)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'chamfer', '&Chamfer', self._onChamfer)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'bisect', '&Bisect', self._onBisect)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'text', '&Text', self._onText)
        #   Dimension
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Dimension, 'dimension', '&Aligned Dimension', self._onDimension)
        # View
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'fit', '&Fit', self._onFit)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'zoomwindow', 'Zoom&Window', self._onZoomWindow)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'zoomitem', 'Zoom&Item',self._onCenterItem)
        # Snap
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapauto', 'Automatic Snap', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapend', 'End', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapmid', 'Middle', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapint', 'Intersection', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapper', 'Perpendicular', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapcen', 'Center', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snapqua', 'Quadrant', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snaptan', 'Tangent', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'snap00', 'Origin', self._onSnapCommand)

        #Tools
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Tools, 'info2p', 'Info Two Points', self._onInfo2p)

        #--menu: Windows
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'tile', '&Tile', self._onTile)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'cascade', '&Cascade', self._onCascade)

        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'next', 'Ne&xt', self.mdiArea.activateNextSubWindow)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'previous', 'Pre&vious', self.mdiArea.activatePreviousSubWindow)

        # Help
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Help, 'about', '&About PythonCAD', self._onAbout)
        return
    def updateRecentFileList(self):
        """
            update the menu recent file list
        """
        i=0
        for file in self.Application.getRecentFiles:
            fileName=self.strippedName(file)
            self.__cmd_intf.updateText('file_'+str(i), fileName)
            i+=1
    def strippedName(self, fullFileName):
        """
            get only the name of the filePath
        """
        # 正確取得 stripped file name
        return QtCore.QFileInfo(fullFileName).fileName()
    # ##########################################              ON COMMANDS
    # ##########################################################

    def _onNewDrawing(self):
        '''
            Create a new drawing
        '''
        child = self.createMdiChild()
        child.show()
        self.updateRecentFileList()
        return
    def _onOpenDrawing(self):
        '''
            Open an existing drawing PDR or DXF
        '''
        # ask the user to select an existing drawing
        # 可以正確打開檔案, 與 PyQt4 不同
        drawing = str(QtWidgets.QFileDialog.getOpenFileName(parent=self,directory=self.lastDirectory,  caption ="Open Drawing", filter ="Drawings (*.pdr *.dxf)")[0])
        # open a document and load the drawing
        #print("drawing is:", drawing)
        if len(drawing)>0:
            self.lastDirectory=os.path.split(drawing)[0]
            (name, extension)=os.path.splitext(drawing)
            if extension.upper()=='.DXF':
                child = self.createMdiChild()
                child.importExternalFormat(drawing)
            elif extension.upper()=='.PDR':
                child = self.createMdiChild(drawing)
            else:
                self.critical("Wrong command selected")
                return
            child.show()
            self.updateRecentFileList()
            self.view.fit()
        return
    def _onImportDrawing(self):
        '''
            Import existing drawing in current drawing (some issues with PyQt4.7)
        '''
        drawing = QtWidgets.QFileDialog.getOpenFileName(parent=self, caption="Import Drawing", directory=self.lastDirectory, filter="Dxf (*.dxf)")[0]
        # open a document and load the drawing
        if len(drawing)>0:
            self.lastDirectory=os.path.split(drawing)[0]
            self.mdiArea.activeSubWindow().importExternalFormat(drawing)
        return
    def _onOpenRecent(self):
        """
            on open recent file
        """
        #FIXME: if in the command line we insert file_1 or file_2
        #here we get en error action dose not have command attributes
        # action is en edit command not an action and have an empty value
        action = self.sender()
        if action:
            spool, index=action.command.split('_')
            fileName=self.Application.getRecentFiles[int(index)]
            if len(fileName)>0:
                child = self.createMdiChild(fileName)
                child.show()
                self.updateRecentFileList()
                self.view.fit()
        return
    def _onSaveAsDrawing(self):
        drawing = QtWidgets.QFileDialog.getSaveFileName(self, "Save As...", "/home", filter ="Drawings (*.pdr *.dxf)")[0]
        if len(drawing)>0:
            self.__application.saveAs(drawing)
    def _onPrint(self):
    #       printer.setPaperSize(QPrinter.A4);
        self.scene.clearSelection()
        printer=QtPrintSupport.QPrinter()
        printDialog=QtPrintSupport.QPrintDialog(printer)
        if (printDialog.exec_() == QtWidgets.QDialog.Accepted):
            painter=QtGui.QPainter()
            painter.begin(printer)
            painter.setRenderHint(QtGui.QPainter.Antialiasing);
            #self.mdiArea.activeSubWindow().scene.render(painter)
            self.mdiArea.activeSubWindow().view.render(painter)
            painter.end()
        self.statusBar().showMessage("Ready")
        return
    def _onCloseDrawing(self):
        path=self.mdiArea.activeSubWindow().fileName
        self.__application.closeDocument(path)
        self.mdiArea.closeActiveSubWindow()
        return
    #---------------------ON COMMANDS in DRAW

    def _onPoint(self):
        self.statusBar().showMessage("CMD:Point")
        self.callCommand('POINT')
        return
    def _onSegment(self):
        self.statusBar().showMessage("CMD:Segment")
        self.callCommand('SEGMENT')
        return
    def _onCircle(self):
        self.statusBar().showMessage("CMD:Circle")
        self.callCommand('CIRCLE')
        return
    def _onArc(self):
        self.statusBar().showMessage("CMD:Arc")
        self.callCommand('ARC')
        return
    def _onEllipse(self):
        self.statusBar().showMessage("CMD:Ellipse")
        self.callCommand('ELLIPSE')
        return
    def _onRectangle(self):
        self.statusBar().showMessage("CMD:Rectangle")
        self.callCommand('RECTANGLE')
        return
    def _onPolygon(self):
        self.statusBar().showMessage("CMD:Polygon")
        self.callCommand('POLYGON')
        return
    def _onPolyline(self):
        self.statusBar().showMessage("CMD:Polyline")
        self.callCommand('POLYLINE')
        return
    def _onFillet(self):
        self.statusBar().showMessage("CMD:Fillet")
        self.callCommand('FILLET')
        return
    def _onChamfer(self):
        self.statusBar().showMessage("CMD:Chamfer")
        self.callCommand('CHAMFER')
        return
    def _onBisect(self):
        self.statusBar().showMessage("CMD:Bisect")
        self.callCommand('BISECTOR')
        return
    def _onText(self):
        self.statusBar().showMessage("CMD:Text")
        self.callCommand('TEXT')
        return
    def _onDimension(self):
        self.statusBar().showMessage("CMD:Dimension")
        self.callCommand('DIMENSION')
        return
    #-------------------------ON COMMANDS in EDIT

    def _onUndo(self):
        self.scene.clearSelection()
        try:
           self.mdiArea.activeSubWindow().unDo()
        except UndoDbExc:
            self.critical("Unable To Perform Undo")
        self.statusBar().showMessage("Ready")
        return
    def _onRedo(self):
        self.scene.clearSelection()
        try:
            self.mdiArea.activeSubWindow().reDo()
        except UndoDbExc:
            self.critical("Unable To Perform Redo")
        self.statusBar().showMessage("Ready")
    def _onProperty(self):
        self.statusBar().showMessage("CMD:Property")
        self.callCommand('PROPERTY')
    def preferences(self):
        p=Preferences(self)
        #TODO: Fill up preferences
        if (p.exec_() == QtWidgets.QDialog.Accepted):
            #TODO: save Preferences
            pass
    #---------------------------ON COMMANDS in MODIFY

    def _onCopy(self):
        self.statusBar().showMessage("CMD:Copy")
        self.callCommand('COPY')
        return
    def _onMove(self):
        self.statusBar().showMessage("CMD:Move")
        self.callCommand('MOVE')
        return
    def _onDelete(self):
        self.statusBar().showMessage("CMD:Delete")
        self.callCommand('DELETE')
        self.statusBar().showMessage("Ready")
        return
    def _onTrim(self):
        self.statusBar().showMessage("CMD:Trim")
        self.callCommand('TRIM')
        self.statusBar().showMessage("Ready")
        return
    def _onMirror(self):
        self.statusBar().showMessage("CMD:Mirror")
        self.callCommand('MIRROR')
        return
    def _onRotate(self):
        self.statusBar().showMessage("CMD:Rotate")
        self.callCommand('ROTATE')
        return
    #---------------------------ON COMMANDS in VIEW

    def _onFit(self):
        self.view.fit()
    def _onZoomWindow(self):
        self.statusBar().showMessage("CMD:ZoomWindow")
        self.scene._cmdZoomWindow=True
    def _onCenterItem(self):
        self.view.centerOnSelection()
    #---------------------------ON COMMANDS in SNAP

    def _onSnapCommand(self):
        """
            On snep Command action
        """
        #__________SNAP NONE?
        self.scene.clearSelection()
        action = self.sender()
        if action:
            if action.command=="snapauto":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["LIST"])
            elif action.command=="snapend":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["END"])
            elif action.command=="snapmid":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["MID"])
            elif action.command=="snapcen":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["CENTER"])
            elif action.command=="snapper":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ORTHO"])
            elif action.command=="snaptan":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["TANGENT"])
            elif action.command=="snapqua":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["QUADRANT"])
            elif action.command=="snap00":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ORIG"])
            elif action.command=="snapint":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["INTERSECTION"])
            else:
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["LIST"])
    #------------------------ON COMMANDS in TOOLS

    def _onInfo2p(self):
        """
            on info two point command
        """
        self.scene.clearSelection()
        self.statusBar().showMessage("CMD:Info2Points")
        self.callCommand('DISTANCE2POINT', 'document')
        return
    #-- - - -=- - - - -=on commands in menu: Windows
    def _onTile(self):   #<-(by: S-PM 110524)
        "on Tile command"    #standard  "Documentation String"

        self.mdiArea.tileSubWindows()   #--call "tile" method
        return
    #_onTile>


    def _onCascade(self):   #<-(by: S-PM 110524)
        "on Cascade command"    #standard  "Documentation String"

    #-- - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=
    #                                                                       Prologue
        def cascadeFit(self):  #<-"Fit" function definition
            #--Register
            rgL=[]      #List
            rgN=0       #Integer
            rgGp=None   #General purpose

            #--Action
            rgL=self.mdiArea.subWindowList()    #--get child-List,
            rgN=len(rgL)                        #  and child-count
            if (rgN<1):  return(rgN)    #no sub-window: exit

            rgW = self.mdiArea.width()  #--get actually available room
            rgH = self.mdiArea.height()

            #--compute cascade offset dimensions
            if (rgN<2):     #<-less than 2 sub-windows: no offset
                rgCx=0
                rgCy=0
            elif (rgN>1):   #<-more than 1 sub-window: get offset
                rgCx=rgL[1].x()
                rgCy=rgL[1].y()
            #>
            rgCx=rgCx*(rgN-1)   #compute total cascade offset
            rgCy=rgCy*(rgN-1)

            #<-loop resize all sub-windows, so to fit them into available room
            for rgGp in rgL:
                rgGp.resize(rgW-rgCx, rgH-rgCy)
            #>

            return(rgN)
        #cascadeFit>

    #-- - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=
    #                                                                       Action
        #--call "cascade" method, as-is (rudimentary)
        self.mdiArea.cascadeSubWindows()

        rgN=cascadeFit(self)    #"fit" all sub-windows into available room
        return
    #encoding: utf-8
    #_onCascade>



    #-----------------------ON COMMANDS in ABOUT

    def _onAbout(self):
        QtWidgets.QMessageBox.about(self, "About PythonCAD",
                """<b>PythonCAD</b> is a CAD package written, surprisingly enough, in Python using the PyQt5 interface.<p>
                   The PythonCAD project aims to produce a scriptable, open-source,
                   easy to use CAD package for any Python/PyQt supported Platforms
                   <p>
                   This is an Alfa Release For The new R38 Vesion <b>(R38.0.0.5)<b><P>
                   <p>
                   <a href="http://sourceforge.net/projects/pythoncad/">PythonCAD Web Site On Sourceforge</a>
                   <p>
                   <a href="http://pythoncad.sourceforge.net/dokuwiki/doku.php">PythonCAD Wiki Page</a>
                   <p>
                   由 KMOL 改為 Python3 與 PyQt5 版本
                   """)
        return
    # ########################################## CALL COMMAND
    # ##########################################################

    def callCommand(self, commandName, commandFrom=None):
        """
            call a document command (kernel)
        """
        try:
            if commandFrom==None or commandFrom=='kernel':
                self.scene.activeKernelCommand=self.__application.getCommand(commandName)
            elif commandFrom=='document':
                self.scene.activeKernelCommand=self.getCommand(commandName)
            else:
                return
            self.scene.activeICommand=ICommand(self.scene)
            self.scene.activeICommand.updateInput+=self.updateInput
            self.updateInput(self.scene.activeKernelCommand.activeMessage)
        except EntityMissing:
            self.scene.cancelCommand()
            self.critical("You need to have an active document to perform this command")
        #checks if scene has selected items and launches them directly to the ICommand
        #if it's first prompt it's "give me entities"
        if len(self.scene.selectedItems())>0:
            if  self.scene.activeKernelCommand.activeException()==ExcMultiEntity:
                qtItems=[item for item in self.scene.selectedItems() if isinstance(item, BaseEntity)]
                self.scene.activeICommand.addMauseEvent(point=None,
                                                    entity=qtItems,
                                                    force=None)
            else:
                self.scene.clearSelection()
    def getCommand(self, name):
        """
            get an interface command
        """
        if name in INTERFACE_COMMAND:
            return INTERFACE_COMMAND[name](self.mdiArea.activeSubWindow().document,
                                           self.mdiArea.activeSubWindow())
        else:
            self.critical("Wrong command")
    def updateInput(self, message):
            self.__cmd_intf.commandLine.printMsg(str(message))
            self.statusBar().showMessage(str(message))
    @staticmethod
    def critical(text):
        '''
            Shows an critical message dialog
        '''
        dlg = QtWidgets.QMessageBox()
        dlg.setText(text)
        dlg.setIcon(QtWidgets.QMessageBox.Critical)
        dlg.exec_()
        return
    # ########################################## SETTINGS STORAGE
    # ##########################################################
    def readSettings(self):
        settings = QtCore.QSettings('PythonCAD', 'MDI Settings')
        settings.beginGroup("CadWindow")
        max = settings.value("maximized", False)
        # settings.setValue("size", QtCore.QSize(800, 600))
        # settings.setValue("pos", QtCore.QPoint(400, 300))
        if max == True:  # if cadwindow was maximized set it maximized again
            self.showMaximized()
        else:  # else set it to the previous position and size
            try:
                self.resize(settings.value("size").toSize()) # self.resize(settings.value("size", QtCore.QSize(800, 600)).toSize())
                self.move(settings.value("pos").toPoint())   # self.move(settings.value("pos", QtCore.QPoint(400, 300)).toPoint())+
                #self.resize(settings.value("size", QtCore.QSize(800, 600)))
                #self.move(settings.value("pos", QtCore.QPoint(400, 300)))
                #self.resize(settings.value("size"))
                #self.move(settings.value("pos"))
            except:    
                print("Warning: unable to set the previews values")
        settings.endGroup()
        
        settings.beginGroup("CadWindowState")
        try:
            self.restoreState(settings.value('State').toByteArray())
        except:
            print("Warning: Unable to set state")
        settings.endGroup()

    # ########################################## END SETTINGS STORAGE
    # ##########################################################

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None
    def switchLayoutDirection(self):
        if self.layoutDirection() == QtCore.Qt.LeftToRight:
            QtWidgets.QApplication.setLayoutDirection(QtCore.Qt.RightToLeft)
        else:
            QtWidgets.QApplication.setLayoutDirection(QtCore.Qt.LeftToRight)
    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)
    def _getIcon(self, cmd):
        '''
        Create an QIcon object based on the command name.
        The name of the icon is ':/images/' + cmd + '.png'.
        If the cmd = 'Open', the name of the icon is ':/images/Open.png'.
        '''
        icon_name = cmd + '.png'
        icon_path = os.path.join(os.path.join(os.getcwd(), 'icons'), icon_name)
        # check if icon exist
        if os.path.exists(icon_path):
            icon = QtGui.QIcon(icon_path)
            return icon
        # icon not found, don't use an icon, return None
        return None
    def keyPressEvent(self, event):
        if event.key()==QtCore.Qt.Key_Escape:
            self.resetCommand()

        super(CadWindowMdi, self).keyPressEvent(event)
    # ########################################## SYMPY INTEGRATION
    # ##########################################################

    def plotFromSympy(self, objects):
        """
            plot the sympy Object into PythonCAD
        """
        if self.mdiArea.currentSubWindow()==None:
            self._onNewDrawing()
        for obj in objects:
            self.plotSympyEntity(obj)
    def plotSympyEntity(self, sympyEntity):
        """
            plot the sympy entity
        """
        self.mdiArea.currentSubWindow().document.saveSympyEnt(sympyEntity)
    def createSympyDocument(self):
        """
            create a new document to be used by sympy plugin
        """
        self._onNewDrawing()
    def getSympyObject(self):
        """
            get an array of sympy object
        """
        #if self.Application.ActiveDocument==None:
        if self.mdiArea.currentSubWindow()==None:
            raise StructuralError("unable to get the active document")

        ents=self.mdiArea.currentSubWindow().scene.getAllBaseEntity()
        return [ents[ent].geoItem.getSympy() for ent in ents if ent!=None]
Пример #2
0
class CadWindowMdi(QtGui.QMainWindow):
    def __init__(self):
        super(CadWindowMdi, self).__init__()
        self.mdiArea = QtGui.QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)
        self.mdiArea.subWindowActivated.connect(self.subWindowActivatedEvent)
        self.oldSubWin = None
        #        self.readSettings() #now works for position and size, support for toolbars is still missing(http://www.opendocs.net/pyqt/pyqt4/html/qsettings.html)
        self.setWindowTitle("PythonCAD")
        qIcon = self._getIcon('pythoncad')
        if qIcon:
            self.setWindowIcon(qIcon)
        self.setUnifiedTitleAndToolBarOnMac(True)
        #pythoncad kernel
        self.__application = Application()
        self.__cmd_intf = CmdIntf(self)
        #self.__cmd_intf.FunctionHandler.commandExecuted+=self.commandExecuted
        # create all dock windows
        self._createDockWindows()
        # create status bar
        self._createStatusBar()
        self.setUnifiedTitleAndToolBarOnMac(True)
        self._registerCommands()
        self.updateMenus()
        self.lastDirectory = os.getenv('USERPROFILE') or os.getenv('HOME')

        self.readSettings(
        )  #now works for position and size and ismaximized, and finally toolbar position

        self.updateOpenFileList()
        self.updateRecentFileList()
        return

    @property
    def scene(self):
        if self.mdiArea.activeSubWindow():
            return self.mdiArea.activeSubWindow().scene

    @property
    def view(self):
        if self.mdiArea.activeSubWindow():
            return self.mdiArea.activeSubWindow().view

    @property
    def Application(self):
        """
            get the kernel application object
        """
        return self.__application

    @property
    def LayerDock(self):
        """
            get the layer tree dockable window
        """
        return self.__layer_dock

# ###############################################STATUSBAR
# ##########################################################

    def _createStatusBar(self):
        '''
            Creates the statusbar object.
        '''

        self.statusBar().showMessage("Ready")

        #------------------------------------------------------------------------------------Create status buttons

        #Force Direction
        self.forceDirectionStatus = statusButton(
            'SForceDir.png',
            'Orthogonal Mode [right click will in the future set increment constrain angle]'
        )
        self.connect(self.forceDirectionStatus, QtCore.SIGNAL('clicked()'),
                     self.setForceDirection)
        self.forceDirectionStatus.setMenu(getPolarMenu())
        self.statusBar().addPermanentWidget(self.forceDirectionStatus)

        #Snap
        self.SnapStatus = statusButton(
            'SSnap.png',
            'Snap [right click displays snap list]\n for future implementation it should be a checkist'
        )
        self.connect(self.SnapStatus, QtCore.SIGNAL('clicked()'),
                     self.setSnapStatus)
        self.SnapStatus.setMenu(self.__cmd_intf.Category.getMenu(6))
        self.SnapStatus.setChecked(True)
        self.statusBar().addPermanentWidget(self.SnapStatus)

        #Grid
        self.GridStatus = statusButton('SGrid.png',
                                       'Grid Mode [not available yet]')
        self.connect(self.GridStatus, QtCore.SIGNAL('clicked()'), self.setGrid)
        self.statusBar().addPermanentWidget(self.GridStatus)

        #------------------------------------------------------------------------------------Set coordinates label on statusbar (updated by idocumet)
        self.coordLabel = QtGui.QLabel("x=0.000\ny=0.000")
        self.coordLabel.setAlignment(QtCore.Qt.AlignVCenter)
        self.coordLabel.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken)
        self.coordLabel.setMinimumWidth(80)
        self.coordLabel.setMaximumHeight(20)
        self.coordLabel.setFont(QtGui.QFont("Sans", 6))
        self.statusBar().addPermanentWidget(self.coordLabel)

    def setForceDirection(self):
        if self.forceDirectionStatus.isChecked():
            self.scene.forceDirectionEnabled = True
            self.forceDirectionStatus.setFocus(False)
            if self.scene.activeICommand != None and self.scene.fromPoint != None:
                self.scene.GuideHandler.show()
        else:
            self.scene.forceDirectionEnabled = False
            self.scene.GuideHandler.hide()

    def setSnapStatus(self):
        if self.SnapStatus.isChecked():
            self.scene.snappingPoint.activeSnap = SNAP_POINT_ARRAY['LIST']
        else:
            self.scene.snappingPoint.activeSnap = SNAP_POINT_ARRAY['NONE']

    def setGrid(self):
        pass
# ###############################################END STATUSBAR
# ##########################################################

    def commandExecuted(self):
        self.resetCommand()

    def _createDockWindows(self):
        '''
            Creates all dockable windows for the application
        '''
        # commandline
        command_dock = self.__cmd_intf.commandLine
        # if the commandline exists, add it
        if not command_dock is None:
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, command_dock)
        return

    def closeEvent(self, event):
        """
            manage close event
        """
        self.mdiArea.closeAllSubWindows()
        if self.activeMdiChild():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()

    def subWindowActivatedEvent(self):
        """
            Sub windows activation
        """
        if self.mdiArea.activeSubWindow():
            if (self.mdiArea.activeSubWindow().document !=
                    self.__application.ActiveDocument):
                self.resetCommand()
                self.__application.ActiveDocument = self.mdiArea.activeSubWindow(
                ).document
        self.updateMenus()

    def resetCommand(self):
        """
            Resect the active command
        """
        self.__cmd_intf.resetCommand()
        if self.scene != None:
            self.scene.cancelCommand()
        self.statusBar().showMessage("Ready")

# ################################# SET if ICON AND MENU are ENABLED
# ##########################################################

    def updateMenus(self):
        """
            update menu status
        """
        hasMdiChild = (self.activeMdiChild() is not None)
        #File
        self.__cmd_intf.setVisible('import', hasMdiChild)
        self.__cmd_intf.setVisible('saveas', hasMdiChild)
        self.__cmd_intf.setVisible('close', hasMdiChild)
        self.__cmd_intf.setVisible('closeall', hasMdiChild)
        self.__cmd_intf.setVisible('print', hasMdiChild)
        #Edit
        self.__cmd_intf.setVisible('undo', hasMdiChild)
        self.__cmd_intf.setVisible('redo', hasMdiChild)
        self.__cmd_intf.setVisible('copy', hasMdiChild)
        self.__cmd_intf.setVisible('move', hasMdiChild)
        self.__cmd_intf.setVisible('delete', hasMdiChild)
        self.__cmd_intf.setVisible('mirror', hasMdiChild)
        self.__cmd_intf.setVisible('rotate', hasMdiChild)
        self.__cmd_intf.setVisible('trim', hasMdiChild)
        self.__cmd_intf.setVisible('property', hasMdiChild)
        #Draw
        self.__cmd_intf.setVisible('point', hasMdiChild)
        self.__cmd_intf.setVisible('segment', hasMdiChild)
        self.__cmd_intf.setVisible('rectangle', hasMdiChild)
        self.__cmd_intf.setVisible('polyline', hasMdiChild)
        self.__cmd_intf.setVisible('circle', hasMdiChild)
        self.__cmd_intf.setVisible('arc', hasMdiChild)
        self.__cmd_intf.setVisible('ellipse', hasMdiChild)
        self.__cmd_intf.setVisible('polygon', hasMdiChild)
        self.__cmd_intf.setVisible('fillet', hasMdiChild)
        self.__cmd_intf.setVisible('chamfer', hasMdiChild)
        self.__cmd_intf.setVisible('bisect', hasMdiChild)
        self.__cmd_intf.setVisible('text', hasMdiChild)
        #Dimension
        self.__cmd_intf.setVisible('dimension', hasMdiChild)
        #View
        self.__cmd_intf.setVisible('fit', hasMdiChild)
        self.__cmd_intf.setVisible('zoomwindow', hasMdiChild)
        self.__cmd_intf.setVisible('zoomitem', hasMdiChild)
        #snap
        self.__cmd_intf.setVisible('snapauto', hasMdiChild)
        self.__cmd_intf.setVisible('snapend', hasMdiChild)
        self.__cmd_intf.setVisible('snapmid', hasMdiChild)
        self.__cmd_intf.setVisible('snapcen', hasMdiChild)
        self.__cmd_intf.setVisible('snapper', hasMdiChild)
        self.__cmd_intf.setVisible('snaptan', False)
        self.__cmd_intf.setVisible('snapqua', hasMdiChild)
        self.__cmd_intf.setVisible('snap00', hasMdiChild)
        self.__cmd_intf.setVisible('snapint', hasMdiChild)
        #Tools
        self.__cmd_intf.setVisible('info2p', hasMdiChild)
        #window
        self.__cmd_intf.setVisible('tile', hasMdiChild)
        self.__cmd_intf.setVisible('cascade', hasMdiChild)
        self.__cmd_intf.setVisible('next', hasMdiChild)
        self.__cmd_intf.setVisible('previous', hasMdiChild)
        #hasSelection = (self.activeMdiChild() is not None and
        #                self.activeMdiChild().textCursor().hasSelection())
        #self.cutAct.setEnabled(hasSelection)
        #self.copyAct.setEnabled(hasSelection)

        #StatusBAR Satus Tools
        self.forceDirectionStatus.setEnabled(hasMdiChild)
        self.GridStatus.setEnabled(hasMdiChild)
        self.SnapStatus.setEnabled(hasMdiChild)

    def createMdiChild(self, file=None):
        """
            Create new IDocument
        """
        if file:
            newDoc = self.__application.openDocument(file)
        else:
            newDoc = self.__application.newDocument()
        for mdiwind in self.mdiArea.subWindowList():
            if mdiwind._IDocument__document.dbPath == file:
                child = mdiwind
                break
        else:
            child = IDocument(newDoc, self.__cmd_intf, self)
            self.mdiArea.addSubWindow(child)

        #child.copyAvailable.connect(self.cutAct.setEnabled)
        #child.copyAvailable.connect(self.copyAct.setEnabled)
        return child

    #def setAppDocActiveOnUi(self, doc):
    #    self.mdiArea.

    def _registerCommands(self):
        '''
            Register all commands that are handed by this object
        '''
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'new',
                                        '&New Drawing', self._onNewDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'open',
                                        '&Open Drawing...',
                                        self._onOpenDrawing)

        # Sub menu for recent files
        file_menu = self.__cmd_intf.Category.getMenu(
            self.__cmd_intf.Category.File)
        self.open_recent_menu = file_menu.addMenu('Open Recent Drawing')

        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'close',
                                        '&Close', self._onCloseDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File,
                                        'closeall', 'Close All',
                                        self._onCloseAll)

        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File,
                                        'saveas', '&Save As...',
                                        self._onSaveAsDrawing)

        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File,
                                        'import', '&Import Drawing...',
                                        self._onImportDrawing)

        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'print',
                                        '&Print', self._onPrint)
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'quit',
                                        '&Quit', self.close)
        # Edit
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'undo',
                                        '&Undo', self._onUndo)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'redo',
                                        '&Redo', self._onRedo)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit,
                                        'property', '&Property',
                                        self._onProperty)

        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit,
                                        'preferences', '&User Preferences',
                                        self.preferences)
        #Modify
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify,
                                        'copy', '&Copy', self._onCopy)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify,
                                        'move', '&Move', self._onMove)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify,
                                        'rotate', '&Rotate', self._onRotate)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify,
                                        'mirror', '&Mirror', self._onMirror)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify,
                                        'delete', '&Delete', self._onDelete)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify,
                                        'trim', '&Trim', self._onTrim)
        # Draw
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'point',
                                        '&Point', self._onPoint)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'segment', '&Segment', self._onSegment)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'rectangle', '&Rectangle',
                                        self._onRectangle)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'polyline', '&Polyline',
                                        self._onPolyline)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'circle', '&Circle', self._onCircle)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'arc',
                                        '&Arc', self._onArc)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'ellipse', '&Ellipse', self._onEllipse)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'polygon', '&Polygon', self._onPolygon)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'fillet', '&Fillet', self._onFillet)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'chamfer', '&Chamfer', self._onChamfer)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw,
                                        'bisect', '&Bisect', self._onBisect)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'text',
                                        '&Text', self._onText)
        #   Dimension
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Dimension,
                                        'dimension', '&Aligned Dimension',
                                        self._onDimension)
        # View
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'fit',
                                        '&Fit', self._onFit)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View,
                                        'zoomwindow', 'Zoom&Window',
                                        self._onZoomWindow)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View,
                                        'zoomitem', 'Zoom&Item',
                                        self._onCenterItem)
        # Snap
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapauto', 'Automatic Snap',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapend', 'End', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapmid', 'Middle',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapint', 'Intersection',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapper', 'Perpendicular',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapcen', 'Center',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snapqua', 'Quadrant',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snaptan', 'Tangent',
                                        self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap,
                                        'snap00', 'Origin',
                                        self._onSnapCommand)

        #Tools
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Tools,
                                        'info2p', 'Info Two Points',
                                        self._onInfo2p)

        #--menu: Windows
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows,
                                        'tile', '&Tile', self._onTile)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows,
                                        'cascade', '&Cascade', self._onCascade)

        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows,
                                        'next', 'Ne&xt',
                                        self.mdiArea.activateNextSubWindow)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows,
                                        'previous', 'Pre&vious',
                                        self.mdiArea.activatePreviousSubWindow)

        # Sub menu for displaying currently open files
        window_menu = self.__cmd_intf.Category.getMenu(
            self.__cmd_intf.Category.Windows)
        self.open_window_menu = window_menu.addMenu('Open Documents')

        # Help
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Help, 'about',
                                        '&About PythonCAD', self._onAbout)

        return

    def updateOpenFileList(self):
        # Currently open windows
        self.open_window_menu.clear()
        window_list = self.mdiArea.subWindowList()
        if not window_list:
            self.open_window_menu.addAction('None').setDisabled(True)
            return
        for window in window_list:
            entry = self.open_window_menu.addAction(window.document.dbPath)
            self.connect(
                entry, QtCore.SIGNAL('triggered()'),
                functools.partial(self.mdiArea.setActiveSubWindow, window))
            self.open_window_menu.addAction(entry)

    def updateRecentFileList(self):
        """
            update the menu recent file list
        """
        self.open_recent_menu.clear()
        recent_files = self.Application.getRecentFiles
        if not recent_files:
            self.open_recent_menu.addAction('None').setDisabled(True)
            return
        for recent_file in recent_files:
            entry = self.open_recent_menu.addAction(recent_file)
            self.connect(entry, QtCore.SIGNAL('triggered()'),
                         functools.partial(self.openDrawing, recent_file))
            self.open_recent_menu.addAction(entry)

    def strippedName(self, fullFileName):
        """
            get only the name of the filePath
        """
        return QtCore.QFileInfo(fullFileName).fileName()

    def openDrawing(self, file_path):
        if not os.path.exists(file_path):
            # TODO: Return a proper error
            return
        child = self.createMdiChild(file_path)
        child.show()
        self.updateRecentFileList()
        self.updateOpenFileList()
        self.view.fit()
        return

# ##########################################              ON COMMANDS
# ##########################################################

    def _onNewDrawing(self):
        '''
            Create a new drawing
        '''
        child = self.createMdiChild()
        child.show()
        self.updateOpenFileList()
        self.updateRecentFileList()
        return

    def _onOpenDrawing(self):
        '''
            Open an existing drawing PDR or DXF
        '''
        # ask the user to select an existing drawing
        drawing = str(
            QtGui.QFileDialog.getOpenFileName(parent=self,
                                              directory=self.lastDirectory,
                                              caption="Open Drawing",
                                              filter="Drawings (*.pdr *.dxf)"))
        # open a document and load the drawing
        if len(drawing) > 0:
            self.lastDirectory = os.path.split(drawing)[0]
            (name, extension) = os.path.splitext(drawing)
            if extension.upper() == '.DXF':
                child = self.createMdiChild()
                child.importExternalFormat(drawing)
            elif extension.upper() == '.PDR':
                child = self.createMdiChild(drawing)
            else:
                self.critical("Wrong command selected")
                return
            child.show()
            self.updateRecentFileList()
            self.updateOpenFileList()
            self.view.fit()
        return

    def _onImportDrawing(self):
        '''
            Import existing drawing in current drawing (some issues with PyQt4.7)
        '''
        drawing = QtGui.QFileDialog.getOpenFileName(
            parent=self,
            caption="Import Drawing",
            directory=self.lastDirectory,
            filter="Dxf (*.dxf)")
        # open a document and load the drawing
        if len(drawing) > 0:
            self.lastDirectory = os.path.split(drawing)[0]
            self.mdiArea.activeSubWindow().importExternalFormat(drawing)
        return

    def _onSaveAsDrawing(self):
        drawing = QtGui.QFileDialog.getSaveFileName(
            self, "Save As...", "/home", filter="Drawings (*.pdr *.dxf)")
        if len(drawing) > 0:
            self.__application.saveAs(drawing)

            # Connection has been closed already so close the child window
            self.mdiArea.closeActiveSubWindow()
            # Create new child window with the new path/filename
            child = self.createMdiChild(drawing)
            child.show()
            self.updateRecentFileList()
            self.updateOpenFileList()
            self.view.fit()

    def _onPrint(self):
        #       printer.setPaperSize(QPrinter.A4);
        self.scene.clearSelection()
        printer = QtGui.QPrinter()
        printDialog = QtGui.QPrintDialog(printer)
        if (printDialog.exec_() == QtGui.QDialog.Accepted):
            painter = QtGui.QPainter()
            painter.begin(printer)
            painter.setRenderHint(QtGui.QPainter.Antialiasing)
            #self.mdiArea.activeSubWindow().scene.render(painter)
            self.mdiArea.activeSubWindow().view.render(painter)
            painter.end()
        self.statusBar().showMessage("Ready")
        return

    def _onCloseDrawing(self):
        path = self.mdiArea.activeSubWindow().fileName
        self.__application.closeDocument(path)
        self.mdiArea.closeActiveSubWindow()
        self.updateOpenFileList()
        return

    def _onCloseAll(self):
        window_list = self.mdiArea.subWindowList()
        for window in window_list:
            self.__application.closeDocument(window.fileName)
        self.mdiArea.closeAllSubWindows()
        self.updateOpenFileList()
        return

#---------------------ON COMMANDS in DRAW

    def _onPoint(self):
        self.statusBar().showMessage("CMD:Point")
        self.callCommand('POINT')
        return

    def _onSegment(self):
        self.statusBar().showMessage("CMD:Segment")
        self.callCommand('SEGMENT')
        return

    def _onCircle(self):
        self.statusBar().showMessage("CMD:Circle")
        self.callCommand('CIRCLE')
        return

    def _onArc(self):
        self.statusBar().showMessage("CMD:Arc")
        self.callCommand('ARC')
        return

    def _onEllipse(self):
        self.statusBar().showMessage("CMD:Ellipse")
        self.callCommand('ELLIPSE')
        return

    def _onRectangle(self):
        self.statusBar().showMessage("CMD:Rectangle")
        self.callCommand('RECTANGLE')
        return

    def _onPolygon(self):
        self.statusBar().showMessage("CMD:Polygon")
        self.callCommand('POLYGON')
        return

    def _onPolyline(self):
        self.statusBar().showMessage("CMD:Polyline")
        self.callCommand('POLYLINE')
        return

    def _onFillet(self):
        self.statusBar().showMessage("CMD:Fillet")
        self.callCommand('FILLET')
        return

    def _onChamfer(self):
        self.statusBar().showMessage("CMD:Chamfer")
        self.callCommand('CHAMFER')
        return

    def _onBisect(self):
        self.statusBar().showMessage("CMD:Bisect")
        self.callCommand('BISECTOR')
        return

    def _onText(self):
        self.statusBar().showMessage("CMD:Text")
        self.callCommand('TEXT')
        return

    def _onDimension(self):
        self.statusBar().showMessage("CMD:Dimension")
        self.callCommand('DIMENSION')
        return
#-------------------------ON COMMANDS in EDIT

    def _onUndo(self):
        self.scene.clearSelection()
        try:
            self.mdiArea.activeSubWindow().unDo()
        except UndoDbExc:
            self.critical("Unable To Perform Undo")
        self.statusBar().showMessage("Ready")
        return

    def _onRedo(self):
        self.scene.clearSelection()
        try:
            self.mdiArea.activeSubWindow().reDo()
        except UndoDbExc:
            self.critical("Unable To Perform Redo")
        self.statusBar().showMessage("Ready")

    def _onProperty(self):
        self.statusBar().showMessage("CMD:Property")
        self.callCommand('PROPERTY')

    def preferences(self):
        p = Preferences(self)
        #TODO: Fill up preferences
        if (p.exec_() == QtGui.QDialog.Accepted):
            #TODO: save Preferences
            pass

#---------------------------ON COMMANDS in MODIFY

    def _onCopy(self):
        self.statusBar().showMessage("CMD:Copy")
        self.callCommand('COPY')
        return

    def _onMove(self):
        self.statusBar().showMessage("CMD:Move")
        self.callCommand('MOVE')
        return

    def _onDelete(self):
        self.statusBar().showMessage("CMD:Delete")
        self.callCommand('DELETE')
        self.statusBar().showMessage("Ready")
        return

    def _onTrim(self):
        self.statusBar().showMessage("CMD:Trim")
        self.callCommand('TRIM')
        self.statusBar().showMessage("Ready")
        return

    def _onMirror(self):
        self.statusBar().showMessage("CMD:Mirror")
        self.callCommand('MIRROR')
        return

    def _onRotate(self):
        self.statusBar().showMessage("CMD:Rotate")
        self.callCommand('ROTATE')
        return

#---------------------------ON COMMANDS in VIEW

    def _onFit(self):
        self.view.fit()

    def _onZoomWindow(self):
        self.statusBar().showMessage("CMD:ZoomWindow")
        self.scene._cmdZoomWindow = True

    def _onCenterItem(self):
        self.view.centerOnSelection()

#---------------------------ON COMMANDS in SNAP

    def _onSnapCommand(self):
        """
            On snep Command action
        """
        #__________SNAP NONE?
        self.scene.clearSelection()
        action = self.sender()
        if action:
            if action.command == "snapauto":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["LIST"])
            elif action.command == "snapend":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["END"])
            elif action.command == "snapmid":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["MID"])
            elif action.command == "snapcen":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["CENTER"])
            elif action.command == "snapper":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ORTHO"])
            elif action.command == "snaptan":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["TANGENT"])
            elif action.command == "snapqua":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["QUADRANT"])
            elif action.command == "snap00":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ORIG"])
            elif action.command == "snapint":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["INTERSECTION"])
            else:
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["LIST"])

#------------------------ON COMMANDS in TOOLS

    def _onInfo2p(self):
        """
            on info two point command
        """
        self.scene.clearSelection()
        self.statusBar().showMessage("CMD:Info2Points")
        self.callCommand('DISTANCE2POINT', 'document')
        return

#-- - - -=- - - - -=on commands in menu: Windows

    def _onTile(self):  #<-(by: S-PM 110524)
        "on Tile command"  #standard  "Documentation String"

        self.mdiArea.tileSubWindows()  #--call "tile" method
        return

    #_onTile>

    def _onCascade(self):  #<-(by: S-PM 110524)
        "on Cascade command"  #standard  "Documentation String"

        #-- - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=
        #                                                                       Prologue
        def cascadeFit(self):  #<-"Fit" function definition
            #--Register
            rgL = []  #List
            rgN = 0  #Integer
            rgGp = None  #General purpose

            #--Action
            rgL = self.mdiArea.subWindowList()  #--get child-List,
            rgN = len(rgL)  #  and child-count
            if (rgN < 1): return (rgN)  #no sub-window: exit

            rgW = self.mdiArea.width()  #--get actually available room
            rgH = self.mdiArea.height()

            #--compute cascade offset dimensions
            if (rgN < 2):  #<-less than 2 sub-windows: no offset
                rgCx = 0
                rgCy = 0
            elif (rgN > 1):  #<-more than 1 sub-window: get offset
                rgCx = rgL[1].x()
                rgCy = rgL[1].y()
            #>
            rgCx = rgCx * (rgN - 1)  #compute total cascade offset
            rgCy = rgCy * (rgN - 1)

            #<-loop resize all sub-windows, so to fit them into available room
            for rgGp in rgL:
                rgGp.resize(rgW - rgCx, rgH - rgCy)
            #>

            return (rgN)

        #cascadeFit>

#-- - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=- - - - -=
#                                                                       Action
#--call "cascade" method, as-is (rudimentary)
        self.mdiArea.cascadeSubWindows()

        rgN = cascadeFit(self)  #"fit" all sub-windows into available room
        return

    #_onCascade>

#-----------------------ON COMMANDS in ABOUT

    def _onAbout(self):
        QtGui.QMessageBox.about(
            self, "About PythonCAD",
            """<b>PythonCAD</b> is a CAD package written, surprisingly enough, in Python using the PyQt4 interface.<p>
                   The PythonCAD project aims to produce a scriptable, open-source,
                   easy to use CAD package for any Python/PyQt supported Platforms
                   <p>
                   This is an Alfa Release For The new R38 Vesion <b>(R38.0.0.5)<b><P>
                   <p>
                   <a href="http://sourceforge.net/projects/pythoncad/">PythonCAD Web Site On Sourceforge</a>
                   <p>
                   <a href="http://pythoncad.sourceforge.net/dokuwiki/doku.php">PythonCAD Wiki Page</a>
                   """)
        return

# ########################################## CALL COMMAND
# ##########################################################

    def callCommand(self, commandName, commandFrom=None):
        """
            call a document command (kernel)
        """
        try:
            if commandFrom == None or commandFrom == 'kernel':
                self.scene.activeKernelCommand = self.__application.getCommand(
                    commandName)
            elif commandFrom == 'document':
                self.scene.activeKernelCommand = self.getCommand(commandName)
            else:
                return
            self.scene.activeICommand = ICommand(self.scene)
            self.scene.activeICommand.updateInput += self.updateInput
            self.updateInput(self.scene.activeKernelCommand.activeMessage)
        except EntityMissing:
            self.scene.cancelCommand()
            self.critical(
                "You need to have an active document to perform this command")
        #checks if scene has selected items and launches them directly to the ICommand
        #if it's first prompt it's "give me entities"
        if len(self.scene.selectedItems()) > 0:
            if self.scene.activeKernelCommand.activeException(
            ) == ExcMultiEntity:
                qtItems = [
                    item for item in self.scene.selectedItems()
                    if isinstance(item, BaseEntity)
                ]
                self.scene.activeICommand.addMauseEvent(point=None,
                                                        entity=qtItems,
                                                        force=None)
            else:
                self.scene.clearSelection()

    def getCommand(self, name):
        """
            get an interface command
        """
        if INTERFACE_COMMAND.has_key(name):
            return INTERFACE_COMMAND[name](
                self.mdiArea.activeSubWindow().document,
                self.mdiArea.activeSubWindow())
        else:
            self.critical("Wrong command")

    def updateInput(self, message):
        self.__cmd_intf.commandLine.printMsg(str(message))
        self.statusBar().showMessage(str(message))

    @staticmethod
    def critical(text):
        '''
            Shows an critical message dialog
        '''
        dlg = QtGui.QMessageBox()
        dlg.setText(text)
        dlg.setIcon(QtGui.QMessageBox.Critical)
        dlg.exec_()
        return
# ########################################## SETTINGS STORAGE
# ##########################################################

    def readSettings(self):
        settings = QtCore.QSettings('PythonCAD', 'MDI Settings')
        settings.beginGroup("CadWindow")
        max = settings.value("maximized", False)
        if max == True:  #if cadwindow was maximized set it maximized again
            self.showMaximized()
        else:  #else set it to the previous position and size
            try:
                self.resize(
                    settings.value("size")
                )  # self.resize(settings.value("size", QtCore.QSize(800, 600)).toSize())
                self.move(
                    settings.value("pos")
                )  # self.move(settings.value("pos", QtCore.QPoint(400, 300)).toPoint())+
            except:
                print "Warning: unable to set the previews values"
        settings.endGroup()

        settings.beginGroup("CadWindowState")
        try:
            self.restoreState(settings.value('State'))
        except:
            print "Warning: Unable to set state"
        settings.endGroup()

    def writeSettings(self):
        settings = QtCore.QSettings('PythonCAD', 'MDI Settings')

        settings.beginGroup("CadWindow")
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())
        settings.setValue('maximized', self.isMaximized())
        settings.endGroup()

        settings.beginGroup("CadWindowState")
        settings.setValue("state", self.saveState())
        settings.endGroup()

# ########################################## END SETTINGS STORAGE
# ##########################################################

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None

    def switchLayoutDirection(self):
        if self.layoutDirection() == QtCore.Qt.LeftToRight:
            QtGui.qApp.setLayoutDirection(QtCore.Qt.RightToLeft)
        else:
            QtGui.qApp.setLayoutDirection(QtCore.Qt.LeftToRight)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)

    def _getIcon(self, cmd):
        '''
        Create an QIcon object based on the command name.
        The name of the icon is ':/images/' + cmd + '.png'.
        If the cmd = 'Open', the name of the icon is ':/images/Open.png'.
        '''
        icon_name = cmd + '.png'
        icon_path = os.path.join(os.path.join(os.getcwd(), 'icons'), icon_name)
        # check if icon exist
        if os.path.exists(icon_path):
            icon = QtGui.QIcon(icon_path)
            return icon
        # icon not found, don't use an icon, return None
        return None

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.resetCommand()

        super(CadWindowMdi, self).keyPressEvent(event)

# ########################################## SYMPY INTEGRATION
# ##########################################################

    def plotFromSympy(self, objects):
        """
            plot the sympy Object into PythonCAD
        """
        if self.mdiArea.currentSubWindow() == None:
            self._onNewDrawing()
        for obj in objects:
            self.plotSympyEntity(obj)

    def plotSympyEntity(self, sympyEntity):
        """
            plot the sympy entity
        """
        self.mdiArea.currentSubWindow().document.saveSympyEnt(sympyEntity)

    def createSympyDocument(self):
        """
            create a new document to be used by sympy plugin
        """
        self._onNewDrawing()

    def getSympyObject(self):
        """
            get an array of sympy object
        """
        #if self.Application.ActiveDocument==None:
        if self.mdiArea.currentSubWindow() == None:
            raise StructuralError("unable to get the active document")

        ents = self.mdiArea.currentSubWindow().scene.getAllBaseEntity()
        return [ents[ent].geoItem.getSympy() for ent in ents if ent != None]
Пример #3
0
class CadWindowMdi(QtWidgets.QMainWindow):
    def __init__(self):
        super(CadWindowMdi, self).__init__()
        self.mdiArea = QtWidgets.QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)
        self.mdiArea.subWindowActivated.connect(self.subWindowActivatedEvent)
#        self.readSettings() #now works for position and size, support for toolbars is still missing(http://www.opendocs.net/pyqt/pyqt4/html/qsettings.html)
        self.setWindowTitle("PythonCAD")
        qIcon = self._getIcon('pythoncad')
        if qIcon:
            self.setWindowIcon(qIcon)
        self.setUnifiedTitleAndToolBarOnMac(True)
        #pythoncad kernel
        self.__application = Application()
        self.__cmd_intf = CmdIntf(self)
        #self.__cmd_intf.FunctionHandler.commandExecuted+=self.commandExecuted
        # create all dock windows
        self._createDockWindows()
        # create status bar
        self._createStatusBar()
        self.setUnifiedTitleAndToolBarOnMac(True)
        self._registerCommands()
        self.updateMenus()
        self.lastDirectory = os.getenv('USERPROFILE') or os.getenv('HOME')
        
        self.readSettings() #now works for position and size and ismaximized, and finally toolbar position
        return
      
    @property
    def scene(self):
        if self.mdiArea.activeSubWindow():
            return self.mdiArea.activeSubWindow().scene
    
    @property
    def view(self):
        if self.mdiArea.activeSubWindow():
            return self.mdiArea.activeSubWindow().view 
   
    @property
    def Application(self):
        """
            get the kernel application object
        """
        return self.__application
    
    @property
    def LayerDock(self):
        """
            get the layer tree dockable window
        """
        return self.__layer_dock   

# ###############################################STATUSBAR
# ##########################################################

    def _createStatusBar(self):
        '''
            Creates the statusbar object.
        '''

        self.statusBar().showMessage("Ready")

        #------------------------------------------------------------------------------------Create status buttons        
        #Force Direction
        self.forceDirectionStatus = statusButton('SForceDir.png', 'Orthogonal Mode [right click will in the future set increment constrain angle]')
        # self.connect(self.forceDirectionStatus, QtCore.SIGNAL('clicked()'), self.setForceDirection)  # old, for new, help here: http://qt-project.org/wiki/Signals_and_Slots_in_PySide
        # http://stackoverflow.com/questions/15080731/call-a-function-when-a-button-is-pressed-pyqt
        self.forceDirectionStatus.clicked.connect(self.setForceDirection)
        self.statusBar().addPermanentWidget(self.forceDirectionStatus)
        
        #Snap
        self.SnapStatus = statusButton('SSnap.png', 'Snap [right click displays snap list]\n for future implementation it should be a checkist')
        # self.connect(self.SnapStatus, QtCore.SIGNAL('clicked()'), self.setSnapStatus)
        self.SnapStatus.clicked.connect(self.setSnapStatus)
        self.SnapStatus.setMenu(self.__cmd_intf.Category.getMenu(5))
        self.statusBar().addPermanentWidget(self.SnapStatus)

        
        #Grid
        self.GridStatus = statusButton('SGrid.png', 'Grid Mode [not available yet]') 
        # self.connect(self.GridStatus, QtCore.SIGNAL('clicked()'), self.setGrid)
        self.GridStatus.clicked.connect(self.setGrid)
        self.statusBar().addPermanentWidget(self.GridStatus)
        
        #------------------------------------------------------------------------------------Set coordinates label on statusbar (updated by idocumet)
        self.coordLabel = QtWidgets.QLabel("x=0.000\ny=0.000")
        self.coordLabel.setAlignment(QtCore.Qt.AlignVCenter)
        self.coordLabel.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken)
        self.coordLabel.setMinimumWidth(80)
        self.coordLabel.setMaximumHeight(20)
        self.coordLabel.setFont(QtGui.QFont("Sans", 6))
        self.statusBar().addPermanentWidget(self.coordLabel)
       
    def setForceDirection(self):
        if self.forceDirectionStatus.isChecked():
            print("abilita")
            self.scene.forceDirection = True
            self.forceDirectionStatus.setFocus(False)
        else:
            self.scene.forceDirection = False

    def setSnapStatus(self):
        print("status")
        pass
        
    def setGrid(self):
        pass
# ###############################################END STATUSBAR
# ##########################################################

    def commandExecuted(self):
        self.resetCommand()
        
    def _createDockWindows(self):
        '''
            Creates all dockable windows for the application
        '''
        # commandline
        command_dock = self.__cmd_intf.commandLine
        # if the commandline exists, add it
        if not command_dock is None:
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, command_dock)
        return    
    
    def closeEvent(self, event):
        """
            manage close event
        """
        self.mdiArea.closeAllSubWindows()
        if self.activeMdiChild():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()
            
    def subWindowActivatedEvent(self):
        """
            Sub windows activation
        """
        if self.mdiArea.activeSubWindow():
            self.resetCommand()
            self.__application.setActiveDocument(self.mdiArea.activeSubWindow().document)   
        self.updateMenus()
        
    def resetCommand(self):    
        """
            Resect the active command
        """
        self.__cmd_intf.resetCommand()
        if self.scene != None:
            self.scene.cancelCommand()
        self.statusBar().showMessage("Ready")

# ################################# SET if ICON AND MENU are ENABLED
# ##########################################################
    def updateMenus(self):
        """
            update menu status
        """
        hasMdiChild = (self.activeMdiChild() is not None)
        #File
        self.__cmd_intf.setVisible('import', hasMdiChild)
        self.__cmd_intf.setVisible('saveas', hasMdiChild)
        self.__cmd_intf.setVisible('close', hasMdiChild)
        self.__cmd_intf.setVisible('print', hasMdiChild)
        #Edit
        self.__cmd_intf.setVisible('undo', hasMdiChild)
        self.__cmd_intf.setVisible('redo', hasMdiChild)
        self.__cmd_intf.setVisible('copy', hasMdiChild)
        self.__cmd_intf.setVisible('move', hasMdiChild)
        self.__cmd_intf.setVisible('delete', hasMdiChild)
        self.__cmd_intf.setVisible('mirror', hasMdiChild)
        self.__cmd_intf.setVisible('rotate', hasMdiChild)
        #Draw
        self.__cmd_intf.setVisible('point', hasMdiChild)
        self.__cmd_intf.setVisible('segment', hasMdiChild)
        self.__cmd_intf.setVisible('rectangle', hasMdiChild)
        self.__cmd_intf.setVisible('polyline', hasMdiChild)
        self.__cmd_intf.setVisible('arc', hasMdiChild)
        self.__cmd_intf.setVisible('ellipse', hasMdiChild)
        self.__cmd_intf.setVisible('polygon', hasMdiChild)
        self.__cmd_intf.setVisible('fillet', hasMdiChild)
        self.__cmd_intf.setVisible('chamfer', hasMdiChild)
        self.__cmd_intf.setVisible('bisect', hasMdiChild)
        self.__cmd_intf.setVisible('text', hasMdiChild)
        #View
        self.__cmd_intf.setVisible('fit', hasMdiChild)
        self.__cmd_intf.setVisible('zoomwindow', hasMdiChild)
        self.__cmd_intf.setVisible('zoomitem', hasMdiChild)
        #snap
        self.__cmd_intf.setVisible('autosnap', hasMdiChild)
        self.__cmd_intf.setVisible('endsnap', hasMdiChild)
        self.__cmd_intf.setVisible('middlesnap', hasMdiChild)
        self.__cmd_intf.setVisible('centersnap', hasMdiChild)
        self.__cmd_intf.setVisible('ortosnap', False)
        self.__cmd_intf.setVisible('tangentsnap', False)
        self.__cmd_intf.setVisible('quadrantsnap', hasMdiChild)
        self.__cmd_intf.setVisible('originsnap', hasMdiChild)
        self.__cmd_intf.setVisible('intersection', hasMdiChild)
        #Tools
        self.__cmd_intf.setVisible('info2p', hasMdiChild)
        #window
        self.__cmd_intf.setVisible('tile', hasMdiChild)
        self.__cmd_intf.setVisible('cascade', hasMdiChild)
        self.__cmd_intf.setVisible('next', hasMdiChild)
        self.__cmd_intf.setVisible('previous', hasMdiChild)
        #hasSelection = (self.activeMdiChild() is not None and
        #                self.activeMdiChild().textCursor().hasSelection())
        #self.cutAct.setEnabled(hasSelection)
        #self.copyAct.setEnabled(hasSelection)
        
        #StatusBAR Satus Tools
        self.forceDirectionStatus.setEnabled(hasMdiChild)
        self.GridStatus.setEnabled(hasMdiChild)
        self.SnapStatus.setEnabled(hasMdiChild)
        
    def createMdiChild(self, file=None):
        """
            Create new IDocument 
        """
        if file:
            newDoc = self.__application.openDocument(file)
        else:
            newDoc = self.__application.newDocument()
        for mdiwind in self.mdiArea.subWindowList():
            if mdiwind._IDocument__document.dbPath == file:
                child = mdiwind
                break
        else:
            child = IDocument(newDoc,self.__cmd_intf, self)
            self.mdiArea.addSubWindow(child)

        # child.copyAvailable.connect(self.cutAct.setEnabled)
        # child.copyAvailable.connect(self.copyAct.setEnabled)
        return child
    # def setAppDocActiveOnUi(self, doc):
    #    self.mdiArea.
        
    def _registerCommands(self):
        '''
            Register all commands that are handed by this object
        '''
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'new', '&New Drawing', self._onNewDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'open', '&Open Drawing...', self._onOpenDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'import', '&Import Drawing...', self._onImportDrawing)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'saveas', '&Save In A Different location...', self._onSaveAsDrawing)
        #
        # Create recentFile structure
        #
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        
        i = 0
        for file in self.Application.getRecentFiles:
            fileName = self.strippedName(file)
            self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'file_' + str(i), fileName, self._onOpenRecent)    
            i += 1
        #
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'close', '&Close', self._onCloseDrawing)
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'print', '&Print', self._onPrint)
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.File, 'quit', '&Quit PyCAD', self.close)
        # Edit
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'undo', '&Undo', self._onUndo)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'redo', '&Redo', self._onRedo)
        # separator
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Edit, 'preferences', '&User Preferences', self.preferences)
        #Modify
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'copy', '&Copy', self._onCopy)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'move', '&Move', self._onMove)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'rotate', '&Rotate', self._onRotate)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'mirror', '&Mirror', self._onMirror)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Modify, 'delete', '&Delete', self._onDelete)
        # Draw
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'point', '&Point', self._onPoint)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'segment', '&Segment', self._onSegment)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'rectangle', '&Rectangle', self._onRectangle)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'polyline', '&Polyline', self._onPolyline)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'arc', '&Arc', self._onArc)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'ellipse', '&Ellipse', self._onEllipse)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'polygon', '&polygon', self._onPolygon)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'fillet', '&Fillet', self._onFillet)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'chamfer', '&Chamfer', self._onChamfer)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'bisect', '&Bisect', self._onBisect)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, '-')
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Draw, 'text', '&Text', self._onText)
        # View
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'fit', '&Fit', self._onFit)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'zoomwindow', 'Zoom&Window', self._onZoomWindow)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.View, 'zoomitem', 'Zoom&Item',self._onCenterItem)
        # Snap
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'autosnap', 'Automatic Snap', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'endsnap', 'End', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'middlesnap', 'Middle', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'centersnap', 'Center', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'ortosnap', 'Ortogonal', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'tangentsnap', 'Tangent', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'quadrantsnap', 'Quadrant', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'intersection', 'Intersection', self._onSnapCommand)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Snap, 'originsnap', 'Origin', self._onSnapCommand)
        
        #Tools
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Tools, 'info2p', 'Info Two Points', self._onInfo2p)
        # window
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'tile', '&Tile', self.mdiArea.tileSubWindows)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'cascade', '&Cascade', self.mdiArea.cascadeSubWindows)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'next', 'Ne&xt', self.mdiArea.activateNextSubWindow)
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Windows, 'previous', 'Pre&vious', self.mdiArea.activatePreviousSubWindow)
        # Help
        self.__cmd_intf.registerCommand(self.__cmd_intf.Category.Help, 'about', '&About PyCAD', self._onAbout)
        return
        
    def updateRecentFileList(self):
        """
            update the menu recent file list
        """
        i=0
        for file in self.Application.getRecentFiles:
            fileName=self.strippedName(file)
            self.__cmd_intf.updateText('file_'+str(i), fileName)
            i+=1
            
    def strippedName(self, fullFileName):
        """
            get only the name of the filePath
        """
        fullFileName_str = fullFileName[0]
        return QtCore.QFileInfo(fullFileName_str).fileName()    
        
        
# ##########################################              ON COMMANDS
# ##########################################################

    def _onNewDrawing(self):
        '''
            Create a new drawing 
        '''
        child = self.createMdiChild()
        child.show()
        self.updateRecentFileList()
        return
        
    def _onOpenDrawing(self):
        # ask the user to select an existing drawing
        drawing = QtWidgets.QFileDialog.getOpenFileName(parent=self,directory=self.lastDirectory,  caption ="Open Drawing", filter ="Drawings (*.pdr *.dxf)");
        # open a document and load the drawing
        if len(drawing) > 0:
            # self.lastDirectory = os.path.split(drawing)[0]
            self.lastDirectory = os.path.split(drawing[0])
            # (name, extension) = os.path.splitext(drawing)
            (name, extension) = os.path.splitext(drawing[0])
            if extension.upper() == '.DXF':
                child = self.createMdiChild()
                child.importExternalFormat(drawing)
            elif extension.upper() == '.PDR':
                child = self.createMdiChild(drawing)
            else:
                self.critical("Wrong command selected")
                return
            child.show() 
            self.updateRecentFileList()           
        return
    
    def _onImportDrawing(self):
        drawing = QtGui.QFileDialog.getOpenFileName(parent=self, caption="Import Drawing", directory=self.lastDirectory, filter="Dxf (*.dxf)");
        # open a document and load the drawing
        if len(drawing)>0:
            self.lastDirectory=os.path.split(drawing)[0]
            self.mdiArea.activeSubWindow().importExternalFormat(drawing)
        return
        
    def _onOpenRecent(self):
        """
            on open recent file
        """
        #FIXME: if in the command line we insert file_1 or file_2
        #here we get en error action dose not have command attributes
        # action is en edit command not an action and have an empty value
        action = self.sender()
        if action:
            spool, index=action.command.split('_')
            fileName=self.Application.getRecentFiles[int(index)]
            if len(fileName)>0:
                child = self.createMdiChild(fileName)
                child.show() 
                self.updateRecentFileList()
        return
        
    def _onSaveAsDrawing(self):
        drawing = QtGui.QFileDialog.getSaveFileName(self, "Save As Drawing", "/home", "Drawings (*.pdr)");
        if len(drawing)>0:
            self.__application.saveAs(drawing)
            
    def _onPrint(self):
#       printer.setPaperSize(QPrinter.A4);
        self.scene.clearSelection()
        printer=QtGui.QPrinter()
        printDialog=QtGui.QPrintDialog(printer)
        if (printDialog.exec_() == QtGui.QDialog.Accepted): 
            painter=QtGui.QPainter()
            painter.begin(printer)
            painter.setRenderHint(QtGui.QPainter.Antialiasing);
            #self.mdiArea.activeSubWindow().scene.render(painter)
            self.mdiArea.activeSubWindow().view.render(painter)
            painter.end()
        self.statusBar().showMessage("Ready")
        return
            
    def _onCloseDrawing(self):
        path=self.mdiArea.activeSubWindow().fileName
        self.__application.closeDocument(path)
        self.mdiArea.closeActiveSubWindow()
        return

#---------------------ON COMMANDS in DRAW

    def _onPoint(self):
        self.statusBar().showMessage("CMD:Point")
        self.callCommand('POINT')
        return    
    def _onSegment(self):
        self.statusBar().showMessage("CMD:Segment")
        self.callCommand('SEGMENT')
        return
    def _onArc(self):
        self.statusBar().showMessage("CMD:Arc")
        self.callCommand('ARC')
        return
    def _onEllipse(self):
        self.statusBar().showMessage("CMD:Ellipse")
        self.callCommand('ELLIPSE')
        return
    def _onRectangle(self):
        self.statusBar().showMessage("CMD:Rectangle")
        self.callCommand('RECTANGLE')
        return
    def _onPolygon(self):
        self.statusBar().showMessage("CMD:Polygon")
        self.callCommand('POLYGON')
        return
    def _onPolyline(self):
        self.statusBar().showMessage("CMD:Polyline")
        self.callCommand('POLYLINE')
        return
    
    def _onFillet(self):
        self.statusBar().showMessage("CMD:Fillet")
        self.callCommand('FILLET')
        return
        
    def _onChamfer(self):
        self.statusBar().showMessage("CMD:Chamfer")
        self.callCommand('CHAMFER')
        return
            
    def _onBisect(self):
        self.statusBar().showMessage("CMD:Bisect")
        self.callCommand('BISECTOR')
        return
    def _onText(self):
        self.statusBar().showMessage("CMD:Text")
        self.callCommand('TEXT')
        return      

#-------------------------ON COMMANDS in EDIT

    def _onUndo(self):
        self.scene.clearSelection()
        try:
           self.mdiArea.activeSubWindow().unDo() 
        except UndoDbExc:
            self.critical("Unable To Perform Undo")
        self.statusBar().showMessage("Ready")
        return
        
    def _onRedo(self):
        self.scene.clearSelection()
        try:
            self.mdiArea.activeSubWindow().reDo()
        except UndoDbExc:
            self.critical("Unable To Perform Redo")
        self.statusBar().showMessage("Ready")
    
    def preferences(self):
        p=ConfigDialog()
        #p.exec_()

#---------------------------ON COMMANDS in EDIT

    def _onCopy(self):
        self.statusBar().showMessage("CMD:Copy")
        self.callCommand('COPY')
        return
        
    def _onMove(self):
        self.statusBar().showMessage("CMD:Move")
        self.callCommand('MOVE')
        return
        
    def _onDelete(self):
        self.statusBar().showMessage("CMD:Delete")
        self.callCommand('DELETE')
        self.statusBar().showMessage("Ready")
        return
        
    def _onMirror(self):
        self.statusBar().showMessage("CMD:Mirror")
        self.callCommand('MIRROR')
        return
        
    def _onRotate(self):
        self.statusBar().showMessage("CMD:Rotate")
        self.callCommand('ROTATE')
        return

#---------------------------ON COMMANDS in VIEW

    def _onFit(self):
        self.view.fit()
        
    def _onZoomWindow(self):
        self.statusBar().showMessage("CMD:ZoomWindow")
        self.scene._cmdZoomWindow=True
    
    def _onCenterItem(self):
        self.view.centerOnSelection()

#---------------------------ON COMMANDS in SNAP

    def _onSnapCommand(self):
        """
            On snep Command action
        """
        #__________SNAP NONE?
        self.scene.clearSelection()
        action = self.sender()
        if action:
            if action.command=="autosnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ALL"])
            elif action.command=="endsnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["END"])
            elif action.command=="middlesnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["MID"])
            elif action.command=="centersnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["CENTER"])
            elif action.command=="ortosnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ORTO"])
            elif action.command=="tangentsnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["TANGENT"])
            elif action.command=="quadrantsnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["QUADRANT"]) 
            elif action.command=="originsnap":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ORIG"])
            elif action.command=="intersection":
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["INTERSECTION"])
            else:
                self.scene.setActiveSnap(SNAP_POINT_ARRAY["ALL"])

#------------------------ON COMMANDS in TOOLS

    def _onInfo2p(self):
        """
            on info two point command
        """
        self.scene.clearSelection()
        self.statusBar().showMessage("CMD:Info2Points")
        self.callCommand('DISTANCE2POINT', 'document')
        return

#-----------------------ON COMMANDS in ABOUT
        
    def _onAbout(self):
        QtWidgets.QMessageBox.about(self, "About PythonCAD",
                """<b>PythonCAD</b> is a CAD package written, surprisingly enough, in Python using the PyQt4 interface.<p>
                   The PythonCAD project aims to produce a scriptable, open-source,
                   easy to use CAD package for any Python/PyQt supported Platforms
                   <p>
                   This is an Alfa Release For The new R38 Vesion <b>(R38.0.0.4)<b><P>
                   <p>
                   <a href="http://sourceforge.net/projects/pythoncad/">PythonCAD Web Site On Sourceforge</a>
                   <p>
                   <a href="http://pythoncad.sourceforge.net/dokuwiki/doku.php">PythonCAD Wiki Page</a>
                   """)
        return
                
# ########################################## CALL COMMAND
# ##########################################################

    def callCommand(self, commandName, commandFrom=None):
        """
            call a document command (kernel)
        """
        try:
            if commandFrom==None or commandFrom=='kernel':
                self.scene.activeKernelCommand=self.__application.getCommand(commandName)
            elif commandFrom=='document':
                self.scene.activeKernelCommand=self.getCommand(commandName)
            else:
                return
            self.scene.activeICommand=ICommand(self.scene)
            self.scene.activeICommand.updateInput+=self.updateInput
            self.updateInput(self.scene.activeKernelCommand.activeMessage)
        except EntityMissing:
            self.scene.cancelCommand()
            self.critical("You need to have an active document to perform this command")
        #checks if scene has selected items and lauches them direclty to the Icommand if it's first prompt it's "give me entities"
        if len(self.scene.selectedItems())>0:
            print("selezioneesiste")
            if  self.scene.activeKernelCommand.activeException()==ExcMultiEntity:
                qtItems=[item for item in self.scene.selectedItems() if isinstance(item, BaseEntity)]
                self.scene.activeICommand.addMauseEvent(point=None,
                                                    entity=qtItems,
                                                    force=None)
            else:
                self.scene.clearSelection()
    
    def getCommand(self, name):
        """
            get an interface command
        """
        if INTERFACE_COMMAND.has_key(name):
            return INTERFACE_COMMAND[name](self.mdiArea.activeSubWindow().document, 
                                           self.mdiArea.activeSubWindow())
        else:
            self.critical("Wrong command")
        
    def updateInput(self, message):
            self.__cmd_intf.commandLine.printMsg(str(message))
            self.statusBar().showMessage(str(message))

    @staticmethod
    def critical(text):
        '''
            Shows an critical message dialog
        '''
        dlg = QtGui.QMessageBox()
        dlg.setText(text)
        dlg.setIcon(QtGui.QMessageBox.Critical)
        dlg.exec_()
        return
# ########################################## SETTINGS STORAGE
# ##########################################################
    def readSettings(self):
        settings = QtCore.QSettings('PythonCAD', 'MDI Settings')
        settings.beginGroup("CadWindow")
        max = settings.value("maximized", False)
        # settings.setValue("size", QtCore.QSize(800, 600))
        # settings.setValue("pos", QtCore.QPoint(400, 300))
        if max == True:  # if cadwindow was maximized set it maximized again
            self.showMaximized()
        else:  # else set it to the previous position and size
            try:
                self.resize(settings.value("size").toSize()) # self.resize(settings.value("size", QtCore.QSize(800, 600)).toSize())
                self.move(settings.value("pos").toPoint())   # self.move(settings.value("pos", QtCore.QPoint(400, 300)).toPoint())+
                #self.resize(settings.value("size", QtCore.QSize(800, 600)))
                #self.move(settings.value("pos", QtCore.QPoint(400, 300)))
                #self.resize(settings.value("size"))
                #self.move(settings.value("pos"))
            except:    
                print("Warning: unable to set the previews values")
        settings.endGroup()
        
        settings.beginGroup("CadWindowState")
        try:
            self.restoreState(settings.value('State').toByteArray())
        except:
            print("Warning: Unable to set state")
        settings.endGroup()

    def writeSettings(self):
        settings = QtCore.QSettings('PythonCAD', 'MDI Settings')
        
        settings.beginGroup("CadWindow")
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())
        settings.setValue('maximized', self.isMaximized())
        settings.endGroup()
        
        settings.beginGroup("CadWindowState")
        settings.setValue("state", self.saveState()) 
        settings.endGroup()
        
# ########################################## END SETTINGS STORAGE
# ########################################################## 

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None

    def switchLayoutDirection(self):
        if self.layoutDirection() == QtCore.Qt.LeftToRight:
            QtGui.qApp.setLayoutDirection(QtCore.Qt.RightToLeft)
        else:
            QtGui.qApp.setLayoutDirection(QtCore.Qt.LeftToRight)
        
    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)


    def _getIcon(self, cmd):
        '''
        Create an QIcon object based on the command name.
        The name of the icon is ':/images/' + cmd + '.png'.
        If the cmd = 'Open', the name of the icon is ':/images/Open.png'.
        '''
        icon_name = cmd + '.png'
        icon_path = os.path.join(os.path.join(os.getcwd(), 'icons'), icon_name)
        # check if icon exist
        if os.path.exists(icon_path):
            icon = QtGui.QIcon(icon_path)
            return icon
        # icon not found, don't use an icon, return None
        return None

    def keyPressEvent(self, event):
        if event.key()==QtCore.Qt.Key_Escape:
            self.resetCommand()
            
        super(CadWindowMdi, self).keyPressEvent(event)
        
# ########################################## SYMPY INTEGRATION
# ##########################################################

    def plotFromSympy(self, objects):
        """
            plot the sympy Object into PythonCAD
        """
        if self.mdiArea.currentSubWindow() == None:
            self._onNewDrawing()
        for obj in objects:
            self.plotSympyEntity(obj)
    
    def plotSympyEntity(self, sympyEntity):
        """
            plot the sympy entity
        """
        self.mdiArea.currentSubWindow().document.saveSympyEnt(sympyEntity)
    
    def createSympyDocument(self):
        """
            create a new document to be used by sympy plugin
        """
        self._onNewDrawing()
        
    def getSympyObject(self):
        """
            get an array of sympy object
        """
        #if self.Application.getActiveDocument()==None:
        if self.mdiArea.currentSubWindow() == None:
            raise StructuralError("unable to get the active document")
        
        ents = self.mdiArea.currentSubWindow().scene.getAllBaseEntity()
        return [ents[ent].geoItem.getSympy() for ent in ents if ent!=None]