def __init__(self, parent=None, filePath=''):
        """Default class constructor."""
        super(MDISubWindow_TextEdit, self).__init__(parent)

        print(filePath)
        self.filePath = filePath
        self.fileName = os.path.basename(os.path.abspath(filePath))
        self.fileExt = os.path.splitext(self.fileName)[1]

        if not filePath:
            self.setWindowTitle('Untitled[*]')
            parent.setWindowIcon(QIcon(gIconDir + os.sep + 'new.png'))
        else:
            f = open(filePath, 'r')
            txt = f.read()
            f.close()
            self.setText(txt)

            self.setWindowTitle('%s[*]' % self.fileName)

            # TODO: This is changing all the subwindows icons. We want individual icons based on filetype...?
            if self.fileExt in ('.py', '.pyw'):
                parent.setWindowIcon(QIcon(gIconDir + os.sep + 'pyscript.png'))
            else:
                parent.setWindowIcon(QIcon(gIconDir + os.sep + 'new.png'))

        monoFont = QFont('Courier New')
        monoFont.setFixedPitch(True)
        self.setFont(monoFont)
        self.setWordWrapMode(QTextOption.NoWrap)
        ## self.setTextBackgroundColor(QColor('#000000'))
        ## self.setTextColor(QColor('#FFFFFF'))
        self.setCursorWidth(2)
        self.CreateActions()

        self.zoomLevel = 0

        gMainWin.action_Edit_Cut.setEnabled(False)
        gMainWin.action_Edit_Copy.setEnabled(False)
        self.copyAvailable.connect(gMainWin.action_Edit_Cut.setEnabled)
        self.copyAvailable.connect(gMainWin.action_Edit_Copy.setEnabled)
        # Handle the Context Menu Entries Also.
        self.action_Edit_Undo.setEnabled(False)
        self.action_Edit_Redo.setEnabled(False)
        self.action_Edit_Cut.setEnabled(False)
        self.action_Edit_Copy.setEnabled(False)
        self.undoAvailable.connect(self.action_Edit_Undo.setEnabled)
        self.redoAvailable.connect(self.action_Edit_Redo.setEnabled)
        self.copyAvailable.connect(self.action_Edit_Cut.setEnabled)
        self.copyAvailable.connect(self.action_Edit_Copy.setEnabled)

        self.document().contentsChanged.connect(self.TheDocumentWasModified)

        # self.show()
        # self.showMaximized()
        # self.setFocusPolicy(Qt.WheelFocus)
        ##### self.setFocus() # This makes the MDIArea go into SubWindowView...?

        self.gCornerWidget = QToolButton(self)
        # self.gCornerWidgetToolTip = QToolTip()
        QToolTip.setFont(QFont('SansSerif', 10))
        br = QBrush(QPixmap(gImgDir + os.sep + 'texture-spirals.png'))
        pal = QPalette()
        # pal.setBrush(QPalette.Active, QPalette.Base, br)
        # pal.setColor(QPalette.Background, QColor('#FF8000'))
        pal.setColor(QPalette.ColorGroup.Inactive,
                     QPalette.ColorRole.ToolTipBase,
                     QColor(EMBROIDERBLUE2))
        QToolTip.setPalette(QPalette(pal))
        self.action_Edit_SelectAll.setToolTip('This is a <b>QWidget</b> widget')

        self.gCornerWidget.setDefaultAction(self.action_Edit_SelectAll)
        self.setCornerWidget(self.gCornerWidget)
        # We want to show the corner widget no matter what so...
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
Exemplo n.º 2
0
class Bar(QToolBar):

    clicked = Signal(str)

    def __init__(self, orientation=Qt.Horizontal, parent=None):
        super().__init__(parent)
        self.setOrientation(orientation)
        policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed,
                             QSizePolicy.ButtonBox)
        policy.setHeightForWidth(True)
        policy.setWidthForHeight(True)
        self.setSizePolicy(policy)
        self.setFloatable(False)
        self.setToolTip("""<p><b>Goto Letter</b></p>
<p>Left-click a letter to navigate to the first entry starting with that
letter.</p>
<p>Right-click a letter to navigate to the first entry starting with the
most recently left-clicked letter, plus any subsequent right-clicked
letters, and this letter.</p>
<p>(One left-click or a fifth right-click clears the previous letters.)</p>
<p>For example, left-click <i>S</i> to go to the first “s” entry. Then
right-click <i>A</i> to go to the first “sa” entry, then right-click
<i>T</i> to go to the first “sat” entry.</p>""")
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.timeout.connect(self.onTimeout)
        size = self.font().pointSizeF()
        strategy = QFont.StyleStrategy(QFont.PreferOutline
                                       | QFont.PreferAntialias
                                       | QFont.PreferQuality)
        self.mainFont = QFont("courier new")
        self.mainFont.setFixedPitch(True)
        self.mainFont.setStyleStrategy(strategy)
        self.mainFont.setStyleHint(QFont.Monospace)
        self.mainFont.setPointSizeF(size * 1.5)
        self.mainFont.setBold(True)
        self.mainFont.setItalic(False)
        self.setFont(self.mainFont)
        self.smallFont = QFont("helvetica")
        self.smallFont.setStyleStrategy(strategy)
        self.smallFont.setStyleHint(QFont.Times)
        self.smallFont.setPointSizeF(size * 1.25)
        self.smallFont.setBold(False)
        self.smallFont.setItalic(False)
        self.letters = string.ascii_uppercase
        self.word = None

    def sizeHint(self):
        return self.minimumSizeHint()

    def minimumSizeHint(self):
        count = len(self.letters)
        widthAll = self.fontMetrics().width(self.letters) * H_GAP_PC
        widthW = self.fontMetrics().width("WW")
        heightOne = self.fontMetrics().height()
        if self.orientation == Qt.Vertical:
            return QSize(widthW, (heightOne * count) + HANDLE_OFFSET)
        return QSize(widthAll + HANDLE_OFFSET, heightOne * V_GAP_PC)

    def paintEvent(self, event):
        super().paintEvent(event)
        letterPen = QPen(Qt.darkGreen if self.isEnabled() else Qt.lightGray)
        wordPen = QPen(Qt.darkCyan if self.isEnabled() else Qt.lightGray)
        painter = QPainter(self)
        painter.setRenderHints(QPainter.TextAntialiasing)
        painter.setPen(letterPen)
        heightOne = self.fontMetrics().height()
        widthOne = self.fontMetrics().width("W")
        if self.orientation == Qt.Vertical:
            y = HANDLE_OFFSET
            for c in self.letters:
                rect = QRectF(X_OFFSET, y, widthOne, heightOne)
                painter.drawText(rect, Qt.AlignCenter, c)
                y += heightOne
            if self.word is not None:
                painter.setFont(self.smallFont)
                painter.setPen(wordPen)
                rect = self.rect().adjusted(0, HANDLE_OFFSET, -widthOne / 3, 0)
                painter.drawText(rect,
                                 Qt.AlignTop | Qt.AlignRight | Qt.TextWordWrap,
                                 "\n".join(self.word.lower()))
                painter.setPen(letterPen)
                painter.setFont(self.mainFont)
        else:
            widthOne *= H_GAP_PC
            x = HANDLE_OFFSET
            for c in self.letters:
                rect = QRectF(x, 0, widthOne, heightOne * V_GAP_PC)
                painter.drawText(rect, Qt.AlignCenter, c)
                x += widthOne
            if self.word is not None:
                painter.setFont(self.smallFont)
                painter.setPen(wordPen)
                rect = self.rect().adjusted(HANDLE_OFFSET, 0, 0, 0)
                painter.drawText(rect, Qt.AlignBottom | Qt.AlignLeft,
                                 self.word.lower())
                painter.setPen(letterPen)
                painter.setFont(self.mainFont)

    def mousePressEvent(self, event):
        if self.orientation == Qt.Vertical:
            if event.y() < HANDLE_OFFSET:
                event.ignore()
                return
            heightOne = self.fontMetrics().height()
            i = clamp(0, int((event.y() - HANDLE_OFFSET) / heightOne),
                      len(self.letters) - 1)
        else:
            if event.x() < HANDLE_OFFSET:
                event.ignore()
                return
            widthOne = self.fontMetrics().width("W") * H_GAP_PC
            i = clamp(0, int((event.x() - HANDLE_OFFSET) / widthOne),
                      len(self.letters) - 1)
        event.accept()
        word = self.letters[i]
        if event.button() == Qt.LeftButton or self.word is None:
            self.word = word
        elif event.button() == Qt.RightButton:
            if len(self.word) >= 4:
                self.word = word
            elif self.word is not None:
                self.word += word
        if self.word is not None:
            self.clicked.emit(self.word.lower())
            self.timer.start(10000)
        self.update()

    def contextMenuEvent(self, event):
        if ((self.orientation == Qt.Vertical and event.y() < HANDLE_OFFSET) or
            (self.orientation == Qt.Horizontal and event.x() < HANDLE_OFFSET)):
            event.ignore()
        else:
            event.accept()

    def setOrientation(self, orientation):
        self.orientation = orientation
        self.update()

    def heightForWidth(self, width):
        count = len(self.letters)
        heightOne = self.fontMetrics().height()
        widthAll = self.fontMetrics().width(self.letters) * H_GAP_PC
        if widthAll > width:  # Needs to be vertical
            return heightOne * count
        return heightOne * V_GAP_PC  # Needs to be horizontal

    def onTimeout(self):
        self.timer.stop()
        if self.word is not None:
            self.word = None
            self.update()
    def __init__(self, parent=None, filePath=''):
        """Default class constructor."""
        super(MDISubWindow_TextEdit, self).__init__(parent)

        print(filePath)
        self.filePath = filePath
        self.fileName = os.path.basename(os.path.abspath(filePath))
        self.fileExt = os.path.splitext(self.fileName)[1]

        if not filePath:
            self.setWindowTitle('Untitled[*]')
            parent.setWindowIcon(QIcon(gIconDir + os.sep + 'new.png'))
        else:
            f = open(filePath, 'r')
            txt = f.read()
            f.close()
            self.setText(txt)

            self.setWindowTitle('%s[*]' % self.fileName)

            # TODO: This is changing all the subwindows icons. We want individual icons based on filetype...?
            if self.fileExt in ('.py', '.pyw'):
                parent.setWindowIcon(QIcon(gIconDir + os.sep + 'pyscript.png'))
            else:
                parent.setWindowIcon(QIcon(gIconDir + os.sep + 'new.png'))

        monoFont = QFont('Courier New')
        monoFont.setFixedPitch(True)
        self.setFont(monoFont)
        self.setWordWrapMode(QTextOption.NoWrap)
        ## self.setTextBackgroundColor(QColor('#000000'))
        ## self.setTextColor(QColor('#FFFFFF'))
        self.setCursorWidth(2)
        self.CreateActions()

        self.zoomLevel = 0

        gMainWin.action_Edit_Cut.setEnabled(False)
        gMainWin.action_Edit_Copy.setEnabled(False)
        self.copyAvailable.connect(gMainWin.action_Edit_Cut.setEnabled)
        self.copyAvailable.connect(gMainWin.action_Edit_Copy.setEnabled)
        # Handle the Context Menu Entries Also.
        self.action_Edit_Undo.setEnabled(False)
        self.action_Edit_Redo.setEnabled(False)
        self.action_Edit_Cut.setEnabled(False)
        self.action_Edit_Copy.setEnabled(False)
        self.undoAvailable.connect(self.action_Edit_Undo.setEnabled)
        self.redoAvailable.connect(self.action_Edit_Redo.setEnabled)
        self.copyAvailable.connect(self.action_Edit_Cut.setEnabled)
        self.copyAvailable.connect(self.action_Edit_Copy.setEnabled)

        self.document().contentsChanged.connect(self.TheDocumentWasModified)

        # self.show()
        # self.showMaximized()
        # self.setFocusPolicy(Qt.WheelFocus)
        ##### self.setFocus() # This makes the MDIArea go into SubWindowView...?

        self.gCornerWidget = QToolButton(self)
        # self.gCornerWidgetToolTip = QToolTip()
        QToolTip.setFont(QFont('SansSerif', 10))
        br = QBrush(QPixmap(gImgDir + os.sep + 'texture-spirals.png'))
        pal = QPalette()
        # pal.setBrush(QPalette.Active, QPalette.Base, br)
        # pal.setColor(QPalette.Background, QColor('#FF8000'))
        pal.setColor(QPalette.ColorGroup.Inactive,
                     QPalette.ColorRole.ToolTipBase, QColor(EMBROIDERBLUE2))
        QToolTip.setPalette(QPalette(pal))
        self.action_Edit_SelectAll.setToolTip(
            'This is a <b>QWidget</b> widget')

        self.gCornerWidget.setDefaultAction(self.action_Edit_SelectAll)
        self.setCornerWidget(self.gCornerWidget)
        # We want to show the corner widget no matter what so...
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
Exemplo n.º 4
0
class EditorWindow(QMainWindow):
    """initialize editor"""
    def __init__(self, tixi, xmlFilename, cpacs_scheme=Config.path_cpacs_21_schema):
        super(EditorWindow, self).__init__()   
        
        self.cur_file_path = ""
        self.cur_schema_path = ""
        
        self.setupEditor()
        self.setupButtonMenu()
        self.setupSearchBox()
        self.setupStatusbar()
        self.setupMenubar()
        self.setupNumbar()
        
        self.popUpWidget = None
        
        self.flag_layout = False
       
        self.hbox = QHBoxLayout()
        self.hbox.setSpacing(0)
        self.hbox.setContentsMargins(0,0,0,0)
        self.hbox.addWidget(self.number_bar)
        self.hbox.addWidget(self.editor)         
        
        self.layout = QGridLayout()
        
        self.layout.addWidget(self.searchbox,       0, 0, 1, 4)
        self.layout.addWidget(self.button1,         0, 4, 1, 1)
        self.layout.addWidget(self.button2,         0, 5, 1, 1)
        self.layout.addLayout(self.hbox,            2, 0, 1, 8)       
        self.layout.addWidget(self.fontsizeSpinBox, 0, 6, 1, 1)
        self.layout.addWidget(self.label1,          0, 7, 1, 1)
       
        self.window = QWidget()
        self.window.setLayout(self.layout) 

        self.setWindowTitle('Simple XML editor')
        self.setCentralWidget(self.window)
        self.resize(800, 800)
        self.show()       

        self.tixi = tixi
        self.loadFile(xmlFilename, cpacs_scheme) 

    '''
    loads cpacs file and validates it against the cpacs_schema
    @param xmlFilename: input file
    @param cpacs_scheme: validation scheme
    '''
    def loadFile(self, xmlFilename=None, cpacs_scheme=Config.path_cpacs_21_schema):
        if xmlFilename and cpacs_scheme :
            try:
                self.tixi.open(xmlFilename)
                #self.tixi.openDocument(xmlFilename) 
                #self.tixi.schemaValidateFromFile(cpacs_scheme)
                self.editor.setPlainText(self.tixi.exportDocumentAsString())
                self.cur_file_path = xmlFilename
                self.cur_schema_path = cpacs_scheme  
            except TixiException as e:  
                self.statusBar().showMessage('CPACS ERROR: ' + e.error)

    '''
    update the dictionary by the cpacs scheme
    @param path_dict: path to directory
    @param path_scheme: path to cpacs_scheme
    '''
    def updatedictionary(self, path_dict=Config.path_code_completion_dict, path_scheme=Config.path_cpacs_21_schema):
        found       = False
        olddict      = open(path_dict)
        scheme_file = open(path_scheme, 'r')
        
        with open(path_dict, "a") as newdict :
            for line in scheme_file :
                word = re.search("(?<=\<xsd:complexType name=\").*(?=\"\>)", line)
                if word != None :
                    for tmp in olddict : 
                        if tmp == word.group(0) +"\n" :
                            found = True
                            break
                    if(not found) :
                        newdict.write(word.group(0)+"\n")
                        olddict.seek(0)
                    found = False
            
        olddict.close()
        newdict.close()
        scheme_file.close()            

    '''
    validate xml file and write result to statusBar
    '''
    def validate(self):
        try:
            etree.fromstring(str(self.editor.toPlainText()))
            self.statusBar().showMessage("Valid XML")
        except etree.XMLSyntaxError as e:
            if e.error_log.last_error is not None:
                msg  = e.error_log.last_error.message
                line = e.error_log.last_error.line
                col  = e.error_log.last_error.column
                self.statusBar().showMessage("Invalid XML: Line %s, Col %s: %s"%(line,col,msg))
        except:
            self.statusBar().showMessage("Invalid XML: Unknown error") 

    '''
    close and cleanup tixi
    '''
    def __del__(self):
        pass
        #self.tixi.close()
        #self.tixi.cleanup() 

    '''
    set and connect the search buttons
    '''
    def setupButtonMenu(self):
        self.button1         = QPushButton("previous" )
        self.button2         = QPushButton("next" )
        self.label1          = QLabel("font")
        self.fontsizeSpinBox = QSpinBox()
        
        self.button1.hide()
        self.button2.hide()
        self.label1.hide()
        self.fontsizeSpinBox.hide()

        self.button1.clicked.connect(self.fire_search_backward)
        self.button2.clicked.connect(self.fire_search_foreward)
         
        self.fontsizeSpinBox.setRange(4, 30)
        self.fontsizeSpinBox.setSingleStep(1)
        self.fontsizeSpinBox.setSuffix('pt')
        self.fontsizeSpinBox.setValue(10)        
        self.fontsizeSpinBox.valueChanged.connect(self.setfontsize)         
    
    def setfontsize(self, value):
        self.font.setPointSize(value)
        self.editor.setFont(self.font)
                
    def setupEditor(self):
        self.font = QFont()
        self.font.setFamily('Courier')
        self.font.setFixedPitch(True)
        self.font.setPointSize(10)
        
        self.editor = EditorCodeCompletion(Config().path_code_completion_dict)       
        self.editor.setFont(self.font)
        self.editor.setTabStopWidth(20)
        self.editor.setAcceptRichText(False)
        self.editor.setLineWrapMode(QTextEdit.NoWrap)
        self.editor.textChanged.connect(self.validate)
        
        self.highlighter = Highlighter(self.editor.document())
    
    def setupNumbar(self):
        self.number_bar = NumberBar()
        self.number_bar.setTextEdit(self.getStates())
        self.editor.cursorPositionChanged.connect(self.fireUpdateNumbar)        
        self.connect(self.editor.verticalScrollBar(), SIGNAL("valueChanged(int)"), self.fireUpdateNumbar)  
        #self.editor.verticalScrollBar.valueChanged.connect(self.fireUpdateNumbar)

    def setupStatusbar(self):
        self.lineNumber = -1
        self.colNumber = -1
        self.m_statusRight = QLabel("row: " + str(self.lineNumber) + ", col:"  + str(self.colNumber), self)
        self.statusBar().addPermanentWidget(self.m_statusRight, 0) 

    def setupSearchBox(self):
        self.searchbox = SearchField() 
        self.searchbox.hide()     
        
    def setupMenubar(self):
        commentAction = QAction('Comment', self)
        commentAction.setShortcut('Ctrl+K')
        commentAction.setStatusTip('Comment Block')
        commentAction.triggered.connect(self.fireComment)
        
        uncommentAction = QAction('Uncomment', self)
        uncommentAction.setShortcut('Ctrl+Shift+K')
        uncommentAction.setStatusTip('Comment Block')
        uncommentAction.triggered.connect(self.fireUnComment)        
                        
        searchAction = QAction('search', self)
        searchAction.setShortcut('Ctrl+F')
        searchAction.setStatusTip('search')
        searchAction.triggered.connect(self.fireSearchView)     
        
                        
        newAction = QAction('New', self)
        newAction.setShortcut('Ctrl+N') 
        newAction.setStatusTip('creats empty cpacs-file')
        newAction.triggered.connect(self.fireNewAction)                       
                        
        self.updateAction = QAction('Update', self)
        self.updateAction.setShortcut('Ctrl+U')
        self.updateAction.setStatusTip('Update CPACS')
        self.updateAction.triggered.connect(self.fireUpdate)

        revertAction = QAction('Revert', self)
        revertAction.setShortcut('Ctrl+R')
        revertAction.triggered.connect(self.fireRevert)        

        clearAction = QAction('Clear', self)
        clearAction.setStatusTip('Clear Editor')
        clearAction.triggered.connect(self.editor.clear)

        numbarAction = QAction('Line Number', self)
        numbarAction.triggered.connect(self.fireSwitchLayout)                 

        self.xpathAction = QAction('Current XPath', self)
        self.xpathAction.triggered.connect(self.getCursorXPath)  

        link_to_node_YesAction = QAction('yes', self)
        link_to_node_YesAction.triggered.connect(self.dummyFuction)  

        link_to_node_NoAction = QAction('no', self)
        link_to_node_NoAction.triggered.connect(self.dummyFuction)  

        toolXAction = QAction('Tool X',self)
        toolXAction.triggered.connect(self.fireToolX)

        menubar = self.menuBar()
        filemenu = menubar.addMenu("File")
        filemenu.addAction(newAction)
        filemenu.addAction(self.updateAction) 
        filemenu.addAction(revertAction)         
        sourcemenu = menubar.addMenu("Source")  
        sourcemenu.addAction(commentAction)  
        sourcemenu.addAction(uncommentAction)
        sourcemenu.addAction(searchAction)
        editormenu = menubar.addMenu("Editor")
        editormenu.addAction(clearAction) 
        editormenu.addSeparator()
        editormenu.addAction(numbarAction)
        editormenu.addAction(self.xpathAction)
        editormenu_child1 = editormenu.addMenu('Link to node')
        editormenu_child1.addAction(link_to_node_YesAction)
        editormenu_child1.addAction(link_to_node_NoAction)
        toolmenu = menubar.addMenu("Tools")
        toolmenu.addAction(toolXAction)

        self.editor.setContextMenuPolicy(Qt.CustomContextMenu)
        self.editor.customContextMenuRequested.connect(self.showMenu)
        #self.editor.connect(self.editor, SIGNAL( "customContextMenuRequested(QPoint)" ), self.showMenu )

    def showMenu( self, pos ):
        """ Show a context menu for the active layer in the legend """
        menu = self.editor.createStandardContextMenu()
        menu.addAction(self.xpathAction)
        menu.exec_(QtCore.QPoint( self.mapToGlobal( pos ).x() + 5, self.mapToGlobal( pos ).y() )) 
            

    def fireUpdateNumbar(self):
        self.updateLineNumber()
        self.number_bar.update()

    def dummyFuction(self):
        print ("not implemented yet")
  
    def getStates(self):
        self.stats = { "searchbox":self.searchbox, "editor":self.editor}
        return self.stats    
        
    ''' find previous button '''    
    def fire_search_backward(self):
        self.editor.find(self.searchbox.text(), QTextDocument.FindBackward)  
        self.searchbox.setFocus()
        
    ''' find next button '''    
    def fire_search_foreward(self):
        
        #print self.tixi.getNumberOfChilds('/cpacs/vehicles/aircraft/model[@uID="Aircraft1"]/wings/wing[@uID="Aircraft1_Wing1"]/transformation[@uID="Aircraft1_Wing1_Transf"]/scaling[@uID="Aircraft1_Wing1_Transf_Sca"]/z')
        
        searchList = list(filter(lambda a : a!='',  self.searchbox.text().split('/')))
        if len(searchList) == 1 :
            if self.editor.find(searchList[0]) : 
                pass
            elif not self.editor.find(searchList[0], QTextDocument.FindBackward):
                QMessageBox.about(self, "error", "String %s not found" % (searchList[0]))
            else :
                self.editor.moveCursor(QTextCursor.Start)
                self.editor.find(searchList[0])
        else :
            self.searchXPath(self.searchbox.text(), searchList)
                
        self.searchbox.setFocus()     
      
    # test  
    # /cpacs/vehicles/aircraft/model/wings/wing/sections/section
    def searchXPath(self, path, searchList):
        try:
            if self.tixi.xPathEvaluateNodeNumber(path) > 1 :
                QMessageBox.about(self, "error", "XPath %s not unique" % path)
                return
                
            self.editor.moveCursor(QTextCursor.Start)
            
            found = True

            # search index snd loop
            j = 0
        
            # search backwards for uid 
            for i in range(len(searchList)-1, -1, -1) :
                if '[' in searchList[i] :    
                    # get value in brackets : [x] --> x
                    uid = re.search(r'\[(.*)\]', searchList[i]).group(1)
                    uid = self.__transToSearchUid(searchList[:i+1], uid)
                    
                    found = self.editor.find(uid)
                    j = i+1
                    break
                
            # search forward for all nodes after last uid
            while found and j < len(searchList) :
                found = self.editor.find('<'+searchList[j])
                j += 1
            if not found :
                QMessageBox.about(self, "error", "XPath %s not found" % path)
        except TixiException :
            QMessageBox.about(self, "error", "XPath %s not found" % path)


    def __transToSearchUid(self, path_list, uid):
        try: 
            int(uid)
            path = ""
            for p in path_list : path = path + '/' + p 
            return self.tixi.getTextAttribute(path , 'uID')
        except ValueError: 
            return uid.replace('@', '')

    def getCursorXPath(self):
        start_pos = self.editor.textCursor().position()

        tag , tag_pos , isCursorInTag = self.getTagNameAtCursor()
        
        _,xpath_idx, xpath_uid = self.__findXPath_rec('/cpacs', '/cpacs' , tag, tag_pos)  
        
        if not isCursorInTag:
            xpath_idx = self.__strRemoveReverseToChar(xpath_idx, '/')
            xpath_uid = self.__strRemoveReverseToChar(xpath_uid, '/')
 
        self.__setCursorToPostion(start_pos)
        self.__startXPathPopUp(xpath_idx, xpath_uid)
        
        
    def getTagNameAtCursor(self):
        '''
        @return: name of tag , position of tag , cursor is btw open and closing tag 
        '''
        self.editor.find('<', QTextDocument.FindBackward)
        isClosingTag , fst_tag   = self.__getTagName()

        pos = self.editor.textCursor().position()
        
        if isClosingTag :
            # find open tag of this closing tag
            self.editor.find('<'+fst_tag, QTextDocument.FindBackward)
            pos = self.editor.textCursor().position()
            
            return fst_tag , pos , False
        else:
            return fst_tag , pos , True


    def __getTagName(self):
        tc = self.editor.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        
        tx = tc.selectedText()  
        isClosingTag = False
        
        if "</" in tx :
            # select next word
            tc.select(QTextCursor.WordUnderCursor)
            tx = tc.selectedText()
            isClosingTag = True
        
        return isClosingTag , "" if "<" in tx else tx
        

    def __findXPath_rec(self, xpath_idx, xpath_uid, search, pos):
        nodes = self.__getChildNodesIdxTuple(xpath_idx)
        
        for (node, idx) in nodes:
            if node != '#text' :
                new_xpath_idx, new_xpath_uid = self.__createNewXPath(xpath_idx, xpath_uid, node, idx)
                if search == node and self.isNodeAtSearchedTagPosition(new_xpath_uid, pos) :
                    print ("gefunden" , new_xpath_idx)
                    return True, new_xpath_idx , new_xpath_uid
                else:
                    flag , res_idx, res_uid = self.__findXPath_rec(new_xpath_idx, new_xpath_uid, search, pos)
                    if flag : return True, res_idx, res_uid
        return False , xpath_idx , xpath_uid


    def __getChildNodesIdxTuple(self, xpath):
        n = self.tixi.getNumberOfChilds(xpath) + 1
        node_list = list(map(lambda i : self.tixi.getChildNodeName(xpath, i), range(1,n)))
        
        res = []
        for j in range(len(node_list)) :
            cnt = 1
            for k in range(j):
                if node_list[k] == node_list[j] : 
                    cnt = cnt + 1
            res.append((node_list[j],cnt))
        
        return res
    

    def __createNewXPath(self, xpath_idx, xpath_uid, node, idx):
        path_idx = xpath_idx + '/' + node
        path_uid = xpath_uid + '/' + node

        try :
            uID = self.tixi.getTextAttribute(path_idx + '[' + str(idx) + ']', 'uID')
            path_idx = path_idx + '[' + str(idx) + ']'
            path_uid = path_uid+'[@uID="' + uID + '"]'
            
        except TixiException:
            pass # e.error == 'ATTRIBUTE_NOT_FOUND
            
        return path_idx , path_uid


    
    def isNodeAtSearchedTagPosition(self, xpath, pos):
        '''
        @param xpath: xpath with uids (doesn't work with indices)
        @param param: 
        '''
        self.editor.moveCursor(QTextCursor.Start)
        
        # split string at / and remove all empty strings
        l = list(filter(lambda x : x != '' , xpath.split('/')))
        
        # search index snd loop
        j = 0
        
        # search backwards for uid 
        for i in range(len(l)-1, -1, -1) :
            if '[' in l[i] :    
                # get value in brackets : [x] --> x
                uid = re.search(r'\[@(.*)\]', l[i]).group(1)
                self.editor.find(uid)
                
                j = i+1
                break
        
        # search forward for all nodes after last uid
        while j < len(l) :
            self.editor.find('<'+l[j])
            j += 1

        return pos <= self.editor.textCursor().position()


    def __setCursorToPostion(self, pos):
        tc = self.editor.textCursor()
        tc.setPosition(pos)
        self.editor.setTextCursor(tc)

    def __startXPathPopUp(self, xpath_idx, xpath_uid):
        self.popUpWidget = XPathDialog(xpath_idx, xpath_uid) 

        self.setEnabled(False)
        self.popUpWidget.closeAct.triggered.connect(self.__resetPopUpWidget)
        
        self.popUpWidget.show()  


    def updateLineNumber(self): 
        '''
        sets the line and column number
        '''
        self.lineNumber = self.editor.textCursor().blockNumber() + 1
        self.colNumber = self.editor.textCursor().columnNumber() + 1
        self.m_statusRight.setText("row: " + str(self.lineNumber) + ", col:"  + str(self.colNumber))           

       
    def highlightCurrentLine(self) :
        '''
        highlight line under cursor
        ''' 
        extraSelections = []
        selection = QTextEdit.ExtraSelection()
        lineColor = QColor(255, 250, 205)
        selection.format.setBackground(lineColor)
        selection.format.setProperty(QTextFormat.FullWidthSelection, True)
        selection.cursor = self.editor.textCursor()
        selection.cursor.clearSelection()
        extraSelections.append(selection)
        self.editor.setExtraSelections(extraSelections)
        self.editor.setFocus()  
 
    #TODO: implemnt
    def fireUpdate(self):
        print ('dummy function - update the model')
        text_file = open(Config.path_cpacs_tmp_file, "w")
        text_file.write(self.editor.toPlainText())
        text_file.close()
        
        
        #self.tixi.saveDocument(Config.path_cpacs_tmp_file)
      # '../cpacs_files/temp.xml'
        

    def fireRevert(self):
        '''
        reloads cpacs file if not updated yet
        '''
        if(self.cur_file_path and self.cur_schema_path) :
            self.loadFile(self.cur_file_path, self.cur_schema_path)
        else :
            QMessageBox.about(self, "error", "CPACS-File or Validation-Schema not available")
            

    def fireSwitchLayout(self): 
        '''
        function to show or hide line numbers
        '''
        if(self.flag_layout) :
            self.number_bar.flag_show_numbers = True
            self.update()
        else :  
            self.number_bar.flag_show_numbers = False
            self.update()
        self.flag_layout = not self.flag_layout 
    
    def fireNewAction(self):
        '''
        opens new file input form   
        '''          
        self.setEnabled(False)
        self.popUpWidget = NewFileDialog()
        self.popUpWidget.buttonBox.accepted.connect(self.__createNewCpacsFile)
        self.popUpWidget.buttonBox.rejected.connect(self.__resetPopUpWidget)
        self.popUpWidget.closeAct.triggered.connect(self.__resetPopUpWidget)
        self.popUpWidget.show()
   
    def fireToolX(self):
        self.popUpWidget = ToolX("X-Tool", self.tixi)
        self.setEnabled(False)
        self.popUpWidget.buttonBox.accepted.connect(self.__resetPopUpWidget)
        self.popUpWidget.buttonBox.rejected.connect(self.__resetPopUpWidget)
        # closeAct for pressing X to close window
        self.popUpWidget.closeAct.triggered.connect(self.__resetPopUpWidget)
        self.popUpWidget.show()        
       
    def __createNewCpacsFile(self):
        '''
        closes all documents and creates new empty cpacs temporary file   
        '''        
        idict = self.popUpWidget.fire_submitInput()
        self.tixi.closeAllDocuments()
        self.tixi.create('cpacs')
        self.tixi.addCpacsHeader(idict['name'], idict['creator'], idict['version'], idict['description'], idict['cpacsVersion'])
        self.tixi.saveDocument(Config.path_cpacs_tmp_file)
        self.loadFile(Config.path_cpacs_tmp_file)
        self.__resetPopUpWidget()
        
    def __resetPopUpWidget(self):
        self.popUpWidget.close()
        self.popUpWidget = None    
        self.setEnabled(True)
    
    
    def fireComment(self):  
        '''
        inserts open respective closing tag before and after a selected text. 
        '''
        tc = self.editor.textCursor()

        tc.beginEditBlock()
        tc.setPosition(self.editor.textCursor().selectionStart())
        tc.insertText("<!--")
        
        tc.setPosition(self.editor.textCursor().selectionEnd())
        tc.insertText("-->")  
        tc.endEditBlock()      


    def fireUnComment(self):
        '''
        removes open respective closing tag before and after a selected text. 
        '''        
        tc = self.editor.textCursor()
        selectTxt = tc.selectedText()
        
        if selectTxt.find('<!--') != -1 : 
            if selectTxt.rfind('-->') != -1 :
                selectTxt = selectTxt.replace('<!--', '', 1)
                selectTxt = self.__rreplace(selectTxt, '-->' , '', 1)
                tc.insertText(selectTxt)
            else:
                QMessageBox.about(self, "error", "no open tag (%s) in selection" % ('-->')) 
        else:
            QMessageBox.about(self, "error", "no close tag (%s) in selection" % ('<!--')) 
        

    def fireSearchView(self):
        '''
        show and hide searchbox and buttons
        '''        
        if self.searchbox.isFocused() :
            self.searchbox.hide()
            self.button1.hide()
            self.button2.hide()
            self.label1.hide()
            self.fontsizeSpinBox.hide()
        else :
            self.searchbox.show()
            self.button1.show()
            self.button2.show()
            self.label1.show()
            self.fontsizeSpinBox.show()
            self.searchbox.setFocus()

    def keyPressEvent(self,event):
        '''
        handle for searching strings by pressing enter key
        '''        
        if self.searchbox.isFocused() and event.key() == Qt.Key_Return :            
            self.fire_search_foreward()   
   
    # ======================================================================================================================
    # utilities
    # ======================================================================================================================
    def __strRemoveReverseToChar(self, s, c):
        return self.__rm_rec(s, c)
    
    def __rm_rec(self, s, c):
        if s == "" :
            return ""
        elif s[-1] == c :
            return s[:-1]
        else :
            return self.__rm_rec(s[:-1], c)     
    
    def __rreplace(self, s, old, new, occurrence):
        '''
        reverse string replace function
        @param s: source string
        @param old: char to be replaced
        @param new: new char 
        @param occurrence: only the given count occurrences are replaced.
        ''' 
        li = s.rsplit(old, occurrence)
        return new.join(li)   
