def _init_stylesheet(profile): """Initialize custom stylesheets. Mostly inspired by QupZilla: https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101 https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/tools/scripts.cpp#L119-L132 FIXME:qtwebengine Use QWebEngineStyleSheet once that's available https://codereview.qt-project.org/#/c/148671/ """ old_script = profile.scripts().findScript('_qute_stylesheet') if not old_script.isNull(): profile.scripts().remove(old_script) css = shared.get_user_stylesheet() source = """ (function() {{ var css = document.createElement('style'); css.setAttribute('type', 'text/css'); css.appendChild(document.createTextNode('{}')); document.getElementsByTagName('head')[0].appendChild(css); }})() """.format(javascript.string_escape(css)) script = QWebEngineScript() script.setName('_qute_stylesheet') script.setInjectionPoint(QWebEngineScript.DocumentReady) script.setWorldId(QWebEngineScript.ApplicationWorld) script.setRunsOnSubFrames(True) script.setSourceCode(source) profile.scripts().insert(script)
def _initPreviewToTextSync(self): """Initialize the system per items 1, 2, and 4 above.""" # When a web page finishes loading, reinsert our JavaScript. page = self._dock._widget.webEngineView.page() # Insert our scripts into every loaded page. qwebchannel_js = QFile(':/qtwebchannel/qwebchannel.js') if not qwebchannel_js.open(QIODevice.ReadOnly): raise SystemExit( 'Failed to load qwebchannel.js with error: %s' % qwebchannel_js.errorString()) qwebchannel_js = bytes(qwebchannel_js.readAll()).decode('utf-8') # Set up the QWebChannel. See http://doc.qt.io/qt-5/qtwebchannel-javascript.html. # Run the script containing QWebChannel.js first. beforeScript = QWebEngineScript() beforeScript.setSourceCode(qwebchannel_js + self._jsPreviewSync + self._qtJsInit) beforeScript.setName('qwebchannel.js, previewSync') # Run this JavaScript separated from any JavaScript present in the loaded web page. This provides better security (rogue pages can't access the QWebChannel) and better isolation (handlers, etc. won't conflict, I hope). beforeScript.setWorldId(QWebEngineScript.ApplicationWorld) beforeScript.setInjectionPoint(QWebEngineScript.DocumentCreation) # Per `setWebChannel <http://doc.qt.io/qt-5/qwebenginepage.html#setWebChannel>`_, only one channel is allowed per page. So, don't run this on sub-frames, since it will attempt the creation of more channels for each subframe. beforeScript.setRunsOnSubFrames(False) page.scripts().insert(beforeScript) # Set up the web channel. See https://riverbankcomputing.com/pipermail/pyqt/2015-August/036346.html # and http://stackoverflow.com/questions/28565254/how-to-use-qt-webengine-and-qwebchannel. # For debug, ``set QTWEBENGINE_REMOTE_DEBUGGING=port`` then browse to # http://127.0.0.1:port, where port=60000 works for me. See https://riverbankcomputing.com/pipermail/pyqt/2015-August/036346.html. self.channel = QWebChannel(page) self.channel.registerObject("previewSync", self) # Expose the ``qt.webChannelTransport`` object in the world where these scripts live. page.setWebChannel(self.channel, QWebEngineScript.ApplicationWorld)
def inject_userscripts(): """Register user JavaScript files with the global profiles.""" # The Greasemonkey metadata block support in QtWebEngine only starts at # Qt 5.8. With 5.7.1, we need to inject the scripts ourselves in response # to urlChanged. if not qtutils.version_check('5.8'): return # Since we are inserting scripts into profile.scripts they won't # just get replaced by new gm scripts like if we were injecting them # ourselves so we need to remove all gm scripts, while not removing # any other stuff that might have been added. Like the one for # stylesheets. greasemonkey = objreg.get('greasemonkey') for profile in [default_profile, private_profile]: scripts = profile.scripts() for script in scripts.toList(): if script.name().startswith("GM-"): log.greasemonkey.debug('Removing script: {}' .format(script.name())) removed = scripts.remove(script) assert removed, script.name() # Then add the new scripts. for script in greasemonkey.all_scripts(): # @run-at (and @include/@exclude/@match) is parsed by # QWebEngineScript. new_script = QWebEngineScript() new_script.setWorldId(QWebEngineScript.MainWorld) new_script.setSourceCode(script.code()) new_script.setName("GM-{}".format(script.name)) new_script.setRunsOnSubFrames(script.runs_on_sub_frames) log.greasemonkey.debug('adding script: {}' .format(new_script.name())) scripts.insert(new_script)
def _init_stylesheet(profile): """Initialize custom stylesheets. Partially inspired by QupZilla: https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101 """ old_script = profile.scripts().findScript('_qute_stylesheet') if not old_script.isNull(): profile.scripts().remove(old_script) css = shared.get_user_stylesheet() source = '\n'.join([ '"use strict";', 'window._qutebrowser = window._qutebrowser || {};', utils.read_file('javascript/stylesheet.js'), javascript.assemble('stylesheet', 'set_css', css), ]) script = QWebEngineScript() script.setName('_qute_stylesheet') script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setWorldId(QWebEngineScript.ApplicationWorld) script.setRunsOnSubFrames(True) script.setSourceCode(source) profile.scripts().insert(script)
def injectJS(self,sourceCode,name): script = QWebEngineScript(); script.setSourceCode(sourceCode) script.setName(name) script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setWorldId(QWebEngineScript.MainWorld) script.setRunsOnSubFrames(True) self.view.page.scripts().insert(script) self.page.scripts().insert(script)
def _add_script(script, injection_point): new_script = QWebEngineScript() new_script.setInjectionPoint(injection_point) new_script.setWorldId(QWebEngineScript.MainWorld) new_script.setSourceCode(script.code()) new_script.setName("GM-{}".format(script.name)) new_script.setRunsOnSubFrames(script.runs_on_sub_frames) log.greasemonkey.debug("Adding script: {}" .format(new_script.name())) scripts.insert(new_script)
def getProfile(self): profile=QWebEngineProfile("myProfile") profile.cachePath="/home/yyk/Desktop/cache" jsFile = constants.QTWEBCHANNELJS_FILE with open(jsFile, encoding="UTF-8") as file: js = file.read() script = QWebEngineScript(); script.setSourceCode(js) script.setName('qwebchannel.js') script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setWorldId(QWebEngineScript.MainWorld) script.setRunsOnSubFrames(False) profile.scripts().insert(script) return profile
def orbitScripts(connParams): scripts = [] jsFile = QFile(':/share/js/orbit-db/orbitdb.js') if not jsFile.open(QFile.ReadOnly): return scriptJsIpfs = QWebEngineScript() scriptJsIpfs.setName('orbit-db') scriptJsIpfs.setSourceCode(jsFile.readAll().data().decode('utf-8')) scriptJsIpfs.setWorldId(QWebEngineScript.MainWorld) scriptJsIpfs.setInjectionPoint(QWebEngineScript.DocumentCreation) scriptJsIpfs.setRunsOnSubFrames(True) scripts.append(scriptJsIpfs) script = QWebEngineScript() script.setSourceCode('\n'.join([ "document.addEventListener('DOMContentLoaded', function () {", "window.orbitdb = new OrbitDB(window.ipfs)", "})"])) script.setWorldId(QWebEngineScript.MainWorld) return scripts
def ethereumClientScripts(connParams): scripts = [] jsFile = QFile(':/share/js/web3.min.js') if not jsFile.open(QFile.ReadOnly): return None libCode = jsFile.readAll().data().decode('utf-8') libCode += "\n" if connParams.provType == 'http': libCode += w3ScriptHttp.format(rpcurl=connParams.rpcUrl) elif connParams.provType == 'websocket': libCode += w3ScriptWs.format(rpcurl=connParams.rpcUrl) scriptWeb3 = QWebEngineScript() scriptWeb3.setName('web3.js') scriptWeb3.setSourceCode(libCode) scriptWeb3.setWorldId(QWebEngineScript.MainWorld) scriptWeb3.setInjectionPoint(QWebEngineScript.DocumentCreation) scripts.append(scriptWeb3) return scripts
def ipfsClientScripts(connParams): scripts = [] jsFile = QFile(':/share/js/ipfs-http-client/index.min.js') if not jsFile.open(QFile.ReadOnly): return scriptJsIpfs = QWebEngineScript() scriptJsIpfs.setName('ipfs-http-client') libCode = jsFile.readAll().data().decode('utf-8') libCode += "\n" libCode += ipfsInjScript.format( host=connParams.host, port=connParams.apiPort) scriptJsIpfs.setSourceCode(libCode) scriptJsIpfs.setWorldId(QWebEngineScript.MainWorld) scriptJsIpfs.setInjectionPoint(QWebEngineScript.DocumentCreation) scriptJsIpfs.setRunsOnSubFrames(True) scripts.append(scriptJsIpfs) return scripts
def __init__(self): QWebEngineView.__init__(self) url = QDir().current().filePath( "html/QWebEngineView_07_print_request.html") url = QUrl.fromLocalFile(url) self.setUrl(url) web_channel_js = QWebEngineScript() web_channel_js.setInjectionPoint(QWebEngineScript.DocumentCreation) web_channel_js.setWorldId(QWebEngineScript.MainWorld) web_channel_js.setRunsOnSubFrames(True) web_channel_js_file = QFile(":/qwebchannel") web_channel_js_file.open(QFile.ReadOnly) js = str(web_channel_js_file.readAll(), 'utf-8') web_channel_js.setSourceCode(js) self.page().scripts().insert(web_channel_js) # Javascript window.print()를 오버라이드 # 기본 window.print()는 웹브라우져에게 프린터 다이얼로그를 요청하지만 # 받을 수 없기 때문에 QWebChannel을 통해 받는다. override_js_print = QWebEngineScript() override_js_print.setInjectionPoint(QWebEngineScript.DocumentCreation) override_js_print.setWorldId(QWebEngineScript.MainWorld) override_js_print.setName("oveerridejsprint.js") override_js_print.setRunsOnSubFrames(True) override_js_print.setSourceCode( "window.print = function() { " " new QWebChannel(qt.webChannelTransport, function(channel) { " " handler = channel.objects.handler; " " handler.webToAppRequestPrint(); " " });" "};") self.page().scripts().insert(override_js_print) channel = QWebChannel(self.page()) self.page().setWebChannel(channel) self.handler = CallHandler() channel.registerObject('handler', self.handler) # 시그널슬롯 처리 self.handler.request_print.connect(self.printer)
def setUserStyleSheet(self, filePath): userCss = '' if not const.OS_UNIX and not const.OS_MACOS: # Don't grey out selection on losing focus (to prevent graying out # found text) highlightColor = '' highlightedTextColor = '' if const.OS_MACOS: # TODO: ? can not enter this branch highlightColor = '#b6d6fc' highlightedTextColor = '#000' else: pal = self.style().standardPalette() highlightColor = pal.color(QPalette.Highlight).name() highlightedTextColor = pal.color( QPalette.HighlightedText).name() userCss += "::selection {background: %s; color: %s;} " % \ (highlightColor, highlightedTextColor) userCss += gVar.appTools.readAllFileContents(filePath).replace( '\n', '') name = '_app_userstylesheet' oldScript = self._webProfile.scripts().findScript(name) if not oldScript.isNull(): self._webProfile.scripts().remove(oldScript) if not userCss: return script = QWebEngineScript() script.setName(name) script.setInjectionPoint(QWebEngineScript.DocumentReady) script.setWorldId(WebPage.SafeJsWorld) script.setRunsOnSubFrames(True) script.setSourceCode(Scripts.setCss(userCss)) self._webProfile.scripts().insert(script)
def _build_app(self): if self._inspector: os.environ.setdefault('QTWEBENGINE_REMOTE_DEBUGGING', '8001') # build webengine container self._lensview = lv = _QWebView(inspector=self._inspector) self._page = p = _QWebPage() lv.setPage(self._page) # connect to Qt signals lv.loadFinished.connect(self._loaded_cb) self._app.lastWindowClosed.connect(self._last_window_closed_cb) # build webchannel script and inject qwebchannel_js = QFile(':/qtwebchannel/qwebchannel.js') if not qwebchannel_js.open(QIODevice.ReadOnly): raise SystemExit('Failed to load qwebchannel.js with error: %s' % qwebchannel_js.errorString()) qwebchannel_js = bytes(qwebchannel_js.readAll()).decode('utf-8') script = QWebEngineScript() script.setSourceCode(qwebchannel_js + ''' window.lens = window.lens || {}; window.lens._channel = new QWebChannel(qt.webChannelTransport, function(channel) { window.lens.emit = function() { var args = Array.prototype.slice.call(arguments); if (args.length > 0) { channel.objects.bridge._from_bridge(args); } }; channel.objects.bridge._emit_js_signal.connect(function(name, args) { window.lens.__broadcast(name, args); }); }); ''') script.setName('lens-bridge') script.setWorldId(QWebEngineScript.MainWorld) script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setRunsOnSubFrames(True) p.profile().scripts().insert(script) self._channel = QWebChannel(p) p.setWebChannel(self._channel) self._channel.registerObject('bridge', self) # set up scheme handlers for app:// and lens:// self._app_scheme_handler = AppSchemeHandler() self._lens_scheme_handler = LensSchemeHandler() self._interceptor = RequestInterceptor() self._profile = QWebEngineProfile().defaultProfile() self._profile.installUrlSchemeHandler('app'.encode(), self._app_scheme_handler) self._profile.installUrlSchemeHandler('lens'.encode(), self._lens_scheme_handler) self._profile.setRequestInterceptor(self._interceptor) # connect to Lens signals self.on('__close_app', self._close_cb) # center on screen _frame_geometry = lv.frameGeometry() _active_screen = self._app.desktop().screenNumber(self._app.desktop().cursor().pos()) _center = self._app.desktop().screenGeometry(_active_screen).center() _frame_geometry.moveCenter(_center) lv.move(_frame_geometry.topLeft()) self.set_title(self._app_name) self.set_size(self._app_width, self._app_height)
def _build_app(self): if self._inspector: os.environ.setdefault('QTWEBENGINE_REMOTE_DEBUGGING', '8001') # build webengine container self._lensview = lv = _QWebView(inspector=self._inspector) self._page = p = _QWebPage() lv.setPage(self._page) # connect to Qt signals lv.loadFinished.connect(self._loaded_cb) self._app.lastWindowClosed.connect(self._last_window_closed_cb) # build webchannel script and inject qwebchannel_js = QFile(':/qtwebchannel/qwebchannel.js') if not qwebchannel_js.open(QIODevice.ReadOnly): raise SystemExit('Failed to load qwebchannel.js with error: %s' % qwebchannel_js.errorString()) qwebchannel_js = bytes(qwebchannel_js.readAll()).decode('utf-8') script = QWebEngineScript() script.setSourceCode(qwebchannel_js + ''' window.lens = window.lens || {}; window.lens._channel = new QWebChannel(qt.webChannelTransport, function(channel) { window.lens.emit = function() { var args = Array.prototype.slice.call(arguments); if (args.length > 0) { channel.objects.bridge._from_bridge(args); } }; channel.objects.bridge._emit_js_signal.connect(function(name, args) { window.lens.__broadcast(name, args); }); }); ''') script.setName('lens-bridge') script.setWorldId(QWebEngineScript.MainWorld) script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setRunsOnSubFrames(True) p.profile().scripts().insert(script) self._channel = QWebChannel(p) p.setWebChannel(self._channel) self._channel.registerObject('bridge', self) # set up scheme handlers for app:// and lens:// self._app_scheme_handler = AppSchemeHandler() self._lens_scheme_handler = LensSchemeHandler() self._profile = QWebEngineProfile().defaultProfile() self._profile.installUrlSchemeHandler('app'.encode(), self._app_scheme_handler) self._profile.installUrlSchemeHandler('lens'.encode(), self._lens_scheme_handler) # connect to Lens signals self.on('__close_app', self._close_cb) # center on screen _frame_geometry = lv.frameGeometry() _active_screen = self._app.desktop().screenNumber( self._app.desktop().cursor().pos()) _center = self._app.desktop().screenGeometry(_active_screen).center() _frame_geometry.moveCenter(_center) lv.move(_frame_geometry.topLeft()) self.set_title(self._app_name) self.set_size(self._app_width, self._app_height)
def initLayout(self): # ----------------------------left layout---------------------------- # self.treeModel = QStandardItemModel() self.pageItem = QStandardItem(ROOT_ITEM_PAGE) self.pageItem.type = ITEM_TYPE_PAGE_ROOT self.buildPageItem() self.userobjectItem = QStandardItem(ROOT_ITEM_USER_OBJECT) self.userobjectItem.type = ITEM_TYPE_USER_OBJECT_ROOT self.buildUserObjectItem() self.providerRequestItem = QStandardItem(ROOT_ITEM_PROVIDER_REQUESTS) self.providerRequestItem.type = ITEM_TYPE_PROVIDER_REQUESTS_ROOT self.pluginItem = QStandardItem(ROOT_ITEM_PLUGIN) self.pluginItem.type = ITEM_TYPE_PLUGIN_ROOT self.treeModel.appendColumn([ self.pageItem, self.userobjectItem, self.providerRequestItem, self.pluginItem ]) self.treeModel.setHeaderData(0, Qt.Horizontal, 'Model') self.treeView = QTreeView() self.treeView.setModel(self.treeModel) self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.treeView.setContextMenuPolicy(Qt.CustomContextMenu) self.treeView.customContextMenuRequested.connect(self.openContextMenu) self.treeView.doubleClicked.connect(self.onTreeItemDoubleClicked) self.treeView.clicked.connect(self.getDebugData) leftContainer = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 6, 0) # left, top, right, bottom layout.addWidget(self.treeView) leftContainer.setLayout(layout) # ----------------------------middle layout---------------------------- # middleContainer = QWidget() # search shall start not before the user completed typing # filter_delay = DelayedExecutionTimer(self) # new_column.search_bar.textEdited[str].connect(filter_delay.trigger) # filter_delay.triggered[str].connect(self.search) self.tabBar = QTabBar() self.tabBar.setUsesScrollButtons(False) self.tabBar.setDrawBase(False) # self.tabBar.addTab('tab1') # self.tabBar.addTab('tab2') self.pathBar = QWidget() layout = QHBoxLayout() layout.setAlignment(Qt.AlignLeft) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(1) self.pathBar.setLayout(layout) self.searchHolder = QWidget() layout = QHBoxLayout() layout.addWidget(self.tabBar) layout.addWidget(self.pathBar) layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) self.searchHolder.setLayout(layout) self.searchHolder.layout().setContentsMargins(6, 6, 6, 0) self.tabContentWidget = QWidget() self.browser = QWebEngineView() self.browser.setZoomFactor(1.3) self.channel = QWebChannel() self.webObject = WebShareObject() self.channel.registerObject('bridge', self.webObject) self.browser.page().setWebChannel(self.channel) self.webObject.jsCallback.connect(lambda value: self.addUpdate(value)) qwebchannel_js = QFile(':/qtwebchannel/qwebchannel.js') if not qwebchannel_js.open(QIODevice.ReadOnly): raise SystemExit('Failed to load qwebchannel.js with error: %s' % qwebchannel_js.errorString()) qwebchannel_js = bytes(qwebchannel_js.readAll()).decode('utf-8') script = QWebEngineScript() script.setSourceCode(qwebchannel_js) script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setName('qtwebchannel.js') script.setWorldId(QWebEngineScript.MainWorld) script.setRunsOnSubFrames(True) self.browser.page().scripts().insert(script) Utils.scriptCreator(os.path.join('..', 'resources', 'js', 'event.js'), 'event.js', self.browser.page()) self.browser.page().setWebChannel(self.channel) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.initQCheckBoxUI()) layout.addWidget(self.initSearchView()) layout.addWidget(self.browser) self.tabContentWidget.setLayout(layout) self.searchWidget.hide() middleContainer.stackedWidget = QStackedWidget() self.url = XulDebugServerHelper.HOST + 'list-pages' self.showXulDebugData(self.url) middleContainer.stackedWidget.addWidget(self.tabContentWidget) middleContainer.stackedWidget.addWidget(QLabel('tab2 content')) self.tabBar.currentChanged.connect( lambda: middleContainer.stackedWidget.setCurrentIndex( self.tabBar.currentIndex())) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.searchHolder) layout.addWidget(middleContainer.stackedWidget) middleContainer.setLayout(layout) # ----------------------------right layout---------------------------- # self.rightSiderClickInfo = 'Property' self.rightSiderTabWidget = QTabWidget() self.rightSiderTabBar = QTabBar() self.rightSiderTabWidget.setTabBar(self.rightSiderTabBar) self.rightSiderTabWidget.setTabPosition(QTabWidget.East) self.favoriteTreeView = FavoriteTreeView(self) # self.propertyEditor = PropertyEditor(['Key', 'Value']) self.inputWidget = UpdateProperty() self.rightSiderTabWidget.addTab(self.inputWidget, IconTool.buildQIcon('property.png'), 'Property') self.rightSiderTabWidget.setStyleSheet( ('QTab::tab{height:60px;width:32px;color:black;padding:0px}' 'QTabBar::tab:selected{background:lightgray}')) # self.rightSiderTabWidget.addTab(self.propertyEditor,IconTool.buildQIcon('property.png'),'property') self.rightSiderTabWidget.addTab(self.favoriteTreeView, IconTool.buildQIcon('favorites.png'), 'Favorites') self.rightSiderTabBar.tabBarClicked.connect(self.rightSiderClick) # ----------------------------entire layout---------------------------- # self.contentSplitter = QSplitter(Qt.Horizontal) self.contentSplitter.setHandleWidth(0) # thing to grab the splitter self.contentSplitter.addWidget(leftContainer) self.contentSplitter.addWidget(middleContainer) self.contentSplitter.addWidget(self.rightSiderTabWidget) self.contentSplitter.setStretchFactor(0, 0) self.contentSplitter.setStretchFactor(1, 6) self.contentSplitter.setStretchFactor(2, 6) self.mainSplitter = QSplitter(Qt.Vertical) self.mainSplitter.setHandleWidth(0) self.mainSplitter.addWidget(self.contentSplitter) self.mainSplitter.addWidget(self.consoleWindow) self.mainSplitter.setStretchFactor(1, 0) self.mainSplitter.setStretchFactor(2, 1) self.setCentralWidget(self.mainSplitter) # 默认隐藏掉复选框 self.groupBox.setHidden(True)