manuskript/manuskript/ui/views/textEditCompleter.py

165 lines
5.4 KiB
Python
Raw Normal View History

#!/usr/bin/env python
2016-02-07 00:34:22 +13:00
# --!-- coding: utf8 --!--
import re
2016-02-07 00:34:22 +13:00
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
2016-02-07 00:34:22 +13:00
class textEditCompleter(textEditView):
2016-02-07 00:34:22 +13:00
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
2015-06-27 22:20:05 +12:00
self.setMouseTracking(True)
self.refRects = []
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
self.textChanged.connect(self.getRefRects)
self.document().documentLayoutChanged.connect(self.getRefRects)
2016-02-07 00:34:22 +13:00
def setCurrentModelIndex(self, index):
textEditView.setCurrentModelIndex(self, index)
2015-06-28 00:11:26 +12:00
if self._index and not self.completer:
self.setCompleter(completer())
2016-02-07 00:34:22 +13:00
def setCompleter(self, completer):
self.completer = completer
self.completer.activated.connect(self.insertCompletion)
2016-02-07 00:34:22 +13:00
def insertCompletion(self, txt):
tc = self.textCursor()
tc.insertText(txt)
self.setTextCursor(tc)
2016-02-07 00:34:22 +13:00
2015-06-27 20:27:52 +12:00
def textUnderCursor(self, select=False):
tc = self.textCursor()
tc.select(QTextCursor.WordUnderCursor)
2015-06-27 20:27:52 +12:00
if select:
self.setTextCursor(tc)
return tc.selectedText()
2016-02-07 00:34:22 +13:00
def refUnderCursor(self, cursor):
pos = cursor.position()
2015-06-28 22:55:32 +12:00
cursor.select(QTextCursor.BlockUnderCursor)
text = cursor.selectedText()
pos -= cursor.selectionStart()
2015-07-03 03:33:05 +12:00
match = re.findall(Ref.RegExNonCapturing, text)
for m in match:
if text.find(m) <= pos <= text.find(m) + len(m):
return m
2016-02-07 00:34:22 +13:00
# 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)
2015-06-27 20:27:52 +12:00
def createStandardContextMenu(self):
menu = textEditView.createStandardContextMenu(self)
2016-02-07 00:34:22 +13:00
2015-06-27 20:27:52 +12:00
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
2016-02-07 00:34:22 +13:00
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
2016-02-07 00:34:22 +13:00
isShortcut = (event.modifiers() == Qt.ControlModifier and \
event.key() == Qt.Key_Space)
2016-02-07 00:34:22 +13:00
if not self.completer or not isShortcut:
self.completer.setVisible(False)
textEditView.keyPressEvent(self, event)
return
2016-02-07 00:34:22 +13:00
2015-06-27 20:27:52 +12:00
self.popupCompleter()
2016-02-07 00:34:22 +13:00
2015-06-27 20:27:52 +12:00
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))
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
def mouseMoveEvent(self, event):
textEditView.mouseMoveEvent(self, event)
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
onRef = [r for r in self.refRects if r.contains(event.pos())]
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
if not onRef:
qApp.restoreOverrideCursor()
QToolTip.hideText()
return
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
cursor = self.cursorForPosition(event.pos())
ref = self.refUnderCursor(cursor)
if ref:
if not qApp.overrideCursor():
qApp.setOverrideCursor(Qt.PointingHandCursor)
2015-07-03 03:33:05 +12:00
QToolTip.showText(self.mapToGlobal(event.pos()), Ref.tooltip(ref))
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
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:
2015-07-03 03:33:05 +12:00
Ref.open(ref)
2015-06-27 22:20:05 +12:00
qApp.restoreOverrideCursor()
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
def resizeEvent(self, event):
textEditView.resizeEvent(self, event)
self.getRefRects()
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
def getRefRects(self):
cursor = self.textCursor()
f = self.font()
f.setFixedPitch(True)
f.setWeight(QFont.DemiBold)
fm = QFontMetrics(f)
2015-06-27 22:20:05 +12:00
refs = []
2015-07-03 03:33:05 +12:00
for txt in re.finditer(Ref.RegEx, self.toPlainText()):
2015-06-27 22:20:05 +12:00
cursor.setPosition(txt.start())
r = self.cursorRect(cursor)
r.setWidth(fm.width(txt.group(0)))
refs.append(r)
self.refRects = refs
2016-02-07 00:34:22 +13:00
2015-06-27 22:20:05 +12:00
def paintEvent(self, event):
QTextEdit.paintEvent(self, event)
2016-02-07 00:34:22 +13:00
2015-07-10 22:29:25 +12:00
# Debug: paint rects
2016-02-07 00:34:22 +13:00
# painter = QPainter(self.viewport())
# painter.setPen(Qt.gray)
# for r in self.refRects:
# painter.drawRect(r)