diff options
| author | Adrien Tétar | 2015-10-10 18:41:33 +0200 |
|---|---|---|
| committer | Adrien Tétar | 2015-10-10 18:41:33 +0200 |
| commit | bd72f20da531207c16f5967101a230ca12e84657 (patch) | |
| tree | f64430b3b10d44195539ffcdd79ccb5dfd9596b1 | |
| parent | a37c85e39a38fe11efbd7df3c1cf4fce5a84a7c9 (diff) | |
| download | trufont-bd72f20da531207c16f5967101a230ca12e84657.tar.bz2 | |
glyphView: layers support, fontView: change UFO open behavior, various
| -rw-r--r-- | Lib/defconQt/fontView.py | 25 | ||||
| -rw-r--r-- | Lib/defconQt/glyphCollectionView.py | 18 | ||||
| -rw-r--r-- | Lib/defconQt/glyphView.py | 128 | ||||
| -rw-r--r-- | Lib/defconQt/spaceCenter.py | 2 |
4 files changed, 137 insertions, 36 deletions
diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index 38cc054..e8e110f 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -5,7 +5,7 @@ from defconQt.glyphView import MainGfxWindow from defconQt.groupsView import GroupsWindow from defconQt.scriptingWindow import MainScriptingWindow from defconQt.objects.defcon import CharacterSet, TFont, TGlyph -from defcon import Component +from defcon import Color, Component from defconQt.spaceCenter import MainSpaceWindow # TODO: remove globs when things start to stabilize from PyQt5.QtCore import * @@ -551,7 +551,6 @@ class MainWindow(QMainWindow): self.font = font self.collectionWidget.characterSelectedCallback = self._selectionChanged self.collectionWidget.doubleClickCallback = self._glyphOpened - # XXX: should spaceCenter have this functionality as well? # TODO: should default be True or False? self.collectionWidget.updateCurrentGlyph = True self.collectionWidget.setFocus() @@ -660,8 +659,12 @@ class MainWindow(QMainWindow): def openFile(self, path=None): if not path: + if sys.platform == "darwin": + fileFormats = "UFO Fonts (*.ufo)" + else: + fileFormats = "UFO Fonts (metainfo.plist)" path, ok = QFileDialog.getOpenFileName(self, "Open File", '', - "UFO Fonts (metainfo.plist)") + fileFormats) if not ok: return if path: if ".plist" in path: @@ -781,14 +784,13 @@ class MainWindow(QMainWindow): def maybeSaveBeforeExit(self): if self.font.dirty: - title = "Me" if self.font.path is not None: # TODO: maybe cache this font name in the Font 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, title, body, + 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) @@ -913,11 +915,7 @@ class MainWindow(QMainWindow): glyphs = self.collectionWidget.glyphs for key in self.collectionWidget.selection: glyph = glyphs[key] - 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()) + glyph.markColor = Color(color.getRgbF() if color is not None else None) def _fontChanged(self, notification): self.collectionWidget.update() @@ -1051,11 +1049,12 @@ class MainWindow(QMainWindow): self.sortDescriptor = self.sortDescriptor def about(self): - QMessageBox.about(self, "About Me", - "<h3>About Me</h3>" \ + 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>") + "package.</p>".format(name)) class SettingsDialog(QDialog): def __init__(self, parent=None): diff --git a/Lib/defconQt/glyphCollectionView.py b/Lib/defconQt/glyphCollectionView.py index 687d76f..81d35f9 100644 --- a/Lib/defconQt/glyphCollectionView.py +++ b/Lib/defconQt/glyphCollectionView.py @@ -399,18 +399,12 @@ class GlyphCollectionWidget(QWidget): linesColor = cellHeaderHighlightLineColor # mark color if not glyph.template: - # TODO: fetch via defcon dict - if "public.markColor" in glyph.lib: - colorStr = glyph.lib["public.markColor"].split(",") - if len(colorStr) == 4: - comp = [] - for c in colorStr: - comp.append(float(c.strip())) - markColor = QColor.fromRgbF(*comp) - 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.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) diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py index d7968ed..02a6994 100644 --- a/Lib/defconQt/glyphView.py +++ b/Lib/defconQt/glyphView.py @@ -125,7 +125,7 @@ class AddAnchorDialog(QDialog): self.setLayout(layout) @classmethod - def getNewAnchorData(cls, parent, pos=None): + def getNewAnchorName(cls, parent, pos=None): dialog = cls(pos, parent) result = dialog.exec_() name = dialog.anchorNameEdit.text() @@ -138,6 +138,36 @@ class AddComponentDialog(GotoDialog): 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) + self.setWindowTitle("Add layer…") + + layout = QGridLayout(self) + + layerNameLabel = QLabel("Layer name:", self) + self.layerNameEdit = QLineEdit(self) + self.layerNameEdit.setFocus(True) + + buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + buttonBox.accepted.connect(self.accept) + buttonBox.rejected.connect(self.reject) + + l = 0 + layout.addWidget(layerNameLabel, l, 0) + layout.addWidget(self.layerNameEdit, l, 1) + l += 1 + layout.addWidget(buttonBox, l, 2) + self.setLayout(layout) + + @classmethod + def getNewLayerName(cls, parent): + dialog = cls(parent) + result = dialog.exec_() + name = dialog.layerNameEdit.text() + return (name, result) + class MainGfxWindow(QMainWindow): def __init__(self, glyph, parent=None): super(MainGfxWindow, self).__init__(parent) @@ -157,6 +187,7 @@ class MainGfxWindow(QMainWindow): toolBar = QToolBar(self) toolBar.setMovable(False) + toolBar.setContentsMargins(2, 0, 2, 0) selectionToolButton = toolBar.addAction("Selection", self.view.setSceneSelection) selectionToolButton.setCheckable(True) selectionToolButton.setChecked(True) @@ -170,6 +201,11 @@ class MainGfxWindow(QMainWindow): knifeToolButton = toolBar.addAction("Knife", self.view.setSceneKnife) knifeToolButton.setCheckable(True) knifeToolButton.setIcon(QIcon("defconQt/resources/cut.svg")) + # http://www.setnode.com/blog/right-aligning-a-button-in-a-qtoolbar/ + spacer = QWidget() + spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + toolBar.addWidget(spacer) + toolBar.addWidget(self.view.currentLayerBox()) toolsGroup = QActionGroup(self) toolsGroup.addAction(selectionToolButton) toolsGroup.addAction(penToolButton) @@ -177,10 +213,6 @@ class MainGfxWindow(QMainWindow): toolsGroup.addAction(knifeToolButton) self.addToolBar(toolBar) - self.setCentralWidget(self.view) - self.setWindowTitle(glyph.name, glyph.getParent()) - self.adjustSize() - self.setContextMenuPolicy(Qt.ActionsContextMenu) createAnchorAction = QAction("Add Anchor…", self) createAnchorAction.triggered.connect(self.view.createAnchor) @@ -189,6 +221,10 @@ class MainGfxWindow(QMainWindow): createComponentAction.triggered.connect(self.view.createComponent) self.addAction(createComponentAction) + self.setCentralWidget(self.view) + self.setWindowTitle(glyph.name, glyph.getParent()) + self.adjustSize() + def changeGlyph(self): glyph = self.view._glyph newGlyph, ok = GotoDialog.getNewGlyph(self, glyph) @@ -748,6 +784,12 @@ class GlyphScene(QGraphicsScene): self._blocked = False + def _get_glyphObject(self): + view = self.views()[0] + return view._glyph + + _glyphObject = property(_get_glyphObject, doc="Get the current glyph in the view.") + def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.acceptProposedAction() @@ -1285,6 +1327,7 @@ class GlyphView(QGraphicsView): super(GlyphView, self).__init__(parent) self._glyph = glyph self._glyph.addObserver(self, "_glyphChanged", "Glyph.Changed") + self._glyph.layerSet.addObserver(self, "_layersChanged", "LayerSet.Changed") self._impliedPointSize = 1000 self._pointSize = None @@ -1303,6 +1346,9 @@ class GlyphView(QGraphicsView): font.setFixedPitch(True) self.setFont(font) + self._currentLayerBox = QComboBox(self) + self._currentLayerBox.currentIndexChanged.connect(self._currentLayerChanged) + self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) #self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate) @@ -1315,11 +1361,15 @@ class GlyphView(QGraphicsView): self.addBackground() self.addBlues() self.addHorizontalMetrics() + self.addOtherLayersOutlines() self.addOutlines() self.addComponents() self.addAnchors() self.addPoints() + def currentLayerBox(self): + return self._currentLayerBox + def _glyphChanged(self, notification): # TODO: maybe detect sidebearing changes (space center) and then only # translate elements rather than reconstructing them. @@ -1327,6 +1377,11 @@ class GlyphView(QGraphicsView): # sp.center values. self.redrawGlyph() + # TODO: diagnose notifications count + def _layersChanged(self, notification): + self.redrawGlyph() + self.redrawOtherLayers() + def redrawGlyph(self): path = self._glyph.getRepresentation("defconQt.NoComponentsQPainterPath") scene = self.scene() @@ -1346,6 +1401,14 @@ class GlyphView(QGraphicsView): # this will not be the case anymore when drag sidebearings pops up scene._widthItem.setRect(0, -1000, self._glyph.width, 3000) + def redrawOtherLayers(self): + scene = self.scene() + for item in scene.items(): + # XXX: discriminate better + if isinstance(item, QGraphicsPathItem) and item.zValue() == -997: + scene.removeItem(item) + self.addOtherLayersOutlines() + def addBackground(self): scene = self.scene() font = self._glyph.getParent() @@ -1409,16 +1472,38 @@ class GlyphView(QGraphicsView): item = VGuidelinesTextItem(text, font) item.setBrush(metricsColor) item.setFlag(QGraphicsItem.ItemIgnoresTransformations) - item.setPos(width, y) # XXX + item.setPos(width, y) item.setZValue(-997) scene.addItem(item) + def addOtherLayersOutlines(self): + comboBox = self._currentLayerBox + comboBox.blockSignals(True) + comboBox.clear() + scene = self.scene() + layerSet = self._glyph.layerSet + for layer in layerSet: + comboBox.addItem(layer.name, layer) + if layer == self._glyph.layer: + comboBox.setCurrentText(layer.name) + continue + if not self._glyph.name in layer: + continue + path = layer[self._glyph.name].getRepresentation("defconQt.NoComponentsQPainterPath") + if layer.color is not None: + layerColor = QColor.fromRgbF(tuple(layer.color)) + else: + layerColor = Qt.black + item = scene.addPath(path, QPen(layerColor)) + item.setZValue(-997) + comboBox.addItem("New layer...", None) + comboBox.blockSignals(False) + def addOutlines(self): scene = self.scene() path = self._glyph.getRepresentation("defconQt.NoComponentsQPainterPath") scene._outlineItem = scene.addPath(path, brush=QBrush(fillColor)) scene._outlineItem.setZValue(-995) - scene._glyphObject = self._glyph def addComponents(self): scene = self.scene() @@ -1532,7 +1617,7 @@ class GlyphView(QGraphicsView): if scene._integerPlane: pos.setX(int(pos.x())) pos.setY(int(pos.y())) - newAnchorName, ok = AddAnchorDialog.getNewAnchorData(self, pos) + newAnchorName, ok = AddAnchorDialog.getNewAnchorName(self, pos) if ok: anchor = Anchor() anchor.x = pos.x() @@ -1547,21 +1632,44 @@ class GlyphView(QGraphicsView): component.baseGlyph = newGlyph.name self._glyph.appendComponent(component) + def _currentLayerChanged(self, newLayerIndex): + comboBox = self.sender() + newLayer = comboBox.itemData(newLayerIndex) + if newLayer is None: + # add a new layer + newLayerName, ok = AddLayerDialog.getNewLayerName(self) + if ok: + self._glyph.layerSet.newLayer(newLayerName) + self._currentLayerBox.blockSignals(True) + self._currentLayerBox.setCurrentText(newLayerName) + self._currentLayerBox.blockSignals(False) + newLayer = self._glyph.layerSet[newLayerName] + else: + return + if not self._glyph.name in newLayer: + newLayer.newGlyph(self._glyph.name) + # TODO: generalize this out, can’t use newStandardGlyph unfortunately + newLayer[self._glyph.name].width = self._glyph.width + newLayer[self._glyph.name].template = True + newGlyph = newLayer[self._glyph.name] + self.setGlyph(newGlyph) + def setGlyph(self, glyph): scene = self.scene() self._glyph.removeObserver(self, "Glyph.Changed") + self._glyph.layerSet.removeObserver(self, "LayerSet.Changed") # TODO: consider creating a new scene instead of zeroing things out # manually scene._dataForUndo = [] scene._dataForRedo = [] self._glyph = glyph - # XXX: DRY ALERT! - scene._glyphObject = glyph app = QApplication.instance() app.setCurrentGlyph(glyph) self._glyph.addObserver(self, "_glyphChanged", "Glyph.Changed") + self._glyph.layerSet.addObserver(self, "_layersChanged", "LayerSet.Changed") self.parent().setWindowTitle(self._glyph.name, self._glyph.getParent()) self.redrawGlyph() + self.redrawOtherLayers() def showEvent(self, event): super(GlyphView, self).showEvent(event) diff --git a/Lib/defconQt/spaceCenter.py b/Lib/defconQt/spaceCenter.py index 4224979..d588ef8 100644 --- a/Lib/defconQt/spaceCenter.py +++ b/Lib/defconQt/spaceCenter.py @@ -142,7 +142,7 @@ class MainSpaceWindow(QWidget): glyphName = self.font.unicodeData.glyphNameForUnicode(ord(c)) glyphNames.append(glyphName) # catch remaining compile. - if compileStack is not None: + if compileStack is not None and compileStack: catchCompile() return glyphNames |
