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 | |
| parent | 9ce52ed3a18616828daf475fc487fd69322bee0e (diff) | |
| download | trufont-63f83224f474c2c191e8cac3cb6bda8f2cb81b7d.tar.bz2 | |
Use PEP8 code style
Diffstat (limited to 'Lib')
| -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()  | 
