manuskript/manuskript/ui/views/textEditCompleter.py
2016-02-06 12:34:22 +01:00

165 lines
5.4 KiB
Python

#!/usr/bin/env python
# --!-- coding: utf8 --!--
import re
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor, QFont, QFontMetrics
from PyQt5.QtWidgets import QAction, qApp, QToolTip, QTextEdit
from manuskript.ui.editors.completer import completer
from manuskript.ui.views.textEditView import textEditView
from manuskript.models import references as Ref
try:
import enchant
except ImportError:
enchant = None
class textEditCompleter(textEditView):
def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="",
autoResize=False):
textEditView.__init__(self, parent=parent, index=index, html=html, spellcheck=spellcheck, highlighting=True,
dict=dict, autoResize=autoResize)
self.completer = None
self.setMouseTracking(True)
self.refRects = []
self.textChanged.connect(self.getRefRects)
self.document().documentLayoutChanged.connect(self.getRefRects)
def setCurrentModelIndex(self, index):
textEditView.setCurrentModelIndex(self, index)
if self._index and not self.completer:
self.setCompleter(completer())
def setCompleter(self, completer):
self.completer = completer
self.completer.activated.connect(self.insertCompletion)
def insertCompletion(self, txt):
tc = self.textCursor()
tc.insertText(txt)
self.setTextCursor(tc)
def textUnderCursor(self, select=False):
tc = self.textCursor()
tc.select(QTextCursor.WordUnderCursor)
if select:
self.setTextCursor(tc)
return tc.selectedText()
def refUnderCursor(self, cursor):
pos = cursor.position()
cursor.select(QTextCursor.BlockUnderCursor)
text = cursor.selectedText()
pos -= cursor.selectionStart()
match = re.findall(Ref.RegExNonCapturing, text)
for m in match:
if text.find(m) <= pos <= text.find(m) + len(m):
return m
# def event(self, event):
# if event.type() == QEvent.ToolTip:
# cursor = self.cursorForPosition(event.pos())
# ref = self.refUnderCursor(cursor)
# if ref:
# QToolTip.showText(self.mapToGlobal(event.pos()), infoForRef(ref))
# else:
# QToolTip.hideText()
# return True
# return textEditView.event(self, event)
def createStandardContextMenu(self):
menu = textEditView.createStandardContextMenu(self)
a = QAction(self.tr("Insert reference"), menu)
a.triggered.connect(self.popupCompleter)
menu.insertSeparator(menu.actions()[0])
menu.insertAction(menu.actions()[0], a)
return menu
def keyPressEvent(self, event):
if self.completer.isVisible():
if event.key() in (
Qt.Key_Enter,
Qt.Key_Return,
Qt.Key_Escape,
Qt.Key_Tab,
Qt.Key_Backtab):
event.ignore()
return
isShortcut = (event.modifiers() == Qt.ControlModifier and \
event.key() == Qt.Key_Space)
if not self.completer or not isShortcut:
self.completer.setVisible(False)
textEditView.keyPressEvent(self, event)
return
self.popupCompleter()
def popupCompleter(self):
if self.completer:
cr = self.cursorRect()
cr.moveTopLeft(self.mapToGlobal(cr.bottomLeft()))
cr.setWidth(self.completer.sizeHint().width())
self.completer.setGeometry(cr)
self.completer.popup(self.textUnderCursor(select=True))
def mouseMoveEvent(self, event):
textEditView.mouseMoveEvent(self, event)
onRef = [r for r in self.refRects if r.contains(event.pos())]
if not onRef:
qApp.restoreOverrideCursor()
QToolTip.hideText()
return
cursor = self.cursorForPosition(event.pos())
ref = self.refUnderCursor(cursor)
if ref:
if not qApp.overrideCursor():
qApp.setOverrideCursor(Qt.PointingHandCursor)
QToolTip.showText(self.mapToGlobal(event.pos()), Ref.tooltip(ref))
def mouseReleaseEvent(self, event):
textEditView.mouseReleaseEvent(self, event)
onRef = [r for r in self.refRects if r.contains(event.pos())]
if onRef:
cursor = self.cursorForPosition(event.pos())
ref = self.refUnderCursor(cursor)
if ref:
Ref.open(ref)
qApp.restoreOverrideCursor()
def resizeEvent(self, event):
textEditView.resizeEvent(self, event)
self.getRefRects()
def getRefRects(self):
cursor = self.textCursor()
f = self.font()
f.setFixedPitch(True)
f.setWeight(QFont.DemiBold)
fm = QFontMetrics(f)
refs = []
for txt in re.finditer(Ref.RegEx, self.toPlainText()):
cursor.setPosition(txt.start())
r = self.cursorRect(cursor)
r.setWidth(fm.width(txt.group(0)))
refs.append(r)
self.refRects = refs
def paintEvent(self, event):
QTextEdit.paintEvent(self, event)
# Debug: paint rects
# painter = QPainter(self.viewport())
# painter.setPen(Qt.gray)
# for r in self.refRects:
# painter.drawRect(r)