示例#1
0
 def __init__(self, parent = None):
     super().__init__(parent),
     self.mUi = Ui_NewMapDialog()
     self.mUi.setupUi(self)
     self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
     # Restore previously used settings
     prefs = preferences.Preferences.instance()
     s = prefs.settings()
     orientation = s.value(ORIENTATION_KEY, 0)
     mapWidth = s.value(MAP_WIDTH_KEY, 100)
     mapHeight = s.value(MAP_HEIGHT_KEY, 100)
     tileWidth = s.value(TILE_WIDTH_KEY, 32)
     tileHeight = s.value(TILE_HEIGHT_KEY, 32)
     self.mUi.layerFormat.addItem(QCoreApplication.translate("PreferencesDialog", "XML"))
     self.mUi.layerFormat.addItem(QCoreApplication.translate("PreferencesDialog", "Base64 (uncompressed)"))
     self.mUi.layerFormat.addItem(QCoreApplication.translate("PreferencesDialog", "Base64 (gzip compressed)"))
     self.mUi.layerFormat.addItem(QCoreApplication.translate("PreferencesDialog", "Base64 (zlib compressed)"))
     self.mUi.layerFormat.addItem(QCoreApplication.translate("PreferencesDialog", "CSV"))
     self.mUi.renderOrder.addItem(QCoreApplication.translate("PreferencesDialog", "Right Down"))
     self.mUi.renderOrder.addItem(QCoreApplication.translate("PreferencesDialog", "Right Up"))
     self.mUi.renderOrder.addItem(QCoreApplication.translate("PreferencesDialog", "Left Down"))
     self.mUi.renderOrder.addItem(QCoreApplication.translate("PreferencesDialog", "Left Up"))
     self.mUi.orientation.addItem(self.tr("Orthogonal"), Map.Orientation.Orthogonal)
     self.mUi.orientation.addItem(self.tr("Isometric"), Map.Orientation.Isometric)
     self.mUi.orientation.addItem(self.tr("Isometric (Staggered)"), Map.Orientation.Staggered)
     self.mUi.orientation.addItem(self.tr("Hexagonal (Staggered)"), Map.Orientation.Hexagonal)
     self.mUi.orientation.setCurrentIndex(orientation)
     self.mUi.layerFormat.setCurrentIndex(prefs.layerDataFormat().value)
     self.mUi.renderOrder.setCurrentIndex(prefs.mapRenderOrder().value)
     self.mUi.mapWidth.setValue(mapWidth)
     self.mUi.mapHeight.setValue(mapHeight)
     self.mUi.tileWidth.setValue(tileWidth)
     self.mUi.tileHeight.setValue(tileHeight)
     # Make the font of the pixel size label smaller
     font = self.mUi.pixelSizeLabel.font()
     size = QFontInfo(font).pointSizeF()
     font.setPointSizeF(size - 1)
     self.mUi.pixelSizeLabel.setFont(font)
     self.mUi.mapWidth.valueChanged.connect(self.refreshPixelSize)
     self.mUi.mapHeight.valueChanged.connect(self.refreshPixelSize)
     self.mUi.tileWidth.valueChanged.connect(self.refreshPixelSize)
     self.mUi.tileHeight.valueChanged.connect(self.refreshPixelSize)
     self.mUi.orientation.currentIndexChanged.connect(self.refreshPixelSize)
     self.refreshPixelSize()
    def doubleClickedCB(self, model_index):
        """Double click handler for the property table"""

        # Get translation object
        _ = get_app()._tr

        # Get data model and selection
        model = self.clip_properties_model.model

        row = model_index.row()
        selected_label = model.item(row, 0)
        self.selected_item = model.item(row, 1)

        if selected_label:
            cur_property = selected_label.data()
            property_type = cur_property[1]["type"]

            if property_type == "color":
                # Get current value of color
                red = cur_property[1]["red"]["value"]
                green = cur_property[1]["green"]["value"]
                blue = cur_property[1]["blue"]["value"]

                # Show color dialog
                currentColor = QColor(red, green, blue)
                log.debug("Launching ColorPicker for %s", currentColor.name())
                ColorPicker(
                    currentColor, parent=self, title=_("Select a Color"),
                    callback=self.color_callback)
                return

            elif property_type == "font":
                # Get font from user
                current_font_name = cur_property[1].get("memo", "sans")
                current_font = QFont(current_font_name)
                font, ok = QFontDialog.getFont(current_font, caption=("Change Font"))

                # Update font
                if ok and font:
                    fontinfo = QFontInfo(font)
                    # TODO: pass font details to value_updated so we can set multiple values
                    font_details = { "font_family": fontinfo.family(),
                                     "font_style": fontinfo.styleName(),
                                     "font_weight": fontinfo.weight(),
                                     "font_size_pixel": fontinfo.pixelSize() }
                    self.clip_properties_model.value_updated(self.selected_item, value=fontinfo.family())
示例#3
0
def _get_monospace_font_impl(small=False) -> QFont:
    begun = time.monotonic()
    multiplier = 0.8 if small else 1.0
    min_font_size = min(7, QFont().pointSize())
    preferred = [
        'Consolas', 'DejaVu Sans Mono', 'Monospace', 'Lucida Console', 'Monaco'
    ]
    for name in preferred:
        font = QFont(name)
        if QFontInfo(font).fixedPitch():
            font.setPointSize(
                round(max(min_font_size,
                          QFont().pointSize() * multiplier)))
            _logger.info('Selected monospace font (%.6f seconds): %r',
                         time.monotonic() - begun, font.toString())
            return font

    font = QFont()
    font.setStyleHint(QFont().Monospace)
    font.setFamily('monospace')
    _logger.info('Using fallback monospace font (%.6f seconds): %r',
                 time.monotonic() - begun, font.toString())
    return font
