QWebView Auto Tabs - qt

I open a web page with QWebView.load(QUrl(myurl)) , the webpage gets some input and returns a new php generated page.
If executed in Firefox the browser automatically opens a new tab/window to show the returned page.
How to tell QWebView to open a new instance of QWebview with the returned data loaded?
I was looking at at the QwebView documentation at
www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qwebview.html ... but no joy.
Example of such a page :
http://www.iqfront.com/index.php?option=com_content&view=article&id=5&Itemid=4
Thanks for any ideas.

from my understanding this is developer's job to create and open new tabs for urls clicked.You would need to define a custom slot for QWebView::linkClicked signal. This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy property is set to delegate the link handling for the specified url. There you can create a new instance of QWebView add it a tab and open new url there. Below is an example:
import sys
from PyQt4 import QtGui, QtCore, QtWebKit
class MainForm(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
self.tabWidget = QtGui.QTabWidget(self)
self.setCentralWidget(self.tabWidget)
self.loadUrl(QtCore.QUrl('http://qt.nokia.com/'))
def loadUrl(self, url):
view = QtWebKit.QWebView()
view.connect(view, QtCore.SIGNAL('loadFinished(bool)'), self.loadFinished)
view.connect(view, QtCore.SIGNAL('linkClicked(const QUrl&)'), self.linkClicked)
view.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
self.tabWidget.setCurrentIndex(self.tabWidget.addTab(view, 'loading...'))
view.load(url)
def loadFinished(self, ok):
index = self.tabWidget.indexOf(self.sender())
self.tabWidget.setTabText(index, self.sender().url().host())
def linkClicked(self, url):
self.loadUrl(url)
def main():
app = QtGui.QApplication(sys.argv)
form = MainForm()
form.show()
app.exec_()
if __name__ == '__main__':
main()
hope this helps, regards

Related

QT creator python stream video using opencv

I've been at it from quite some days, searched the docs online but have not been able to find any example :/.
I want to stream video on a page using opencv.Im using QtCreator and on a QtQuick application, that is with qml files.
MediaPlayer {
id: mediaplayer
source: "videoplayback.mp4"
}
VideoOutput {
anchors.fill: parent
source: mediaplayer
}
MouseArea {
id: playArea
anchors.fill: parent
onPressed: mediaplayer.play();
}
Which shows this:
Now i can play the video.
But i rather want the source to be coming from my backend main.py file so i can work upon it.
The main.py file as of now is:
'''
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
#QTimer
self.timer = QTimer()
self.timer.timeout.connect(lambda: self.setTime())
self.timer.start(1000)
def setTime(self):
now = datetime.datetime.now()
formatDate = now.strftime("Time: %H:%M:%S %p of %Y/%m/%d")
#print(formatDate)
self.printTime.emit(formatDate)
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
#Get Context
main = MainWindow()
engine.rootContext().setContextProperty("backend", main)
engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
In the above code, basically this line:
engine.rootContext().setContextProperty("backend", main)
Is the one for connection with the qml files using
Connections{
target: backend
function onPrintTime(time){
labelDate.text = time
}
}
So in context i want to ouput video on my page using source as being from opencv. Basically it's a surviellance system app, so i want to show multiple feeds, but if someone could help me with just one from webcam, as in how to stream it to the mediaplayer i'll be really really grateful.
Note: Im working with qml files inside the QT Creator application. There are a number of ways to do this with UI files but that doens't help me :/

Scrapy does not extract data

I am trying to get some technical informations about automobiles from this page
Here is my current code:
import scrapy
import re
from arabamcom.items import ArabamcomItem
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class BasicSpider(CrawlSpider):
name="arabamcom"
allowed_domains=["arabam.com"]
start_urls=['https://www.arabam.com/ikinci-el/otomobil']
rules=(Rule(LinkExtractor(allow=(r'/ilan')),callback="parse_item",follow=True),)
def parse_item(self,response):
item=ArabamcomItem()
item['fiyat']=response.css('span.color-red.font-huge.bold::text').extract()
item['marka']=response.css('p.color-black.bold.word-break.mb4::text').extract()
item['yil']=response.xpath('//*[#id="js-hook-appendable-technicalPropertiesWrapper"]/div[2]/dl[1]/dd/span/text()').extract()
And this is my items.py file
import scrapy
class ArabamcomItem(scrapy.Item):
fiyat=scrapy.Field()
marka=scrapy.Field()
yil=scrapy.Field()
When i run the code i can get data from 'marka' and 'fiyat' item but spider does not get anything for 'yil' attribute. Also other parts like 'Yakit Tipi','Vites Tipi' etc. How can i solve this problem ?
What's wrong:
//*[#id="js-hook-appendable-technicalPropertiesWrapper"]/......
This id start with js and may be dynamic element appeded by javascript
Scrapy do not have the ability to render javascript by default.
There are 2 solutions you can try
Scrapy-Splash
This is a javascript rendering engine for scrapy
Install Splash as a Docker container
Modify your settings.py file to integrate splash (append following middlewares to your project)
SPLASH_URL = 'http://127.0.0.1:8050'
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware':100,
}
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware':723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
Replace your Request Function with SplashRequest
from scrapy_splash import SplashRequest as SP
SP(url=url, callback=parse, endpoint='render.html', args={'wait': 5})
Selenium WebDriver
This is a browser automation-testing framework
Install Selenium from PyPi and install there corresponding driver(e.g. Firefox -> Geckodriver) to PATH folder
Append following middleware class to your project's middleware.py file:
class SeleniumMiddleware(object):
#classmethod
def from_crawler(cls, crawler):
middleware = cls()
crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
return middleware
def process_request(self, request, spider):
request.meta['driver'] = self.driver
self.driver.get(request.url)
self.driver.implicitly_wait(2)
body = to_bytes(self.driver.page_source)
return HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)
def spider_opened(self, spider):
"""Change your browser mode here"""
self.driver = webdriver.Firefox()
def spider_closed(self, spider):
self.driver.close()
Modify your settings.py file to integrate the Selenium middleware (append following middleware to your project and replace yourproject with your project name)
DOWNLOADER_MIDDLEWARES = {
'yourproject.middlewares.SeleniumMiddleware': 200
}
Comparison
Scrapy-Splash
An official module by Scrapy Company
You can deploy splash instance to cloud, so that you will be able to browse the url in cloud then transfer the render.html back to your spider
It's slow
Splash container will stop if there is a memory leak. (Be sure to deploy splash instance on a high memory cloud instance)
Selenium web driver
You have to have Firefox or Chrome with their corresponding automated-test-driver on your machine, unless you use PhantomJS.
You can't modify request headers directly with Selenium web driver
You could render the webpage using a headless browser but this data can be easily extracted without it, try this:
import re
import ast
...
def parse_item(self,response):
regex = re.compile('dataLayer.push\((\{.*\})\);', re.DOTALL)
html_info = response.xpath('//script[contains(., "dataLayer.push")]').re_first(regex)
data = ast.literal_eval(html_info)
yield {'fiyat': data['CD_Fiyat'],
'marka': data['CD_marka'],
'yil': data['CD_yil']}
# output an item with {'fiyat': '103500', 'marka': 'Renault', 'yil': '2017'}

Programmatically created user is active?

Django 1.9.6
I just want to test if anonymous user is redirected to login page.
I've created some user. It is definitely not registered.
Could you help me understand, why its property is_active is set to True.
Well, I stopped at pdb breakpoint and:
-> pdb.set_trace()
(Pdb) request.user.is_active
True
I have to explicitly set user.is_active = False. But why is the user active by default is a mystery to me. Nobody has activated it, I would say.
The code is below.
from django.test import TestCase
from .views import HomePageView
from django.http.request import HttpRequest
from django.contrib.auth.models import User
class GeneralTest(TestCase):
def test_anonymous_user_redirected_to_login_page(self):
user = User(username='anonymous', email='vvv#mail.ru', password='ttrrttrr')
request = HttpRequest()
request.user = user
hpv = HomePageView()
response = hpv.get(request)
pdb.set_trace()

Create new dialog in PyQT + Webview

I`m trying to develop nice-looking app in pyqt using WebView and have a little problem.
I want to create new Window by pressing button in WebView.
I have main window(short view):
class LoginWindow(QWidget):
def __init__(self):
# creating window and different properties...
# Its not important,i think.
self.foo = LoginConnector(self)
view.page().mainFrame().addToJavaScriptWindowObject("foo", self.foo)
... connector to JS
class LoginConnector(QObject):
#pyqtSlot(result=str)
def get_user_list(self):
return ','.join(core.available_users())
#pyqtSlot()
def new_window(self):
print 'Hello!'
#What can i do here?
#pyqtSlot()
def quit(self):
QApplication.quit()
When i`m pressing button in window,its call new_window() from LoginConnector,but how create Dialog inside LoginConnector?
Full code
SOLVED! I`m idiot,listen that clever guy below
Just look at the api docs. http://pyqt.sourceforge.net/Docs/PyQt4/classes.html
If you don't like this PySide is basically the same thing with a few differences in syntax. http://pyside.github.io/docs/pyside/
class LoginWindow(QWebView):
def __init__(self, *args, **kwargs):
super(QWebView, self).__init__(*args, **kwargs):
...
self.foo = LoginConnector(self)
self.loadPage("httpdocs/login.hmtl")
# end Constructor
def loadPage(self, web_page):
"""Loads a web page in the browser.
Args:
webPage (str): The URL of the desired web page with JavaScript Python Communication.
"""
# Inspector - right click inspect to debug javascript and have access to the console.
inspector = QtWebKit.QWebInspector()
inspector.setPage(self.page())
# Force relative path otherwise you get a does not except file:// error
if os.path.isabs(web_page):
web_page = os.path.relpath(web_page)
url = QtCore.QUrl(web_page)
self.load(url)
self.frame = self.page().mainFrame()
self.frame.addToJavaScriptWindowObject("foo", self.foo)
# end loadPage
# end class LoginWindow
class LoginConnector(QObject):
#pyqtSlot()
def new_window(self):
self.dialog = QDialog()
self.dialog.show() # or exec
# end new_window
# end class LoginConnector
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = LoginWindow()
window.show()
sys.exit(app.exec_())
This is the main application structure for PySide. PyQt should be similar.

How to restrict image file extension on Plone?

I have a Plone application in which I can upload images, which are ATImages. I want to validate the extension file (mainly to forbid pdf files). There are created with a url call like http://blablba.com/createObject?type_name=Image
I have tried setting the /content_type_registry with file extensions associated with images, with no success (pdf upload still work)
I guess I could write a new class extending ATImages, create a form with a validator, but it looks a little bit complicated and it seemed that some settings on content_type registry would be enough (or elsewhere).
How would you do that ? (forbid pdf ?)
thx
We had a similar problem.
Archetypes fires several events during its magic, amongst others a "post validation event" (IObjectPostValidation). This way we added a check for the content-type.
subscriber (zcml):
<subscriber provides="Products.Archetypes.interfaces.IObjectPostValidation"
factory=".subscribers.ImageFieldContentValidator" />
quick and dirty implementation:
from Products.Archetypes.interfaces.field import IImageField
from plone.app.blob.interfaces import IBlobImageField
from Products.Archetypes.interfaces import IObjectPostValidation
from zope.interface import implements
from zope.component import adapts
# import your message factory as _
ALLOWED_IMAGETYPES = ['image/png',
'image/jpeg',
'image/gif',
'image/pjpeg',
'image/x-png']
class ImageFieldContentValidator(object):
"""Validate that the ImageField really contains a Imagefile.
Show a Errormessage if it doesn't.
"""
implements(IObjectPostValidation)
adapts(IBaseObject)
img_interfaces = [IBlobImageField, IImageField]
msg = _(u"error_not_image",
default="The File you wanted to upload is no image")
def __init__(self, context):
self.context = context
def __call__(self, request):
for fieldname in self.context.Schema().keys():
field = self.context.getField(fieldname)
if True in [img_interface.providedBy(field) \
for img_interface in self.img_interfaces]:
item = request.get(fieldname + '_file', None)
if item:
header = item.headers
ct = header.get('content-type')
if ct in ALLOWED_IMAGETYPES:
return
else:
return {fieldname: self.msg}

Resources