diff options
| author | Denis Jacquerye | 2015-10-19 10:24:34 +0100 |
|---|---|---|
| committer | Denis Jacquerye | 2015-10-19 10:30:56 +0100 |
| commit | 63f83224f474c2c191e8cac3cb6bda8f2cb81b7d (patch) | |
| tree | 16b7c79b713832b93683cca9bc87018c48a3a88e /Lib/defconQt | |
| parent | 9ce52ed3a18616828daf475fc487fd69322bee0e (diff) | |
| download | trufont-63f83224f474c2c191e8cac3cb6bda8f2cb81b7d.tar.bz2 | |
Use PEP8 code style
Diffstat (limited to 'Lib/defconQt')
| -rw-r--r-- | Lib/defconQt/__main__.py | 8 | ||||
| -rw-r--r-- | Lib/defconQt/baseCodeEditor.py | 44 | ||||
| -rw-r--r-- | Lib/defconQt/featureTextEditor.py | 90 | ||||
| -rw-r--r-- | Lib/defconQt/fontInfo.py | 572 | ||||
| -rw-r--r-- | Lib/defconQt/fontView.py | 332 | ||||
| -rw-r--r-- | Lib/defconQt/glyphCollectionView.py | 230 | ||||
| -rw-r--r-- | Lib/defconQt/glyphView.py | 841 | ||||
| -rw-r--r-- | Lib/defconQt/groupsView.py | 90 | ||||
| -rw-r--r-- | Lib/defconQt/layerSetList.py | 21 | ||||
| -rw-r--r-- | Lib/defconQt/objects/defcon.py | 33 | ||||
| -rw-r--r-- | Lib/defconQt/pens/copySelectionPen.py | 16 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/__init__.py | 18 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/glyphViewFactory.py | 36 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/qPainterPathFactory.py | 1 | ||||
| -rw-r--r-- | Lib/defconQt/scriptingWindow.py | 22 | ||||
| -rw-r--r-- | Lib/defconQt/spaceCenter.py | 239 |
16 files changed, 1710 insertions, 883 deletions
diff --git a/Lib/defconQt/__main__.py b/Lib/defconQt/__main__.py index 843a4fb..4a5a849 100644 --- a/Lib/defconQt/__main__.py +++ b/Lib/defconQt/__main__.py @@ -1,5 +1,5 @@ from defconQt.objects.defcon import TFont -from defconQt import icons_db, representationFactories +from defconQt import representationFactories from defconQt.fontView import Application, MainWindow import sys import os @@ -10,10 +10,10 @@ if len(sys.argv) > 1: else: font = None -#from pycallgraph import PyCallGraph -#from pycallgraph.output import GraphvizOutput +# from pycallgraph import PyCallGraph +# from pycallgraph.output import GraphvizOutput representationFactories.registerAllFactories() -#with PyCallGraph(output=GraphvizOutput()): +# with PyCallGraph(output=GraphvizOutput()): app = Application(sys.argv) # TODO: http://stackoverflow.com/a/21330349/2037879 app.setOrganizationName("A. Tétar & Co.") diff --git a/Lib/defconQt/baseCodeEditor.py b/Lib/defconQt/baseCodeEditor.py index cab9ce9..a13faca 100644 --- a/Lib/defconQt/baseCodeEditor.py +++ b/Lib/defconQt/baseCodeEditor.py @@ -1,10 +1,13 @@ -from PyQt5.QtCore import QRegularExpression, Qt -from PyQt5.QtGui import QColor, QFont, QPainter, QSyntaxHighlighter, QTextCursor +from PyQt5.QtCore import QRegularExpression, Qt, QSize +from PyQt5.QtGui import ( + QColor, QFont, QPainter, QSyntaxHighlighter, QTextCursor) from PyQt5.QtWidgets import QPlainTextEdit, QWidget # maybe add closeEvent + class LineNumberArea(QWidget): + def __init__(self, editor): super(LineNumberArea, self).__init__(editor) @@ -14,7 +17,9 @@ class LineNumberArea(QWidget): def paintEvent(self, event): self.parent().lineNumberAreaPaintEvent(event) + class CodeEditor(QPlainTextEdit): + def __init__(self, text=None, parent=None): super(CodeEditor, self).__init__(parent) # https://gist.github.com/murphyrandle/2921575 @@ -44,14 +49,17 @@ class CodeEditor(QPlainTextEdit): block = self.firstVisibleBlock() blockNumber = block.blockNumber() - top = int(self.blockBoundingGeometry(block).translated(self.contentOffset()).top()) + top = int( + self.blockBoundingGeometry(block).translated( + self.contentOffset()).top()) bottom = top + int(self.blockBoundingRect(block).height()) while block.isValid() and top <= event.rect().bottom(): if block.isVisible() and bottom >= event.rect().top(): number = str(blockNumber + 1) painter.drawText(4, top, self.lineNumbers.width() - 8, - self.fontMetrics().height(), Qt.AlignRight, number) + self.fontMetrics().height(), Qt.AlignRight, + number) block = block.next() top = bottom bottom = top + int(self.blockBoundingRect(block).height()) @@ -64,7 +72,8 @@ class CodeEditor(QPlainTextEdit): top /= 10 digits += 1 # Avoid too frequent geometry changes - if digits < 3: digits = 3 + if digits < 3: + digits = 3 return 10 + self.fontMetrics().width('9') * digits def updateLineNumberArea(self, rect, dy): @@ -72,7 +81,7 @@ class CodeEditor(QPlainTextEdit): self.lineNumbers.scroll(0, dy) else: self.lineNumbers.update(0, rect.y(), self.lineNumbers.width(), - rect.height()) + rect.height()) if rect.contains(self.viewport().rect()): self.updateLineNumberAreaWidth(0) @@ -84,7 +93,7 @@ class CodeEditor(QPlainTextEdit): super(CodeEditor, self).resizeEvent(event) cr = self.contentsRect() self.lineNumbers.setGeometry(cr.left(), cr.top(), - self.lineNumberAreaWidth(), cr.height()) + self.lineNumberAreaWidth(), cr.height()) def findLineIndentLevel(self, cursor): indent = 0 @@ -93,12 +102,14 @@ class CodeEditor(QPlainTextEdit): cursor.movePosition(QTextCursor.StartOfLine) while lineLength > 0: cursor.movePosition(QTextCursor.NextCharacter, - QTextCursor.KeepAnchor, len(self.indent)) + QTextCursor.KeepAnchor, len(self.indent)) if cursor.selectedText() == self.indent: indent += 1 - else: break + else: + break # Now move the anchor back to the position() - #cursor.movePosition(QTextCursor.NoMove) # shouldn't NoMove work here? + # shouldn't NoMove work here? + # cursor.movePosition(QTextCursor.NoMove) cursor.setPosition(cursor.position()) lineLength -= 1 cursor.movePosition(QTextCursor.EndOfLine) @@ -110,7 +121,8 @@ class CodeEditor(QPlainTextEdit): cursor = self.textCursor() indentLvl = self.findLineIndentLevel(cursor) if self.openBlockDelimiter is not None: - cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) + cursor.movePosition(QTextCursor.PreviousCharacter, + QTextCursor.KeepAnchor) if cursor.selectedText() == self.openBlockDelimiter: indentLvl += 1 super(CodeEditor, self).keyPressEvent(event) @@ -122,8 +134,9 @@ class CodeEditor(QPlainTextEdit): cursor.insertText(self.indent) elif key == Qt.Key_Backspace: cursor = self.textCursor() - cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor, - len(self.indent)) + cursor.movePosition(QTextCursor.PreviousCharacter, + QTextCursor.KeepAnchor, + len(self.indent)) if cursor.selectedText() == self.indent: cursor.removeSelectedText() else: @@ -136,13 +149,16 @@ class CodeEditor(QPlainTextEdit): font = self.font() newPointSize = font.pointSize() + event.angleDelta().y() / 120.0 event.accept() - if newPointSize < 6: return + if newPointSize < 6: + return font.setPointSize(newPointSize) self.setFont(font) else: super(CodeEditor, self).wheelEvent(event) + class CodeHighlighter(QSyntaxHighlighter): + def __init__(self, parent=None): super(CodeHighlighter, self).__init__(parent) self.highlightingRules = [] diff --git a/Lib/defconQt/featureTextEditor.py b/Lib/defconQt/featureTextEditor.py index b11947a..6e7d4c8 100644 --- a/Lib/defconQt/featureTextEditor.py +++ b/Lib/defconQt/featureTextEditor.py @@ -1,12 +1,13 @@ from defconQt.baseCodeEditor import CodeEditor, CodeHighlighter -from PyQt5.QtCore import QFile, Qt -from PyQt5.QtGui import (QColor, QFont, QKeySequence, QPainter, QTextCharFormat, - QTextCursor) -from PyQt5.QtWidgets import (QApplication, QFileDialog, QMainWindow, QMenu, - QMessageBox, QPlainTextEdit, QWidget) +from PyQt5.QtCore import Qt +from PyQt5.QtGui import (QColor, QFont, QKeySequence, QTextCharFormat, + QTextCursor) +from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QMessageBox + # TODO: implement search and replace class MainEditWindow(QMainWindow): + def __init__(self, font=None, parent=None): super(MainEditWindow, self).__init__(parent) @@ -27,16 +28,26 @@ class MainEditWindow(QMainWindow): self.editor.undoAvailable.connect(self.setWindowModified) def setWindowTitle(self, title, font): - if font is not None: puts = "[*]%s – %s %s" % (title, self.font.info.familyName, self.font.info.styleName) - else: puts = "[*]%s" % title + if font is not None: + puts = "[*]%s – %s %s" % ( + title, self.font.info.familyName, self.font.info.styleName) + else: + puts = "[*]%s" % title super(MainEditWindow, self).setWindowTitle(puts) def closeEvent(self, event): if self.editor.document().isModified(): name = QApplication.applicationName() - closeDialog = QMessageBox(QMessageBox.Question, name, "Save your changes?", - QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self) - closeDialog.setInformativeText("Your changes will be lost if you don’t save them.") + closeDialog = QMessageBox( + QMessageBox.Question, + name, + "Save your changes?", + QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, + self + ) + closeDialog.setInformativeText( + "Your changes will be lost if you don’t save them." + ) closeDialog.setModal(True) ret = closeDialog.exec_() if ret == QMessageBox.Save: @@ -54,7 +65,9 @@ class MainEditWindow(QMainWindow): def save(self): self.editor.write(self.font.features) + class FeatureTextEditor(CodeEditor): + def __init__(self, text=None, parent=None): super(FeatureTextEditor, self).__init__(text, parent) self.openBlockDelimiter = '{' @@ -70,19 +83,23 @@ class FeatureTextEditor(CodeEditor): indentLvl = self.findLineIndentLevel(cursor) newBlock = False - cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) + cursor.movePosition(QTextCursor.PreviousCharacter, + QTextCursor.KeepAnchor) if cursor.selectedText() == self.openBlockDelimiter: - # We don't add a closing tag if there is text right below with the same - # indentation level because in that case the user might just be looking - # to add a new line + # We don't add a closing tag if there is text right + # below with the same indentation level because in + # that case the user might just be looking to add a + # new line ok = cursor.movePosition(QTextCursor.Down) if ok: downIndentLvl = self.findLineIndentLevel(cursor) cursor.select(QTextCursor.LineUnderCursor) - if cursor.selectedText().strip() == '' or downIndentLvl <= indentLvl: + if (cursor.selectedText().strip() == '' + or downIndentLvl <= indentLvl): newBlock = True cursor.movePosition(QTextCursor.Up) - else: newBlock = True + else: + newBlock = True indentLvl += 1 cursor.select(QTextCursor.LineUnderCursor) @@ -102,7 +119,8 @@ class FeatureTextEditor(CodeEditor): cursor.insertText(newLineSpace) if newBlock: cursor.insertText("\n") - newLineSpace = "".join((newLineSpace[:-len(self.indent)], "} ", feature, ";")) + newLineSpace = "".join((newLineSpace[:-len(self.indent)], "} ", + feature, ";")) cursor.insertText(newLineSpace) cursor.movePosition(QTextCursor.Up) cursor.movePosition(QTextCursor.EndOfLine) @@ -110,30 +128,38 @@ class FeatureTextEditor(CodeEditor): else: super(FeatureTextEditor, self).keyPressEvent(event) -keywordPatterns = ["Ascender", "Attach", "CapHeight", "CaretOffset", "CodePageRange", +keywordPatterns = [ + "Ascender", "Attach", "CapHeight", "CaretOffset", "CodePageRange", "Descender", "FontRevision", "GlyphClassDef", "HorizAxis.BaseScriptList", - "HorizAxis.BaseTagList", "HorizAxis.MinMax", "IgnoreBaseGlyphs", "IgnoreLigatures", - "IgnoreMarks", "LigatureCaretByDev", "LigatureCaretByIndex", "LigatureCaretByPos", - "LineGap", "MarkAttachClass", "MarkAttachmentType", "NULL", "Panose", "RightToLeft", - "TypoAscender", "TypoDescender", "TypoLineGap", "UnicodeRange", "UseMarkFilteringSet", - "Vendor", "VertAdvanceY", "VertAxis.BaseScriptList", "VertAxis.BaseTagList", - "VertAxis.MinMax", "VertOriginY", "VertTypoAscender", "VertTypoDescender", - "VertTypoLineGap", "XHeight", "anchorDef", "anchor", "anonymous", "anon", - "by", "contour", "cursive", "device", "enumerate", "enum", "exclude_dflt", - "featureNames", "feature", "from", "ignore", "include_dflt", "include", - "languagesystem", "language", "lookupflag", "lookup", "markClass", "mark", - "nameid", "name", "parameters", "position", "pos", "required", "reversesub", - "rsub", "script", "sizemenuname", "substitute", "subtable", "sub", "table", - "useExtension", "valueRecordDef", "winAscent", "winDescent"] + "HorizAxis.BaseTagList", "HorizAxis.MinMax", "IgnoreBaseGlyphs", + "IgnoreLigatures", "IgnoreMarks", "LigatureCaretByDev", + "LigatureCaretByIndex", "LigatureCaretByPos", "LineGap", "MarkAttachClass", + "MarkAttachmentType", "NULL", "Panose", "RightToLeft", "TypoAscender", + "TypoDescender", "TypoLineGap", "UnicodeRange", "UseMarkFilteringSet", + "Vendor", "VertAdvanceY", "VertAxis.BaseScriptList", + "VertAxis.BaseTagList", "VertAxis.MinMax", "VertOriginY", + "VertTypoAscender", "VertTypoDescender", "VertTypoLineGap", "XHeight", + "anchorDef", "anchor", "anonymous", "anon", "by", "contour", "cursive", + "device", "enumerate", "enum", "exclude_dflt", "featureNames", "feature", + "from", "ignore", "include_dflt", "include", "languagesystem", "language", + "lookupflag", "lookup", "markClass", "mark", "nameid", "name", + "parameters", "position", "pos", "required", "reversesub", "rsub", + "script", "sizemenuname", "substitute", "subtable", "sub", "table", + "useExtension", "valueRecordDef", "winAscent", "winDescent" +] + class FeatureTextHighlighter(CodeHighlighter): + def __init__(self, parent=None): super(FeatureTextHighlighter, self).__init__(parent) keywordFormat = QTextCharFormat() keywordFormat.setForeground(QColor(34, 34, 34)) keywordFormat.setFontWeight(QFont.Bold) - self.highlightingRules.append(("\\b(%s)\\b" % ("|".join(keywordPatterns)), keywordFormat)) + self.highlightingRules.append(("\\b(%s)\\b" + % ("|".join(keywordPatterns)), + keywordFormat)) singleLineCommentFormat = QTextCharFormat() singleLineCommentFormat.setForeground(Qt.darkGray) diff --git a/Lib/defconQt/fontInfo.py b/Lib/defconQt/fontInfo.py index 8be0f1b..45f954f 100644 --- a/Lib/defconQt/fontInfo.py +++ b/Lib/defconQt/fontInfo.py @@ -1,12 +1,19 @@ -from PyQt5.QtCore import *#QDate, QDateTime, QTime, Qt -from PyQt5.QtGui import *#QDoubleValidator, QIntValidator -from PyQt5.QtWidgets import *#QComboBox, QDateTimeEdit, QDialog, QDialogButtonBox, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QScrollArea, QTabWidget, QVBoxLayout, QWidget +from PyQt5.QtCore import QDate, QDateTime, QTime, Qt +from PyQt5.QtGui import QDoubleValidator, QIntValidator +from PyQt5.QtWidgets import ( + QCheckBox, QComboBox, QDateTimeEdit, QDialog, QDialogButtonBox, + QGridLayout, QGroupBox, QLabel, QLineEdit, QPlainTextEdit, QTabWidget, + QVBoxLayout, QWidget) + class InfoTabWidget(QTabWidget): + def addNamedTab(self, tab): self.addTab(tab, tab.name) + class TabDialog(QDialog): + def __init__(self, font, parent=None): super(TabDialog, self).__init__(parent) self.font = font @@ -17,7 +24,8 @@ class TabDialog(QDialog): self.tabWidget.addNamedTab(OpenTypeTab(self.font)) self.tabWidget.addNamedTab(PostScriptTab(self.font)) - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -27,13 +35,15 @@ class TabDialog(QDialog): mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) - self.setWindowTitle("Font Info – %s %s" % (self.font.info.familyName, self.font.info.styleName)) + self.setWindowTitle("Font Info – %s %s" % ( + self.font.info.familyName, self.font.info.styleName)) def accept(self): for i in range(self.tabWidget.count()): self.tabWidget.widget(i).writeValues(self.font) super(TabDialog, self).accept() + class GeneralTab(QWidget): name = "General" @@ -58,19 +68,22 @@ class GeneralTab(QWidget): mainLayout.addWidget(self.designerEdit, 1, 1, 1, 5) designerURLLabel = QLabel("Designer URL:", self) - self.designerURLEdit = QLineEdit(font.info.openTypeNameDesignerURL, self) + self.designerURLEdit = QLineEdit( + font.info.openTypeNameDesignerURL, self) mainLayout.addWidget(designerURLLabel, 2, 0) mainLayout.addWidget(self.designerURLEdit, 2, 1, 1, 5) manufacturerLabel = QLabel("Manufacturer:", self) - self.manufacturerEdit = QLineEdit(font.info.openTypeNameManufacturer, self) + self.manufacturerEdit = QLineEdit( + font.info.openTypeNameManufacturer, self) mainLayout.addWidget(manufacturerLabel, 3, 0) mainLayout.addWidget(self.manufacturerEdit, 3, 1, 1, 5) manufacturerURLLabel = QLabel("Manufacturer URL:", self) - self.manufacturerURLEdit = QLineEdit(font.info.openTypeNameManufacturerURL, self) + self.manufacturerURLEdit = QLineEdit( + font.info.openTypeNameManufacturerURL, self) mainLayout.addWidget(manufacturerURLLabel, 4, 0) mainLayout.addWidget(self.manufacturerURLEdit, 4, 1, 1, 5) @@ -81,15 +94,22 @@ class GeneralTab(QWidget): mainLayout.addWidget(copyrightLabel, 5, 0) mainLayout.addWidget(self.copyrightEdit, 5, 1, 1, 5) - # TODO: give visual feedback of input data validity using QLineEdit lose focus event - # http://snorf.net/blog/2014/08/09/using-qvalidator-in-pyqt4-to-validate-user-input/ + # TODO: give visual feedback of input data validity using QLineEdit + # lose focus event + # http://snorf.net/blog/2014/08/09/using-qvalidator-in-pyqt4-to-validate-user-input/ # noqa versionLabel = QLabel("Version:", self) - versionMajor = str(font.info.versionMajor) if font.info.versionMajor is not None else '' + if font.info.versionMajor is not None: + versionMajor = str(font.info.versionMajor) + else: + versionMajor = '' self.versionMajorEdit = QLineEdit(versionMajor, self) self.versionMajorEdit.setAlignment(Qt.AlignRight) self.versionMajorEdit.setValidator(QIntValidator(self)) versionDotLabel = QLabel(".", self) - versionMinor = str(font.info.versionMinor) if font.info.versionMinor is not None else '' + if font.info.versionMinor is not None: + versionMinor = str(font.info.versionMinor) + else: + versionMinor = '' self.versionMinorEdit = QLineEdit(versionMinor, self) validator = QIntValidator(self) validator.setBottom(0) @@ -102,7 +122,8 @@ class GeneralTab(QWidget): dateCreatedLabel = QLabel("Date created:", self) dateTime = QDateTime() - #dateTime.fromString(font.info.openTypeHeadCreated, "yyyy/MM/dd hh:mm:ss") # XXX: why does this not work? + # dateTime.fromString(font.info.openTypeHeadCreated, "yyyy/MM/dd + # hh:mm:ss") # XXX: why does this not work? dateCreated = font.info.openTypeHeadCreated if dateCreated: parse = dateCreated.split(" ") @@ -144,30 +165,68 @@ class GeneralTab(QWidget): def writeValues(self, font): familyName = self.familyNameEdit.text() - font.info.familyName = familyName if familyName != '' else None + if familyName != '': + font.info.familyName = familyName + else: + font.info.trademark = None styleName = self.styleNameEdit.text() - font.info.styleName = styleName if styleName != '' else None + if styleName != '': + font.info.styleName = styleName + else: + font.info.trademark = None designer = self.designerEdit.text() - font.info.openTypeNameDesigner = designer if designer != '' else None + if designer != '': + font.info.openTypeNameDesigner = designer + else: + font.info.trademark = None designerURL = self.designerURLEdit.text() - font.info.openTypeNameDesignerURL = designerURL if designerURL != '' else None + if designerURL != '': + font.info.openTypeNameDesignerURL = designerURL + else: + font.info.trademark = None manufacturer = self.manufacturerEdit.text() - font.info.openTypeNameManufacturer = manufacturer if manufacturer != '' else None + if manufacturer != '': + font.info.openTypeNameManufacturer = manufacturer + else: + font.info.trademark = None manufacturerURL = self.manufacturerURLEdit.text() - font.info.openTypeNameManufacturerURL = manufacturerURL if manufacturerURL != '' else None + if manufacturerURL != '': + font.info.openTypeNameManufacturerURL = manufacturerURL + else: + font.info.trademark = None copyright = self.copyrightEdit.text() - font.info.copyright = copyright if copyright != '' else None + if copyright != '': + font.info.copyright = copyright + else: + font.info.trademark = None versionMajor = self.versionMajorEdit.text() - font.info.versionMajor = int(versionMajor) if versionMajor else None + if versionMajor: + font.info.versionMajor = int(versionMajor) + else: + font.info.versionMajor = None versionMinor = self.versionMinorEdit.text() - font.info.versionMinor = int(versionMinor) if versionMinor else None - font.info.openTypeHeadCreated = self.dateCreatedEdit.dateTime().toString("yyyy/MM/dd hh:mm:ss") + if versionMinor: + font.info.versionMinor = int(versionMinor) + else: + font.info.versionMinor = None + font.info.openTypeHeadCreated = self.dateCreatedEdit.dateTime( + ).toString("yyyy/MM/dd hh:mm:ss") license = self.licenseEdit.text() - font.info.openTypeNameLicense = license if license != '' else None + if license != '': + font.info.openTypeNameLicense = license + else: + font.info.trademark = None licenseURL = self.licenseURLEdit.text() - font.info.openTypeNameLicenseURL = licenseURL if licenseURL != '' else None + if licenseURL != '': + font.info.openTypeNameLicenseURL = licenseURL + else: + font.info.trademark = None trademark = self.trademarkEdit.text() - font.info.trademark = trademark if trademark != '' else None + if trademark != '': + font.info.trademark = trademark + else: + font.info.trademark = None + class MetricsTab(QWidget): name = "Metrics" @@ -184,11 +243,16 @@ class MetricsTab(QWidget): items = ["None", "Regular", "Italic", "Bold", "Bold Italic"] self.styleMapStyleDrop.insertItems(0, items) sn = font.info.styleMapStyleName - if sn == "regular": self.styleMapStyleDrop.setCurrentIndex(1) - elif sn == "regular italic": self.styleMapStyleDrop.setCurrentIndex(2) - elif sn == "bold": self.styleMapStyleDrop.setCurrentIndex(3) - elif sn == "bold italic": self.styleMapStyleDrop.setCurrentIndex(4) - else: self.styleMapStyleDrop.setCurrentIndex(0) + if sn == "regular": + self.styleMapStyleDrop.setCurrentIndex(1) + elif sn == "regular italic": + self.styleMapStyleDrop.setCurrentIndex(2) + elif sn == "bold": + self.styleMapStyleDrop.setCurrentIndex(3) + elif sn == "bold italic": + self.styleMapStyleDrop.setCurrentIndex(4) + else: + self.styleMapStyleDrop.setCurrentIndex(0) mainLayout.addWidget(styleMapFamilyLabel, 0, 0) mainLayout.addWidget(self.styleMapFamilyEdit, 0, 1, 1, 3) @@ -196,19 +260,22 @@ class MetricsTab(QWidget): mainLayout.addWidget(self.styleMapStyleDrop, 0, 5) unitsPerEmLabel = QLabel("Units per em:", self) - unitsPerEm = str(font.info.unitsPerEm) if font.info.unitsPerEm is not None else '' + unitsPerEm = str( + font.info.unitsPerEm) if font.info.unitsPerEm is not None else '' self.unitsPerEmEdit = QLineEdit(unitsPerEm, self) validator = QIntValidator(self) validator.setBottom(0) self.unitsPerEmEdit.setValidator(validator) ascenderLabel = QLabel("Ascender:", self) - ascender = str(font.info.ascender) if font.info.ascender is not None else '' + ascender = str( + font.info.ascender) if font.info.ascender is not None else '' self.ascenderEdit = QLineEdit(ascender, self) self.ascenderEdit.setValidator(QIntValidator(self)) capHeightLabel = QLabel("Cap height:", self) - capHeight = str(font.info.capHeight) if font.info.capHeight is not None else '' + capHeight = str( + font.info.capHeight) if font.info.capHeight is not None else '' self.capHeightEdit = QLineEdit(capHeight, self) self.capHeightEdit.setValidator(QIntValidator(self)) @@ -220,17 +287,20 @@ class MetricsTab(QWidget): mainLayout.addWidget(self.capHeightEdit, 1, 5) italicAngleLabel = QLabel("Italic angle:", self) - italicAngle = str(font.info.italicAngle) if font.info.italicAngle is not None else '' + italicAngle = str( + font.info.italicAngle) if font.info.italicAngle is not None else '' self.italicAngleEdit = QLineEdit(italicAngle, self) self.italicAngleEdit.setValidator(QDoubleValidator(self)) descenderLabel = QLabel("Descender:", self) - descender = str(font.info.descender) if font.info.descender is not None else '' + descender = str( + font.info.descender) if font.info.descender is not None else '' self.descenderEdit = QLineEdit(descender, self) self.descenderEdit.setValidator(QIntValidator(self)) xHeightLabel = QLabel("x-height:", self) - xHeight = str(font.info.xHeight) if font.info.xHeight is not None else '' + xHeight = str( + font.info.xHeight) if font.info.xHeight is not None else '' self.xHeightEdit = QLineEdit(xHeight, self) self.xHeightEdit.setValidator(QIntValidator(self)) @@ -251,27 +321,69 @@ class MetricsTab(QWidget): def writeValues(self, font): styleMapFamilyName = self.styleMapFamilyEdit.text() - font.info.styleMapFamilyName = styleMapFamilyName if styleMapFamilyName != '' else None + if styleMapFamilyName != '': + font.info.styleMapFamilyName = styleMapFamilyName + else: + font.info.styleMapFamilyName = None sn = self.styleMapStyleDrop.currentIndex() - if sn == 1: font.info.styleMapStyleName = "regular" - elif sn == 2: font.info.styleMapStyleName = "italic" - elif sn == 3: font.info.styleMapStyleName = "bold" - elif sn == 4: font.info.styleMapStyleName = "bold italic" - else: font.info.styleMapStyleName = None + if sn == 1: + font.info.styleMapStyleName = "regular" + elif sn == 2: + font.info.styleMapStyleName = "italic" + elif sn == 3: + font.info.styleMapStyleName = "bold" + elif sn == 4: + font.info.styleMapStyleName = "bold italic" + else: + font.info.styleMapStyleName = None unitsPerEm = self.unitsPerEmEdit.text() - font.info.unitsPerEm = float(unitsPerEm) if "." in unitsPerEm else int(unitsPerEm) if unitsPerEm else None + if "." in unitsPerEm: + font.info.unitsPerEm = float(unitsPerEm) + elif unitsPerEm: + font.info.unitsPerEm = int(unitsPerEm) + else: + font.info.unitsPerEm = None italicAngle = self.italicAngleEdit.text() - font.info.italicAngle = float(italicAngle) if "." in italicAngle else int(italicAngle) if italicAngle else None + if "." in italicAngle: + font.info.italicAngle = float(italicAngle) + elif italicAngle: + font.info.italicAngle = int(italicAngle) + else: + font.info.italicAngle = None ascender = self.ascenderEdit.text() - font.info.ascender = float(ascender) if "." in ascender else int(ascender) if ascender else None + if "." in ascender: + font.info.ascender = float(ascender) + elif ascender: + font.info.ascender = int(ascender) + else: + font.info.ascender = None descender = self.descenderEdit.text() - font.info.descender = float(descender) if "." in descender else int(descender) if descender else None + if "." in descender: + font.info.descender = float(descender) + elif descender: + font.info.descender = int(descender) + else: + font.info.descender = None capHeight = self.capHeightEdit.text() - font.info.capHeight = float(capHeight) if "." in capHeight else int(capHeight) if capHeight else None + if "." in capHeight: + font.info.capHeight = float(capHeight) + elif capHeight: + font.info.capHeight = int(capHeight) + else: + font.info.capHeight = None xHeight = self.xHeightEdit.text() - font.info.xHeight = float(xHeight) if "." in xHeight else int(xHeight) if xHeight else None + if "." in xHeight: + font.info.xHeight = float(xHeight) + elif xHeight: + font.info.xHeight = int(xHeight) + else: + font.info.xHeight = None note = self.noteEdit.toPlainText() - font.info.note = note if note != '' else None + if note != '': + font.info.note = note + else: + font.info.note = None + class OpenTypeTab(QWidget): name = "OpenType" @@ -280,23 +392,28 @@ class OpenTypeTab(QWidget): super(OpenTypeTab, self).__init__(parent) nameGroup = QGroupBox("name table", self) - #nameGroup.setFlat(True) + # nameGroup.setFlat(True) nameLayout = QGridLayout(self) preferredFamilyNameLabel = QLabel("Pref. Family Name:", self) - self.preferredFamilyNameEdit = QLineEdit(font.info.openTypeNamePreferredFamilyName, self) + self.preferredFamilyNameEdit = QLineEdit( + font.info.openTypeNamePreferredFamilyName, self) preferredSubfamilyNameLabel = QLabel("Pref. Subfamily Name:", self) - self.preferredSubfamilyNameEdit = QLineEdit(font.info.openTypeNamePreferredSubfamilyName, self) + self.preferredSubfamilyNameEdit = QLineEdit( + font.info.openTypeNamePreferredSubfamilyName, self) compatibleFullNameLabel = QLabel("Compatible Full Name:", self) - self.compatibleFullNameEdit = QLineEdit(font.info.openTypeNameCompatibleFullName, self) + self.compatibleFullNameEdit = QLineEdit( + font.info.openTypeNameCompatibleFullName, self) WWSFamilyNameLabel = QLabel("WWS Family Name:", self) - self.WWSFamilyNameEdit = QLineEdit(font.info.openTypeNameWWSFamilyName, self) + self.WWSFamilyNameEdit = QLineEdit( + font.info.openTypeNameWWSFamilyName, self) WWSSubfamilyNameLabel = QLabel("WWS Subfamily Name:", self) - self.WWSSubfamilyNameEdit = QLineEdit(font.info.openTypeNameWWSSubfamilyName, self) + self.WWSSubfamilyNameEdit = QLineEdit( + font.info.openTypeNameWWSSubfamilyName, self) versionLabel = QLabel("Version:", self) self.versionEdit = QLineEdit(font.info.openTypeNameVersion, self) @@ -305,7 +422,8 @@ class OpenTypeTab(QWidget): self.uniqueIDEdit = QLineEdit(font.info.openTypeNameUniqueID, self) descriptionLabel = QLabel("Description:", self) - self.descriptionEdit = QLineEdit(font.info.openTypeNameDescription, self) + self.descriptionEdit = QLineEdit( + font.info.openTypeNameDescription, self) sampleTextLabel = QLabel("Sample text:", self) self.sampleTextEdit = QLineEdit(font.info.openTypeNameSampleText, self) @@ -336,36 +454,54 @@ class OpenTypeTab(QWidget): nameGroup.setLayout(nameLayout) hheaGroup = QGroupBox("hhea table", self) - #hheaGroup.setFlat(True) + # hheaGroup.setFlat(True) hheaLayout = QGridLayout(self) ascenderLabel = QLabel("Ascender:", self) - ascender = str(font.info.openTypeHheaAscender) if font.info.openTypeHheaAscender is not None else '' + if font.info.openTypeHheaAscender is not None: + ascender = str(font.info.openTypeHheaAscender) + else: + ascender = '' self.ascenderEdit = QLineEdit(ascender, self) self.ascenderEdit.setValidator(QIntValidator(self)) descenderLabel = QLabel("Descender:", self) - descender = str(font.info.openTypeHheaDescender) if font.info.openTypeHheaDescender is not None else '' + if font.info.openTypeHheaDescender is not None: + descender = str(font.info.openTypeHheaDescender) + else: + descender = '' self.descenderEdit = QLineEdit(descender, self) self.descenderEdit.setValidator(QIntValidator(self)) lineGapLabel = QLabel("LineGap:", self) - lineGap = str(font.info.openTypeHheaLineGap) if font.info.openTypeHheaLineGap is not None else '' + if font.info.openTypeHheaLineGap is not None: + lineGap = str(font.info.openTypeHheaLineGap) + else: + lineGap = '' self.lineGapEdit = QLineEdit(lineGap, self) self.lineGapEdit.setValidator(QIntValidator(self)) caretSlopeRiseLabel = QLabel("caretSlopeRise:", self) - caretSlopeRise = str(font.info.openTypeHheaCaretSlopeRise) if font.info.openTypeHheaCaretSlopeRise is not None else '' + if font.info.openTypeHheaCaretSlopeRise is not None: + caretSlopeRise = str(font.info.openTypeHheaCaretSlopeRise) + else: + caretSlopeRise = '' self.caretSlopeRiseEdit = QLineEdit(caretSlopeRise, self) self.caretSlopeRiseEdit.setValidator(QIntValidator(self)) caretSlopeRunLabel = QLabel("caretSlopeRun:", self) - caretSlopeRun = str(font.info.openTypeHheaCaretSlopeRun) if font.info.openTypeHheaCaretSlopeRun is not None else '' + if font.info.openTypeHheaCaretSlopeRun is not None: + caretSlopeRun = str(font.info.openTypeHheaCaretSlopeRun) + else: + caretSlopeRun = '' self.caretSlopeRunEdit = QLineEdit(caretSlopeRun, self) self.caretSlopeRunEdit.setValidator(QIntValidator(self)) caretOffsetLabel = QLabel("caretOffset:", self) - caretOffset = str(font.info.openTypeHheaCaretOffset) if font.info.openTypeHheaCaretOffset is not None else '' + if font.info.openTypeHheaCaretOffset is not None: + caretOffset = str(font.info.openTypeHheaCaretOffset) + else: + caretOffset = '' self.caretOffsetEdit = QLineEdit(caretOffset, self) self.caretOffsetEdit.setValidator(QIntValidator(self)) @@ -387,36 +523,54 @@ class OpenTypeTab(QWidget): hheaGroup.setLayout(hheaLayout) vheaGroup = QGroupBox("vhea table", self) - #vheaGroup.setFlat(True) + # vheaGroup.setFlat(True) vheaLayout = QGridLayout(self) vertTypoAscenderLabel = QLabel("vertTypoAscender:", self) - vertTypoAscender = str(font.info.openTypeVheaVertTypoAscender) if font.info.openTypeVheaVertTypoAscender is not None else '' + if font.info.openTypeVheaVertTypoAscender is not None: + vertTypoAscender = str(font.info.openTypeVheaVertTypoAscender) + else: + vertTypoAscender = '' self.vertTypoAscenderEdit = QLineEdit(vertTypoAscender, self) self.vertTypoAscenderEdit.setValidator(QIntValidator(self)) vertTypoDescenderLabel = QLabel("vertTypoDescender:", self) - vertTypoDescender = str(font.info.openTypeVheaVertTypoDescender) if font.info.openTypeVheaVertTypoDescender is not None else '' + if font.info.openTypeVheaVertTypoDescender is not None: + vertTypoDescender = str(font.info.openTypeVheaVertTypoDescender) + else: + vertTypoDescender = '' self.vertTypoDescenderEdit = QLineEdit(vertTypoDescender, self) self.vertTypoDescenderEdit.setValidator(QIntValidator(self)) vertTypoLineGapLabel = QLabel("vertTypoLineGap:", self) - vertTypoLineGap = str(font.info.openTypeVheaVertTypoLineGap) if font.info.openTypeVheaVertTypoLineGap is not None else '' + if font.info.openTypeVheaVertTypoLineGap is not None: + vertTypoLineGap = str(font.info.openTypeVheaVertTypoLineGap) + else: + vertTypoLineGap = '' self.vertTypoLineGapEdit = QLineEdit(vertTypoLineGap, self) self.vertTypoLineGapEdit.setValidator(QIntValidator(self)) vheaCaretSlopeRiseLabel = QLabel("caretSlopeRise:", self) - vheaCaretSlopeRise = str(font.info.openTypeVheaCaretSlopeRise) if font.info.openTypeVheaCaretSlopeRise is not None else '' + if font.info.openTypeVheaCaretSlopeRise is not None: + vheaCaretSlopeRise = str(font.info.openTypeVheaCaretSlopeRise) + else: + vheaCaretSlopeRise = '' self.vheaCaretSlopeRiseEdit = QLineEdit(vheaCaretSlopeRise, self) self.vheaCaretSlopeRiseEdit.setValidator(QIntValidator(self)) vheaCaretSlopeRunLabel = QLabel("caretSlopeRun:", self) - vheaCaretSlopeRun = str(font.info.openTypeVheaCaretSlopeRun) if font.info.openTypeVheaCaretSlopeRun is not None else '' + if font.info.openTypeVheaCaretSlopeRun is not None: + vheaCaretSlopeRun = str(font.info.openTypeVheaCaretSlopeRun) + else: + vheaCaretSlopeRun = '' self.vheaCaretSlopeRunEdit = QLineEdit(vheaCaretSlopeRun, self) self.vheaCaretSlopeRunEdit.setValidator(QIntValidator(self)) vheaCaretOffsetLabel = QLabel("caretOffset:", self) - vheaCaretOffset = str(font.info.openTypeVheaCaretOffset) if font.info.openTypeVheaCaretOffset is not None else '' + if font.info.openTypeVheaCaretOffset is not None: + vheaCaretOffset = str(font.info.openTypeVheaCaretOffset) + else: + vheaCaretOffset = '' self.vheaCaretOffsetEdit = QLineEdit(vheaCaretOffset, self) self.vheaCaretOffsetEdit.setValidator(QIntValidator(self)) @@ -445,47 +599,112 @@ class OpenTypeTab(QWidget): def writeValues(self, font): preferredFamilyName = self.preferredFamilyNameEdit.text() - font.info.openTypeNamePreferredFamilyName = preferredFamilyName if preferredFamilyName != '' else None + if preferredFamilyName != '': + font.info.openTypeNamePreferredFamilyName = preferredFamilyName + else: + font.info.openTypeNamePreferredFamilyName = None preferredSubfamilyName = self.preferredSubfamilyNameEdit.text() - font.info.openTypeNamePreferredSubfamilyName = preferredSubfamilyName if preferredSubfamilyName != '' else None + if preferredSubfamilyName != '': + font.info.openTypeNamePreferredSubfamilyName = \ + preferredSubfamilyName + else: + font.info.openTypeNamePreferredSubfamilyName = None WWSFamilyName = self.WWSFamilyNameEdit.text() - font.info.openTypeNameWWSFamilyName = WWSFamilyName if WWSFamilyName != '' else None + if WWSFamilyName != '': + font.info.openTypeNameWWSFamilyName = WWSFamilyName + else: + font.info.openTypeNameWWSFamilyName = None WWSSubfamilyName = self.WWSSubfamilyNameEdit.text() - font.info.openTypeNameWWSSubfamilyName = WWSSubfamilyName if WWSSubfamilyName != '' else None + if WWSSubfamilyName != '': + font.info.openTypeNameWWSSubfamilyName = WWSSubfamilyName + else: + font.info.openTypeNameWWSSubfamilyName = None compatibleFullName = self.compatibleFullNameEdit.text() - font.info.openTypeNameCompatibleFullName = compatibleFullName if compatibleFullName != '' else None + if compatibleFullName != '': + font.info.openTypeNameCompatibleFullName = compatibleFullName + else: + font.info.openTypeNameCompatibleFullName = None version = self.versionEdit.text() - font.info.openTypeNameVersion = version if version != '' else None + if version != '': + font.info.openTypeNameVersion = version + else: + font.info.openTypeNameVersion = None uniqueID = self.uniqueIDEdit.text() - font.info.openTypeNameUniqueID = uniqueID if uniqueID != '' else None + if uniqueID != '': + font.info.openTypeNameUniqueID = uniqueID + else: + font.info.openTypeNameUniqueID = None description = self.descriptionEdit.text() - font.info.openTypeNameDescription = description if description != '' else None + if description != '': + font.info.openTypeNameDescription = description + else: + font.info.openTypeNameDescription = None sampleText = self.sampleTextEdit.text() - font.info.openTypeNameSampleText = sampleText if sampleText != '' else None + if sampleText != '': + font.info.openTypeNameSampleText = sampleText + else: + font.info.openTypeNameSampleText = None ascender = self.ascenderEdit.text() - font.info.openTypeHheaAscender = int(ascender) if ascender != '' else None + if ascender != '': + font.info.openTypeHheaAscender = int(ascender) + else: + font.info.openTypeHheaAscender = None descender = self.descenderEdit.text() - font.info.openTypeHheaDescender = int(descender) if descender != '' else None + if descender != '': + font.info.openTypeHheaDescender = int(descender) + else: + font.info.openTypeHheaDescender = None lineGap = self.lineGapEdit.text() - font.info.openTypeHheaLineGap = int(lineGap) if lineGap != '' else None + if lineGap != '': + font.info.openTypeHheaLineGap = int(lineGap) + else: + font.info.openTypeHheaLineGap = None caretSlopeRise = self.caretSlopeRiseEdit.text() - font.info.openTypeHheaCaretSlopeRise = int(caretSlopeRise) if caretSlopeRise != '' else None + if caretSlopeRise != '': + font.info.openTypeHheaCaretSlopeRise = int(caretSlopeRise) + else: + font.info.openTypeHheaCaretSlopeRise = None caretSlopeRun = self.caretSlopeRunEdit.text() - font.info.openTypeHheaCaretSlopeRun = int(caretSlopeRun) if caretSlopeRun != '' else None + if caretSlopeRun != '': + font.info.openTypeHheaCaretSlopeRun = int(caretSlopeRun) + else: + font.info.openTypeHheaCaretSlopeRun = None caretOffset = self.caretOffsetEdit.text() - font.info.openTypeHheaCaretOffset = int(caretOffset) if caretOffset != '' else None + if caretOffset != '': + font.info.openTypeHheaCaretOffset = int(caretOffset) + else: + font.info.openTypeHheaCaretOffset = None vertTypoAscender = self.vertTypoAscenderEdit.text() - font.info.openTypeVheaAscender = int(vertTypoAscender) if vertTypoAscender != '' else None + if vertTypoAscender != '': + font.info.openTypeVheaAscender = int(vertTypoAscender) + else: + font.info.openTypeVheaAscender = None vertTypoDescender = self.vertTypoDescenderEdit.text() - font.info.openTypeVheaDescender = int(vertTypoDescender) if vertTypoDescender != '' else None + if vertTypoDescender != '': + font.info.openTypeVheaDescender = int(vertTypoDescender) + else: + font.info.openTypeVheaDescender = None vertTypoLineGap = self.vertTypoLineGapEdit.text() - font.info.openTypeVheaLineGap = int(vertTypoLineGap) if vertTypoLineGap != '' else None + if vertTypoLineGap != '': + font.info.openTypeVheaLineGap = int(vertTypoLineGap) + else: + font.info.openTypeVheaLineGap = None vheaCaretSlopeRise = self.vheaCaretSlopeRiseEdit.text() - font.info.openTypeVheaCaretSlopeRise = int(vheaCaretSlopeRise) if vheaCaretSlopeRise != '' else None + if vheaCaretSlopeRise != '': + font.info.openTypeVheaCaretSlopeRise = int(vheaCaretSlopeRise) + else: + font.info.openTypeVheaCaretSlopeRise = None vheaCaretSlopeRun = self.vheaCaretSlopeRunEdit.text() - font.info.openTypeVheaCaretSlopeRun = int(vheaCaretSlopeRun) if vheaCaretSlopeRun != '' else None + if vheaCaretSlopeRun != '': + font.info.openTypeVheaCaretSlopeRun = int(vheaCaretSlopeRun) + else: + font.info.openTypeVheaCaretSlopeRun = None vheaCaretOffset = self.vheaCaretOffsetEdit.text() - font.info.openTypeVheaCaretOffset = int(vheaCaretOffset) if vheaCaretOffset != '' else None + if vheaCaretOffset != '': + font.info.openTypeVheaCaretOffset = int(vheaCaretOffset) + else: + font.info.openTypeVheaCaretOffset = None + class PostScriptTab(QWidget): name = "Postscript" @@ -494,7 +713,7 @@ class PostScriptTab(QWidget): super(PostScriptTab, self).__init__(parent) namingGroup = QGroupBox("Naming", self) - #namingGroup.setFlat(True) + # namingGroup.setFlat(True) namingLayout = QGridLayout(self) fontNameLabel = QLabel("FontName:", self) @@ -507,7 +726,10 @@ class PostScriptTab(QWidget): self.weightNameEdit = QLineEdit(font.info.postscriptWeightName, self) uniqueIDLabel = QLabel("Unique ID:", self) - uniqueID = str(font.info.postscriptUniqueID) if font.info.postscriptUniqueID is not None else '' + if font.info.postscriptUniqueID is not None: + uniqueID = str(font.info.postscriptUniqueID) + else: + uniqueID = '' self.uniqueIDEdit = QLineEdit(uniqueID, self) self.uniqueIDEdit.setValidator(QIntValidator(self)) @@ -524,23 +746,27 @@ class PostScriptTab(QWidget): namingGroup.setLayout(namingLayout) hintingGroup = QGroupBox("Hinting", self) - #hintingGroup.setFlat(True) + # hintingGroup.setFlat(True) hintingLayout = QGridLayout(self) blueValuesLabel = QLabel("Blue values:", self) - blueValues = " ".join(str(val) for val in font.info.postscriptBlueValues) + blueValues = " ".join(str(val) + for val in font.info.postscriptBlueValues) self.blueValuesEdit = QLineEdit(blueValues, self) otherBluesLabel = QLabel("Other blues:", self) - otherBlues = " ".join(str(val) for val in font.info.postscriptOtherBlues) + otherBlues = " ".join(str(val) + for val in font.info.postscriptOtherBlues) self.otherBluesEdit = QLineEdit(otherBlues, self) familyBluesLabel = QLabel("Family blues:", self) - familyBlues = " ".join(str(val) for val in font.info.postscriptFamilyBlues) + familyBlues = " ".join(str(val) + for val in font.info.postscriptFamilyBlues) self.familyBluesEdit = QLineEdit(familyBlues, self) familyOtherBluesLabel = QLabel("Family other blues:", self) - familyOtherBlues = " ".join(str(val) for val in font.info.postscriptFamilyOtherBlues) + familyOtherBlues = " ".join( + str(val) for val in font.info.postscriptFamilyOtherBlues) self.familyOtherBluesEdit = QLineEdit(familyOtherBlues, self) l = 0 @@ -556,7 +782,10 @@ class PostScriptTab(QWidget): l += 1 blueFuzzLabel = QLabel("Blue fuzz:", self) - blueFuzz = str(font.info.postscriptBlueFuzz) if font.info.postscriptBlueFuzz is not None else '' + if font.info.postscriptBlueFuzz is not None: + blueFuzz = str(font.info.postscriptBlueFuzz) + else: + blueFuzz = '' self.blueFuzzEdit = QLineEdit(blueFuzz, self) self.blueFuzzEdit.setValidator(QDoubleValidator(self)) @@ -565,7 +794,10 @@ class PostScriptTab(QWidget): self.stemSnapHEdit = QLineEdit(stemSnapH, self) blueScaleLabel = QLabel("Blue scale:", self) - blueScale = str(font.info.postscriptBlueScale) if font.info.postscriptBlueScale is not None else '' + if font.info.postscriptBlueScale is not None: + blueScale = str(font.info.postscriptBlueScale) + else: + blueScale = '' self.blueScaleEdit = QLineEdit(blueScale, self) self.blueScaleEdit.setValidator(QDoubleValidator(self)) @@ -574,7 +806,10 @@ class PostScriptTab(QWidget): self.stemSnapVEdit = QLineEdit(stemSnapV, self) blueShiftLabel = QLabel("Blue shift:", self) - blueShift = str(font.info.postscriptBlueShift) if font.info.postscriptBlueShift is not None else '' + if font.info.postscriptBlueShift is not None: + blueShift = str(font.info.postscriptBlueShift) + else: + blueShift = '' self.blueShiftEdit = QLineEdit(blueShift, self) self.blueShiftEdit.setValidator(QDoubleValidator(self)) @@ -582,8 +817,10 @@ class PostScriptTab(QWidget): forceBold = font.info.postscriptForceBold self.forceBoldBox = QCheckBox(self) self.forceBoldBox.setTristate() - if forceBold is None: self.forceBoldBox.setCheckState(Qt.PartiallyChecked) - else: self.forceBoldBox.setChecked(forceBold) + if forceBold is None: + self.forceBoldBox.setCheckState(Qt.PartiallyChecked) + else: + self.forceBoldBox.setChecked(forceBold) hintingLayout.addWidget(blueFuzzLabel, l, 0) hintingLayout.addWidget(self.blueFuzzEdit, l, 1, 1, 2) @@ -602,31 +839,46 @@ class PostScriptTab(QWidget): hintingGroup.setLayout(hintingLayout) metricsGroup = QGroupBox("Metrics", self) - #metricsGroup.setFlat(True) + # metricsGroup.setFlat(True) metricsLayout = QGridLayout(self) defaultWidthXLabel = QLabel("DefaultWidthX:", self) - defaultWidthX = str(font.info.postscriptDefaultWidthX) if font.info.postscriptDefaultWidthX is not None else '' + if font.info.postscriptDefaultWidthX is not None: + defaultWidthX = str(font.info.postscriptDefaultWidthX) + else: + defaultWidthX = '' self.defaultWidthXEdit = QLineEdit(defaultWidthX, self) self.defaultWidthXEdit.setValidator(QDoubleValidator(self)) underlineThicknessLabel = QLabel("UnderlineThickness:", self) - underlineThickness = str(font.info.postscriptUnderlineThickness) if font.info.postscriptUnderlineThickness is not None else '' + if font.info.postscriptUnderlineThickness is not None: + underlineThickness = str(font.info.postscriptUnderlineThickness) + else: + underlineThickness = '' self.underlineThicknessEdit = QLineEdit(underlineThickness, self) self.underlineThicknessEdit.setValidator(QDoubleValidator(self)) nominalWidthXLabel = QLabel("NominalWidthX:", self) - nominalWidthX = str(font.info.postscriptNominalWidthX) if font.info.postscriptNominalWidthX is not None else '' + if font.info.postscriptNominalWidthX is not None: + nominalWidthX = str(font.info.postscriptNominalWidthX) + else: + nominalWidthX = '' self.nominalWidthXEdit = QLineEdit(nominalWidthX, self) self.nominalWidthXEdit.setValidator(QDoubleValidator(self)) underlinePositionLabel = QLabel("UnderlinePosition:", self) - underlinePosition = str(font.info.postscriptUnderlinePosition) if font.info.postscriptUnderlinePosition is not None else '' + if font.info.postscriptUnderlinePosition is not None: + underlinePosition = str(font.info.postscriptUnderlinePosition) + else: + underlinePosition = '' self.underlinePositionEdit = QLineEdit(underlinePosition, self) self.underlinePositionEdit.setValidator(QDoubleValidator(self)) slantAngleLabel = QLabel("SlantAngle:", self) - slantAngle = str(font.info.postscriptSlantAngle) if font.info.postscriptSlantAngle is not None else '' + if font.info.postscriptSlantAngle is not None: + slantAngle = str(font.info.postscriptSlantAngle) + else: + slantAngle = '' self.slantAngleEdit = QLineEdit(slantAngle, self) self.slantAngleEdit.setValidator(QDoubleValidator(self)) @@ -634,8 +886,10 @@ class PostScriptTab(QWidget): isFixedPitch = font.info.postscriptIsFixedPitch self.isFixedPitchBox = QCheckBox(self) self.isFixedPitchBox.setTristate() - if isFixedPitch is None: self.isFixedPitchBox.setCheckState(Qt.PartiallyChecked) - else: self.isFixedPitchBox.setChecked(isFixedPitch) + if isFixedPitch is None: + self.isFixedPitchBox.setCheckState(Qt.PartiallyChecked) + else: + self.isFixedPitchBox.setChecked(isFixedPitch) l = 0 metricsLayout.addWidget(defaultWidthXLabel, l, 0) @@ -655,20 +909,24 @@ class PostScriptTab(QWidget): metricsGroup.setLayout(metricsLayout) charactersGroup = QGroupBox("Characters", self) - #charactersGroup.setFlat(True) + # charactersGroup.setFlat(True) charactersLayout = QGridLayout(self) defaultCharacterLabel = QLabel("Default character:", self) - self.defaultCharacterEdit = QLineEdit(font.info.postscriptDefaultCharacter, self) + self.defaultCharacterEdit = QLineEdit( + font.info.postscriptDefaultCharacter, self) windowsCharacterSetLabel = QLabel("Windows character set:", self) self.windowsCharacterSetDrop = QComboBox(self) - items = ["None", "ANSI", "Default", "Symbol", "Macintosh", "Shift JIS", "Hangul", "Hangul (Johab)", "GB2312", - "Chinese BIG5", "Greek", "Turkish", "Vietnamese", "Hebrew", "Arabic", "Baltic", "Bitstream", + items = [ + "None", "ANSI", "Default", "Symbol", "Macintosh", "Shift JIS", + "Hangul", "Hangul (Johab)", "GB2312", "Chinese BIG5", "Greek", + "Turkish", "Vietnamese", "Hebrew", "Arabic", "Baltic", "Bitstream", "Cyrillic", "Thai", "Eastern European", "OEM"] self.windowsCharacterSetDrop.insertItems(0, items) if font.info.postscriptWindowsCharacterSet is not None: - self.windowsCharacterSetDrop.setCurrentIndex(font.info.postscriptWindowsCharacterSet) + self.windowsCharacterSetDrop.setCurrentIndex( + font.info.postscriptWindowsCharacterSet) l = 0 charactersLayout.addWidget(defaultCharacterLabel, l, 0) @@ -686,13 +944,25 @@ class PostScriptTab(QWidget): def writeValues(self, font): fontName = self.fontNameEdit.text() - font.info.postscriptFontName = fontName if fontName != '' else None + if fontName != '': + font.info.postscriptFontName = fontName + else: + font.info.postscriptFontName = None fullName = self.fullNameEdit.text() - font.info.postscriptFullName = fullName if fullName != '' else None + if fullName != '': + font.info.postscriptFullName = fullName + else: + font.info.postscriptFullName = None weightName = self.weightNameEdit.text() - font.info.postscriptWeightName = weightName if weightName != '' else None + if weightName != '': + font.info.postscriptWeightName = weightName + else: + font.info.postscriptWeightName = None uniqueID = self.uniqueIDEdit.text() - font.info.postscriptUniqueID = int(uniqueID) if uniqueID != '' else None + if uniqueID != '': + font.info.postscriptUniqueID = int(uniqueID) + else: + font.info.postscriptUniqueID = None blueValues = self.blueValuesEdit.text().split(" ") if blueValues is None: font.info.postscriptBlueValues = None @@ -730,11 +1000,24 @@ class PostScriptTab(QWidget): blues.append(int(blue)) font.info.postscriptFamilyOtherBlues = blues blueFuzz = self.blueFuzzEdit.text() - font.info.postscriptBlueFuzz = float(blueFuzz) if "." in blueFuzz else int(blueFuzz) if blueFuzz != '' else None + if "." in blueFuzz: + font.info.postscriptBlueFuzz = float(blueFuzz) + elif blueFuzz != '': + font.info.postscriptBlueFuzz = int(blueFuzz) + else: + font.info.postscriptBlueFuzz = None blueScale = self.blueScaleEdit.text() - font.info.postscriptBlueScale = float(blueScale) if blueScale != '' else None + if blueScale != '': + font.info.postscriptBlueScale = float(blueScale) + else: + font.info.postscriptBlueScale = None blueShift = self.blueShiftEdit.text() - font.info.postscriptBlueShift = float(blueShift) if "." in blueShift else int(blueShift) if blueShift != '' else None + if "." in blueShift: + font.info.postscriptBlueShift = float(blueShift) + elif blueShift != '': + font.info.postscriptBlueShift = int(blueShift) + else: + font.info.postscriptBlueShift = None stemSnapH = self.stemSnapHEdit.text().split(" ") if stemSnapH is None: font.info.postscriptStemSnapH = None @@ -759,22 +1042,51 @@ class PostScriptTab(QWidget): else: font.info.postscriptForceBold = bool(forceBold) defaultWidthX = self.defaultWidthXEdit.text() - font.info.postscriptDefaultWidthX = float(defaultWidthX) if "." in defaultWidthX else int(defaultWidthX) if defaultWidthX != '' else None + if "." in defaultWidthX: + font.info.postscriptDefaultWidthX = float(defaultWidthX) + elif defaultWidthX != '': + font.info.postscriptDefaultWidthX = int(defaultWidthX) + else: + font.info.postscriptDefaultWidthX = None nominalWidthX = self.nominalWidthXEdit.text() - font.info.postscriptNominalWidthX = float(nominalWidthX) if "." in nominalWidthX else int(nominalWidthX) if nominalWidthX != '' else None + if "." in nominalWidthX: + font.info.postscriptNominalWidthX = float(nominalWidthX) + elif nominalWidthX != '': + font.info.postscriptNominalWidthX = int(nominalWidthX) + else: + font.info.postscriptNominalWidthX = None underlineThickness = self.underlineThicknessEdit.text() - font.info.postscriptUnderlineThickness = float(underlineThickness) if "." in underlineThickness else int(underlineThickness) if underlineThickness != '' else None + if "." in underlineThickness: + font.info.postscriptUnderlineThickness = float(underlineThickness) + elif underlineThickness != '': + font.info.postscriptUnderlineThickness = \ + int(underlineThickness) + else: + font.info.postscriptUnderlineThickness = None underlinePosition = self.underlinePositionEdit.text() - font.info.postscriptUnderlinePosition = float(underlinePosition) if "." in underlinePosition else int(underlinePosition) if underlinePosition != '' else None + if "." in underlinePosition: + font.info.postscriptUnderlinePosition = float(underlinePosition) + elif underlinePosition != '': + font.info.postscriptUnderlinePosition = int(underlinePosition) + else: + font.info.postscriptUnderlinePosition = None slantAngle = self.slantAngleEdit.text() - font.info.postscriptSlantAngle = float(slantAngle) if "." in slantAngle else int(slantAngle) if slantAngle != '' else None + if "." in slantAngle: + font.info.postscriptSlantAngle = float(slantAngle) + elif slantAngle != '': + font.info.postscriptSlantAngle = int(slantAngle) + else: + font.info.postscriptSlantAngle = None isFixedPitch = self.isFixedPitchBox.checkState() if isFixedPitch == Qt.PartiallyChecked: font.info.postscriptIsFixedPitch = None else: font.info.postscriptIsFixedPitch = bool(isFixedPitch) defaultCharacter = self.defaultCharacterEdit.text() - font.info.postscriptDefaultCharacter = defaultCharacter if defaultCharacter != '' else None + if defaultCharacter != '': + font.info.postscriptDefaultCharacter = defaultCharacter + else: + font.info.postscriptDefaultCharacter = None windowsCharacterSet = self.windowsCharacterSetDrop.currentIndex() if windowsCharacterSet == 0: font.info.postscriptWindowsCharacterSet = None diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index e3e5b2d..5d00e93 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -10,42 +10,58 @@ from defconQt.util import platformSpecific from defcon import Color, Component from defconQt.spaceCenter import MainSpaceWindow # TODO: remove globs when things start to stabilize -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * +from PyQt5.QtCore import ( + pyqtSignal, QEvent, QMimeData, QRegularExpression, QSettings, Qt) +from PyQt5.QtGui import ( + QColor, QCursor, QIcon, QIntValidator, QKeySequence, QPixmap, + QRegularExpressionValidator, QTextCursor) +from PyQt5.QtWidgets import ( + QAction, QApplication, QCheckBox, QComboBox, QDialog, QDialogButtonBox, + QErrorMessage, QFileDialog, QGridLayout, QGroupBox, QLabel, QLineEdit, + QListWidget, QListWidgetItem, QMainWindow, QMenu, QMessageBox, + QPlainTextEdit, QPushButton, QRadioButton, QSlider, QSplitter, QTabWidget, + QTextEdit, QToolTip, QVBoxLayout, QWidget) from collections import OrderedDict -import os, pickle, traceback +import os +import pickle +import traceback cannedDesign = [ dict(type="cannedDesign", allowPseudoUnicode=True) ] sortItems = ["alphabetical", "category", "unicode", "script", "suffix", - "decompositionBase", "weightedSuffix", "ligature"] + "decompositionBase", "weightedSuffix", "ligature"] latinDefault = GlyphSet( -["space","exclam","quotesingle","quotedbl","numbersign","dollar", -"percent","ampersand","parenleft","parenright","asterisk","plus","comma", -"hyphen","period","slash","zero","one","two","three","four","five", -"six","seven","eight","nine","colon","semicolon","less","equal", -"greater","question","at","A","B","C","D","E","F","G","H","I","J", -"K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", -"bracketleft","backslash","bracketright","asciicircum","underscore","grave", -"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t", -"u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","exclamdown", -"cent","sterling","currency","yen","brokenbar","section","copyright", -"ordfeminine","guillemotleft","logicalnot","registered","macron","degree", -"plusminus","twosuperior","threesuperior","mu","paragraph","periodcentered", -"onesuperior","ordmasculine","guillemotright","onequarter","onehalf", -"threequarters","questiondown","Agrave","Aacute","Acircumflex","Atilde", -"Adieresis","Aring","AE","Ccedilla","Egrave","Eacute","Ecircumflex","Edieresis", -"Igrave","Iacute","Icircumflex","Idieresis","Eth","Ntilde","Ograve","Oacute", -"Ocircumflex","Otilde","Odieresis","multiply","Oslash","Ugrave","Uacute", -"Ucircumflex","Udieresis","Yacute","Thorn","germandbls","agrave","aacute", -"acircumflex","atilde","adieresis","aring","ae","ccedilla","egrave","eacute", -"ecircumflex","edieresis","igrave","iacute","icircumflex","idieresis","eth", -"ntilde","ograve","oacute","ocircumflex","otilde","odieresis","divide","oslash", -"ugrave","uacute","ucircumflex","udieresis","yacute","thorn","ydieresis", -"dotlessi","gravecomb","acutecomb","uni0302","uni0308","uni030A","tildecomb", -"uni0327","quoteleft","quoteright","minus"],"Latin-default") + ["space", "exclam", "quotesingle", "quotedbl", "numbersign", "dollar", + "percent", "ampersand", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", + "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", + "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", + "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", + "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", + "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", + "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", + "asciitilde", "exclamdown", "cent", "sterling", "currency", "yen", + "brokenbar", "section", "copyright", "ordfeminine", "guillemotleft", + "logicalnot", "registered", "macron", "degree", "plusminus", + "twosuperior", "threesuperior", "mu", "paragraph", "periodcentered", + "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", + "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex", + "Atilde", "Adieresis", "Aring", "AE", "Ccedilla", "Egrave", "Eacute", + "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", + "Idieresis", "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", + "Otilde", "Odieresis", "multiply", "Oslash", "Ugrave", "Uacute", + "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls", "agrave", + "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla", + "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", + "icircumflex", "idieresis", "eth", "ntilde", "ograve", "oacute", + "ocircumflex", "otilde", "odieresis", "divide", "oslash", "ugrave", + "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis", + "dotlessi", "gravecomb", "acutecomb", "uni0302", "uni0308", "uni030A", + "tildecomb", "uni0327", "quoteleft", "quoteright", "minus"], + "Latin-default") + class Application(QApplication): currentFontChanged = pyqtSignal() @@ -98,7 +114,9 @@ class Application(QApplication): MAX_RECENT_FILES = 6 + class InspectorWindow(QWidget): + def __init__(self): super(InspectorWindow, self).__init__(flags=Qt.Tool) self.setWindowTitle("Inspector") @@ -108,7 +126,7 @@ class InspectorWindow(QWidget): glyphGroup = QGroupBox("Glyph", self) glyphGroup.setFlat(True) glyphLayout = QGridLayout(self) - columnOneWidth = self.fontMetrics().width('0')*7 + columnOneWidth = self.fontMetrics().width('0') * 7 nameLabel = QLabel("Name:", self) self.nameEdit = QLineEdit(self) @@ -116,7 +134,8 @@ class InspectorWindow(QWidget): unicodesLabel = QLabel("Unicode:", self) self.unicodesEdit = QLineEdit(self) self.unicodesEdit.editingFinished.connect(self.writeUnicodes) - unicodesRegExp = QRegularExpression("(|([a-fA-F0-9]{4,6})( ([a-fA-F0-9]{4,6}))*)") + unicodesRegExp = QRegularExpression( + "(|([a-fA-F0-9]{4,6})( ([a-fA-F0-9]{4,6}))*)") unicodesValidator = QRegularExpressionValidator(unicodesRegExp, self) self.unicodesEdit.setValidator(unicodesValidator) widthLabel = QLabel("Width:", self) @@ -126,12 +145,14 @@ class InspectorWindow(QWidget): self.widthEdit.setValidator(QIntValidator(self)) leftSideBearingLabel = QLabel("Left:", self) self.leftSideBearingEdit = QLineEdit(self) - self.leftSideBearingEdit.editingFinished.connect(self.writeLeftSideBearing) + self.leftSideBearingEdit.editingFinished.connect( + self.writeLeftSideBearing) self.leftSideBearingEdit.setMaximumWidth(columnOneWidth) self.leftSideBearingEdit.setValidator(QIntValidator(self)) rightSideBearingLabel = QLabel("Right:", self) self.rightSideBearingEdit = QLineEdit(self) - self.rightSideBearingEdit.editingFinished.connect(self.writeRightSideBearing) + self.rightSideBearingEdit.editingFinished.connect( + self.writeRightSideBearing) self.rightSideBearingEdit.setMaximumWidth(columnOneWidth) self.rightSideBearingEdit.setValidator(QIntValidator(self)) markColorLabel = QLabel("Mark:", self) @@ -239,14 +260,14 @@ class InspectorWindow(QWidget): xMin, yMin, xMax, yMax = self._glyph.controlPointBounds for contour in self._glyph: for point in contour: - point.x = xMin + xMax - point.x + point.x = xMin + xMax - point.x self._glyph.dirty = True def vSymmetry(self): xMin, yMin, xMax, yMax = self._glyph.controlPointBounds for contour in self._glyph: for point in contour: - point.y = yMin + yMax - point.y + point.y = yMin + yMax - point.y self._glyph.dirty = True def lockMove(self, checked): @@ -271,7 +292,8 @@ class InspectorWindow(QWidget): else: sY = self.scaleYEdit.text() sX, sY = int(sX) if sX != "" else 1, int(sY) if sY != "" else 1 - sX /= 100; sY /= 100 + sX /= 100 + sY /= 100 xMin, yMin, xMax, yMax = self._glyph.controlPointBounds for contour in self._glyph: for point in contour: @@ -285,26 +307,33 @@ class InspectorWindow(QWidget): self._glyph.removeObserver(self, "Glyph.Changed") self._glyph = app.currentGlyph() if self._glyph is not None: - self._glyph.addObserver(self, "updateGlyphAttributes", "Glyph.Changed") + self._glyph.addObserver( + self, "updateGlyphAttributes", "Glyph.Changed") self.updateGlyphAttributes() def updateGlyphAttributes(self, notification=None): - if self._blocked: return + if self._blocked: + return + name = None + unicodes = None + width = None + leftSideBearing = None + rightSideBearing = None colorStr = "white" if self._glyph is not None: name = self._glyph.name - unicodes = " ".join("%06X" % u if u > 0xFFFF else "%04X" % u for u in self._glyph.unicodes) - width = str(int(self._glyph.width)) if self._glyph.width else None - leftSideBearing = str(int(self._glyph.leftMargin)) if self._glyph.leftMargin is not None else None - rightSideBearing = str(int(self._glyph.rightMargin)) if self._glyph.rightMargin is not None else None + unicodes = " ".join("%06X" % u if u > 0xFFFF else "%04X" % + u for u in self._glyph.unicodes) + if self._glyph.width: + width = str(int(self._glyph.width)) + if self._glyph.leftMargin is not None: + leftSideBearing = str(int(self._glyph.leftMargin)) + if self._glyph.rightMargin is not None: + rightSideBearing = str(int(self._glyph.rightMargin)) if self._glyph.markColor is not None: - colorStr = QColor.fromRgbF(*tuple(self._glyph.markColor)).name() - else: - name = None - unicodes = None - width = None - leftSideBearing = None - rightSideBearing = None + colorStr = QColor.fromRgbF( + *tuple(self._glyph.markColor)).name() + self.nameEdit.setText(name) self.unicodesEdit.setText(unicodes) self.widthEdit.setText(width) @@ -314,13 +343,15 @@ class InspectorWindow(QWidget): border: 1px solid black;".format(colorStr)) def writeGlyphName(self): - if self._glyph is None: return + if self._glyph is None: + return self._blocked = True self._glyph.name = self.nameEdit.text() self._blocked = False def writeUnicodes(self): - if self._glyph is None: return + if self._glyph is None: + return self._blocked = True unicodes = self.unicodesEdit.text().split(" ") if len(unicodes) == 1 and unicodes[0] == "": @@ -330,25 +361,31 @@ class InspectorWindow(QWidget): self._blocked = False def writeWidth(self): - if self._glyph is None: return + if self._glyph is None: + return self._blocked = True self._glyph.width = int(self.widthEdit.text()) self._blocked = False def writeLeftSideBearing(self): - if self._glyph is None: return + if self._glyph is None: + return self._blocked = True self._glyph.leftMargin = int(self.leftSideBearingEdit.text()) self._blocked = False def writeRightSideBearing(self): - if self._glyph is None: return + if self._glyph is None: + return self._blocked = True self._glyph.rightMargin = int(self.nameEdit.text()) self._blocked = False # TODO: implement Frederik's Glyph Construction Builder + + class AddGlyphDialog(QDialog): + def __init__(self, currentGlyphs=None, parent=None): super(AddGlyphDialog, self).__init__(parent) self.setWindowModality(Qt.WindowModal) @@ -372,7 +409,8 @@ class AddGlyphDialog(QDialog): self.addAsTemplateBox.setChecked(True) self.sortFontBox = QCheckBox("Sort font", self) self.overrideBox = QCheckBox("Override", self) - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -394,10 +432,10 @@ class AddGlyphDialog(QDialog): result = dialog.exec_() sortFont = False params = dict( - addUnicode = dialog.addUnicodeBox.isChecked(), - asTemplate = dialog.addAsTemplateBox.isChecked(), - override = dialog.overrideBox.isChecked(), - sortFont = dialog.sortFontBox.isChecked(), + addUnicode=dialog.addUnicodeBox.isChecked(), + asTemplate=dialog.addAsTemplateBox.isChecked(), + override=dialog.overrideBox.isChecked(), + sortFont=dialog.sortFontBox.isChecked(), ) newGlyphNames = [] for name in dialog.addGlyphEdit.toPlainText().split(): @@ -410,7 +448,8 @@ class AddGlyphDialog(QDialog): return (newGlyphNames, params, result) def importGlyphs(self, index): - if index == 0: return + if index == 0: + return glyphNames = self.importCharDrop.currentData() editorNames = self.addGlyphEdit.toPlainText().split() currentNames = set(self.currentGlyphNames) ^ set(editorNames) @@ -427,7 +466,9 @@ class AddGlyphDialog(QDialog): self.importCharDrop.setCurrentIndex(0) self.addGlyphEdit.setFocus(True) + class SortDialog(QDialog): + def __init__(self, desc=None, parent=None): super(SortDialog, self).__init__(parent) self.setWindowModality(Qt.WindowModal) @@ -468,7 +509,8 @@ class SortDialog(QDialog): line.append(QCheckBox("Ascending", self)) line.append(QCheckBox("Allow pseudo-unicode", self)) if self.customSortBox.isChecked(): - line[0].setCurrentIndex(self.indexFromItemName(desc[i]["type"])) + line[0].setCurrentIndex( + self.indexFromItemName(desc[i]["type"])) line[1].setChecked(desc[i]["ascending"]) line[2].setChecked(desc[i]["allowPseudoUnicode"]) else: @@ -492,7 +534,8 @@ class SortDialog(QDialog): btn.pressed.connect(self._deleteRow) self.customSortGroup.setLayout(self.customSortLayout) - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -523,15 +566,16 @@ class SortDialog(QDialog): self.customSortLayout.addWidget(line[1], i, 1) self.customSortLayout.addWidget(line[2], i, 2) self.customSortLayout.addWidget(line[3], i, 3) - if i == 7: self.sender().setEnabled(False) + if i == 7: + self.sender().setEnabled(False) def _deleteRow(self): rel = self.sender().property("index") desc = self.customDescriptors - for i in range(rel+1, len(desc)-1): - desc[i][0].setCurrentIndex(desc[i+1][0].currentIndex()) - desc[i][1].setChecked(desc[i+1][1].isChecked()) - desc[i][2].setChecked(desc[i+1][2].isChecked()) + for i in range(rel + 1, len(desc) - 1): + desc[i][0].setCurrentIndex(desc[i + 1][0].currentIndex()) + desc[i][1].setChecked(desc[i + 1][1].isChecked()) + desc[i][2].setChecked(desc[i + 1][2].isChecked()) for elem in desc[-1]: elem.setParent(None) del self.customDescriptors[-1] @@ -540,7 +584,8 @@ class SortDialog(QDialog): def indexFromItemName(self, name): for index, item in enumerate(sortItems): - if name == item: return index + if name == item: + return index print("Unknown descriptor name: %s", name) return 0 @@ -555,8 +600,10 @@ class SortDialog(QDialog): elif dialog.customSortBox.isChecked(): descriptors = [] for line in dialog.customDescriptors: - descriptors.append(dict(type=line[0].currentText(), ascending=line[1].isChecked(), - allowPseudoUnicode=line[2].isChecked())) + descriptors.append(dict(type=line[0].currentText(), + ascending=line[1].isChecked(), + allowPseudoUnicode=line[2].isChecked() + )) ret = descriptors else: ret = cannedDesign @@ -570,7 +617,9 @@ class SortDialog(QDialog): checkBox = self.sender() self.customSortGroup.setEnabled(checkBox.isChecked()) + class MainWindow(QMainWindow): + def __init__(self, font): super(MainWindow, self).__init__() self.setAttribute(Qt.WA_DeleteOnClose) @@ -631,15 +680,16 @@ class MainWindow(QMainWindow): green.setData(QColor(Qt.green)) editMenu.addMenu(markColorMenu) editMenu.addAction("Copy", self.copy, QKeySequence.Copy) - editMenu.addAction("Copy as component", self.copyAsComponent, "Ctrl+Alt+C") + editMenu.addAction("Copy as component", + self.copyAsComponent, "Ctrl+Alt+C") editMenu.addAction("Paste", self.paste, QKeySequence.Paste) editMenu.addSeparator() editMenu.addAction("Settings…", self.settings) menuBar.addMenu(editMenu) fontMenu = QMenu("&Font", self) - # TODO: work out sensible shortcuts and make sure they're cross-platform - # ready - consider extracting them into separate file? + # TODO: work out sensible shortcuts and make sure they're + # cross-platform ready - consider extracting them into separate file? fontMenu.addAction("&Add glyph", self.addGlyph, "Ctrl+Alt+G") fontMenu.addAction("Font &info", self.fontInfo, "Ctrl+Alt+I") fontMenu.addAction("Font &features", self.fontFeatures, "Ctrl+Alt+F") @@ -667,7 +717,7 @@ class MainWindow(QMainWindow): self.sqSizeSlider = QSlider(Qt.Horizontal, self) self.sqSizeSlider.setMinimum(36) self.sqSizeSlider.setMaximum(96) - self.sqSizeSlider.setFixedWidth(.9*self.sqSizeSlider.width()) + self.sqSizeSlider.setFixedWidth(.9 * self.sqSizeSlider.width()) self.sqSizeSlider.setValue(squareSize) self.sqSizeSlider.valueChanged.connect(self._squareSizeChanged) self.selectionLabel = QLabel(self) @@ -689,7 +739,7 @@ class MainWindow(QMainWindow): font.info.capHeight = 750 font.info.xHeight = 500 defaultGlyphSet = QSettings().value("settings/defaultGlyphSet", - latinDefault.name, type=str) + latinDefault.name, type=str) if defaultGlyphSet: glyphNames = None if defaultGlyphSet == latinDefault.name: @@ -710,14 +760,18 @@ class MainWindow(QMainWindow): def openFile(self, path=None): if not path: - path, ok = QFileDialog.getOpenFileName(self, "Open File", '', - platformSpecific.fileFormats) - if not ok: return + path, ok = QFileDialog.getOpenFileName( + self, "Open File", '', + platformSpecific.fileFormats + ) + if not ok: + return if path: if ".plist" in path: path = os.path.dirname(path) for window in QApplication.topLevelWidgets(): - if isinstance(window, MainWindow) and window._font.path == path: + if (isinstance(window, MainWindow) + and window._font.path == path): window.raise_() return try: @@ -756,9 +810,10 @@ class MainWindow(QMainWindow): ("UFO Font version 3 (*.ufo)", 3), ("UFO Fonts version 2 (*.ufo)", 2), ]) - # TODO: see if OSX works nicely with UFO as files, then switch to directory - # on platforms that need it - dialog = QFileDialog(self, "Save File", None, ";;".join(fileFormats.keys())) + # TODO: see if OSX works nicely with UFO as files, then switch + # to directory on platforms that need it + dialog = QFileDialog(self, "Save File", None, + ";;".join(fileFormats.keys())) dialog.setAcceptMode(QFileDialog.AcceptSave) ok = dialog.exec_() if ok: @@ -766,7 +821,7 @@ class MainWindow(QMainWindow): path = dialog.selectedFiles()[0] self.saveFile(path, fileFormats[nameFilter]) self.setWindowTitle() - #return ok + # return ok def export(self): try: @@ -781,18 +836,19 @@ class MainWindow(QMainWindow): return path, ok = QFileDialog.getSaveFileName(self, "Save File", None, - "PS OpenType font (*.otf)") + "PS OpenType font (*.otf)") if ok: compiler = OTFCompiler() # XXX: allow choosing parameters reports = compiler.compile(self.font, path, checkOutlines=False, - autohint=True, releaseMode=True) + autohint=True, releaseMode=True) print(reports["autohint"]) print(reports["makeotf"]) def setCurrentFile(self, path): - if path is None: return + if path is None: + return settings = QSettings() recentFiles = settings.value("core/recentFiles", [], type=str) if path in recentFiles: @@ -837,10 +893,14 @@ class MainWindow(QMainWindow): currentFont = os.path.basename(self.font.path.rstrip(os.sep)) else: currentFont = "Untitled.ufo" - body = "Do you want to save the changes you made to “%s”?" % currentFont - closeDialog = QMessageBox(QMessageBox.Question, None, body, - QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self) - closeDialog.setInformativeText("Your changes will be lost if you don’t save them.") + body = "Do you want to save the changes you made to “%s”?" \ + % currentFont + closeDialog = QMessageBox( + QMessageBox.Question, None, body, + QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, + self) + closeDialog.setInformativeText( + "Your changes will be lost if you don’t save them.") closeDialog.setModal(True) ret = closeDialog.exec_() if ret == QMessageBox.Save: @@ -901,13 +961,13 @@ class MainWindow(QMainWindow): glyphs.append(glyph) else: glyphs = [self._font[k] for k in self._font.unicodeData - .sortGlyphNames(self._font.keys(), desc)] + .sortGlyphNames(self._font.keys(), desc)] self.collectionWidget.glyphs = glyphs self._sortDescriptor = desc sortDescriptor = property(_get_sortDescriptor, _set_sortDescriptor, - doc="The sortDescriptor. Takes glyphs from the font and sorts them \ - when set.") + doc="The sortDescriptor. Takes glyphs from the " + "font and sorts them when set.") def getGlyphs(self): return self.collectionWidget.glyphs @@ -920,7 +980,8 @@ class MainWindow(QMainWindow): pickled.append(glyphs[index].serialize()) clipboard = QApplication.clipboard() mimeData = QMimeData() - mimeData.setData("application/x-defconQt-glyph-data", pickle.dumps(pickled)) + mimeData.setData("application/x-defconQt-glyph-data", + pickle.dumps(pickled)) clipboard.setMimeData(mimeData) def copyAsComponent(self): @@ -937,14 +998,16 @@ class MainWindow(QMainWindow): pickled.append(componentGlyph.serialize()) clipboard = QApplication.clipboard() mimeData = QMimeData() - mimeData.setData("application/x-defconQt-glyph-data", pickle.dumps(pickled)) + mimeData.setData("application/x-defconQt-glyph-data", + pickle.dumps(pickled)) clipboard.setMimeData(mimeData) def paste(self): clipboard = QApplication.clipboard() mimeData = clipboard.mimeData() if mimeData.hasFormat("application/x-defconQt-glyph-data"): - data = pickle.loads(mimeData.data("application/x-defconQt-glyph-data")) + data = pickle.loads(mimeData.data( + "application/x-defconQt-glyph-data")) glyphs = self.collectionWidget.getSelectedGlyphs() if len(data) == len(glyphs): for pickled, glyph in zip(data, glyphs): @@ -968,7 +1031,8 @@ class MainWindow(QMainWindow): glyphs = self.collectionWidget.glyphs for key in self.collectionWidget.selection: glyph = glyphs[key] - glyph.markColor = Color(color.getRgbF() if color is not None else None) + glyph.markColor = Color( + color.getRgbF() if color is not None else None) def _fontChanged(self, notification): self.collectionWidget.update() @@ -988,7 +1052,8 @@ class MainWindow(QMainWindow): text = "" if not count == 0: text = "%s(%d selected)" % (text, count) - else: text = "" + else: + text = "" self.selectionLabel.setText(text) def _squareSizeChanged(self): @@ -1006,7 +1071,8 @@ class MainWindow(QMainWindow): return super(MainWindow, self).event(event) def resizeEvent(self, event): - if self.isVisible(): self.collectionWidget._sizeEvent(event.size().width()) + if self.isVisible(): + self.collectionWidget._sizeEvent(event.size().width()) super(MainWindow, self).resizeEvent(event) def setWindowTitle(self, title=None): @@ -1019,10 +1085,12 @@ class MainWindow(QMainWindow): def fontInfo(self): # If a window is already opened, bring it to the front, else spawn one. - # TODO: see about using widget.setAttribute(Qt.WA_DeleteOnClose) otherwise - # it seems we're just leaking memory after each close... (both raise_ and - # show allocate memory instead of using the hidden widget it seems) - if not (hasattr(self, 'fontInfoWindow') and self.fontInfoWindow.isVisible()): + # TODO: see about using widget.setAttribute(Qt.WA_DeleteOnClose) + # otherwise it seems we're just leaking memory after each close... + # (both raise_ and show allocate memory instead of using the hidden + # widget it seems) + if not (hasattr(self, 'fontInfoWindow') + and self.fontInfoWindow.isVisible()): self.fontInfoWindow = TabDialog(self.font, self) self.fontInfoWindow.show() else: @@ -1032,7 +1100,8 @@ class MainWindow(QMainWindow): def fontFeatures(self): # TODO: see up here - if not (hasattr(self, 'fontFeaturesWindow') and self.fontFeaturesWindow.isVisible()): + if not (hasattr(self, 'fontFeaturesWindow') + and self.fontFeaturesWindow.isVisible()): self.fontFeaturesWindow = MainEditWindow(self.font, self) self.fontFeaturesWindow.show() else: @@ -1040,8 +1109,10 @@ class MainWindow(QMainWindow): def spaceCenter(self): # TODO: see up here - # TODO: show selection in a space center, rewind selection if we raise window (rf) - if not (hasattr(self, 'spaceCenterWindow') and self.spaceCenterWindow.isVisible()): + # TODO: show selection in a space center, rewind selection if we raise + # window (rf) + if not (hasattr(self, 'spaceCenterWindow') + and self.spaceCenterWindow.isVisible()): self.spaceCenterWindow = MainSpaceWindow(self.font, parent=self) self.spaceCenterWindow.show() else: @@ -1056,7 +1127,8 @@ class MainWindow(QMainWindow): def fontGroups(self): # TODO: see up here - if not (hasattr(self, 'fontGroupsWindow') and self.fontGroupsWindow.isVisible()): + if not (hasattr(self, 'fontGroupsWindow') + and self.fontGroupsWindow.isVisible()): self.fontGroupsWindow = GroupsWindow(self.font, self) self.fontGroupsWindow.show() else: @@ -1086,13 +1158,15 @@ class MainWindow(QMainWindow): app.inspectorWindow.show() def sortGlyphs(self): - sortDescriptor, ok = SortDialog.getDescriptor(self, self.sortDescriptor) + sortDescriptor, ok = SortDialog.getDescriptor(self, + self.sortDescriptor) if ok: self.sortDescriptor = sortDescriptor def addGlyph(self): glyphs = self.collectionWidget.glyphs - newGlyphNames, params, ok = AddGlyphDialog.getNewGlyphNames(self, glyphs) + newGlyphNames, params, ok = AddGlyphDialog.getNewGlyphNames( + self, glyphs) if ok: sortFont = params.pop("sortFont") for name in newGlyphNames: @@ -1109,22 +1183,26 @@ class MainWindow(QMainWindow): def about(self): name = QApplication.applicationName() - QMessageBox.about(self, "About {}".format(name), - "<h3>About {}</h3>" \ - "<p>I am a new UFO-centric font editor and I aim to bring the <b>robofab</b> " \ - "ecosystem to all main operating systems, in a fast and dependency-free " \ - "package.</p>".format(name)) + QMessageBox.about( + self, "About {}".format(name), + "<h3>About {}</h3>" + "<p>I am a new UFO-centric font editor and I aim to bring " + "the <b>robofab</b> ecosystem to all main operating systems, " + "in a fast and dependency-free package.</p>".format(name)) + class SettingsDialog(QDialog): + def __init__(self, parent=None): super(SettingsDialog, self).__init__(parent) - #self.setWindowModality(Qt.WindowModal) + # self.setWindowModality(Qt.WindowModal) self.setWindowTitle("Settings") self.tabWidget = QTabWidget(self) self.tabWidget.addTab(GlyphSetTab(self), "Glyph sets") - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -1138,11 +1216,13 @@ class SettingsDialog(QDialog): self.tabWidget.widget(i).writeValues() super(SettingsDialog, self).accept() + def getDefaultGlyphSet(settings=None): if settings is None: settings = QSettings() settings.value("settings/defaultGlyphSet", latinDefault.name, type=str) + def readGlyphSets(settings=None): if settings is None: settings = QSettings() @@ -1159,14 +1239,17 @@ def readGlyphSets(settings=None): settings.endArray() return glyphSets + class GlyphSetTab(QWidget): + def __init__(self, parent=None): super(GlyphSetTab, self).__init__(parent) settings = QSettings() self.defaultGlyphSetBox = QCheckBox("Default glyph set:", self) self.defaultGlyphSetDrop = QComboBox(self) - defaultGlyphSet = settings.value("settings/defaultGlyphSet", latinDefault.name, type=str) + defaultGlyphSet = settings.value( + "settings/defaultGlyphSet", latinDefault.name, type=str) self.defaultGlyphSetBox.toggled.connect(self.toggleGlyphSetDrop) self.defaultGlyphSetBox.setChecked(len(defaultGlyphSet)) self.glyphSets = readGlyphSets() @@ -1177,10 +1260,12 @@ class GlyphSetTab(QWidget): self.glyphSetList.setSortingEnabled(True) self.glyphSetContents = QTextEdit(self) self.glyphSetContents.setAcceptRichText(False) - self.glyphSetList.currentItemChanged.connect(self.updateGlyphSetContents) + self.glyphSetList.currentItemChanged.connect( + self.updateGlyphSetContents) self.glyphSetList.itemChanged.connect(self.renameGlyphSet) self._cachedName = None - # Normally we should enforce this rather decently in the interface already + # Normally we should enforce this rather decently in the interface + # already if glyphSetNames: for glyphSetName in glyphSetNames: item = QListWidgetItem(glyphSetName, self.glyphSetList) @@ -1196,7 +1281,8 @@ class GlyphSetTab(QWidget): self.removeGlyphSetButton.pressed.connect(self.removeGlyphSet) self.importButton = QPushButton("Import", self) importMenu = QMenu(self) - importMenu.addAction("Import from current font", self.importFromCurrentFont) + importMenu.addAction("Import from current font", + self.importFromCurrentFont) self.importButton.setMenu(importMenu) mainLayout = QGridLayout() @@ -1233,7 +1319,8 @@ class GlyphSetTab(QWidget): def renameGlyphSet(self): newKey = self.glyphSetList.currentItem() - if newKey is None: return + if newKey is None: + return newKey = newKey.text() self.glyphSets[newKey] = self.glyphSets[self._cachedName] del self.glyphSets[self._cachedName] @@ -1263,7 +1350,8 @@ class GlyphSetTab(QWidget): def writeGlyphSets(self, settings): # technically we're already enforcing that this doesn't happen - if not len(self.glyphSets): return + if not len(self.glyphSets): + return settings.beginWriteArray("glyphSets", len(self.glyphSets)) index = 0 for name, cset in self.glyphSets.items(): diff --git a/Lib/defconQt/glyphCollectionView.py b/Lib/defconQt/glyphCollectionView.py index 5f4cadb..c4ee9e4 100644 --- a/Lib/defconQt/glyphCollectionView.py +++ b/Lib/defconQt/glyphCollectionView.py @@ -1,9 +1,12 @@ from defconQt.util import platformSpecific from PyQt5.QtCore import QMimeData, QRectF, QSize, Qt -from PyQt5.QtGui import (QBrush, QColor, QCursor, QDrag, QFont, QFontMetrics, - QKeySequence, QLinearGradient, QPainter, QPen) +from PyQt5.QtGui import ( + QBrush, QColor, QCursor, QDrag, QFont, QFontMetrics, QKeySequence, + QLinearGradient, QPainter, QPen) from PyQt5.QtWidgets import QApplication, QMessageBox, QScrollArea, QWidget -import math, time, unicodedata +import math +import time +import unicodedata cellGridColor = QColor(130, 130, 130) cellHeaderBaseColor = QColor(230, 230, 230) @@ -14,8 +17,8 @@ cellSelectionColor = QColor.fromRgbF(.2, .3, .7, .15) GlyphCellBufferHeight = .2 GlyphCellHeaderHeight = 14 -# TODO: consider extracting each platform-specific thing (fonts, shortcuts) in a -# purposed folder +# TODO: consider extracting each platform-specific thing (fonts, shortcuts) in +# a autpurposed folder headerFont = QFont() headerFont.setFamily('Lucida Sans Unicode') headerFont.insertSubstitution('Lucida Sans Unicode', 'Lucida Grande') @@ -27,9 +30,10 @@ metrics = QFontMetrics(headerFont) arrowKeys = (Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right) + def proceedWithDeletion(self): closeDialog = QMessageBox(QMessageBox.Question, "", "Delete glyphs", - QMessageBox.Yes | QMessageBox.No, self) + QMessageBox.Yes | QMessageBox.No, self) closeDialog.setInformativeText("Are you sure you want to delete them?") closeDialog.setModal(True) ret = closeDialog.exec_() @@ -40,7 +44,10 @@ def proceedWithDeletion(self): """ A widget that presents a list of glyphs in cells. """ + + class GlyphCollectionWidget(QWidget): + def __init__(self, parent=None): super(GlyphCollectionWidget, self).__init__(parent) self.setAttribute(Qt.WA_KeyCompression) @@ -78,10 +85,11 @@ class GlyphCollectionWidget(QWidget): self._glyphs = glyphs self.adjustSize() self.selection = set() - #self.update() # self.selection changed will do it + # self.update() # self.selection changed will do it - glyphs = property(_get_glyphs, _set_glyphs, doc="A list of glyphs \ - displayed. Clears selection and schedules display refresh when set.") + glyphs = property( + _get_glyphs, _set_glyphs, doc="A list of glyphs displayed. Clears " + "selection and schedules display refresh when set.") def _get_selection(self): return self._selection @@ -91,8 +99,9 @@ class GlyphCollectionWidget(QWidget): self.computeCharacterSelected() self.update() - selection = property(_get_selection, _set_selection, doc="A set that contains \ - indexes of selected glyphs. Schedules display refresh when set.") + selection = property( + _get_selection, _set_selection, doc="A set that contains indexes of " + "selected glyphs. Schedules display refresh when set.") def getSelectedGlyphs(self): return [self._glyphs[key] for key in sorted(self._selection)] @@ -109,7 +118,8 @@ class GlyphCollectionWidget(QWidget): if index is not None: self.scrollToCell(index) - lastSelectedCell = property(_get_lastSelectedCell, _set_lastSelectedCell, + lastSelectedCell = property( + _get_lastSelectedCell, _set_lastSelectedCell, doc="The current lastSelectedCell in selection.") def lastSelectedGlyph(self): @@ -122,7 +132,8 @@ class GlyphCollectionWidget(QWidget): def scrollToCell(self, index): x = (.5 + index % self._columns) * self.squareSize y = (.5 + index // self._columns) * self.squareSize - self._scrollArea.ensureVisible(x, y, .5*self.squareSize, .5*self.squareSize) + self._scrollArea.ensureVisible( + x, y, .5 * self.squareSize, .5 * self.squareSize) def _get_currentDropIndex(self): return self._currentDropIndex @@ -141,15 +152,16 @@ class GlyphCollectionWidget(QWidget): def pipeDragMoveEvent(self, event): if event.source() == self: pos = event.posF() - self.currentDropIndex = int(self._columns * (pos.y() // self.squareSize) \ - + (pos.x() + .5*self.squareSize) // self.squareSize) + self.currentDropIndex = int( + self._columns * (pos.y() // self.squareSize) + + (pos.x() + .5 * self.squareSize) // self.squareSize) def pipeDragLeaveEvent(self, event): self.currentDropIndex = None def pipeDropEvent(self, event): - # TODO: consider dropping this check, maybe only subclasses should do it - # so as to dispatch but here we presumably don't need it + # TODO: consider dropping this check, maybe only subclasses should do + # it so as to dispatch but here we presumably don't need it if event.source() == self: insert = self.currentDropIndex newGlyphNames = event.mimeData().text().split(" ") @@ -163,27 +175,34 @@ class GlyphCollectionWidget(QWidget): self._glyphs[index] = None # insert newGlyphs into the list lst = self._glyphs[:insert] - lst.extend(newGlyphs+self._glyphs[insert:]) + lst.extend(newGlyphs + self._glyphs[insert:]) self._glyphs = lst # now, elide None self.currentDropIndex = None - self.glyphs = [glyph for glyph in self._glyphs if glyph != None] + self.glyphs = [glyph + for glyph in self._glyphs if glyph is not None] # TODO: break this down into set width/set square # TODO: see whether scrollArea gets resizeEvents def _sizeEvent(self, width, squareSize=None): - sw = self._scrollArea.verticalScrollBar().width() + self._scrollArea.contentsMargins().right() - if squareSize is not None: self.squareSize = squareSize + sw = self._scrollArea.verticalScrollBar().width( + ) + self._scrollArea.contentsMargins().right() + if squareSize is not None: + self.squareSize = squareSize columns = (width - sw) // self.squareSize - if not columns > 0: return + if not columns > 0: + return self._columns = columns self.adjustSize() def sizeHint(self): - # Calculate sizeHint with max(height, _scrollArea.height()) because if scrollArea is - # bigger than widget height after an update, we risk leaving old painted content on screen - return QSize(self._columns * self.squareSize, - max(math.ceil(len(self._glyphs) / self._columns) * self.squareSize, self._scrollArea.height())) + # Calculate sizeHint with max(height, _scrollArea.height()) because + # if scrollArea is bigger than widget height after an update, we risk + # leaving old painted content on screen + return QSize( + self._columns * self.squareSize, + max(math.ceil(len(self._glyphs) / self._columns) * self.squareSize, + self._scrollArea.height())) def computeCharacterSelected(self): if self.characterSelectedCallback is None: @@ -210,7 +229,7 @@ class GlyphCollectionWidget(QWidget): delta = -1 elif key == Qt.Key_Right: delta = 1 - newSel = self._lastSelectedCell + delta*count + newSel = self._lastSelectedCell + delta * count if newSel < 0 or newSel >= len(self._glyphs): return if modifiers & Qt.ShiftModifier: @@ -229,16 +248,17 @@ class GlyphCollectionWidget(QWidget): elif key == Qt.Key_Return: index = self._lastSelectedCell if index is not None and self.doubleClickCallback is not None: - # TODO: does it still make sense to call this doubleClickCallback? + # TODO: does it still make sense to call this + # doubleClickCallback? self.doubleClickCallback(self._glyphs[index]) elif event.matches(QKeySequence.SelectAll): self.selection = set(range(len(self._glyphs))) elif key == Qt.Key_D and modifiers & Qt.ControlModifier: self.selection = set() - # XXX: this is specific to fontView so should be done thru subclassing of a base widget, - # as is done in groupsView + # XXX: this is specific to fontView so should be done thru subclassing + # of a base widget, as is done in groupsView elif key == platformSpecific.deleteKey: - #if self.characterDeletionCallback is not None: + # if self.characterDeletionCallback is not None: if proceedWithDeletion(self) and self.selection: # we need to del in reverse order to keep key references valid for key in sorted(self._selection, reverse=True): @@ -252,8 +272,8 @@ class GlyphCollectionWidget(QWidget): # XXX: have template setter clear glyph content glyph.template = True self.selection = set() - elif modifiers in (Qt.NoModifier, Qt.ShiftModifier) and \ - unicodedata.category(event.text()) != "Cc": + elif (modifiers in (Qt.NoModifier, Qt.ShiftModifier) and + unicodedata.category(event.text()) != "Cc"): # adapted from defconAppkit # get the current time rightNow = time.time() @@ -274,22 +294,26 @@ class GlyphCollectionWidget(QWidget): lastResortIndex = None for index, glyph in enumerate(self._glyphs): item = glyph.name - # if the item starts with the input string, it is considered a match + # if the item starts with the input string, it is considered + # a match if item.startswith(self._inputString): if match is None: match = item matchIndex = index continue - # only if the item is less than the previous match is it a more relevant match + # only if the item is less than the previous match is it + # a more relevant match # example: # given this order: sys, signal # and this input string: s - # sys will be the first match, but signal is the more accurate match + # sys will be the first match, but signal is the more + # accurate match if item < match: match = item matchIndex = index continue - # if the item is greater than the input string,it can be used as a last resort + # if the item is greater than the input string,it can be used + # as a last resort # example: # given this order: vanilla, zipimport # and this input string: x @@ -319,7 +343,8 @@ class GlyphCollectionWidget(QWidget): event.accept() def _findEventIndex(self, event): - index = (event.y() // self.squareSize) * self._columns + event.x() // self.squareSize + index = (event.y() // self.squareSize) * \ + self._columns + event.x() // self.squareSize if index >= len(self._glyphs): return None return index @@ -331,9 +356,11 @@ class GlyphCollectionWidget(QWidget): newSelection = {index} else: if index < self._lastSelectedCell: - newSelection = self._selection | set(range(index, self._lastSelectedCell + 1)) + newSelection = self._selection | set( + range(index, self._lastSelectedCell + 1)) else: - newSelection = self._selection | set(range(self._lastSelectedCell, index + 1)) + newSelection = self._selection | set( + range(self._lastSelectedCell, index + 1)) return newSelection # TODO: in mousePressEvent and mouseMoveEvent below, self._lastSelectedCell @@ -345,7 +372,8 @@ class GlyphCollectionWidget(QWidget): modifiers = event.modifiers() event.accept() if index is None: - if not (modifiers & Qt.ControlModifier or modifiers & Qt.ShiftModifier): + if not (modifiers & Qt.ControlModifier or + modifiers & Qt.ShiftModifier): self.selection = set() self._lastSelectedCell = index return @@ -363,7 +391,7 @@ class GlyphCollectionWidget(QWidget): newSelection = self._linearSelection(index) if newSelection is not None: self.selection = newSelection - elif not index in self._selection: + elif index not in self._selection: self.selection = {index} else: self._maybeDragPosition = event.pos() @@ -375,10 +403,12 @@ class GlyphCollectionWidget(QWidget): if event.buttons() & Qt.LeftButton: index = self._findEventIndex(event) if self._maybeDragPosition is not None: - if ((event.pos() - self._maybeDragPosition).manhattanLength() \ - < QApplication.startDragDistance()): return + if ((event.pos() - self._maybeDragPosition).manhattanLength() + < QApplication.startDragDistance()): + return # TODO: needs ordering or not? - glyphList = " ".join(glyph.name for glyph in self.getSelectedGlyphs()) + glyphList = " ".join( + glyph.name for glyph in self.getSelectedGlyphs()) drag = QDrag(self) mimeData = QMimeData() mimeData.setText(glyphList) @@ -394,7 +424,8 @@ class GlyphCollectionWidget(QWidget): modifiers = event.modifiers() event.accept() if index is None: - if not (modifiers & Qt.ControlModifier or modifiers & Qt.ShiftModifier): + if not (modifiers & Qt.ControlModifier or + modifiers & Qt.ShiftModifier): self.selection = set() self._lastSelectedCell = index return @@ -403,7 +434,8 @@ class GlyphCollectionWidget(QWidget): selection = self.selection selection.remove(index) self.selection = selection - elif index not in self._selection and index not in self._oldSelection: + elif (index not in self._selection and + index not in self._oldSelection): selection = self.selection selection.add(index) self.selection = selection @@ -453,76 +485,93 @@ class GlyphCollectionWidget(QWidget): dirtyGradient = QLinearGradient(0, 0, 0, GlyphCellHeaderHeight) dirtyGradient.setColorAt(0.0, cellHeaderBaseColor.darker(125)) dirtyGradient.setColorAt(1.0, cellHeaderLineColor.darker(125)) - markGradient = QLinearGradient(0, 0, 0, self.squareSize-GlyphCellHeaderHeight) + markGradient = QLinearGradient( + 0, 0, 0, self.squareSize - GlyphCellHeaderHeight) for row in range(beginRow, endRow + 1): for column in range(beginColumn, endColumn + 1): key = row * self._columns + column - if key >= len(self._glyphs): break + if key >= len(self._glyphs): + break glyph = self._glyphs[key] painter.save() - painter.translate(column * self.squareSize, row * self.squareSize) - painter.fillRect(0, 0, self.squareSize, self.squareSize, Qt.white) + painter.translate(column * self.squareSize, + row * self.squareSize) + painter.fillRect(0, 0, self.squareSize, + self.squareSize, Qt.white) # prepare header colors brushColor = gradient linesColor = cellHeaderHighlightLineColor # mark color - if not glyph.template: - if glyph.markColor is not None: - markColor = QColor.fromRgbF(*tuple(glyph.markColor)) - markGradient.setColorAt(1.0, markColor) - markGradient.setColorAt(0.0, markColor.lighter(125)) - painter.fillRect(0, GlyphCellHeaderHeight, self.squareSize, - self.squareSize - GlyphCellHeaderHeight, QBrush(markGradient)) - if glyph.dirty: - brushColor = dirtyGradient - linesColor = cellHeaderHighlightLineColor.darker(110) + if not glyph.template and glyph.markColor is not None: + markColor = QColor.fromRgbF(*tuple(glyph.markColor)) + markGradient.setColorAt(1.0, markColor) + markGradient.setColorAt(0.0, markColor.lighter(125)) + painter.fillRect(0, GlyphCellHeaderHeight, self.squareSize, + self.squareSize - GlyphCellHeaderHeight, + QBrush(markGradient)) + if not glyph.template and glyph.dirty: + brushColor = dirtyGradient + linesColor = cellHeaderHighlightLineColor.darker(110) # header gradient painter.fillRect(0, 0, self.squareSize, GlyphCellHeaderHeight, - QBrush(brushColor)) + QBrush(brushColor)) # header lines painter.setPen(linesColor) minOffset = painter.pen().width() # disable antialiasing to avoid lines bleeding over background painter.setRenderHint(QPainter.Antialiasing, False) painter.drawLine(0, 0, 0, GlyphCellHeaderHeight - 1) - painter.drawLine(self.squareSize - 2, 0, self.squareSize - 2, GlyphCellHeaderHeight -1) + painter.drawLine(self.squareSize - 2, 0, + self.squareSize - 2, + GlyphCellHeaderHeight - 1) painter.setPen(QColor(170, 170, 170)) - painter.drawLine(0, GlyphCellHeaderHeight, self.squareSize, GlyphCellHeaderHeight) + painter.drawLine(0, GlyphCellHeaderHeight, + self.squareSize, GlyphCellHeaderHeight) painter.setRenderHint(QPainter.Antialiasing) # header text painter.setFont(headerFont) painter.setPen(QColor(80, 80, 80)) - name = metrics.elidedText(glyph.name, Qt.ElideRight, self.squareSize - 2) - painter.drawText(1, 0, self.squareSize - 2, GlyphCellHeaderHeight - minOffset, - Qt.TextSingleLine | Qt.AlignCenter, name) + name = metrics.elidedText( + glyph.name, Qt.ElideRight, self.squareSize - 2) + painter.drawText(1, 0, self.squareSize - 2, + GlyphCellHeaderHeight - minOffset, + Qt.TextSingleLine | Qt.AlignCenter, + name) painter.restore() painter.setPen(cellGridColor) rightEdgeX = column * self.squareSize + self.squareSize bottomEdgeY = row * self.squareSize + self.squareSize - painter.drawLine(rightEdgeX, row * self.squareSize + 1, rightEdgeX, bottomEdgeY) - painter.drawLine(rightEdgeX, bottomEdgeY, column * self.squareSize + 1, bottomEdgeY) + painter.drawLine(rightEdgeX, row * + self.squareSize + 1, rightEdgeX, bottomEdgeY) + painter.drawLine(rightEdgeX, bottomEdgeY, + column * self.squareSize + 1, bottomEdgeY) if self._currentDropIndex is not None: painter.setPen(Qt.green) if self._currentDropIndex == key: - painter.drawLine(column * self.squareSize, row * self.squareSize, + painter.drawLine( + column * self.squareSize, row * self.squareSize, column * self.squareSize, bottomEdgeY) # special-case the end-column - elif column == endColumn and self._currentDropIndex == key+1: + elif (column == endColumn and + self._currentDropIndex == key + 1): yPos = self.mapFromGlobal(QCursor.pos()).y() if row == yPos // self.squareSize: - painter.drawLine(rightEdgeX - 1, row * self.squareSize, + painter.drawLine( + rightEdgeX - 1, row * self.squareSize, rightEdgeX - 1, bottomEdgeY) # selection code if key in self._selection: painter.setRenderHint(QPainter.Antialiasing, False) painter.fillRect(column * self.squareSize + 1, - row * self.squareSize + 1, self.squareSize - 3, - self.squareSize - 3, cellSelectionColor) + row * self.squareSize + 1, + self.squareSize - 3, + self.squareSize - 3, + cellSelectionColor) painter.setRenderHint(QPainter.Antialiasing) if not glyph.template: @@ -534,18 +583,25 @@ class GlyphCollectionWidget(QWidget): descender = font.info.descender if descender is None or not descender < 0: descender = -250 - factor = (self.squareSize-GlyphCellHeaderHeight) / (uPM*(1+2*GlyphCellBufferHeight)) - x_offset = (self.squareSize-glyph.width*factor)/2 - # If the glyph overflows horizontally we need to adjust the scaling factor + factor = (self.squareSize - GlyphCellHeaderHeight) / \ + (uPM * (1 + 2 * GlyphCellBufferHeight)) + x_offset = (self.squareSize - glyph.width * factor) / 2 + # If the glyph overflows horizontally we need to adjust the + # scaling factor if x_offset < 0: - factor *= 1+2*x_offset/(glyph.width*factor) + factor *= 1 + 2 * x_offset / (glyph.width * factor) x_offset = 0 # TODO: the * 1.8 below is somewhat artificial - y_offset = descender*factor * 1.8 + y_offset = descender * factor * 1.8 painter.save() - painter.setClipRect(column * self.squareSize, row * self.squareSize+GlyphCellHeaderHeight, - self.squareSize, self.squareSize-GlyphCellHeaderHeight) - painter.translate(column * self.squareSize + x_offset, row * self.squareSize + self.squareSize + y_offset) + painter.setClipRect( + column * self.squareSize, + row * self.squareSize + GlyphCellHeaderHeight, + self.squareSize, + self.squareSize - GlyphCellHeaderHeight) + painter.translate( + column * self.squareSize + x_offset, + row * self.squareSize + self.squareSize + y_offset) painter.scale(factor, -factor) painter.fillPath(outline, Qt.black) painter.restore() @@ -553,9 +609,13 @@ class GlyphCollectionWidget(QWidget): painter.save() painter.setFont(voidFont) painter.setPen(QPen(Qt.lightGray)) - rect = QRectF(column * self.squareSize, row * self.squareSize+GlyphCellHeaderHeight, - self.squareSize, self.squareSize-GlyphCellHeaderHeight) - # TODO: need to flag template glyphs as to whether they have unicodings or not + rect = QRectF( + column * self.squareSize, + row * self.squareSize + GlyphCellHeaderHeight, + self.squareSize, + self.squareSize - GlyphCellHeaderHeight) + # TODO: need to flag template glyphs as to whether they + # have unicodings or not if glyph.unicode is not None: text = chr(glyph.unicode) else: diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py index adebab3..eb4f4ba 100644 --- a/Lib/defconQt/glyphView.py +++ b/Lib/defconQt/glyphView.py @@ -8,11 +8,18 @@ from defconQt.objects.defcon import TContour, TGlyph from defconQt.pens.copySelectionPen import CopySelectionPen from defconQt.util import platformSpecific from fontTools.misc import bezierTools -from PyQt5.QtCore import *#QFile, QLineF, QObject, QPointF, QRectF, QSize, Qt -from PyQt5.QtGui import *#QBrush, QColor, QImage, QKeySequence, QPainter, QPainterPath, QPixmap, QPen, QColorDialog -from PyQt5.QtWidgets import *#(QAction, QActionGroup, QApplication, QFileDialog, - #QGraphicsItem, QGraphicsEllipseItem, QGraphicsLineItem, QGraphicsPathItem, QGraphicsRectItem, QGraphicsScene, QGraphicsView, - #QMainWindow, QMenu, QMessageBox, QStyle, QStyleOptionGraphicsItem, QWidget) +from PyQt5.QtCore import QEvent, QLineF, QMimeData, QPointF, Qt +from PyQt5.QtGui import ( + QBrush, QColor, QFont, QIcon, QKeySequence, QPainter, QPainterPath, QPen, + QPixmap, QTransform) +from PyQt5.QtWidgets import ( + QAction, QActionGroup, QApplication, QColorDialog, QComboBox, QDialog, + QDialogButtonBox, QGraphicsEllipseItem, QGraphicsItem, QGraphicsLineItem, + QGraphicsPathItem, QGraphicsPixmapItem, QGraphicsRectItem, QGraphicsScene, + QGraphicsSimpleTextItem, QGraphicsView, QGridLayout, QLabel, QLineEdit, + QListWidget, QMainWindow, QMenu, QRadioButton, QSizePolicy, QStyle, + QStyleOptionGraphicsItem, QToolBar, QWidget) + class GotoDialog(QDialog): alphabetical = [ @@ -24,7 +31,8 @@ class GotoDialog(QDialog): self.setWindowModality(Qt.WindowModal) self.setWindowTitle("Go to…") self.font = currentGlyph.getParent() - self._sortedGlyphs = self.font.unicodeData.sortGlyphNames(self.font.keys(), self.alphabetical) + self._sortedGlyphs = self.font.unicodeData.sortGlyphNames( + self.font.keys(), self.alphabetical) layout = QGridLayout(self) self.glyphLabel = QLabel("Glyph:", self) @@ -41,7 +49,8 @@ class GotoDialog(QDialog): self.glyphList = QListWidget(self) self.glyphList.itemDoubleClicked.connect(self.accept) - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -81,11 +90,13 @@ class GotoDialog(QDialog): self.glyphList.addItems(self._sortedGlyphs) text = self.glyphEdit.text() if select: - glyphs = [glyph for glyph in self._sortedGlyphs if glyph.startswith(text)] + glyphs = [glyph for glyph in self._sortedGlyphs + if glyph.startswith(text)] else: glyphs = [glyph for glyph in self._sortedGlyphs if text in glyph] self.glyphList.addItems(glyphs) - if select: self.glyphList.setCurrentRow(0) + if select: + self.glyphList.setCurrentRow(0) @classmethod def getNewGlyph(cls, parent, currentGlyph): @@ -99,7 +110,9 @@ class GotoDialog(QDialog): newGlyph = dialog.font[newGlyphName] return (newGlyph, result) + class AddAnchorDialog(QDialog): + def __init__(self, pos=None, parent=None): super(AddAnchorDialog, self).__init__(parent) self.setWindowModality(Qt.WindowModal) @@ -111,10 +124,12 @@ class AddAnchorDialog(QDialog): self.anchorNameEdit = QLineEdit(self) self.anchorNameEdit.setFocus(True) if pos is not None: - anchorPositionLabel = QLabel("The anchor will be added at ({}, {})." - .format(pos.x(), pos.y()), self) + anchorPositionLabel = QLabel( + "The anchor will be added at ({}, {})." + .format(pos.x(), pos.y()), self) - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -134,14 +149,18 @@ class AddAnchorDialog(QDialog): name = dialog.anchorNameEdit.text() return (name, result) + class AddComponentDialog(GotoDialog): + def __init__(self, *args, **kwargs): super(AddComponentDialog, self).__init__(*args, **kwargs) self.setWindowTitle("Add component…") self._sortedGlyphs.remove(args[0].name) self.updateGlyphList(False) + class AddLayerDialog(QDialog): + def __init__(self, parent=None): super(AddLayerDialog, self).__init__(parent) self.setWindowModality(Qt.WindowModal) @@ -153,7 +172,8 @@ class AddLayerDialog(QDialog): self.layerNameEdit = QLineEdit(self) self.layerNameEdit.setFocus(True) - buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -173,8 +193,9 @@ class AddLayerDialog(QDialog): class GenericSettings(object): + def __init__(self, title, parent, callback): - #super().__init__() + # super().__init__() self._menuWidget = QMenu(title, parent) self._actions = {} self._callback = callback @@ -194,7 +215,8 @@ class GenericSettings(object): return self._menuWidget def _addAction(self, key, label, checked): - action = self._menuWidget.addAction(label, partial(self._callback, key)) + action = self._menuWidget.addAction(label, + partial(self._callback, key)) action.setCheckable(True) action.setChecked(checked) self._actions[key] = action @@ -225,38 +247,31 @@ class GenericSettings(object): return self._actions[name].isChecked() - class DisplayStyleSettings(GenericSettings): _presets = ( ('TruFont Default', dict( - activeLayerOnTop = True - , activeLayerFilled = True - , otherLayersFilled = False - , activeLayerUseLayerColor = False - , otherLayerUseLayerColor = True - , drawOtherLayers = True - )) - , ('Layer Fonts', dict( - activeLayerOnTop = False - , activeLayerFilled = True - , otherLayersFilled = True - , activeLayerUseLayerColor = True - , otherLayerUseLayerColor = True - , drawOtherLayers = True + activeLayerOnTop=True, activeLayerFilled=True, + otherLayersFilled=False, activeLayerUseLayerColor=False, + otherLayerUseLayerColor=True, drawOtherLayers=True + )), ('Layer Fonts', dict( + activeLayerOnTop=False, activeLayerFilled=True, + otherLayersFilled=True, activeLayerUseLayerColor=True, + otherLayerUseLayerColor=True, drawOtherLayers=True )) ) _items = ( - ('activeLayerOnTop', ('Active Layer on Top', True)) - , ('activeLayerFilled', ('Active Layer Filled', True)) - , ('activeLayerUseLayerColor', ('Active Layer use Custom Color', False)) - , ('otherLayersFilled', ('Other Layers Filled', False)) - , ('otherLayerUseLayerColor', ('Other Layers use Custom Color', True)) - , ('drawOtherLayers', ('Show Other Layers', True)) + ('activeLayerOnTop', ('Active Layer on Top', True)), + ('activeLayerFilled', ('Active Layer Filled', True)), + ('activeLayerUseLayerColor', ('Active Layer use Custom Color', False)), + ('otherLayersFilled', ('Other Layers Filled', False)), + ('otherLayerUseLayerColor', ('Other Layers use Custom Color', True)), + ('drawOtherLayers', ('Show Other Layers', True)) ) class MainGfxWindow(QMainWindow): + def __init__(self, glyph, parent=None): super(MainGfxWindow, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) @@ -268,18 +283,17 @@ class MainGfxWindow(QMainWindow): self._layerSetNotifications = [] - layerSet.addObserver(self, '_layerSetLayerAdded', 'LayerSet.LayerAdded') - layerSet.addObserver(self, '_layerSetLayerDeleted', 'LayerSet.LayerDeleted') + layerSet.addObserver(self, '_layerSetLayerAdded', + 'LayerSet.LayerAdded') + layerSet.addObserver(self, '_layerSetLayerDeleted', + 'LayerSet.LayerDeleted') self._layerSetNotifications.append('LayerSet.LayerAdded') self._layerSetNotifications.append('LayerSet.LayerDeleted') - - for event in ('LayerSet.LayerChanged', 'LayerSet.DefaultLayerChanged' - , 'LayerSet.LayerOrderChanged'): + for event in ('LayerSet.LayerChanged', 'LayerSet.DefaultLayerChanged', + 'LayerSet.LayerOrderChanged'): self._layerSetNotifications.append(event) - layerSet.addObserver(self, '_layerSetEvents', event) - - + layerSet.addObserver(self, '_layerSetEvents', event) menuBar = self.menuBar() @@ -291,24 +305,28 @@ class MainGfxWindow(QMainWindow): glyphMenu.addAction("&Jump", self.changeGlyph, "J") menuBar.addMenu(glyphMenu) - - self._displaySettings = DisplayStyleSettings("&Display", self, self._displayChanged) + self._displaySettings = DisplayStyleSettings( + "&Display", self, self._displayChanged) menuBar.addMenu(self._displaySettings.menuWidget) self._toolBar = toolBar = QToolBar(self) toolBar.setMovable(False) toolBar.setContentsMargins(2, 0, 2, 0) - selectionToolButton = toolBar.addAction("Selection", self._redirect('view', 'setSceneSelection')) + selectionToolButton = toolBar.addAction( + "Selection", self._redirect('view', 'setSceneSelection')) selectionToolButton.setCheckable(True) selectionToolButton.setChecked(True) selectionToolButton.setIcon(QIcon(":/resources/cursor.svg")) - penToolButton = toolBar.addAction("Pen", self._redirect('view', 'setSceneDrawing')) + penToolButton = toolBar.addAction( + "Pen", self._redirect('view', 'setSceneDrawing')) penToolButton.setCheckable(True) penToolButton.setIcon(QIcon(":/resources/curve.svg")) - rulerToolButton = toolBar.addAction("Ruler", self._redirect('view', 'setSceneRuler')) + rulerToolButton = toolBar.addAction( + "Ruler", self._redirect('view', 'setSceneRuler')) rulerToolButton.setCheckable(True) rulerToolButton.setIcon(QIcon(":/resources/ruler.svg")) - knifeToolButton = toolBar.addAction("Knife", self._redirect('view', 'setSceneKnife')) + knifeToolButton = toolBar.addAction( + "Knife", self._redirect('view', 'setSceneKnife')) knifeToolButton.setCheckable(True) knifeToolButton.setIcon(QIcon(":/resources/cut.svg")) @@ -317,12 +335,13 @@ class MainGfxWindow(QMainWindow): spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolBar.addWidget(spacer) self._currentLayerBox = QComboBox(self) - self._currentLayerBox.currentIndexChanged.connect(self._changeLayerHandler) + self._currentLayerBox.currentIndexChanged.connect( + self._changeLayerHandler) toolBar.addWidget(self._currentLayerBox) self._layerColorButton = toolBar.addAction( - "Layer Color (shift + click to remove the color)", - self._chooseLayerColor) + "Layer Color (shift + click to remove the color)", + self._chooseLayerColor) toolsGroup = QActionGroup(self) toolsGroup.addAction(selectionToolButton) @@ -333,10 +352,12 @@ class MainGfxWindow(QMainWindow): self.setContextMenuPolicy(Qt.ActionsContextMenu) createAnchorAction = QAction("Add Anchor…", self) - createAnchorAction.triggered.connect(self._redirect('view', 'createAnchor')) + createAnchorAction.triggered.connect( + self._redirect('view', 'createAnchor')) self.addAction(createAnchorAction) createComponentAction = QAction("Add Component…", self) - createComponentAction.triggered.connect(self._redirect('view', 'createComponent')) + createComponentAction.triggered.connect( + self._redirect('view', 'createComponent')) self.addAction(createComponentAction) for layer in self._layerSet: @@ -350,13 +371,14 @@ class MainGfxWindow(QMainWindow): def _changeGlyph(self, glyph): oldView = self.view + # Preserve the selected layer (by setting the glyph from that layer) + # Todo: If that layer is already in the glyph, it would be a little bit + # harder to create it here and may be better or worse. Worse becaue + # we'd alter the data without being explicitly asked to do so. + # Ask someone who does UX. if oldView: - # Preserve the selected layer (by setting the glyph from that layer) - # Todo: If that layer is already in the glyph, it would be a little bit - # harder to create it here and may be better or worse. Worse becaue - # we'd alter the data without being explicitly asked to do so. - # Ask someone who does UX. - if oldView.layer is not glyph.layer and glyph.name in oldView.layer: + if (oldView.layer is not glyph.layer and + glyph.name in oldView.layer): glyph = oldView.layer[glyph.name] oldView.hide() oldView.deleteLater() @@ -380,8 +402,10 @@ class MainGfxWindow(QMainWindow): def _executeRemoteCommand(self, targetName, commandName, *args, **kwds): """ - Execute a method named `commandName` on the attribute named `targetName`. - This strongly suggest that there is always a known interface at self.{targetName} + Execute a method named `commandName` on the attribute named + `targetName`. + This strongly suggest that there is always a known interface at + self.{targetName} See MainGfxWindow._redirect """ target = getattr(self, targetName) @@ -400,7 +424,6 @@ class MainGfxWindow(QMainWindow): assert layerSet is self._layerSet self._updateComboBox() - def _layerSetLayerDeleted(self, notification): self._layerSetEvents(notification) self._changeLayerHandler(0) @@ -424,7 +447,8 @@ class MainGfxWindow(QMainWindow): color = None else: startColor = self.view.getLayerColor() or QColor('limegreen') - qColor = QColorDialog.getColor(startColor, self, options=QColorDialog.ShowAlphaChannel) + qColor = QColorDialog.getColor( + startColor, self, options=QColorDialog.ShowAlphaChannel) if not qColor.isValid(): # cancelled return @@ -523,23 +547,29 @@ class MainGfxWindow(QMainWindow): event.accept() def setWindowTitle(self, title, font=None): - if font is not None: title = "%s – %s %s" % (title, font.info.familyName, font.info.styleName) + if font is not None: + title = "%s – %s %s" % ( + title, font.info.familyName, font.info.styleName) super(MainGfxWindow, self).setWindowTitle(title) + def roundPosition(value): - value = value * 10#self._scale + value = value * 10 # self._scale value = round(value) - .5 - value = value * .1#self._inverseScale + value = value * .1 # self._inverseScale return value -offCurvePointSize = 8#5 -onCurvePointSize = 9#6 -onCurveSmoothPointSize = 10#7 -offWidth = offHeight = roundPosition(offCurvePointSize)# * self._inverseScale) +offCurvePointSize = 8 # 5 +onCurvePointSize = 9 # 6 +onCurveSmoothPointSize = 10 # 7 +offWidth = offHeight = roundPosition(offCurvePointSize) +# * self._inverseScale) offHalf = offWidth / 2.0 -onWidth = onHeight = roundPosition(onCurvePointSize)# * self._inverseScale) +onWidth = onHeight = roundPosition(onCurvePointSize) +# * self._inverseScale) onHalf = onWidth / 2.0 -smoothWidth = smoothHeight = roundPosition(onCurveSmoothPointSize)# * self._inverseScale) +smoothWidth = smoothHeight = roundPosition(onCurveSmoothPointSize) +# * self._inverseScale) smoothHalf = smoothWidth / 2.0 onCurvePenWidth = 1.5 offCurvePenWidth = 1.0 @@ -559,29 +589,36 @@ onCurvePointStrokeColor = offCurvePointColor anchorColor = QColor(120, 120, 255) anchorSelectionColor = Qt.blue bluesColor = QColor.fromRgbF(.5, .7, 1, .3) -fillColor = QColor(200, 200, 200, 120)#QColor.fromRgbF(0, 0, 0, .4) -componentFillColor = QColor.fromRgbF(0, 0, 0, .4)#QColor.fromRgbF(.2, .2, .3, .4) +fillColor = QColor(200, 200, 200, 120) # QColor.fromRgbF(0, 0, 0, .4) +componentFillColor = QColor.fromRgbF( + 0, 0, 0, .4) # QColor.fromRgbF(.2, .2, .3, .4) metricsColor = QColor(70, 70, 70) pointSelectionColor = Qt.red + class SceneTools(Enum): SelectionTool = 0 DrawingTool = 1 RulerTool = 2 KnifeTool = 3 + class HandleLineItem(QGraphicsLineItem): + def __init__(self, x1, y1, x2, y2, parent): super(HandleLineItem, self).__init__(x1, y1, x2, y2, parent) self.setPen(QPen(bezierHandleColor, 1.0)) self.setFlag(QGraphicsItem.ItemStacksBehindParent) + class OffCurvePointItem(QGraphicsEllipseItem): + def __init__(self, x, y, parent=None): super(OffCurvePointItem, self).__init__(parent) # since we have a parent, setPos must be relative to it self.setPointPath() - self.setPos(x, y) # TODO: abstract and use pointX-self.parent().pos().x() + # TODO: abstract and use pointX-self.parent().pos().x() + self.setPos(x, y) self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsSelectable) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) @@ -599,7 +636,7 @@ class OffCurvePointItem(QGraphicsEllipseItem): value.setX(round(value.x())) value.setY(round(value.y())) if QApplication.keyboardModifiers() & Qt.ShiftModifier \ - and len(self.scene().selectedItems()) == 1: + and len(self.scene().selectedItems()) == 1: ax = abs(value.x()) ay = abs(value.y()) if ay >= ax * 2: @@ -613,7 +650,7 @@ class OffCurvePointItem(QGraphicsEllipseItem): elif change == QGraphicsItem.ItemPositionHasChanged: self.parentItem()._CPMoved(value) # TODO: consider what to do w offCurves - #elif change == QGraphicsItem.ItemSelectedHasChanged: + # elif change == QGraphicsItem.ItemSelectedHasChanged: # pass#self.parentItem()._CPSelChanged(value) return value @@ -630,7 +667,7 @@ class OffCurvePointItem(QGraphicsEllipseItem): # http://www.qtfr.org/viewtopic.php?pid=21045#p21045 def paint(self, painter, option, widget): - #if self.x() == 0 and self.y() == 0: return + # if self.x() == 0 and self.y() == 0: return newOption = QStyleOptionGraphicsItem(option) newOption.state = QStyle.State_None pen = self.pen() @@ -648,13 +685,18 @@ class OffCurvePointItem(QGraphicsEllipseItem): scale = scene.getViewScale() else: scale = 1 - if scale > 4: scale = 4 - elif scale < .4: scale = .4 + if scale > 4: + scale = 4 + elif scale < .4: + scale = .4 self.prepareGeometryChange() - self.setRect(-offHalf/scale, -offHalf/scale, offWidth/scale, offHeight/scale) - self.setPen(QPen(offCurvePointStrokeColor, offCurvePenWidth/scale)) + self.setRect(-offHalf / scale, -offHalf / scale, + offWidth / scale, offHeight / scale) + self.setPen(QPen(offCurvePointStrokeColor, offCurvePenWidth / scale)) + class OnCurvePointItem(QGraphicsPathItem): + def __init__(self, x, y, isSmooth, contour, point, scale=1, parent=None): super(OnCurvePointItem, self).__init__(parent) self._contour = contour @@ -674,7 +716,7 @@ class OnCurvePointItem(QGraphicsPathItem): for _ in self._contour: if self._contour[index].segmentType is not None: break - index = (index+1) % len(self._contour) + index = (index + 1) % len(self._contour) return index scene = self.scene() @@ -689,9 +731,12 @@ class OnCurvePointItem(QGraphicsPathItem): self._contour[0].segmentType = "move" self._contour.dirty = True else: - # Using preserveShape at the edge of an open contour will traceback - if ptIndex == len(self._contour): preserveShape = False - self._contour.removeSegment(self.getSegmentIndex(), preserveShape) + # Using preserveShape at the edge of an open contour will + # traceback + if ptIndex == len(self._contour): + preserveShape = False + self._contour.removeSegment( + self.getSegmentIndex(), preserveShape) nextOnCurveIndex = findNextOnCurve(self) self._contour.setStartPoint(nextOnCurveIndex) # This object will be removed from scene by notification mechanism @@ -704,25 +749,32 @@ class OnCurvePointItem(QGraphicsPathItem): scale = scene.getViewScale() else: scale = 1 - if scale > 4: scale = 4 - elif scale < .4: scale = .4 + if scale > 4: + scale = 4 + elif scale < .4: + scale = .4 if self._isSmooth: - path.addEllipse(-smoothHalf/scale, -smoothHalf/scale, smoothWidth/scale, smoothHeight/scale) + path.addEllipse(-smoothHalf / scale, -smoothHalf / + scale, smoothWidth / scale, smoothHeight / scale) else: - path.addRect(-onHalf/scale, -onHalf/scale, onWidth/scale, onHeight/scale) + path.addRect(-onHalf / scale, -onHalf / scale, + onWidth / scale, onHeight / scale) self.prepareGeometryChange() self.setPath(path) - self.setPen(QPen(onCurvePointStrokeColor, onCurvePenWidth/scale)) + self.setPen(QPen(onCurvePointStrokeColor, onCurvePenWidth / scale)) def getPointIndex(self): return self._contour.index(self._point) def getSegmentIndex(self): - # closed contour cycles and so the "previous" segment goes to current point + # closed contour cycles and so the "previous" segment goes to current + # point index = 0 if self._contour.open else -1 for pt in self._contour: - if pt == self._point: break - if pt.segmentType is not None: index += 1 + if pt == self._point: + break + if pt.segmentType is not None: + index += 1 return index % len(self._contour.segments) def _CPDeleted(self): @@ -732,9 +784,10 @@ class OnCurvePointItem(QGraphicsPathItem): if not (children[1].isVisible() and children[1].isSelected()): selected = 3 - firstSibling = self._contour[pointIndex+selected-2] - secondSibling = self._contour[pointIndex+(selected-2)*2] - if firstSibling.segmentType is None and secondSibling.segmentType is None: + firstSibling = self._contour[pointIndex + selected - 2] + secondSibling = self._contour[pointIndex + (selected - 2) * 2] + if (firstSibling.segmentType is None and + secondSibling.segmentType is None): # we have two offCurves, wipe them self._contour.removePoint(firstSibling) self._contour.removePoint(secondSibling) @@ -750,34 +803,38 @@ class OnCurvePointItem(QGraphicsPathItem): selected = 3 propagate = 1 curValue = children[selected].pos() - line = children[selected-1].line() - children[selected-1].setLine(line.x1(), line.y1(), newValue.x(), newValue.y()) + line = children[selected - 1].line() + children[selected - 1].setLine(line.x1(), + line.y1(), newValue.x(), newValue.y()) if not len(children) > 4: - elemIndex = pointIndex-2+selected - self._contour[elemIndex].x = self.pos().x()+newValue.x() - self._contour[elemIndex].y = self.pos().y()+newValue.y() + elemIndex = pointIndex - 2 + selected + self._contour[elemIndex].x = self.pos().x() + newValue.x() + self._contour[elemIndex].y = self.pos().y() + newValue.y() if not (self._isSmooth and children[propagate].isVisible()): self.setShallowDirty() return if children[selected]._needsUngrab: - targetLen = children[selected-1].line().length()*2 + targetLen = children[selected - 1].line().length() * 2 else: - targetLen = children[selected-1].line().length()+children[propagate-1].line().length() + targetLen = children[selected - 1].line().length() + \ + children[propagate - 1].line().length() if not newValue.isNull(): tmpLine = QLineF(newValue, QPointF()) tmpLine.setLength(targetLen) else: - # if newValue is null, we’d construct a zero-length line and collapse - # both offCurves + # if newValue is null, we’d construct a zero-length line and + # collapse both offCurves tmpLine = QLineF(QPointF(), children[propagate].pos()) - children[propagate].setFlag(QGraphicsItem.ItemSendsGeometryChanges, False) + children[propagate].setFlag( + QGraphicsItem.ItemSendsGeometryChanges, False) children[propagate].setPos(tmpLine.x2(), tmpLine.y2()) children[propagate].setFlag(QGraphicsItem.ItemSendsGeometryChanges) - children[propagate-1].setLine(line.x1(), line.y1(), tmpLine.x2(), tmpLine.y2()) - propagateInContour = pointIndex-2+propagate - self._contour[propagateInContour].x = self.pos().x()+tmpLine.x2() - self._contour[propagateInContour].y = self.pos().y()+tmpLine.y2() + children[propagate - 1].setLine(line.x1(), + line.y1(), tmpLine.x2(), tmpLine.y2()) + propagateInContour = pointIndex - 2 + propagate + self._contour[propagateInContour].x = self.pos().x() + tmpLine.x2() + self._contour[propagateInContour].y = self.pos().y() + tmpLine.y2() self.setShallowDirty() def itemChange(self, change, value): @@ -794,12 +851,12 @@ class OnCurvePointItem(QGraphicsPathItem): children = self.childItems() if children[1].isVisible(): prevPos = children[1].pos() - self._contour[pointIndex-1].x = self.pos().x()+prevPos.x() - self._contour[pointIndex-1].y = self.pos().y()+prevPos.y() + self._contour[pointIndex - 1].x = self.pos().x() + prevPos.x() + self._contour[pointIndex - 1].y = self.pos().y() + prevPos.y() if children[3].isVisible(): nextPos = children[3].pos() - self._contour[pointIndex+1].x = self.pos().x()+nextPos.x() - self._contour[pointIndex+1].y = self.pos().y()+nextPos.y() + self._contour[pointIndex + 1].x = self.pos().x() + nextPos.x() + self._contour[pointIndex + 1].y = self.pos().y() + nextPos.y() self.setShallowDirty() elif change == QGraphicsItem.ItemSelectedHasChanged: self._point.selected = value @@ -815,31 +872,38 @@ class OnCurvePointItem(QGraphicsPathItem): modifiers = event.modifiers() children = self.childItems() # Ctrl: get and move prevCP, Alt: nextCP - if modifiers & Qt.ControlModifier and children[1].x() == 0 and children[1].y() == 0: + if (modifiers & Qt.ControlModifier and children[1].x() == 0 and + children[1].y() == 0): i, o = 1, 3 - elif modifiers & Qt.AltModifier and children[3].x() == 0 and children[3].y() == 0: + elif (modifiers & Qt.AltModifier and children[3].x() == 0 and + children[3].y() == 0): i, o = 3, 1 - elif not (modifiers & Qt.ControlModifier or modifiers & Qt.AltModifier): + elif not (modifiers & Qt.ControlModifier or + modifiers & Qt.AltModifier): super(OnCurvePointItem, self).mouseMoveEvent(event) return - else: # eat the event if we are not going to yield an offCP + else: # eat the event if we are not going to yield an offCP event.accept() return ptIndex = self.getPointIndex() scene = self.scene() scene._blocked = True # if we have line segment, insert offCurve points - insertIndex = (ptIndex+(i-1)//2) % len(self._contour) + insertIndex = (ptIndex + (i - 1) // 2) % len(self._contour) if self._contour[insertIndex].segmentType == "line": - nextToCP = self._contour[(ptIndex-2+i) % len(self._contour)] + nextToCP = self._contour[(ptIndex - 2 + i) % len(self._contour)] assert(nextToCP.segmentType is not None) self._contour[insertIndex].segmentType = "curve" if i == 1: - first, second = (self._point.x, self._point.y), (nextToCP.x, nextToCP.y) + first, second = ( + self._point.x, self._point.y), (nextToCP.x, nextToCP.y) else: - first, second = (nextToCP.x, nextToCP.y), (self._point.x, self._point.y) - self._contour.insertPoint(insertIndex, self._contour._pointClass(first)) - self._contour.insertPoint(insertIndex, self._contour._pointClass(second)) + first, second = ( + nextToCP.x, nextToCP.y), (self._point.x, self._point.y) + self._contour.insertPoint( + insertIndex, self._contour._pointClass(first)) + self._contour.insertPoint( + insertIndex, self._contour._pointClass(second)) children[i].setVisible(True) # TODO: need a list of items to make this efficient scene.getItemForPoint(nextToCP).childItems()[o].setVisible(True) @@ -856,8 +920,10 @@ class OnCurvePointItem(QGraphicsPathItem): event.accept() def mouseDoubleClickEvent(self, event): - view = self.scene().views()[0] # XXX: meh, maybe refactor doubleClick event into the scene? - if view._currentTool == SceneTools.RulerTool or view._currentTool == SceneTools.KnifeTool: + # XXX: meh, maybe refactor doubleClick event into the scene? + view = self.scene().views()[0] + if (view._currentTool == SceneTools.RulerTool or + view._currentTool == SceneTools.KnifeTool): return self.setIsSmooth(not self._isSmooth) @@ -879,7 +945,9 @@ class OnCurvePointItem(QGraphicsPathItem): self.setPen(pen) super(OnCurvePointItem, self).paint(painter, newOption, widget) + class StartPointItem(QGraphicsPathItem): + def __init__(self, x, y, angle, scale=1, parent=None): super(StartPointItem, self).__init__(parent) self._angle = 360 - angle @@ -895,21 +963,23 @@ class StartPointItem(QGraphicsPathItem): scale = scene.getViewScale() else: scale = 1 - if scale > 1.30: scale = 1.30 - elif scale < .6: scale = .6 + if scale > 1.30: + scale = 1.30 + elif scale < .6: + scale = .6 self.prepareGeometryChange() dist = startItemDist / scale path = QPainterPath() - line = QLineF(0, 0, 0+dist, 0) + line = QLineF(0, 0, 0 + dist, 0) line2 = QLineF(line) - line.setAngle(self._angle-90) + line.setAngle(self._angle - 90) path.lineTo(line.x2(), line.y2()) line2.setAngle(self._angle) - line2.translate(line.p2()-line.p1()) + line2.translate(line.p2() - line.p1()) path.lineTo(line2.x2(), line2.y2()) line.setP1(line2.p2()) line.setAngle(line.angle() - 27.5) - line.setLength(2*dist/5) + line.setLength(2 * dist / 5) line2.setLength(line2.length() + .5) path.moveTo(line.x2(), line.y2()) path.lineTo(line2.x2(), line2.y2()) @@ -917,7 +987,9 @@ class StartPointItem(QGraphicsPathItem): path.lineTo(line.x2(), line.y2()) self.setPath(path) + class AnchorItem(QGraphicsPathItem): + def __init__(self, anchor, scale=1, parent=None): super(AnchorItem, self).__init__(parent) self._anchor = anchor @@ -962,19 +1034,22 @@ class AnchorItem(QGraphicsPathItem): scale = scene.getViewScale() else: scale = 1 - if scale > 4: scale = 4 - elif scale < .4: scale = .4 - - path.moveTo(-anchorHalf/scale, 0) - path.lineTo(0, anchorHalf/scale) - path.lineTo(anchorHalf/scale, 0) - path.lineTo(0, -anchorHalf/scale) + if scale > 4: + scale = 4 + elif scale < .4: + scale = .4 + + path.moveTo(-anchorHalf / scale, 0) + path.lineTo(0, anchorHalf / scale) + path.lineTo(anchorHalf / scale, 0) + path.lineTo(0, -anchorHalf / scale) path.closeSubpath() self.prepareGeometryChange() self.setPath(path) textItem = self.childItems()[0] - textItem.setPos(anchorHalf/scale, textItem.boundingRect().height()/2) + textItem.setPos(anchorHalf / scale, + textItem.boundingRect().height() / 2) # http://www.qtfr.org/viewtopic.php?pid=21045#p21045 def paint(self, painter, option, widget): @@ -987,7 +1062,9 @@ class AnchorItem(QGraphicsPathItem): self.setBrush(anchorColor) super(AnchorItem, self).paint(painter, newOption, widget) + class ComponentItem(QGraphicsPathItem): + def __init__(self, path, component, parent=None): super(ComponentItem, self).__init__(path, parent) self._component = component @@ -1015,14 +1092,18 @@ class ComponentItem(QGraphicsPathItem): scene._blocked = False return value + class VGuidelinesTextItem(QGraphicsSimpleTextItem): + def __init__(self, text, font, parent=None): super(VGuidelinesTextItem, self).__init__(text, parent) self.setBrush(metricsColor) self.setFlag(QGraphicsItem.ItemIgnoresTransformations) self.setFont(font) + class ResizeHandleItem(QGraphicsRectItem): + def __init__(self, parent=None): super(QGraphicsRectItem, self).__init__(parent) self.setPointPath() @@ -1030,7 +1111,7 @@ class ResizeHandleItem(QGraphicsRectItem): self.setPen(QPen(Qt.NoPen)) self.setFlag(QGraphicsItem.ItemIgnoresParentOpacity) self.setFlag(QGraphicsItem.ItemIsMovable) - #self.setFlag(QGraphicsItem.ItemIsSelectable) + # self.setFlag(QGraphicsItem.ItemIsSelectable) self.setCursor(Qt.SizeFDiagCursor) rect = self.parentItem().boundingRect() @@ -1038,7 +1119,8 @@ class ResizeHandleItem(QGraphicsRectItem): def itemChange(self, change, value): if change == QGraphicsItem.ItemSelectedChange: - if not value: self.setVisible(value) + if not value: + self.setVisible(value) return value def mouseMoveEvent(self, event): @@ -1051,11 +1133,15 @@ class ResizeHandleItem(QGraphicsRectItem): scale = scene.getViewScale() else: scale = 1 - if scale > 4: scale = 4 + if scale > 4: + scale = 4 self.prepareGeometryChange() - self.setRect(-onHalf/scale, -onHalf/scale, onWidth/scale, onHeight/scale) + self.setRect(-onHalf / scale, -onHalf / scale, + onWidth / scale, onHeight / scale) + class PixmapItem(QGraphicsPixmapItem): + def __init__(self, x, y, pixmap, parent=None): super(QGraphicsPixmapItem, self).__init__(pixmap, parent) self.setPos(x, y) @@ -1076,7 +1162,8 @@ class PixmapItem(QGraphicsPixmapItem): pos = event.scenePos() if modifiers & Qt.ControlModifier: # rotate - refLine = QLineF(self.x(), self.y(), self.x()+self._rWidth, self.y()-self._rHeight) + refLine = QLineF(self.x(), self.y(), self.x() + + self._rWidth, self.y() - self._rHeight) curLine = QLineF(self.x(), self.y(), pos.x(), pos.y()) self.setRotation(refLine.angleTo(curLine)) else: @@ -1097,7 +1184,9 @@ class PixmapItem(QGraphicsPixmapItem): children[0].setVisible(value) return value + class GlyphScene(QGraphicsScene): + def __init__(self, parent, sceneAddedItems=None): super(GlyphScene, self).__init__(parent) self._editing = False @@ -1125,7 +1214,8 @@ class GlyphScene(QGraphicsScene): view = self.views()[0] return view._glyph - _glyphObject = property(_get_glyphObject, doc="Get the current glyph in the view.") + _glyphObject = property( + _get_glyphObject, doc="Get the current glyph in the view.") def _addRegisterItem(self, item): """The parent object will take care of removing these again""" @@ -1174,26 +1264,28 @@ class GlyphScene(QGraphicsScene): key = event.key() count = event.count() modifiers = event.modifiers() - # XXX: clean this up, prioritize key dispatching before processing things + # XXX: clean this up, prioritize key dispatching before processing + # things # TODO: this is not DRY w space center, put this in a function if modifiers & Qt.ShiftModifier: count *= 10 if modifiers & Qt.ControlModifier: count *= 10 if key == Qt.Key_Left: - x,y = -count,0 + x, y = -count, 0 elif key == Qt.Key_Up: - x,y = 0,count + x, y = 0, count elif key == Qt.Key_Right: - x,y = count,0 + x, y = count, 0 elif key == Qt.Key_Down: - x,y = 0,-count + x, y = 0, -count elif key == platformSpecific.deleteKey: self._blocked = True for item in self.selectedItems(): if isinstance(item, OnCurvePointItem): item.delete(not event.modifiers() & Qt.ShiftModifier) - elif isinstance(item, (AnchorItem, ComponentItem, OffCurvePointItem)): + elif isinstance(item, (AnchorItem, ComponentItem, + OffCurvePointItem)): item.delete() elif isinstance(item, PixmapItem): self.removeItem(item) @@ -1238,7 +1330,8 @@ class GlyphScene(QGraphicsScene): # TODO: somehow try to do this in the pen # pass the glyph to a controller object that holds a self._pen copyGlyph.width = self._glyphObject.width - mimeData.setData("application/x-defconQt-glyph-data", pickle.dumps([copyGlyph.serialize()])) + mimeData.setData("application/x-defconQt-glyph-data", + pickle.dumps([copyGlyph.serialize()])) clipboard.setMimeData(mimeData) event.accept() return @@ -1246,7 +1339,8 @@ class GlyphScene(QGraphicsScene): clipboard = QApplication.clipboard() mimeData = clipboard.mimeData() if mimeData.hasFormat("application/x-defconQt-glyph-data"): - data = pickle.loads(mimeData.data("application/x-defconQt-glyph-data")) + data = pickle.loads(mimeData.data( + "application/x-defconQt-glyph-data")) if len(data) == 1: undo = self._glyphObject.serialize() self._dataForUndo.append(undo) @@ -1258,9 +1352,10 @@ class GlyphScene(QGraphicsScene): return else: sel = self.selectedItems() - if len(sel) == 1 and isinstance(sel[0], OffCurvePointItem) and \ - sel[0].parentItem().getPointIndex() == len(sel[0].parentItem()._contour)-2 and \ - key == Qt.Key_Alt and self._editing is not False: + if (len(sel) == 1 and isinstance(sel[0], OffCurvePointItem) and + (sel[0].parentItem().getPointIndex() == + len(sel[0].parentItem()._contour) - 2) and + key == Qt.Key_Alt and self._editing is not False): sel[0].parentItem().setIsSmooth(False) super(GlyphScene, self).keyPressEvent(event) return @@ -1268,17 +1363,23 @@ class GlyphScene(QGraphicsScene): super(GlyphScene, self).keyPressEvent(event) return for item in self.selectedItems(): - # TODO: if isinstance turns out to be slow, we might want to make a selectedMoveBy - # function in items that calls moveBy for onCurve, noops for offCurve - if isinstance(item, OffCurvePointItem) and item.parentItem().isSelected(): continue - item.moveBy(x,y) + # TODO: if isinstance turns out to be slow, we might want to make + # a selectedMoveBy function in items that calls moveBy for onCurve, + # noops for offCurve + if (isinstance(item, OffCurvePointItem) and + item.parentItem().isSelected()): + continue + item.moveBy(x, y) event.accept() def keyReleaseEvent(self, event): sel = self.selectedItems() - if len(sel) == 1 and isinstance(sel[0], OffCurvePointItem) and \ - sel[0].parentItem().getPointIndex() == len(sel[0].parentItem()._contour)-2 and \ - event.key() == Qt.Key_Alt and self._editing is not False: + if (len(sel) == 1 and + isinstance(sel[0], OffCurvePointItem) and + sel[0].parentItem().getPointIndex() == + len(sel[0].parentItem()._contour) - 2 and + event.key() == Qt.Key_Alt and + self._editing is not False): sel[0].parentItem().setIsSmooth(True) super(GlyphScene, self).keyReleaseEvent(event) @@ -1308,21 +1409,27 @@ class GlyphScene(QGraphicsScene): x, y = round(x), round(y) # XXX: not sure why isinstance does not work here if len(sel) == 1: - isLastOnCurve = type(sel[0]) is OnCurvePointItem and sel[0]._contour.open and \ - sel[0].getPointIndex() == len(sel[0]._contour)-1 + isLastOnCurve = type(sel[0]) is OnCurvePointItem and \ + sel[0]._contour.open and \ + sel[0].getPointIndex() == len(sel[0]._contour) - 1 # TODO: reimplement convenience methods in OffCurvePointItem - isLastOffCurve = type(sel[0]) is OffCurvePointItem and sel[0].parentItem()._contour.open and \ - sel[0].parentItem().getPointIndex()+1 == len(sel[0].parentItem()._contour)-1 + isLastOffCurve = type(sel[0]) is OffCurvePointItem and \ + sel[0].parentItem()._contour.open and \ + sel[0].parentItem().getPointIndex() + 1 == \ + len(sel[0].parentItem()._contour) - 1 if len(sel) == 1 and (isLastOffCurve or isLastOnCurve): if isLastOnCurve: lastContour = sel[0]._contour else: lastContour = sel[0].parentItem()._contour - if (touched and isinstance(touched, OnCurvePointItem)) and touched.getPointIndex() == 0 \ - and lastContour == touched._contour and len(lastContour) > 1: - # Changing the first point from move to line/curve will cycle and so close the contour + if ((touched and isinstance(touched, OnCurvePointItem)) and + touched.getPointIndex() == 0 and + lastContour == touched._contour and + len(lastContour) > 1): + # Changing the first point from move to line/curve will cycle + # and so close the contour if isLastOffCurve: - lastContour.addPoint((x,y)) + lastContour.addPoint((x, y)) lastContour[0].segmentType = "curve" touched.childItems()[1].setVisible(True) else: @@ -1339,14 +1446,18 @@ class GlyphScene(QGraphicsScene): else: refx = sel[0].parentItem().x() refy = sel[0].parentItem().y() - if abs(x-refx) > abs(y-refy): y = copysign(refy, y) - else: x = copysign(refx, x) + if abs(x - refx) > abs(y - refy): + y = copysign(refy, y) + else: + x = copysign(refx, x) if isLastOffCurve: - lastContour.addPoint((x,y)) - lastContour.addPoint((x,y), "curve") + lastContour.addPoint((x, y)) + lastContour.addPoint((x, y), "curve") else: - lastContour.addPoint((x,y), "line") - item = OnCurvePointItem(x, y, False, lastContour, lastContour[-1], self.getViewScale()) + lastContour.addPoint((x, y), "line") + item = OnCurvePointItem( + x, y, False, lastContour, lastContour[-1], + self.getViewScale()) self._addRegisterItem(item) for _ in range(2): lineObj = HandleLineItem(0, 0, 0, 0, item) @@ -1359,9 +1470,12 @@ class GlyphScene(QGraphicsScene): elif not (touched and isinstance(touched, OnCurvePointItem)): nextC = TContour() self._glyphObject.appendContour(nextC) - nextC.addPoint((x,y), "move") + nextC.addPoint((x, y), "move") - item = OnCurvePointItem(x, y, False, self._glyphObject[-1], self._glyphObject[-1][-1], self.getViewScale()) + item = OnCurvePointItem( + x, y, False, + self._glyphObject[-1], self._glyphObject[-1][-1], + self.getViewScale()) self._addRegisterItem(item) for _ in range(2): lineObj = HandleLineItem(0, 0, 0, 0, item) @@ -1371,82 +1485,92 @@ class GlyphScene(QGraphicsScene): self._blocked = False super(GlyphScene, self).mousePressEvent(event) # Since shift clamps, we might be missing the point in mousePressEvent - if forceSelect: item.setSelected(True) + if forceSelect: + item.setSelected(True) def mouseMoveEvent(self, event): if self._editing is True: sel = self.selectedItems() - if len(sel) == 1: - if isinstance(sel[0], OnCurvePointItem) and (event.scenePos() - sel[0].pos()).manhattanLength() >= 2: - mouseGrabberItem = self.mouseGrabberItem() - # If we drawn an onCurve w Shift and we're not touching the item, we wont have - # a mouse grabber (anyways), return early here. - if mouseGrabberItem is None: - event.accept() - return - self._blocked = True - if len(sel[0]._contour) < 2: - # release current onCurve - self.sendEvent(sel[0], QEvent(QEvent.MouseButtonRelease)) - mouseGrabberItem.ungrabMouse() - sel[0].setSelected(False) - # append an offCurve point and start moving it - sel[0]._contour.addPoint((event.scenePos().x(), event.scenePos().y())) - nextCP = sel[0].childItems()[3] - nextCP.setVisible(True) - nextCP._needsUngrab = True - #nextCP.setSelected(True) - self.sendEvent(nextCP, QEvent(QEvent.MouseButtonPress)) - nextCP.grabMouse() - else: - # release current onCurve, delete from contour - self.sendEvent(sel[0], QEvent(QEvent.MouseButtonRelease)) - mouseGrabberItem.ungrabMouse() - sel[0].setSelected(False) - - # construct a curve segment to the current point if there is not one - onCurve = sel[0]._point - if not onCurve.segmentType == "curve": - # remove the last onCurve - sel[0]._contour.removePoint(onCurve) - prev = sel[0]._contour[-1] - self.getItemForPoint(prev).childItems()[3].setVisible(True) - # add a zero-length offCurve to the previous point - sel[0]._contour.addPoint((prev.x, prev.y)) - # add prevOffCurve and activate - sel[0]._contour.addPoint((sel[0].x(), sel[0].y())) - sel[0].childItems()[1].setVisible(True) - # add back current onCurve as a curve point - sel[0]._contour.addPoint((onCurve.x, onCurve.y), "curve") - sel[0]._point = sel[0]._contour[-1] - if not QApplication.keyboardModifiers() & Qt.AltModifier: - sel[0]._point.smooth = True - sel[0]._isSmooth = True - sel[0].setPointPath() - if sel[0].getPointIndex() == 0: - # we're probably dealing with the first point that we looped. - # preserve nextCP whatsoever. - lineObj = HandleLineItem(0, 0, 0, 0, sel[0]) - nextCP = OffCurvePointItem(0, 0, sel[0]) - # now we have l1, p1, l2, p2, l3, p3 - l2 = sel[0].childItems()[2] - lineObj.stackBefore(l2) - nextCP.stackBefore(l2) - else: - # add last offCurve - sel[0]._contour.addPoint((sel[0].x(), sel[0].y())) - nextCP = sel[0].childItems()[3] - nextCP._needsUngrab = True - nextCP.setVisible(True) - #nextCP.setSelected(True) - self.sendEvent(nextCP, QEvent(QEvent.MouseButtonPress)) - nextCP.grabMouse() - self._blocked = False - self._editing = None - super(GlyphScene, self).mouseMoveEvent(event) - else: - # eat the event + if (len(sel) == 1 and isinstance(sel[0], OnCurvePointItem) and + (event.scenePos() - sel[0].pos()).manhattanLength() >= 2): + mouseGrabberItem = self.mouseGrabberItem() + # If we drawn an onCurve w Shift and we're not touching + # the item, we wont have a mouse grabber (anyways), return + # early here. + if mouseGrabberItem is None: event.accept() + return + self._blocked = True + if len(sel[0]._contour) < 2: + # release current onCurve + self.sendEvent(sel[0], QEvent( + QEvent.MouseButtonRelease)) + mouseGrabberItem.ungrabMouse() + sel[0].setSelected(False) + # append an offCurve point and start moving it + sel[0]._contour.addPoint( + (event.scenePos().x(), event.scenePos().y())) + nextCP = sel[0].childItems()[3] + nextCP.setVisible(True) + nextCP._needsUngrab = True + # nextCP.setSelected(True) + self.sendEvent(nextCP, QEvent(QEvent.MouseButtonPress)) + nextCP.grabMouse() + else: + # release current onCurve, delete from contour + self.sendEvent(sel[0], QEvent( + QEvent.MouseButtonRelease)) + mouseGrabberItem.ungrabMouse() + sel[0].setSelected(False) + + # construct a curve segment to the current point if + # there is not one + onCurve = sel[0]._point + if not onCurve.segmentType == "curve": + # remove the last onCurve + sel[0]._contour.removePoint(onCurve) + prev = sel[0]._contour[-1] + self.getItemForPoint(prev).childItems()[ + 3].setVisible(True) + # add a zero-length offCurve to the previous point + sel[0]._contour.addPoint((prev.x, prev.y)) + # add prevOffCurve and activate + sel[0]._contour.addPoint((sel[0].x(), sel[0].y())) + sel[0].childItems()[1].setVisible(True) + # add back current onCurve as a curve point + sel[0]._contour.addPoint( + (onCurve.x, onCurve.y), "curve") + sel[0]._point = sel[0]._contour[-1] + if (not QApplication.keyboardModifiers() & + Qt.AltModifier): + sel[0]._point.smooth = True + sel[0]._isSmooth = True + sel[0].setPointPath() + if sel[0].getPointIndex() == 0: + # we're probably dealing with the first point that + # we looped. + # preserve nextCP whatsoever. + lineObj = HandleLineItem(0, 0, 0, 0, sel[0]) + nextCP = OffCurvePointItem(0, 0, sel[0]) + # now we have l1, p1, l2, p2, l3, p3 + l2 = sel[0].childItems()[2] + lineObj.stackBefore(l2) + nextCP.stackBefore(l2) + else: + # add last offCurve + sel[0]._contour.addPoint((sel[0].x(), sel[0].y())) + nextCP = sel[0].childItems()[3] + nextCP._needsUngrab = True + nextCP.setVisible(True) + # nextCP.setSelected(True) + self.sendEvent(nextCP, QEvent(QEvent.MouseButtonPress)) + nextCP.grabMouse() + self._blocked = False + self._editing = None + super(GlyphScene, self).mouseMoveEvent(event) + elif len(sel) == 1: + # eat the event + event.accept() else: currentTool = self.views()[0]._currentTool if currentTool == SceneTools.RulerTool: @@ -1458,8 +1582,9 @@ class GlyphScene(QGraphicsScene): items = self.items(event.scenePos()) # XXX: we must cater w mouse tracking # we dont need isSelected() once its rid - if len(items) > 1 and isinstance(items[0], OnCurvePointItem) and \ - isinstance(items[1], OffCurvePointItem) and items[1].isSelected(): + if (len(items) > 1 and isinstance(items[0], OnCurvePointItem) and + isinstance(items[1], OffCurvePointItem) and + items[1].isSelected()): items[1].setPos(0, 0) else: super(GlyphScene, self).mouseMoveEvent(event) @@ -1469,7 +1594,8 @@ class GlyphScene(QGraphicsScene): currentTool = self.views()[0]._currentTool if currentTool == SceneTools.DrawingTool: # cleanup extra point elements if we dealt w curved first point - touched = self.itemAt(event.scenePos(), self.views()[0].transform()) + touched = self.itemAt(event.scenePos(), + self.views()[0].transform()) if touched and isinstance(touched, OffCurvePointItem): onCurve = touched.parentItem() children = onCurve.childItems() @@ -1492,7 +1618,7 @@ class GlyphScene(QGraphicsScene): def rulerMousePress(self, event): touched = self.itemAt(event.scenePos(), self.views()[0].transform()) if touched is not None and isinstance(touched, OnCurvePointItem) or \ - isinstance(touched, OffCurvePointItem): + isinstance(touched, OffCurvePointItem): x, y = touched.scenePos().x(), touched.scenePos().y() else: x, y = event.scenePos().x(), event.scenePos().y() @@ -1503,8 +1629,8 @@ class GlyphScene(QGraphicsScene): self._cachedRuler = None path = QPainterPath() path.moveTo(x, y) - path.lineTo(x+1, y) - path.lineTo(x+1, y+1) + path.lineTo(x + 1, y) + path.lineTo(x + 1, y + 1) path.closeSubpath() self._rulerObject = self.addPath(path) textItem = QGraphicsSimpleTextItem("0", self._rulerObject) @@ -1516,11 +1642,13 @@ class GlyphScene(QGraphicsScene): event.accept() def rulerMouseMove(self, event): - # XXX: shouldnt have to do this, it seems mouseTracking is wrongly activated - if self._rulerObject is None: return + # XXX: shouldnt have to do this, it seems mouseTracking is wrongly + # activated + if self._rulerObject is None: + return touched = self.itemAt(event.scenePos(), self.views()[0].transform()) if touched is not None and isinstance(touched, OnCurvePointItem) or \ - isinstance(touched, OffCurvePointItem): + isinstance(touched, OffCurvePointItem): x, y = touched.scenePos().x(), touched.scenePos().y() else: # TODO: 45deg clamp w ShiftModifier @@ -1547,11 +1675,15 @@ class GlyphScene(QGraphicsScene): text = "%d\n↔ %d\n↕ %d\nα %dº" % (l, h, v, a) textItem.setText(text) dx = x - baseElem.x - if dx >= 0: px = x - else: px = x - textItem.boundingRect().width() + if dx >= 0: + px = x + else: + px = x - textItem.boundingRect().width() dy = y - baseElem.y - if dy > 0: py = baseElem.y - else: py = baseElem.y + textItem.boundingRect().height() + if dy > 0: + py = baseElem.y + else: + py = baseElem.y + textItem.boundingRect().height() textItem.setPos(px, py) event.accept() @@ -1579,26 +1711,27 @@ class GlyphScene(QGraphicsScene): Takes four defcon points describing curve and four scalars describing line parameters. """ + def computeIntersections(self, p1, p2, p3, p4, x1, y1, x2, y2): bx, by = x1 - x2, y2 - y1 - m = x1*(y1-y2) + y1*(x2-x1) - a, b, c, d = bezierTools.calcCubicParameters((p1.x, p1.y), (p2.x, p2.y), - (p3.x, p3.y), (p4.x, p4.y)) - - pc0 = by*a[0] + bx*a[1] - pc1 = by*b[0] + bx*b[1] - pc2 = by*c[0] + bx*c[1] - pc3 = by*d[0] + bx*d[1] + m + m = x1 * (y1 - y2) + y1 * (x2 - x1) + a, b, c, d = bezierTools.calcCubicParameters( + (p1.x, p1.y), (p2.x, p2.y), (p3.x, p3.y), (p4.x, p4.y)) + + pc0 = by * a[0] + bx * a[1] + pc1 = by * b[0] + bx * b[1] + pc2 = by * c[0] + bx * c[1] + pc3 = by * d[0] + bx * d[1] + m r = bezierTools.solveCubic(pc0, pc1, pc2, pc3) sol = [] for t in r: - s0 = a[0]*t**3 + b[0]*t**2 + c[0]*t + d[0] - s1 = a[1]*t**3 + b[1]*t**2 + c[1]*t + d[1] - if (x2-x1) != 0: - s = (s0-x1) / (x2-x1) + s0 = a[0] * t ** 3 + b[0] * t ** 2 + c[0] * t + d[0] + s1 = a[1] * t ** 3 + b[1] * t ** 2 + c[1] * t + d[1] + if (x2 - x1) != 0: + s = (s0 - x1) / (x2 - x1) else: - s = (s1-y1) / (y2-y1) + s = (s1 - y1) / (y2 - y1) if not (t < 0 or t > 1 or s < 0 or s > 1): sol.append((s0, s1, t)) return sol @@ -1606,22 +1739,26 @@ class GlyphScene(QGraphicsScene): """ G. Bach, http://stackoverflow.com/a/1968345 """ + def lineIntersection(self, x1, y1, x2, y2, x3, y3, x4, y4): Bx_Ax = x2 - x1 By_Ay = y2 - y1 Dx_Cx = x4 - x3 Dy_Cy = y4 - y3 determinant = (-Dx_Cx * By_Ay + Bx_Ax * Dy_Cy) - if abs(determinant) < 1e-20: return [] + if abs(determinant) < 1e-20: + return [] s = (-By_Ay * (x1 - x3) + Bx_Ax * (y1 - y3)) / determinant - t = ( Dx_Cx * (y1 - y3) - Dy_Cy * (x1 - x3)) / determinant + t = (Dx_Cx * (y1 - y3) - Dy_Cy * (x1 - x3)) / determinant if s >= 0 and s <= 1 and t >= 0 and t <= 1: return [(x1 + (t * Bx_Ax), y1 + (t * By_Ay), t)] return [] def knifeMouseMove(self, event): - # XXX: shouldnt have to do this, it seems mouseTracking is wrongly activated - if self._knifeLine is None: return + # XXX: shouldnt have to do this, it seems mouseTracking is wrongly + # activated + if self._knifeLine is None: + return for dot in self._knifeDots: self.removeItem(dot) self._knifeDots = [] @@ -1635,14 +1772,19 @@ class GlyphScene(QGraphicsScene): for contour in glyph: segments = contour.segments for index, seg in enumerate(segments): - prev = segments[index-1][-1] + prev = segments[index - 1][-1] if len(seg) == 3: - i = self.computeIntersections(prev, seg[0], seg[1], seg[2], line.x1(), line.y1(), x, y) + i = self.computeIntersections( + prev, seg[0], seg[1], seg[2], + line.x1(), line.y1(), x, y) else: - i = self.lineIntersection(prev.x, prev.y, seg[0].x, seg[0].y, line.x1(), line.y1(), x, y) + i = self.lineIntersection( + prev.x, prev.y, seg[0].x, seg[0].y, + line.x1(), line.y1(), x, y) for pt in i: scale = self.getViewScale() - item = self.addEllipse(-offHalf/scale, -offHalf/scale, offWidth/scale, offHeight/scale) + item = self.addEllipse(-offHalf / scale, -offHalf / scale, + offWidth / scale, offHeight / scale) item.setPos(pt[0], pt[1]) self._cachedIntersections.append((contour, index, pt[2])) self._knifeDots.append(item) @@ -1667,6 +1809,7 @@ class GlyphScene(QGraphicsScene): class GlyphView(QGraphicsView): + def __init__(self, glyph, settings, parent=None): super(GlyphView, self).__init__(parent) @@ -1688,7 +1831,8 @@ class GlyphView(QGraphicsView): self._showMetricsTitles = True self.setBackgroundBrush(QBrush(Qt.lightGray)) - self.setScene(GlyphScene(self, self._getSceneItems('scene-added-items'))) + self.setScene(GlyphScene( + self, self._getSceneItems('scene-added-items'))) font = self.font() font.setFamily("Roboto Mono") font.setFixedPitch(True) @@ -1696,7 +1840,7 @@ class GlyphView(QGraphicsView): self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) - #self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate) + # self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate) self.horizontalScrollBar().valueChanged.connect(self.scaleElements) self.setSceneSelection() @@ -1716,7 +1860,6 @@ class GlyphView(QGraphicsView): self.changeCurrentLayer(self._layer) - @property def _glyph(self): # instead of a getter we could change the glyph each time @@ -1736,11 +1879,13 @@ class GlyphView(QGraphicsView): def defaultWidth(self): defaultLayer = self._layerSet[None] return defaultLayer[self._name].width \ - if self._name in defaultLayer else 0 + if self._name in defaultLayer else 0 def _listenToLayerSet(self): - self._layerSet.addObserver(self, '_layerDeleted', 'LayerSet.LayerWillBeDeleted') - self._layerSet.addObserver(self, '_layerGenericVisualChange', 'LayerSet.LayerOrderChanged') + self._layerSet.addObserver( + self, '_layerDeleted', 'LayerSet.LayerWillBeDeleted') + self._layerSet.addObserver( + self, '_layerGenericVisualChange', 'LayerSet.LayerOrderChanged') def _listenToLayer(self, layer, remove=False): if remove: @@ -1753,7 +1898,8 @@ class GlyphView(QGraphicsView): def _listenToGlyph(self, layer): layer[self._name].addObserver(self, "_glyphChanged", "Glyph.Changed") - layer.addObserver(self, '_layerGenericVisualChange', 'Layer.ColorChanged') + layer.addObserver(self, '_layerGenericVisualChange', + 'Layer.ColorChanged') def layerAdded(self, layer): self._listenToLayer(layer) @@ -1822,16 +1968,21 @@ class GlyphView(QGraphicsView): scene = self.scene() font = self._glyph.getParent() width = self._glyph.width - if width is None: width = 0 - item = scene.addRect(-1000, -1000, 3000, 3000, QPen(Qt.black), QBrush(Qt.gray)) + if width is None: + width = 0 + item = scene.addRect(-1000, -1000, 3000, 3000, + QPen(Qt.black), QBrush(Qt.gray)) item.setZValue(-1000) - scene._widthItem = scene.addRect(0, -1000, width, 3000, QPen(Qt.NoPen), QBrush(backgroundColor)) + scene._widthItem = scene.addRect( + 0, -1000, width, 3000, QPen(Qt.NoPen), QBrush(backgroundColor)) scene._widthItem.setZValue(-999) descender = font.info.descender - if descender is None: descender = -250 + if descender is None: + descender = -250 unitsPerEm = font.info.unitsPerEm - if unitsPerEm is None: unitsPerEm = 1000 - self.centerOn(width/2, descender+unitsPerEm/2) + if unitsPerEm is None: + unitsPerEm = 1000 + self.centerOn(width / 2, descender + unitsPerEm / 2) def addBlues(self): scene = self.scene() @@ -1847,16 +1998,18 @@ class GlyphView(QGraphicsView): yMaxs = [i for index, i in enumerate(values) if index % 2] for yMin, yMax in zip(yMins, yMaxs): if yMin == yMax: - item = scene.addLine(-1000, yMin, 3000, yMax, QPen(bluesColor)) + item = scene.addLine(-1000, yMin, 3000, + yMax, QPen(bluesColor)) item.setZValue(-998) else: - item = scene.addRect(-1000, yMin, 3000, yMax - yMin, QPen(Qt.NoPen), QBrush(bluesColor)) + item = scene.addRect(-1000, yMin, 3000, yMax - yMin, + QPen(Qt.NoPen), QBrush(bluesColor)) item.setZValue(-998) def addHorizontalMetrics(self): scene = self.scene() font = self._glyph.getParent() - width = self._glyph.width# * self._inverseScale + width = self._glyph.width # * self._inverseScale toDraw = [ ("Descender", font.info.descender), ("Baseline", 0), @@ -1877,11 +2030,10 @@ class GlyphView(QGraphicsView): item = scene.addLine(-1000, y, 2000, y, QPen(metricsColor)) item.setZValue(-997) - labels = self._getSceneItems('hMetricLabels', clear=True) # text - if self._showMetricsTitles:# and self._impliedPointSize > 150: - fontSize = 9# * self._inverseScale + if self._showMetricsTitles: # and self._impliedPointSize > 150: + fontSize = 9 # * self._inverseScale font = self.font() font.setPointSize(fontSize) for position, names in sorted(positions.items()): @@ -1903,21 +2055,23 @@ class GlyphView(QGraphicsView): return QColor.fromRgbF(*layer.color) return None - def _getDrawingStyleForLayer(self, layer, kind=None): isActive = layer is self._layer isFilled = self._settings.activeLayerFilled \ - if isActive else self._settings.otherLayersFilled + if isActive else self._settings.otherLayersFilled isOutlined = not isFilled useLayerColor = self._settings.activeLayerUseLayerColor \ - if isActive else self._settings.otherLayerUseLayerColor + if isActive else self._settings.otherLayerUseLayerColor if useLayerColor: brushcolor = self.getLayerColor(layer) or Qt.black pencolor = brushcolor else: # default app colors - brushcolor = fillColor if kind != 'component' else componentFillColor + if kind != 'component': + brushcolor = fillColor + else: + brushcolor = componentFillColor pencolor = Qt.black if isOutlined: @@ -1930,12 +2084,12 @@ class GlyphView(QGraphicsView): if isActive and not useLayerColor: # The originally released app did fall back to QT's default # behavior i.e. no pen defined, so I preserve this here - if isOutlined: brush = None # like Qt.NoBrush - else: pen = None # like Qt.black + if isOutlined: + brush = None # like Qt.NoBrush + else: + pen = None # like Qt.black return (pen, brush) - - @property def _activeLayerZValue(self): return -995 if not self._settings.activeLayerOnTop else -993 @@ -1943,7 +2097,8 @@ class GlyphView(QGraphicsView): def drawAllLayers(self): activeLayer = self._layer # all layers before the active layer are -996 - # the active layer is -995 or -993 if self._settings.activeLayerOnTop == True + # the active layer is -995 or -993 if + # self._settings.activeLayerOnTop == True # all layers after the active layer are -996 zValue = -996 for layer in reversed(list(self._layerSet)): @@ -1983,8 +2138,10 @@ class GlyphView(QGraphicsView): item.setPath(path) pen, brush = self._getDrawingStyleForLayer(layer) - if pen: item.setPen(pen) - if brush: item.setBrush(brush) + if pen: + item.setPen(pen) + if brush: + item.setBrush(brush) item.setZValue(zValue) @@ -1998,9 +2155,11 @@ class GlyphView(QGraphicsView): return item def updateActiveLayerPath(self): - self.updateLayerPath(self._layer, representationKey="defconQt.NoComponentsQPainterPath") + self.updateLayerPath( + self._layer, representationKey="defconQt.NoComponentsQPainterPath") - def updateLayerPath(self, layer, representationKey="defconQt.QPainterPath"): + def updateLayerPath(self, layer, + representationKey="defconQt.QPainterPath"): glyph = layer[self._name] scene = self.scene() path = glyph.getRepresentation(representationKey) @@ -2032,8 +2191,10 @@ class GlyphView(QGraphicsView): componentGlyph = layer[component.baseGlyph] path = componentGlyph.getRepresentation("defconQt.QPainterPath") item = ComponentItem(path, component) - if pen: item.setPen(pen) - if brush: item.setBrush(brush) + if pen: + item.setPen(pen) + if brush: + item.setBrush(brush) item.setZValue(self._activeLayerZValue) components.append(item) scene.addItem(item) @@ -2051,7 +2212,8 @@ class GlyphView(QGraphicsView): def addStartPoints(self): scene = self.scene() startPointItems = self._getSceneItems('startPoints', clear=True) - startPointsData = self._glyph.getRepresentation("defconQt.StartPointsInformation") + startPointsData = self._glyph.getRepresentation( + "defconQt.StartPointsInformation") path = QPainterPath() for point, angle in startPointsData: x, y = point @@ -2064,13 +2226,17 @@ class GlyphView(QGraphicsView): scene = self.scene() pointItems = self._getSceneItems('points', clear=True) # use the data from the outline representation - outlineData = self._glyph.getRepresentation("defconQt.OutlineInformation") + outlineData = self._glyph.getRepresentation( + "defconQt.OutlineInformation") scale = self.transform().m11() for onCurve in outlineData: # on curve x, y = onCurve.x, onCurve.y - item = OnCurvePointItem(x, y, onCurve.isSmooth, self._glyph[onCurve.contourIndex], - self._glyph[onCurve.contourIndex][onCurve.pointIndex], scale) + item = OnCurvePointItem( + x, y, onCurve.isSmooth, + self._glyph[onCurve.contourIndex], + self._glyph[onCurve.contourIndex][onCurve.pointIndex], + scale) pointItems.append(item) scene.addItem(item) # off curve @@ -2078,12 +2244,12 @@ class GlyphView(QGraphicsView): if CP: cx, cy = CP # line - lineObj = HandleLineItem(0, 0, cx-x, cy-y, item) + lineObj = HandleLineItem(0, 0, cx - x, cy - y, item) # point - CPObject = OffCurvePointItem(cx-x, cy-y, item) + CPObject = OffCurvePointItem(cx - x, cy - y, item) else: lineObj = HandleLineItem(0, 0, 0, 0, item) - #lineObj.setVisible(False) + # lineObj.setVisible(False) CPObject = OffCurvePointItem(0, 0, item) CPObject.setVisible(False) ''' @@ -2164,10 +2330,13 @@ class GlyphView(QGraphicsView): # TODO: we should have an app-wide mechanism to handle default metrics # values (that are applied to new fonts as well) descender = font.info.descender - if descender is None: descender = -250 + if descender is None: + descender = -250 unitsPerEm = font.info.unitsPerEm - if unitsPerEm is None: unitsPerEm = 1000 - self.fitInView(0, descender, self._glyph.width, unitsPerEm, Qt.KeepAspectRatio) + if unitsPerEm is None: + unitsPerEm = 1000 + self.fitInView(0, descender, self._glyph.width, + unitsPerEm, Qt.KeepAspectRatio) def mousePressEvent(self, event): if (event.button() == Qt.MidButton): @@ -2209,10 +2378,12 @@ class GlyphView(QGraphicsView): self.scale(factor, factor) def scaleElements(self): - # TODO: stop displaying SimpleTextItems at certains sizes, maybe anchor them differently as well + # TODO: stop displaying SimpleTextItems at certains sizes, maybe anchor + # them differently as well scale = self.transform().m11() if scale < 4: for item in self.scene().items(): - if isinstance(item, (OnCurvePointItem, OffCurvePointItem, \ - ResizeHandleItem, AnchorItem, StartPointItem)): + if isinstance(item, (OnCurvePointItem, OffCurvePointItem, + ResizeHandleItem, AnchorItem, + StartPointItem)): item.setPointPath(scale) diff --git a/Lib/defconQt/groupsView.py b/Lib/defconQt/groupsView.py index 9772528..d52a0c5 100644 --- a/Lib/defconQt/groupsView.py +++ b/Lib/defconQt/groupsView.py @@ -1,13 +1,17 @@ from defconQt.glyphCollectionView import GlyphCollectionWidget from defconQt.util import platformSpecific -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * +from PyQt5.QtCore import QSize, Qt +from PyQt5.QtGui import QColor, QPainter +from PyQt5.QtWidgets import ( + QAbstractItemView, QGridLayout, QListWidget, QListWidgetItem, QPushButton, + QRadioButton, QWidget) + class GroupListWidget(QListWidget): + def __init__(self, groupNames, parent=None): super(GroupListWidget, self).__init__(parent) - #self.setAlternatingRowColors(True) + # self.setAlternatingRowColors(True) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSortingEnabled(True) @@ -17,7 +21,7 @@ class GroupListWidget(QListWidget): for groupName in groupNames: item = QListWidgetItem(groupName, self) item.setFlags(item.flags() | Qt.ItemIsEditable) - #if len(groupNames): self.setCurrentRow(0) + # if len(groupNames): self.setCurrentRow(0) def keyPressEvent(self, event): key = event.key() @@ -31,15 +35,20 @@ class GroupListWidget(QListWidget): else: super(GroupListWidget, self).keyPressEvent(event) + class GroupStackWidget(QWidget): + def __init__(self, font, glyphs=[], parent=None): super(GroupStackWidget, self).__init__(parent) self.ascender = font.info.ascender - if self.ascender is None: self.ascender = 750 + if self.ascender is None: + self.ascender = 750 self.glyphs = glyphs - self.maxWidth = max(glyph.width for glyph in self.glyphs) if len(self.glyphs) else 300 + self.maxWidth = max(glyph.width for glyph in self.glyphs) if len( + self.glyphs) else 300 self.upm = font.info.unitsPerEm - if self.upm is None: self.upm = 1000 + if self.upm is None: + self.upm = 1000 self.padding = 10 self.alignRight = False @@ -49,36 +58,44 @@ class GroupStackWidget(QWidget): def setGlyphs(self, glyphs): self.glyphs = glyphs - self.maxWidth = max(glyph.width for glyph in self.glyphs) if len(self.glyphs) else 300 + self.maxWidth = max(glyph.width for glyph in self.glyphs) if len( + self.glyphs) else 300 self.update() def sizeHint(self): - return QSize(self.maxWidth+2*self.padding, 400) + return QSize(self.maxWidth + 2 * self.padding, 400) def paintEvent(self, event): - # TODO: maybe use self.upm*(1+2*BufferHeight) for the denominator as in fontView - scale = self.height() / (self.upm*1.2) - x_offset = (self.width()-self.maxWidth*scale-self.padding*2)/2 + # TODO: maybe use self.upm*(1+2*BufferHeight) for the denominator as in + # fontView + scale = self.height() / (self.upm * 1.2) + x_offset = \ + (self.width() - self.maxWidth * scale - self.padding * 2) / 2 if x_offset < 0: - scale *= 1+2*x_offset/(self.maxWidth*scale) + scale *= 1 + 2 * x_offset / (self.maxWidth * scale) x_offset = 0 painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) - painter.translate(self.padding, self.padding+(self.ascender*1.2)*scale) + painter.translate(self.padding, self.padding + + (self.ascender * 1.2) * scale) painter.scale(scale, -scale) col = QColor(Qt.black) col.setAlphaF(.2) for glyph in self.glyphs: - if self.alignRight: dist = self.maxWidth - glyph.width - else: dist = 0 + if self.alignRight: + dist = self.maxWidth - glyph.width + else: + dist = 0 glyphPath = glyph.getRepresentation("defconQt.QPainterPath") painter.save() - painter.translate(x_offset+dist, 0) + painter.translate(x_offset + dist, 0) painter.fillPath(glyphPath, col) painter.restore() + class GroupCollectionWidget(GlyphCollectionWidget): + def __init__(self, parent=None): super(GroupCollectionWidget, self).__init__(parent) self._columns = 9 @@ -88,8 +105,9 @@ class GroupCollectionWidget(GlyphCollectionWidget): self.characterDropCallback = None self.resize(self.width(), 200) - # TODO: The standard QListWidget has scrollbar and does not need three times parent call. - # Find out how to handle that properly. + # TODO: The standard QListWidget has scrollbar and does not need three + # times parent call. + # Find out how to handle that properly. def keyPressEvent(self, event): if event.key() == platformSpecific.deleteKey: if self.characterDeletionCallback is not None: @@ -99,8 +117,9 @@ class GroupCollectionWidget(GlyphCollectionWidget): super(GroupCollectionWidget, self).keyPressEvent(event) def pipeDragEnterEvent(self, event): - # TODO: the problem with text/plain is that any sort of text can get here. - # (It allows direct compatibility with featureTextEditor though.) + # TODO: the problem with text/plain is that any sort of text can get + # here. + # (It allows direct compatibility with featureTextEditor though.) if (event.mimeData().hasText()): event.acceptProposedAction() else: @@ -113,6 +132,7 @@ class GroupCollectionWidget(GlyphCollectionWidget): elif self.characterDropCallback is not None: self.characterDropCallback(event) + class GroupsWindow(QWidget): leftGroups = ["@MMK_L", "public.kern1"] rightGroups = ["@MMK_R", "public.kern2"] @@ -134,7 +154,8 @@ class GroupsWindow(QWidget): self.addGroupButton.clicked.connect(self._groupAdd) self.removeGroupButton = QPushButton("−", self) self.removeGroupButton.clicked.connect(self._groupDelete) - if not groups: self.removeGroupButton.setEnabled(False) + if not groups: + self.removeGroupButton.setEnabled(False) self.alignLeftBox = QRadioButton("Align left", self) self.alignRightBox = QRadioButton("Align right", self) @@ -143,7 +164,8 @@ class GroupsWindow(QWidget): self._autoDirection = True self.collectionWidget = GroupCollectionWidget(parent=self) - self.collectionWidget.characterDeletionCallback = self.characterDeleteEvent + self.collectionWidget.characterDeletionCallback = \ + self.characterDeleteEvent self.collectionWidget.characterDropCallback = self.characterDropEvent self._cachedName = None @@ -159,7 +181,8 @@ class GroupsWindow(QWidget): layout.setColumnStretch(4, 1) self.setLayout(layout) - self.setWindowTitle("Groups window – %s %s" % (self.font.info.familyName, self.font.info.styleName)) + self.setWindowTitle("Groups window – %s %s" % ( + self.font.info.familyName, self.font.info.styleName)) def _alignmentChanged(self): alignRight = self.alignRightBox.isChecked() @@ -181,7 +204,8 @@ class GroupsWindow(QWidget): def _groupChanged(self): currentItem = self.groupsList.currentItem() - if currentItem is None: return + if currentItem is None: + return self._cachedName = currentItem.text() if self._autoDirection: for name in self.leftGroups: @@ -201,9 +225,11 @@ class GroupsWindow(QWidget): def _groupRenamed(self): currentItem = self.groupsList.currentItem() - if currentItem is None: return + if currentItem is None: + return newKey = currentItem.text() - if newKey == self._cachedName: return + if newKey == self._cachedName: + return self.font.groups[newKey] = self.font.groups[self._cachedName] del self.font.groups[self._cachedName] self._cachedName = newKey @@ -212,7 +238,8 @@ class GroupsWindow(QWidget): newKey = self.groupsList.currentItem().text() del self.font.groups[newKey] self.groupsList.takeItem(self.groupsList.currentRow()) - if not self.font.groups.keys(): self.removeGroupButton.setEnabled(False) + if not self.font.groups.keys(): + self.removeGroupButton.setEnabled(False) self._groupChanged() # XXX: it seems the notification doesn't trigger... @@ -223,7 +250,7 @@ class GroupsWindow(QWidget): self.groupsList.fillGroupNames(self) # TODO: consider transferring currentGroup as well self.groupsList.blockSignals(False) - #self.groupsList.setCurrentRow(0) + # self.groupsList.setCurrentRow(0) def characterDeleteEvent(self, selection): currentGroup = self.groupsList.currentItem().text() @@ -237,7 +264,8 @@ class GroupsWindow(QWidget): def characterDropEvent(self, event): currentGroup = self.groupsList.currentItem() - if currentGroup is None: return + if currentGroup is None: + return currentGroup = currentGroup.text() glyphNames = event.mimeData().text().split(" ") for gName in glyphNames: diff --git a/Lib/defconQt/layerSetList.py b/Lib/defconQt/layerSetList.py index 485477b..e5617b9 100644 --- a/Lib/defconQt/layerSetList.py +++ b/Lib/defconQt/layerSetList.py @@ -1,11 +1,14 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QKeySequence, QColor, QPixmap, QIcon -from PyQt5.QtWidgets import (QApplication, QWidget, QMenu, QListWidget, - QListWidgetItem, QAbstractItemView, QVBoxLayout, QAction, QColorDialog) -from defconQt import icons_db +from PyQt5.QtWidgets import ( + QApplication, QListWidget, QListWidgetItem, QAbstractItemView, QAction, + QColorDialog) +# from defconQt import icons_db from defconQt.glyphView import AddLayerDialog + class LayerSetList(QListWidget): + def __init__(self, parent=None, *args, **kwargs): super().__init__(parent, *args, **kwargs) @@ -27,7 +30,7 @@ class LayerSetList(QListWidget): action = QAction("Change &Name", self) action.setShortcuts(QKeySequence('n')) - action.triggered.connect(lambda : self.editItem(self.currentItem())) + action.triggered.connect(lambda: self.editItem(self.currentItem())) self.addAction(action) action = QAction("Change &Color", self) @@ -81,7 +84,7 @@ class LayerSetList(QListWidget): item.setFlags(item.flags() | Qt.ItemIsEditable) - return item; + return item def _getCurrentLayer(self): item = self.currentItem() @@ -99,7 +102,7 @@ class LayerSetList(QListWidget): # because I think we can't handle a font without a default layer # TODO: try this return - del self._layerSet[layer.name]; + del self._layerSet[layer.name] def _reordered(self, *args): # get a new layer order @@ -122,8 +125,10 @@ class LayerSetList(QListWidget): if not layer: return - startColor = layer.color and QColor.fromRgbF(*layer.color) or QColor('limegreen') - qcolor = QColorDialog.getColor(startColor, self, options=QColorDialog.ShowAlphaChannel) + startColor = layer.color and QColor.fromRgbF(*layer.color) or \ + QColor('limegreen') + qcolor = QColorDialog.getColor( + startColor, self, options=QColorDialog.ShowAlphaChannel) if not qcolor.isValid(): # cancelled return diff --git a/Lib/defconQt/objects/defcon.py b/Lib/defconQt/objects/defcon.py index 75d14c6..24f585f 100644 --- a/Lib/defconQt/objects/defcon.py +++ b/Lib/defconQt/objects/defcon.py @@ -2,17 +2,20 @@ from defcon import Font, Contour, Glyph, Point from defcon.objects.base import BaseObject from fontTools.agl import AGL2UV + class TFont(Font): + def __init__(self, *args, **kwargs): - if not "glyphClass" in kwargs: + if "glyphClass" not in kwargs: kwargs["glyphClass"] = TGlyph - if not "glyphContourClass" in kwargs: + if "glyphContourClass" not in kwargs: kwargs["glyphContourClass"] = TContour - if not "glyphPointClass" in kwargs: + if "glyphPointClass" not in kwargs: kwargs["glyphPointClass"] = TPoint super(TFont, self).__init__(*args, **kwargs) - def newStandardGlyph(self, name, override=False, addUnicode=True, asTemplate=False, width=500): + def newStandardGlyph(self, name, override=False, addUnicode=True, + asTemplate=False, width=500): if not override: if name in self: return None @@ -33,7 +36,9 @@ class TFont(Font): glyph.dirty = False super(TFont, self).save(path, formatVersion) + class TGlyph(Glyph): + def __init__(self, *args, **kwargs): super(TGlyph, self).__init__(*args, **kwargs) self._template = False @@ -44,7 +49,9 @@ class TGlyph(Glyph): def _set_template(self, value): self._template = value - template = property(_get_template, _set_template, doc="A boolean indicating whether the glyph is a template glyph.") + template = property( + _get_template, _set_template, + doc="A boolean indicating whether the glyph is a template glyph.") def _set_dirty(self, value): BaseObject._set_dirty(self, value) @@ -68,7 +75,9 @@ class TGlyph(Glyph): return self.unicodes = [uni] + class TContour(Contour): + def __init__(self, pointClass=None, **kwargs): if pointClass is None: pointClass = TPoint @@ -80,9 +89,13 @@ class TContour(Contour): """ pointPen.beginPath() for point in self._points: - pointPen.addPoint((point.x, point.y), segmentType=point.segmentType, smooth=point.smooth, name=point.name, selected=point.selected) + pointPen.addPoint((point.x, point.y), + segmentType=point.segmentType, + smooth=point.smooth, name=point.name, + selected=point.selected) pointPen.endPath() + class TPoint(Point): __slots__ = ["_selected"] @@ -96,7 +109,10 @@ class TPoint(Point): def _set_selected(self, value): self._selected = value - selected = property(_get_selected, _set_selected, doc="A boolean indicating the selected state of the point.") + selected = property( + _get_selected, _set_selected, + doc="A boolean indicating the selected state of the point.") + class GlyphSet(object): __slots__ = ["_name", "_glyphNames"] @@ -119,4 +135,5 @@ class GlyphSet(object): def _set_glyphNames(self, glyphNames): self._glyphNames = glyphNames - glyphNames = property(_get_glyphNames, _set_glyphNames, doc="List of glyph names.") + glyphNames = property(_get_glyphNames, _set_glyphNames, + doc="List of glyph names.") diff --git a/Lib/defconQt/pens/copySelectionPen.py b/Lib/defconQt/pens/copySelectionPen.py index fd8909e..118f3ba 100644 --- a/Lib/defconQt/pens/copySelectionPen.py +++ b/Lib/defconQt/pens/copySelectionPen.py @@ -1,7 +1,9 @@ from defconQt.objects.defcon import TGlyph from robofab.pens.pointPen import AbstractPointPen + class CopySelectionPen(AbstractPointPen): + def __init__(self, glyph=None): if glyph is None: glyph = TGlyph() @@ -11,7 +13,8 @@ class CopySelectionPen(AbstractPointPen): self._originalContourIsOpen = False def beginPath(self): - self._contour = self._glyph.contourClass(pointClass=self._glyph.pointClass) + self._contour = self._glyph.contourClass( + pointClass=self._glyph.pointClass) def endPath(self, keepOpened=False): if self._havePoint: @@ -24,7 +27,8 @@ class CopySelectionPen(AbstractPointPen): self._havePoint = False self._originalContourIsOpen = False - def addPoint(self, pt, segmentType=None, smooth=False, name=None, selected=False, **kwargs): + def addPoint(self, pt, segmentType=None, smooth=False, name=None, + selected=False, **kwargs): if segmentType == "move": self._originalContourIsOpen = True if segmentType is None or selected: @@ -40,7 +44,7 @@ class CopySelectionPen(AbstractPointPen): self.beginPath() def addComponent(self, baseGlyphName, transformation): - pass # XXX + pass # XXX def elideOrphanOffCurves(self, arrivedAtBoundary): # onCurves that aren't selected and preceding offCurves if any are @@ -48,9 +52,9 @@ class CopySelectionPen(AbstractPointPen): for _ in range(2): if len(self._contour): if len(self._contour) > 1 and arrivedAtBoundary and \ - self._contour[0].segmentType == "curve": - # We're at the end of drawing and the offCurves lead to begin - # onCurve. Let them in. + self._contour[0].segmentType == "curve": + # We're at the end of drawing and the offCurves lead to + # begin onCurve. Let them in. pass elif self._contour[-1].segmentType is None: self._contour.removePoint(self._contour[-1]) diff --git a/Lib/defconQt/representationFactories/__init__.py b/Lib/defconQt/representationFactories/__init__.py index df13068..86b8b06 100644 --- a/Lib/defconQt/representationFactories/__init__.py +++ b/Lib/defconQt/representationFactories/__init__.py @@ -1,15 +1,19 @@ from defcon.objects.glyph import addRepresentationFactory
-from defconQt.representationFactories.qPainterPathFactory import QPainterPathFactory
-from defconQt.representationFactories.glyphViewFactory import NoComponentsQPainterPathFactory, OnlyComponentsQPainterPathFactory, OutlineInformationFactory, StartPointsInformationFactory
+from defconQt.representationFactories.qPainterPathFactory import (
+ QPainterPathFactory)
+from defconQt.representationFactories.glyphViewFactory import (
+ NoComponentsQPainterPathFactory, OnlyComponentsQPainterPathFactory,
+ OutlineInformationFactory, StartPointsInformationFactory)
_factories = {
- "defconQt.QPainterPath" : QPainterPathFactory,
- "defconQt.OnlyComponentsQPainterPath" : OnlyComponentsQPainterPathFactory,
- "defconQt.NoComponentsQPainterPath" : NoComponentsQPainterPathFactory,
- "defconQt.OutlineInformation" : OutlineInformationFactory,
- "defconQt.StartPointsInformation" : StartPointsInformationFactory,
+ "defconQt.QPainterPath": QPainterPathFactory,
+ "defconQt.OnlyComponentsQPainterPath": OnlyComponentsQPainterPathFactory,
+ "defconQt.NoComponentsQPainterPath": NoComponentsQPainterPathFactory,
+ "defconQt.OutlineInformation": OutlineInformationFactory,
+ "defconQt.StartPointsInformation": StartPointsInformationFactory,
}
+
def registerAllFactories():
for name, factory in _factories.items():
addRepresentationFactory(name, factory)
diff --git a/Lib/defconQt/representationFactories/glyphViewFactory.py b/Lib/defconQt/representationFactories/glyphViewFactory.py index 3edfe3b..0f5df18 100644 --- a/Lib/defconQt/representationFactories/glyphViewFactory.py +++ b/Lib/defconQt/representationFactories/glyphViewFactory.py @@ -19,7 +19,9 @@ def NoComponentsQPainterPathFactory(glyph): pen.path.setFillRule(Qt.WindingFill)
return pen.path
+
class NoComponentsQtPen(QtPen):
+
def addComponent(self, glyphName, transformation):
pass
@@ -34,6 +36,7 @@ def OnlyComponentsQPainterPathFactory(glyph): pen.path.setFillRule(Qt.WindingFill)
return pen.path
+
class OnlyComponentsQtPen(BasePen):
def __init__(self, glyphSet):
@@ -63,12 +66,15 @@ class OnlyComponentsQtPen(BasePen): # start points
# ------------
+
def StartPointsInformationFactory(glyph):
pen = StartPointsInformationPen()
glyph.drawPoints(pen)
return pen.getData()
+
class StartPointsInformationPen(AbstractPointPen):
+
def __init__(self):
self._rawPointData = []
@@ -87,8 +93,9 @@ class StartPointsInformationPen(AbstractPointPen): if not haveFirst:
haveFirst = True
nextOn = None
- for nextPoint in contour[pointIndex:] + contour[:pointIndex]:
- #if nextPoint["segmentType"] is None:
+ for nextPoint in contour[pointIndex:] + \
+ contour[:pointIndex]:
+ # if nextPoint["segmentType"] is None:
# continue
if nextPoint["point"] == point["point"]:
continue
@@ -100,7 +107,8 @@ class StartPointsInformationPen(AbstractPointPen): x2, y2 = nextOn["point"]
xDiff = x2 - x1
yDiff = y2 - y1
- angle = round(math.atan2(yDiff, xDiff) * 180 / math.pi, 3)
+ angle = round(math.atan2(yDiff, xDiff)
+ * 180 / math.pi, 3)
data.append((point["point"], angle))
return data
@@ -110,7 +118,8 @@ class StartPointsInformationPen(AbstractPointPen): def endPath(self):
pass
- def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
+ def addPoint(self, pt, segmentType=None, smooth=False, name=None,
+ **kwargs):
d = dict(point=pt, segmentType=segmentType, smooth=smooth, name=name)
self._rawPointData[-1].append(d)
@@ -121,6 +130,7 @@ class StartPointsInformationPen(AbstractPointPen): # point data
# ----------
+
class OutlineInformationPen(AbstractPointPen):
def __init__(self):
@@ -130,7 +140,9 @@ class OutlineInformationPen(AbstractPointPen): def getData(self):
data = []
- CPoint = namedtuple('Point', ['x', 'y', 'contourIndex', 'pointIndex', 'isSmooth', 'isFirst', 'prevCP', 'nextCP'])
+ CPoint = namedtuple('Point', [
+ 'x', 'y', 'contourIndex', 'pointIndex', 'isSmooth', 'isFirst',
+ 'prevCP', 'nextCP'])
for contour in self._rawPointData:
# anchor
@@ -145,14 +157,17 @@ class OutlineInformationPen(AbstractPointPen): if point["segmentType"] is not None:
prevCP, nextCP = None, None
if back["segmentType"] is None:
- # if we have an open contour with a trailing offCurve, don't signal it to the
- # first point
- if not (not haveFirst and contour[pointIndex-2]["segmentType"] is not None):
+ # if we have an open contour with a trailing
+ # offCurve, don't signal it to the first point
+ if not (not haveFirst and
+ contour[pointIndex - 2]["segmentType"] is
+ not None):
prevCP = back["point"]
if forward["segmentType"] is None:
nextCP = forward["point"]
x, y = point["point"]
- pt = CPoint(x, y, self.cIndex, self.index, point["smooth"], not haveFirst, prevCP, nextCP)
+ pt = CPoint(x, y, self.cIndex, self.index, point[
+ "smooth"], not haveFirst, prevCP, nextCP)
data.append(pt)
# catch first point
if not haveFirst:
@@ -170,7 +185,8 @@ class OutlineInformationPen(AbstractPointPen): def endPath(self):
pass
- def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
+ def addPoint(self, pt, segmentType=None, smooth=False, name=None,
+ **kwargs):
d = dict(point=pt, segmentType=segmentType, smooth=smooth, name=name)
self._rawPointData[-1].append(d)
diff --git a/Lib/defconQt/representationFactories/qPainterPathFactory.py b/Lib/defconQt/representationFactories/qPainterPathFactory.py index 0b99b82..7270f5f 100644 --- a/Lib/defconQt/representationFactories/qPainterPathFactory.py +++ b/Lib/defconQt/representationFactories/qPainterPathFactory.py @@ -1,6 +1,7 @@ from fontTools.pens.qtPen import QtPen
from PyQt5.QtCore import Qt
+
def QPainterPathFactory(glyph):
pen = QtPen(glyph.layer)
glyph.draw(pen)
diff --git a/Lib/defconQt/scriptingWindow.py b/Lib/defconQt/scriptingWindow.py index 38f70ab..c6403e8 100644 --- a/Lib/defconQt/scriptingWindow.py +++ b/Lib/defconQt/scriptingWindow.py @@ -2,10 +2,13 @@ from defconQt.baseCodeEditor import CodeEditor, CodeHighlighter from keyword import kwlist import traceback from PyQt5.QtCore import Qt -from PyQt5.QtGui import QColor, QFont, QKeySequence, QTextCharFormat, QTextCursor -from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QPlainTextEdit +from PyQt5.QtGui import ( + QColor, QFont, QKeySequence, QTextCharFormat, QTextCursor) +from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu + class MainScriptingWindow(QMainWindow): + def __init__(self): super(MainScriptingWindow, self).__init__() @@ -39,6 +42,7 @@ class MainScriptingWindow(QMainWindow): except: print(traceback.format_exc()) + class PythonEditor(CodeEditor): autocomplete = { Qt.Key_ParenLeft: "()", @@ -69,21 +73,25 @@ class PythonEditor(CodeEditor): cursor = self.textCursor() ok = cursor.movePosition(QTextCursor.PreviousCharacter) if ok: - ok = cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, 2) + ok = cursor.movePosition( + QTextCursor.NextCharacter, QTextCursor.KeepAnchor, 2) if ok and cursor.selectedText() in self.autocomplete.values(): cursor.removeSelectedText() event.accept() return super(PythonEditor, self).keyPressEvent(event) + class PythonHighlighter(CodeHighlighter): + def __init__(self, parent=None): super(PythonHighlighter, self).__init__(parent) keywordFormat = QTextCharFormat() keywordFormat.setForeground(QColor(34, 34, 34)) keywordFormat.setFontWeight(QFont.Bold) - self.highlightingRules.append(("\\b(%s)\\b" % ("|".join(kwlist)), keywordFormat)) + self.highlightingRules.append( + ("\\b(%s)\\b" % ("|".join(kwlist)), keywordFormat)) singleLineCommentFormat = QTextCharFormat() singleLineCommentFormat.setForeground(Qt.darkGray) @@ -91,8 +99,10 @@ class PythonHighlighter(CodeHighlighter): classOrFnNameFormat = QTextCharFormat() classOrFnNameFormat.setForeground(QColor(96, 106, 161)) - self.highlightingRules.append(("(?<=\\bclass\\s|def\\s\\b)\\s*(\\w+)", classOrFnNameFormat)) + self.highlightingRules.append( + ("(?<=\\bclass\\s|def\\s\\b)\\s*(\\w+)", classOrFnNameFormat)) quotationFormat = QTextCharFormat() quotationFormat.setForeground(QColor(223, 17, 68)) - self.highlightingRules.append(("'.*'|[\"]{1,3}.*[\"]{1,3}", quotationFormat)) + self.highlightingRules.append( + ("'.*'|[\"]{1,3}.*[\"]{1,3}", quotationFormat)) diff --git a/Lib/defconQt/spaceCenter.py b/Lib/defconQt/spaceCenter.py index ee698e8..c450c72 100644 --- a/Lib/defconQt/spaceCenter.py +++ b/Lib/defconQt/spaceCenter.py @@ -2,18 +2,23 @@ from defconQt import icons_db from defconQt.glyphCollectionView import cellSelectionColor from defconQt.glyphView import MainGfxWindow from getpass import getuser -from PyQt5.QtCore import *#QAbstractTableModel, QEvent, QSize, Qt -from PyQt5.QtGui import *#(QBrush, QColor, QFont, QIcon, QKeySequence, QLinearGradient, QPainter, - #QPainterPath, QPalette, QPen) -from PyQt5.QtWidgets import *#(QAbstractItemView, QActionGroup, QApplication, QComboBox, QGridLayout, QLabel, QLineEdit, - #QMainWindow, QMenu, QPushButton, QScrollArea, QStyledItemDelegate, QTableView, QTableWidget, QTableWidgetItem, QVBoxLayout, QSizePolicy, QSpinBox, QToolBar, QWidget) +from PyQt5.QtCore import QEvent, QSize, Qt +from PyQt5.QtGui import ( + QBrush, QColor, QIcon, QIntValidator, QKeySequence, QPainter, QPen) +from PyQt5.QtWidgets import ( + QAbstractItemView, QActionGroup, QApplication, QComboBox, QLineEdit, QMenu, + QPushButton, QScrollArea, QStyledItemDelegate, QTableWidget, + QTableWidgetItem, QVBoxLayout, QSizePolicy, QToolBar, QWidget) defaultPointSize = 150 glyphSelectionColor = QColor(cellSelectionColor) glyphSelectionColor.setAlphaF(.09) + class MainSpaceWindow(QWidget): - def __init__(self, font, string=None, pointSize=defaultPointSize, parent=None): + + def __init__(self, font, string=None, pointSize=defaultPointSize, + parent=None): super(MainSpaceWindow, self).__init__(parent, Qt.Window) if string is None: @@ -27,7 +32,8 @@ class MainSpaceWindow(QWidget): self.toolbar = FontToolBar(string, pointSize, self) self.canvas = GlyphsCanvas(self.font, self.glyphs, pointSize, self) self.table = SpaceTable(self.glyphs, self) - self.toolbar.comboBox.currentIndexChanged[str].connect(self.canvas.setPointSize) + self.toolbar.comboBox.currentIndexChanged[ + str].connect(self.canvas.setPointSize) self.toolbar.textField.textEdited.connect(self._textChanged) self.canvas.doubleClickCallback = self._glyphOpened self.canvas.pointSizeCallback = self.toolbar.setPointSize @@ -50,7 +56,8 @@ class MainSpaceWindow(QWidget): self.font.info.addObserver(self, "_fontInfoChanged", "Info.Changed") - self.setWindowTitle("Space center – %s %s" % (self.font.info.familyName, self.font.info.styleName)) + self.setWindowTitle("Space center – %s %s" % ( + self.font.info.familyName, self.font.info.styleName)) def setupFileMenu(self): fileMenu = QMenu("&File", self) @@ -123,7 +130,8 @@ class MainSpaceWindow(QWidget): if c == "/": # finishing a previous compile. if compileStack is not None: - # only add the compile if something has been added to the stack. + # only add the compile if something has been added to the + # stack. if compileStack: glyphNames.append("".join(compileStack)) # reset the stack. @@ -132,7 +140,8 @@ class MainSpaceWindow(QWidget): elif compileStack is not None: # space. conclude the glyph name compile. if c == " ": - # only add the compile if something has been added to the stack. + # only add the compile if something has been added to the + # stack. catchCompile() compileStack = None # add the character to the stack. @@ -164,7 +173,7 @@ class MainSpaceWindow(QWidget): continue handledGlyphs.add(glyph) glyph.removeObserver(self, "Glyph.Changed") - #self.glyphs = None + # self.glyphs = None def setGlyphs(self, glyphs): # unsubscribe from the old glyphs @@ -173,22 +182,28 @@ class MainSpaceWindow(QWidget): self._subscribeToGlyphs(glyphs) glyphNames = [] for glyph in glyphs: - glyphNames.append(chr(glyph.unicode) if glyph.unicode else "".join(("/", glyph.name, " "))) + if glyph.unicode: + glyphNames.append(chr(glyph.unicode)) + else: + glyphNames.append("".join(("/", glyph.name, " "))) self.toolbar.textField.setText("".join(glyphNames)) # set the records into the view self.canvas.setGlyphs(self.glyphs) self.table.setGlyphs(self.glyphs) def resizeEvent(self, event): - if self.isVisible(): self.canvas._sizeEvent(event) + if self.isVisible(): + self.canvas._sizeEvent(event) super(MainSpaceWindow, self).resizeEvent(event) pointSizes = [50, 75, 100, 125, 150, 200, 250, 300, 350, 400, 450, 500] + class FontToolBar(QToolBar): + def __init__(self, string, pointSize, parent=None): super(FontToolBar, self).__init__(parent) - auxiliaryWidth = self.fontMetrics().width('0')*8 + auxiliaryWidth = self.fontMetrics().width('0') * 8 self.leftTextField = QLineEdit(self) self.leftTextField.setMaximumWidth(auxiliaryWidth) self.textField = QLineEdit(string, self) @@ -206,11 +221,13 @@ class FontToolBar(QToolBar): self.configBar = QPushButton(self) self.configBar.setFlat(True) self.configBar.setIcon(QIcon(":/resources/settings.svg")) - self.configBar.setStyleSheet("padding: 2px 0px; padding-right: 10px"); + self.configBar.setStyleSheet("padding: 2px 0px; padding-right: 10px") self.toolsMenu = QMenu(self) - showKerning = self.toolsMenu.addAction("Show Kerning", self.showKerning) + showKerning = self.toolsMenu.addAction( + "Show Kerning", self.showKerning) showKerning.setCheckable(True) - showMetrics = self.toolsMenu.addAction("Show Metrics", self.showMetrics) + showMetrics = self.toolsMenu.addAction( + "Show Metrics", self.showMetrics) showMetrics.setCheckable(True) self.toolsMenu.addSeparator() wrapLines = self.toolsMenu.addAction("Wrap lines", self.wrapLines) @@ -218,13 +235,15 @@ class FontToolBar(QToolBar): noWrapLines = self.toolsMenu.addAction("No wrap", self.noWrapLines) noWrapLines.setCheckable(True) self.toolsMenu.addSeparator() - verticalFlip = self.toolsMenu.addAction("Vertical flip", self.verticalFlip) + verticalFlip = self.toolsMenu.addAction( + "Vertical flip", self.verticalFlip) verticalFlip.setCheckable(True) """ lineHeight = QWidgetAction(self.toolsMenu) lineHeight.setText("Line height:") lineHeightSlider = QSlider(Qt.Horizontal, self) - # QSlider works with integers so we'll just divide by 100 what comes out of it + # QSlider works with integers so we'll just divide by 100 what comes + # out of it lineHeightSlider.setMinimum(80) lineHeightSlider.setMaximum(160) lineHeightSlider.setValue(100) @@ -238,7 +257,7 @@ class FontToolBar(QToolBar): wrapLinesGroup.addAction(wrapLines) wrapLinesGroup.addAction(noWrapLines) wrapLines.setChecked(True) - #self.toolsMenu.setActiveAction(wrapLines) + # self.toolsMenu.setActiveAction(wrapLines) self.configBar.setMenu(self.toolsMenu) self.addWidget(self.leftTextField) @@ -277,7 +296,9 @@ class FontToolBar(QToolBar): def noWrapLines(self): self.parent().canvas.setWrapLines(False) + class GlyphsCanvas(QWidget): + def __init__(self, font, glyphs, pointSize=defaultPointSize, parent=None): super(GlyphsCanvas, self).__init__(parent) # XXX: make canvas font-agnostic as in defconAppkit and use @@ -310,7 +331,8 @@ class GlyphsCanvas(QWidget): def calculateScale(self): scale = self.ptSize / self.upm - if scale < .01: scale = 0.01 + if scale < .01: + scale = 0.01 self.scale = scale def setShowKerning(self, showKerning): @@ -330,27 +352,36 @@ class GlyphsCanvas(QWidget): self.update() def setWrapLines(self, wrapLines): - if self._wrapLines == wrapLines: return + if self._wrapLines == wrapLines: + return self._wrapLines = wrapLines if self._wrapLines: - sw = self._scrollArea.verticalScrollBar().width() + self._scrollArea.contentsMargins().right() - self.resize(self.parent().parent().parent().width() - sw, self.height()) - self._scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + sw = self._scrollArea.verticalScrollBar().width( + ) + self._scrollArea.contentsMargins().right() + self.resize(self.parent().parent().parent().width() - + sw, self.height()) + self._scrollArea.setHorizontalScrollBarPolicy( + Qt.ScrollBarAlwaysOff) self._scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) else: - sh = self._scrollArea.horizontalScrollBar().height() + self._scrollArea.contentsMargins().bottom() - self.resize(self.width(), self.parent().parent().parent().height() - sh) + sh = self._scrollArea.horizontalScrollBar().height( + ) + self._scrollArea.contentsMargins().bottom() + self.resize(self.width(), self.parent( + ).parent().parent().height() - sh) self._scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.update() def fetchFontMetrics(self): self.ascender = self.font.info.ascender - if self.ascender is None: self.ascender = 750 + if self.ascender is None: + self.ascender = 750 self.descender = self.font.info.descender - if self.descender is None: self.descender = 250 + if self.descender is None: + self.descender = 250 self.upm = self.font.info.unitsPerEm - if self.upm is None or not self.upm > 0: self.upm = 1000 + if self.upm is None or not self.upm > 0: + self.upm = 1000 def setGlyphs(self, newGlyphs): self.glyphs = newGlyphs @@ -374,28 +405,35 @@ class GlyphsCanvas(QWidget): break cur_len += len(li) if line > -1: - x = self.padding + pos + width/2 - y = self.padding + (line+.5)*self.ptSize*self._lineHeight - self._scrollArea.ensureVisible(x, y, width/2+20, .5*self.ptSize*self._lineHeight+20) + x = self.padding + pos + width / 2 + y = self.padding + (line + .5) * self.ptSize * self._lineHeight + self._scrollArea.ensureVisible( + x, y, width / 2 + 20, + .5 * self.ptSize * self._lineHeight + 20) self.update() def _sizeEvent(self, event): if self._wrapLines: - sw = self._scrollArea.verticalScrollBar().width() + self._scrollArea.contentsMargins().right() + sw = self._scrollArea.verticalScrollBar().width( + ) + self._scrollArea.contentsMargins().right() self.resize(event.size().width() - sw, self.height()) else: - sh = self._scrollArea.horizontalScrollBar().height() + self._scrollArea.contentsMargins().bottom() + sh = self._scrollArea.horizontalScrollBar().height( + ) + self._scrollArea.contentsMargins().bottom() self.resize(self.width(), event.size().height() - sh) def wheelEvent(self, event): if event.modifiers() & Qt.ControlModifier: - # TODO: should it snap to predefined pointSizes? is the scaling factor okay? + # TODO: should it snap to predefined pointSizes? + # is the scaling factor okay? # XXX: current alg. is not reversible... decay = event.angleDelta().y() / 120.0 scale = round(self.ptSize / 10) - if scale == 0 and decay >= 0: scale = 1 + if scale == 0 and decay >= 0: + scale = 1 newPointSize = self.ptSize + int(decay) * scale - if newPointSize <= 0: return + if newPointSize <= 0: + return self.setPointSize(newPointSize) if self.pointSizeChangedCallback is not None: @@ -455,7 +493,8 @@ class GlyphsCanvas(QWidget): else: baselineShift = self.ascender found = False - line = (event.y() - self.padding) // (self.ptSize*self._lineHeight) + line = \ + (event.y() - self.padding) // (self.ptSize * self._lineHeight) # XXX: Shouldnt // yield an int? line = int(line) if line >= len(self._positions): @@ -470,13 +509,14 @@ class GlyphsCanvas(QWidget): x = event.x() - self.padding for index, data in enumerate(self._positions[line]): pos, width = data - if pos <= x and pos+width > x: + if pos <= x and pos + width > x: count = 0 for i in range(line): count += len(self._positions[i]) - self._selected = count+index + self._selected = count + index found = True - if not found: self._selected = None + if not found: + self._selected = None if self.selectionChangedCallback is not None: self.selectionChangedCallback(self._selected) event.accept() @@ -495,9 +535,10 @@ class GlyphsCanvas(QWidget): linePen = QPen(Qt.black) linePen.setWidth(3) width = self.width() / self.scale + def paintLineMarks(painter): painter.save() - painter.scale(self.scale, yDirection*self.scale) + painter.scale(self.scale, yDirection * self.scale) painter.setPen(linePen) painter.drawLine(0, self.ascender, width, self.ascender) painter.drawLine(0, 0, width, 0) @@ -513,23 +554,30 @@ class GlyphsCanvas(QWidget): else: baselineShift = self.ascender yDirection = -1 - painter.translate(self.padding, self.padding+baselineShift*self.scale*self._lineHeight) + painter.translate(self.padding, self.padding + + baselineShift * self.scale * self._lineHeight) # TODO: scale painter here to avoid g*scale everywhere below cur_width = 0 lines = 1 self._positions = [[]] - if self._showMetrics: paintLineMarks(painter) + if self._showMetrics: + paintLineMarks(painter) for index, glyph in enumerate(self.glyphs): # line wrapping - gWidth = glyph.width*self.scale + gWidth = glyph.width * self.scale doKern = index > 0 and self._showKerning and cur_width > 0 if doKern: - kern = self.lookupKerningValue(self.glyphs[index-1].name, glyph.name)*self.scale - else: kern = 0 - if self._wrapLines and cur_width + gWidth + kern + 2*self.padding > self.width(): - painter.translate(-cur_width, self.ptSize*self._lineHeight) - if self._showMetrics: paintLineMarks(painter) + kern = self.lookupKerningValue( + self.glyphs[index - 1].name, glyph.name) * self.scale + else: + kern = 0 + if (self._wrapLines and + cur_width + gWidth + kern + 2 * self.padding > + self.width()): + painter.translate(-cur_width, self.ptSize * self._lineHeight) + if self._showMetrics: + paintLineMarks(painter) self._positions.append([(0, gWidth)]) cur_width = gWidth lines += 1 @@ -537,29 +585,36 @@ class GlyphsCanvas(QWidget): if doKern: painter.translate(kern, 0) self._positions[-1].append((cur_width, gWidth)) - cur_width += gWidth+kern + cur_width += gWidth + kern glyphPath = glyph.getRepresentation("defconQt.QPainterPath") painter.save() - painter.scale(self.scale, yDirection*self.scale) + painter.scale(self.scale, yDirection * self.scale) if self._showMetrics: - halfDescent = self.descender/2 + halfDescent = self.descender / 2 painter.drawLine(0, 0, 0, halfDescent) painter.drawLine(glyph.width, 0, glyph.width, halfDescent) if self._selected is not None and index == self._selected: - painter.fillRect(0, self.descender, glyph.width, self.upm, glyphSelectionColor) + painter.fillRect(0, self.descender, glyph.width, + self.upm, glyphSelectionColor) painter.fillPath(glyphPath, Qt.black) painter.restore() painter.translate(gWidth, 0) scrollMargins = self._scrollArea.contentsMargins() - innerHeight = self._scrollArea.height() - scrollMargins.top() - scrollMargins.bottom() + innerHeight = self._scrollArea.height() - scrollMargins.top() - \ + scrollMargins.bottom() if not self._wrapLines: - innerWidth = self._scrollArea.width() - scrollMargins.left() - scrollMargins.right() - width = max(innerWidth, cur_width+self.padding*2) - else: width = self.width() - self.resize(width, max(innerHeight, lines*self.ptSize*self._lineHeight+2*self.padding)) + innerWidth = self._scrollArea.width() - scrollMargins.left() - \ + scrollMargins.right() + width = max(innerWidth, cur_width + self.padding * 2) + else: + width = self.width() + self.resize(width, max(innerHeight, lines * self.ptSize * + self._lineHeight + 2 * self.padding)) + class SpaceTableWidgetItem(QTableWidgetItem): + def setData(self, role, value): if role & Qt.EditRole: # don't set empty data @@ -568,10 +623,13 @@ class SpaceTableWidgetItem(QTableWidgetItem): return super(SpaceTableWidgetItem, self).setData(role, value) + class GlyphCellItemDelegate(QStyledItemDelegate): + def createEditor(self, parent, option, index): - editor = super(GlyphCellItemDelegate, self).createEditor(parent, option, index) - #editor.setAlignment(Qt.AlignCenter) + editor = super(GlyphCellItemDelegate, self).createEditor( + parent, option, index) + # editor.setAlignment(Qt.AlignCenter) editor.setValidator(QIntValidator(self)) return editor @@ -599,22 +657,24 @@ class GlyphCellItemDelegate(QStyledItemDelegate): if modifiers & Qt.ControlModifier: chg *= 10 cur = int(editor.text()) - editor.setText(str(cur+chg)) + editor.setText(str(cur + chg)) self.commitData.emit(editor) editor.selectAll() return True return False + class SpaceTable(QTableWidget): + def __init__(self, glyphs, parent=None): self.glyphs = glyphs - super(SpaceTable, self).__init__(4, len(glyphs)+1, parent) + super(SpaceTable, self).__init__(4, len(glyphs) + 1, parent) self.setAttribute(Qt.WA_KeyCompression) self.setItemDelegate(GlyphCellItemDelegate(self)) # XXX: dunno why but without updating col count # scrollbar reports incorrect height... # fillGlyphs() will change this value back - self.setColumnCount(len(self.glyphs)+2) + self.setColumnCount(len(self.glyphs) + 2) data = [None, "Width", "Left", "Right"] self._fgOverride = SpaceTableWidgetItem().foreground() for index, title in enumerate(data): @@ -623,14 +683,15 @@ class SpaceTable(QTableWidget): item.setForeground(self._fgOverride) self.setItem(index, 0, item) # let's use this one column to compute the width of others - self._cellWidth = .5*self.columnWidth(0) + self._cellWidth = .5 * self.columnWidth(0) self.setColumnWidth(0, self._cellWidth) self.horizontalHeader().hide() self.verticalHeader().hide() # always show a scrollbar to fix layout self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) - self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)) + self.setSizePolicy(QSizePolicy( + QSizePolicy.Preferred, QSizePolicy.Fixed)) self.fillGlyphs() self.resizeRowsToContents() self.currentItemChanged.connect(self._itemChanged) @@ -657,22 +718,28 @@ class SpaceTable(QTableWidget): self.blockSignals(False) def _cellEdited(self, row, col): - if row == 0 or col == 0: return + if row == 0 or col == 0: + return item = self.item(row, col).text() # Glyphs that do not have outlines leave empty cells, can't convert # that to a scalar - if not item: return + if not item: + return item = int(item) # -1 because the first col contains descriptive text - glyph = self.glyphs[col-1] - # != comparisons avoid making glyph dirty when editor content is unchanged + glyph = self.glyphs[col - 1] + # != comparisons avoid making glyph dirty when editor content is + # unchanged self._editing = True if row == 1: - if item != glyph.width: glyph.width = item + if item != glyph.width: + glyph.width = item elif row == 2: - if item != glyph.leftMargin: glyph.leftMargin = item + if item != glyph.leftMargin: + glyph.leftMargin = item elif row == 3: - if item != glyph.rightMargin: glyph.rightMargin = item + if item != glyph.rightMargin: + glyph.rightMargin = item self._editing = False # defcon callbacks do the update @@ -715,10 +782,10 @@ class SpaceTable(QTableWidget): self.blockSignals(True) if glyphIndex is not None: # so we can scroll to the item - self.setCurrentCell(1, glyphIndex+1) + self.setCurrentCell(1, glyphIndex + 1) self.setCurrentItem(None) if glyphIndex is not None: - self.colorColumn(glyphIndex+1) + self.colorColumn(glyphIndex + 1) else: self.colorColumn(glyphIndex) self.blockSignals(False) @@ -727,25 +794,27 @@ class SpaceTable(QTableWidget): def glyphTableWidgetItem(content, disableCell=False): if isinstance(content, float): content = round(content) - if content is not None: content = str(content) + if content is not None: + content = str(content) item = SpaceTableWidgetItem(content) if disableCell: item.setFlags(Qt.NoItemFlags) item.setForeground(self._fgOverride) - elif content is None: item.setFlags(Qt.ItemIsEnabled) + elif content is None: + item.setFlags(Qt.ItemIsEnabled) # TODO: should fields be centered? I find left-aligned more # natural to read, personally... - #item.setTextAlignment(Qt.AlignCenter) + # item.setTextAlignment(Qt.AlignCenter) return item - self.setColumnCount(len(self.glyphs)+1) + self.setColumnCount(len(self.glyphs) + 1) for index, glyph in enumerate(self.glyphs): # TODO: see about allowing glyph name edit here - self.setItem(0, index+1, glyphTableWidgetItem(glyph.name, True)) - self.setItem(1, index+1, glyphTableWidgetItem(glyph.width)) - self.setItem(2, index+1, glyphTableWidgetItem(glyph.leftMargin)) - self.setItem(3, index+1, glyphTableWidgetItem(glyph.rightMargin)) - self.setColumnWidth(index+1, self._cellWidth) + self.setItem(0, index + 1, glyphTableWidgetItem(glyph.name, True)) + self.setItem(1, index + 1, glyphTableWidgetItem(glyph.width)) + self.setItem(2, index + 1, glyphTableWidgetItem(glyph.leftMargin)) + self.setItem(3, index + 1, glyphTableWidgetItem(glyph.rightMargin)) + self.setColumnWidth(index + 1, self._cellWidth) def wheelEvent(self, event): cur = self.horizontalScrollBar().value() |