示例#4
0
    def exportSource(self):
        """
        Public method performing the export.
        """
        filename = self._getFileName(self.tr("RTF Files (*.rtf)"))
        if not filename:
            return

        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            QApplication.processEvents()

            self.editor.recolor(0, -1)
            lex = self.editor.getLexer()

            tabSize = Preferences.getEditor("TabWidth")
            if tabSize == 0:
                tabSize = 4
            wysiwyg = Preferences.getEditorExporter("RTF/WYSIWYG")
            if wysiwyg:
                if lex:
                    defaultFont = lex.font(QsciScintilla.STYLE_DEFAULT)
                else:
                    defaultFont = Preferences.getEditorOtherFonts(
                        "DefaultFont")
            else:
                defaultFont = Preferences.getEditorExporter("RTF/Font")
            fontface = defaultFont.family()
            fontsize = QFontInfo(defaultFont).pointSize() << 1
            if fontsize == 0:
                fontsize = 10 << 1
            characterset = QsciScintilla.SC_CHARSET_DEFAULT
            tabs = Preferences.getEditorExporter("RTF/UseTabs")

            if lex:
                fgColour = lex.color(QsciScintilla.STYLE_DEFAULT)
                bgColour = lex.paper(QsciScintilla.STYLE_DEFAULT)
            else:
                fgColour = self.editor.color()
                bgColour = self.editor.paper()

            try:
                f = open(filename, "w", encoding="utf-8")

                styles = {}
                fonts = {}
                colors = {}
                lastStyle = ""

                f.write(self.RTF_HEADEROPEN + self.RTF_FONTDEFOPEN)
                fonts[0] = fontface
                fontCount = 1
                f.write(self.RTF_FONTDEF.format(0, characterset, fontface))
                colors[0] = fgColour
                colors[1] = bgColour
                colorCount = 2

                if lex:
                    istyle = 0
                    while istyle <= QsciScintilla.STYLE_MAX:
                        if (istyle < QsciScintilla.STYLE_DEFAULT or
                                istyle > QsciScintilla.STYLE_LASTPREDEFINED):
                            if lex.description(istyle):
                                font = lex.font(istyle)
                                if wysiwyg:
                                    fontKey = None
                                    for key, value in list(fonts.items()):
                                        if value.lower() == \
                                                font.family().lower():
                                            fontKey = key
                                            break
                                    if fontKey is None:
                                        fonts[fontCount] = font.family()
                                        f.write(
                                            self.RTF_FONTDEF.format(
                                                fontCount, characterset,
                                                font.family()))
                                        fontKey = fontCount
                                        fontCount += 1
                                    lastStyle = self.RTF_SETFONTFACE + \
                                        "{0:d}".format(fontKey)
                                else:
                                    lastStyle = self.RTF_SETFONTFACE + "0"

                                if wysiwyg and QFontInfo(font).pointSize():
                                    lastStyle += self.RTF_SETFONTSIZE + \
                                        "{0:d}".format(
                                            QFontInfo(font).pointSize() << 1)
                                else:
                                    lastStyle += self.RTF_SETFONTSIZE + \
                                        "{0:d}".format(fontsize)

                                sColour = lex.color(istyle)
                                sColourKey = None
                                for key, value in list(colors.items()):
                                    if value == sColour:
                                        sColourKey = key
                                        break
                                if sColourKey is None:
                                    colors[colorCount] = sColour
                                    sColourKey = colorCount
                                    colorCount += 1
                                lastStyle += self.RTF_SETCOLOR + \
                                    "{0:d}".format(sColourKey)

                                sColour = lex.paper(istyle)
                                sColourKey = None
                                for key, value in list(colors.items()):
                                    if value == sColour:
                                        sColourKey = key
                                        break
                                if sColourKey is None:
                                    colors[colorCount] = sColour
                                    sColourKey = colorCount
                                    colorCount += 1
                                lastStyle += self.RTF_SETBACKGROUND + \
                                    "{0:d}".format(sColourKey)

                                if font.bold():
                                    lastStyle += self.RTF_BOLD_ON
                                else:
                                    lastStyle += self.RTF_BOLD_OFF
                                if font.italic():
                                    lastStyle += self.RTF_ITALIC_ON
                                else:
                                    lastStyle += self.RTF_ITALIC_OFF
                                styles[istyle] = lastStyle
                            else:
                                styles[istyle] = \
                                    self.RTF_SETFONTFACE + "0" + \
                                    self.RTF_SETFONTSIZE + \
                                    "{0:d}".format(fontsize) + \
                                    self.RTF_SETCOLOR + "0" + \
                                    self.RTF_SETBACKGROUND + "1" + \
                                    self.RTF_BOLD_OFF + self.RTF_ITALIC_OFF

                        istyle += 1
                else:
                    styles[0] = self.RTF_SETFONTFACE + "0" + \
                        self.RTF_SETFONTSIZE + \
                        "{0:d}".format(fontsize) + \
                        self.RTF_SETCOLOR + "0" + \
                        self.RTF_SETBACKGROUND + "1" + \
                        self.RTF_BOLD_OFF + self.RTF_ITALIC_OFF

                f.write(self.RTF_FONTDEFCLOSE + self.RTF_COLORDEFOPEN)
                for value in list(colors.values()):
                    f.write(
                        self.RTF_COLORDEF.format(value.red(), value.green(),
                                                 value.blue()))
                f.write(self.RTF_COLORDEFCLOSE)
                f.write(self.RTF_INFOOPEN + self.RTF_COMMENT)
                f.write(time.strftime(self.RTF_CREATED))
                f.write(self.RTF_INFOCLOSE)
                f.write(self.RTF_HEADERCLOSE + self.RTF_BODYOPEN +
                        self.RTF_SETFONTFACE + "0" + self.RTF_SETFONTSIZE +
                        "{0:d}".format(fontsize) + self.RTF_SETCOLOR + "0 ")
                lastStyle = self.RTF_SETFONTFACE + "0" + \
                    self.RTF_SETFONTSIZE + "{0:d}".format(fontsize) + \
                    self.RTF_SETCOLOR + "0" + \
                    self.RTF_SETBACKGROUND + "1" + \
                    self.RTF_BOLD_OFF + self.RTF_ITALIC_OFF

                lengthDoc = self.editor.length()
                prevCR = False
                column = 0
                pos = 0
                deltaStyle = ""
                styleCurrent = -1
                utf8 = self.editor.isUtf8()
                utf8Ch = b""
                utf8Len = 0

                while pos < lengthDoc:
                    ch = self.editor.byteAt(pos)
                    style = self.editor.styleAt(pos)
                    if style != styleCurrent:
                        deltaStyle = self.__GetRTFStyleChange(
                            lastStyle, styles[style])
                        if deltaStyle:
                            f.write(deltaStyle)
                        styleCurrent = style
                        lastStyle = styles[style]

                    if ch == b'{':
                        f.write('\\{')
                    elif ch == b'}':
                        f.write('\\}')
                    elif ch == b'\\':
                        f.write('\\\\')
                    elif ch == b'\t':
                        if tabs:
                            f.write(self.RTF_TAB)
                        else:
                            ts = tabSize - (column % tabSize)
                            f.write(' ' * ts)
                            column += ts - 1
                    elif ch == b'\n':
                        if not prevCR:
                            f.write(self.RTF_EOLN)
                            column -= 1
                    elif ch == b'\r':
                        f.write(self.RTF_EOLN)
                        column -= 1
                    else:
                        if ord(ch) > 0x7F and utf8:
                            utf8Ch += ch
                            if utf8Len == 0:
                                if (utf8Ch[0] & 0xF0) == 0xF0:
                                    utf8Len = 4
                                elif (utf8Ch[0] & 0xE0) == 0xE0:
                                    utf8Len = 3
                                elif (utf8Ch[0] & 0xC0) == 0xC0:
                                    utf8Len = 2
                                column -= 1  # will be incremented again later
                            elif len(utf8Ch) == utf8Len:
                                ch = utf8Ch.decode('utf8')
                                if ord(ch) <= 0xff:
                                    f.write("\\'{0:x}".format(ord(ch)))
                                else:
                                    f.write("\\u{0:d}\\'{1:x}".format(
                                        ord(ch),
                                        ord(ch) & 0xFF))
                                utf8Ch = b""
                                utf8Len = 0
                            else:
                                column -= 1  # will be incremented again later
                        else:
                            f.write(ch.decode())

                    column += 1
                    prevCR = ch == b'\r'
                    pos += 1

                f.write(self.RTF_BODYCLOSE)
                f.close()
            except IOError as err:
                QApplication.restoreOverrideCursor()
                E5MessageBox.critical(
                    self.editor, self.tr("Export source"),
                    self.tr("""<p>The source could not be exported to"""
                            """ <b>{0}</b>.</p><p>Reason: {1}</p>""").format(
                                filename, str(err)))
        finally:
            QApplication.restoreOverrideCursor()
示例#5
0
 def get_font_display_str(self):
     info = QFontInfo(self.font)
     info_str = f"{info.pointSize()}pt {info.family()}"
     return info_str
示例#6
0
 def fontPrev(self):
     # Update font preview
     f = self.fontComboBox.currentFont()
     self.font.setFamily(QFontInfo(f).family())
     self.font.setPointSize(self.fontSize.value())
     self.fontPreview.setFont(self.font)
示例#7
0
    def __init__(self):
        """ Initialise the page. """

        super().__init__()

        self._project = None

        # Create the page's GUI.
        layout = QGridLayout()

        form = BetterForm()

        self._name_edit = QLineEdit(
            placeholderText="Application name",
            whatsThis="The name of the application. It will default to "
            "the base name of the application script without any "
            "extension.",
            textEdited=self._name_changed)
        form.addRow("Name", self._name_edit)

        self._script_edit = FilenameEditor(
            "Application Script",
            placeholderText="Application script",
            whatsThis="The name of the application's optional main script "
            "file.",
            textEdited=self._script_changed)
        form.addRow("Main script file", self._script_edit)

        self._entry_point_edit = QLineEdit(
            placeholderText="Entry point in application package",
            whatsThis="The name of the optional entry point in the "
            "application's package.",
            textEdited=self._entry_point_changed)
        form.addRow("Entry point", self._entry_point_edit)

        self._sys_path_edit = QLineEdit(
            placeholderText="Additional sys.path directories",
            whatsThis="A space separated list of additional directories, "
            "ZIP files and eggs to add to <tt>sys.path</tt>. Only "
            "set this if you want to allow external packages to "
            "be imported.",
            textEdited=self._sys_path_changed)
        form.addRow("sys.path", self._sys_path_edit)

        layout.addLayout(form, 0, 0)

        options_layout = BetterForm()

        self._console_edit = QCheckBox(
            "Use console (Windows)",
            whatsThis="Enable console output for Windows applications. "
            "Console output will be enabled automatically if no "
            "graphical PyQt modules are used.",
            stateChanged=self._console_changed)
        options_layout.addRow(self._console_edit)

        self._bundle_edit = QCheckBox(
            "Application bundle (macOS)",
            whatsThis="Build an application bundle on macOS. If it is not "
            "checked then the application will be built as a "
            "simple executable.",
            stateChanged=self._bundle_changed)
        options_layout.addRow(self._bundle_edit)

        layout.addLayout(options_layout, 0, 1)

        # Extra space is needed before the application package editor.
        layout.setRowMinimumHeight(
            1, 1.4 * QFontInfo(QGuiApplication.font()).pixelSize())

        self._package_edit = _ApplicationPackageEditor()
        self._package_edit.package_changed.connect(self._package_changed)
        package_edit_gb = QGroupBox(self._package_edit.title)
        package_edit_gb.setFlat(True)
        package_edit_gb.setLayout(self._package_edit)
        layout.addWidget(package_edit_gb, 2, 0, 1, 2)

        qmake = CollapsibleWidget("Additional qmake Configuration")
        self._qmake_edit = QPlainTextEdit(
            whatsThis="Any text entered here will be appended to the "
            "generated <tt>.pro</tt> that will be processed by "
            "<tt>qmake</tt>.",
            textChanged=self._qmake_changed)
        qmake.setWidget(self._qmake_edit)
        layout.addWidget(qmake, 3, 0, 1, 2)

        self.setLayout(layout)
