aboutsummaryrefslogtreecommitdiffstats
path: root/Lib/defconQt/fontView.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/defconQt/fontView.py')
-rw-r--r--Lib/defconQt/fontView.py115
1 files changed, 88 insertions, 27 deletions
diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py
index 3f556d3..b3502f3 100644
--- a/Lib/defconQt/fontView.py
+++ b/Lib/defconQt/fontView.py
@@ -17,22 +17,31 @@ glyphSortDescriptors = [
dict(type="decompositionBase", allowPseudoUnicode=True)
]
+cellGridColor = QColor(130, 130, 130)
+cellHeaderBaseColor = QColor(230, 230, 230)
+cellHeaderLineColor = QColor(220, 220, 220)
+cellHeaderHighlightLineColor = QColor(240, 240, 240)
+cellSelectionColor = QColor.fromRgbF(.2, .3, .7, .15)
+
+GlyphCellBufferHeight = .2
+GlyphCellHeaderHeight = 14
+
class CharacterWidget(QWidget):
characterSelected = pyqtSignal(int, str)
glyphOpened = pyqtSignal(str)
- def __init__(self, font, squareSize=48, scrollArea=None, parent=None):
+ def __init__(self, font, squareSize=56, scrollArea=None, parent=None):
super(CharacterWidget, self).__init__(parent)
self.font = font
self.glyphs = [font[k] for k in font.unicodeData.sortGlyphNames(font.keys(), glyphSortDescriptors)]
self.scrollArea = scrollArea
+ self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.squareSize = squareSize
- self.columns = 11
+ self.columns = 10
self.lastKey = -1
self.moveKey = -1
#self.setMouseTracking(True)
- self.col = QColor.fromRgbF(.2, .3, .7, .15)
def updateFont(self, font):
self.font = font
@@ -46,7 +55,6 @@ class CharacterWidget(QWidget):
self.update()
def _sizeEvent(self, width, squareSize=None):
- # TODO: Still some horizontal scrollbar appearing, should disable it entirely
if self.scrollArea is not None: sw = self.scrollArea.verticalScrollBar().width() + self.scrollArea.contentsMargins().right()
else: sw = 0
if squareSize is not None: self.squareSize = squareSize
@@ -54,7 +62,6 @@ class CharacterWidget(QWidget):
if not columns > 0: return
self.columns = columns
self.adjustSize()
- #super(CharacterWidget, self).resizeEvent(event)
def sizeHint(self):
return QSize(self.columns * self.squareSize,
@@ -65,8 +72,7 @@ class CharacterWidget(QWidget):
self.lastKey = (event.y() // self.squareSize) * self.columns + event.x() // self.squareSize
self.moveKey = -1
if self.lastKey > len(self.glyphs)-1: return
-
- self.col = QColor.fromRgbF(.2, .3, .7, .15)
+
self.characterSelected.emit(1, self.glyphs[self.lastKey].name)
event.accept()
self.update()
@@ -75,7 +81,7 @@ class CharacterWidget(QWidget):
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
- moveKey = (event.y() // self.squareSize) * self.columns + event.x() // self.squareSize
+ moveKey = (event.y() // self.squareSize) * self.columns + min(event.x() // self.squareSize, self.columns-1)
event.accept()
if (moveKey == self.lastKey and self.moveKey != -1):
self.moveKey = -1
@@ -103,7 +109,7 @@ class CharacterWidget(QWidget):
def mouseDoubleClickEvent(self, event):
if event.button() == Qt.LeftButton:
- key = (event.y() // self.squareSize) * self.columns + event.x() // self.squareSize
+ key = (event.y() // self.squareSize) * self.columns + min(event.x() // self.squareSize, self.columns-1)
if key != self.lastKey: return
event.accept()
self.glyphOpened.emit(self.glyphs[key].name)
@@ -113,7 +119,6 @@ class CharacterWidget(QWidget):
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
- painter.fillRect(event.rect(), Qt.white)
redrawRect = event.rect()
beginRow = redrawRect.top() // self.squareSize
@@ -121,6 +126,7 @@ class CharacterWidget(QWidget):
beginColumn = redrawRect.left() // self.squareSize
endColumn = redrawRect.right() // self.squareSize
+ painter.setPen(cellGridColor)
painter.drawLine(redrawRect.left(), redrawRect.top(), redrawRect.left(), redrawRect.bottom())
painter.drawLine(0, 0, redrawRect.right(), 0)
@@ -131,43 +137,79 @@ class CharacterWidget(QWidget):
select = False
if firstKey != -1 and firstKey < minKeyInViewport and lastKey > minKeyInViewport:
select = True
+
+ gradient = QLinearGradient(0, 0, 0, GlyphCellHeaderHeight)
+ gradient.setColorAt(0.0, cellHeaderBaseColor)
+ gradient.setColorAt(1.0, cellHeaderLineColor)
- painter.setPen(Qt.gray)
for row in range(beginRow, endRow + 1):
for column in range(beginColumn, endColumn + 1):
key = row * self.columns + column
if key > len(self.glyphs)-1: break
+ painter.save()
+ painter.translate(column * self.squareSize, row * self.squareSize)
+ # background
+ painter.fillRect(0, 0, self.squareSize, self.squareSize, Qt.white)
+ # header gradient
+ painter.fillRect(0, 0, self.squareSize,
+ GlyphCellHeaderHeight, QBrush(gradient))
+ # header lines
+ painter.setPen(cellHeaderHighlightLineColor)
+ minOffset = painter.pen().width()
+ painter.setRenderHint(QPainter.Antialiasing, False)
+ painter.drawLine(0, 0, 0, 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.setRenderHint(QPainter.Antialiasing)
+ # header text
+ headerFont = QFont()
+ headerFont.setFamily('Lucida Sans Unicode')
+ painter.setFont(headerFont)
+ painter.setPen(QColor(80, 80, 80))
+ metrics = QFontMetrics(headerFont)
+ name = metrics.elidedText(self.glyphs[key].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.setRenderHint(QPainter.Antialiasing, False)
# selection code
if key == firstKey:
select = not select
if select or (key == self.lastKey and self.moveKey == -1):
painter.fillRect(column * self.squareSize + 1,
- row * self.squareSize + 1, self.squareSize - 2,
- self.squareSize - 2, self.col)
+ row * self.squareSize + 1, self.squareSize - 3,
+ self.squareSize - 3, cellSelectionColor)
if key == lastKey and self.moveKey != -1:
select = not select
+ painter.setRenderHint(QPainter.Antialiasing)
glyph = self.glyphs[key].getRepresentation("defconQt.QPainterPath")
if self.font.info.unitsPerEm is None: break
if not self.font.info.unitsPerEm > 0: self.font.info.unitsPerEm = 1000
- factor = self.squareSize/(self.font.info.unitsPerEm*(1+2*.125))
+ factor = (self.squareSize-GlyphCellHeaderHeight)/(self.font.info.unitsPerEm*(1+2*GlyphCellBufferHeight))
x_offset = (self.squareSize-self.glyphs[key].width*factor)/2
+ # If the glyph overflows horizontally we need to adjust the scaling factor
if x_offset < 0:
factor *= 1+2*x_offset/(self.glyphs[key].width*factor)
x_offset = 0
- y_offset = self.font.info.descender*factor
+ # TODO: the * 1.8 below is somewhat artificial
+ y_offset = self.font.info.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.scale(factor, -factor)
painter.fillPath(glyph, Qt.black)
painter.restore()
-
class MainWindow(QMainWindow):
def __init__(self, font=Font()):
@@ -178,27 +220,27 @@ class MainWindow(QMainWindow):
# TODO: have the scrollarea be part of the widget itself?
# or better yet, switch to QGraphicsScene
self.scrollArea = QScrollArea(self)
- squareSize = 48
+ squareSize = 56
self.characterWidget = CharacterWidget(self.font, squareSize, self.scrollArea, self)
self.scrollArea.setWidget(self.characterWidget)
# TODO: make shortcuts platform-independent
- # TODO: work out sensible shortcuts
fileMenu = QMenu("&File", self)
self.menuBar().addMenu(fileMenu)
- fileMenu.addAction("&New...", self.newFile, QKeySequence.New)
- fileMenu.addAction("&Open...", self.openFile, QKeySequence.Open)
+ fileMenu.addAction("&New…", self.newFile, QKeySequence.New)
+ fileMenu.addAction("&Open…", self.openFile, QKeySequence.Open)
# TODO: add functionality
#fileMenu.addMenu(QMenu("Open &Recent...", self))
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("E&xit", self.close, QKeySequence.Quit)
fontMenu = QMenu("&Font", self)
self.menuBar().addMenu(fontMenu)
+ # TODO: work out sensible shortcuts
fontMenu.addAction("Font &info", self.fontInfo, "Ctrl+I")
fontMenu.addAction("Font &features", self.fontFeatures, "Ctrl+F")
fontMenu.addAction("&Add glyph", self.addGlyph, "Ctrl+U")
@@ -212,21 +254,19 @@ class MainWindow(QMainWindow):
helpMenu.addAction("About &Qt", QApplication.instance().aboutQt)
self.sqSizeSlider = QSlider(Qt.Horizontal, self)
- self.sqSizeSlider.setMinimum(24)
+ self.sqSizeSlider.setMinimum(36)
self.sqSizeSlider.setMaximum(96)
- #sz = self.sqSizeSlider.sizeHint()
- #self.sqSizeSlider.setSize(.7*sz.width(), sz.height())
+ self.sqSizeSlider.setFixedWidth(.9*self.sqSizeSlider.width())
self.sqSizeSlider.setValue(squareSize)
self.sqSizeSlider.valueChanged.connect(self._squareSizeChanged)
self.selectionLabel = QLabel(self)
- self.selectionLabel.setFixedWidth(self.selectionLabel.fontMetrics().width('M') * 15)
self.characterWidget.characterSelected.connect(self._selectionChanged)
self.statusBar().addPermanentWidget(self.sqSizeSlider)
self.statusBar().addWidget(self.selectionLabel)
self.setCentralWidget(self.scrollArea)
self.characterWidget.glyphOpened.connect(self._glyphOpened)
- self.setWindowTitle(os.path.basename(self.font.path.rstrip(os.sep)))
+ self.setWindowTitle()
# TODO: dump the hardcoded path
#self.setWindowIcon(QIcon("C:\\Users\\Adrien\\Downloads\\defconQt\\Lib\\defconQt\\resources\\icon.png"))
@@ -251,9 +291,11 @@ class MainWindow(QMainWindow):
path = os.path.dirname(path)
self.font = Font(path)
self.characterWidget.updateFont(self.font)
+ self.setWindowTitle()
def saveFile(self, path=None):
self.font.save(path=path)
+# self.font.dirty = False
# self.font.path = path # done by defcon
def saveFileAs(self):
@@ -261,11 +303,26 @@ class MainWindow(QMainWindow):
"UFO Fonts (*.ufo)")
if ok:
self.saveFile(path)
+ #return ok
def close(self):
# TODO: check if font changed
self.font.removeObserver(self, "Font.Changed")
QApplication.instance().quit()
+
+ def closeEvent(self, event):
+ if self.font.dirty:
+ closeDialog = QMessageBox(QMessageBox.Question, "Save your work?", "Will you save, dear",
+ QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, self)
+ closeDialog.setModal(True)
+ ret = closeDialog.exec_()
+ if ret == QMessageBox.Yes:
+ self.saveFile()
+ event.accept()
+ elif ret == QMessageBox.No:
+ event.accept()
+ elif ret == QMessageBox.Cancel:
+ event.ignore()
def _fontChanged(self, event):
self.characterWidget.update()
@@ -287,6 +344,10 @@ class MainWindow(QMainWindow):
def resizeEvent(self, event):
if self.isVisible(): self.characterWidget._sizeEvent(event.size().width())
super(MainWindow, self).resizeEvent(event)
+
+ def setWindowTitle(self, title=None):
+ if title is None: title = os.path.basename(self.font.path.rstrip(os.sep))
+ super(MainWindow, self).setWindowTitle(title)
def fontInfo(self):
# If a window is already opened, bring it to the front, else spawn one.
@@ -347,6 +408,6 @@ if __name__ == '__main__':
# TODO: http://stackoverflow.com/a/21330349/2037879
app.setWindowIcon(QIcon("C:\\Users\\Adrien\\Downloads\\defconQt\\Lib\\defconQt\\resources\\icon.png"))
window = MainWindow(Font("C:\\CharterNova-Regular.ufo"))
- window.resize(565, 430)
+ window.resize(605, 430)
window.show()
sys.exit(app.exec_())