diff options
| author | Adrien Tétar | 2015-10-29 21:42:25 +0100 | 
|---|---|---|
| committer | Adrien Tétar | 2015-10-29 21:42:25 +0100 | 
| commit | 9c66d880cfaa938f3d0814eaaf215e9a9dbfffa3 (patch) | |
| tree | 83d9b76e4fb6a40d096e63a122b989061cf1bc65 | |
| parent | 5d62be8c4dfb601b92f9153400e3e1cc8712cf94 (diff) | |
| parent | 1a889dc612c036763d80815a00d4b9a8fc73ba78 (diff) | |
| download | trufont-9c66d880cfaa938f3d0814eaaf215e9a9dbfffa3.tar.bz2 | |
Merge pull request #95 from trufont/patch-5
meta: shufflings, loadMostRecentFile, metricsWindow: canvas key short…
| -rw-r--r-- | Lib/defconQt/fontView.py | 203 | ||||
| -rw-r--r-- | Lib/defconQt/glyphView.py | 4 | ||||
| -rw-r--r-- | Lib/defconQt/metricsWindow.py (renamed from Lib/defconQt/spaceCenter.py) | 127 | 
3 files changed, 214 insertions, 120 deletions
| diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index b0cc7e9..523719f 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -1,3 +1,4 @@ +from defconQt import __version__  from defconQt.featureTextEditor import MainEditWindow  from defconQt.fontInfo import TabDialog  from defconQt.glyphCollectionView import GlyphCollectionWidget @@ -8,7 +9,7 @@ from defconQt.scriptingWindow import MainScriptingWindow  from defconQt.objects.defcon import GlyphSet, TFont, TGlyph  from defconQt.util import platformSpecific  from defcon import Color, Component -from defconQt.spaceCenter import MainSpaceWindow, comboBoxItems +from defconQt.metricsWindow import MainMetricsWindow, comboBoxItems  from PyQt5.QtCore import (      pyqtSignal, QEvent, QMimeData, QRegularExpression, QSettings, Qt)  from PyQt5.QtGui import ( @@ -16,13 +17,14 @@ from PyQt5.QtGui import (      QRegularExpressionValidator, QTextCursor)  from PyQt5.QtWidgets import (      QAbstractItemView, 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) +    QDialogButtonBox, 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  import pickle +import platform  import traceback  cannedDesign = [ @@ -114,11 +116,11 @@ class Application(QApplication):  MAX_RECENT_FILES = 6 -class InspectorWindow(QWidget): +class InfoPanel(QWidget):      def __init__(self): -        super(InspectorWindow, self).__init__(flags=Qt.Tool) -        self.setWindowTitle("Inspector") +        super().__init__(flags=Qt.Tool) +        self.setWindowTitle("Info Panel")          self._blocked = False          self._glyph = None @@ -248,7 +250,8 @@ class InspectorWindow(QWidget):          self.setLayout(mainLayout)      def showEvent(self, event): -        super(InspectorWindow, self).showEvent(event) +        super().showEvent(event) +        # TODO: does not put window on secondary screen if applicable          screenRect = QApplication.desktop().screenGeometry()          widgetRect = self.frameGeometry()          x = screenRect.width() - (widgetRect.width() + 20) @@ -381,11 +384,11 @@ class InspectorWindow(QWidget):          self._blocked = False -class AddGlyphDialog(QDialog): +class AddGlyphsDialog(QDialog):      # TODO: implement Frederik's Glyph Construction Builder      def __init__(self, currentGlyphs=None, parent=None): -        super(AddGlyphDialog, self).__init__(parent) +        super(AddGlyphsDialog, self).__init__(parent)          self.setWindowModality(Qt.WindowModal)          self.setWindowTitle("Add glyphs…")          self.currentGlyphs = currentGlyphs @@ -398,8 +401,8 @@ class AddGlyphDialog(QDialog):          for name, glyphNames in glyphSets.items():              self.importCharDrop.addItem(name, glyphNames)          self.importCharDrop.currentIndexChanged[int].connect(self.importGlyphs) -        self.addGlyphEdit = QPlainTextEdit(self) -        self.addGlyphEdit.setFocus(True) +        self.addGlyphsEdit = QPlainTextEdit(self) +        self.addGlyphsEdit.setFocus(True)          self.addUnicodeBox = QCheckBox("Add Unicode", self)          self.addUnicodeBox.setChecked(True) @@ -415,7 +418,7 @@ class AddGlyphDialog(QDialog):          l = 0          layout.addWidget(self.importCharDrop, l, 3, 1, 2)          l += 1 -        layout.addWidget(self.addGlyphEdit, l, 0, 1, 5) +        layout.addWidget(self.addGlyphsEdit, l, 0, 1, 5)          l += 1          layout.addWidget(self.addUnicodeBox, l, 0)          layout.addWidget(self.addAsTemplateBox, l, 1) @@ -435,7 +438,7 @@ class AddGlyphDialog(QDialog):              sortFont=dialog.sortFontBox.isChecked(),          )          newGlyphNames = [] -        for name in dialog.addGlyphEdit.toPlainText().split(): +        for name in dialog.addGlyphsEdit.toPlainText().split():              if name not in dialog.currentGlyphNames:                  newGlyphNames.append(name)          return (newGlyphNames, params, result) @@ -444,7 +447,7 @@ class AddGlyphDialog(QDialog):          if index == 0:              return          glyphNames = self.importCharDrop.currentData() -        editorNames = self.addGlyphEdit.toPlainText().split() +        editorNames = self.addGlyphsEdit.toPlainText().split()          currentNames = set(self.currentGlyphNames) ^ set(editorNames)          changed = False          for name in glyphNames: @@ -452,12 +455,12 @@ class AddGlyphDialog(QDialog):                  changed = True                  editorNames.append(name)          if changed: -            self.addGlyphEdit.setPlainText(" ".join(editorNames)) -            cursor = self.addGlyphEdit.textCursor() +            self.addGlyphsEdit.setPlainText(" ".join(editorNames)) +            cursor = self.addGlyphsEdit.textCursor()              cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) -            self.addGlyphEdit.setTextCursor(cursor) +            self.addGlyphsEdit.setTextCursor(cursor)          self.importCharDrop.setCurrentIndex(0) -        self.addGlyphEdit.setFocus(True) +        self.addGlyphsEdit.setFocus(True)  class SortDialog(QDialog): @@ -467,7 +470,7 @@ class SortDialog(QDialog):          self.setWindowModality(Qt.WindowModal)          self.setWindowTitle("Sort…") -        self.smartSortBox = QRadioButton("Smart sort", self) +        self.smartSortBox = QRadioButton("Optimized sort", self)          self.smartSortBox.setToolTip("A combination of simple, complex and "                                       "custom sorts that give optimized "                                       "ordering results.") @@ -624,10 +627,16 @@ class MainWindow(QMainWindow):          self.collectionWidget = GlyphCollectionWidget(self)          self._font = None          self._sortDescriptor = None -        if font is None: -            self.newFile(True) -        else: +        settings = QSettings() +        loadRecentFile = settings.value("core/loadRecentFile", False, bool) +        if font is None and loadRecentFile: +            recentFiles = settings.value("core/recentFiles", [], type=str) +            if len(recentFiles): +                self.openFile(recentFiles[0], True) +        elif font is not None:              self.font = font +        if self._font is None: +            self.newFile(True)          self.collectionWidget.glyphSelectedCallback = self._selectionChanged          self.collectionWidget.doubleClickCallback = self._glyphOpened          # TODO: should default be True or False? @@ -640,7 +649,7 @@ class MainWindow(QMainWindow):          fileMenu.addAction("&New…", self.newFile, QKeySequence.New)          fileMenu.addAction("&Open…", self.openFile, QKeySequence.Open)          # recent files -        self.recentFilesMenu = QMenu("Open &recent…", self) +        self.recentFilesMenu = QMenu("Open &Recent…", self)          for i in range(MAX_RECENT_FILES):              action = QAction(self.recentFilesMenu)              action.setVisible(False) @@ -650,14 +659,14 @@ class MainWindow(QMainWindow):          fileMenu.addMenu(self.recentFilesMenu)          fileMenu.addSeparator()          fileMenu.addAction("&Save", self.saveFile, QKeySequence.Save) -        fileMenu.addAction("Save &as…", self.saveFileAs, QKeySequence.SaveAs) +        fileMenu.addAction("Save &As…", self.saveFileAs, QKeySequence.SaveAs)          fileMenu.addAction("Export…", self.export) -        fileMenu.addAction("Reload from disk", self.reload) +        fileMenu.addAction("Reload From Disk", self.reload)          fileMenu.addAction("E&xit", self.close, QKeySequence.Quit)          menuBar.addMenu(fileMenu)          editMenu = QMenu("&Edit", self) -        markColorMenu = QMenu("Flag color", self) +        markColorMenu = QMenu("Flag Color", self)          pixmap = QPixmap(24, 24)          none = markColorMenu.addAction("None", self.markColor)          none.setData(None) @@ -675,7 +684,7 @@ class MainWindow(QMainWindow):          green.setData(QColor(Qt.green))          editMenu.addMenu(markColorMenu)          editMenu.addAction("Copy", self.copy, QKeySequence.Copy) -        editMenu.addAction("Copy as component", +        editMenu.addAction("Copy As Component",                             self.copyAsComponent, "Ctrl+Alt+C")          editMenu.addAction("Paste", self.paste, QKeySequence.Paste)          editMenu.addSeparator() @@ -685,23 +694,23 @@ class MainWindow(QMainWindow):          fontMenu = QMenu("&Font", self)          # 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+G") -        fontMenu.addAction("Font &info", self.fontInfo, "Ctrl+Alt+I") -        fontMenu.addAction("Font &features", self.fontFeatures, "Ctrl+Alt+F") +        fontMenu.addAction("&Add Glyphs…", self.addGlyphs, "Ctrl+G") +        fontMenu.addAction("Font &Info", self.fontInfo, "Ctrl+Alt+I") +        fontMenu.addAction("Font &Features", self.fontFeatures, "Ctrl+Alt+F")          fontMenu.addSeparator() -        fontMenu.addAction("Sort…", self.sortGlyphs) +        fontMenu.addAction("&Sort…", self.sortGlyphs)          menuBar.addMenu(fontMenu)          pythonMenu = QMenu("&Python", self) -        pythonMenu.addAction("Scripting &window", self.scripting, "Ctrl+Alt+R") +        pythonMenu.addAction("Scripting &Window", self.scripting, "Ctrl+Alt+R")          menuBar.addMenu(pythonMenu)          windowMenu = QMenu("&Windows", self) -        action = windowMenu.addAction("&Inspector", self.inspector, "Ctrl+I") +        action = windowMenu.addAction("&Info Panel", self.infoPanel, "Ctrl+I")          # XXX: we're getting duplicate shortcut when we spawn a new window...          action.setShortcutContext(Qt.ApplicationShortcut) -        windowMenu.addAction("&Space center", self.spaceCenter, "Ctrl+Alt+S") -        windowMenu.addAction("&Groups window", self.fontGroups, "Ctrl+Alt+G") +        windowMenu.addAction("&Metrics Window", self.metrics, "Ctrl+Alt+S") +        windowMenu.addAction("&Groups Window", self.groups, "Ctrl+Alt+G")          menuBar.addMenu(windowMenu)          helpMenu = QMenu("&Help", self) @@ -753,7 +762,7 @@ class MainWindow(QMainWindow):          else:              self.font = font -    def openFile(self, path=None): +    def openFile(self, path=None, stickToSelf=False):          if not path:              path, ok = QFileDialog.getOpenFileName(                  self, "Open File", '', @@ -765,7 +774,7 @@ class MainWindow(QMainWindow):              if ".plist" in path:                  path = os.path.dirname(path)              for window in QApplication.topLevelWidgets(): -                if (isinstance(window, MainWindow) +                if (isinstance(window, MainWindow) and window._font is not None                          and window._font.path == path):                      window.raise_()                      return @@ -774,8 +783,11 @@ class MainWindow(QMainWindow):              except:                  print(traceback.format_exc())                  return -            window = MainWindow(font) -            window.show() +            if not stickToSelf: +                window = MainWindow(font) +                window.show() +            else: +                self.font = font      def openRecentFont(self):          fontPath = self.sender().toolTip() @@ -822,12 +834,12 @@ class MainWindow(QMainWindow):          try:              from ufo2fdk import haveFDK, OTFCompiler          except Exception as e: -            errorMessage = QErrorMessage(self) -            errorMessage.showMessage(e) +            title = e.__class__.__name__ +            QMessageBox.critical(self, title, str(e))              return          if not haveFDK(): -            errorMessage = QErrorMessage(self) -            errorMessage.showMessage("The Adobe FDK could not be found.") +            QMessageBox.critical(self, "Missing dependency", "The Adobe FDK " +                                 "could not be found.")              return          path, ok = QFileDialog.getSaveFileName(self, "Save File", None, @@ -1095,32 +1107,31 @@ class MainWindow(QMainWindow):          else:              self.fontFeaturesWindow.raise_() -    def spaceCenter(self): +    def metrics(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()): -            self.spaceCenterWindow = MainSpaceWindow(self.font, parent=self) -            self.spaceCenterWindow.show() +        if not (hasattr(self, 'metricsWindow') +                and self.metricsWindow.isVisible()): +            self.metricsWindow = MainMetricsWindow(self.font, parent=self) +            self.metricsWindow.show()          else: -            self.spaceCenterWindow.raise_() +            self.metricsWindow.raise_() +        # TODO: decouple          selection = self.collectionWidget.selection          if selection:              glyphs = []              for item in sorted(selection):                  glyph = self.collectionWidget.glyphs[item]                  glyphs.append(glyph) -            self.spaceCenterWindow.setGlyphs(glyphs) +            self.metricsWindow.setGlyphs(glyphs) -    def fontGroups(self): +    def groups(self):          # TODO: see up here -        if not (hasattr(self, 'fontGroupsWindow') -                and self.fontGroupsWindow.isVisible()): -            self.fontGroupsWindow = GroupsWindow(self.font, self) -            self.fontGroupsWindow.show() +        if not (hasattr(self, 'groupsWindow') +                and self.groupsWindow.isVisible()): +            self.groupsWindow = GroupsWindow(self.font, self) +            self.groupsWindow.show()          else: -            self.fontGroupsWindow.raise_() +            self.groupsWindow.raise_()      def scripting(self):          app = QApplication.instance() @@ -1132,18 +1143,18 @@ class MainWindow(QMainWindow):          else:              app.scriptingWindow.show() -    def inspector(self): +    def infoPanel(self):          app = QApplication.instance() -        if not hasattr(app, 'inspectorWindow'): -            app.inspectorWindow = InspectorWindow() -            app.inspectorWindow.show() -        elif app.inspectorWindow.isVisible(): +        if not hasattr(app, 'infoPanelWindow'): +            app.infoPanelWindow = InfoPanel() +            app.infoPanelWindow.show() +        elif app.infoPanelWindow.isVisible():              # TODO: do this only if the widget is user-visible, otherwise the              # key press feels as if it did nothing              # toggle -            app.inspectorWindow.close() +            app.infoPanelWindow.close()          else: -            app.inspectorWindow.show() +            app.infoPanelWindow.show()      def sortGlyphs(self):          sortDescriptor, ok = SortDialog.getDescriptor(self, @@ -1151,9 +1162,9 @@ class MainWindow(QMainWindow):          if ok:              self.sortDescriptor = sortDescriptor -    def addGlyph(self): +    def addGlyphs(self):          glyphs = self.collectionWidget.glyphs -        newGlyphNames, params, ok = AddGlyphDialog.getNewGlyphNames( +        newGlyphNames, params, ok = AddGlyphsDialog.getNewGlyphNames(              self, glyphs)          if ok:              sortFont = params.pop("sortFont") @@ -1171,12 +1182,19 @@ 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)) +        domain = QApplication.organizationDomain() +        text = "<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>" \ +               "<p>Version {} – Python {}.".format( +                   name, __version__, platform.python_version()) +        if domain: +            text += "<br>See <a href='http://{d}'>{d}</a> for more " \ +                    "information.</p>".format(d=domain) +        else: +            text += "</p>" +        QMessageBox.about(self, "About {}".format(name), text)  class SettingsDialog(QDialog): @@ -1188,7 +1206,8 @@ class SettingsDialog(QDialog):          self.tabWidget = QTabWidget(self)          self.tabWidget.addTab(GlyphSetTab(self), "Glyph sets") -        self.tabWidget.addTab(SpaceCenterTab(self), "Space center") +        self.tabWidget.addTab(MetricsWindowTab(self), "Metrics Window") +        self.tabWidget.addTab(MiscTab(self), "Misc")          buttonBox = QDialogButtonBox(              QDialogButtonBox.Ok | QDialogButtonBox.Cancel) @@ -1232,7 +1251,7 @@ def readGlyphSets(settings=None):  class GlyphSetTab(QWidget):      def __init__(self, parent=None): -        super(GlyphSetTab, self).__init__(parent) +        super().__init__(parent)          settings = QSettings()          self.defaultGlyphSetBox = QCheckBox("Default glyph set:", self) @@ -1366,16 +1385,16 @@ class GlyphSetTab(QWidget):                  settings.setValue("settings/defaultGlyphSet", defaultGlyphSet) -class SpaceCenterTab(QTabWidget): +class MetricsWindowTab(QTabWidget):      def __init__(self, parent=None): -        super(SpaceCenterTab, self).__init__(parent) +        super().__init__(parent)          settings = QSettings()          self.inputTextLabel = QLabel("Default text:", self)          self.inputTextList = QListWidget(self)          self.inputTextList.setDragDropMode(QAbstractItemView.InternalMove) -        entries = settings.value("spaceCenter/comboBoxItems", comboBoxItems, +        entries = settings.value("metricsWindow/comboBoxItems", comboBoxItems,                                   str)          for entry in entries:              item = QListWidgetItem(entry, self.inputTextList) @@ -1414,4 +1433,26 @@ class SpaceCenterTab(QTabWidget):              item = self.inputTextList.item(i)              entries.append(item.text())          settings = QSettings() -        settings.setValue("spaceCenter/comboBoxItems", entries) +        settings.setValue("metricsWindow/comboBoxItems", entries) + + +class MiscTab(QTabWidget): + +    def __init__(self, parent=None): +        super().__init__(parent) + +        settings = QSettings() +        loadRecentFile = settings.value("core/loadRecentFile", False, bool) +        self.loadRecentFileBox = QCheckBox("Load most recent file on start", +                                           self) +        self.loadRecentFileBox.setChecked(loadRecentFile) + +        layout = QVBoxLayout(self) +        l = 0 +        layout.addWidget(self.loadRecentFileBox, l) +        self.setLayout(layout) + +    def writeValues(self): +        settings = QSettings() +        loadRecentFile = self.loadRecentFileBox.isChecked() +        settings.setValue("core/loadRecentFile", loadRecentFile) diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py index 87232c3..c9b483a 100644 --- a/Lib/defconQt/glyphView.py +++ b/Lib/defconQt/glyphView.py @@ -181,7 +181,7 @@ class AddLayerDialog(QDialog):          layout.addWidget(layerNameLabel, l, 0)          layout.addWidget(self.layerNameEdit, l, 1)          l += 1 -        layout.addWidget(buttonBox, l, 2) +        layout.addWidget(buttonBox, l, 0, 1, 2)          self.setLayout(layout)      @classmethod @@ -302,7 +302,7 @@ class MainGfxWindow(QMainWindow):          menuBar.addMenu(fileMenu)          glyphMenu = QMenu("&Glyph", self) -        glyphMenu.addAction("&Jump", self.changeGlyph, "J") +        glyphMenu.addAction("&Go to…", self.changeGlyph, "G")          menuBar.addMenu(glyphMenu)          self._displaySettings = DisplayStyleSettings( diff --git a/Lib/defconQt/spaceCenter.py b/Lib/defconQt/metricsWindow.py index e360653..27689ab 100644 --- a/Lib/defconQt/spaceCenter.py +++ b/Lib/defconQt/metricsWindow.py @@ -1,6 +1,7 @@  from defconQt import icons_db  # noqa -from defconQt.glyphCollectionView import cellSelectionColor +from defconQt.glyphCollectionView import arrowKeys, cellSelectionColor  from defconQt.glyphView import MainGfxWindow +from defconQt.objects.defcon import TGlyph  from getpass import getuser  from PyQt5.QtCore import QEvent, QSettings, QSize, Qt  from PyQt5.QtGui import ( @@ -10,6 +11,7 @@ from PyQt5.QtWidgets import (      QAbstractItemView, QActionGroup, QApplication, QComboBox, QLineEdit, QMenu,      QPushButton, QScrollArea, QStyledItemDelegate, QTableWidget,      QTableWidgetItem, QVBoxLayout, QSizePolicy, QToolBar, QWidget) +import re  comboBoxItems = [      "abcdefghijklmnopqrstuvwxyz", @@ -23,12 +25,19 @@ defaultPointSize = 150  glyphSelectionColor = QColor(cellSelectionColor)  glyphSelectionColor.setAlphaF(.09) +escapeRep = { +    "//": "/slash ", +    "\\n": "\u2029", +} +escapeRep = dict((re.escape(k), v) for k, v in escapeRep.items()) +escapeRe = re.compile("|".join(escapeRep.keys())) -class MainSpaceWindow(QWidget): + +class MainMetricsWindow(QWidget):      def __init__(self, font, string=None, pointSize=defaultPointSize,                   parent=None): -        super(MainSpaceWindow, self).__init__(parent, Qt.Window) +        super().__init__(parent, Qt.Window)          if string is None:              try: @@ -65,7 +74,7 @@ class MainSpaceWindow(QWidget):          self.font.info.addObserver(self, "_fontInfoChanged", "Info.Changed") -        self.setWindowTitle("Space center – %s %s" % ( +        self.setWindowTitle("Metrics Window – %s %s" % (              self.font.info.familyName, self.font.info.styleName))      def setupFileMenu(self): @@ -77,41 +86,45 @@ class MainSpaceWindow(QWidget):      def close(self):          self.font.info.removeObserver(self, "Info.Changed")          self._unsubscribeFromGlyphs() -        super(MainSpaceWindow, self).close() +        super().close()      def _fontInfoChanged(self, notification):          self.canvas.fetchFontMetrics()          self.canvas.update()      def _glyphChanged(self, notification): -        self.canvas.update() -        self.table.updateCells() +        if not self.canvas._editing: +            self.canvas.update() +        if not self.table._editing: +            self.table.updateCells(self.canvas._editing)      def _glyphOpened(self, glyph):          glyphViewWindow = MainGfxWindow(glyph, self.parent())          glyphViewWindow.show()      def _textChanged(self): +        def fetchGlyphs(glyphNames, leftGlyphs=[], rightGlyphs=[]): +            ret = [] +            for name in glyphNames: +                if name == "\u2029": +                    glyph = TGlyph() +                    glyph.unicode = 2029 +                    ret.append(glyph) +                elif name in self.font: +                    ret.extend(leftGlyphs) +                    ret.append(self.font[name]) +                    ret.extend(rightGlyphs) +            return ret +          # unsubscribe from the old glyphs          self._unsubscribeFromGlyphs()          # subscribe to the new glyphs          left = self.textToGlyphNames(self.toolbar.leftTextField.text())          newText = self.textToGlyphNames(self.toolbar.textField.currentText())          right = self.textToGlyphNames(self.toolbar.rightTextField.text()) -        leftGlyphs = [] -        for name in left: -            if name in self.font: -                leftGlyphs.append(self.font[name]) -        rightGlyphs = [] -        for name in right: -            if name in self.font: -                rightGlyphs.append(self.font[name]) -        finalGlyphs = [] -        for name in newText: -            if name in self.font: -                finalGlyphs.extend(leftGlyphs) -                finalGlyphs.append(self.font[name]) -                finalGlyphs.extend(rightGlyphs) +        leftGlyphs = fetchGlyphs(left) +        rightGlyphs = fetchGlyphs(right) +        finalGlyphs = fetchGlyphs(newText, leftGlyphs, rightGlyphs)          self._subscribeToGlyphs(finalGlyphs)          # set the records into the view          self.canvas.setGlyphs(self.glyphs) @@ -128,8 +141,8 @@ class MainSpaceWindow(QWidget):                  glyphNames.append("".join(compileStack))          app = QApplication.instance() -        # escape // -        text = text.replace("//", "/slash ") +        # escape //, \n +        text = escapeRe.sub(lambda m: escapeRep[re.escape(m.group(0))], text)          #          glyphNames = []          compileStack = None @@ -157,7 +170,11 @@ class MainSpaceWindow(QWidget):                      compileStack.append(c)              # adding a character that needs to be converted to a glyph name.              else: -                glyphName = self.font.unicodeData.glyphNameForUnicode(ord(c)) +                uni = ord(c) +                if uni == 0x2029: +                    glyphName = c +                else: +                    glyphName = self.font.unicodeData.glyphNameForUnicode(uni)                  glyphNames.append(glyphName)          # catch remaining compile.          if compileStack is not None and compileStack: @@ -217,7 +234,7 @@ class FontToolBar(QToolBar):          # XXX: had to use Maximum because Preferred did entend the widget(?)          self.textField.setSizePolicy(QSizePolicy.Expanding,                                       QSizePolicy.Maximum) -        items = QSettings().value("spaceCenter/comboBoxItems", comboBoxItems, +        items = QSettings().value("metricsWindow/comboBoxItems", comboBoxItems,                                    str)          self.textField.addItems(items)          self.rightTextField = QLineEdit(self) @@ -314,6 +331,9 @@ class GlyphsCanvas(QWidget):      def __init__(self, font, pointSize=defaultPointSize, parent=None):          super(GlyphsCanvas, self).__init__(parent) +        self.setAttribute(Qt.WA_KeyCompression) +        # TODO: should we take focus by tabbing +        self.setFocusPolicy(Qt.ClickFocus)          # XXX: make canvas font-agnostic as in defconAppkit and use          # glyph.getParent() instead          self.font = font @@ -322,6 +342,7 @@ class GlyphsCanvas(QWidget):          self.ptSize = pointSize          self.calculateScale()          self.padding = 10 +        self._editing = False          self._showKerning = False          self._showMetrics = False          self._verticalFlip = False @@ -487,10 +508,36 @@ class GlyphsCanvas(QWidget):                  return kerning[pair]          return 0 +    def _arrowKeyPressEvent(self, event): +        key = event.key() +        modifiers = event.modifiers() +        self._editing = True +        if self._selected is not None: +            glyph = self.glyphs[self._selected] +            # TODO: not really DRY w other widgets +            delta = event.count() +            if modifiers & Qt.ShiftModifier: +                delta *= 10 +                if modifiers & Qt.ControlModifier: +                    delta *= 10 +            if key == Qt.Key_Left: +                delta = -delta +            if modifiers & Qt.AltModifier: +                if glyph.leftMargin is not None: +                    glyph.leftMargin += delta +            else: +                glyph.width += delta +        self._editing = False +        event.accept() + +    def keyPressEvent(self, event): +        key = event.key() +        if key in arrowKeys: +            self._arrowKeyPressEvent(event) +        else: +            super().keyPressEvent(event) +      def mousePressEvent(self, event): -        # Take focus to quit eventual cell editing -        # XXX: shouldnt set focus if we are in input field... -        self.setFocus(Qt.MouseFocusReason)          if event.button() == Qt.LeftButton:              # XXX: investigate, baselineShift is unused              # if self._verticalFlip: @@ -527,6 +574,10 @@ class GlyphsCanvas(QWidget):                  self.selectionChangedCallback(self._selected)              event.accept()              self.update() +            # restore focus to ourselves, the table widget did take it when we +            # sent notification +            # TODO: maybe not set focus on notifiee instead +            self.setFocus(Qt.MouseFocusReason)          else:              super(GlyphsCanvas, self).mousePressEvent(event) @@ -578,9 +629,8 @@ class GlyphsCanvas(QWidget):                      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()): +            if (self._wrapLines and cur_width + gWidth + kern + +                    2 * self.padding > self.width()) or glyph.unicode == 2029:                  painter.translate(-cur_width, self.ptSize * self._lineHeight)                  if self._showMetrics:                      paintLineMarks(painter) @@ -688,6 +738,7 @@ class SpaceTable(QTableWidget):          self.setColumnWidth(0, self._cellWidth)          self.horizontalHeader().hide()          self.verticalHeader().hide() +        self._coloredColumn = None          # always show a scrollbar to fix layout          self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) @@ -703,20 +754,21 @@ class SpaceTable(QTableWidget):          self.setEditTriggers(QAbstractItemView.CurrentChanged)          self._editing = False          self.selectionChangedCallback = None -        self._coloredColumn = None      def setGlyphs(self, newGlyphs):          self.glyphs = newGlyphs          # TODO: we don't need to reallocate cells, split alloc and fill          self.updateCells() -    def updateCells(self): +    def updateCells(self, keepColor=False):          self.blockSignals(True) -        if self._editing: -            coloredColumn = self._coloredColumn +        self.setEditTriggers(QAbstractItemView.NoEditTriggers) +        coloredColumn = self._coloredColumn          self.fillGlyphs() -        if self._editing: -            self._coloredColumn = coloredColumn +        if keepColor and coloredColumn is not None and \ +                coloredColumn < self.columnCount(): +            self.colorColumn(coloredColumn) +        self.setEditTriggers(QAbstractItemView.CurrentChanged)          self.blockSignals(False)      def _cellEdited(self, row, col): @@ -808,6 +860,7 @@ class SpaceTable(QTableWidget):              # item.setTextAlignment(Qt.AlignCenter)              return item +        self._coloredColumn = None          self.setColumnCount(len(self.glyphs) + 1)          for index, glyph in enumerate(self.glyphs):              # TODO: see about allowing glyph name edit here | 