示例#8
0
    def generate(self,
                 tabSize=4,
                 useTabs=False,
                 wysiwyg=True,
                 folding=False,
                 onlyStylesUsed=False,
                 titleFullPath=False):
        """
        Public method to generate HTML for the source editor.
        
        @keyparam tabSize size of tabs (integer)
        @keyparam useTabs flag indicating the use of tab characters (boolean)
        @keyparam wysiwyg flag indicating colorization (boolean)
        @keyparam folding flag indicating usage of fold markers
        @keyparam onlyStylesUsed flag indicating to include only style
            definitions for styles used in the source (boolean)
        @keyparam titleFullPath flag indicating to include the full file path
            in the title tag (boolean)
        @return generated HTML text (string)
        """
        self.editor.recolor(0, -1)

        lengthDoc = self.editor.length()
        styleIsUsed = {}
        if onlyStylesUsed:
            for index in range(QsciScintilla.STYLE_MAX + 1):
                styleIsUsed[index] = False
            # check the used styles
            pos = 0
            while pos < lengthDoc:
                styleIsUsed[self.editor.styleAt(pos) & 0x7F] = True
                pos += 1
        else:
            for index in range(QsciScintilla.STYLE_MAX + 1):
                styleIsUsed[index] = True
        styleIsUsed[QsciScintilla.STYLE_DEFAULT] = True

        html = \
            '''<!DOCTYPE html PUBLIC "-//W3C//DTD''' \
            ''' XHTML 1.0 Transitional//EN"\n''' \
            ''' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">''' \
            '''\n''' \
            '''<html xmlns="http://www.w3.org/1999/xhtml">\n''' \
            '''<head>\n'''
        if titleFullPath:
            html += '''<title>{0}</title>\n'''.format(
                self.editor.getFileName())
        else:
            html += '''<title>{0}</title>\n'''.format(
                os.path.basename(self.editor.getFileName()))
        html += '''<meta name="Generator" content="eric6" />\n''' \
            '''<meta http-equiv="Content-Type" ''' \
            '''content="text/html; charset=utf-8" />\n'''
        if folding:
            html += \
                '''<script language="JavaScript" type="text/javascript">\n''' \
                '''<!--\n''' \
                '''function symbol(id, sym) {\n''' \
                '''  if (id.textContent == undefined) {\n''' \
                '''    id.innerText = sym;\n''' \
                '''  } else {\n''' \
                '''    id.textContent = sym;\n''' \
                '''  }\n''' \
                '''}\n''' \
                '''function toggle(id) {\n''' \
                '''  var thislayer = document.getElementById('ln' + id);\n''' \
                '''  id -= 1;\n''' \
                '''  var togline = document.getElementById('hd' + id);\n''' \
                '''  var togsym = document.getElementById('bt' + id);\n''' \
                '''  if (thislayer.style.display == 'none') {\n''' \
                '''    thislayer.style.display = 'block';\n''' \
                '''    togline.style.textDecoration = 'none';\n''' \
                '''    symbol(togsym, '- ');\n''' \
                '''  } else {\n''' \
                '''    thislayer.style.display = 'none';\n''' \
                '''    togline.style.textDecoration = 'underline';\n''' \
                '''    symbol(togsym, '+ ');\n''' \
                '''  }\n''' \
                '''}\n''' \
                '''//-->\n''' \
                '''</script>\n'''

        lex = self.editor.getLexer()
        if lex:
            bgColour = lex.paper(QsciScintilla.STYLE_DEFAULT).name()
        else:
            bgColour = self.editor.paper().name()

        html += '''<style type="text/css">\n'''
        if lex:
            istyle = 0
            while istyle <= QsciScintilla.STYLE_MAX:
                if (istyle <= QsciScintilla.STYLE_DEFAULT or
                    istyle > QsciScintilla.STYLE_LASTPREDEFINED) and \
                   styleIsUsed[istyle]:
                    if lex.description(istyle) or \
                       istyle == QsciScintilla.STYLE_DEFAULT:
                        font = lex.font(istyle)
                        colour = lex.color(istyle)
                        paper = lex.paper(istyle)
                        if istyle == QsciScintilla.STYLE_DEFAULT:
                            html += '''span {\n'''
                        else:
                            html += '''.S{0:d} {{\n'''.format(istyle)
                        if font.italic():
                            html += '''    font-style: italic;\n'''
                        if font.bold():
                            html += '''    font-weight: bold;\n'''
                        if wysiwyg:
                            html += '''    font-family: '{0}';\n'''.format(
                                font.family())
                        html += '''    color: {0};\n'''.format(colour.name())
                        if istyle != QsciScintilla.STYLE_DEFAULT and \
                           bgColour != paper.name():
                            html += '''    background: {0};\n'''.format(
                                paper.name())
                            html += '''    text-decoration: inherit;\n'''
                        if wysiwyg:
                            html += '''    font-size: {0:d}pt;\n'''.format(
                                QFontInfo(font).pointSize())
                        html += '''}\n'''
                    else:
                        styleIsUsed[istyle] = False
                istyle += 1
        else:
            colour = self.editor.color()
            paper = self.editor.paper()
            font = Preferences.getEditorOtherFonts("DefaultFont")
            html += '''.S0 {\n'''
            if font.italic():
                html += '''    font-style: italic;\n'''
            if font.bold():
                html += '''    font-weight: bold;\n'''
            if wysiwyg:
                html += '''    font-family: '{0}';\n'''.format(font.family())
            html += '''    color: {0};\n'''.format(colour.name())
            if bgColour != paper.name():
                html += '''    background: {0};\n'''.format(paper.name())
                html += '''    text-decoration: inherit;\n'''
            if wysiwyg:
                html += '''    font-size: {0:d}pt;\n'''.format(
                    QFontInfo(font).pointSize())
            html += '''}\n'''
        html += '''</style>\n'''
        html += '''</head>\n'''

        html += '''<body bgcolor="{0}">\n'''.format(bgColour)
        line = self.editor.lineAt(0)
        level = self.editor.foldLevelAt(line) - QsciScintilla.SC_FOLDLEVELBASE
        levelStack = [level]
        styleCurrent = self.editor.styleAt(0)
        inStyleSpan = False
        inFoldSpan = False
        # Global span for default attributes
        if wysiwyg:
            html += '''<span>'''
        else:
            html += '''<pre>'''

        if folding:
            if self.editor.foldFlagsAt(line) & \
               QsciScintilla.SC_FOLDLEVELHEADERFLAG:
                html += '''<span id="hd{0:d}" onclick="toggle('{1:d}')">'''\
                        .format(line, line + 1)
                html += '''<span id="bt{0:d}">- </span>'''.format(line)
                inFoldSpan = True
            else:
                html += '''&nbsp; '''

        if styleIsUsed[styleCurrent]:
            html += '''<span class="S{0:0d}">'''.format(styleCurrent)
            inStyleSpan = True

        column = 0
        pos = 0
        utf8 = self.editor.isUtf8()
        utf8Ch = b""
        utf8Len = 0

        while pos < lengthDoc:
            ch = self.editor.byteAt(pos)
            style = self.editor.styleAt(pos)
            if style != styleCurrent:
                if inStyleSpan:
                    html += '''</span>'''
                    inStyleSpan = False
                if ch not in [b'\r', b'\n']:  # no need of a span for the EOL
                    if styleIsUsed[style]:
                        html += '''<span class="S{0:d}">'''.format(style)
                        inStyleSpan = True
                    styleCurrent = style

            if ch == b' ':
                if wysiwyg:
                    prevCh = b''
                    if column == 0:
                        # at start of line, must put a &nbsp;
                        # because regular space will be collapsed
                        prevCh = b' '
                    while pos < lengthDoc and self.editor.byteAt(pos) == b' ':
                        if prevCh != b' ':
                            html += ' '
                        else:
                            html += '''&nbsp;'''
                        prevCh = self.editor.byteAt(pos)
                        pos += 1
                        column += 1
                    pos -= 1
                    # the last incrementation will be done by the outer loop
                else:
                    html += ' '
                    column += 1
            elif ch == b'\t':
                ts = tabSize - (column % tabSize)
                if wysiwyg:
                    html += '''&nbsp;''' * ts
                    column += ts
                else:
                    if useTabs:
                        html += '\t'
                        column += 1
                    else:
                        html += ' ' * ts
                        column += ts
            elif ch in [b'\r', b'\n']:
                if inStyleSpan:
                    html += '''</span>'''
                    inStyleSpan = False
                if inFoldSpan:
                    html += '''</span>'''
                    inFoldSpan = False
                if ch == b'\r' and self.editor.byteAt(pos + 1) == b'\n':
                    pos += 1  # CR+LF line ending, skip the "extra" EOL char
                column = 0
                if wysiwyg:
                    html += '''<br />'''

                styleCurrent = self.editor.styleAt(pos + 1)
                if folding:
                    line = self.editor.lineAt(pos + 1)
                    newLevel = self.editor.foldLevelAt(line)

                    if newLevel < level:
                        while levelStack[-1] > newLevel:
                            html += '''</span>'''
                            levelStack.pop()
                    html += '\n'  # here to get clean code
                    if newLevel > level:
                        html += '''<span id="ln{0:d}">'''.format(line)
                        levelStack.append(newLevel)
                    if self.editor.foldFlagsAt(line) & \
                       QsciScintilla.SC_FOLDLEVELHEADERFLAG:
                        html += \
                            '''<span id="hd{0:d}"''' \
                            ''' onclick="toggle('{1:d}')">''' \
                            .format(line, line + 1)
                        html += '''<span id="bt{0:d}">- </span>'''.format(line)
                        inFoldSpan = True
                    else:
                        html += '''&nbsp; '''
                    level = newLevel
                else:
                    html += '\n'

                if styleIsUsed[styleCurrent] and \
                   self.editor.byteAt(pos + 1) not in [b'\r', b'\n']:
                    # We know it's the correct next style,
                    # but no (empty) span for an empty line
                    html += '''<span class="S{0:0d}">'''.format(styleCurrent)
                    inStyleSpan = True
            else:
                if ch == b'<':
                    html += '''&lt;'''
                elif ch == b'>':
                    html += '''&gt'''
                elif ch == b'&':
                    html += '''&amp;'''
                else:
                    if ord(ch) > 127 and utf8:
                        utf8Ch += ch
                        if utf8Len == 0:
                            if (utf8Ch[0] & 0xF0) == 0xF0:
                                utf8Len = 4
                            elif (utf8Ch[0] & 0xE0) == 0xE0:
                                utf8Len = 3
                            elif (utf8Ch[0] & 0xC0) == 0xC0:
                                utf8Len = 2
                            column -= 1  # will be incremented again later
                        elif len(utf8Ch) == utf8Len:
                            ch = utf8Ch.decode('utf8')
                            html += Utilities.html_encode(ch)
                            utf8Ch = b""
                            utf8Len = 0
                        else:
                            column -= 1  # will be incremented again later
                    else:
                        html += ch.decode()
                column += 1

            pos += 1

        if inStyleSpan:
            html += '''</span>'''

        if folding:
            while levelStack:
                html += '''</span>'''
                levelStack.pop()

        if wysiwyg:
            html += '''</span>'''
        else:
            html += '''</pre>'''

        html += '''</body>\n</html>\n'''

        return html
