class TemplateMultipleVariablesDialog(QDialog):
    """
    Class implementing a dialog for entering multiple template variables.
    """

    def __init__(self, variables, parent=None):
        """
        Constructor
        
        @param variables list of template variable names (list of strings)
        @param parent parent widget of this dialog (QWidget)
        """
        super(TemplateMultipleVariablesDialog, self).__init__(parent)

        self.TemplateMultipleVariablesDialogLayout = QVBoxLayout(self)
        self.TemplateMultipleVariablesDialogLayout.setContentsMargins(6, 6, 6, 6)
        self.TemplateMultipleVariablesDialogLayout.setSpacing(6)
        self.TemplateMultipleVariablesDialogLayout.setObjectName("TemplateMultipleVariablesDialogLayout")
        self.setLayout(self.TemplateMultipleVariablesDialogLayout)

        # generate the scrollarea
        self.variablesView = QScrollArea(self)
        self.variablesView.setObjectName("variablesView")
        self.TemplateMultipleVariablesDialogLayout.addWidget(self.variablesView)

        self.variablesView.setWidgetResizable(True)
        self.variablesView.setFrameStyle(QFrame.NoFrame)

        self.top = QWidget(self)
        self.variablesView.setWidget(self.top)
        self.grid = QGridLayout(self.top)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.grid.setSpacing(6)
        self.top.setLayout(self.grid)

        # populate the scrollarea with labels and text edits
        self.variablesEntries = {}
        row = 0
        for var in variables:
            label = QLabel("{0}:".format(var), self.top)
            self.grid.addWidget(label, row, 0, Qt.Alignment(Qt.AlignTop))
            if var.find(":") >= 0:
                formatStr = var[1:-1].split(":")[1]
                if formatStr in ["ml", "rl"]:
                    t = QTextEdit(self.top)
                    t.setTabChangesFocus(True)
                else:
                    t = QLineEdit(self.top)
            else:
                t = QLineEdit(self.top)
            self.grid.addWidget(t, row, 1)
            self.variablesEntries[var] = t
            row += 1
        # add a spacer to make the entries aligned at the top
        spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.grid.addItem(spacer, row, 1)
        self.variablesEntries[variables[0]].setFocus()
        self.top.adjustSize()

        # generate the buttons
        layout1 = QHBoxLayout()
        layout1.setContentsMargins(0, 0, 0, 0)
        layout1.setSpacing(6)
        layout1.setObjectName("layout1")

        spacer1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout1.addItem(spacer1)

        self.okButton = QPushButton(self)
        self.okButton.setObjectName("okButton")
        self.okButton.setDefault(True)
        layout1.addWidget(self.okButton)

        self.cancelButton = QPushButton(self)
        self.cancelButton.setObjectName("cancelButton")
        layout1.addWidget(self.cancelButton)

        spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout1.addItem(spacer2)

        self.TemplateMultipleVariablesDialogLayout.addLayout(layout1)

        # set the texts of the standard widgets
        self.setWindowTitle(self.tr("Enter Template Variables"))
        self.okButton.setText(self.tr("&OK"))
        self.cancelButton.setText(self.tr("&Cancel"))

        # polish up the dialog
        self.resize(QSize(400, 480).expandedTo(self.minimumSizeHint()))

        self.okButton.clicked.connect(self.accept)
        self.cancelButton.clicked.connect(self.reject)

    def getVariables(self):
        """
        Public method to get the values for all variables.
        
        @return dictionary with the variable as a key and its value (string)
        """
        values = {}
        for var, textEdit in list(self.variablesEntries.items()):
            try:
                values[var] = textEdit.text()
            except AttributeError:
                values[var] = textEdit.toPlainText()
        return values
