Maths is pretty!

The below image is a collage of 48 individual images of the same Mandelbrot set drawn six different ways with eight different colour palettes.

Mandelbrot Collage

A collage of Mandelbrot set images using different colour palettes and drawing techniques.

I hope you’ll agree that some of them are truly beautiful. In fact I’m gonna create some much larger versions of a few of them because the detail and patterns are gorgeous. Just need to find a wall to hang them on…

Anywho, they were generated by me using a custom Python algorithm. I may well package this up with a GUI at some point so other people can play with the parameters and create there own pretty and unique images, but until then you’ll have to enjoy these.

Like and share 🙂

QtWebKit and Favicons

I’m currently working on developing a stripped down tabbed browser for a project and therefore wanted to get the favicon for the page that is being displayed in each tab. However, there seems to be a bug with Qt4/WebKit when it comes to using the QWebSettings.iconForUrl() method in that it doesn’t seem to (consistently at least) return anything… so I wrote my own solution as follows:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebKit import *
from PyQt5.QtNetwork import *
 
from html.parser import HTMLParser
 
class QtFavicon(QObject):
    NAIVE = 0
    PAGE  = 1
    ICON  = 2
 
    class _Threaded(QObject):
        finished=pyqtSignal()
 
        def __init__(self, url, parent=None, **kwargs):
            QObject.__init__(self, parent, **kwargs)
 
            self._nam=None
            self._url=QUrl(url)
            self.data=QByteArray()
 
        def request(self, url, reason=0):
            self._reason=reason
            request=QNetworkRequest(url)
            request.setRawHeader("User-Agent", "PyQt4.QtNetwork.QNetworkAccessManager")
            request.setRawHeader("Connection", "close")
 
            if not self._nam: self._nam=QNetworkAccessManager()
            self._reply=self._nam.get(request)
            self._reply.finished.connect(self._finished)
 
        @pyqtSlot()
        def start(self): self.request(self._url.resolved(QUrl("favicon.ico")))
 
        @pyqtSlot()
        def _finished(self):
            try:
                if self._reply.error()==QNetworkReply.NoError:
                    if self._reason in (QtFavicon.NAIVE, QtFavicon.ICON) and \
                            self._reply.bytesAvailable()>0:
                        self.data=self._reply.readAll()
 
                    elif self._reason in (QtFavicon.PAGE,) and self._reply.bytesAvailable()>0:
                        page=self._reply.readAll()
                        p=QtFavicon._Parser()
                        p.feed(page.data())
                        self.request(QUrl(p.faviconHref), QtFavicon.ICON)
                        return
 
                elif self._reply.error()==QNetworkReply.ContentNotFoundError:
                    if self._reason in (QtFavicon.NAIVE,):
                        return self.request(self._url, QtFavicon.PAGE)
            except: pass
            self.finished.emit()
 
    class _Parser(HTMLParser):
        def __init__(self, *args, **kwargs):
            HTMLParser.__init__(self, *args, **kwargs)
 
            self.faviconHref=None
 
        def handle_starttag(self, tag, attrs):
            attrs=dict(attrs)
            if tag.lower()!="link" or \
                    'rel' not in attrs or \
                    attrs['rel'] not in ("icon", "shortcut icon"): return
            self.faviconHref=attrs['href']
 
    @staticmethod
    def iconForUrl(url, timeout=10000):
        thread=QThread()
        threaded=QtFavicon._Threaded(url, finished=thread.quit)
        thread.started.connect(threaded.start)
        threaded.moveToThread(thread)
 
        _timeout=QTime.currentTime().addMSecs(timeout)
        thread.start()
        while not thread.isFinished():
            qApp.processEvents()
            if QTime.currentTime()<_timeout: continue
            thread.terminate()
            thread.wait(timeout)
            break
             
        p=QPixmap()
        data=threaded.data
        if data.length()>0: p.loadFromData(threaded.data)
        return QIcon(p)
 
if __name__=="__main__":
    from sys import argv, exit
 
    class Widget(QWidget):
        def __init__(self, parent=None, **kwargs):
            QWidget.__init__(self, parent, **kwargs)
 
            l=QVBoxLayout(self)
            self._href=QLineEdit(self)
            l.addWidget(self._href)
            l.addWidget(QPushButton("Get Favicon", self, clicked=self.iconForUrl))
 
        @pyqtSlot()
        def iconForUrl(self):
            href=self._href.text()
            self.setWindowTitle(href)
            self.setWindowIcon(QtFavicon.iconForUrl(href))
 
    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())

I hope somebody else finds this useful.