示例#9
0
 def get_default_font_family(self):
     font = QFont('Monospace')
     font.setStyleHint(QFont.Monospace)
     return QFontInfo(font).family()
示例#10
0
    def _doBuild(self, bldObj, isPreview=False, doConvert=True):
        """Rund the build with a specific build object.
        """
        tStart = int(time())

        # Get Settings
        fmtTitle      = self.fmtTitle.text()
        fmtChapter    = self.fmtChapter.text()
        fmtUnnumbered = self.fmtUnnumbered.text()
        fmtScene      = self.fmtScene.text()
        fmtSection    = self.fmtSection.text()
        buildLang     = self.buildLang.currentData()
        hideScene     = self.hideScene.isChecked()
        hideSection   = self.hideSection.isChecked()
        textFont      = self.textFont.text()
        textSize      = self.textSize.value()
        lineHeight    = self.lineHeight.value()
        justifyText   = self.justifyText.isChecked()
        noStyling     = self.noStyling.isChecked()
        incSynopsis   = self.includeSynopsis.isChecked()
        incComments   = self.includeComments.isChecked()
        incKeywords   = self.includeKeywords.isChecked()
        novelFiles    = self.novelFiles.isChecked()
        noteFiles     = self.noteFiles.isChecked()
        ignoreFlag    = self.ignoreFlag.isChecked()
        includeBody   = self.includeBody.isChecked()
        replaceUCode  = self.replaceUCode.isChecked()

        # The language lookup dict is reloaded if needed
        self.theProject.setProjectLang(buildLang)

        # Get font information
        fontInfo = QFontInfo(QFont(textFont, textSize))
        textFixed = fontInfo.fixedPitch()

        isHtml = isinstance(bldObj, ToHtml)
        isOdt = isinstance(bldObj, ToOdt)

        bldObj.setTitleFormat(fmtTitle)
        bldObj.setChapterFormat(fmtChapter)
        bldObj.setUnNumberedFormat(fmtUnnumbered)
        bldObj.setSceneFormat(fmtScene, hideScene)
        bldObj.setSectionFormat(fmtSection, hideSection)

        bldObj.setFont(textFont, textSize, textFixed)
        bldObj.setJustify(justifyText)
        bldObj.setLineHeight(lineHeight)

        bldObj.setSynopsis(incSynopsis)
        bldObj.setComments(incComments)
        bldObj.setKeywords(incKeywords)
        bldObj.setBodyText(includeBody)

        if isHtml:
            bldObj.setStyles(not noStyling)
            bldObj.setReplaceUnicode(replaceUCode)

        if isOdt:
            bldObj.setColourHeaders(not noStyling)
            bldObj.setLanguage(buildLang)
            bldObj.initDocument()

        # Make sure the project and document is up to date
        self.mainGui.saveDocument()

        self.buildProgress.setMaximum(len(self.theProject.tree))
        self.buildProgress.setValue(0)

        for nItt, tItem in enumerate(self.theProject.tree):

            noteRoot = noteFiles
            noteRoot &= tItem.itemType == nwItemType.ROOT
            noteRoot &= tItem.itemClass != nwItemClass.NOVEL
            noteRoot &= tItem.itemClass != nwItemClass.ARCHIVE

            try:
                if noteRoot:
                    # Add headers for root folders of notes
                    bldObj.addRootHeading(tItem.itemHandle)
                    if doConvert:
                        bldObj.doConvert()

                elif self._checkInclude(tItem, noteFiles, novelFiles, ignoreFlag):
                    bldObj.setText(tItem.itemHandle)
                    bldObj.doPreProcessing()
                    bldObj.tokenizeText()
                    bldObj.doHeaders()
                    if doConvert:
                        bldObj.doConvert()
                    bldObj.doPostProcessing()

            except Exception:
                logger.error("Failed to build document '%s'", tItem.itemHandle)
                logException()
                if isPreview:
                    self.docView.setText((
                        "Failed to generate preview. "
                        "Document with title '%s' could not be parsed."
                    ) % tItem.itemName)

                return False

            # Update progress bar, also for skipped items
            self.buildProgress.setValue(nItt+1)

        if isOdt:
            bldObj.closeDocument()

        tEnd = int(time())
        logger.debug("Built project in %.3f ms", 1000*(tEnd - tStart))

        if bldObj.errData:
            self.mainGui.makeAlert([
                self.tr("There were problems when building the project:")
            ] + bldObj.errData, nwAlert.ERROR)

        return