class PyRegExpWizardCharactersDialog(
        QDialog, Ui_PyRegExpWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    specialChars = {
        4: "\\a",
        5: "\\f",
        6: "\\n",
        7: "\\r",
        8: "\\t",
        9: "\\v"
    }
    
    predefinedClasses = ["\\s", "\\S", "\\w", "\\W", "\\d", "\\D"]
    
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent parent widget (QWidget)
        """
        super(PyRegExpWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.comboItems = []
        self.singleComboItems = []      # these are in addition to the above
        self.comboItems.append(self.tr("Normal character"))
        self.comboItems.append(
            self.tr("Unicode character in hexadecimal notation"))
        self.comboItems.append(
            self.tr("Unicode character in octal notation"))
        self.singleComboItems.append(self.tr("---"))
        self.singleComboItems.append(self.tr("Bell character (\\a)"))
        self.singleComboItems.append(self.tr("Page break (\\f)"))
        self.singleComboItems.append(self.tr("Line feed (\\n)"))
        self.singleComboItems.append(self.tr("Carriage return (\\r)"))
        self.singleComboItems.append(self.tr("Horizontal tabulator (\\t)"))
        self.singleComboItems.append(self.tr("Vertical tabulator (\\v)"))
        
        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
        
        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)
        
        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()
        
        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(
            self.tr("Additional Entries"), self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
        
        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)
        
        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()
        
        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(
            self.tr("Additional Entries"), self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)
        
    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        cb1.addItems(self.comboItems)
        cb1.addItems(self.singleComboItems)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        cb2.addItems(self.comboItems)
        cb2.addItems(self.singleComboItems)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.singlesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()
        
        self.singlesItemsBox.adjustSize()
        
        self.singlesEntries.append([cb1, le1])
        self.singlesEntries.append([cb2, le2])
        
    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        cb1.addItems(self.comboItems)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        
        hbox.show()
        
        self.rangesItemsBox.adjustSize()
        
        self.rangesEntries.append([cb1, le1, le2])
        
    def __performSelectedAction(self, index, lineedit):
        """
        Private method performing some actions depending on the input.
        
        @param index selected list index (integer)
        @param lineedit line edit widget to act on (QLineEdit)
        """
        if index < 3:
            lineedit.setEnabled(True)
            if index == 0:
                lineedit.setValidator(self.charValidator)
            elif index == 1:
                lineedit.setValidator(self.hexValidator)
            elif index == 2:
                lineedit.setValidator(self.octValidator)
        elif index > 3:
            lineedit.setEnabled(False)
        lineedit.clear()
        
    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                self.__performSelectedAction(index, entriesList[1])
                break
        
    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                self.__performSelectedAction(index, entriesList[1])
                self.__performSelectedAction(index, entriesList[2])
                break
        
    def __formatCharacter(self, index, char):
        """
        Private method to format the characters entered into the dialog.
        
        @param index selected list index (integer)
        @param char character string enetered into the dialog (string)
        @return formated character string (string)
        """
        if index == 0:
            return char
        elif index == 1:
            return "\\x{0}".format(char.lower())
        elif index == 2:
            return "\\0{0}".format(char)
        else:
            try:
                return self.specialChars[index]
            except KeyError:
                return ""
        
    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""
        
        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"
            
        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
            
        # single characters
        for entrieslist in self.singlesEntries:
            index = entrieslist[0].currentIndex()
            char = entrieslist[1].text()
            regexp += self.__formatCharacter(index, char)
        
        # character ranges
        for entrieslist in self.rangesEntries:
            if entrieslist[1].text() == "" or \
               entrieslist[2].text() == "":
                continue
            index = entrieslist[0].currentIndex()
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(
                self.__formatCharacter(index, char1),
                self.__formatCharacter(index, char2))
        
        if regexp:
            if (len(regexp) == 2 and
                (regexp in self.predefinedClasses or
                 regexp in self.specialChars)) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
Esempio n. 3
0
class PixmapDiagram(E5MainWindow):
    """
    Class implementing a dialog showing a pixmap.
    """
    ZoomLevels = [
        1, 3, 5, 7, 9,
        10, 20, 30, 50, 67, 80, 90,
        100,
        110, 120, 133, 150, 170, 200, 240, 300, 400,
        500, 600, 700, 800, 900, 1000,
    ]
    ZoomLevelDefault = 100
    
    def __init__(self, pixmap, parent=None, name=None):
        """
        Constructor
        
        @param pixmap filename of a graphics file to show (string)
        @param parent parent widget of the view (QWidget)
        @param name name of the view widget (string)
        """
        super(PixmapDiagram, self).__init__(parent)
        if name:
            self.setObjectName(name)
        else:
            self.setObjectName("PixmapDiagram")
        self.setWindowTitle(self.tr("Pixmap-Viewer"))
        
        self.pixmapLabel = QLabel()
        self.pixmapLabel.setObjectName("pixmapLabel")
        self.pixmapLabel.setBackgroundRole(QPalette.Base)
        self.pixmapLabel.setSizePolicy(
            QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.pixmapLabel.setScaledContents(True)
        
        self.pixmapView = QScrollArea()
        self.pixmapView.setObjectName("pixmapView")
        self.pixmapView.setBackgroundRole(QPalette.Dark)
        self.pixmapView.setWidget(self.pixmapLabel)
        
        self.setCentralWidget(self.pixmapView)
        
        self.__zoomWidget = E5ZoomWidget(
            UI.PixmapCache.getPixmap("zoomOut.png"),
            UI.PixmapCache.getPixmap("zoomIn.png"),
            UI.PixmapCache.getPixmap("zoomReset.png"), self)
        self.statusBar().addPermanentWidget(self.__zoomWidget)
        self.__zoomWidget.setMapping(
            PixmapDiagram.ZoomLevels, PixmapDiagram.ZoomLevelDefault)
        self.__zoomWidget.valueChanged.connect(self.__doZoom)
        
        # polish up the dialog
        self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint()))
        
        self.pixmapfile = pixmap
        self.status = self.__showPixmap(self.pixmapfile)
        
        self.__initActions()
        self.__initContextMenu()
        self.__initToolBars()
        
        self.grabGesture(Qt.PinchGesture)
    
    def __initActions(self):
        """
        Private method to initialize the view actions.
        """
        self.closeAct = \
            QAction(UI.PixmapCache.getIcon("close.png"),
                    self.tr("Close"), self)
        self.closeAct.triggered.connect(self.close)
        
        self.printAct = \
            QAction(UI.PixmapCache.getIcon("print.png"),
                    self.tr("Print"), self)
        self.printAct.triggered.connect(self.__printDiagram)
        
        self.printPreviewAct = \
            QAction(UI.PixmapCache.getIcon("printPreview.png"),
                    self.tr("Print Preview"), self)
        self.printPreviewAct.triggered.connect(self.__printPreviewDiagram)
        
    def __initContextMenu(self):
        """
        Private method to initialize the context menu.
        """
        self.__menu = QMenu(self)
        self.__menu.addAction(self.closeAct)
        self.__menu.addSeparator()
        self.__menu.addAction(self.printPreviewAct)
        self.__menu.addAction(self.printAct)
        
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.__showContextMenu)
        
    def __showContextMenu(self, coord):
        """
        Private slot to show the context menu of the listview.
        
        @param coord the position of the mouse pointer (QPoint)
        """
        self.__menu.popup(self.mapToGlobal(coord))
        
    def __initToolBars(self):
        """
        Private method to populate the toolbars with our actions.
        """
        self.windowToolBar = QToolBar(self.tr("Window"), self)
        self.windowToolBar.setIconSize(UI.Config.ToolBarIconSize)
        self.windowToolBar.addAction(self.closeAct)
        
        self.graphicsToolBar = QToolBar(self.tr("Graphics"), self)
        self.graphicsToolBar.setIconSize(UI.Config.ToolBarIconSize)
        self.graphicsToolBar.addAction(self.printPreviewAct)
        self.graphicsToolBar.addAction(self.printAct)
        
        self.addToolBar(Qt.TopToolBarArea, self.windowToolBar)
        self.addToolBar(Qt.TopToolBarArea, self.graphicsToolBar)
        
    def __showPixmap(self, filename):
        """
        Private method to show a file.
        
        @param filename name of the file to be shown (string)
        @return flag indicating success (boolean)
        """
        image = QImage(filename)
        if image.isNull():
            E5MessageBox.warning(
                self,
                self.tr("Pixmap-Viewer"),
                self.tr(
                    """<p>The file <b>{0}</b> cannot be displayed."""
                    """ The format is not supported.</p>""").format(filename))
            return False
        
        self.pixmapLabel.setPixmap(QPixmap.fromImage(image))
        self.pixmapLabel.adjustSize()
        return True
        
    def getDiagramName(self):
        """
        Public method to retrieve a name for the diagram.
        
        @return name for the diagram
        """
        return self.pixmapfile
        
    def getStatus(self):
        """
        Public method to retrieve the status of the canvas.
        
        @return flag indicating a successful pixmap loading (boolean)
        """
        return self.status
    
    def wheelEvent(self, evt):
        """
        Protected method to handle wheel events.
        
        @param evt reference to the wheel event (QWheelEvent)
        """
        if evt.modifiers() & Qt.ControlModifier:
            if qVersion() >= "5.0.0":
                delta = evt.angleDelta().y()
            else:
                delta = evt.delta()
            if delta < 0:
                self.__zoomOut()
            else:
                self.__zoomIn()
            evt.accept()
            return
        
        super(PixmapDiagram, self).wheelEvent(evt)
    
    def event(self, evt):
        """
        Public method handling events.
        
        @param evt reference to the event (QEvent)
        @return flag indicating, if the event was handled (boolean)
        """
        if evt.type() == QEvent.Gesture:
            self.gestureEvent(evt)
            return True
        
        return super(PixmapDiagram, self).event(evt)
    
    def gestureEvent(self, evt):
        """
        Protected method handling gesture events.
        
        @param evt reference to the gesture event (QGestureEvent
        """
        pinch = evt.gesture(Qt.PinchGesture)
        if pinch:
            if pinch.state() == Qt.GestureStarted:
                pinch.setScaleFactor(self.__zoom() / 100)
            else:
                self.__doZoom(int(pinch.scaleFactor() * 100))
            evt.accept()
    
    ###########################################################################
    ## Private menu handling methods below.
    ###########################################################################
    
    def __adjustScrollBar(self, scrollBar, factor):
        """
        Private method to adjust a scrollbar by a certain factor.
        
        @param scrollBar reference to the scrollbar object (QScrollBar)
        @param factor factor to adjust by (float)
        """
        scrollBar.setValue(int(factor * scrollBar.value()
                           + ((factor - 1) * scrollBar.pageStep() / 2)))
        
    def __levelForZoom(self, zoom):
        """
        Private method determining the zoom level index given a zoom factor.
        
        @param zoom zoom factor (integer)
        @return index of zoom factor (integer)
        """
        try:
            index = PixmapDiagram.ZoomLevels.index(zoom)
        except ValueError:
            for index in range(len(PixmapDiagram.ZoomLevels)):
                if zoom <= PixmapDiagram.ZoomLevels[index]:
                    break
        return index
    
    def __doZoom(self, value):
        """
        Private method to set the zoom value in percent.
        
        @param value zoom value in percent (integer)
        """
        oldValue = self.__zoom()
        if value != oldValue:
            self.pixmapLabel.resize(
                value / 100 * self.pixmapLabel.pixmap().size())
            
            factor = value / oldValue
            self.__adjustScrollBar(
                self.pixmapView.horizontalScrollBar(), factor)
            self.__adjustScrollBar(
                self.pixmapView.verticalScrollBar(), factor)
            
            self.__zoomWidget.setValue(value)
        
    def __zoomIn(self):
        """
        Private method to zoom into the pixmap.
        """
        index = self.__levelForZoom(self.__zoom())
        if index < len(PixmapDiagram.ZoomLevels) - 1:
            self.__doZoom(PixmapDiagram.ZoomLevels[index + 1])
        
    def __zoomOut(self):
        """
        Private method to zoom out of the pixmap.
        """
        index = self.__levelForZoom(self.__zoom())
        if index > 0:
            self.__doZoom(PixmapDiagram.ZoomLevels[index - 1])
        
    def __zoomReset(self):
        """
        Private method to reset the zoom value.
        """
        self.__doZoom(PixmapDiagram.ZoomLevels[PixmapDiagram.ZoomLevelDefault])
        
    def __zoom(self):
        """
        Private method to get the current zoom factor in percent.
        
        @return current zoom factor in percent (integer)
        """
        return int(self.pixmapLabel.width() /
                   self.pixmapLabel.pixmap().width() * 100.0)
        
    def __printDiagram(self):
        """
        Private slot called to print the diagram.
        """
        printer = QPrinter(mode=QPrinter.ScreenResolution)
        printer.setFullPage(True)
        if Preferences.getPrinter("ColorMode"):
            printer.setColorMode(QPrinter.Color)
        else:
            printer.setColorMode(QPrinter.GrayScale)
        if Preferences.getPrinter("FirstPageFirst"):
            printer.setPageOrder(QPrinter.FirstPageFirst)
        else:
            printer.setPageOrder(QPrinter.LastPageFirst)
        printer.setPrinterName(Preferences.getPrinter("PrinterName"))
        
        printDialog = QPrintDialog(printer, self)
        if printDialog.exec_():
            self.__print(printer)
        
    def __printPreviewDiagram(self):
        """
        Private slot called to show a print preview of the diagram.
        """
        from PyQt5.QtPrintSupport import QPrintPreviewDialog
        
        printer = QPrinter(mode=QPrinter.ScreenResolution)
        printer.setFullPage(True)
        if Preferences.getPrinter("ColorMode"):
            printer.setColorMode(QPrinter.Color)
        else:
            printer.setColorMode(QPrinter.GrayScale)
        if Preferences.getPrinter("FirstPageFirst"):
            printer.setPageOrder(QPrinter.FirstPageFirst)
        else:
            printer.setPageOrder(QPrinter.LastPageFirst)
        printer.setPageMargins(
            Preferences.getPrinter("LeftMargin") * 10,
            Preferences.getPrinter("TopMargin") * 10,
            Preferences.getPrinter("RightMargin") * 10,
            Preferences.getPrinter("BottomMargin") * 10,
            QPrinter.Millimeter
        )
        printer.setPrinterName(Preferences.getPrinter("PrinterName"))
        
        preview = QPrintPreviewDialog(printer, self)
        preview.paintRequested[QPrinter].connect(self.__print)
        preview.exec_()
        
    def __print(self, printer):
        """
        Private slot to the actual printing.
        
        @param printer reference to the printer object (QPrinter)
        """
        painter = QPainter()
        painter.begin(printer)

        # calculate margin and width of printout
        font = QFont("times", 10)
        painter.setFont(font)
        fm = painter.fontMetrics()
        fontHeight = fm.lineSpacing()
        marginX = printer.pageRect().x() - printer.paperRect().x()
        marginX = Preferences.getPrinter("LeftMargin") * \
            int(printer.resolution() / 2.54) - marginX
        marginY = printer.pageRect().y() - printer.paperRect().y()
        marginY = Preferences.getPrinter("TopMargin") * \
            int(printer.resolution() / 2.54) - marginY

        width = printer.width() - marginX - \
            Preferences.getPrinter("RightMargin") * \
            int(printer.resolution() / 2.54)
        height = printer.height() - fontHeight - 4 - marginY - \
            Preferences.getPrinter("BottomMargin") * \
            int(printer.resolution() / 2.54)

        # write a foot note
        s = self.tr("Diagram: {0}").format(self.getDiagramName())
        tc = QColor(50, 50, 50)
        painter.setPen(tc)
        painter.drawRect(marginX, marginY, width, height)
        painter.drawLine(marginX, marginY + height + 2,
                         marginX + width, marginY + height + 2)
        painter.setFont(font)
        painter.drawText(marginX, marginY + height + 4, width,
                         fontHeight, Qt.AlignRight, s)

        # render the diagram
        size = self.pixmapLabel.pixmap().size()
        size.scale(QSize(width - 10, height - 10),  # 5 px inner margin
                   Qt.KeepAspectRatio)
        painter.setViewport(marginX + 5, marginY + 5,
                            size.width(), size.height())
        painter.setWindow(self.pixmapLabel.pixmap().rect())
        painter.drawPixmap(0, 0, self.pixmapLabel.pixmap())
        painter.end()
Esempio n. 4
0
class UgMgmt(QWidget):
    def __init__(self, gui):
        super(UgMgmt, self).__init__()

        self.ui = gui
        self.tran = self.ui.tran
        self.parser = self.ui.configparser
        self.config = self.ui.config
        self.setObjectName("ugmtab")

        self.layout = QGridLayout(self)
        self.layout.setObjectName("ugmtab_layout")

        # new button
        self.button_new = QPushButton(self)
        self.button_new.setObjectName("ugmtab_button_new")
        self.button_new.setText(self.tran.get_text(self.button_new.objectName()))

        # delete button
        self.button_delete = QPushButton(self)
        self.button_delete.setObjectName("ugmtab_button_delete")
        self.button_delete.setText(self.tran.get_text(self.button_delete.objectName()))

        # edit button
        self.button_edit = QPushButton(self)
        self.button_edit.setObjectName("ugmtab_button_edit")
        self.button_edit.setText(self.tran.get_text(self.button_edit.objectName()))

        # arrow left to right
        self.button_ltrarrow = QPushButton(self)
        self.button_ltrarrow.setObjectName("ugmtab_button_arrow_ltr")
        self.button_ltrarrow.setIcon(QIcon("./resources/arrow_ltr.png"))

        # arrow right to left
        self.button_rtlarrow = QPushButton(self)
        self.button_rtlarrow.setObjectName("ugmtab_button_arrow_rtl")
        self.button_rtlarrow.setIcon(QIcon("./resources/arrow_rtl.png"))

        # setup the combo box
        self.combobox = QComboBox(self)
        self.combobox.setObjectName("ugmtab_combobox")

        # setup the left label
        self.label_left = QLabel(self)
        self.label_left.setObjectName("ugmtab_label_left")

        # setup the middle label
        self.label_middle = QLabel(self)
        self.label_middle.setObjectName("ugmtab_label_middle")

        # setup the right label
        self.label_right = QLabel(self)
        self.label_right.setObjectName("ugmtab_label_right")

        # setup the left scoll area
        self.scroll_left = QScrollArea(self)
        self.scroll_left.setWidgetResizable(True)
        self.scroll_left.setObjectName("ugmtab_scroll_left")

        # setup the widget that holds the contents of the left scroll area
        self.scroll_left_content = QWidget()
        self.scroll_left_content.setGeometry(QRect(0, 0, 150, 80))
        self.scroll_left_content.setObjectName("ugmtab_scroll_left_content")
        self.scroll_left.setWidget(self.scroll_left_content)

        # setup the middle scroll area
        self.scroll_middle = QScrollArea(self)
        self.scroll_middle.setWidgetResizable(True)
        self.scroll_middle.setObjectName("ugmtab_scroll_middle")

        # setup the widget that holds the contents of the middle scroll area
        self.scroll_middle_content = QWidget()
        self.scroll_middle_content.setGeometry(QRect(0, 0, 150, 80))
        self.scroll_middle_content.setObjectName("ugmtab_scroll_middle_content")
        self.scroll_middle.setWidget(self.scroll_middle_content)

        # setup the right scroll area
        self.scroll_right = QScrollArea(self)
        self.scroll_right.setWidgetResizable(True)
        self.scroll_right.setObjectName("ugmtab_scroll_right")

        # setup the widget that holds the contents of the middle scroll area
        self.scroll_right_content = QWidget()
        self.scroll_right_content.setGeometry(QRect(0, 0, 150, 80))
        self.scroll_right_content.setObjectName("ugmtab_scroll_right_content")
        self.scroll_right.setWidget(self.scroll_right_content)

        # add the components to the top level layout of the tab
        self.layout.addWidget(self.button_new, 0, 0, 1, 1)
        self.layout.addWidget(self.button_delete, 0, 1, 1, 1)
        self.layout.addWidget(self.button_edit, 0, 2, 1, 1)
        self.layout.addWidget(self.combobox, 0, 6, 1, 2)
        self.layout.addWidget(self.label_left, 1, 0, 1, 2)
        self.layout.addWidget(self.label_middle, 1, 3, 1, 2)
        self.layout.addWidget(self.label_right, 1, 5, 1, 2)
        self.layout.addWidget(self.scroll_left, 2, 0, 4, 2)
        self.layout.addWidget(self.scroll_middle, 2, 3, 4, 2)
        self.layout.addWidget(self.scroll_right, 2, 6, 4, 2)
        self.layout.addWidget(self.button_ltrarrow, 3, 5, 1, 1)
        self.layout.addWidget(self.button_rtlarrow, 4, 5, 1, 1)
class QRegularExpressionWizardCharactersDialog(
        QDialog, Ui_QRegularExpressionWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(QRegularExpressionWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.__initCharacterSelectors()
        
        self.comboItems = []
        self.singleComboItems = []      # these are in addition to the above
        self.comboItems.append((self.tr("Normal character"), "-c"))
        self.comboItems.append((self.tr(
            "Unicode character in hexadecimal notation"), "-h"))
        self.comboItems.append((self.tr(
            "ASCII/Latin1 character in octal notation"), "-o"))
        self.singleComboItems.extend([
            ("---", "-i"),
            (self.tr("Bell character (\\a)"), "\\a"),
            (self.tr("Escape character (\\e)"), "\\e"),
            (self.tr("Page break (\\f)"), "\\f"),
            (self.tr("Line feed (\\n)"), "\\n"),
            (self.tr("Carriage return (\\r)"), "\\r"),
            (self.tr("Horizontal tabulator (\\t)"), "\\t"),
            ("---", "-i"),
            (self.tr("Character Category"), "-ccp"),
            (self.tr("Special Character Category"), "-csp"),
            (self.tr("Character Block"), "-cbp"),
            (self.tr("POSIX Named Set"), "-psp"),
            (self.tr("Not Character Category"), "-ccn"),
            (self.tr("Not Character Block"), "-cbn"),
            (self.tr("Not Special Character Category"), "-csn"),
            (self.tr("Not POSIX Named Set"), "-psn"),
        ])
        
        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
        
        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)
        
        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBox.setMinimumWidth(1000)
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()
        
        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(
            self.tr("Additional Entries"), self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
        
        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)
        
        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBox.setMinimumWidth(1000)
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()
        
        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(
            self.tr("Additional Entries"), self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)
    
    def __initCharacterSelectors(self):
        """
        Private method to initialize the W3C character selector entries.
        """
        self.__characterCategories = (
            # display name                                  code
            (self.tr("Letter, Any"), "L"),
            (self.tr("Letter, Lower case"), "Ll"),
            (self.tr("Letter, Modifier"), "Lm"),
            (self.tr("Letter, Other"), "Lo"),
            (self.tr("Letter, Title case"), "Lt"),
            (self.tr("Letter, Upper case"), "Lu"),
            (self.tr("Letter, Lower, Upper or Title"), "L&"),
            (self.tr("Mark, Any"), "M"),
            (self.tr("Mark, Spacing"), "Mc"),
            (self.tr("Mark, Enclosing"), "Me"),
            (self.tr("Mark, Non-spacing"), "Mn"),
            (self.tr("Number, Any"), "N"),
            (self.tr("Number, Decimal"), "Nd"),
            (self.tr("Number, Letter"), "Nl"),
            (self.tr("Number, Other"), "No"),
            (self.tr("Punctuation, Any"), "P"),
            (self.tr("Punctuation, Connector"), "Pc"),
            (self.tr("Punctuation, Dash"), "Pd"),
            (self.tr("Punctuation, Close"), "Pe"),
            (self.tr("Punctuation, Final"), "Pf"),
            (self.tr("Punctuation, Initial"), "Pi"),
            (self.tr("Punctuation, Other"), "Po"),
            (self.tr("Punctuation, Open"), "Ps"),
            (self.tr("Symbol, Any"), "S"),
            (self.tr("Symbol, Currency"), "Sc"),
            (self.tr("Symbol, Modifier"), "Sk"),
            (self.tr("Symbol, Mathematical"), "Sm"),
            (self.tr("Symbol, Other"), "So"),
            (self.tr("Separator, Any"), "Z"),
            (self.tr("Separator, Line"), "Zl"),
            (self.tr("Separator, Paragraph"), "Zp"),
            (self.tr("Separator, Space"), "Zs"),
            (self.tr("Other, Any"), "C"),
            (self.tr("Other, Control"), "Cc"),
            (self.tr("Other, Format"), "Cf"),
            (self.tr("Other, Unassigned"), "Cn"),
            (self.tr("Other, Private Use"), "Co"),
            (self.tr("Other, Surrogat"), "Cn"),
        )
        
        self.__specialCharacterCategories = (
            # display name                           code
            (self.tr("Alphanumeric"), "Xan"),
            (self.tr("POSIX Space"), "Xps"),
            (self.tr("Perl Space"), "Xsp"),
            (self.tr("Universal Character"), "Xuc"),
            (self.tr("Perl Word"), "Xan"),
        )
        
        self.__characterBlocks = (
            # display name                           code
            (self.tr("Arabic"), "Arabic"),
            (self.tr("Armenian"), "Armenian"),
            (self.tr("Avestan"), "Avestan"),
            (self.tr("Balinese"), "Balinese"),
            (self.tr("Bamum"), "Bamum"),
            (self.tr("Batak"), "Batak"),
            (self.tr("Bengali"), "Bengali"),
            (self.tr("Bopomofo"), "Bopomofo"),
            (self.tr("Brahmi"), "Brahmi"),
            (self.tr("Braille"), "Braille"),
            (self.tr("Buginese"), "Buginese"),
            (self.tr("Buhid"), "Buhid"),
            (self.tr("Canadian Aboriginal"), "Canadian_Aboriginal"),
            (self.tr("Carian"), "Carian"),
            (self.tr("Chakma"), "Chakma"),
            (self.tr("Cham"), "Cham"),
            (self.tr("Cherokee"), "Cherokee"),
            (self.tr("Common"), "Common"),
            (self.tr("Coptic"), "Coptic"),
            (self.tr("Cuneiform"), "Cuneiform"),
            (self.tr("Cypriot"), "Cypriot"),
            (self.tr("Cyrillic"), "Cyrillic"),
            (self.tr("Deseret"), "Deseret,"),
            (self.tr("Devanagari"), "Devanagari"),
            (self.tr("Egyptian Hieroglyphs"), "Egyptian_Hieroglyphs"),
            (self.tr("Ethiopic"), "Ethiopic"),
            (self.tr("Georgian"), "Georgian"),
            (self.tr("Glagolitic"), "Glagolitic"),
            (self.tr("Gothic"), "Gothic"),
            (self.tr("Greek"), "Greek"),
            (self.tr("Gujarati"), "Gujarati"),
            (self.tr("Gurmukhi"), "Gurmukhi"),
            (self.tr("Han"), "Han"),
            (self.tr("Hangul"), "Hangul"),
            (self.tr("Hanunoo"), "Hanunoo"),
            (self.tr("Hebrew"), "Hebrew"),
            (self.tr("Hiragana"), "Hiragana"),
            (self.tr("Imperial Aramaic"), "Imperial_Aramaic"),
            (self.tr("Inherited"), "Inherited"),
            (self.tr("Inscriptional Pahlavi"), "Inscriptional_Pahlavi"),
            (self.tr("Inscriptional Parthian"), "Inscriptional_Parthian"),
            (self.tr("Javanese"), "Javanese"),
            (self.tr("Kaithi"), "Kaithi"),
            (self.tr("Kannada"), "Kannada"),
            (self.tr("Katakana"), "Katakana"),
            (self.tr("Kayah Li"), "Kayah_Li"),
            (self.tr("Kharoshthi"), "Kharoshthi"),
            (self.tr("Khmer"), "Khmer"),
            (self.tr("Lao"), "Lao"),
            (self.tr("Latin"), "Latin"),
            (self.tr("Lepcha"), "Lepcha"),
            (self.tr("Limbu"), "Limbu"),
            (self.tr("Linear B"), "Linear_B"),
            (self.tr("Lisu"), "Lisu"),
            (self.tr("Lycian"), "Lycian"),
            (self.tr("Lydian"), "Lydian"),
            (self.tr("Malayalam"), "Malayalam"),
            (self.tr("Mandaic"), "Mandaic"),
            (self.tr("Meetei Mayek"), "Meetei_Mayek"),
            (self.tr("Meroitic Cursive"), "Meroitic_Cursive"),
            (self.tr("Meroitic Hieroglyphs"), "Meroitic_Hieroglyphs"),
            (self.tr("Miao"), "Miao"),
            (self.tr("Mongolian"), "Mongolian"),
            (self.tr("Myanmar"), "Myanmar"),
            (self.tr("New Tai Lue"), "New_Tai_Lue"),
            (self.tr("N'Ko"), "Nko"),
            (self.tr("Ogham"), "Ogham"),
            (self.tr("Old Italic"), "Old_Italic"),
            (self.tr("Old Persian"), "Old_Persian"),
            (self.tr("Old South Arabian"), "Old_South_Arabian"),
            (self.tr("Old Turkic"), "Old_Turkic,"),
            (self.tr("Ol Chiki"), "Ol_Chiki"),
            (self.tr("Oriya"), "Oriya"),
            (self.tr("Osmanya"), "Osmanya"),
            (self.tr("Phags-pa"), "Phags_Pa"),
            (self.tr("Phoenician"), "Phoenician"),
            (self.tr("Rejang"), "Rejang"),
            (self.tr("Runic"), "Runic"),
            (self.tr("Samaritan"), "Samaritan"),
            (self.tr("Saurashtra"), "Saurashtra"),
            (self.tr("Sharada"), "Sharada"),
            (self.tr("Shavian"), "Shavian"),
            (self.tr("Sinhala"), "Sinhala"),
            (self.tr("Sora Sompeng"), "Sora_Sompeng"),
            (self.tr("Sundanese"), "Sundanese"),
            (self.tr("Syloti Nagri"), "Syloti_Nagri"),
            (self.tr("Syriac"), "Syriac"),
            (self.tr("Tagalog"), "Tagalog"),
            (self.tr("Tagbanwa"), "Tagbanwa"),
            (self.tr("Tai Le"), "Tai_Le"),
            (self.tr("Tai Tham"), "Tai_Tham"),
            (self.tr("Tai Viet"), "Tai_Viet"),
            (self.tr("Takri"), "Takri"),
            (self.tr("Tamil"), "Tamil"),
            (self.tr("Telugu"), "Telugu"),
            (self.tr("Thaana"), "Thaana"),
            (self.tr("Thai"), "Thai"),
            (self.tr("Tibetan"), "Tibetan"),
            (self.tr("Tifinagh"), "Tifinagh"),
            (self.tr("Ugaritic"), "Ugaritic"),
            (self.tr("Vai"), "Vai"),
            (self.tr("Yi"), "Yi"),
        )
        
        self.__posixNamedSets = (
            # display name                                  code
            (self.tr("Alphanumeric"), "alnum"),
            (self.tr("Alphabetic"), "alpha"),
            (self.tr("ASCII"), "ascii"),
            (self.tr("Word Letter"), "word"),
            (self.tr("Lower Case Letter"), "lower"),
            (self.tr("Upper Case Letter"), "upper"),
            (self.tr("Decimal Digit"), "digit"),
            (self.tr("Hexadecimal Digit"), "xdigit"),
            (self.tr("Space or Tab"), "blank"),
            (self.tr("White Space"), "space"),
            (self.tr("Printing (excl. space)"), "graph"),
            (self.tr("Printing (incl. space)"), "print"),
            (self.tr("Printing (excl. alphanumeric)"), "punct"),
            (self.tr("Control Character"), "cntrl"),
        )
    
    def __populateCharTypeCombo(self, combo, isSingle):
        """
        Private method to populate a given character type selection combo box.
        
        @param combo reference to the combo box to be populated (QComboBox)
        @param isSingle flag indicating a singles combo (boolean)
        """
        for txt, value in self.comboItems:
            combo.addItem(txt, value)
        if isSingle:
            for txt, value in self.singleComboItems:
                combo.addItem(txt, value)

    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, True)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb1a = QComboBox(hbox)
        cb1a.setEditable(False)
        cb1a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb1a)
        cb1a.hide()
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        self.__populateCharTypeCombo(cb2, True)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        cb2a = QComboBox(hbox)
        cb2a.setEditable(False)
        cb2a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb2a)
        cb2a.hide()
        self.singlesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()
        
        self.singlesItemsBox.adjustSize()
        
        self.singlesEntries.append([cb1, le1, cb1a])
        self.singlesEntries.append([cb2, le2, cb2a])
    
    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, False)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        hbox.show()
        
        self.rangesItemsBox.adjustSize()
        
        self.rangesEntries.append([cb1, le1, le2])
    
    def __populateCharacterCombo(self, combo, format):
        """
        Private method to populate a character selection combo.
        
        @param combo combo box to be populated (QComboBox)
        @param format format identifier (one of "-ccp", "-ccn",
            "-cbp", "-cbn", "-csp", "-csn", "-psp", "-psn")
        """
        combo.clear()
        
        if format in ["-ccp", "-ccn"]:
            items = self.__characterCategories
        elif format in ["-csp", "-csn"]:
            items = self.__specialCharacterCategories
        elif format in ["-cbp", "-cbn"]:
            items = self.__characterBlocks
        elif format in ["-psp", "-psn"]:
            items = self.__posixNamedSets
        
        comboLen = 0
        for txt, code in items:
            combo.addItem(txt, code)
            comboLen = max(comboLen, len(txt))
        combo.setMinimumContentsLength(comboLen)
    
    def __performSelectedAction(self, format, lineedit, combo):
        """
        Private method performing some actions depending on the input.
        
        @param format format of the selected entry (string)
        @param lineedit line edit widget to act on (QLineEdit)
        @param combo combo box widget to act on (QComboBox)
        """
        if format == "-i":
            return
        
        if format in ["-c", "-h", "-o"]:
            lineedit.show()
            lineedit.setEnabled(True)
            if combo is not None:
                combo.hide()
            if format == "-c":
                lineedit.setValidator(self.charValidator)
            elif format == "-h":
                lineedit.setValidator(self.hexValidator)
            elif format == "-o":
                lineedit.setValidator(self.octValidator)
        elif format in ["-ccp", "-ccn", "-cbp", "-cbn", "-csp", "-csn",
                        "-psp", "-psn"]:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.show()
            self.__populateCharacterCombo(combo, format)
        else:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.hide()
        lineedit.clear()
    
    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(
                    format, entriesList[1], entriesList[2])
                break
    
    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1], None)
                self.__performSelectedAction(format, entriesList[2], None)
                break
    
    def __formatCharacter(self, char, format):
        """
        Private method to format the characters entered into the dialog.
        
        @param char character string entered into the dialog (string)
        @param format string giving a special format (-c, -h, -i or -o) or
            the already formatted character (string)
        @return formatted character string (string)
        """
        if format == "-c":
            return char
        elif format == "-i":
            return ""
        
        if format == "-h":
            while len(char) < 2:
                char = "0" + char
            if len(char) > 2:
                return "\\x{{{0}}}".format(char.lower())
            else:
                return "\\x{0}".format(char.lower())
        elif format == "-o":
            while len(char) < 3:
                char = "0" + char
            if len(char) > 3:
                char = char[:3]
            return "\\{0}".format(char)
        elif format in ["-ccp", "-cbp", "-csp"]:
            return "\\p{{{0}}}".format(char)
        elif format in ["-ccn", "-cbn", "-csn"]:
            return "\\P{{{0}}}".format(char)
        elif format == "-psp":
            return "[:{0}:]".format(char)
        elif format == "-psn":
            return "[:^{0}:]".format(char)
        else:
            return format
    
    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""
        
        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"
            
        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.newlineCheckBox.isChecked():
            regexp += "\\R"
        if self.nonNewlineCheckBox.isChecked():
            regexp += "\\N"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
        if self.horizontalWhitespaceCheckBox.isChecked():
            regexp += "\\h"
        if self.nonHorizontalWhitespaceCheckBox.isChecked():
            regexp += "\\H"
        if self.verticalWhitespaceCheckBox.isChecked():
            regexp += "\\v"
        if self.nonVerticalWhitespaceCheckBox.isChecked():
            regexp += "\\V"
        
        # single characters
        for entrieslist in self.singlesEntries:
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            if format in ["-ccp", "-ccn", "-cbp", "-cbn", "-csp", "-csn",
                          "-psp", "-psn"]:
                char = entrieslist[2].itemData(entrieslist[2].currentIndex())
            else:
                char = entrieslist[1].text()
            regexp += self.__formatCharacter(char, format)
        
        # character ranges
        for entrieslist in self.rangesEntries:
            if not entrieslist[1].text() or \
               not entrieslist[2].text():
                continue
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(
                self.__formatCharacter(char1, format),
                self.__formatCharacter(char2, format))
        
        if regexp:
            if (regexp.startswith("\\") and
                regexp.count("\\") == 1 and
                "-" not in regexp) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
Esempio n. 6
0
class UIPreviewer(E5MainWindow):
    """
    Class implementing the UI Previewer main window.
    """
    def __init__(self, filename=None, parent=None, name=None):
        """
        Constructor
        
        @param filename name of a UI file to load
        @param parent parent widget of this window (QWidget)
        @param name name of this window (string)
        """
        self.mainWidget = None
        self.currentFile = QDir.currentPath()
        
        super(UIPreviewer, self).__init__(parent)
        if not name:
            self.setObjectName("UIPreviewer")
        else:
            self.setObjectName(name)
        
        self.setStyle(Preferences.getUI("Style"),
                      Preferences.getUI("StyleSheet"))
        
        self.resize(QSize(600, 480).expandedTo(self.minimumSizeHint()))
        self.statusBar()
        
        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
        self.setWindowTitle(self.tr("UI Previewer"))

        self.cw = QWidget(self)
        self.cw.setObjectName("centralWidget")
        
        self.UIPreviewerLayout = QVBoxLayout(self.cw)
        self.UIPreviewerLayout.setContentsMargins(6, 6, 6, 6)
        self.UIPreviewerLayout.setSpacing(6)
        self.UIPreviewerLayout.setObjectName("UIPreviewerLayout")

        self.styleLayout = QHBoxLayout()
        self.styleLayout.setContentsMargins(0, 0, 0, 0)
        self.styleLayout.setSpacing(6)
        self.styleLayout.setObjectName("styleLayout")

        self.styleLabel = QLabel(self.tr("Select GUI Theme"), self.cw)
        self.styleLabel.setObjectName("styleLabel")
        self.styleLayout.addWidget(self.styleLabel)

        self.styleCombo = QComboBox(self.cw)
        self.styleCombo.setObjectName("styleCombo")
        self.styleCombo.setEditable(False)
        self.styleCombo.setToolTip(self.tr("Select the GUI Theme"))
        self.styleLayout.addWidget(self.styleCombo)
        self.styleCombo.addItems(sorted(QStyleFactory().keys()))
        currentStyle = Preferences.Prefs.settings.value('UIPreviewer/style')
        if currentStyle is not None:
            self.styleCombo.setCurrentIndex(int(currentStyle))
        
        styleSpacer = QSpacerItem(
            40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.styleLayout.addItem(styleSpacer)
        self.UIPreviewerLayout.addLayout(self.styleLayout)

        self.previewSV = QScrollArea(self.cw)
        self.previewSV.setObjectName("preview")
        self.previewSV.setFrameShape(QFrame.NoFrame)
        self.previewSV.setFrameShadow(QFrame.Plain)
        self.previewSV.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.UIPreviewerLayout.addWidget(self.previewSV)

        self.setCentralWidget(self.cw)
        
        self.styleCombo.activated[str].connect(self.__guiStyleSelected)
        
        self.__initActions()
        self.__initMenus()
        self.__initToolbars()
        
        self.__updateActions()
        
        # defere loading of a UI file until we are shown
        self.fileToLoad = filename
        
    def show(self):
        """
        Public slot to show this dialog.
        
        This overloaded slot loads a UI file to be previewed after
        the main window has been shown. This way, previewing a dialog
        doesn't interfere with showing the main window.
        """
        super(UIPreviewer, self).show()
        if self.fileToLoad is not None:
            fn, self.fileToLoad = (self.fileToLoad, None)
            self.__loadFile(fn)
            
    def __initActions(self):
        """
        Private method to define the user interface actions.
        """
        self.openAct = QAction(
            UI.PixmapCache.getIcon("openUI.png"),
            self.tr('&Open File'), self)
        self.openAct.setShortcut(
            QKeySequence(self.tr("Ctrl+O", "File|Open")))
        self.openAct.setStatusTip(self.tr('Open a UI file for display'))
        self.openAct.setWhatsThis(self.tr(
            """<b>Open File</b>"""
            """<p>This opens a new UI file for display.</p>"""
        ))
        self.openAct.triggered.connect(self.__openFile)
        
        self.printAct = QAction(
            UI.PixmapCache.getIcon("print.png"),
            self.tr('&Print'), self)
        self.printAct.setShortcut(
            QKeySequence(self.tr("Ctrl+P", "File|Print")))
        self.printAct.setStatusTip(self.tr('Print a screen capture'))
        self.printAct.setWhatsThis(self.tr(
            """<b>Print</b>"""
            """<p>Print a screen capture.</p>"""
        ))
        self.printAct.triggered.connect(self.__printImage)
        
        self.printPreviewAct = QAction(
            UI.PixmapCache.getIcon("printPreview.png"),
            self.tr('Print Preview'), self)
        self.printPreviewAct.setStatusTip(self.tr(
            'Print preview a screen capture'))
        self.printPreviewAct.setWhatsThis(self.tr(
            """<b>Print Preview</b>"""
            """<p>Print preview a screen capture.</p>"""
        ))
        self.printPreviewAct.triggered.connect(self.__printPreviewImage)
        
        self.imageAct = QAction(
            UI.PixmapCache.getIcon("screenCapture.png"),
            self.tr('&Screen Capture'), self)
        self.imageAct.setShortcut(
            QKeySequence(self.tr("Ctrl+S", "File|Screen Capture")))
        self.imageAct.setStatusTip(self.tr(
            'Save a screen capture to an image file'))
        self.imageAct.setWhatsThis(self.tr(
            """<b>Screen Capture</b>"""
            """<p>Save a screen capture to an image file.</p>"""
        ))
        self.imageAct.triggered.connect(self.__saveImage)
        
        self.exitAct = QAction(
            UI.PixmapCache.getIcon("exit.png"), self.tr('&Quit'), self)
        self.exitAct.setShortcut(
            QKeySequence(self.tr("Ctrl+Q", "File|Quit")))
        self.exitAct.setStatusTip(self.tr('Quit the application'))
        self.exitAct.setWhatsThis(self.tr(
            """<b>Quit</b>"""
            """<p>Quit the application.</p>"""
        ))
        self.exitAct.triggered.connect(qApp.closeAllWindows)
        
        self.copyAct = QAction(
            UI.PixmapCache.getIcon("editCopy.png"), self.tr('&Copy'), self)
        self.copyAct.setShortcut(
            QKeySequence(self.tr("Ctrl+C", "Edit|Copy")))
        self.copyAct.setStatusTip(
            self.tr('Copy screen capture to clipboard'))
        self.copyAct.setWhatsThis(self.tr(
            """<b>Copy</b>"""
            """<p>Copy screen capture to clipboard.</p>"""
        ))
        self.copyAct.triggered.connect(self.__copyImageToClipboard)
        
        self.whatsThisAct = QAction(
            UI.PixmapCache.getIcon("whatsThis.png"),
            self.tr('&What\'s This?'), self)
        self.whatsThisAct.setShortcut(QKeySequence(self.tr("Shift+F1")))
        self.whatsThisAct.setStatusTip(self.tr('Context sensitive help'))
        self.whatsThisAct.setWhatsThis(self.tr(
            """<b>Display context sensitive help</b>"""
            """<p>In What's This? mode, the mouse cursor shows an arrow"""
            """ with a question mark, and you can click on the interface"""
            """ elements to get a short description of what they do and"""
            """ how to use them. In dialogs, this feature can be accessed"""
            """ using the context help button in the titlebar.</p>"""
        ))
        self.whatsThisAct.triggered.connect(self.__whatsThis)

        self.aboutAct = QAction(self.tr('&About'), self)
        self.aboutAct.setStatusTip(self.tr(
            'Display information about this software'))
        self.aboutAct.setWhatsThis(self.tr(
            """<b>About</b>"""
            """<p>Display some information about this software.</p>"""
        ))
        self.aboutAct.triggered.connect(self.__about)
                     
        self.aboutQtAct = QAction(self.tr('About &Qt'), self)
        self.aboutQtAct.setStatusTip(
            self.tr('Display information about the Qt toolkit'))
        self.aboutQtAct.setWhatsThis(self.tr(
            """<b>About Qt</b>"""
            """<p>Display some information about the Qt toolkit.</p>"""
        ))
        self.aboutQtAct.triggered.connect(self.__aboutQt)

    def __initMenus(self):
        """
        Private method to create the menus.
        """
        mb = self.menuBar()

        menu = mb.addMenu(self.tr('&File'))
        menu.setTearOffEnabled(True)
        menu.addAction(self.openAct)
        menu.addAction(self.imageAct)
        menu.addSeparator()
        menu.addAction(self.printPreviewAct)
        menu.addAction(self.printAct)
        menu.addSeparator()
        menu.addAction(self.exitAct)
        
        menu = mb.addMenu(self.tr("&Edit"))
        menu.setTearOffEnabled(True)
        menu.addAction(self.copyAct)
        
        mb.addSeparator()
        
        menu = mb.addMenu(self.tr('&Help'))
        menu.setTearOffEnabled(True)
        menu.addAction(self.aboutAct)
        menu.addAction(self.aboutQtAct)
        menu.addSeparator()
        menu.addAction(self.whatsThisAct)

    def __initToolbars(self):
        """
        Private method to create the toolbars.
        """
        filetb = self.addToolBar(self.tr("File"))
        filetb.setIconSize(UI.Config.ToolBarIconSize)
        filetb.addAction(self.openAct)
        filetb.addAction(self.imageAct)
        filetb.addSeparator()
        filetb.addAction(self.printPreviewAct)
        filetb.addAction(self.printAct)
        filetb.addSeparator()
        filetb.addAction(self.exitAct)
        
        edittb = self.addToolBar(self.tr("Edit"))
        edittb.setIconSize(UI.Config.ToolBarIconSize)
        edittb.addAction(self.copyAct)
        
        helptb = self.addToolBar(self.tr("Help"))
        helptb.setIconSize(UI.Config.ToolBarIconSize)
        helptb.addAction(self.whatsThisAct)

    def __whatsThis(self):
        """
        Private slot called in to enter Whats This mode.
        """
        QWhatsThis.enterWhatsThisMode()
        
    def __guiStyleSelected(self, selectedStyle):
        """
        Private slot to handle the selection of a GUI style.
        
        @param selectedStyle name of the selected style (string)
        """
        if self.mainWidget:
            self.__updateChildren(selectedStyle)
    
    def __about(self):
        """
        Private slot to show the about information.
        """
        E5MessageBox.about(
            self,
            self.tr("UI Previewer"),
            self.tr(
                """<h3> About UI Previewer </h3>"""
                """<p>The UI Previewer loads and displays Qt User-Interface"""
                """ files with various styles, which are selectable via a"""
                """ selection list.</p>"""
            )
        )
    
    def __aboutQt(self):
        """
        Private slot to show info about Qt.
        """
        E5MessageBox.aboutQt(self, self.tr("UI Previewer"))

    def __openFile(self):
        """
        Private slot to load a new file.
        """
        fn = E5FileDialog.getOpenFileName(
            self,
            self.tr("Select UI file"),
            self.currentFile,
            self.tr("Qt User-Interface Files (*.ui)"))
        if fn:
            self.__loadFile(fn)
        
    def __loadFile(self, fn):
        """
        Private slot to load a ui file.
        
        @param fn name of the ui file to be laoded (string)
        """
        if self.mainWidget:
            self.mainWidget.close()
            self.previewSV.takeWidget()
            del self.mainWidget
            self.mainWidget = None
            
        # load the file
        try:
            self.mainWidget = uic.loadUi(fn)
        except:
            pass
        
        if self.mainWidget:
            self.currentFile = fn
            self.__updateChildren(self.styleCombo.currentText())
            if isinstance(self.mainWidget, QDialog) or \
               isinstance(self.mainWidget, QMainWindow):
                self.mainWidget.show()
                self.mainWidget.installEventFilter(self)
            else:
                self.previewSV.setWidget(self.mainWidget)
                self.mainWidget.show()
        else:
            E5MessageBox.warning(
                self,
                self.tr("Load UI File"),
                self.tr(
                    """<p>The file <b>{0}</b> could not be loaded.</p>""")
                .format(fn))
        self.__updateActions()
    
    def __updateChildren(self, sstyle):
        """
        Private slot to change the style of the show UI.
        
        @param sstyle name of the selected style (string)
        """
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        qstyle = QStyleFactory.create(sstyle)
        self.mainWidget.setStyle(qstyle)
        
        lst = self.mainWidget.findChildren(QWidget)
        for obj in lst:
            try:
                obj.setStyle(qstyle)
            except AttributeError:
                pass
        del lst
        
        self.mainWidget.hide()
        self.mainWidget.show()
        
        self.lastQStyle = qstyle
        self.lastStyle = sstyle
        Preferences.Prefs.settings.setValue(
            'UIPreviewer/style', self.styleCombo.currentIndex())
        QApplication.restoreOverrideCursor()
    
    def __updateActions(self):
        """
        Private slot to update the actions state.
        """
        if self.mainWidget:
            self.imageAct.setEnabled(True)
            self.printAct.setEnabled(True)
            if self.printPreviewAct:
                self.printPreviewAct.setEnabled(True)
            self.copyAct.setEnabled(True)
            self.styleCombo.setEnabled(True)
        else:
            self.imageAct.setEnabled(False)
            self.printAct.setEnabled(False)
            if self.printPreviewAct:
                self.printPreviewAct.setEnabled(False)
            self.copyAct.setEnabled(False)
            self.styleCombo.setEnabled(False)

    def __handleCloseEvent(self):
        """
        Private slot to handle the close event of a viewed QMainWidget.
        """
        if self.mainWidget:
            self.mainWidget.removeEventFilter(self)
            del self.mainWidget
            self.mainWidget = None
        self.__updateActions()
    
    def eventFilter(self, obj, ev):
        """
        Public method called to filter an event.
        
        @param obj object, that generated the event (QObject)
        @param ev the event, that was generated by object (QEvent)
        @return flag indicating if event was filtered out
        """
        if obj == self.mainWidget:
            if ev.type() == QEvent.Close:
                self.__handleCloseEvent()
            return True
        else:
            if isinstance(self.mainWidget, QDialog):
                return QDialog.eventFilter(self, obj, ev)
            elif isinstance(self.mainWidget, QMainWindow):
                return QMainWindow.eventFilter(self, obj, ev)
            else:
                return False
    
    def __saveImage(self):
        """
        Private slot to handle the Save Image menu action.
        """
        if self.mainWidget is None:
            E5MessageBox.critical(
                self,
                self.tr("Save Image"),
                self.tr("""There is no UI file loaded."""))
            return
        
        defaultExt = "PNG"
        filters = ""
        formats = QImageWriter.supportedImageFormats()
        for format in formats:
            filters = "{0}*.{1} ".format(
                filters, bytes(format).decode().lower())
        filter = self.tr("Images ({0})").format(filters[:-1])
        
        fname = E5FileDialog.getSaveFileName(
            self,
            self.tr("Save Image"),
            "",
            filter)
        if not fname:
            return
            
        ext = QFileInfo(fname).suffix().upper()
        if not ext:
            ext = defaultExt
            fname.append(".{0}".format(defaultExt.lower()))
        
        if qVersion() >= "5.0.0":
            pix = self.mainWidget.grab()
        else:
            pix = QPixmap.grabWidget(self.mainWidget)
        self.__updateChildren(self.lastStyle)
        if not pix.save(fname, str(ext)):
            E5MessageBox.critical(
                self,
                self.tr("Save Image"),
                self.tr(
                    """<p>The file <b>{0}</b> could not be saved.</p>""")
                .format(fname))

    def __copyImageToClipboard(self):
        """
        Private slot to handle the Copy Image menu action.
        """
        if self.mainWidget is None:
            E5MessageBox.critical(
                self,
                self.tr("Save Image"),
                self.tr("""There is no UI file loaded."""))
            return
        
        cb = QApplication.clipboard()
        if qVersion() >= "5.0.0":
            cb.setPixmap(self.mainWidget.grab())
        else:
            cb.setPixmap(QPixmap.grabWidget(self.mainWidget))
        self.__updateChildren(self.lastStyle)
    
    def __printImage(self):
        """
        Private slot to handle the Print Image menu action.
        """
        if self.mainWidget is None:
            E5MessageBox.critical(
                self,
                self.tr("Print Image"),
                self.tr("""There is no UI file loaded."""))
            return
        
        settings = Preferences.Prefs.settings
        printer = QPrinter(QPrinter.HighResolution)
        printer.setFullPage(True)
        
        printerName = Preferences.getPrinter("UIPreviewer/printername")
        if printerName:
            printer.setPrinterName(printerName)
        printer.setPageSize(
            QPrinter.PageSize(int(settings.value("UIPreviewer/pagesize"))))
        printer.setPageOrder(
            QPrinter.PageOrder(int(settings.value("UIPreviewer/pageorder"))))
        printer.setOrientation(QPrinter.Orientation(
            int(settings.value("UIPreviewer/orientation"))))
        printer.setColorMode(
            QPrinter.ColorMode(int(settings.value("UIPreviewer/colormode"))))
        
        printDialog = QPrintDialog(printer, self)
        if printDialog.exec_() == QDialog.Accepted:
            self.statusBar().showMessage(self.tr("Printing the image..."))
            self.__print(printer)
            
            settings.setValue("UIPreviewer/printername", printer.printerName())
            settings.setValue("UIPreviewer/pagesize", printer.pageSize())
            settings.setValue("UIPreviewer/pageorder", printer.pageOrder())
            settings.setValue("UIPreviewer/orientation", printer.orientation())
            settings.setValue("UIPreviewer/colormode", printer.colorMode())
        
        self.statusBar().showMessage(
            self.tr("Image sent to printer..."), 2000)

    def __printPreviewImage(self):
        """
        Private slot to handle the Print Preview menu action.
        """
        from PyQt5.QtPrintSupport import QPrintPreviewDialog
        
        if self.mainWidget is None:
            E5MessageBox.critical(
                self,
                self.tr("Print Preview"),
                self.tr("""There is no UI file loaded."""))
            return
        
        settings = Preferences.Prefs.settings
        printer = QPrinter(QPrinter.HighResolution)
        printer.setFullPage(True)
        
        printerName = Preferences.getPrinter("UIPreviewer/printername")
        if printerName:
            printer.setPrinterName(printerName)
        printer.setPageSize(
            QPrinter.PageSize(int(settings.value("UIPreviewer/pagesize"))))
        printer.setPageOrder(
            QPrinter.PageOrder(int(settings.value("UIPreviewer/pageorder"))))
        printer.setOrientation(QPrinter.Orientation(
            int(settings.value("UIPreviewer/orientation"))))
        printer.setColorMode(
            QPrinter.ColorMode(int(settings.value("UIPreviewer/colormode"))))
        
        preview = QPrintPreviewDialog(printer, self)
        preview.paintRequested.connect(self.__print)
        preview.exec_()
        
    def __print(self, printer):
        """
        Private slot to the actual printing.
        
        @param printer reference to the printer object (QPrinter)
        """
        p = QPainter(printer)
        marginX = (printer.pageRect().x() - printer.paperRect().x()) // 2
        marginY = (printer.pageRect().y() - printer.paperRect().y()) // 2

        # double the margin on bottom of page
        if printer.orientation() == QPrinter.Portrait:
            width = printer.width() - marginX * 2
            height = printer.height() - marginY * 3
        else:
            marginX *= 2
            width = printer.width() - marginX * 2
            height = printer.height() - marginY * 2
        if qVersion() >= "5.0.0":
            img = self.mainWidget.grab().toImage()
        else:
            img = QPixmap.grabWidget(self.mainWidget).toImage()
        self.__updateChildren(self.lastStyle)
        p.drawImage(marginX, marginY,
                    img.scaled(width, height,
                               Qt.KeepAspectRatio, Qt.SmoothTransformation))
        p.end()
