copy/paste updates

- unify handling of shortcut key and context menu cut/copy/paste
- don't adjust selection on window/popup focus, so context works on win32 now
- remove undocumented shift to keep behaviour
This commit is contained in:
Damien Elmes 2012-05-04 23:54:36 +09:00
parent 1794c69fe7
commit cfa95af722
2 changed files with 54 additions and 43 deletions

View file

@ -917,49 +917,54 @@ class EditorWebView(AnkiWebView):
self.strip = self.editor.mw.pm.profile['stripHTML']
def keyPressEvent(self, evt):
self._curKey = True
self.origClip = None
shiftPaste = (evt.modifiers() == (Qt.ShiftModifier | Qt.ControlModifier)
and evt.key() == Qt.Key_V)
if evt.matches(QKeySequence.Paste) or shiftPaste:
self.prepareClip(shiftPaste)
if shiftPaste:
self.triggerPageAction(QWebPage.Paste)
if evt.matches(QKeySequence.Paste):
self.onPaste()
return evt.accept()
elif evt.matches(QKeySequence.Copy):
self.triggerPageAction(QWebPage.Copy)
self._flagAnkiText()
self.onCopy()
return evt.accept()
elif evt.matches(QKeySequence.Cut):
self.triggerPageAction(QWebPage.Cut)
self._flagAnkiText()
self.onCut()
return evt.accept()
QWebView.keyPressEvent(self, evt)
self.restoreClip()
def onCut(self):
self.triggerPageAction(QWebPage.Cut)
self._flagAnkiText()
def onCopy(self):
self.triggerPageAction(QWebPage.Copy)
self._flagAnkiText()
def onPaste(self):
mime = self.prepareClip()
self.triggerPageAction(QWebPage.Paste)
self.restoreClip(mime)
def mouseReleaseEvent(self, evt):
if not isMac and not isWin and evt.button() == Qt.MidButton:
# middle click on x11; munge the clipboard before standard
# handling
self.prepareClip(mode=QClipboard.Selection)
mime = self.prepareClip(mode=QClipboard.Selection)
AnkiWebView.mouseReleaseEvent(self, evt)
self.restoreClip(mode=QClipboard.Selection)
self.restoreClip(mime, mode=QClipboard.Selection)
else:
AnkiWebView.mouseReleaseEvent(self, evt)
def focusInEvent(self, evt):
window = False
if evt.reason() in (Qt.ActiveWindowFocusReason, Qt.PopupFocusReason):
# editor area got focus again; need to tell js not to adjust cursor
self.eval("mouseDown++;")
window = True
AnkiWebView.focusInEvent(self, evt)
if evt.reason() == Qt.TabFocusReason:
self.eval("focusField(0);")
elif evt.reason() == Qt.BacktabFocusReason:
n = len(self.editor.note.fields) - 1
self.eval("focusField(%d);" % n)
# Buggy; disable for now.
# def contextMenuEvent(self, evt):
# # adjust in case the user is going to paste
# self.prepareClip()
# QWebView.contextMenuEvent(self, evt)
# self.restoreClip()
elif window:
self.eval("mouseDown--;")
def dropEvent(self, evt):
oldmime = evt.mimeData()
@ -983,7 +988,7 @@ class EditorWebView(AnkiWebView):
# tell the drop target to take focus so the drop contents are saved
self.eval("dropTarget.focus();")
def prepareClip(self, keep=False, mode=QClipboard.Clipboard):
def prepareClip(self, mode=QClipboard.Clipboard):
clip = self.editor.mw.app.clipboard()
mime = clip.mimeData(mode=mode)
if mime.hasHtml() and mime.html().startswith("<!--anki-->"):
@ -993,22 +998,14 @@ class EditorWebView(AnkiWebView):
mime.setHtml(html)
return
self.saveClip(mode=mode)
if keep:
new = QMimeData()
if mime.hasHtml():
new.setHtml(_filterHTML(mime.html()))
else:
new.setText(mime.text())
mime = new
else:
mime = self._processMime(mime)
mime = self._processMime(mime)
clip.setMimeData(mime, mode=mode)
def restoreClip(self, mode=QClipboard.Clipboard):
if not self.origClip:
def restoreClip(self, mime, mode=QClipboard.Clipboard):
if not mime:
return
clip = self.editor.mw.app.clipboard()
clip.setMimeData(self.origClip, mode=mode)
clip.setMimeData(mime, mode=mode)
def saveClip(self, mode):
# we don't own the clipboard object, so we need to copy it
@ -1022,7 +1019,7 @@ class EditorWebView(AnkiWebView):
n.setUrls(mime.urls())
if mime.hasImage():
n.setImageData(mime.imageData())
self.origClip = n
return n
def _processMime(self, mime):
# print "html=%s image=%s urls=%s txt=%s" % (