示例#11
0
    def paint(
        self,
        painter: QPainter,
        option: QStyleOptionViewItem,
        idx: QModelIndex,
    ) -> None:
        font_family = idx.data(Qt.ItemDataRole.DisplayRole)
        font = QFont(option.font)
        font.setPointSize(QFontInfo(font).pointSize() * 3 // 2)
        font2 = QFont(font)
        font2.setFamily(font_family)

        if option.state & QStyle.StateFlag.State_Selected:
            painter.save()
            painter.setBrush(option.palette.highlight())
            painter.setPen(Qt.PenStyle.NoPen)
            painter.drawRect(option.rect)
            painter.setPen(QPen(option.palette.highlightedText(), 0))

        icon = self.bitmap
        if QFontDatabase().isSmoothlyScalable(font_family):
            icon = self.truetype
        actual_size = icon.actualSize(option.rect.size())

        icon.paint(
            painter,
            option.rect,
            Qt.AlignmentFlag(Qt.AlignmentFlag.AlignLeft
                             | Qt.AlignmentFlag.AlignVCenter),
        )
        if option.direction == Qt.LayoutDirection.RightToLeft:
            option.rect.setRight(option.rect.right() - actual_size.width() - 4)
        else:
            option.rect.setLeft(option.rect.left() + actual_size.width() + 4)

        half1 = QRect(option.rect)
        half2 = QRect(option.rect)
        half1.setRight(half1.right() // 2)
        half2.setLeft(half1.right())

        painter.drawText(
            half1,
            Qt.AlignmentFlag.AlignVCenter
            | Qt.AlignmentFlag.AlignLeading
            | Qt.TextFlag.TextSingleLine,
            font_family,
        )

        old = painter.font()
        painter.setFont(font2)
        painter.drawText(
            half2,
            Qt.AlignmentFlag.AlignVCenter
            | Qt.AlignmentFlag.AlignLeading
            | Qt.TextFlag.TextSingleLine,
            self.sample_text,
        )
        painter.setFont(old)

        if option.state & QStyle.StateFlag.State_Selected:
            painter.restore()
示例#12
0
 def reportCodeViewerProperties(self, font):
     wposition = self.pos()
     font_info = QFontInfo(font)
     print("---------- Code Viewer Report ----------")
     print("Size: width: %d, height: %d" % (self.width, self.height))
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y()))
     print("Top-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width, wposition.y()))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y() + self.height))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width, wposition.y() + self.height))
     print("---------- Side Bar    Report ----------")
     print("Size: width: %d, height: %d" %
           (self.listWidth, self.editorHeight))
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y()))
     print("Top-Right position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth, wposition.y()))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y() + self.editorHeight))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth,
            wposition.y() + self.editorHeight))
     print("---------- Code Editor Report ----------")
     print("Size: width: %d, height: %d" %
           (self.editorWidth, self.editorHeight))
     print("Margins: %f pixels" % self.editor.document().documentMargin())
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth, wposition.y()))
     print(
         "Top-Right position in screen: (%d, %d)" %
         (wposition.x() + self.listWidth + self.editorWidth, wposition.y()))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth,
            wposition.y() + self.editorHeight))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth + self.editorWidth,
            wposition.y() + self.editorHeight))
     print("Padding: left: %d, top: %d, bottom: %d, right: %d" %
           (self.padding_left, self.padding_top, self.padding_bottom,
            self.padding_right))
     print("---------- Font report (font) ----------")
     print("font family: %s" % font.family())
     print("font pixelSize: %f" % font.pixelSize())
     print("font pointSize: %f" % font.pointSize())
     print("font pointSizeF: %f" % font.pointSizeF())
     print("QFont.pixelSize(): %f" % font.pixelSize())
     print("---------- QFontInfo   (font) ----------")
     print("family(): %s" % font_info.family())
     print("pixelSize(): %f" % font_info.pixelSize())
     print("pointSize(): %f" % font_info.pointSize())
     print("pointSizeF(): %f" % font_info.pointSizeF())
     print("QFontInfo.pixelSize(): %d" % font_info.pixelSize())
     print("---------- QFontMetrics (font) ---------")
     print("QFontMetrics.lineSpacing(): %f" %
           QFontMetrics(font).lineSpacing())
     print("QFontMetrics.leading(): %f" % QFontMetrics(font).leading())
     print("QFontMetrics.height(): %f" % QFontMetrics(font).height())
     print("---------- Eye tracking area  ----------")
     x1 = wposition.x() + self.listWidth + self.padding_left
     y1 = wposition.y() + self.padding_top
     x2 = wposition.x(
     ) + self.listWidth + self.editorWidth - self.padding_right
     y2 = wposition.y() + self.editorHeight - self.padding_bottom
     self.editor.x_offset = x1  # For the eye tracker, as it uses the entire screen
     self.editor.y_offset = y1  # For the eye tracker, as it uses the entire screen
     self.editor.most_right_x = x2
     self.editor.most_bottom_y = y2
     print("Size: width: %d, height: %d" % (x2 - x1, y2 - y1))
     print("Top-Left position in screen: (%d, %d)" % (x1, y1))
     print("Top-Right position in screen: (%d, %d)" % (x2, y1))
     print("Bottom-Left position in screen: (%d, %d)" % (x1, y2))
     print("Bottom-Right position in screen: (%d, %d)" % (x2, y2))
     print("x_offset = %d" % x1)
     print("y_offset = %d" % y1)
     print("---------- Status Bar  Report ----------")
     print("Size: width: %d, height: %d" %
           (self.width, self.status_bar_height))
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y() + self.editorHeight))
     print("Top-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width, wposition.y() + self.editorHeight))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x(),
            wposition.y() + self.editorHeight + self.status_bar_height))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width,
            wposition.y() + self.editorHeight + self.status_bar_height))
     print("----------------------------------------")
    def contextMenuEvent(self, event):
        """ Display context menu """
        # Get property being acted on
        index = self.indexAt(event.pos())
        if not index.isValid():
            event.ignore()
            return

        # Get data model and selection
        idx = self.indexAt(event.pos())
        row = idx.row()
        selected_label = idx.model().item(row, 0)
        selected_value = idx.model().item(row, 1)
        self.selected_item = selected_value
        frame_number = self.clip_properties_model.frame_number

        # Get translation object
        _ = get_app()._tr

        # If item selected
        if selected_label:
            # Get data from selected item
            cur_property = selected_label.data()
            property_name = cur_property[1]["name"]
            self.property_type = cur_property[1]["type"]
            points = cur_property[1]["points"]
            self.choices = cur_property[1]["choices"]
            property_key = cur_property[0]
            clip_id, item_type = selected_value.data()
            log.info("Context menu shown for %s (%s) for clip %s on frame %s" % (property_name, property_key, clip_id, frame_number))
            log.info("Points: %s" % points)

            # Clear menu if models updated
            if self.menu_reset:
                self.choices = []
                self.menu_reset = False

            # Handle parent effect options
            if property_key == "parent_effect_id" and not self.choices:
                clip_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                # Instantiate the timeline
                timeline_instance = get_app().window.timeline_sync.timeline
                # Instantiate this effect
                effect = timeline_instance.GetClipEffect(clip_id)
                effect_json = json.loads(effect.Json())

                # Loop through timeline's clips
                for clip_instance in timeline_instance.Clips():
                    clip_instance_id = clip_instance.Id()
                    # Avoid parent a clip effect to it's own effect
                    if (clip_instance_id != effect.ParentClipId()):
                        # Clip's propertyJSON data
                        clip_instance_data = Clip.get(id = clip_instance_id).data
                        # Path to the clip file
                        clip_instance_path = clip_instance_data["reader"]["path"]
                        # Iterate through all clip files on the timeline
                        for clip_number in range(self.files_model.rowCount()):
                            clip_index = self.files_model.index(clip_number, 0)
                            clip_name = clip_index.sibling(clip_number, 1).data()
                            clip_path = os.path.join(clip_index.sibling(clip_number, 4).data(), clip_name)
                            # Check if the timeline's clip file name matches the clip the user selected
                            if (clip_path == clip_instance_path):
                                # Generate the clip icon to show in the selection menu
                                clip_instance_icon = clip_index.data(Qt.DecorationRole)
                        effect_choices = [{"name": "None",
                                            "value": "None",
                                            "selected": False,
                                            "icon": QIcon()}]
                        # Iterate through clip's effects
                        for effect_data in clip_instance_data["effects"]:
                            # Make sure the user can only set a parent effect of the same type as this effect
                            if effect_data['class_name'] == effect_json['class_name']:
                                effect_id = effect_data["id"]
                                effect_name = effect_data['class_name']
                                effect_icon = QIcon(QPixmap(os.path.join(info.PATH, "effects", "icons", "%s.png" % effect_data['class_name'].lower())))
                                effect_choices.append({"name": effect_id,
                                                "value": effect_id,
                                                "selected": False,
                                                "icon": effect_icon})
                        self.choices.append({"name": _(clip_instance_data["title"]),
                                            "value": effect_choices,
                                            "selected": False,
                                            "icon": clip_instance_icon})


            # Handle selected object options (ObjectDetection effect)
            if property_key == "selected_object_index" and not self.choices:
                # Get all visible object's indexes
                timeline_instance = get_app().window.timeline_sync.timeline
                # Instantiate the effect
                effect = timeline_instance.GetClipEffect(clip_id)
                # Get the indexes and IDs of the visible objects
                visible_objects = json.loads(effect.GetVisibleObjects(frame_number))
                # Add visible objects as choices
                object_index_choices = []
                for object_index in visible_objects["visible_objects_index"]:
                    object_index_choices.append({
                                "name": str(object_index),
                                "value": str(object_index),
                                "selected": False,
                                "icon": QIcon()
                            })
                self.choices.append({"name": _("Detected Objects"), "value": object_index_choices, "selected": False, "icon": None})

            # Handle property to set the Tracked Object's child clip
            if property_key == "child_clip_id" and not self.choices:
                clip_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                # Instantiate the timeline
                timeline_instance = get_app().window.timeline_sync.timeline
                current_effect = timeline_instance.GetClipEffect(clip_id)

                # Loop through timeline's clips
                for clip_instance in timeline_instance.Clips():
                    clip_instance_id = clip_instance.Id()

                    # Avoid attach a clip to it's own object
                    if (clip_instance_id != clip_id and (current_effect and clip_instance_id != current_effect.ParentClip().Id())):
                        # Clip's propertyJSON data
                        clip_instance_data = Clip.get(id = clip_instance_id).data
                        # Path to the clip file
                        clip_instance_path = clip_instance_data["reader"]["path"]
                        # Iterate through all clip files on the timeline
                        for clip_number in range(self.files_model.rowCount()):
                            clip_index = self.files_model.index(clip_number, 0)
                            clip_name = clip_index.sibling(clip_number, 1).data()
                            clip_path = os.path.join(clip_index.sibling(clip_number, 4).data(), clip_name)
                            # Check if the timeline's clip file name matches the clip the user selected
                            if (clip_path == clip_instance_path):
                                # Generate the clip icon to show in the selection menu
                                clip_instance_icon = clip_index.data(Qt.DecorationRole)
                                self.choices.append({"name": clip_instance_data["title"],
                                              "value": clip_instance_id,
                                              "selected": False,
                                              "icon": clip_instance_icon})

            # Handle clip attach options
            if property_key == "parentObjectId" and not self.choices:
                # Add all Clips as choices - initialize with None
                tracked_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                clip_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                # Instantiate the timeline
                timeline_instance = get_app().window.timeline_sync.timeline
                # Loop through timeline's clips
                for clip_instance in timeline_instance.Clips():
                    clip_instance_id = clip_instance.Id()
                    # Avoid attach a clip to it's own object
                    if (clip_instance_id != clip_id):
                        # Clip's propertyJSON data
                        clip_instance_data = Clip.get(id = clip_instance_id).data
                        # Path to the clip file
                        clip_instance_path = clip_instance_data["reader"]["path"]
                        # Iterate through all clip files on the timeline
                        for clip_number in range(self.files_model.rowCount()):
                            clip_index = self.files_model.index(clip_number, 0)
                            clip_name = clip_index.sibling(clip_number, 1).data()
                            clip_path = os.path.join(clip_index.sibling(clip_number, 4).data(), clip_name)
                            # Check if the timeline's clip file name matches the clip the user selected
                            if (clip_path == clip_instance_path):
                                # Generate the clip icon to show in the selection menu
                                clip_instance_icon = clip_index.data(Qt.DecorationRole)
                                clip_choices.append({"name": clip_instance_data["title"],
                                              "value": clip_instance_id,
                                              "selected": False,
                                              "icon": clip_instance_icon})
                        # Get the pixmap of the clip icon
                        icon_size = 72
                        icon_pixmap = clip_instance_icon.pixmap(icon_size, icon_size)
                        # Add tracked objects to the selection menu
                        tracked_objects = []
                        for effect in clip_instance_data["effects"]:
                            # Check if effect has a tracked object
                            if effect.get("has_tracked_object"):
                                # Instantiate the effect
                                effect_instance = timeline_instance.GetClipEffect(effect["id"])
                                # Get the visible object's ids
                                visible_objects_id = json.loads(effect_instance.GetVisibleObjects(frame_number))["visible_objects_id"]
                                for object_id in visible_objects_id:
                                    # Get the Tracked Object properties
                                    object_properties = json.loads(timeline_instance.GetTrackedObjectValues(object_id, 0))
                                    x1 = object_properties['x1']
                                    y1 = object_properties['y1']
                                    x2 = object_properties['x2']
                                    y2 = object_properties['y2']
                                    # Get the tracked object's icon from the clip's icon
                                    tracked_object_icon = icon_pixmap.copy(QRect(x1*icon_size, y1*icon_size, (x2-x1)*icon_size, (y2-y1)*icon_size)).scaled(icon_size, icon_size)
                                    tracked_objects.append({"name": str(object_id),
                                                            "value": str(object_id),
                                                            "selected": False,
                                                            "icon": QIcon(tracked_object_icon)})
                        tracked_choices.append({"name": clip_instance_data["title"],
                                              "value": tracked_objects,
                                              "selected": False,
                                              "icon": clip_instance_icon})
                self.choices.append({"name": _("Tracked Objects"), "value": tracked_choices, "selected": False, "icon": None})
                self.choices.append({"name": _("Clips"), "value": clip_choices, "selected": False, "icon": None})

            # Handle reader type values
            if self.property_type == "reader" and not self.choices:
                # Add all files
                file_choices = []
                for i in range(self.files_model.rowCount()):
                    idx = self.files_model.index(i, 0)
                    if not idx.isValid():
                        continue
                    icon = idx.data(Qt.DecorationRole)
                    name = idx.sibling(i, 1).data()
                    path = os.path.join(idx.sibling(i, 4).data(), name)

                    # Append file choice
                    file_choices.append({"name": name,
                                         "value": path,
                                         "selected": False,
                                         "icon": icon
                                         })

                # Add root file choice
                self.choices.append({"name": _("Files"), "value": file_choices, "selected": False, icon: None})

                # Add all transitions
                trans_choices = []
                for i in range(self.transition_model.rowCount()):
                    idx = self.transition_model.index(i, 0)
                    if not idx.isValid():
                        continue
                    icon = idx.data(Qt.DecorationRole)
                    name = idx.sibling(i, 1).data()
                    path = idx.sibling(i, 3).data()

                    # Append transition choice
                    trans_choices.append({"name": name,
                                          "value": path,
                                          "selected": False,
                                          "icon": icon
                                          })

                # Add root transitions choice
                self.choices.append({"name": _("Transitions"), "value": trans_choices, "selected": False})

            # Handle reader type values
            if property_name == "Track" and self.property_type == "int" and not self.choices:
                # Populate all display track names
                all_tracks = get_app().project.get("layers")
                display_count = len(all_tracks)
                for track in reversed(sorted(all_tracks, key=itemgetter('number'))):
                    # Append track choice
                    track_name = track.get("label") or _("Track %s") % display_count
                    self.choices.append({"name": track_name, "value": track.get("number"), "selected": False, "icon": None})
                    display_count -= 1
                return

            elif self.property_type == "font":
                # Get font from user
                current_font_name = cur_property[1].get("memo", "sans")
                current_font = QFont(current_font_name)
                font, ok = QFontDialog.getFont(current_font, caption=("Change Font"))

                # Update font
                if ok and font:
                    fontinfo = QFontInfo(font)
                    self.clip_properties_model.value_updated(self.selected_item, value=fontinfo.family())

            # Define bezier presets
            bezier_presets = [
                (0.250, 0.100, 0.250, 1.000, _("Ease (Default)")),
                (0.420, 0.000, 1.000, 1.000, _("Ease In")),
                (0.000, 0.000, 0.580, 1.000, _("Ease Out")),
                (0.420, 0.000, 0.580, 1.000, _("Ease In/Out")),

                (0.550, 0.085, 0.680, 0.530, _("Ease In (Quad)")),
                (0.550, 0.055, 0.675, 0.190, _("Ease In (Cubic)")),
                (0.895, 0.030, 0.685, 0.220, _("Ease In (Quart)")),
                (0.755, 0.050, 0.855, 0.060, _("Ease In (Quint)")),
                (0.470, 0.000, 0.745, 0.715, _("Ease In (Sine)")),
                (0.950, 0.050, 0.795, 0.035, _("Ease In (Expo)")),
                (0.600, 0.040, 0.980, 0.335, _("Ease In (Circ)")),
                (0.600, -0.280, 0.735, 0.045, _("Ease In (Back)")),

                (0.250, 0.460, 0.450, 0.940, _("Ease Out (Quad)")),
                (0.215, 0.610, 0.355, 1.000, _("Ease Out (Cubic)")),
                (0.165, 0.840, 0.440, 1.000, _("Ease Out (Quart)")),
                (0.230, 1.000, 0.320, 1.000, _("Ease Out (Quint)")),
                (0.390, 0.575, 0.565, 1.000, _("Ease Out (Sine)")),
                (0.190, 1.000, 0.220, 1.000, _("Ease Out (Expo)")),
                (0.075, 0.820, 0.165, 1.000, _("Ease Out (Circ)")),
                (0.175, 0.885, 0.320, 1.275, _("Ease Out (Back)")),

                (0.455, 0.030, 0.515, 0.955, _("Ease In/Out (Quad)")),
                (0.645, 0.045, 0.355, 1.000, _("Ease In/Out (Cubic)")),
                (0.770, 0.000, 0.175, 1.000, _("Ease In/Out (Quart)")),
                (0.860, 0.000, 0.070, 1.000, _("Ease In/Out (Quint)")),
                (0.445, 0.050, 0.550, 0.950, _("Ease In/Out (Sine)")),
                (1.000, 0.000, 0.000, 1.000, _("Ease In/Out (Expo)")),
                (0.785, 0.135, 0.150, 0.860, _("Ease In/Out (Circ)")),
                (0.680, -0.550, 0.265, 1.550, _("Ease In/Out (Back)"))
            ]

            # Add menu options for keyframes
            menu = QMenu(self)
            if self.property_type == "color":
                Color_Action = menu.addAction(_("Select a Color"))
                Color_Action.triggered.connect(functools.partial(self.Color_Picker_Triggered, cur_property))
                menu.addSeparator()
            if points > 1:
                # Menu items only for multiple points
                Bezier_Menu = menu.addMenu(self.bezier_icon, _("Bezier"))
                for bezier_preset in bezier_presets:
                    preset_action = Bezier_Menu.addAction(bezier_preset[4])
                    preset_action.triggered.connect(functools.partial(
                        self.Bezier_Action_Triggered, bezier_preset))
                Linear_Action = menu.addAction(self.linear_icon, _("Linear"))
                Linear_Action.triggered.connect(self.Linear_Action_Triggered)
                Constant_Action = menu.addAction(self.constant_icon, _("Constant"))
                Constant_Action.triggered.connect(self.Constant_Action_Triggered)
                menu.addSeparator()
            if points >= 1:
                # Menu items for one or more points
                Insert_Action = menu.addAction(_("Insert Keyframe"))
                Insert_Action.triggered.connect(self.Insert_Action_Triggered)
                Remove_Action = menu.addAction(_("Remove Keyframe"))
                Remove_Action.triggered.connect(self.Remove_Action_Triggered)
                menu.popup(event.globalPos())

            # Menu for choices
            if not self.choices:
                return
            for choice in self.choices:
                if type(choice["value"]) != list:
                    # Just add root choice item
                    Choice_Action = menu.addAction(_(choice["name"]))
                    Choice_Action.setData(choice["value"])
                    Choice_Action.triggered.connect(self.Choice_Action_Triggered)
                    continue

                # Add sub-choice items (for nested choice lists)
                # Divide into smaller QMenus (since large lists cover the entire screen)
                # For example: Transitions -> 1 -> sub items
                SubMenu = None
                if choice["icon"] is not None:
                    SubMenuRoot = menu.addMenu(choice["icon"], choice["name"])
                else:
                    SubMenuRoot = menu.addMenu(choice["name"])

                SubMenuSize = 25
                SubMenuNumber = 0
                if len(choice["value"]) > SubMenuSize:
                    SubMenu = SubMenuRoot.addMenu(str(SubMenuNumber))
                else:
                    SubMenu = SubMenuRoot
                for i, sub_choice in enumerate(choice["value"], 1):
                    # Divide SubMenu if it's item is a list
                    if type(sub_choice["value"]) == list:
                        SubSubMenu = SubMenu.addMenu(sub_choice["icon"], sub_choice["name"])
                        for sub_sub_choice in sub_choice["value"]:
                            Choice_Action = SubSubMenu.addAction(
                                sub_sub_choice["icon"], sub_sub_choice["name"])
                            Choice_Action.setData(sub_sub_choice["value"])
                            Choice_Action.triggered.connect(self.Choice_Action_Triggered)
                    else:
                        if i % SubMenuSize == 0:
                            SubMenuNumber += 1
                            SubMenu = SubMenuRoot.addMenu(str(SubMenuNumber))
                        Choice_Action = SubMenu.addAction(
                            sub_choice["icon"], _(sub_choice["name"]))
                        Choice_Action.setData(sub_choice["value"])
                        Choice_Action.triggered.connect(self.Choice_Action_Triggered)

            # Show choice menuk
            menu.popup(event.globalPos())
