diff options
| author | Adrien Tétar | 2015-06-01 23:31:16 +0200 | 
|---|---|---|
| committer | Adrien Tétar | 2015-06-01 23:31:16 +0200 | 
| commit | 153f7a7f706b68c463cae2f6f0148bf73c1f74de (patch) | |
| tree | d2f9b75a642cafb8b3edb2785f482f2f674b2428 /Lib/defconQt | |
| parent | 0897c38388d900fc6c181a460a0917e28cd6e269 (diff) | |
| download | trufont-153f7a7f706b68c463cae2f6f0148bf73c1f74de.tar.bz2 | |
improve groups window, fontView tweaks, featureTextEditor smart block fixes
Diffstat (limited to 'Lib/defconQt')
| -rw-r--r-- | Lib/defconQt/featureTextEditor.py | 37 | ||||
| -rw-r--r-- | Lib/defconQt/fontView.py | 55 | ||||
| -rw-r--r-- | Lib/defconQt/groupsView.py | 71 | 
3 files changed, 129 insertions, 34 deletions
diff --git a/Lib/defconQt/featureTextEditor.py b/Lib/defconQt/featureTextEditor.py index 0786c03..9571229 100644 --- a/Lib/defconQt/featureTextEditor.py +++ b/Lib/defconQt/featureTextEditor.py @@ -148,7 +148,10 @@ class TextEditor(QPlainTextEdit):              cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, len(self._indent))              if cursor.selectedText() == self._indent:                  indent += 1 -            cursor.movePosition(QTextCursor.NoMove) +            else: break +            # Now move the anchor back to the position() +            #cursor.movePosition(QTextCursor.NoMove) # shouldn't NoMove work here? +            cursor.setPosition(cursor.position())              lineLength -= 1          cursor.movePosition(QTextCursor.EndOfLine)          return indent @@ -210,6 +213,22 @@ class TextEditor(QPlainTextEdit):          else:              super(TextEditor, self).keyPressEvent(event) +keywordPatterns = ["\\bAscender\\b", "\\bAttach\\b", "\\bCapHeight\\b", "\\bCaretOffset\\b", "\\bCodePageRange\\b", +    "\\bDescender\\b", "\\bFontRevision\\b", "\\bGlyphClassDef\\b", "\\bHorizAxis.BaseScriptList\\b", +    "\\bHorizAxis.BaseTagList\\b", "\\bHorizAxis.MinMax\\b", "\\bIgnoreBaseGlyphs\\b", "\\bIgnoreLigatures\\b", +    "\\bIgnoreMarks\\b", "\\bLigatureCaretByDev\\b", "\\bLigatureCaretByIndex\\b", "\\bLigatureCaretByPos\\b", +    "\\bLineGap\\b", "\\bMarkAttachClass\\b", "\\bMarkAttachmentType\\b", "\\bNULL\\b", "\\bPanose\\b", "\\bRightToLeft\\b", +    "\\bTypoAscender\\b", "\\bTypoDescender\\b", "\\bTypoLineGap\\b", "\\bUnicodeRange\\b", "\\bUseMarkFilteringSet\\b", +    "\\bVendor\\b", "\\bVertAdvanceY\\b", "\\bVertAxis.BaseScriptList\\b", "\\bVertAxis.BaseTagList\\b", +    "\\bVertAxis.MinMax\\b", "\\bVertOriginY\\b", "\\bVertTypoAscender\\b", "\\bVertTypoDescender\\b", +    "\\bVertTypoLineGap\\b", "\\bXHeight\\b", "\\banchorDef\\b", "\\banchor\\b", "\\banonymous\\b", "\\banon\\b", +    "\\bby\\b", "\\bcontour\\b", "\\bcursive\\b", "\\bdevice\\b", "\\benumerate\\b", "\\benum\\b", "\\bexclude_dflt\\b", +    "\\bfeatureNames\\b", "\\bfeature\\b", "\\bfrom\\b", "\\bignore\\b", "\\binclude_dflt\\b", "\\binclude\\b", +    "\\blanguagesystem\\b", "\\blanguage\\b", "\\blookupflag\\b", "\\blookup\\b", "\\bmarkClass\\b", "\\bmark\\b", +    "\\bnameid\\b", "\\bname\\b", "\\bparameters\\b", "\\bposition\\b", "\\bpos\\b", "\\brequired\\b", "\\breversesub\\b", +    "\\brsub\\b", "\\bscript\\b", "\\bsizemenuname\\b", "\\bsubstitute\\b", "\\bsubtable\\b", "\\bsub\\b", "\\btable\\b", +    "\\buseExtension\\b", "\\bvalueRecordDef\\b", "\\bwinAscent\\b", "\\bwinDescent\\b"] +  class Highlighter(QSyntaxHighlighter):      def __init__(self, parent=None):          super(Highlighter, self).__init__(parent) @@ -218,22 +237,6 @@ class Highlighter(QSyntaxHighlighter):          keywordFormat.setForeground(QColor(30, 150, 220))          keywordFormat.setFontWeight(QFont.Bold) -        keywordPatterns = ["\\bAscender\\b", "\\bAttach\\b", "\\bCapHeight\\b", "\\bCaretOffset\\b", "\\bCodePageRange\\b", -            "\\bDescender\\b", "\\bFontRevision\\b", "\\bGlyphClassDef\\b", "\\bHorizAxis.BaseScriptList\\b", -            "\\bHorizAxis.BaseTagList\\b", "\\bHorizAxis.MinMax\\b", "\\bIgnoreBaseGlyphs\\b", "\\bIgnoreLigatures\\b", -            "\\bIgnoreMarks\\b", "\\bLigatureCaretByDev\\b", "\\bLigatureCaretByIndex\\b", "\\bLigatureCaretByPos\\b", -            "\\bLineGap\\b", "\\bMarkAttachClass\\b", "\\bMarkAttachmentType\\b", "\\bNULL\\b", "\\bPanose\\b", "\\bRightToLeft\\b", -            "\\bTypoAscender\\b", "\\bTypoDescender\\b", "\\bTypoLineGap\\b", "\\bUnicodeRange\\b", "\\bUseMarkFilteringSet\\b", -            "\\bVendor\\b", "\\bVertAdvanceY\\b", "\\bVertAxis.BaseScriptList\\b", "\\bVertAxis.BaseTagList\\b", -            "\\bVertAxis.MinMax\\b", "\\bVertOriginY\\b", "\\bVertTypoAscender\\b", "\\bVertTypoDescender\\b", -            "\\bVertTypoLineGap\\b", "\\bXHeight\\b", "\\banchorDef\\b", "\\banchor\\b", "\\banonymous\\b", "\\banon\\b", -            "\\bby\\b", "\\bcontour\\b", "\\bcursive\\b", "\\bdevice\\b", "\\benumerate\\b", "\\benum\\b", "\\bexclude_dflt\\b", -            "\\bfeatureNames\\b", "\\bfeature\\b", "\\bfrom\\b", "\\bignore\\b", "\\binclude_dflt\\b", "\\binclude\\b", -            "\\blanguagesystem\\b", "\\blanguage\\b", "\\blookupflag\\b", "\\blookup\\b", "\\bmarkClass\\b", "\\bmark\\b", -            "\\bnameid\\b", "\\bname\\b", "\\bparameters\\b", "\\bposition\\b", "\\bpos\\b", "\\brequired\\b", "\\breversesub\\b", -            "\\brsub\\b", "\\bscript\\b", "\\bsizemenuname\\b", "\\bsubstitute\\b", "\\bsubtable\\b", "\\bsub\\b", "\\btable\\b", -            "\\buseExtension\\b", "\\bvalueRecordDef\\b", "\\bwinAscent\\b", "\\bwinDescent\\b"] -          self.highlightingRules = [(QRegExp("%s%s%s" % ("(", "|".join(keywordPatterns), ")")), keywordFormat)]          singleLineCommentFormat = QTextCharFormat() diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index 6168ffd..64019f2 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -8,6 +8,9 @@ from PyQt5.QtCore import *  from PyQt5.QtGui import *  from PyQt5.QtWidgets import * +cannedDesign = [ +    dict(type="cannedDesign", allowPseudoUnicode=True) +]  glyphSortDescriptors = [      dict(type="alphabetical", allowPseudoUnicode=True),      dict(type="category", allowPseudoUnicode=True), @@ -16,9 +19,6 @@ glyphSortDescriptors = [      dict(type="suffix", allowPseudoUnicode=True),      dict(type="decompositionBase", allowPseudoUnicode=True)  ] -cannedDesign = [ -    dict(type="cannedDesign", allowPseudoUnicode=True) -]  cellGridColor = QColor(130, 130, 130)  cellHeaderBaseColor = QColor(230, 230, 230) @@ -37,26 +37,31 @@ class CharacterWidget(QWidget):          super(CharacterWidget, self).__init__(parent)          self.font = font -        #self.glyphs = [font[k] for k in font.unicodeData.sortGlyphNames(font.keys(), glyphSortDescriptors)] -        self.glyphs = [font[k] for k in font.unicodeData.sortGlyphNames(font.keys(), cannedDesign)] +        self.glyphs = []          self.scrollArea = scrollArea          self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) +        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)          self.squareSize = squareSize          self.columns = 10          self._selection = set()          self.lastKey = -1          self.moveKey = -1 +        self._maybeDragPosition = None          self.setFocusPolicy(Qt.ClickFocus)      def updateFont(self, font):          self.font = font -        self.glyphs = [font[k] for k in font.unicodeData.sortGlyphNames(font.keys(), cannedDesign)] +        self.updateGlyphsFromFont() +     +    def updateGlyphsFromFont(self, descriptor=cannedDesign): +        self.glyphs = [self.font[k] for k in self.font.unicodeData.sortGlyphNames(self.font.keys(), descriptor)]          self.adjustSize()          self.update() -    def updateGlyphs(self): -        self.glyphs = [self.font[k] for k in self.font.unicodeData.sortGlyphNames(self.font.keys(), cannedDesign)] +    def setGlyphs(self, glyphs): +        self.glyphs = glyphs +        self._selection = set()          self.adjustSize()          self.update() @@ -76,7 +81,11 @@ class CharacterWidget(QWidget):      def markSelection(self, color):          for key in self._selection:              glyph = self.glyphs[key] -            glyph.lib["public.markColor"] = ",".join(str(c) for c in color.getRgbF()) +            if color is None: +                if "public.markColor" in glyph.lib: +                    del glyph.lib["public.markColor"] +            else: +                glyph.lib["public.markColor"] = ",".join(str(c) for c in color.getRgbF())          self.update()      # TODO: eventually get rid of the signal @@ -101,6 +110,11 @@ class CharacterWidget(QWidget):              self.computeCharacterSelected()              self.update()              event.accept() +        elif event.key() == Qt.Key_D and event.modifiers() & Qt.ControlModifier: +            self._selection = set() +            self.computeCharacterSelected() +            self.update() +            event.accept()          else:              super(CharacterWidget, self).keyPressEvent(event) @@ -112,6 +126,10 @@ class CharacterWidget(QWidget):              if modifiers & Qt.ShiftModifier and len(self._selection)==1:                  self.lastKey = self._selection.pop()                  self.moveKey = key +            elif key in self._selection: +                self._maybeDragPosition = event.pos() +                event.accept() +                return              else:                  self.lastKey = key                  self.moveKey = self.lastKey @@ -126,6 +144,19 @@ class CharacterWidget(QWidget):      def mouseMoveEvent(self, event):          if event.buttons() & Qt.LeftButton: +            if self._maybeDragPosition is not None: +                if ((event.pos() - self._maybeDragPosition).manhattanLength() \ +                    < QApplication.startDragDistance()): return +                # TODO: needs ordering or not? +                glyphList = " ".join((self.glyphs[key].name for key in self._selection)) +                drag = QDrag(self) +                mimeData = QMimeData() +                mimeData.setData("text/plain", glyphList) +                drag.setMimeData(mimeData) +                 +                dropAction = drag.exec_() +                event.accept() +                return              key = (event.y() // self.squareSize) * self.columns + min(event.x() // self.squareSize, self.columns-1)              if key > len(self.glyphs)-1: return              self.moveKey = key @@ -138,6 +169,7 @@ class CharacterWidget(QWidget):      def mouseReleaseEvent(self, event):          if event.button() == Qt.LeftButton: +            self._maybeDragPosition = None              lastKey = self.lastKey if self.lastKey < len(self.glyphs) else len(self.glyphs)-1              moveKey = self.moveKey if self.moveKey < len(self.glyphs) else len(self.glyphs)-1              if event.modifiers() & Qt.ControlModifier: @@ -292,6 +324,7 @@ class MainWindow(QMainWindow):          self.scrollArea = QScrollArea(self)          squareSize = 56          self.characterWidget = CharacterWidget(self.font, squareSize, self.scrollArea, self) +        self.characterWidget.updateGlyphsFromFont()          self.scrollArea.setWidget(self.characterWidget)          # TODO: make shortcuts platform-independent @@ -312,6 +345,8 @@ class MainWindow(QMainWindow):          markColorMenu = QMenu("Mark color", self)          pixmap = QPixmap(24, 24) +        none = markColorMenu.addAction("None", self.colorFill) +        none.setData(None)          red = markColorMenu.addAction("Red", self.colorFill)          pixmap.fill(Qt.red)          red.setIcon(QIcon(pixmap)) @@ -504,7 +539,7 @@ class MainWindow(QMainWindow):          if ok and gName != '':              self.font.newGlyph(gName)              self.font[gName].width = 500 -            self.characterWidget.updateGlyphs() +            self.characterWidget.updateGlyphsFromFont()      def about(self):          QMessageBox.about(self, "About Me", diff --git a/Lib/defconQt/groupsView.py b/Lib/defconQt/groupsView.py index db4645f..a88d9eb 100644 --- a/Lib/defconQt/groupsView.py +++ b/Lib/defconQt/groupsView.py @@ -1,28 +1,64 @@ +from fontView import CharacterWidget  from PyQt5.QtCore import *  from PyQt5.QtGui import *  from PyQt5.QtWidgets import * +class GroupCharacterWidget(CharacterWidget): +    def __init__(self, font, squareSize=56, scrollArea=None, parent=None): +        super(GroupCharacterWidget, self).__init__(font, squareSize, scrollArea, parent) +        self.columns = 8 +        self.scrollArea.setAcceptDrops(True) +        self.scrollArea.dragEnterEvent = self.pipeDragEnterEvent +        self.scrollArea.dropEvent = self.pipeDropEvent +     +    def keyPressEvent(self, event): +        if event.key() == Qt.Key_Delete: +            self.parent().parent().parent().characterDeleteEvent(self._selection) +            event.accept() +        else: +            super(GroupCharacterWidget, 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.) +        if (event.mimeData().hasFormat("text/plain")): +            event.acceptProposedAction() +     +    def pipeDropEvent(self, event): +        self.parent().parent().parent().characterDropEvent(event) +  class GroupsWindow(QWidget):      def __init__(self, font, parent=None):          super(GroupsWindow, self).__init__(parent, Qt.Window)          self.font = font -        self.groups = sorted(font.groups.keys(), key=lambda t: t[0])          self.groupsList = QListWidget(self) -        #self.groupsList.addItems(self.font.groups.keys()) -        #self.groupsList.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed) +        self.groupsList.setSelectionMode(QAbstractItemView.SingleSelection) +        self.groupsList.setSortingEnabled(True)          for groupName in self.font.groups.keys():              item = QListWidgetItem(groupName, self.groupsList) -            #item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsEditable)              item.setFlags(item.flags() | Qt.ItemIsEditable)          self.groupsList.itemChanged.connect(self._groupRenamed) -        layout = QVBoxLayout(self) +        self.scrollArea = QScrollArea(self) +        self.characterWidget = GroupCharacterWidget(self.font, scrollArea=self.scrollArea, parent=self) +        self.scrollArea.setWidget(self.characterWidget) +        self.groupsList.currentItemChanged.connect(self._groupChanged) +         +        layout = QHBoxLayout(self)          layout.addWidget(self.groupsList) +        layout.addWidget(self.scrollArea)          self.setLayout(layout)          self.setWindowTitle("%s%s%s%s" % ("Groups window – ", self.font.info.familyName, " ", self.font.info.styleName)) +    def _groupChanged(self): +        currentGroup = self.groupsList.currentItem().text() +        glyphs = [] +        for gName in self.font.groups[currentGroup]: +            glyphs.append(self.font[gName]) +        self.characterWidget.setGlyphs(glyphs) +          def _groupRenamed(self):          cur = self.groupsList.currentItem()          # XXX: perf? @@ -30,5 +66,26 @@ class GroupsWindow(QWidget):          newKey = cur.text()          self.font.groups[newKey] = self.font.groups[self.groups[index]]          del self.font.groups[self.groups[index]] -        self.groups[index] = newKey -        #print(self.groupsList.currentItem().text())
\ No newline at end of file +        #print(self.groupsList.currentItem().text()) +     +    def characterDeleteEvent(self, selection): +        currentGroup = self.groupsList.currentItem().text() +        currentGroupList = self.font.groups[currentGroup] +        # relying on ordered group elements +        # reverse to not change index of smaller elements +        for key in sorted(selection, reverse=True): +            del currentGroupList[key] +        self.font.groups[currentGroup] = currentGroupList +        self.characterWidget.update() +     +    def characterDropEvent(self, event): +        currentGroup = self.groupsList.currentItem().text() +        glyphNames = event.mimeData().text().split(" ") +        for gName in glyphNames: +            # Due to defcon limitations, we must fetch and update for the +            # notification to pass through +            currentGroupList = self.font.groups[currentGroup] +            currentGroupList.append(gName) +            self.font.groups[currentGroup] = currentGroupList +        event.acceptProposedAction() +        self._groupChanged()
\ No newline at end of file  | 