View file

@ -39,6 +39,7 @@ class AnkiWebPage(QWebPage):
##########################################################################
class AnkiWebView(QWebView):
def __init__(self):
QWebView.__init__(self)
self.setObjectName("mainText")
@ -51,8 +52,8 @@ class AnkiWebView(QWebView):
self.setKeyHandler()
self.connect(self, SIGNAL("linkClicked(QUrl)"), self._linkHandler)
self.connect(self, SIGNAL("loadFinished(bool)"), self._loadFinished)
self._curKey = None
self.allowDrops = False
def keyPressEvent(self, evt):
if evt.matches(QKeySequence.Copy):
self.triggerPageAction(QWebPage.Copy)
@ -62,35 +63,42 @@ class AnkiWebView(QWebView):
evt.accept()
return
QWebView.keyPressEvent(self, evt)
def keyReleaseEvent(self, evt):
if self._keyHandler:
if self._keyHandler(evt):
evt.accept()
return
QWebView.keyPressEvent(self, evt)
def contextMenuEvent(self, evt):
if isWin:
# broken on windows for now; events are being fired at the popup
return
m = QMenu(self)
m.addAction(self.pageAction(QWebPage.Cut))
m.addAction(self.pageAction(QWebPage.Copy))
m.addAction(self.pageAction(QWebPage.Paste))
a = m.addAction(_("Cut"))
a.connect(a, SIGNAL("activated()"), self.onCut)
a = m.addAction(_("Copy"))
a.connect(a, SIGNAL("activated()"), self.onCopy)
a = m.addAction(_("Paste"))
a.connect(a, SIGNAL("activated()"), self.onPaste)
m.popup(QCursor.pos())
def dropEvent(self, evt):
pass
def setLinkHandler(self, handler=None):
if handler:
self.linkHandler = handler
else:
self.linkHandler = self._openLinksExternally
self._bridge.setLinkHandler(self.linkHandler)
def setKeyHandler(self, handler=None):
# handler should return true if event should be swallowed
self._keyHandler = handler
def setHtml(self, html, loadCB=None):
self._loadFinishedCB = loadCB
QWebView.setHtml(self, html)
def stdHtml(self, body, css="", bodyClass="", loadCB=None, js=None, head=""):
if isMac:
button = "font-weight: bold; height: 24px;"
@ -110,20 +118,26 @@ button {
<body class="%s">%s</body></html>""" % (
fontForPlatform(), button, css, js or anki.js.jquery+anki.js.browserSel,
head, bodyClass, body), loadCB)
def setBridge(self, bridge):
self._bridge.setBridge(bridge)
def eval(self, js):
self.page().mainFrame().evaluateJavaScript(js)
def _openLinksExternally(self, url):
openLink(url)
def _jsErr(self, msg, line, srcID):
if getattr(sys, 'frozen', None):
obj = sys.stderr
else:
obj = sys.stdout
obj.write(_("JS error on line %(a)d: %(b)s") % dict(a=line, b=msg+"\n"))
def _linkHandler(self, url):
self.linkHandler(url.toString())
def _loadFinished(self):
self.page().mainFrame().addToJavaScriptWindowObject("py", self._bridge)
if self._loadFinishedCB: