The example of the code snippet is here:
from PySide2 import QtCore, QtGui, QtWidgets, QtWebChannel
from PySide2.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
class AppWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.view = WebView(self)
self.setCentralWidget(self.view)
self.view.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
self.view.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True);
self.page = self.view.page()
self.page.setDevToolsPage(self.page)
#self.inspector = QWebInspector(self) # Crash is here!!!
#self.inspector.setPage(self.page)
#self.inspector.hide()
The three lines above were working perfectly in previous versions.
What is the alternative to QWebInspector in PySide2?
There is no equivalent QWebInspector class for QWebEngine, because the dev tools are provided by the underlying Chrome browser. An environment variable needs to be set to enable the tools, and you can then access them via a separate Chrome-based browser - see Qt WebEngine Developer Tools in the Qt5 docs for the full details.
Below is a simple demo based on your example code:
import sys, os
DEBUG_PORT = '5588'
DEBUG_URL = 'http://127.0.0.1:%s' % DEBUG_PORT
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = DEBUG_PORT
from PySide2 import QtCore, QtGui, QtWidgets, QtWebChannel
from PySide2.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
class AppWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.view = QWebEngineView(self)
self.setCentralWidget(self.view)
self.view.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
self.view.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True)
self.view.loadFinished.connect(self.handleLoaded)
self.view.load(QtCore.QUrl('https://google.com/'))
self.inspector = QWebEngineView()
self.inspector.setWindowTitle('Web Inspector')
self.inspector.load(QtCore.QUrl(DEBUG_URL))
def handleLoaded(self, ok):
if ok:
self.view.page().setDevToolsPage(self.inspector.page())
self.inspector.show()
app = QtWidgets.QApplication(sys.argv)
win = AppWindow()
win.setGeometry(600, 100, 600, 480)
win.show()
app.exec_()
Related
I want to download a file and at the same time redirect to a new page. The user is shown a page with a link for the download. When they click it, I want to start the download then redirect to another page so they can't keep clicking it. However, I can only seem to get one or the other to work.
from flask import Flask, render_template, redirect, url_for, session, request, flash, send_file
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, BooleanField
from pytube import YouTube
import os
import random, string
import re
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
session_id = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
class url_form(FlaskForm):
link = StringField('Enter link of YouTube video you would like to convert...')
audio = BooleanField('Audio Only')
submit = SubmitField('Convert')
def download_video(link, just_audio):
yt = YouTube(link)
download_path = 'conversions/'
#global myvar
if just_audio == True:
stream = yt.streams.filter(only_audio=True).first()
tag = 'video'
else:
stream = yt.streams.filter(adaptive=True).first()
tag = 'audio only'
download_video.name = yt.title
download_video.cleanString = re.sub('[^a-zA-Z0-9 \n\.]', '', download_video.name)
download_video.thumbnail = yt.thumbnail_url
download_video.path = stream.download(filename = download_video.cleanString, output_path = download_path)
return
#app.route('/', methods=['GET', 'POST'])
def index():
result = False
form = url_form()
if form.validate_on_submit():
session['link'] = form.link.data
if form.audio.data:
just_audio = True
else:
just_audio = False
session['just_audio'] = just_audio
link = session.get('link')
just_audio = session.get('just_audio')
download_video(link, just_audio)
#download_video(link, just_audio)
#return send_file(download_video.path, attachment_filename=download_video.cleanString + '.mp4', as_attachment=True)
return redirect(url_for('conversion_complete'))
return render_template('index.html', form=form, result=result)
#app.route('/conversion_complete', methods=['GET', 'POST'])
def conversion_complete():
return render_template('conversion_complete.html')
#app.route('/download/', methods=['GET'])
def download():
return send_file(download_video.path, attachment_filename=download_video.cleanString + '.mp4', as_attachment=True)
return render_template('result.html')
<html>
<body>
<h1>Conversion Complete</h1>
<a href='download' target='blank' type='button'><button class='btn btn-default'>Download!</button></a>
</body>
</html>
My urls is not matching with the hashtags. it says 404 url not found.
this is my base.html with hashtag:
$(document).ready(function() {
$("p").each(function(data) {
var strText = $(this).html();
console.log('1. strText=', strText);
var arrElems = strText.match(/#[a-zA-Z0-9]+/g);
console.log('arrElems=', arrElems);
$.each(arrElems, function(index, value){
strText = strText.toString().replace(value, ''+value+'');
});
console.log('2. strText=', strText);
$(this).html(strText);
});
});
my hshtag models.py:
from django.db import models
from blog.models import post
# Create your models here.
class HashTag(models.Model):
tag = models.CharField(max_length=120)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.tag
def get_postss(self):
return post.objects.filter(content__icontains="#" + self.tag)
this is my hashtag view:
from django.shortcuts import render
from django.views import View
from .models import HashTag
# Create your views here.
class HashTagView(View):
def get(self, request, hashtag, *args, **kwargs):
obj, created = HashTag.objects.get_or_create(tag=hashtag)
return render(request, 'hashtags/tag_view.html', {"obj": obj})
i put the url intothe primary url of my site:
from hashtags.views import HashTagView
from django.urls import path, re_path, include
urlpatterns = [
re_path(r'^tags/(?P<hashtag>.*)/$', HashTagView.as_view(), name='hashtag'),
]
There is one issue with your implementation.
1. Browser does not send # part to the server. So if your URL is like /tags/#tag then #tag won't be sent to the server. Further read: Why is the hash part of the URL not available on the server side?
Because of this behavior, your browser will hit /tags/ url. That is the reason of your 404 error.
You can check the example of twitter, If the hashtag is #DelhiElectionResults, then the url for that hashtag is https://twitter.com/hashtag/DelhiElectionResults.
Solution: Just remove # from the url and make it like: /tags/tag/. In your JS, you can use value.replace('#', '') to remove the # from the value.
$.each(arrElems, function(index, value){
strText = strText.toString().replace(value, ''+value+'');
});
I'm planning on executing a javascript function from pyqt QWebEngine. I followed a example which was using a map and map bound were retrieved when a Qt application button was pushed, and wrote a small example.
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
function helloWorld(param1, param2) {
return "Hello world " + param1 + " " + param2;
}
</script>
</body>
</html>
Python:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtWebEngineWidgets import QWebEngineView
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.form_widget = FormWidget(self)
_widget = QWidget()
_layout = QVBoxLayout(_widget)
_layout.addWidget(self.form_widget)
self.setCentralWidget(_widget)
class FormWidget(QWidget):
def __init__(self, parent):
super(FormWidget, self).__init__(parent)
self.__controls()
self.__layout()
self.browser.page().runJavaScript("helloWorld()", self.ready)
def __controls(self):
html = open('test.html', 'r').read()
self.browser = QWebEngineView()
self.browser.setHtml(html)
def __layout(self):
self.vbox = QVBoxLayout()
self.hBox = QVBoxLayout()
self.hBox.addWidget(self.browser)
self.vbox.addLayout(self.hBox)
self.setLayout(self.vbox)
def ready(self, returnValue):
print(returnValue)
def main():
app = QApplication(sys.argv)
win = MainWindow()
win.show()
app.exec_()
if __name__ == '__main__':
sys.exit(main())
Nevertheless, I get the following error:
js: Uncaught ReferenceError: helloWorld is not defined
None ----> This is the return value printed at ready()
What am I missing?
You have 2 errors:
You are calling the function when the page has not yet finished loading.
Your function needs 2 parameters, although it also works but will signal undefined.
Using the above you get the following:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtWebEngineWidgets import QWebEngineView
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.form_widget = FormWidget(self)
_widget = QWidget()
_layout = QVBoxLayout(_widget)
_layout.addWidget(self.form_widget)
self.setCentralWidget(_widget)
class FormWidget(QWidget):
def __init__(self, parent):
super(FormWidget, self).__init__(parent)
self.__controls()
self.__layout()
def __controls(self):
html = open('test.html', 'r').read()
self.browser = QWebEngineView()
self.browser.setHtml(html)
self.browser.loadFinished.connect(self.onLoadFinished)
def onLoadFinished(self, ok):
if ok:
self.browser.page().runJavaScript("helloWorld(1, \"2\")", self.ready)
def __layout(self):
self.vbox = QVBoxLayout()
self.hBox = QVBoxLayout()
self.hBox.addWidget(self.browser)
self.vbox.addLayout(self.hBox)
self.setLayout(self.vbox)
def ready(self, returnValue):
print(returnValue)
def main():
app = QApplication(sys.argv)
win = MainWindow()
win.show()
return app.exec_()
if __name__ == '__main__':
sys.exit(main())
plus:
To visualize the output of the js console you must overwrite the javaScriptConsoleMessage method of QWebEnginePage:
...
class WebEnginePage(QWebEnginePage):
def javaScriptConsoleMessage(self, level, message, lineNumber, sourceID):
print("javaScriptConsoleMessage: ", level, message, lineNumber, sourceID)
class FormWidget(QWidget):
...
def __controls(self):
...
self.browser = QWebEngineView()
self.browser.setPage(WebEnginePage(self.browser))
...
To verify this you must use console.log(...):
*.html
...
<script>
function helloWorld(param1, param2) {
console.log("Hello world")
return "Hello world " + param1 + " " + param2;
}
</script>
...
Output:
javaScriptConsoleMessage: 0 Hello world 12 data:text/html;charset=UTF-8,%3C%21DOCTYPE%20html%3E%0A%3Chtml%3E%0A%0A%3Chead%3E%0A%20%20%20%20%3Cmeta%20charset%3D%22UTF-8%22%3E%0A%3C%2Fhead%3E%0A%0A%3Cbody%3E%0A%0A%3Cscript%3E%0A%20%20%20%20function%20helloWorld%28param1%2C%20param2%29%20%7B%0A%20%20%20%20%09console.log%28%22Hello%20world%22%29%0A%20%20%20%20%20%20%20%20return%20%22Hello%20world%20%22%20%2B%20param1%20%2B%20%22%20%22%20%2B%20param2%3B%0A%20%20%20%20%7D%0A%3C%2Fscript%3E%0A%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E
I use django-swampdragon + angularjs to create simple django app which shows website requests in real-time.
All of the Django logic is okay, but when I try make it respond in real-time the system kind of fails. I think the problem is in Angular, since I haven't used it before.
So, the django-swampdragon part of code:
# routers.py
from swampdragon import route_handler
from swampdragon.route_handler import ModelRouter
from .serializers import HttpRequestSerializer
from .models import HttpRequest
class HttpRequestRouter(ModelRouter):
serializer_class = HttpRequestSerializer
model = HttpRequest
route_name = 'activity-route'
def get_object(self, **kwargs):
return self.model.objects.get(pk=kwargs['pk'])
def get_query_set(self, **kwargs):
return self.model.all()
route_handler.register(HttpRequestRouter)
The Angular.js part of code
// controllers.js
var ActivityControllers = angular.module('ActivityControllers', []);
ActivityControllers.controller('ActivityCtrl', ['$scope', '$dragon', function ($scope, $dragon) {
$scope.channel = 'httprequests';
$scope.datasource = [];
// Subscribe to the activity router
$dragon.onReady(function() {
$dragon.subscribe('activity-route', $scope.channel, {}).then(function(response) {
this.dataMapper = new DataMapper(response.data);
});
$dragon.getList('activity-route', {}).then(function(response) {
$scope.datasource = response.data
});
});
$dragon.onChannelMessage(function(channels, new_request) {
if (indexOf.call(channels, $scope.channel) > -1) {
$scope.$apply(function() {
$scope.datasource.unshift(new_request);
});
}
});
}]);
And, finally, my template part:
<div ng-controller="ActivityCtrl">
<ul ng-repeat="req in datasource">
<li>
<span class="request_date">{$ req.date $} ...</span>
</li>
</ul>
</div>
When I run server.py and open browser on that url/port (http://localhost:9999/) i have this error (in browser):
Traceback (most recent call last):
File "...lib/python3.4/site-packages/tornado/web.py", line 1323, in _execute
result = self.prepare()
File "...lib/python3.4/site-packages/tornado/web.py", line 2014, in prepare
raise HTTPError(self._status_code)
tornado.web.HTTPError: HTTP 404: Not Found
And also this error on the console:
-------- SwampDragon ------
Running SwampDragon on 127.0.0.1:9999
DRAGON_URL: http://localhost:9999/
Version 0.4.2
Debug: True
Quit the server with ctrl+c
---------------------------
WARNING:tornado.access:404 GET / (127.0.0.1) 206.58ms
And, of course, my page with request don't work either.
PLease help me find the error!
Just to be sure, you are running your django server and your swmapdragon server, correct? As in you are doing both:
python server.py
python manage.py runserver
For my application I need to inject JS into the loaded url.
I am using the following snippet from here https://stackoverflow.com/a/10866495/1162305
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((700, 700))
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.browser.LoadURL("http://www.google.com")
dialog.Show()
dialog.browser.RunScript('alert("hello");')
app.MainLoop()
Here I am injecting javascript with RunScript but the problem is, this javascript loads before the webpage loads. How can I load this javascript after the webpage (given url) loaded completely.
I know in plain javascript I can use document.readyState === "complete", but here how can I do it?
According to documentation:
http://wxpython.org/Phoenix/docs/html/html2.WebView.html#phoenix-title-asynchronous-notifications
You should use EVT_WEBVIEW_LOADED event to check if asynchronous methods like LoadURL is completed.
self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.browser)
Complete code could look something like (not tested):
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.browser)
self.SetSizer(sizer)
self.SetSize((700, 700))
def OnWebViewLoaded(self, evt):
# The full document has loaded
self.browser.RunScript('alert("hello");')
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.browser.LoadURL("http://www.google.com")
dialog.Show()
app.MainLoop()