PyQt テキストエディタ試作

f:id:togari_takamoto:20120320163442p:plain
現時点では、D&Dでファイル開く、行番号表示、タブ表示、ファイル終端表示(EOF)のみ

#encoding:utf-8
import sys
from see import see
from PyQt4 import QtGui,QtWebKit,QtCore
class Main(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.resize(800, 500)
        self.setAcceptDrops(True)
        self.setWindowTitle("CuteEditor")
        self.editor = Editor()
        self.openAction = QtGui.QAction('&Exit', self)
        self.openAction.setShortcut('Ctrl+F')
        self.menubar = self.menuBar()
        self.fileMenu = self.menubar.addMenu("ファイル")

        self.statusBar()
        self.fileMenu.addAction(self.openAction)
        self.setCentralWidget(self.editor)
    def dragEnterEvent(self, e):
        if e.mimeData().hasUrls():
            e.accept()
        else:
            e.ignore()
    def dropEvent(self, e):
        print("c")
        for u in e.mimeData().urls():
            p = u.toLocalFile()
        self.fileOpen(p)
    def fileOpenByDialog(self,e):
        p = QtGui.QFileDialog.getOpenFileName(self ,"テキストを開く", "/Users/", "All (*)" )
        self.fileOpen(p)
    def fileOpen(self,filePath):
        with open(filePath,"r") as f:
            self.editor.setPlainText(f.read())

class Editor(QtGui.QTextEdit):
    def __init__(self, parent=None):
        super(Editor,self).__init__(parent)
        self.setViewportMargins(self.fontMetrics().width("8")*8,0,0,0)
        self.side = QtGui.QWidget(self)
        self.side.installEventFilter(self)
        self.side.setGeometry(0,0,self.fontMetrics().width("8")*8,self.height())
        self.setAcceptDrops(False)
    def paintEvent(self,e):
        super(Editor,self).paintEvent(e)
        self.drawEOF()
        if self.side.height() == self.height():
            num = 1
        else:
            num = 0
        self.side.setGeometry(0,0,self.fontMetrics().width("8")*8,self.height()+num)
        self.drawTab()
    def eventFilter(self,o,e):
        if e.type() == QtCore.QEvent.Paint and o == self.side:
            self.drawLineNumber(o)
            return True
        return False
    def drawEOF(self):
        c = self.textCursor()
        c.movePosition(c.End)
        r = self.cursorRect(c)
        paint = QtGui.QPainter(self.viewport())
        paint.setPen(QtGui.QColor(255, 0, 0))
        paint.setFont(self.currentFont())
        paint.drawText(QtCore.QPoint(r.left(),r.bottom()-3), "[EOF]")
    def drawTab(self):
        tabchar = "›"
        c = self.cursorForPosition(QtCore.QPoint(0,0))
        paint = QtGui.QPainter()
        paint.begin(self.viewport())
        paint.setPen(QtGui.QColor(150,150,150))
        paint.setFont(self.currentFont())
        c = self.document().find("	",c)
        while not c.isNull():
            c.movePosition(QtGui.QTextCursor.Left)
            r = self.cursorRect(c)
            if r.bottom() > self.height()+10: break
            paint.drawText(QtCore.QPoint(r.left(),r.bottom()-3),tabchar)
            c.movePosition(QtGui.QTextCursor.Right)
            c = self.document().find("	",c)
        paint.end()
    def drawLineNumber(self,o):
        c = self.cursorForPosition(QtCore.QPoint(0,0))
        block = c.block()
        paint = QtGui.QPainter()
        paint.begin(o)
        paint.setPen(QtGui.QColor(0,0,0))
        paint.setFont(self.currentFont())
        while block.isValid():
            c.setPosition(block.position())
            r = self.cursorRect(c)
            if r.bottom() > self.height()+10: break
            paint.drawText(QtCore.QPoint(10,r.bottom()-3),str(block.blockNumber()+1))
            block = block.next()
        paint.end()
def main():
    app = QtGui.QApplication(sys.argv)
    m = Main()
    m.openAction.triggered.connect(m.fileOpenByDialog)
    m.show()
    sys.exit(app.exec_())
if __name__ == '__main__':
    main()