Exemplo n.º 5
0
class ScriptSetVal(QMainWindow):
    def __init__(self, tabID, subWinHandle, parent=None):
        super(ScriptSetVal, self).__init__(parent)
        self.tabID = tabID
        self.subWinHandle = subWinHandle
        self.tableHandle = subWinHandle.widget().centralWidget()
        self.initUI()
        self.initToolBar()
        self.initDocker()

    def initUI(self):
        self.t = QTextEdit()
        self.initFont()
        self.setCentralWidget(self.t)
        self.setGeometry(QRect(200, 200, 410, 610))
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.show()

    def initToolBar(self):
        self.scriptbar = QToolBar('plot options')
        self.addToolBar(Qt.BottomToolBarArea, self.scriptbar)
        scriptAction = QAction('set script', self)
        self.scriptbar.addAction(scriptAction)
        scriptAction.triggered.connect(self.RelectRng)

    def initFont(self):
        self.tabStop = 4
        self.font = QFont('Courier')
        self.metrics = QFontMetrics(self.font)
        self.t.setTabStopWidth(self.tabStop * self.metrics.width(' '))
        self.font.setStyleHint(QFont.Monospace)
        self.font.setFixedPitch(True)
        self.font.setPointSize(12)
        self.p = self.t.palette()
        self.p.setColor(QPalette.Base, QColor(0, 0, 0))
        self.p.setColor(QPalette.Text, QColor(255, 255, 255))
        self.t.setPalette(self.p)
        self.t.setFont(self.font)
        self.highlighter = Highlighter(self.t.document())

    def initDocker(self):
        self.elog = QTextEdit()
        self.elogDockWidget = QDockWidget("  ::  error log ::", self)
        self.elogDockWidget.setFeatures(QDockWidget.DockWidgetMovable)
        self.elogDockWidget.setAllowedAreas(Qt.TopDockWidgetArea
                                            and Qt.BottomDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.elogDockWidget)
        self.elogDockWidget.setWidget(self.elog)
        self.p = self.elog.palette()
        self.p.setColor(QPalette.Base, QColor(0, 0, 0))
        self.p.setColor(QPalette.Text, QColor(255, 0, 0))
        self.elog.setPalette(self.p)
        self.elog.setReadOnly(True)

    def RelectRng(self):
        try:
            self.selectAry = []
            if len(self.tableHandle.selectedRanges()) != 0:
                for i in range(len(self.tableHandle.selectedRanges())):
                    self.leftCol = self.tableHandle.selectedRanges(
                    )[i].leftColumn()
                    self.colCount = self.tableHandle.selectedRanges(
                    )[i].columnCount()
                    for currentCol in range(self.leftCol,
                                            self.leftCol + self.colCount):
                        self.selectAry.append(currentCol)
                self.leftCol = self.tableHandle.selectedRanges()[0].leftColumn(
                )
                self.colCount = self.tableHandle.selectedRanges(
                )[0].columnCount()
                self.topRow = self.tableHandle.selectedRanges()[0].topRow()
                self.rowCount = self.tableHandle.selectedRanges()[0].rowCount()

                rows = []
                cols = []
                for i in range(self.topRow, self.topRow + self.rowCount, 1):
                    rows.append(i)
                for i in range(self.leftCol, self.leftCol + self.colCount, 1):
                    cols.append(i)

                try:
                    exec(self.t.toPlainText())
                except Exception, e:
                    self.elog.moveCursor(QTextCursor.End)
                    self.elog.textCursor().insertHtml(
                        '<span style="color:#FF0000">Error: ' + str(e) +
                        '</span><br>')

                    print str(e)
            else:
