diff options
| author | Adrien Tétar | 2015-05-02 22:04:08 +0200 |
|---|---|---|
| committer | Adrien Tétar | 2015-05-02 22:04:08 +0200 |
| commit | c55eac755c6c7d91010f9b3ba040bc356f350ca7 (patch) | |
| tree | cc267b14ad50595ed3df7b68c0d864e9d1dd5094 /Lib | |
| parent | 7f54aa17a9c49a8688ee64e2aba303769ebb6c53 (diff) | |
| download | trufont-c55eac755c6c7d91010f9b3ba040bc356f350ca7.tar.bz2 | |
More, glyph canvas
Diffstat (limited to 'Lib')
| -rw-r--r-- | Lib/defconQt/fontView.py | 176 | ||||
| -rw-r--r-- | Lib/defconQt/glyphView.py | 6 | ||||
| -rw-r--r-- | Lib/defconQt/spacecenter.py | 56 | ||||
| -rw-r--r-- | Lib/defconQt/svgViewer.py | 87 | ||||
| -rw-r--r-- | Lib/defconQt/syntaxhighlighter.py | 74 |
5 files changed, 290 insertions, 109 deletions
diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index 114a5ca..6fc0207 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -4,12 +4,9 @@ import representationFactories import unicodedata from defcon import Font -from PyQt5.QtCore import pyqtSignal, QSize, Qt -from PyQt5.QtGui import (QClipboard, QFont, QFontDatabase, QFontMetrics, - QIcon, QPainter) -from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QDialogButtonBox, QFileDialog, QFontComboBox, - QFrame, QHBoxLayout, QLabel, QLineEdit, QMainWindow, QMessageBox, QMenu, QPushButton, - QScrollArea, QTabWidget, QToolTip, QVBoxLayout, QWidget) +from PyQt5.QtCore import * +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * glyphSortDescriptors = [ dict(type="alphabetical", allowPseudoUnicode=True), @@ -21,18 +18,19 @@ glyphSortDescriptors = [ ] class CharacterWidget(QWidget): - #characterSelected = pyqtSignal(str) + characterSelected = pyqtSignal(int, str) - def __init__(self, font, parent=None): + def __init__(self, font, squareSize=48, parent=None): super(CharacterWidget, self).__init__(parent) self.font = font self.glyphs = [font[k] for k in font.unicodeData.sortGlyphNames(font.keys(), glyphSortDescriptors)] - self.squareSize = 48 + self.squareSize = squareSize self.columns = 11 self.lastKey = -1 - self.setMouseTracking(True) - self.col = Qt.red + self.moveKey = -1 + #self.setMouseTracking(True) + self.col = QColor.fromRgbF(.2, .3, .7, .15) def updateFont(self, font): self.font = font @@ -47,55 +45,73 @@ class CharacterWidget(QWidget): self.update() def sizeHint(self): - # TODO: adding 2 to glyphlen is cheating, need to find how to properly compensate y_offset - # But why does it even have to be? Does Qt take the origin the painting as the basis for size calculation? Likely... return QSize(self.columns * self.squareSize, - (len(self.glyphs)+2) / self.columns * self.squareSize) - - def mouseMoveEvent(self, event): - if event.modifiers() & Qt.ControlModifier: - widgetPosition = self.mapFromGlobal(event.globalPos()) - key = (widgetPosition.y() // self.squareSize) * self.columns + widgetPosition.x() // self.squareSize - uni = self.glyphs[key].unicode - char = chr(self.glyphs[key].unicode) if uni is not None else "?" - - # http://stackoverflow.com/questions/6598554/is-there-any-way-to-insert-qpixmap-object-in-html - text = '<p align="center" style="font-size: 36pt; font-family: %s">%s</p>' % (QFont().family(), char) - if uni is not None: - text += '<p>U+%04x<p>' % self.glyphs[key].unicode - QToolTip.showText(event.globalPos(), text, self) + math.ceil(len(self.glyphs) / self.columns) * self.squareSize) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.lastKey = (event.y() // self.squareSize) * self.columns + event.x() // self.squareSize - #key_ch = self._chr(self.lastKey) - self.col = Qt.red - - """ - if unicodedata.category(key_ch) != 'Cn': - self.characterSelected.emit(key_ch) - """ + self.moveKey = -1 + if self.lastKey > len(self.glyphs)-1: return + + self.col = QColor.fromRgbF(.2, .3, .7, .15) + uniValue = self.glyphs[self.lastKey].unicode + showName = uniValue is None or unicodedata.category(chr(uniValue)) == 'Zs' + self.characterSelected.emit(1, chr(uniValue) if not showName else self.glyphs[self.lastKey].name) + event.accept() self.update() else: super(CharacterWidget, self).mousePressEvent(event) - + + def mouseMoveEvent(self, event): + if event.buttons() & Qt.LeftButton: + moveKey = (event.y() // self.squareSize) * self.columns + event.x() // self.squareSize + event.accept() + if (moveKey == self.lastKey and self.moveKey != -1): + self.moveKey = -1 + # code duplication :( + uniValue = self.glyphs[self.lastKey].unicode + showName = uniValue is None or unicodedata.category(chr(uniValue)) == 'Zs' + self.characterSelected.emit(1, chr(uniValue) if not showName else self.glyphs[self.lastKey].name) + elif moveKey > len(self.glyphs)-1 \ + or not (moveKey != self.lastKey and moveKey != self.moveKey): return + else: + self.moveKey = moveKey + self.characterSelected.emit(abs(self.moveKey - self.lastKey)+1, "") + self.update() + # elif event.modifiers() & Qt.ControlModifier: + # widgetPosition = self.mapFromGlobal(event.globalPos()) + # key = (widgetPosition.y() // self.squareSize) * self.columns + widgetPosition.x() // self.squareSize + # uni = self.glyphs[key].unicode + # char = chr(self.glyphs[key].unicode) if uni is not None else "?" + + # # http://stackoverflow.com/questions/6598554/is-there-any-way-to-insert-qpixmap-object-in-html + # text = '<p align="center" style="font-size: 36pt; font-family: %s">%s</p>' % (QFont().family(), char) + # if uni is not None: + # text += '<p>U+%04x<p>' % self.glyphs[key].unicode + # text += '<p>%s<p>' % unicodedata.name(chr(self.glyphs[key].unicode)) + # QToolTip.showText(event.globalPos(), text, self) + else: + super(CharacterWidget, self).mouseMoveEvent(event) + + def mouseReleaseEvent(self, event): + if event.button() == Qt.LeftButton: + event.accept() + else: + super(CharacterWidget, self).mouseReleaseEvent(event) + def mouseDoubleClickEvent(self, event): if event.button() == Qt.LeftButton: self.lastKey = (event.y() // self.squareSize) * self.columns + event.x() // self.squareSize - #key_ch = self._chr(self.lastKey) self.col = Qt.green - """ - if unicodedata.category(key_ch) != 'Cn': - self.characterSelected.emit(key_ch) - """ self.update() else: super(CharacterWidget, self).mousePressEvent(event) ''' def resizeEvent(self, event): - self.columns = event.rect().right() // self.squareSize + self.columns = event.size().width() // self.squareSize ''' def paintEvent(self, event): @@ -109,23 +125,51 @@ class CharacterWidget(QWidget): beginColumn = redrawRect.left() // self.squareSize endColumn = redrawRect.right() // self.squareSize + # selection code + firstKey = min(self.lastKey, self.moveKey) + lastKey = max(self.lastKey, self.moveKey) + minKeyInViewport = beginRow * self.columns + beginColumn + select = False + if firstKey != -1 and firstKey < minKeyInViewport and lastKey > minKeyInViewport: + select = True + + # if firstKey == -1: + # column = lastKey % self.columns + # row = lastKey // self.columns + # painter.fillRect(column * self.squareSize + 1, + # row * self.squareSize + 1, self.squareSize - 2, + # self.squareSize - 2, self.col) + # else: + # row_d = firstKey // self.columns + # row_a = lastKey // self.columns + # for row in range(row_d, row_a+1): + # col_d = firstKey % self.columns if row == row_d else 0 + # col_a = lastKey % self.columns if row == row_a else self.columns + # for column in range(col_d, col_a+1): + # painter.fillRect(column * self.squareSize + 1, + # row * self.squareSize + 1, self.squareSize - 2, + # self.squareSize - 2, self.col) + 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.drawRect(column * self.squareSize, row * self.squareSize, self.squareSize, self.squareSize) - for row in range(beginRow, endRow + 1): - for column in range(beginColumn, endColumn + 1): - key = row * self.columns + column - - if key == self.lastKey: + # 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) + if key == lastKey and self.moveKey != -1: + select = not select - if key > len(self.glyphs)-1: break 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 @@ -140,6 +184,7 @@ class CharacterWidget(QWidget): painter.scale(factor, -factor) painter.fillPath(glyph, Qt.black) painter.restore() + class MainWindow(QMainWindow): def __init__(self, font=Font()): @@ -147,7 +192,8 @@ class MainWindow(QMainWindow): self.font = font self.scrollArea = QScrollArea() - self.characterWidget = CharacterWidget(self.font) + squareSize = 48 + self.characterWidget = CharacterWidget(self.font, squareSize, self) self.scrollArea.setWidget(self.characterWidget) # TODO: make shortcuts platform-independent @@ -178,6 +224,20 @@ class MainWindow(QMainWindow): helpMenu.addAction("&About", self.about) helpMenu.addAction("About &Qt", QApplication.instance().aboutQt) + + self.sqSizeSlider = QSlider(Qt.Horizontal) + self.sqSizeSlider.setMinimum(24) + self.sqSizeSlider.setMaximum(96) + #sz = self.sqSizeSlider.sizeHint() + #self.sqSizeSlider.setSize(.7*sz.width(), sz.height()) + self.sqSizeSlider.setValue(squareSize) + self.sqSizeSlider.sliderMoved.connect(self._tipValue) + self.sqSizeSlider.valueChanged.connect(self._squareSizeChanged) + self.selectionLabel = QLabel() + 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.setWindowTitle(os.path.basename(self.font.path.rstrip(os.sep))) @@ -212,7 +272,23 @@ class MainWindow(QMainWindow): def saveAndExit(self): # TODO: check if font changed QApplication.instance().quit() + + def _tipValue(self): + text = str(self.sqSizeSlider.value()) + QToolTip.showText(QCursor.pos(), text, self) + + def _selectionChanged(self, count, glyph): + prefix = glyph + " " if count <= 1 else "" + self.selectionLabel.setText(prefix + "(" + str(count) + " selected)") + + def _squareSizeChanged(self): + self.characterWidget.updateSize(self.sqSizeSlider.value()) + """ + def resizeEvent(self, event): + super(MainWindow, self).resizeEvent(event) + self.characterWidget.resizeEvent(event) + """ def fontInfo(self): # If a window is already opened, bring it to the front, else make another one. @@ -253,7 +329,7 @@ class MainWindow(QMainWindow): from svgViewer import MainGfxWindow if not (hasattr(self, 'glyphViewWindow') and self.glyphViewWindow.isVisible()): # XXX: window collapses when passing self as parent... - self.glyphViewWindow = MainGfxWindow(self.font["a"], self) + self.glyphViewWindow = MainGfxWindow(self.font, self.font["a"], self) self.glyphViewWindow.show() else: self.glyphViewWindow.raise_() @@ -274,7 +350,7 @@ if __name__ == '__main__': representationFactories.registerAllFactories() #with PyCallGraph(output=GraphvizOutput()): app = QApplication(sys.argv) - window = MainWindow(Font("C:\\Veloce.ufo")) + window = MainWindow(Font("C:\\CharterNova-Regular.ufo")) window.resize(565, 430) window.show() sys.exit(app.exec_()) diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py deleted file mode 100644 index 70c9738..0000000 --- a/Lib/defconQt/glyphView.py +++ /dev/null @@ -1,6 +0,0 @@ -class MainSpaceWindow(QWidget): - def __init__(self): - self.scene = QGraphicsScene() - - layout = QVBoxLayout(self) - layout.addWidget(self.scene)
\ No newline at end of file diff --git a/Lib/defconQt/spacecenter.py b/Lib/defconQt/spacecenter.py index 61939b0..1295ca9 100644 --- a/Lib/defconQt/spacecenter.py +++ b/Lib/defconQt/spacecenter.py @@ -75,21 +75,22 @@ class GlyphsCanvas(QWidget): painter.fillRect(0, 0, self.width(), self.height(), Qt.white) painter.translate(self.padding, self.ptSize+self.font.info.descender*self.scale) - cur_width = self.padding + cur_width = 0 for c in self.string: - if c not in self.font: continue + glyph = self.font.unicodeData.glyphNameForUnicode(ord(c)) + if glyph not in self.font: continue # line wrapping - if cur_width + self.font[c].width*self.scale + self.padding > self.width(): + if cur_width + self.font[glyph].width*self.scale + self.padding > self.width(): painter.translate(-cur_width+self.padding, self.ptSize) - cur_width = self.font[c].width*self.scale + cur_width = self.font[glyph].width*self.scale else: - cur_width += self.font[c].width*self.scale - glyph = self.font[c].getRepresentation("defconQt.QPainterPath") + cur_width += self.font[glyph].width*self.scale + glyphPath = self.font[glyph].getRepresentation("defconQt.QPainterPath") painter.save() painter.scale(self.scale, -self.scale) - painter.fillPath(glyph, Qt.black) + painter.fillPath(glyphPath, Qt.black) painter.restore() - painter.translate(self.font[c].width*self.scale, 0) + painter.translate(self.font[glyph].width*self.scale, 0) ''' painter.setPen( @@ -103,23 +104,24 @@ class GlyphsCanvas(QWidget): ''' class SpaceTable(QTableWidget): - def __init__(self, font, glyphs="", parent=None): + def __init__(self, font, string="", parent=None): self.font = font - self.glyphs = glyphs - super(SpaceTable, self).__init__(4, len(self.glyphs), parent) + self.string = string + super(SpaceTable, self).__init__(4, len(self.string), parent) data = [None, "Width", "Left", "Right"] for index, item in enumerate(data): cell = QTableWidgetItem(item) # don't set ItemIsEditable cell.setFlags(Qt.ItemIsEnabled) self.setItem(index, 0, cell) + self.setColumnWidth(0, .6*self.columnWidth(0)) self.horizontalHeader().hide() self.verticalHeader().hide() # always show a scrollbar to fix layout self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.resizeRowsToContents() self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)) - self.fillGlyphs(self.font, self.glyphs) + self.fillGlyphs(self.font, self.string) self.setEditTriggers(QAbstractItemView.CurrentChanged) def sizeHint(self): @@ -130,24 +132,30 @@ class SpaceTable(QTableWidget): height += margins.top() + margins.bottom() return QSize(self.width(), height) - def fillGlyphs(self, font, glyphs): - ''' - def glyphTableWidgetItem(content): + def fillGlyphs(self, font, string): + def glyphTableWidgetItem(content, blockEdition=False): + if content is not None: content = str(content) item = QTableWidgetItem(content) - item.setTextAlignment(Qt.AlignCenter) + if content is None or blockEdition: + # don't set ItemIsEditable + item.setFlags(Qt.ItemIsEnabled) + #item.setTextAlignment(Qt.AlignCenter) return item - ''' - self.setColumnCount(len(glyphs)+1) + + self.setColumnCount(len(string)+1) dropped = 0 - for index, glyph in enumerate(glyphs): + for index, char in enumerate(string): + glyph = font.unicodeData.glyphNameForUnicode(ord(char)) + i = index-dropped+1 if glyph not in font: dropped += 1; continue # TODO: should glyph name edit really be permitted here? # TODO: also find glyphs by /name or should be abstracted by input area or main object? - self.setItem(0, index-dropped+1, QTableWidgetItem(font[glyph].name)) - self.setItem(1, index-dropped+1, QTableWidgetItem(str(font[glyph].width))) - self.setItem(2, index-dropped+1, QTableWidgetItem(str(font[glyph].leftMargin))) - self.setItem(3, index-dropped+1, QTableWidgetItem(str(font[glyph].rightMargin))) - self.setColumnCount(len(glyphs)+1-dropped) + self.setItem(0, i, glyphTableWidgetItem(font[glyph].name, True)) + self.setItem(1, i, glyphTableWidgetItem(font[glyph].width)) + self.setItem(2, i, glyphTableWidgetItem(font[glyph].leftMargin)) + self.setItem(3, i, glyphTableWidgetItem(font[glyph].rightMargin)) + self.setColumnWidth(i, .7*self.columnWidth(i)) + self.setColumnCount(len(string)+1-dropped) def wheelEvent(self, event): cur = self.horizontalScrollBar().value() diff --git a/Lib/defconQt/svgViewer.py b/Lib/defconQt/svgViewer.py index 0208cda..34fd07c 100644 --- a/Lib/defconQt/svgViewer.py +++ b/Lib/defconQt/svgViewer.py @@ -8,13 +8,13 @@ from PyQt5.QtSvg import QGraphicsSvgItem class MainGfxWindow(QMainWindow): - def __init__(self, glyph=None, parent=None): + def __init__(self, font=None, glyph=None, parent=None): super(MainGfxWindow, self).__init__(parent) self.currentPath = '' self.view = SvgView() - self.view.setGlyph(glyph) + self.view.setGlyph(font, glyph) fileMenu = QMenu("&File", self) openAction = fileMenu.addAction("&Open...") @@ -153,14 +153,31 @@ class SvgView(QGraphicsView): p.drawTiledPixmap(self.viewport().rect(), self.backgroundBrush().texture()) p.restore() - - def drawPoints(self): + + def addOutlines(self): + s = self.scene() + #painter = QPainter(self.viewport()) + #painter.translate(0, self.height()*(1+self._font.info.descender/self._font.info.unitsPerEm)) + #painter.scale(1, -1) + #painter.setRenderHint(QPainter.Antialiasing) + # outlines + path = self._glyph.getRepresentation("defconQt.QPainterPath") + s.addPath(path, brush=QBrush(Qt.black)) + # components + ''' + path = self._glyph.getRepresentation("defconAppKit.OnlyComponentsNSBezierPath") + self._componentFillColor.set() + path.fill() + ''' + + def addPoints(self): # work out appropriate sizes and # skip if the glyph is too small - painter = QPainter(self.viewport()) - painter.translate(0, self.height()) - painter.scale(1, -1) - #painter.translate(0, 400) + s = self.scene() + #painter = QPainter(self.viewport()) + #painter.translate(0, self.height()*(1+self._font.info.descender/self._font.info.unitsPerEm)) + #painter.scale(1, -1) + #painter.setRenderHint(QPainter.Antialiasing) pointSize = 1000#self._impliedPointSize if pointSize > 550: startPointSize = 21 @@ -188,7 +205,9 @@ class SvgView(QGraphicsView): points = [] # start point if self._showOnCurvePoints and outlineData["startPoints"]: - startWidth = startHeight = self.roundPosition(startPointSize * self._inverseScale) + startWidth = startHeight = self.roundPosition(startPointSize)# * self._inverseScale) + print("Morsay") + print(startWidth) startHalf = startWidth / 2.0 path = QPainterPath() for point, angle in outlineData["startPoints"]: @@ -203,7 +222,8 @@ class SvgView(QGraphicsView): path.addEllipse(x-startHalf, y-startHalf, startWidth, startHeight) #self._startPointColor.set() #path.fill() - painter.fillPath(path, Qt.blue) + #painter.fillPath(path, Qt.blue) + s.addPath(path, brush=QBrush(Qt.blue)) # off curve if self._showOffCurvePoints and outlineData["offCurvePoints"]: # lines @@ -213,30 +233,36 @@ class SvgView(QGraphicsView): path.lineTo(*point2) #self._bezierHandleColor.set() #path.setLineWidth_(1.0 * self._inverseScale) - painter.drawPath(path) + #painter.setPen(QPen(Qt.black, 1.0 * self._inverseScale)) + # painter.drawPath(path) + s.addPath(path, Qt.black) # points - offWidth = offHeight = self.roundPosition(offCurvePointSize * self._inverseScale) + offWidth = offHeight = self.roundPosition(offCurvePointSize)# * self._inverseScale) offHalf = offWidth / 2.0 path = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] + print(x,y) + print(offWidth, offHeight) + print() points.append((x, y)) x = self.roundPosition(x - offHalf) y = self.roundPosition(y - offHalf) path.addEllipse(x, y, offWidth, offHeight) - #path.setLineWidth_(3.0 * self._inverseScale) + #path.setLineWidth_(3.0#* self._inverseScale) #self._pointStrokeColor.set() - painter.drawPath(path) + #s.addPath(path, QPen(QBrush(Qt.darkGray), 3.0)) #self._backgroundColor.set() - painter.fillPath(path, Qt.green) + s.addPath(path, brush=QBrush(Qt.green)) #self._pointColor.set() #path.setLineWidth_(1.0 * self._inverseScale) + s.addPath(path, QPen(QBrush(Qt.black), 1.0)) #path.stroke() # on curve if self._showOnCurvePoints and outlineData["onCurvePoints"]: - width = height = self.roundPosition(onCurvePointSize * self._inverseScale) + width = height = self.roundPosition(onCurvePointSize)# * self._inverseScale) half = width / 2.0 - smoothWidth = smoothHeight = self.roundPosition(onCurveSmoothPointSize * self._inverseScale) + smoothWidth = smoothHeight = self.roundPosition(onCurveSmoothPointSize)# * self._inverseScale) smoothHalf = smoothWidth / 2.0 path = QPainterPath() for point in outlineData["onCurvePoints"]: @@ -252,9 +278,11 @@ class SvgView(QGraphicsView): path.addRect(x, y, width, height) #self._pointStrokeColor.set() #path.setLineWidth_(3.0 * self._inverseScale) - painter.drawPath(path) + # painter.drawPath(path) + s.addPath(path, Qt.black) #self._pointColor.set() - painter.fillPath(path, Qt.red) + # painter.fillPath(path, Qt.red) + s.addPath(path, brush=QBrush(Qt.red)) # text """ if self._showPointCoordinates and coordinateSize: @@ -281,9 +309,9 @@ class SvgView(QGraphicsView): s = self.scene() s.clear() self.resetTransform() - self.scale(1, -1) + #self.scale(1, -1) - s.addPath(path, brush=QBrush(Qt.gray)) + #s.addPath(path, brush=QBrush(Qt.gray)) #s.setSceneRect(path.boundingRect().adjusted(-10, -10, 10, 10)) def openFile(self, svg_file): @@ -331,18 +359,26 @@ class SvgView(QGraphicsView): s.setSceneRect(self.outlineItem.boundingRect().adjusted(-10, -10, 10, 10)) def roundPosition(self, value): + print("ROUND " + str(value)) value = value * self._scale value = round(value) - .5 value = value * self._inverseScale + print("ROUND2 " + str(value)) return value - def setGlyph(self, glyph): + def setGlyph(self, font, glyph): + self._font = font self._glyph = glyph self._inverseScale = 0.1 - self._scale = 1.0 + self._scale = 10 self._showOffCurvePoints = True self._showOnCurvePoints = True - self.openPath(glyph.getRepresentation("defconQt.QPainterPath")) + + self.translate(0, self.height()*(1+self._font.info.descender/self._font.info.unitsPerEm)) + self.scale(1, -1) + self.addOutlines() + self.addPoints() + #self.openPath(glyph.getRepresentation("defconQt.QPainterPath")) def setRenderer(self, renderer): self.renderer = renderer @@ -380,7 +416,8 @@ class SvgView(QGraphicsView): p.drawImage(0, 0, self.image) else: super(SvgView, self).paintEvent(event) - self.drawPoints() + #self.drawOutlines() + #self.drawPoints() def wheelEvent(self, event): factor = pow(1.2, event.angleDelta().y() / 120.0) diff --git a/Lib/defconQt/syntaxhighlighter.py b/Lib/defconQt/syntaxhighlighter.py index 95c538a..4f48e81 100644 --- a/Lib/defconQt/syntaxhighlighter.py +++ b/Lib/defconQt/syntaxhighlighter.py @@ -1,7 +1,7 @@ from PyQt5.QtCore import QFile, QRegExp, Qt -from PyQt5.QtGui import QColor, QFont, QSyntaxHighlighter, QTextCharFormat +from PyQt5.QtGui import QColor, QFont, QPainter, QSyntaxHighlighter, QTextCharFormat from PyQt5.QtWidgets import (QApplication, QFileDialog, QMainWindow, QMenu, - QMessageBox, QTextEdit) + QMessageBox, QPlainTextEdit, QWidget) class MainEditWindow(QMainWindow): def __init__(self, font=None, parent=None): @@ -58,7 +58,18 @@ class MainEditWindow(QMainWindow): fileMenu.addAction("&Save...", self.save, "Ctrl+S") fileMenu.addAction("E&xit", self.quit, "Ctrl+Q") -class TextEditor(QTextEdit): +class LineNumberArea(QWidget): + def __init__(self,editor): + self.codeEditor = editor + super(LineNumberArea, self).__init__(editor) + + def sizeHint(self): + return QSize(self.codeEditor.lineNumberAreaWidth(), 0) + + def paintEvent(self, event): + self.codeEditor.lineNumberAreaPaintEvent(event) + +class TextEditor(QPlainTextEdit): def __init__(self, text=None, parent=None): super(TextEditor, self).__init__(parent) font = QFont() @@ -66,11 +77,13 @@ class TextEditor(QTextEdit): font.setPointSize(10) font.setFixedPitch(True) - self.setAcceptRichText(False) self.setPlainText(text) self.setFont(font) self.highlighter = Highlighter(self.document()) + self.lineNumbers = LineNumberArea(self) + self.blockCountChanged.connect(self.updateLineNumberAreaWidth) + self.updateRequest.connect(self.updateLineNumberArea) def setFontParams(self, family='CamingoCode', ptSize=10, isMono=True): font = QFont() @@ -81,6 +94,59 @@ class TextEditor(QTextEdit): def write(self, features): features.text = self.toPlainText() + + def lineNumberAreaPaintEvent(self, event): + painter = QPainter(self.lineNumbers) + painter.fillRect(event.rect(), QColor(230, 230, 230)) + d = event.rect().topRight() + a = event.rect().bottomRight() + painter.setPen(Qt.darkGray) + painter.drawLine(d.x(), d.y(), a.x(), a.y()) + painter.setPen(Qt.black) + painter.setFont(self.font()) + + block = self.firstVisibleBlock() + blockNumber = block.blockNumber(); + top = int(self.blockBoundingGeometry(block).translated(self.contentOffset()).top()) + bottom = top + int(self.blockBoundingRect(block).height()) + + while block.isValid() and top <= event.rect().bottom(): + if block.isVisible() and bottom >= event.rect().top(): + number = str(blockNumber + 1) + painter.drawText(4, top, self.lineNumbers.width() - 8, + self.fontMetrics().height(), + Qt.AlignRight, number) + block = block.next() + top = bottom + bottom = top + int(self.blockBoundingRect(block).height()) + blockNumber += 1 + + def lineNumberAreaWidth(self): + digits = 1 + top = max(1, self.blockCount()) + while (top >= 10): + top /= 10 + digits += 1 + return 10 + self.fontMetrics().width('9') * digits + + def updateLineNumberArea(self, rect, dy): + + if dy: + self.lineNumbers.scroll(0, dy); + else: + self.lineNumbers.update(0, rect.y(), + self.lineNumbers.width(), rect.height()) + + if rect.contains(self.viewport().rect()): + self.updateLineNumberAreaWidth(0) + + def updateLineNumberAreaWidth(self, newBlockCount): + self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) + + def resizeEvent(self, event): + super(TextEditor, self).resizeEvent(event) + cr = self.contentsRect() + self.lineNumbers.setGeometry(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()) ''' def keyPressEvent(self, event): |
