class ExtensionBuilderWindow(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle(self.tr("Extension Builder")) layout = QFormLayout(self) layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.nameEdit = QLineEdit(self) self.versionEdit = QLineEdit(self) self.versionEdit.setValidator(VersionValidator(self)) self.developerEdit = QLineEdit(self) self.developerURLEdit = QLineEdit(self) layout.addRow(self.tr("Name:"), self.nameEdit) layout.addRow(self.tr("Version:"), self.versionEdit) layout.addRow(self.tr("Developer:"), self.developerEdit) layout.addRow(self.tr("Developer URL:"), self.developerURLEdit) layout.addRow(HLine(self)) self.resourcesRootBox = FolderComboBox(self) self.resourcesRootBox.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred) self.scriptRootBox = FolderComboBox(self) self.scriptRootBox.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred) self.scriptRootBox.currentFolderModified.connect(self.updateView) layout.addRow(self.tr("Resources root:"), self.resourcesRootBox) layout.addRow(self.tr("Script root:"), self.scriptRootBox) self.launchAtStartupBox = QCheckBox(self.tr("Launch At Startup"), self) self.mainScriptDrop = QComboBox(self) addScriptsLabel = QLabel(self.tr("Add script to main menu:"), self) self.addScriptsView = ListView(self) self.addScriptsView.setList([["", "", "", ""]]) self.addScriptsView.setHeaderLabels( ["", "Script", "Menu name", "Shortcut"]) scriptLayout = QVBoxLayout() scriptLayout.addWidget(self.launchAtStartupBox) scriptLayout.addWidget(self.mainScriptDrop) scriptLayout.addWidget(addScriptsLabel) scriptLayout.addWidget(self.addScriptsView) layout.addRow("", scriptLayout) layout.addRow(HLine(self)) self.tfVersionEdit = QLineEdit(self) self.tfVersionEdit.setValidator(VersionValidator(self)) layout.addRow(self.tr("Requires SimpleFont:"), self.tfVersionEdit) buttonBox = QDialogButtonBox( QDialogButtonBox.Save | QDialogButtonBox.Close, self) buttonBox.accepted.connect(self.saveFile) buttonBox.rejected.connect(self.close) layout.addRow(buttonBox) self.setLayout(layout) self.updateView() def saveFile(self): e = TExtension() e.name = self.nameEdit.text() or None e.version = self.versionEdit.text() or None e.developer = self.developerEdit.text() or None e.developerURL = self.developerURLEdit.text() or None e.resourcesPath = self.resourcesRootBox.currentFolder() e.libPath = self.scriptRootBox.currentFolder() e.launchAtStartup = self.launchAtStartupBox.isChecked() e.mainScript = self.mainScriptDrop.currentText() # Note. for now we always do a list. addToMenu = [] for ok, path, name, shortcut in self.addScriptsView.list(): if not ok: continue data = dict(path=path, name=name, shortcut=shortcut) for k, v in list(data.items()): if v is None: del data[k] addToMenu.append(data) if addToMenu: e.addToMenu = addToMenu e.tfVersion = self.tfVersionEdit.text() or None # TODO: switch to directory on platforms that need it dialog = QFileDialog( self, self.tr("Save File"), None, "SimpleFont Extension (*.tfExt)") dialog.setAcceptMode(QFileDialog.AcceptSave) ok = dialog.exec_() if ok: path = dialog.selectedFiles()[0] e.save(path) def updateView(self): path = self.scriptRootBox.currentFolder() widgets = ( self.launchAtStartupBox, self.mainScriptDrop, self.addScriptsView, ) for widget in widgets: widget.setEnabled(path is not None) if path is None: return elements = [] for root, dirs, files in os.walk(path): for file in files: if os.path.splitext(file)[1] != ".py": continue name = os.path.join(root[len(path)+1:], file) self.mainScriptDrop.addItem(name) elements.append( [False, name, None, ""]) self.addScriptsView.setList(elements) # TODO: should be done in the widget model = self.addScriptsView.model() for i in range(len(elements)): self.addScriptsView.openPersistentEditor(model.index(i, 0)) # ---------- # Qt methods # ---------- def sizeHint(self): return QSize(580, 480)
class MiscTab(QWidget): def __init__(self, parent=None): super().__init__(parent) self.name = self.tr("Misc") self.markColorLabel = QLabel(self.tr("Default flag colors:"), self) self.markColorView = ListView(self) self.markColorView.setDragEnabled(True) # HACK: we need a model before declaring headers self.markColorView.setList([]) self.markColorView.setHeaderLabels( (self.tr("Color"), self.tr("Name"))) self.addItemButton = QPushButton(self) self.addItemButton.setIcon(icons.i_plus()) self.addItemButton.clicked.connect(self.addItem) self.removeItemButton = QPushButton(self) self.removeItemButton.setIcon(icons.i_minus()) self.removeItemButton.clicked.connect(self.removeItem) self.loadRecentFileBox = QCheckBox( self.tr("Load most recent file on start"), self) buttonsLayout = QHBoxLayout() buttonsLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize) buttonsLayout.addWidget(self.addItemButton) buttonsLayout.addWidget(self.removeItemButton) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) buttonsLayout.addWidget(spacer) layout = QVBoxLayout(self) layout.addWidget(self.markColorLabel) layout.addWidget(self.markColorView) layout.addLayout(buttonsLayout) layout.addWidget(self.loadRecentFileBox) self.setLayout(layout) self.readSettings() def addItem(self): lst = self.markColorView.list() lst.append([QColor(170, 255, 255), self.tr("New!")]) self.markColorView.setList(lst) self.markColorView.editIndex(len(lst) - 1, 1) self.removeItemButton.setEnabled(True) def removeItem(self): self.markColorView.removeCurrentRow() if not len(self.markColorView.list()): self.removeItemButton.setEnabled(False) def readSettings(self): entries = settings.readMarkColors() self.markColorView.setList(entries) if not len(entries): self.removeItemButton.setEnabled(False) loadRecentFile = settings.loadRecentFile() self.loadRecentFileBox.setChecked(loadRecentFile) def writeSettings(self): markColors = self.markColorView.list() settings.writeMarkColors(markColors) loadRecentFile = self.loadRecentFileBox.isChecked() settings.setLoadRecentFile(loadRecentFile)
class MiscTab(QWidget): def __init__(self, parent=None): super().__init__(parent) self.name = self.tr("Misc") self.markColorLabel = QLabel(self.tr("Default flag colors:"), self) self.markColorView = ListView(self) self.markColorView.setDragEnabled(True) # HACK: we need a model before declaring headers self.markColorView.setList([]) self.markColorView.setHeaderLabels( (self.tr("Color"), self.tr("Name"))) self.addItemButton = QPushButton("+", self) self.addItemButton.clicked.connect(self.addItem) self.removeItemButton = QPushButton("−", self) self.removeItemButton.clicked.connect(self.removeItem) self.loadRecentFileBox = QCheckBox( self.tr("Load most recent file on start"), self) layout = QGridLayout(self) l = 0 layout.addWidget(self.markColorLabel, l, 0, 1, 3) l += 1 layout.addWidget(self.markColorView, l, 0, 1, 3) l += 1 layout.addWidget(self.addItemButton, l, 0) layout.addWidget(self.removeItemButton, l, 1) l += 1 layout.addWidget(self.loadRecentFileBox, l, 0, 1, 3) self.setLayout(layout) self.readSettings() def addItem(self): lst = self.markColorView.list() lst.append([QColor(170, 255, 255), self.tr("New!")]) self.markColorView.setList(lst) self.markColorView.editIndex(len(lst) - 1, 1) self.removeItemButton.setEnabled(True) def removeItem(self): self.markColorView.removeCurrentRow() if not len(self.markColorView.list()): self.removeItemButton.setEnabled(False) def readSettings(self): entries = settings.readMarkColors() self.markColorView.setList(entries) if not len(entries): self.removeItemButton.setEnabled(False) loadRecentFile = settings.loadRecentFile() self.loadRecentFileBox.setChecked(loadRecentFile) def writeSettings(self): markColors = self.markColorView.list() settings.writeMarkColors(markColors) loadRecentFile = self.loadRecentFileBox.isChecked() settings.setLoadRecentFile(loadRecentFile)
class InspectorWindow(QWidget): def __init__(self, parent=None): super().__init__(parent, Qt.Tool) self.setWindowTitle(self.tr("Inspector")) self._font = None self._glyph = None glyphGroup = AccordionBox(self.tr("Glyph"), self) glyphLayout = QGridLayout(self) columnOneWidth = self.fontMetrics().width('0') * 7 nameLabel = RLabel(self.tr("Name:"), self) self.nameEdit = QLineEdit(self) self.nameEdit.editingFinished.connect(self.writeGlyphName) unicodesLabel = RLabel(self.tr("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}))*)") unicodesValidator = QRegularExpressionValidator(unicodesRegExp, self) self.unicodesEdit.setValidator(unicodesValidator) widthLabel = RLabel(self.tr("Width:"), self) self.widthEdit = QLineEdit(self) self.widthEdit.editingFinished.connect(self.writeWidth) self.widthEdit.setMaximumWidth(columnOneWidth) self.widthEdit.setValidator(QIntValidator(self)) leftSideBearingLabel = RLabel(self.tr("Left:"), self) self.leftSideBearingEdit = QLineEdit(self) self.leftSideBearingEdit.editingFinished.connect( self.writeLeftSideBearing) self.leftSideBearingEdit.setMaximumWidth(columnOneWidth) self.leftSideBearingEdit.setValidator(QIntValidator(self)) rightSideBearingLabel = RLabel(self.tr("Right:"), self) self.rightSideBearingEdit = QLineEdit(self) self.rightSideBearingEdit.editingFinished.connect( self.writeRightSideBearing) self.rightSideBearingEdit.setMaximumWidth(columnOneWidth) self.rightSideBearingEdit.setValidator(QIntValidator(self)) markColorLabel = RLabel(self.tr("Flag:"), self) self.markColorWidget = ColorVignette(self) self.markColorWidget.colorChanged.connect( self.writeMarkColor) self.markColorWidget.setMaximumWidth(columnOneWidth) l = 0 glyphLayout.addWidget(nameLabel, l, 0) glyphLayout.addWidget(self.nameEdit, l, 1, 1, 5) l += 1 glyphLayout.addWidget(unicodesLabel, l, 0) glyphLayout.addWidget(self.unicodesEdit, l, 1, 1, 5) l += 1 glyphLayout.addWidget(widthLabel, l, 0) glyphLayout.addWidget(self.widthEdit, l, 1) l += 1 glyphLayout.addWidget(leftSideBearingLabel, l, 0) glyphLayout.addWidget(self.leftSideBearingEdit, l, 1) glyphLayout.addWidget(rightSideBearingLabel, l, 2) glyphLayout.addWidget(self.rightSideBearingEdit, l, 3) l += 1 glyphLayout.addWidget(markColorLabel, l, 0) glyphLayout.addWidget(self.markColorWidget, l, 1) glyphGroup.setLayout(glyphLayout) transformGroup = AccordionBox(self.tr("Transform"), self) transformLayout = QGridLayout(self) self.alignmentWidget = GlyphAlignmentWidget(self) hMirrorButton = QToolButton() hMirrorButton.clicked.connect(self.hMirror) hMirrorButton.setIcon(QIcon(":swap.svg")) vMirrorButton = QToolButton() vMirrorButton.clicked.connect(self.vMirror) vMirrorButton.setIcon(QIcon(":swap-vertical.svg")) # TODO: implement alignVTopButton = QToolButton() alignVTopButton.setEnabled(False) alignVTopButton.setIcon(QIcon(":format-vertical-align-top.svg")) alignVCenterButton = QToolButton() alignVCenterButton.setEnabled(False) alignVCenterButton.setIcon(QIcon(":format-vertical-align-center.svg")) alignVBottomButton = QToolButton() alignVBottomButton.setEnabled(False) alignVBottomButton.setIcon(QIcon(":format-vertical-align-bottom.svg")) alignHLeftButton = QToolButton() alignHLeftButton.setEnabled(False) alignHLeftButton.setIcon(QIcon(":format-horizontal-align-left.svg")) alignHCenterButton = QToolButton() alignHCenterButton.setEnabled(False) alignHCenterButton.setIcon( QIcon(":format-horizontal-align-center.svg")) alignHRightButton = QToolButton() alignHRightButton.setEnabled(False) alignHRightButton.setIcon(QIcon(":format-horizontal-align-right.svg")) buttonsLayout = QGridLayout() l = 0 buttonsLayout.addWidget(hMirrorButton, l, 0) buttonsLayout.addWidget(vMirrorButton, l, 1) l += 1 buttonsLayout.addWidget(alignVTopButton, l, 0) buttonsLayout.addWidget(alignVCenterButton, l, 1) buttonsLayout.addWidget(alignVBottomButton, l, 2) buttonsLayout.addWidget(alignHLeftButton, l, 3) buttonsLayout.addWidget(alignHCenterButton, l, 4) buttonsLayout.addWidget(alignHRightButton, l, 5) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) buttonsLayout.addWidget(spacer, l, 7) # TODO: should this be implemented for partial selection? moveButton = QPushButton(self.tr("Move"), self) moveButton.clicked.connect(self.moveGlyph) moveXLabel = RLabel("x:", self) self.moveXEdit = QLineEdit("0", self) self.moveXEdit.setValidator(QIntValidator(self)) moveYLabel = RLabel("y:", self) self.moveYEdit = QLineEdit("0", self) self.moveYEdit.setValidator(QIntValidator(self)) moveXYBox = QCheckBox("x=y", self) moveXYBox.clicked.connect(self.lockMove) scaleButton = QPushButton(self.tr("Scale"), self) scaleButton.clicked.connect(self.scaleGlyph) scaleXLabel = RLabel("x:", self) self.scaleXEdit = QLineEdit("100", self) self.scaleXEdit.setValidator(QIntValidator(self)) scaleYLabel = RLabel("y:", self) self.scaleYEdit = QLineEdit("100", self) self.scaleYEdit.setValidator(QIntValidator(self)) scaleXYBox = QCheckBox("x=y", self) scaleXYBox.clicked.connect(self.lockScale) rotateButton = QPushButton(self.tr("Rotate"), self) rotateButton.clicked.connect(self.rotateGlyph) rotateLabel = RLabel("α:", self) self.rotateEdit = QLineEdit("0", self) self.rotateEdit.setValidator(QIntValidator(self)) skewButton = QPushButton(self.tr("Skew"), self) skewButton.clicked.connect(self.skewGlyph) skewXLabel = RLabel("α:", self) self.skewXEdit = QLineEdit("0", self) self.skewXEdit.setValidator(QIntValidator(self)) skewYLabel = RLabel("β:", self) self.skewYEdit = QLineEdit("0", self) self.skewYEdit.setValidator(QIntValidator(self)) skewXYBox = QCheckBox("α=β", self) skewXYBox.clicked.connect(self.lockSkew) snapButton = QPushButton(self.tr("Snap"), self) snapButton.clicked.connect(self.snapGlyph) self.snapEdit = QLineEdit("1", self) self.snapEdit.setValidator(QDoubleValidator(self)) l = 0 transformLayout.addWidget(self.alignmentWidget, l, 0) transformLayout.addLayout(buttonsLayout, l, 1, 1, 5) l += 1 transformLayout.addWidget(moveButton, l, 0) transformLayout.addWidget(moveXLabel, l, 1) transformLayout.addWidget(self.moveXEdit, l, 2) transformLayout.addWidget(moveYLabel, l, 3) transformLayout.addWidget(self.moveYEdit, l, 4) transformLayout.addWidget(moveXYBox, l, 5) l += 1 transformLayout.addWidget(scaleButton, l, 0) transformLayout.addWidget(scaleXLabel, l, 1) transformLayout.addWidget(self.scaleXEdit, l, 2) transformLayout.addWidget(scaleYLabel, l, 3) transformLayout.addWidget(self.scaleYEdit, l, 4) transformLayout.addWidget(scaleXYBox, l, 5) l += 1 transformLayout.addWidget(rotateButton, l, 0) transformLayout.addWidget(rotateLabel, l, 1) transformLayout.addWidget(self.rotateEdit, l, 2) l += 1 transformLayout.addWidget(skewButton, l, 0) transformLayout.addWidget(skewXLabel, l, 1) transformLayout.addWidget(self.skewXEdit, l, 2) transformLayout.addWidget(skewYLabel, l, 3) transformLayout.addWidget(self.skewYEdit, l, 4) transformLayout.addWidget(skewXYBox, l, 5) l += 1 transformLayout.addWidget(snapButton, l, 0) transformLayout.addWidget(self.snapEdit, l, 2) transformGroup.setLayout(transformLayout) layerSetGroup = AccordionBox(self.tr("Layers"), self) layerSetLayout = QVBoxLayout(self) self.layerSetView = ListView(self) self.layerSetView.setDragEnabled(True) # HACK: we need this for header labels self.layerSetView.setList([[None, None]]) self.layerSetView.setHeaderLabels( (self.tr("Color"), self.tr("Layer Name"))) self.layerSetView.dataDropped.connect(self.writeLayerOrder) self.layerSetView.valueChanged.connect(self.writeLayerAttribute) layerSetLayout.addWidget(self.layerSetView) layerSetGroup.setLayout(layerSetLayout) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) mainLayout = QVBoxLayout() mainLayout.addWidget(glyphGroup) mainLayout.addWidget(transformGroup) mainLayout.addWidget(layerSetGroup) mainLayout.addWidget(spacer) self.setLayout(mainLayout) self.readSettings() def readSettings(self): geometry = settings.inspectorWindowGeometry() if geometry: self.restoreGeometry(geometry) def writeSettings(self): settings.setInspectorWindowGeometry(self.saveGeometry()) # ------------- # Notifications # ------------- def _unsubscribeFromGlyph(self): glyph = self._glyph if glyph is not None: glyph.removeObserver(self, "Glyph.Changed") def _subscribeToGlyph(self, glyph): if glyph is not None: glyph.addObserver( self, "_updateGlyphAttributes", "Glyph.Changed") def _unsubscribeFromFont(self): font = self._font if font is not None: layerSet = font.layers if layerSet is not None: layerSet.removeObserver(self, "LayerSet.Changed") def _subscribeToFont(self, font): if font is not None: layerSet = font.layers if layerSet is not None: layerSet.addObserver( self, "_updateLayerAttributes", "LayerSet.Changed") def _updateGlyph(self, notification=None): self._unsubscribeFromGlyph() app = QApplication.instance() self._glyph = app.currentGlyph() self._subscribeToGlyph(self._glyph) self.alignmentWidget.setGlyph(self._glyph) self._updateGlyphAttributes() def _updateFont(self, notification=None): self._unsubscribeFromFont() app = QApplication.instance() self._font = app.currentFont() self._subscribeToFont(self._font) self._updateLayerAttributes() def _updateGlyphAttributes(self, notification=None): name = None unicodes = None width = None leftSideBearing = None rightSideBearing = None markColor = None 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.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: markColor = QColor.fromRgbF( *tuple(self._glyph.markColor)) self.nameEdit.setText(name) self.unicodesEdit.setText(unicodes) self.widthEdit.setText(width) self.leftSideBearingEdit.setText(leftSideBearing) self.rightSideBearingEdit.setText(rightSideBearing) self.markColorWidget.setColor(markColor) def _updateLayerAttributes(self, notification=None): self.layerSetView.setList([]) font = self._font if None in (font, font.layers): return layers = [] for layer in font.layers: color = layer.color if color is not None: color = colorToQColor(color) else: color = QColor() layers.append([color, layer.name]) self.layerSetView.setList(layers) # --------- # Callbacks # --------- # glyph attributes def writeGlyphName(self): if self._glyph is None: return # TODO: should there be an API for this (e.g. glyph.rename()) layerSet = self._glyph.layerSet newName = self.nameEdit.text() if layerSet is not None: oldName = self._glyph.name for layer in layerSet: if oldName in layer: glyph = layer[oldName] glyph.name = newName else: self._glyph.name = newName def writeUnicodes(self): if self._glyph is None: return unicodes = self.unicodesEdit.text().split(" ") if len(unicodes) == 1 and unicodes[0] == "": self._glyph.unicodes = [] else: self._glyph.unicodes = [int(uni, 16) for uni in unicodes] def writeWidth(self): if self._glyph is None: return self._glyph.width = int(self.widthEdit.text()) def writeLeftSideBearing(self): if self._glyph is None: return self._glyph.leftMargin = int(self.leftSideBearingEdit.text()) def writeRightSideBearing(self): if self._glyph is None: return self._glyph.rightMargin = int(self.rightSideBearingEdit.text()) def writeMarkColor(self): color = self.markColorWidget.color() if color is not None: color = color.getRgbF() self._glyph.markColor = color def writeLayerAttribute(self, index, previous, current): font = self._font if None in (font, font.layers): return row, column = index.row(), index.column() layers = font.layers layer = layers[layers.layerOrder[row]] if column == 0: # color if current.isValid(): color = current.getRgbF() else: color = None layer.color = color elif column == 1: # name layer.name = current else: raise ValueError("invalid column selected: %d." % column) def writeLayerOrder(self): font = self._font if None in (font, font.layers): return data = self.layerSetView.list() layerSet = font.layers layerOrder = [] for _, name in data: layerOrder.append(name) # defcon has data validity assertion (constant len etc.) layerSet.layerOrder = layerOrder # transforms def hMirror(self): glyph = self._glyph if None in (glyph, glyph.controlPointBounds): return xMin, _, xMax, _ = glyph.controlPointBounds for contour in glyph: for point in contour: point.x = xMin + xMax - point.x glyph.dirty = True def vMirror(self): glyph = self._glyph if None in (glyph, glyph.controlPointBounds): return _, yMin, _, yMax = glyph.controlPointBounds for contour in glyph: for point in contour: point.y = yMin + yMax - point.y glyph.dirty = True def lockMove(self, checked): self.moveYEdit.setEnabled(not checked) def moveGlyph(self): x = self.moveXEdit.text() if not self.moveYEdit.isEnabled(): y = x else: y = self.moveYEdit.text() x, y = int(x) if x != "" else 0, int(y) if y != "" else 0 self._glyph.move((x, y)) def lockScale(self, checked): self.scaleYEdit.setEnabled(not checked) def scaleGlyph(self): glyph = self._glyph # TODO: consider disabling the buttons in that case? if glyph is None: return sX = self.scaleXEdit.text() if not self.scaleYEdit.isEnabled(): sY = sX else: sY = self.scaleYEdit.text() sX, sY = int(sX) if sX != "" else 100, int(sY) if sY != "" else 100 sX /= 100 sY /= 100 center = self.alignmentWidget.origin() glyph.scale((sX, sY), center=center) def rotateGlyph(self): glyph = self._glyph if glyph is None: return r = self.rotateEdit.text() r = int(r) if r != "" else 0 origin = self.alignmentWidget.origin() glyph.rotate(r, offset=origin) def lockSkew(self, checked): self.skewYEdit.setEnabled(not checked) def skewGlyph(self): glyph = self._glyph if glyph is None: return sX = self.skewXEdit.text() if not self.skewYEdit.isEnabled(): sY = sX else: sY = self.skewYEdit.text() sX, sY = int(sX) if sX != "" else 0, int(sY) if sY != "" else 0 glyph.skew((sX, sY)) def snapGlyph(self): glyph = self._glyph if glyph is None: return base = self.snapEdit.text() base = float(base) if base != "" else 0 glyph.snap(base) # ---------- # Qt methods # ---------- def sizeHint(self): sizeHint = super().sizeHint() sizeHint.setWidth(200) return sizeHint def showEvent(self, event): super().showEvent(event) # positioning # TODO: make this multiscreen aware and kick it off when restoring # geometry """ screenRect = QApplication.desktop().availableGeometry(self) widgetRect = self.frameGeometry() x = screenRect.width() - (widgetRect.width() + 20) y = screenRect.center().y() - widgetRect.height() / 2 self.move(x, y) """ # notifications app = QApplication.instance() self._updateGlyph() app.dispatcher.addObserver(self, "_updateGlyph", "currentGlyphChanged") self._updateFont() app.dispatcher.addObserver(self, "_updateFont", "currentFontChanged") def moveEvent(self, event): self.writeSettings() resizeEvent = moveEvent def closeEvent(self, event): super().closeEvent(event) if event.isAccepted(): app = QApplication.instance() app.dispatcher.removeObserver(self, "currentGlyphChanged") app.dispatcher.removeObserver(self, "currentFontChanged")
class ExtensionBuilderWindow(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle(self.tr("Extension Builder")) layout = QFormLayout(self) layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.nameEdit = QLineEdit(self) self.versionEdit = QLineEdit(self) self.versionEdit.setValidator(VersionValidator(self)) self.developerEdit = QLineEdit(self) self.developerURLEdit = QLineEdit(self) layout.addRow(self.tr("Name:"), self.nameEdit) layout.addRow(self.tr("Version:"), self.versionEdit) layout.addRow(self.tr("Developer:"), self.developerEdit) layout.addRow(self.tr("Developer URL:"), self.developerURLEdit) layout.addRow(HLine(self)) self.resourcesRootBox = FolderComboBox(self) self.scriptRootBox = FolderComboBox(self) self.scriptRootBox.currentFolderModified.connect(self.updateView) layout.addRow(self.tr("Resources root:"), self.resourcesRootBox) layout.addRow(self.tr("Script root:"), self.scriptRootBox) self.launchAtStartupBox = QCheckBox(self.tr("Launch At Startup"), self) self.mainScriptDrop = QComboBox(self) addScriptsLabel = QLabel(self.tr("Add script to main menu:"), self) self.addScriptsView = ListView(self) self.addScriptsView.setList([["", "", "", ""]]) self.addScriptsView.setHeaderLabels(["", "Script", "Menu name", "Shortcut"]) scriptLayout = QVBoxLayout() scriptLayout.addWidget(self.launchAtStartupBox) scriptLayout.addWidget(self.mainScriptDrop) scriptLayout.addWidget(addScriptsLabel) scriptLayout.addWidget(self.addScriptsView) layout.addRow("", scriptLayout) layout.addRow(HLine(self)) self.tfVersionEdit = QLineEdit(self) self.tfVersionEdit.setValidator(VersionValidator(self)) layout.addRow(self.tr("Requires TruFont:"), self.tfVersionEdit) buttonBox = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close, self) buttonBox.accepted.connect(self.saveFile) buttonBox.rejected.connect(self.close) layout.addRow(buttonBox) self.setLayout(layout) self.updateView() def saveFile(self): e = TExtension() e.name = self.nameEdit.text() or None e.version = self.versionEdit.text() or None e.developer = self.developerEdit.text() or None e.developerURL = self.developerURLEdit.text() or None e.resourcesPath = self.resourcesRootBox.currentFolder() e.libPath = self.scriptRootBox.currentFolder() e.launchAtStartup = self.launchAtStartupBox.isChecked() e.mainScript = self.mainScriptDrop.currentText() # Note. for now we always do a list. addToMenu = [] for ok, path, name, shortcut in self.addScriptsView.list(): if not ok: continue data = dict(path=path, name=name, shortcut=shortcut) for k, v in data.items(): if v is None: del data[k] addToMenu.append(data) if addToMenu: e.addToMenu = addToMenu e.tfVersion = self.tfVersionEdit.text() or None # TODO: switch to directory on platforms that need it dialog = QFileDialog(self, self.tr("Save File"), None, "TruFont Extension (*.tfExt)") dialog.setAcceptMode(QFileDialog.AcceptSave) ok = dialog.exec_() if ok: path = dialog.selectedFiles()[0] e.save(path) def updateView(self): path = self.scriptRootBox.currentFolder() widgets = (self.launchAtStartupBox, self.mainScriptDrop, self.addScriptsView) for widget in widgets: widget.setEnabled(path is not None) if path is None: return elements = [] for root, dirs, files in os.walk(path): for file in files: if os.path.splitext(file)[1] != ".py": continue name = os.path.join(root[len(path) + 1 :], file) self.mainScriptDrop.addItem(name) elements.append([False, name, None, ""]) self.addScriptsView.setList(elements) # TODO: should be done in the widget model = self.addScriptsView.model() for i in range(len(elements)): self.addScriptsView.openPersistentEditor(model.index(i, 0))