PyBrowser: a nicer QTextBrowser
Working on some of my personal projects (specifically KRsN and Notty), I have needed to make QTextBrowser act a little more like a mensch in a few ways:
- Since it understands a lot of HTML, why not make it open images referenced in the text, and follow links?
- Since it can show what is pretty much a web page, why not make it use HTTP and whatever as needed?
- Make it print. The helpviewer example has all the needed code. So, I stole it.
To achieve these goals, I had to dig into QMimeSourceFactory and QDragObject, and it ain't all that pretty :-)
Click here for the python file (it's in the public domain, do as you wish with it).
Current problems:
- Slow
- Very slow
- Doesn't give close to enough feedback
- Should have a cache (it's trivial)
If anyone who has better python kungfu can help me, I'm a happy guy.
The result, in 143 lines of python, counting blanks and little demo proggie is this:
Source code for pybrowser.py
from qt import * import urlparse import traceback from urllib import urlopen import time class MimeFactory(QMimeSourceFactory): current=None def __init__(self,browser): QMimeSourceFactory.__init__(self) self.browser=browser def data(self,name,context=None): if context: return self.data(self.makeAbsolute(name,context)) res=None (local,type,subtype)=self.fetchURL(str(name)) if type=="image": i=QImage() #If image loading fails, return empty image if not i.loadFromData(local,None): i.create(10,10,8) res=QImageDrag(i) else: #Assume it's text res=QTextDrag(local) if subtype=="html": res.setSubtype("html") else: res.setSubtype("plain") self.current=res return self.current def makeAbsolute(self,name,context): return urlparse.urljoin(str(context),str(name)) def fetchURL(self,url): local="" type="text" subtype="plain" try: remote=urlopen(url) info=remote.info() (type,subtype)=info.gettype().split("/") local=remote.read() l=info.getheader('content-length') if not l: l=0 else: l=int(l) print 'size',l p=0 c=0 bsize=1024 while True: self.browser.emit(PYSIGNAL('status'),("Downloading: "\
+url+"(%sKB)"%str(p/1024),)) self.browser.emit(PYSIGNAL('size'),(p,)) if l: self.browser.emit(PYSIGNAL('percent'),((p*100)/l,)) qApp.processEvents() #Lame attempt at making this report about once a second stamp=time.time() c=c+1 buf=remote.read(int(bsize)) delta=time.time()-stamp if delta <.5: #Data coming quickly, get more on each loop bsize=min(bsize*1.25,10000) elif delta >.75: #Data coming slowly, get less on each loop bsize=max(bsize*.75,100) #End of file if buf=='': self.browser.emit(PYSIGNAL('percent'),(100,)) break p=p+len(buf) local=local+buf except: traceback.print_exc() return (local,type,subtype) def printPage(self): printer=QPrinter(QPrinter.HighResolution) printer.setFullPage(True) if printer.setup(self): p=QPainter(printer) if not p.isActive(): # starting printing failed return; metrics=QPaintDeviceMetrics(p.device()) dpiy = metrics.logicalDpiY() margin = int(((2/2.54)*dpiy)) # 2 cm margins body=QRect(margin, margin, metrics.width() - 2*margin, metrics.height()-2*margin) richText=QSimpleRichText( self.viewer.text(), QFont(), self.viewer.context(), self.viewer.styleSheet(), self.viewer.mimeSourceFactory(), body.height() ) richText.setWidth( p, body.width() ) view=QRect(body) page = 1 while True: richText.draw(p,body.left(),body.top(),view,self.colorGroup()) view.moveBy(0,body.height()) p.translate(0,-body.height()) p.drawText(view.right()-p.fontMetrics().width(str(page)), view.bottom()+p.fontMetrics().ascent()+5, str(page)); if view.top() >= richText.height(): break printer.newPage() page+=1 p.end() class QBrowser(QTextBrowser): def __init__(self,parent=None): QTextBrowser.__init__(self,parent) self.mf=MimeFactory(self) self.setMimeSourceFactory(self.mf) def printit(arg): print str(arg) if __name__=="__main__": from sys import argv app=QApplication(argv) w=QBrowser() w.connect(w,PYSIGNAL('percent'),printit) w.connect(w,PYSIGNAL('size'),printit) w.connect(w,PYSIGNAL('status'),printit) w.show() w.setSource(argv[1]) app.connect(app, SIGNAL("lastWindowClosed()") , app, SLOT("quit()")) app.exec_loop()
the
def printPage(self):
does nothing just delete it.
What do you mean it does nothing? I haven't looked at this code in three years or so, but I'm pretty sure it did something back then :-)
Reasonably exciting post condition I'm not positive we agree also a talented deal in relation to largely of it. If you complete own selected groovy points I strength add up. Concerning several focus reverse phone lookup resembling so as to talk a propos a change cellular phone lookup lookup I heard in relation to. Stipulation I'm not positive stipulation you require with the intention of checked it not by home so with the purpose of you be capable of carry out a reverse telephone lookup today with the aim of unearth not on home every kinds of bits and pieces a propos one plus anything.
Entirely interesting post but I'm not persuaded we agree also to a great extent as regards generally of it. Stipulation you carry out own some great points I force add together. On uncommon issue reverse phone lookup resembling to talk a propos a repeal telephone lookup search I heard on the topic of. If I'm not definite condition you want to checkered it not in so to facilitate you be capable of carry out a reverse mobile phone lookup at the moment with the purpose of come across elsewhere both kinds of material on the matter of part in addition to anything.
Hi very nice article