class QRegExpWizardCharactersDialog(QDialog, Ui_QRegExpWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    RegExpMode = 0
    WildcardMode = 1
    W3CMode = 2
    
    def __init__(self, mode=RegExpMode, parent=None):
        """
        Constructor
        
        @param mode mode of the dialog (one of RegExpMode, WildcardMode,
            W3CMode)
        @param parent parent widget (QWidget)
        """
        super(QRegExpWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.__mode = mode
        
        if mode == QRegExpWizardCharactersDialog.WildcardMode:
            self.predefinedBox.setEnabled(False)
            self.predefinedBox.hide()
        elif mode == QRegExpWizardCharactersDialog.RegExpMode:
            self.w3cInitialIdentifierCheckBox.hide()
            self.w3cNonInitialIdentifierCheckBox.hide()
            self.w3cNmtokenCheckBox.hide()
            self.w3cNonNmtokenCheckBox.hide()
        elif mode == QRegExpWizardCharactersDialog.W3CMode:
            self.__initCharacterSelectors()
        
        self.comboItems = []
        self.singleComboItems = []      # these are in addition to the above
        self.comboItems.append((self.tr("Normal character"), "-c"))
        if mode == QRegExpWizardCharactersDialog.RegExpMode:
            self.comboItems.append((self.tr(
                "Unicode character in hexadecimal notation"), "-h"))
            self.comboItems.append((self.tr(
                "ASCII/Latin1 character in octal notation"), "-o"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Bell character (\\a)"), "\\a"))
            self.singleComboItems.append(
                (self.tr("Page break (\\f)"), "\\f"))
            self.singleComboItems.append(
                (self.tr("Line feed (\\n)"), "\\n"))
            self.singleComboItems.append(
                (self.tr("Carriage return (\\r)"), "\\r"))
            self.singleComboItems.append(
                (self.tr("Horizontal tabulator (\\t)"), "\\t"))
            self.singleComboItems.append(
                (self.tr("Vertical tabulator (\\v)"), "\\v"))
        elif mode == QRegExpWizardCharactersDialog.W3CMode:
            self.comboItems.append((self.tr(
                "Unicode character in hexadecimal notation"), "-h"))
            self.comboItems.append((self.tr(
                "ASCII/Latin1 character in octal notation"), "-o"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Line feed (\\n)"), "\\n"))
            self.singleComboItems.append(
                (self.tr("Carriage return (\\r)"), "\\r"))
            self.singleComboItems.append(
                (self.tr("Horizontal tabulator (\\t)"), "\\t"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Character Category"), "-ccp"))
            self.singleComboItems.append(
                (self.tr("Character Block"), "-cbp"))
            self.singleComboItems.append(
                (self.tr("Not Character Category"), "-ccn"))
            self.singleComboItems.append(
                (self.tr("Not Character Block"), "-cbn"))
        
        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
        
        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)
        
        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBox.setMinimumWidth(1000)
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()
        
        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(
            self.tr("Additional Entries"), self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
        
        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)
        
        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBox.setMinimumWidth(1000)
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()
        
        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(
            self.tr("Additional Entries"), self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)
        
    def __initCharacterSelectors(self):
        """
        Private method to initialize the W3C character selector entries.
        """
        self.__characterCategories = (
            # display name                              code
            (self.tr("Letter, Any"), "L"),
            (self.tr("Letter, Uppercase"), "Lu"),
            (self.tr("Letter, Lowercase"), "Ll"),
            (self.tr("Letter, Titlecase"), "Lt"),
            (self.tr("Letter, Modifier"), "Lm"),
            (self.tr("Letter, Other"), "Lo"),
            (self.tr("Mark, Any"), "M"),
            (self.tr("Mark, Nonspacing"), "Mn"),
            (self.tr("Mark, Spacing Combining"), "Mc"),
            (self.tr("Mark, Enclosing"), "Me"),
            (self.tr("Number, Any"), "N"),
            (self.tr("Number, Decimal Digit"), "Nd"),
            (self.tr("Number, Letter"), "Nl"),
            (self.tr("Number, Other"), "No"),
            (self.tr("Punctuation, Any"), "P"),
            (self.tr("Punctuation, Connector"), "Pc"),
            (self.tr("Punctuation, Dash"), "Pd"),
            (self.tr("Punctuation, Open"), "Ps"),
            (self.tr("Punctuation, Close"), "Pe"),
            (self.tr("Punctuation, Initial Quote"), "Pi"),
            (self.tr("Punctuation, Final Quote"), "Pf"),
            (self.tr("Punctuation, Other"), "Po"),
            (self.tr("Symbol, Any"), "S"),
            (self.tr("Symbol, Math"), "Sm"),
            (self.tr("Symbol, Currency"), "Sc"),
            (self.tr("Symbol, Modifier"), "Sk"),
            (self.tr("Symbol, Other"), "So"),
            (self.tr("Separator, Any"), "Z"),
            (self.tr("Separator, Space"), "Zs"),
            (self.tr("Separator, Line"), "Zl"),
            (self.tr("Separator, Paragraph"), "Zp"),
            (self.tr("Other, Any"), "C"),
            (self.tr("Other, Control"), "Cc"),
            (self.tr("Other, Format"), "Cf"),
            (self.tr("Other, Private Use"), "Co"),
            (self.tr("Other, Not Assigned"), "Cn"),
        )
        
        self.__characterBlocks = (
            (self.tr("Basic Latin"),
             "IsBasicLatin"),
            (self.tr("Latin-1 Supplement"),
             "IsLatin-1Supplement"),
            (self.tr("Latin Extended-A"),
             "IsLatinExtended-A"),
            (self.tr("Latin Extended-B"),
             "IsLatinExtended-B"),
            (self.tr("IPA Extensions"),
             "IsIPAExtensions"),
            (self.tr("Spacing Modifier Letters"),
             "IsSpacingModifierLetters"),
            (self.tr("Combining Diacritical Marks"),
             "IsCombiningDiacriticalMarks"),
            (self.tr("Greek"),
             "IsGreek"),
            (self.tr("Cyrillic"),
             "IsCyrillic"),
            (self.tr("Armenian"),
             "IsArmenian"),
            (self.tr("Hebrew"),
             "IsHebrew"),
            (self.tr("Arabic"),
             "IsArabic"),
            (self.tr("Syriac"),
             "IsSyriac"),
            (self.tr("Thaana"),
             "IsThaana"),
            (self.tr("Devanagari"),
             "IsDevanagari"),
            (self.tr("Bengali"),
             "IsBengali"),
            (self.tr("Gurmukhi"),
             "IsBengali"),
            (self.tr("Gujarati"),
             "IsGujarati"),
            (self.tr("Oriya"),
             "IsOriya"),
            (self.tr("Tamil"),
             "IsTamil"),
            (self.tr("Telugu"),
             "IsTelugu"),
            (self.tr("Kannada"),
             "IsKannada"),
            (self.tr("Malayalam"),
             "IsMalayalam"),
            (self.tr("Sinhala"),
             "IsSinhala"),
            (self.tr("Thai"),
             "IsThai"),
            (self.tr("Lao"),
             "IsLao"),
            (self.tr("Tibetan"),
             "IsTibetan"),
            (self.tr("Myanmar"),
             "IsMyanmar"),
            (self.tr("Georgian"),
             "IsGeorgian"),
            (self.tr("Hangul Jamo"),
             "IsHangulJamo"),
            (self.tr("Ethiopic"),
             "IsEthiopic"),
            (self.tr("Cherokee"),
             "IsCherokee"),
            (self.tr("Unified Canadian Aboriginal Syllabics"),
             "IsUnifiedCanadianAboriginalSyllabics"),
            (self.tr("Ogham"),
             "IsOgham"),
            (self.tr("Runic"),
             "IsRunic"),
            (self.tr("Khmer"),
             "IsKhmer"),
            (self.tr("Mongolian"),
             "IsMongolian"),
            (self.tr("Latin Extended Additional"),
             "IsLatinExtendedAdditional"),
            (self.tr("Greek Extended"),
             "IsGreekExtended"),
            (self.tr("General Punctuation"),
             "IsGeneralPunctuation"),
            (self.tr("Superscripts and Subscripts"),
             "IsSuperscriptsandSubscripts"),
            (self.tr("Currency Symbols"),
             "IsCurrencySymbols"),
            (self.tr("Combining Marks for Symbols"),
             "IsCombiningMarksforSymbols"),
            (self.tr("Letterlike Symbols"),
             "IsLetterlikeSymbols"),
            (self.tr("Number Forms"),
             "IsNumberForms"),
            (self.tr("Arrows"),
             "IsArrows"),
            (self.tr("Mathematical Operators"),
             "IsMathematicalOperators"),
            (self.tr("Miscellaneous Technical"),
             "IsMiscellaneousTechnical"),
            (self.tr("Control Pictures"),
             "IsControlPictures"),
            (self.tr("Optical Character Recognition"),
             "IsOpticalCharacterRecognition"),
            (self.tr("Enclosed Alphanumerics"),
             "IsEnclosedAlphanumerics"),
            (self.tr("Box Drawing"),
             "IsBoxDrawing"),
            (self.tr("Block Elements"),
             "IsBlockElements"),
            (self.tr("Geometric Shapes"),
             "IsGeometricShapes"),
            (self.tr("Miscellaneous Symbols"),
             "IsMiscellaneousSymbols"),
            (self.tr("Dingbats"),
             "IsDingbats"),
            (self.tr("Braille Patterns"),
             "IsBraillePatterns"),
            (self.tr("CJK Radicals Supplement"),
             "IsCJKRadicalsSupplement"),
            (self.tr("KangXi Radicals"),
             "IsKangXiRadicals"),
            (self.tr("Ideographic Description Chars"),
             "IsIdeographicDescriptionChars"),
            (self.tr("CJK Symbols and Punctuation"),
             "IsCJKSymbolsandPunctuation"),
            (self.tr("Hiragana"),
             "IsHiragana"),
            (self.tr("Katakana"),
             "IsKatakana"),
            (self.tr("Bopomofo"),
             "IsBopomofo"),
            (self.tr("Hangul Compatibility Jamo"),
             "IsHangulCompatibilityJamo"),
            (self.tr("Kanbun"),
             "IsKanbun"),
            (self.tr("Bopomofo Extended"),
             "IsBopomofoExtended"),
            (self.tr("Enclosed CJK Letters and Months"),
             "IsEnclosedCJKLettersandMonths"),
            (self.tr("CJK Compatibility"),
             "IsCJKCompatibility"),
            (self.tr("CJK Unified Ideographs Extension A"),
             "IsCJKUnifiedIdeographsExtensionA"),
            (self.tr("CJK Unified Ideographs"),
             "IsCJKUnifiedIdeographs"),
            (self.tr("Yi Syllables"),
             "IsYiSyllables"),
            (self.tr("Yi Radicals"),
             "IsYiRadicals"),
            (self.tr("Hangul Syllables"),
             "IsHangulSyllables"),
            (self.tr("Private Use"),
             "IsPrivateUse"),
            (self.tr("CJK Compatibility Ideographs"),
             "IsCJKCompatibilityIdeographs"),
            (self.tr("Alphabetic Presentation Forms"),
             "IsAlphabeticPresentationForms"),
            (self.tr("Arabic Presentation Forms-A"),
             "IsArabicPresentationForms-A"),
            (self.tr("Combining Half Marks"),
             "IsCombiningHalfMarks"),
            (self.tr("CJK Compatibility Forms"),
             "IsCJKCompatibilityForms"),
            (self.tr("Small Form Variants"),
             "IsSmallFormVariants"),
            (self.tr("Arabic Presentation Forms-B"),
             "IsArabicPresentationForms-B"),
            (self.tr("Halfwidth and Fullwidth Forms"),
             "IsHalfwidthandFullwidthForms"),
            (self.tr("Specials"),
             "IsSpecials"),
            (self.tr("Old Italic"),
             "IsOldItalic"),
            (self.tr("Gothic"),
             "IsGothic"),
            (self.tr("Deseret"),
             "IsDeseret"),
            (self.tr("Byzantine Musical Symbols"),
             "IsByzantineMusicalSymbols"),
            (self.tr("Musical Symbols"),
             "IsMusicalSymbols"),
            (self.tr("Mathematical Alphanumeric Symbols"),
             "IsMathematicalAlphanumericSymbols"),
            (self.tr("CJK Unified Ideographic Extension B"),
             "IsCJKUnifiedIdeographicExtensionB"),
            (self.tr("CJK Compatapility Ideographic Supplement"),
             "IsCJKCompatapilityIdeographicSupplement"),
            (self.tr("Tags"),
             "IsTags"),
        )
        
    def __populateCharTypeCombo(self, combo, isSingle):
        """
        Private method to populate a given character type selection combo box.
        
        @param combo reference to the combo box to be populated (QComboBox)
        @param isSingle flag indicating a singles combo (boolean)
        """
        for txt, value in self.comboItems:
            combo.addItem(txt, value)
        if isSingle:
            for txt, value in self.singleComboItems:
                combo.addItem(txt, value)
        
    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, True)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb1a = QComboBox(hbox)
        cb1a.setEditable(False)
        cb1a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb1a)
        cb1a.hide()
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        self.__populateCharTypeCombo(cb2, True)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        cb2a = QComboBox(hbox)
        cb2a.setEditable(False)
        cb2a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb2a)
        cb2a.hide()
        self.singlesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()
        
        self.singlesItemsBox.adjustSize()
        
        self.singlesEntries.append([cb1, le1, cb1a])
        self.singlesEntries.append([cb2, le2, cb2a])
        
    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, False)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        hbox.show()
        
        self.rangesItemsBox.adjustSize()
        
        self.rangesEntries.append([cb1, le1, le2])
        
    def __populateW3cCharacterCombo(self, combo, format):
        """
        Private method to populate a W3C character selection combo.
        
        @param combo combo box to be populated (QComboBox)
        @param format format identifier (one of "-ccp", "-ccn", "-cbp", "-cbn")
        """
        combo.clear()
        
        if format in ["-ccp", "-ccn"]:
            comboLen = 0
            for txt, code in self.__characterCategories:
                combo.addItem(txt, code)
                comboLen = max(comboLen, len(txt))
            combo.setMinimumContentsLength(comboLen)
        elif format in ["-cbp", "-cbn"]:
            comboLen = 0
            for txt, code in self.__characterBlocks:
                combo.addItem(txt, code)
                comboLen = max(comboLen, len(txt))
            combo.setMinimumContentsLength(comboLen)
        
    def __performSelectedAction(self, format, lineedit, combo):
        """
        Private method performing some actions depending on the input.
        
        @param format format of the selected entry (string)
        @param lineedit line edit widget to act on (QLineEdit)
        @param combo combo box widget to act on (QComboBox)
        """
        if format == "-i":
            return
        
        if format in ["-c", "-h", "-o"]:
            lineedit.show()
            lineedit.setEnabled(True)
            if combo is not None:
                combo.hide()
            if format == "-c":
                lineedit.setValidator(self.charValidator)
            elif format == "-h":
                lineedit.setValidator(self.hexValidator)
            elif format == "-o":
                lineedit.setValidator(self.octValidator)
        elif format in ["-ccp", "-ccn", "-cbp", "-cbn"]:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.show()
            self.__populateW3cCharacterCombo(combo, format)
        else:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.hide()
        lineedit.clear()
        
    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(
                    format, entriesList[1], entriesList[2])
                break
        
    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1], None)
                self.__performSelectedAction(format, entriesList[2], None)
                break
        
    def __formatCharacter(self, char, format):
        """
        Private method to format the characters entered into the dialog.
        
        @param char character string entered into the dialog (string)
        @param format string giving a special format (-c, -h, -i or -o) or
            the already formatted character (string)
        @return formatted character string (string)
        """
        if format == "-c":
            return char
        elif format == "-i":
            return ""
        
        if self.__mode in [QRegExpWizardCharactersDialog.RegExpMode,
                           QRegExpWizardCharactersDialog.W3CMode]:
            if format == "-h":
                return "\\x{0}".format(char.lower())
            elif format == "-o":
                return "\\0{0}".format(char)
            elif format in ["-ccp", "-cbp"]:
                return "\\p{{{0}}}".format(char)
            elif format in ["-ccn", "-cbn"]:
                return "\\P{{{0}}}".format(char)
            else:
                return format
        
    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""
        
        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"
            
        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
        if self.w3cInitialIdentifierCheckBox.isChecked():
            regexp += "\\i"
        if self.w3cNonInitialIdentifierCheckBox.isChecked():
            regexp += "\\I"
        if self.w3cNmtokenCheckBox.isChecked():
            regexp += "\\c"
        if self.w3cNonNmtokenCheckBox.isChecked():
            regexp += "\\C"
            
        # single characters
        for entrieslist in self.singlesEntries:
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            if format in ["-ccp", "-ccn", "-cbp", "-cbn"]:
                char = entrieslist[2].itemData(entrieslist[2].currentIndex())
            else:
                char = entrieslist[1].text()
            regexp += self.__formatCharacter(char, format)
        
        # character ranges
        for entrieslist in self.rangesEntries:
            if not entrieslist[1].text() or \
               not entrieslist[2].text():
                continue
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(
                self.__formatCharacter(char1, format),
                self.__formatCharacter(char2, format))
        
        if regexp:
            if (regexp.startswith("\\") and
                regexp.count("\\") == 1 and
                "-" not in regexp) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
Esempio n. 8
0
class KeyMgmt(QWidget):

    def __init__(self, gui):
        super(KeyMgmt, self).__init__()

        self.ui = gui
        self.tran = self.ui.tran
        self.parser = self.ui.configparser
        self.config = self.ui.config
        self.setObjectName("keytab")

        self.layout = QGridLayout(self)
        self.layout.setObjectName('keytab_layout')

        # the new button
        self.button_new = QPushButton(self)
        self.button_new.setObjectName('key_tab_button_new')
        self.button_new.setText(self.tran.get_text(self.button_new.objectName()))

        # edit button
        self.button_edit = QPushButton(self)
        self.button_edit.setObjectName('key_tab_button_edit')
        self.button_edit.setText(self.tran.get_text(self.button_edit.objectName()))

        # setup the delete button
        self.button_delete = QPushButton(self)
        self.button_delete.setObjectName('key_tab_button_delete')
        self.button_delete.setText(self.tran.get_text(self.button_delete.objectName()))

        # import button
        self.button_import = QPushButton(self)
        self.button_import.setObjectName('key_tab_button_import')
        self.button_import.setText(self.tran.get_text(self.button_import.objectName()))

        # export button
        self.button_export = QPushButton(self)
        self.button_export.setObjectName('key_tab_button_export')
        self.button_export.setText(self.tran.get_text(self.button_export.objectName()))

        # drop down menu
        self.combobox = QComboBox(self)
        self.combobox.setObjectName('key_tab_combobox')

        # scroll area
        self.scroll = QScrollArea(self)
        self.scroll.setWidgetResizable(True)
        self.scroll.setObjectName('key_tab_scroll')

        # widget that holds the scroll area contents
        self.scroll_content = QWidget()
        self.scroll_content.setGeometry(QRect(0, 0, 800, 400))
        self.scroll_content.setObjectName('key_tab_scroll_content')

        # layout for the scroll area main widget
        self.scroll_content_layout = QGridLayout(self.scroll_content)
        self.scroll_content_layout.setObjectName('key_tab_scroll_content_layout')

        # setup the tree widget
        self.tree = QTreeWidget(self.scroll_content)
        self.tree.setObjectName('key_tab_tree')

        # add the tree widget to the layout of the scroll area
        self.scroll_content_layout.addWidget(self.tree)     # TODO change to grid layout

        # add the contents of the scroll area to the scroll area
        self.scroll.setWidget(self.scroll_content)

        # add the components to the main layout
        self.layout.addWidget(self.button_new, 0, 0, 1, 1)
        self.layout.addWidget(self.button_edit, 0, 1, 1, 1)
        self.layout.addWidget(self.button_delete, 0, 2, 1, 1)
        self.layout.addWidget(self.button_import, 0, 3, 1, 1)
        self.layout.addWidget(self.button_export, 0, 4, 1, 1)
        self.layout.addWidget(self.combobox, 0, 5, 1, 1)
        self.layout.addWidget(self.scroll, 1, 0, 1, 6)

        # add relevant widgets to tooltip list
        self.tooltips = [
            self.button_delete, self.button_edit, self.button_import,
            self.button_new, self.button_export, self.combobox
            ]
Esempio n. 9
-1
class ConfigurationWidget(QWidget):
    """
    Class implementing a dialog for the configuration of eric6.
    
    @signal preferencesChanged() emitted after settings have been changed
    @signal masterPasswordChanged(str, str) emitted after the master
        password has been changed with the old and the new password
    @signal accepted() emitted to indicate acceptance of the changes
    @signal rejected() emitted to indicate rejection of the changes
    """
    preferencesChanged = pyqtSignal()
    masterPasswordChanged = pyqtSignal(str, str)
    accepted = pyqtSignal()
    rejected = pyqtSignal()
    
    DefaultMode = 0
    HelpBrowserMode = 1
    TrayStarterMode = 2
    HexEditorMode = 3
    
    def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode,
                 expandedEntries=[]):
        """
        Constructor
        
        @param parent The parent widget of this dialog. (QWidget)
        @keyparam fromEric flag indicating a dialog generation from within the
            eric6 ide (boolean)
        @keyparam displayMode mode of the configuration dialog
            (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode)
        @exception RuntimeError raised to indicate an invalid dialog mode
        @keyparam expandedEntries list of entries to be shown expanded
            (list of strings)
        """
        assert displayMode in (
            ConfigurationWidget.DefaultMode,
            ConfigurationWidget.HelpBrowserMode,
            ConfigurationWidget.TrayStarterMode,
            ConfigurationWidget.HexEditorMode,
        )
        
        super(ConfigurationWidget, self).__init__(parent)
        self.fromEric = fromEric
        self.displayMode = displayMode
        
        self.__setupUi()
        
        self.itmDict = {}
        
        if not fromEric:
            from PluginManager.PluginManager import PluginManager
            try:
                self.pluginManager = e5App().getObject("PluginManager")
            except KeyError:
                self.pluginManager = PluginManager(self)
                e5App().registerObject("PluginManager", self.pluginManager)
        
        if displayMode == ConfigurationWidget.DefaultMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "applicationPage":
                [self.tr("Application"), "preferences-application.png",
                 "ApplicationPage", None, None],
                "cooperationPage":
                [self.tr("Cooperation"), "preferences-cooperation.png",
                 "CooperationPage", None, None],
                "corbaPage":
                [self.tr("CORBA"), "preferences-orbit.png",
                 "CorbaPage", None, None],
                "emailPage":
                [self.tr("Email"), "preferences-mail_generic.png",
                 "EmailPage", None, None],
                "graphicsPage":
                [self.tr("Graphics"), "preferences-graphics.png",
                 "GraphicsPage", None, None],
                "hexEditorPage":
                [self.tr("Hex Editor"), "hexEditor.png",
                 "HexEditorPage", None, None],
                "iconsPage":
                [self.tr("Icons"), "preferences-icons.png",
                 "IconsPage", None, None],
                "ircPage":
                [self.tr("IRC"), "irc.png",
                 "IrcPage", None, None],
                "logViewerPage":
                [self.tr("Log-Viewer"), "preferences-logviewer.png",
                 "LogViewerPage", None, None],
                "mimeTypesPage":
                [self.tr("Mimetypes"), "preferences-mimetypes.png",
                 "MimeTypesPage", None, None],
                "networkPage":
                [self.tr("Network"), "preferences-network.png",
                 "NetworkPage", None, None],
                "notificationsPage":
                [self.tr("Notifications"),
                 "preferences-notifications.png",
                 "NotificationsPage", None, None],
                "pluginManagerPage":
                [self.tr("Plugin Manager"),
                 "preferences-pluginmanager.png",
                 "PluginManagerPage", None, None],
                "printerPage":
                [self.tr("Printer"), "preferences-printer.png",
                 "PrinterPage", None, None],
                "pythonPage":
                [self.tr("Python"), "preferences-python.png",
                 "PythonPage", None, None],
                "qtPage":
                [self.tr("Qt"), "preferences-qtlogo.png",
                 "QtPage", None, None],
                "securityPage":
                [self.tr("Security"), "preferences-security.png",
                 "SecurityPage", None, None],
                "shellPage":
                [self.tr("Shell"), "preferences-shell.png",
                 "ShellPage", None, None],
                "tasksPage":
                [self.tr("Tasks"), "task.png",
                 "TasksPage", None, None],
                "templatesPage":
                [self.tr("Templates"), "preferences-template.png",
                 "TemplatesPage", None, None],
                "trayStarterPage":
                [self.tr("Tray Starter"), "erict.png",
                 "TrayStarterPage", None, None],
                "vcsPage":
                [self.tr("Version Control Systems"),
                 "preferences-vcs.png",
                 "VcsPage", None, None],
                
                "0debuggerPage":
                [self.tr("Debugger"), "preferences-debugger.png",
                 None, None, None],
                "debuggerGeneralPage":
                [self.tr("General"), "preferences-debugger.png",
                 "DebuggerGeneralPage", "0debuggerPage", None],
                "debuggerPythonPage":
                [self.tr("Python"), "preferences-pyDebugger.png",
                 "DebuggerPythonPage", "0debuggerPage", None],
                "debuggerPython3Page":
                [self.tr("Python3"), "preferences-pyDebugger.png",
                 "DebuggerPython3Page", "0debuggerPage", None],
                
                "0editorPage":
                [self.tr("Editor"), "preferences-editor.png",
                 None, None, None],
                "editorAPIsPage":
                [self.tr("APIs"), "preferences-api.png",
                 "EditorAPIsPage", "0editorPage", None],
                "editorAutocompletionPage":
                [self.tr("Autocompletion"),
                 "preferences-autocompletion.png",
                 "EditorAutocompletionPage", "0editorPage", None],
                "editorAutocompletionQScintillaPage":
                [self.tr("QScintilla"), "qscintilla.png",
                 "EditorAutocompletionQScintillaPage",
                 "editorAutocompletionPage", None],
                "editorCalltipsPage":
                [self.tr("Calltips"), "preferences-calltips.png",
                 "EditorCalltipsPage", "0editorPage", None],
                "editorCalltipsQScintillaPage":
                [self.tr("QScintilla"), "qscintilla.png",
                 "EditorCalltipsQScintillaPage", "editorCalltipsPage", None],
                "editorGeneralPage":
                [self.tr("General"), "preferences-general.png",
                 "EditorGeneralPage", "0editorPage", None],
                "editorFilePage":
                [self.tr("Filehandling"),
                 "preferences-filehandling.png",
                 "EditorFilePage", "0editorPage", None],
                "editorSearchPage":
                [self.tr("Searching"), "preferences-search.png",
                 "EditorSearchPage", "0editorPage", None],
                "editorSpellCheckingPage":
                [self.tr("Spell checking"),
                 "preferences-spellchecking.png",
                 "EditorSpellCheckingPage", "0editorPage", None],
                "editorStylesPage":
                [self.tr("Style"), "preferences-styles.png",
                 "EditorStylesPage", "0editorPage", None],
                "editorSyntaxPage":
                [self.tr("Code Checkers"), "preferences-debugger.png",
                 "EditorSyntaxPage", "0editorPage", None],
                "editorTypingPage":
                [self.tr("Typing"), "preferences-typing.png",
                 "EditorTypingPage", "0editorPage", None],
                "editorExportersPage":
                [self.tr("Exporters"), "preferences-exporters.png",
                 "EditorExportersPage", "0editorPage", None],
                
                "1editorLexerPage":
                [self.tr("Highlighters"),
                 "preferences-highlighting-styles.png",
                 None, "0editorPage", None],
                "editorHighlightersPage":
                [self.tr("Filetype Associations"),
                 "preferences-highlighter-association.png",
                 "EditorHighlightersPage", "1editorLexerPage", None],
                "editorHighlightingStylesPage":
                [self.tr("Styles"),
                 "preferences-highlighting-styles.png",
                 "EditorHighlightingStylesPage", "1editorLexerPage", None],
                "editorKeywordsPage":
                [self.tr("Keywords"), "preferences-keywords.png",
                 "EditorKeywordsPage", "1editorLexerPage", None],
                "editorPropertiesPage":
                [self.tr("Properties"), "preferences-properties.png",
                 "EditorPropertiesPage", "1editorLexerPage", None],
                
                "1editorMouseClickHandlers":
                [self.tr("Mouse Click Handlers"),
                 "preferences-mouse-click-handler.png",
                 "EditorMouseClickHandlerPage", "0editorPage", None],
                
                "0helpPage":
                [self.tr("Help"), "preferences-help.png",
                 None, None, None],
                "helpDocumentationPage":
                [self.tr("Help Documentation"),
                 "preferences-helpdocumentation.png",
                 "HelpDocumentationPage", "0helpPage", None],
                "helpViewersPage":
                [self.tr("Help Viewers"),
                 "preferences-helpviewers.png",
                 "HelpViewersPage", "0helpPage", None],
                
                "0projectPage":
                [self.tr("Project"), "preferences-project.png",
                 None, None, None],
                "projectBrowserPage":
                [self.tr("Project Viewer"), "preferences-project.png",
                 "ProjectBrowserPage", "0projectPage", None],
                "projectPage":
                [self.tr("Project"), "preferences-project.png",
                 "ProjectPage", "0projectPage", None],
                "multiProjectPage":
                [self.tr("Multiproject"),
                 "preferences-multiproject.png",
                 "MultiProjectPage", "0projectPage", None],
                
                "0interfacePage":
                [self.tr("Interface"), "preferences-interface.png",
                 None, None, None],
                "interfacePage":
                [self.tr("Interface"), "preferences-interface.png",
                 "InterfacePage", "0interfacePage", None],
                "viewmanagerPage":
                [self.tr("Viewmanager"), "preferences-viewmanager.png",
                 "ViewmanagerPage", "0interfacePage", None],
            }
            try:
                from PyQt5 import QtWebKit      # __IGNORE_WARNING__
                self.configItems.update({
                    "helpAppearancePage":
                    [self.tr("Appearance"), "preferences-styles.png",
                     "HelpAppearancePage", "0helpPage", None],
                    "helpFlashCookieManagerPage":
                    [self.tr("Flash Cookie Manager"),
                     "flashCookie16.png",
                     "HelpFlashCookieManagerPage", "0helpPage", None],
                    "helpVirusTotalPage":
                    [self.tr("VirusTotal Interface"), "virustotal.png",
                     "HelpVirusTotalPage", "0helpPage", None],
                    "helpWebBrowserPage":
                    [self.tr("eric6 Web Browser"), "ericWeb.png",
                     "HelpWebBrowserPage", "0helpPage", None],
                })
            except ImportError:
                pass
            
            self.configItems.update(
                e5App().getObject("PluginManager").getPluginConfigData())
        
        elif displayMode == ConfigurationWidget.HelpBrowserMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "interfacePage":
                [self.tr("Interface"), "preferences-interface.png",
                 "HelpInterfacePage", None, None],
                "networkPage":
                [self.tr("Network"), "preferences-network.png",
                 "NetworkPage", None, None],
                "printerPage":
                [self.tr("Printer"), "preferences-printer.png",
                 "PrinterPage", None, None],
                "securityPage":
                [self.tr("Security"), "preferences-security.png",
                 "SecurityPage", None, None],
                
                "0helpPage":
                [self.tr("Help"), "preferences-help.png",
                 None, None, None],
                "helpDocumentationPage":
                [self.tr("Help Documentation"),
                 "preferences-helpdocumentation.png",
                 "HelpDocumentationPage", "0helpPage", None],
            }
            try:
                from PyQt5 import QtWebKit      # __IGNORE_WARNING__
                self.configItems.update({
                    "helpAppearancePage":
                    [self.tr("Appearance"), "preferences-styles.png",
                     "HelpAppearancePage", "0helpPage", None],
                    "helpFlashCookieManagerPage":
                    [self.tr("Flash Cookie Manager"),
                     "flashCookie16.png",
                     "HelpFlashCookieManagerPage", "0helpPage", None],
                    "helpVirusTotalPage":
                    [self.tr("VirusTotal Interface"), "virustotal.png",
                     "HelpVirusTotalPage", "0helpPage", None],
                    "helpWebBrowserPage":
                    [self.tr("eric6 Web Browser"), "ericWeb.png",
                     "HelpWebBrowserPage", "0helpPage", None],
                })
            except ImportError:
                pass
        
        elif displayMode == ConfigurationWidget.TrayStarterMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "trayStarterPage":
                [self.tr("Tray Starter"), "erict.png",
                 "TrayStarterPage", None, None],
            }
        
        elif displayMode == ConfigurationWidget.HexEditorMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "hexEditorPage":
                [self.tr("Hex Editor"), "hexEditor.png",
                 "HexEditorPage", None, None],
            }
        
        else:
            raise RuntimeError("Illegal mode value: {0}".format(displayMode))
        
        # generate the list entries
        self.__expandedEntries = []
        for key in sorted(self.configItems.keys()):
            pageData = self.configItems[key]
            if pageData[3]:
                if pageData[3] in self.itmDict:
                    pitm = self.itmDict[pageData[3]]  # get the parent item
                else:
                    continue
            else:
                pitm = self.configList
            self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key,
                                                      pageData[1])
            self.itmDict[key].setData(0, Qt.UserRole, key)
            if (not self.fromEric or
                displayMode != ConfigurationWidget.DefaultMode or
                    key in expandedEntries):
                self.itmDict[key].setExpanded(True)
        self.configList.sortByColumn(0, Qt.AscendingOrder)
        
        # set the initial size of the splitter
        self.configSplitter.setSizes([200, 600])
        
        self.configList.itemActivated.connect(self.__showConfigurationPage)
        self.configList.itemClicked.connect(self.__showConfigurationPage)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.rejected)
        
        if displayMode in [ConfigurationWidget.HelpBrowserMode,
                           ConfigurationWidget.TrayStarterMode,
                           ConfigurationWidget.HexEditorMode]:
            self.configListSearch.hide()
        
        if displayMode not in [ConfigurationWidget.TrayStarterMode,
                               ConfigurationWidget.HexEditorMode]:
            self.__initLexers()
        
    def accept(self):
        """
        Public slot to accept the buttonBox accept signal.
        """
        if not isMacPlatform():
            wdg = self.focusWidget()
            if wdg == self.configList:
                return
        
        self.accepted.emit()
        
    def __setupUi(self):
        """
        Private method to perform the general setup of the configuration
        widget.
        """
        self.setObjectName("ConfigurationDialog")
        self.resize(900, 650)
        self.verticalLayout_2 = QVBoxLayout(self)
        self.verticalLayout_2.setSpacing(6)
        self.verticalLayout_2.setContentsMargins(6, 6, 6, 6)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        
        self.configSplitter = QSplitter(self)
        self.configSplitter.setOrientation(Qt.Horizontal)
        self.configSplitter.setObjectName("configSplitter")
        
        self.configListWidget = QWidget(self.configSplitter)
        self.leftVBoxLayout = QVBoxLayout(self.configListWidget)
        self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.leftVBoxLayout.setSpacing(0)
        self.leftVBoxLayout.setObjectName("leftVBoxLayout")
        self.configListSearch = E5ClearableLineEdit(
            self, self.tr("Enter search text..."))
        self.configListSearch.setObjectName("configListSearch")
        self.leftVBoxLayout.addWidget(self.configListSearch)
        self.configList = QTreeWidget()
        self.configList.setObjectName("configList")
        self.leftVBoxLayout.addWidget(self.configList)
        self.configListSearch.textChanged.connect(self.__searchTextChanged)
        
        self.scrollArea = QScrollArea(self.configSplitter)
        self.scrollArea.setFrameShape(QFrame.NoFrame)
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setObjectName("scrollArea")
        
        self.configStack = QStackedWidget()
        self.configStack.setFrameShape(QFrame.Box)
        self.configStack.setFrameShadow(QFrame.Sunken)
        self.configStack.setObjectName("configStack")
        self.scrollArea.setWidget(self.configStack)
        
        self.emptyPage = QWidget()
        self.emptyPage.setGeometry(QRect(0, 0, 372, 591))
        self.emptyPage.setObjectName("emptyPage")
        self.vboxlayout = QVBoxLayout(self.emptyPage)
        self.vboxlayout.setSpacing(6)
        self.vboxlayout.setContentsMargins(6, 6, 6, 6)
        self.vboxlayout.setObjectName("vboxlayout")
        spacerItem = QSpacerItem(
            20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.vboxlayout.addItem(spacerItem)
        self.emptyPagePixmap = QLabel(self.emptyPage)
        self.emptyPagePixmap.setAlignment(Qt.AlignCenter)
        self.emptyPagePixmap.setObjectName("emptyPagePixmap")
        self.emptyPagePixmap.setPixmap(
            QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png')))
        self.vboxlayout.addWidget(self.emptyPagePixmap)
        self.textLabel1 = QLabel(self.emptyPage)
        self.textLabel1.setAlignment(Qt.AlignCenter)
        self.textLabel1.setObjectName("textLabel1")
        self.vboxlayout.addWidget(self.textLabel1)
        spacerItem1 = QSpacerItem(
            20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.vboxlayout.addItem(spacerItem1)
        self.configStack.addWidget(self.emptyPage)
        
        self.verticalLayout_2.addWidget(self.configSplitter)
        
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Apply | QDialogButtonBox.Cancel |
            QDialogButtonBox.Ok | QDialogButtonBox.Reset)
        self.buttonBox.setObjectName("buttonBox")
        if not self.fromEric and \
                self.displayMode == ConfigurationWidget.DefaultMode:
            self.buttonBox.button(QDialogButtonBox.Apply).hide()
        self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
        self.verticalLayout_2.addWidget(self.buttonBox)

        self.setWindowTitle(self.tr("Preferences"))
        
        self.configList.header().hide()
        self.configList.header().setSortIndicator(0, Qt.AscendingOrder)
        self.configList.setSortingEnabled(True)
        self.textLabel1.setText(
            self.tr("Please select an entry of the list \n"
                    "to display the configuration page."))
        
        QMetaObject.connectSlotsByName(self)
        self.setTabOrder(self.configList, self.configStack)
        
        self.configStack.setCurrentWidget(self.emptyPage)
        
        self.configList.setFocus()
    
    def __searchTextChanged(self, text):
        """
        Private slot to handle a change of the search text.
        
        @param text text to search for (string)
        """
        self.__searchChildItems(self.configList.invisibleRootItem(), text)
    
    def __searchChildItems(self, parent, text):
        """
        Private method to enable child items based on a search string.
        
        @param parent reference to the parent item (QTreeWidgetItem)
        @param text text to search for (string)
        @return flag indicating an enabled child item (boolean)
        """
        childEnabled = False
        text = text.lower()
        for index in range(parent.childCount()):
            itm = parent.child(index)
            if itm.childCount() > 0:
                enable = self.__searchChildItems(itm, text) or \
                    text == "" or text in itm.text(0).lower()
            else:
                enable = text == "" or text in itm.text(0).lower()
            if enable:
                childEnabled = True
            itm.setDisabled(not enable)
        
        return childEnabled
    
    def __initLexers(self):
        """
        Private method to initialize the dictionary of preferences lexers.
        """
        import QScintilla.Lexers
        from .PreferencesLexer import PreferencesLexer, \
            PreferencesLexerLanguageError
        
        self.lexers = {}
        for language in QScintilla.Lexers.getSupportedLanguages():
            if language not in self.lexers:
                try:
                    self.lexers[language] = PreferencesLexer(language, self)
                except PreferencesLexerLanguageError:
                    pass
        
    def __importConfigurationPage(self, name):
        """
        Private method to import a configuration page module.
        
        @param name name of the configuration page module (string)
        @return reference to the configuration page module
        """
        modName = "Preferences.ConfigurationPages.{0}".format(name)
        try:
            mod = __import__(modName)
            components = modName.split('.')
            for comp in components[1:]:
                mod = getattr(mod, comp)
            return mod
        except ImportError:
            E5MessageBox.critical(
                self,
                self.tr("Configuration Page Error"),
                self.tr("""<p>The configuration page <b>{0}</b>"""
                        """ could not be loaded.</p>""").format(name))
            return None
        
    def __showConfigurationPage(self, itm, column):
        """
        Private slot to show a selected configuration page.
        
        @param itm reference to the selected item (QTreeWidgetItem)
        @param column column that was selected (integer) (ignored)
        """
        pageName = itm.getPageName()
        self.showConfigurationPageByName(pageName, setCurrent=False)
        
    def __initPage(self, pageData):
        """
        Private method to initialize a configuration page.
        
        @param pageData data structure for the page to initialize
        @return reference to the initialized page
        """
        page = None
        if isinstance(pageData[2], types.FunctionType):
            page = pageData[2](self)
        else:
            mod = self.__importConfigurationPage(pageData[2])
            if mod:
                page = mod.create(self)
        if page is not None:
            self.configStack.addWidget(page)
            pageData[-1] = page
            try:
                page.setMode(self.displayMode)
            except AttributeError:
                pass
        return page
        
    def showConfigurationPageByName(self, pageName, setCurrent=True):
        """
        Public slot to show a named configuration page.
        
        @param pageName name of the configuration page to show (string)
        @param setCurrent flag indicating to set the current item (boolean)
        """
        if pageName == "empty" or pageName not in self.configItems:
            page = self.emptyPage
        else:
            pageData = self.configItems[pageName]
            if pageData[-1] is None and pageData[2] is not None:
                # the page was not loaded yet, create it
                page = self.__initPage(pageData)
            else:
                page = pageData[-1]
            if page is None:
                page = self.emptyPage
            elif setCurrent:
                items = self.configList.findItems(
                    pageData[0],
                    Qt.MatchFixedString | Qt.MatchRecursive)
                for item in items:
                    if item.data(0, Qt.UserRole) == pageName:
                        self.configList.setCurrentItem(item)
        self.configStack.setCurrentWidget(page)
        ssize = self.scrollArea.size()
        if self.scrollArea.horizontalScrollBar():
            ssize.setHeight(
                ssize.height() -
                self.scrollArea.horizontalScrollBar().height() - 2)
        if self.scrollArea.verticalScrollBar():
            ssize.setWidth(
                ssize.width() -
                self.scrollArea.verticalScrollBar().width() - 2)
        psize = page.minimumSizeHint()
        self.configStack.resize(max(ssize.width(), psize.width()),
                                max(ssize.height(), psize.height()))
        
        if page != self.emptyPage:
            page.polishPage()
            self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True)
            self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True)
        else:
            self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
            self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
        
        # reset scrollbars
        for sb in [self.scrollArea.horizontalScrollBar(),
                   self.scrollArea.verticalScrollBar()]:
            if sb:
                sb.setValue(0)
        
        self.__currentConfigurationPageName = pageName
        
    def getConfigurationPageName(self):
        """
        Public method to get the page name of the current page.
        
        @return page name of the current page (string)
        """
        return self.__currentConfigurationPageName
        
    def calledFromEric(self):
        """
        Public method to check, if invoked from within eric.
        
        @return flag indicating invocation from within eric (boolean)
        """
        return self.fromEric
        
    def getPage(self, pageName):
        """
        Public method to get a reference to the named page.
        
        @param pageName name of the configuration page (string)
        @return reference to the page or None, indicating page was
            not loaded yet
        """
        return self.configItems[pageName][-1]
        
    def getLexers(self):
        """
        Public method to get a reference to the lexers dictionary.
        
        @return reference to the lexers dictionary
        """
        return self.lexers
        
    def setPreferences(self):
        """
        Public method called to store the selected values into the preferences
        storage.
        """
        for key, pageData in list(self.configItems.items()):
            if pageData[-1]:
                pageData[-1].save()
                # page was loaded (and possibly modified)
                QApplication.processEvents()    # ensure HMI is responsive
        
    def on_buttonBox_clicked(self, button):
        """
        Private slot called by a button of the button box clicked.
        
        @param button button that was clicked (QAbstractButton)
        """
        if button == self.buttonBox.button(QDialogButtonBox.Apply):
            self.on_applyButton_clicked()
        elif button == self.buttonBox.button(QDialogButtonBox.Reset):
            self.on_resetButton_clicked()
        
    @pyqtSlot()
    def on_applyButton_clicked(self):
        """
        Private slot called to apply the settings of the current page.
        """
        if self.configStack.currentWidget() != self.emptyPage:
            page = self.configStack.currentWidget()
            savedState = page.saveState()
            page.save()
            self.preferencesChanged.emit()
            if savedState is not None:
                page.setState(savedState)
            page.polishPage()
        
    @pyqtSlot()
    def on_resetButton_clicked(self):
        """
        Private slot called to reset the settings of the current page.
        """
        if self.configStack.currentWidget() != self.emptyPage:
            currentPage = self.configStack.currentWidget()
            savedState = currentPage.saveState()
            pageName = self.configList.currentItem().getPageName()
            self.configStack.removeWidget(currentPage)
            if pageName == "editorHighlightingStylesPage":
                self.__initLexers()
            self.configItems[pageName][-1] = None
            
            self.showConfigurationPageByName(pageName)
            if savedState is not None:
                self.configStack.currentWidget().setState(savedState)
        
    def getExpandedEntries(self):
        """
        Public method to get a list of expanded entries.
        
        @return list of expanded entries (list of string)
        """
        return self.__expandedEntries
    
    @pyqtSlot(QTreeWidgetItem)
    def on_configList_itemCollapsed(self, item):
        """
        Private slot handling a list entry being collapsed.
        
        @param item reference to the collapsed item (QTreeWidgetItem)
        """
        pageName = item.data(0, Qt.UserRole)
        if pageName in self.__expandedEntries:
            self.__expandedEntries.remove(pageName)
    
    @pyqtSlot(QTreeWidgetItem)
    def on_configList_itemExpanded(self, item):
        """
        Private slot handling a list entry being expanded.
        
        @param item reference to the expanded item (QTreeWidgetItem)
        """
        pageName = item.data(0, Qt.UserRole)
        if pageName not in self.__expandedEntries:
            self.__expandedEntries.append(pageName)