class ScriptSetVal(QMainWindow):
    def __init__(self, tabID, subWinHandle, parent=None):
        super(ScriptSetVal,  self).__init__(parent)
        self.tabID = tabID    
        self.subWinHandle = subWinHandle
        self.tableHandle  = subWinHandle.widget().centralWidget()
        self.initUI()
        self.initToolBar()
        self.initDocker()
        
    def initUI(self): 
        self.t = QTextEdit()
        self.initFont()
        self.setCentralWidget(self.t)
        self.setGeometry(QRect(200, 200, 410, 610))
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.show()
    
    def initToolBar(self):
        self.scriptbar    = QToolBar('plot options') 
        self.addToolBar( Qt.BottomToolBarArea , self.scriptbar)
        scriptAction = QAction('set script', self)
        self.scriptbar.addAction(scriptAction)
        scriptAction.triggered.connect(self.RelectRng)

    def initFont(self):
        self.tabStop = 4
        self.font = QFont('Courier')
        self.metrics = QFontMetrics(self.font)
        self.t.setTabStopWidth(self.tabStop * self.metrics.width(' '));
        self.font.setStyleHint(QFont.Monospace);
        self.font.setFixedPitch(True);
        self.font.setPointSize(12)
        self.p = self.t.palette()
        self.p.setColor(QPalette.Base, QColor(0, 0, 0))
        self.p.setColor(QPalette.Text, QColor(255, 255, 255))
        self.t.setPalette(self.p)
        self.t.setFont(self.font)
        self.highlighter = Highlighter(self.t.document())

    def initDocker(self):
        self.elog = QTextEdit()
        self.elogDockWidget = QDockWidget("  ::  error log ::", self)
        self.elogDockWidget.setFeatures(QDockWidget.DockWidgetMovable)
        self.elogDockWidget.setAllowedAreas(Qt.TopDockWidgetArea and Qt.BottomDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.elogDockWidget)
        self.elogDockWidget.setWidget(self.elog)
        self.p = self.elog.palette()
        self.p.setColor(QPalette.Base, QColor(0, 0, 0))
        self.p.setColor(QPalette.Text, QColor(255, 0, 0))
        self.elog.setPalette(self.p)
        self.elog.setReadOnly(True)

          

    def RelectRng(self):
        try:
            self.selectAry = []
            if len(self.tableHandle.selectedRanges()) != 0:
                for i in range( len(self.tableHandle.selectedRanges())):
                    self.leftCol  = self.tableHandle.selectedRanges()[i].leftColumn()
                    self.colCount = self.tableHandle.selectedRanges()[i].columnCount()
                    for currentCol in range( self.leftCol, self.leftCol + self.colCount ):
                        self.selectAry.append( currentCol )
                self.leftCol  = self.tableHandle.selectedRanges()[0].leftColumn()
                self.colCount = self.tableHandle.selectedRanges()[0].columnCount()
                self.topRow   = self.tableHandle.selectedRanges()[0].topRow()
                self.rowCount = self.tableHandle.selectedRanges()[0].rowCount()
                
                rows = []
                cols = []
                for i in range(self.topRow,  self.topRow  + self.rowCount, 1):
                    rows.append(i)
                for i in range(self.leftCol, self.leftCol + self.colCount, 1):
                    cols.append(i)

                try:
                    exec(self.t.toPlainText())
                except Exception, e:
                    self.elog.moveCursor(QTextCursor.End)
                    self.elog.textCursor().insertHtml('<span style="color:#FF0000">Error: '+str(e)+'</span><br>')
                    

                    print str(e)
            else: