I keep on struggling with something as simple as showing a favicon.ico
with PyQt5's QWebEngineView
.
Both tracing and the testing server tell me that pixmap
gets downloaded, but it simply does not show. Conversely, if I replace pixmap
with a local filename, it shows.
I checked similar questions here, but none of the answers seem to work. So, please, post only tested answers. Thanks!
from PyQt5.Qt import *
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
url_web = 'https://hamwaves.com/swx/index.html'
url_ico = 'https://hamwaves.com/swx/favicon.ico'
class Browser(QWebEngineView):
def __init__(self):
QWebEngineView.__init__(self)
self.nam = QNetworkAccessManager()
self.nam.finished.connect(self.set_icon)
self.nam.get(QNetworkRequest(QUrl(url_ico)))
def set_icon(self, response):
pixmap = QPixmap()
pixmap.loadFromData(response.readAll(), format='ico')
self.setWindowIcon(QIcon(pixmap))
app = QApplication(sys.argv)
web = Browser()
web.load(QUrl(url_web))
web.show()
sys.exit(app.exec_())
Always check the contents of what you receive.
If you just do a print(response.readAll()
), you'll see this:
<head><title>Not Acceptable!</title></head><body>
<h1>Not Acceptable!</h1><p>
An appropriate representation of the requested resource could not be
found on this server. This error was generated by Mod_Security.
</p></body></html>
Reformatted for readability
This is quite common for generic "anonymous" network requests, the reason is that QNetworkAccessManager doesn't set any user agent string on its own, and many web servers ignore such requests as basic security measure and partial traffic limitation: only browsers can make requests, and they generally use proper user agents.
Simply use a common user agent string and call setHeader()
on the request before sending it. You can get some from here.
request = QNetworkRequest(QUrl(url_ico))
request.setHeader(request.UserAgentHeader,
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
)
self.nam.get(request)
In reality, all this shouldn't be necessary, since QWebEngineView already supports the feature, so you should just connect the iconChanged
signal to the related function:
class Browser(QWebEngineView):
def __init__(self):
super().__init__()
self.iconChanged.connect(self.setWindowIcon)
When testing with your url above, it properly sets the icon as soon as the page is loaded, so there's no need to use QNetworkAccessManager at all.