示例#14
0
class Ui_MarkWindow(QMainWindow):

    # 构造方法
    def __init__(self):
        super(Ui_MarkWindow, self).__init__()
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)  # 只显示关闭按钮
        self.setupUi(self)  # 初始化窗体设置

    # 自动生成的代码,用来对窗体进行设置
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(578, 418)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        # 设置图片显示列表
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect(0, 0, 141, 391))
        self.listWidget.setObjectName("listWidget")
        # 设置加载图片按钮
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(150, 0, 75, 23))
        self.pushButton.setObjectName("pushButton")

        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(150, 30, 421, 151))
        self.groupBox.setObjectName("groupBox")

        # 设置文字水印单选按钮
        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(20, 20, 101, 16))
        self.radioButton.setChecked(True)  # 默认选中
        self.radioButton.setObjectName("radioButton")

        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(30, 50, 54, 16))
        self.label.setObjectName("label")

        # 设置要输入水印文字的文本框
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit.setGeometry(QtCore.QRect(90, 50, 241, 20))
        self.lineEdit.setObjectName("lineEdit")

        # 设置“字体设置”按钮
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(340, 50, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")

        # 设置图片水印单选按钮
        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(20, 80, 91, 16))
        self.radioButton_2.setChecked(False)  # 默认不选中
        self.radioButton_2.setObjectName("radioButton_2")

        # 设置选择水印图片按钮
        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(340, 110, 75, 23))
        self.pushButton_3.setObjectName("pushButton_3")

        self.label_2 = QtWidgets.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(30, 110, 54, 16))
        self.label_2.setObjectName("label_2")

        # 设置显示水印图片路径的文本框
        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_2.setGeometry(QtCore.QRect(90, 110, 241, 20))
        self.lineEdit_2.setObjectName("lineEdit_2")

        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(150, 190, 421, 71))
        self.groupBox_2.setObjectName("groupBox_2")

        self.label_3 = QtWidgets.QLabel(self.groupBox_2)
        self.label_3.setGeometry(QtCore.QRect(270, 31, 54, 21))
        self.label_3.setObjectName("label_3")

        # 设置水印位置选择框
        self.comboBox = QtWidgets.QComboBox(self.groupBox_2)
        self.comboBox.setGeometry(QtCore.QRect(330, 30, 71, 22))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem('左上角')
        self.comboBox.addItem('右上角')
        self.comboBox.addItem('左下角')
        self.comboBox.addItem('右下角')
        self.comboBox.addItem('居中位置')
        self.comboBox.setCurrentIndex(0)  # 设置默认选择第一项

        self.label_4 = QtWidgets.QLabel(self.groupBox_2)
        self.label_4.setGeometry(QtCore.QRect(20, 30, 51, 21))
        self.label_4.setObjectName("label_4")

        # 设置水印透明度的滑动条
        self.horizontalSlider = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider.setGeometry(QtCore.QRect(70, 30, 181, 22))
        self.horizontalSlider.setMinimum(1)
        self.horizontalSlider.setMaximum(10)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName("horizontalSlider")

        self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_3.setGeometry(QtCore.QRect(150, 270, 421, 71))
        self.groupBox_3.setObjectName("groupBox_3")

        self.label_6 = QtWidgets.QLabel(self.groupBox_3)
        self.label_6.setGeometry(QtCore.QRect(20, 30, 61, 21))
        self.label_6.setObjectName("label_6")

        # 设置显示保存路径的文本框
        self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_3.setGeometry(QtCore.QRect(80, 30, 241, 20))
        self.lineEdit_3.setObjectName("lineEdit_3")

        # 设置选择图片保存路径的按钮
        self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButton_4.setGeometry(QtCore.QRect(330, 30, 75, 23))
        self.pushButton_4.setObjectName("pushButton_4")

        #设置执行按钮
        self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_5.setGeometry(QtCore.QRect(480, 350, 75, 23))
        self.pushButton_5.setObjectName("pushButton_5")

        MainWindow.setCentralWidget(self.centralwidget)
        #设置状态栏
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        self.statusBar.showMessage('准备就绪…… ')  # 设置状态栏默认值
        MainWindow.setStatusBar(self.statusBar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    # 自动生成的代码,用来设置窗体中控件的默认值
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "图片批量添加水印"))
        self.pushButton.setText(_translate("MainWindow", "加载图片"))
        self.groupBox.setTitle(_translate("MainWindow", "水印设置"))
        self.radioButton.setText(_translate("MainWindow", "添加文字水印"))
        self.label.setText(_translate("MainWindow", "水印文字:"))
        self.pushButton_2.setText(_translate("MainWindow", "字体设置"))
        self.radioButton_2.setText(_translate("MainWindow", "添加图片水印"))
        self.pushButton_3.setText(_translate("MainWindow", "浏览"))
        self.label_2.setText(_translate("MainWindow", "水印图片:"))
        self.groupBox_2.setTitle(_translate("MainWindow", "透明度及位置设置"))
        self.label_3.setText(_translate("MainWindow", "水印位置:"))
        self.label_4.setText(_translate("MainWindow", "透明度:"))
        self.groupBox_3.setTitle(_translate("MainWindow", "路径设置"))
        self.label_6.setText(_translate("MainWindow", "保存位置:"))
        self.pushButton_4.setText(_translate("MainWindow", "浏览"))
        self.pushButton_5.setText(_translate("MainWindow", "执行"))
        # 关联“加载图片”按钮的方法
        self.pushButton.clicked.connect(self.getFiles)
        # 关联“字体设置”按钮的方法
        self.pushButton_2.clicked.connect(self.setFont)
        # 关联“选择图片”按钮的方法
        self.pushButton_3.clicked.connect(self.setImg)
        # 关联“选择保存路径”按钮的方法
        self.pushButton_4.clicked.connect(self.msg)
        # 关联“执行”按钮的方法
        self.pushButton_5.clicked.connect(self.addMark)
        # 关联列表单击方法,用来预览选中的图片
        self.listWidget.itemClicked.connect(self.itemClick)

    # 设置字体
    def setFont(self):
        self.waterfont, ok = QFontDialog.getFont()  # 显示字体对话框
        if ok:  # 判断是否选择了字体
            self.lineEdit.setFont(self.waterfont)  # 设置水印文字的字体
            self.fontSize = QFontMetrics(self.waterfont)  # 获取字体尺寸
            self.fontInfo = QFontInfo(self.waterfont)  # 获取字体信息

    # 是否为图片
    def isImg(self, file):
        file = file.lower()
        if file == '.jpg':
            return True
        elif file == '.png':
            return True
        elif file == '.jpeg':
            return True
        elif file == '.bmp':
            return True
        else:
            return False

    # 获取所有文件
    def getFiles(self):
        try:
            # 选择图片文件夹路径
            self.img_path = QFileDialog.getExistingDirectory(
                None, "选择图片文件夹路径", os.getcwd())
            self.list = os.listdir(self.img_path)  # 遍历选择的文件夹
            num = 0  # 记录图片数量
            self.listWidget.clear()  # 清空列表项
            for i in range(0, len(self.list)):  # 遍历图片列表
                filepath = os.path.join(self.img_path,
                                        self.list[i])  # 记录遍历到的文件名
                if os.path.isfile(filepath):  # 判断是否为文件
                    imgType = os.path.splitext(filepath)[1]  # 获取扩展名
                    if self.isImg(imgType):  # 判断是否为图片
                        num += 1  # 数量加1
                        self.item = QtWidgets.QListWidgetItem(
                            self.listWidget)  # 创建列表项
                        self.item.setText(self.list[i])  # 显示图片列表
            self.statusBar.showMessage('共有图片 ' + str(num) + ' 张')  # 显示图片总数
        except Exception:
            QMessageBox.warning(None, '警告', '请选择一个有效路径……', QMessageBox.Ok)

    # 预览图片
    def itemClick(self, item):
        os.startfile(self.img_path + '\\' + item.text())

    # 选择水印图片
    def setImg(self):
        try:
            # waterimg即为选择的水印图片,第二形参为对话框标题,第三个为对话框打开后默认的路径
            self.waterimg = QFileDialog.getOpenFileName(
                None, '选择水印图片', 'C:\\', "图片文件(*.jpeg;*.png;*.jpg;*.bmp)")
            self.lineEdit_2.setText(self.waterimg[0])  # 显示选择的水印图片
        except Exception as e:
            print(e)

    # 选择保存路径
    def msg(self):
        try:
            # dir_path即为选择的文件夹的绝对路径,第二形参为对话框标题,第三个为对话框打开后默认的路径
            self.dir_path = QFileDialog.getExistingDirectory(
                None, "选择路径", os.getcwd())
            self.lineEdit_3.setText(self.dir_path)  # 显示选择的保存路径
        except Exception as e:
            print(e)

    # 文字水印
    def textMark(self, img, newImgPath):
        try:
            im = Image.open(img).convert('RGBA')  # 打开原始图片,并转换为RGBA
            newImg = Image.new('RGBA', im.size,
                               (255, 255, 255, 0))  # 存储添加水印后的图片
            # 创建字体,说明:默认使用楷体,如果需要使用其他字体,需要将字体文件复制到当前目录中
            # 然后对下面第一个参数进行修改,可以使用self.fontInfo.family()动态获取字体名称,后面加扩展名即可
            font = ImageFont.truetype('simkai.ttf', self.fontInfo.pointSize())
            imagedraw = ImageDraw.Draw(newImg)  # 创建绘制对象
            imgwidth, imgheight = im.size  # 记录图片大小
            txtwidth = self.fontSize.maxWidth() * len(
                self.lineEdit.text())  # 获取字体宽度
            txtheight = self.fontSize.height()  # 获取字体高度

            # 设置水印文字位置
            if self.comboBox.currentText() == '左上角':
                position = (0, 0)
            elif self.comboBox.currentText() == '左下角':
                position = (0, imgheight - txtheight)
            elif self.comboBox.currentText() == '右上角':
                position = (imgwidth - txtwidth, 0)
            elif self.comboBox.currentText() == '右下角':
                position = (imgwidth - txtwidth, imgheight - txtheight)
            elif self.comboBox.currentText() == '居中位置':
                position = (imgwidth / 2, imgheight / 2)
            # 设置文本颜色
            imagedraw.text(position,
                           self.lineEdit.text(),
                           font=font,
                           fill="#FCA454")
            # 设置透明度
            alpha = newImg.split()[3]
            alpha = ImageEnhance.Brightness(alpha).enhance(
                int(self.horizontalSlider.value()) / 10.0)
            newImg.putalpha(alpha)
            Image.alpha_composite(im, newImg).save(newImgPath)  # 保存图片
        except Exception:
            QMessageBox.warning(None, '错误', '图片格式有误,请重新选择……', QMessageBox.Ok)

    # 图片水印
    def imgMark(self, img, newImgPath):
        im = Image.open(img)  # 打开原始图片
        mark = Image.open(self.lineEdit_2.text())  # 打开水印图片
        rgbaim = im.convert('RGBA')  # 将原始图片转换为RGBA
        rgbamark = mark.convert('RGBA')  # 将水印图片转换为RGBA
        imgwidth, imgheight = rgbaim.size  # 获取原始图片尺寸
        nimgwidth, nimgheight = rgbamark.size  # 获取水印图片尺寸
        # 缩放水印图片
        scale = 10
        markscale = max(imgwidth / (scale * nimgwidth),
                        imgheight / (scale * nimgheight))
        newsize = (int(nimgwidth * markscale), int(nimgheight * markscale)
                   )  # 计算新的尺寸大小
        rgbamark = rgbamark.resize(newsize,
                                   resample=Image.ANTIALIAS)  # 重新设置水印图片大小
        nimgwidth, nimgheight = rgbamark.size  # 获取水印图片缩放后的尺寸
        # 计算水印位置
        if self.comboBox.currentText() == '左上角':
            position = (0, 0)
        elif self.comboBox.currentText() == '左下角':
            position = (0, imgheight - nimgheight)
        elif self.comboBox.currentText() == '右上角':
            position = (imgwidth - nimgwidth, 0)
        elif self.comboBox.currentText() == '右下角':
            position = (imgwidth - nimgwidth, imgheight - nimgheight)
        elif self.comboBox.currentText() == '居中位置':
            position = (int(imgwidth / 2), int(imgheight / 2))
        # 设置透明度:img.point(function)接受一个参数,且对图片中的每一个点执行这个函数,这个函数是一个匿名函数,使用lambda表达式来完成
        # convert()函数,用于不同模式图像之间的转换,模式“L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
        # 在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:L = R * 299/1000 + G * 587/1000+ B * 114/1000
        rgbamarkpha = rgbamark.convert("L").point(
            lambda x: x / int(self.horizontalSlider.value()))
        rgbamark.putalpha(rgbamarkpha)
        # 水印位置
        rgbaim.paste(rgbamark, position, rgbamarkpha)
        try:
            rgbaim.save(newImgPath)  # 保存水印图片
        except Exception:
            QMessageBox.warning(None, '错误', '请选择其他路径……', QMessageBox.Ok)

    # 添加水印
    def addMark(self):
        if self.lineEdit_3.text() == '':  # 判断是否选择了保存路径
            QMessageBox.warning(None, '警告', '请选择保存路径', QMessageBox.Ok)
            return
        else:
            num = 0  # 记录处理图片数量
            for i in range(0, self.listWidget.count()):  # 遍历图片列表
                # 设置原始图片路径(包括文件名)
                filepath = os.path.join(self.img_path,
                                        self.listWidget.item(i).text())
                # 设置水印图片保存路径(包括文件名)
                newfilepath = os.path.join(self.lineEdit_3.text(),
                                           self.listWidget.item(i).text())
                if self.radioButton.isChecked():  # 判断是否选择文字水印单选按钮
                    if self.lineEdit.text() == '':  # 判断是否输入了水印文字
                        QMessageBox.warning(None, '警告', '请输入水印文字',
                                            QMessageBox.Ok)
                        return
                    else:
                        self.textMark(filepath,
                                      newfilepath)  # 调用textMark方法添加文字水印
                        num += 1  # 处理图片数量加1
                else:
                    if self.lineEdit_2.text() != '':  # 判断水印图片不为空
                        self.imgMark(filepath,
                                     newfilepath)  # 调用imgMark方法添加图片水印
                        num += 1  # 处理图片数量加1
                    else:
                        QMessageBox.warning(None, '警告', '请选择水印图片',
                                            QMessageBox.Ok)
            self.statusBar.showMessage('任务完成,此次共处理 ' + str(num) +
                                       ' 张图片')  # 显示处理图片总数
