forked from OpenShot/openshot-qt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebkit.py
142 lines (116 loc) · 5.36 KB
/
webkit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""
@file
@brief WebKit backend for TimelineWebView
@author Jonathan Thomas <[email protected]>
@author FeRD (Frank Dana) <[email protected]>
@section LICENSE
Copyright (c) 2008-2020 OpenShot Studios, LLC
(http://www.openshotstudios.com). This file is part of
OpenShot Video Editor (http://www.openshot.org), an open-source project
dedicated to delivering high quality video editing and animation solutions
to the world.
OpenShot Video Editor is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenShot Video Editor is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
"""
import os
from functools import partial
from classes import info
from classes.logger import log
from PyQt5.QtCore import QFileInfo, QUrl, Qt, QTimer
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
class LoggingWebKitPage(QWebPage):
"""Override console.log message to display messages"""
def javaScriptConsoleMessage(self, msg, line, source, *args):
self.log_fn('%s@L%d: %s' % (os.path.basename(source), line, msg))
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setObjectName("LoggingWebKitPage")
self.log_fn = log.warning
class TimelineWebKitView(QWebView):
"""QtWebKit Timeline Widget"""
def __init__(self):
"""Initialization code required for widget"""
super().__init__()
self.setObjectName("TimeWebKitView")
self.document_is_ready = False
self.html_path = os.path.join(info.PATH, 'timeline', 'index.html')
# Delete the webview when closed
self.setAttribute(Qt.WA_DeleteOnClose)
# Connect logging web page (for console.log)
self.new_page = LoggingWebKitPage(self)
self.setPage(self.new_page)
# Disable image caching on timeline
self.settings().setObjectCacheCapacities(0, 0, 0)
# Set url from configuration (QUrl takes absolute paths for file system paths, create from QFileInfo)
self.setHtml(self.get_html(), QUrl.fromLocalFile(QFileInfo(self.html_path).absoluteFilePath()))
# Connect signal of javascript initialization to our javascript reference init function
log.info("WebKit backend initializing")
self.page().mainFrame().javaScriptWindowObjectCleared.connect(self.setup_js_data)
def run_js(self, code, callback=None, retries=0):
"""Run JS code async and optionally have a callback for response"""
# Check if document.Ready has fired in JS
if not self.document_is_ready:
# Not ready, try again in a few moments
if retries == 0:
# Log the script contents, the first time
log.debug(
"run_js() called before document ready event. Script queued: %s",
code)
elif retries % 5 == 0:
log.warning(
"WebKit backend still not ready after %d retries.", retries)
else:
log.debug("Script queued, %d retries so far", retries)
QTimer.singleShot(200, partial(self.run_js, code, callback, retries + 1))
return None
# Execute JS code
if callback:
# Pass output to callback
callback(self.page().mainFrame().evaluateJavaScript(code))
else:
return self.page().mainFrame().evaluateJavaScript(code)
def setup_js_data(self):
# Export self as a javascript object in webview
log.info("Registering objects with WebKit")
self.page().mainFrame().addToJavaScriptWindowObject('timeline', self)
def get_html(self):
"""Get HTML for Timeline, adjusted for mixin"""
with open(self.html_path, 'r', encoding='utf-8') as f:
html = f.read()
return html.replace(
'<!--MIXIN_JS_INCLUDE-->',
"""
<script type="text/javascript" src="js/mixin_webkit.js"></script>
""")
def keyPressEvent(self, event):
""" Keypress callback for timeline """
key_value = event.key()
if key_value in [Qt.Key_Shift, Qt.Key_Control]:
# Only pass a few keystrokes to the webview (CTRL and SHIFT)
return QWebView.keyPressEvent(self, event)
else:
# Ignore most keypresses
event.ignore()
def wheelEvent(self, event):
""" Mousewheel scrolling """
if event.modifiers() & Qt.ShiftModifier:
event.accept()
frame = self.page().mainFrame()
# Compute scroll offset from wheel motion
tick_scale = 120
steps = int(event.angleDelta().y() / tick_scale)
delta = -(steps * 100)
log.debug("Scrolling horizontally by %d pixels", delta)
# Update the scroll position using AngularJS
js = f"$('body').scope().scrollLeft({delta});"
frame.evaluateJavaScript(js)
else:
super().wheelEvent(event)