示例#15
0
    def exportSource(self):
        """
        Public method performing the export.
        """
        self.pr = PDFRender()

        filename = self._getFileName(self.tr("PDF Files (*.pdf)"))
        if not filename:
            return

        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            QApplication.processEvents()

            self.editor.recolor(0, -1)
            lex = self.editor.getLexer()

            tabSize = self.editor.getEditorConfig("TabWidth")
            if tabSize == 0:
                tabSize = 4

            # get magnification value to add to default screen font size
            self.pr.fontSize = Preferences.getEditorExporter(
                "PDF/Magnification")

            # set font family according to face name
            fontName = Preferences.getEditorExporter("PDF/Font")
            self.pr.fontSet = PDF_FONT_DEFAULT
            if fontName == "Courier":
                self.pr.fontSet = 0
            elif fontName == "Helvetica":
                self.pr.fontSet = 1
            elif fontName == "Times":
                self.pr.fontSet = 2

            # page size: height, width,
            pageSize = Preferences.getEditorExporter("PDF/PageSize")
            try:
                pageDimensions = PDFpageSizes[pageSize]
            except KeyError:
                pageDimensions = PDFpageSizes["A4"]
            self.pr.pageHeight = pageDimensions[0]
            self.pr.pageWidth = pageDimensions[1]

            # page margins: left, right, top, bottom
            # < 0 to use PDF default values
            val = Preferences.getEditorExporter("PDF/MarginLeft")
            if val < 0:
                self.pr.pageMargins["left"] = PDF_MARGIN_DEFAULT
            else:
                self.pr.pageMargins["left"] = val
            val = Preferences.getEditorExporter("PDF/MarginRight")
            if val < 0:
                self.pr.pageMargins["right"] = PDF_MARGIN_DEFAULT
            else:
                self.pr.pageMargins["right"] = val
            val = Preferences.getEditorExporter("PDF/MarginTop")
            if val < 0:
                self.pr.pageMargins["top"] = PDF_MARGIN_DEFAULT
            else:
                self.pr.pageMargins["top"] = val
            val = Preferences.getEditorExporter("PDF/MarginBottom")
            if val < 0:
                self.pr.pageMargins["bottom"] = PDF_MARGIN_DEFAULT
            else:
                self.pr.pageMargins["bottom"] = val

            # collect all styles available for that 'language'
            # or the default style if no language is available...
            if lex:
                istyle = 0
                while istyle <= QsciScintilla.STYLE_MAX:
                    if (istyle <= QsciScintilla.STYLE_DEFAULT
                            or istyle > QsciScintilla.STYLE_LASTPREDEFINED):
                        if (lex.description(istyle)
                                or istyle == QsciScintilla.STYLE_DEFAULT):
                            style = PDFStyle()

                            font = lex.font(istyle)
                            if font.italic():
                                style.font |= 2
                            if font.bold():
                                style.font |= 1

                            colour = lex.color(istyle)
                            style.fore = self.__getPDFRGB(colour)
                            self.pr.style[istyle] = style

                        # grab font size from default style
                        if istyle == QsciScintilla.STYLE_DEFAULT:
                            fontSize = QFontInfo(font).pointSize()
                            if fontSize > 0:
                                self.pr.fontSize += fontSize
                            else:
                                self.pr.fontSize = PDF_FONTSIZE_DEFAULT

                    istyle += 1
            else:
                style = PDFStyle()

                font = Preferences.getEditorOtherFonts("DefaultFont")
                if font.italic():
                    style.font |= 2
                if font.bold():
                    style.font |= 1

                colour = self.editor.color()
                style.fore = self.__getPDFRGB(colour)
                self.pr.style[0] = style
                self.pr.style[QsciScintilla.STYLE_DEFAULT] = style

                fontSize = QFontInfo(font).pointSize()
                if fontSize > 0:
                    self.pr.fontSize += fontSize
                else:
                    self.pr.fontSize = PDF_FONTSIZE_DEFAULT

            try:
                # save file in win ansi using cp1250
                f = open(filename,
                         "w",
                         encoding="cp1250",
                         errors="backslashreplace")

                # initialise PDF rendering
                ot = PDFObjectTracker(f)
                self.pr.oT = ot
                self.pr.startPDF()

                # do here all the writing
                lengthDoc = self.editor.length()

                if lengthDoc == 0:
                    self.pr.nextLine()  # enable zero length docs
                else:
                    pos = 0
                    column = 0
                    utf8 = self.editor.isUtf8()
                    utf8Ch = b""
                    utf8Len = 0

                    while pos < lengthDoc:
                        ch = self.editor.byteAt(pos)
                        style = self.editor.styleAt(pos)

                        if ch == b'\t':
                            # expand tabs
                            ts = tabSize - (column % tabSize)
                            column += ts
                            self.pr.add(' ' * ts, style)
                        elif ch == b'\r' or ch == b'\n':
                            if (ch == b'\r'
                                    and self.editor.byteAt(pos + 1) == b'\n'):
                                pos += 1
                            # close and begin a newline...
                            self.pr.nextLine()
                            column = 0
                        else:
                            # write the character normally...
                            if ord(ch) > 127 and utf8:
                                utf8Ch += ch
                                if utf8Len == 0:
                                    if (utf8Ch[0] & 0xF0) == 0xF0:
                                        utf8Len = 4
                                    elif (utf8Ch[0] & 0xE0) == 0xE0:
                                        utf8Len = 3
                                    elif (utf8Ch[0] & 0xC0) == 0xC0:
                                        utf8Len = 2
                                    column -= 1
                                    # will be incremented again later
                                elif len(utf8Ch) == utf8Len:
                                    ch = utf8Ch.decode('utf8')
                                    self.pr.add(ch, style)
                                    utf8Ch = b""
                                    utf8Len = 0
                                else:
                                    column -= 1
                                    # will be incremented again later
                            else:
                                self.pr.add(ch.decode(), style)
                            column += 1

                        pos += 1

                # write required stuff and close the PDF file
                self.pr.endPDF()
                f.close()
            except IOError as err:
                QApplication.restoreOverrideCursor()
                E5MessageBox.critical(
                    self.editor, self.tr("Export source"),
                    self.tr("""<p>The source could not be exported to"""
                            """ <b>{0}</b>.</p><p>Reason: {1}</p>""").format(
                                filename, str(err)))
        finally:
            QApplication.restoreOverrideCursor()
示例#16
0
 def setFont(self):
     self.waterfont, ok = QFontDialog.getFont()  # 显示字体对话框
     if ok:  # 判断是否选择了字体
         self.lineEdit.setFont(self.waterfont)  # 设置水印文字的字体
         self.fontSize = QFontMetrics(self.waterfont)  # 获取字体尺寸
         self.fontInfo = QFontInfo(self.waterfont)  # 获取字体信息
示例#17
0
def isFixedPitch(font: QFont) -> bool:
    fi = QFontInfo(font)
    return fi.fixedPitch()