PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : QMimeSourceFactory



cagara
16-06-2005, 14:06
Hallo,

Ich möchte meinem QTextBrowser beibringen bilder aus dem Netz anzuzeigen.

Hierzu habe ich eine Klasse von QMimeSource abgeleitet und wollte jetzt eigentlich eine Funktion ünberschreiben!

Nur wie gehe ich jetzt vor,was muss ich tun

anda_skoa
16-06-2005, 14:20
Ich denke du brauchst erstmal eine QMimeSourceFactory
Jedes davon erzeugte QMimeSource Objekt repräsentiert dann ein Datenobjekt.

Ciao,
_

cagara
16-06-2005, 14:42
Hey

Danke für die antwort, ich habe mich vertippt.

Natürlich habe ich eine classe von QMimeSourceFactory abgeleitet, nun denke ich mal dass ich setImage umschreiben muss,
aber wie mache ich das am besten, bzw wie verknüpfe ich das ganze mit dem QTextBrowser dass der die Bilder aus dem Netz lädt.

Irgendwas mit qhttp wirds sein denke ich mal,
weil momentan bekomme ich
QTextImage no mimesource found for http://localhost/lol.jpg

anda_skoa
16-06-2005, 20:53
setImage dürfte dann benutzbar sein, wenn man das Image schon hat.
zB wenn man ein eigenes Icon oder Logo hat.

Ich denke du wirst data() überschreiben müssen und für jeden Request ein QMimeSource Objekt liefern, dessen Inhalt du dann holst.
Allerdings wirst du da vermutlich nicht um processEvent() Hacks herum kommen, weil das MimeSource Objekt ja alle Daten auf einmal liefern muss

Ciao,
_

cagara
18-06-2005, 22:25
hmm
wie fängt man da am besten an???

das ist ja die aktuelle.


const QMimeSource* QMimeSourceFactory::data(const QString& abs_name) const
{
if ( d->stored.contains(abs_name) )
return d->stored[abs_name];

QMimeSource* r = 0;
QStringList::Iterator it;
if ( abs_name[0] == '/'
#ifdef Q_WS_WIN
|| ( abs_name[0] && abs_name[1] == ':' ) || abs_name.startsWith("\\\\")
#endif
)
{
// handle absolute file names directly
r = dataInternal( abs_name, d->extensions);
}
else { // check list of paths
for ( it = d->path.begin(); !r && it != d->path.end(); ++it ) {
QString filename = *it;
if ( filename[(int)filename.length()-1] != '/' )
filename += '/';
filename += abs_name;
r = dataInternal( filename, d->extensions );
}
}

static bool looping = FALSE;
if ( !r && this == defaultFactory() ) {
// we found no mime-source and we are the default factory, so
// we know all the other installed mime-source factories, so
// ask them
if ( !looping ) {
// to avoid endless recustions, don't enter the loop below
// if data() got called from within the loop below
looping = TRUE;
QPtrListIterator<QMimeSourceFactory> it( d->factories );
QMimeSourceFactory *f;
while ( ( f = it.current() ) ) {
++it;
if ( f == this )
continue;
r = (QMimeSource*)f->data( abs_name );
if ( r ) {
looping = FALSE;
return r;
}
}
looping = FALSE;
}
} else if ( !r ) {
// we are not the default mime-source factory, so ask the
// default one for the mime-source, as this one will loop over
// all installed mime-source factories and ask these
r = (QMimeSource*)defaultFactory()->data( abs_name );
}

return r;
}

hmm reicht es nicht DataInternal neuzuschreiben?

anda_skoa
19-06-2005, 21:40
hmm reicht es nicht DataInternal neuzuschreiben?

Dann hast du eine andere Qt als ich. Bei meiner ist dataInteral private

Ciao,
_

cagara
19-06-2005, 23:07
hey, sorry ich habe dataInternal im Code auf ppublic gesetzt, aber das ist auch net so das gelbe vom ei!

Habe hier ein Python beispiel, aber ich habe wahrlich keinen blassen schimmer wie ich das nun im guten alten c++ umsetzen soll, vorallem weil es keine 3-Argumentige Überladung von data() gibt :(


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.c olorGroup())
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()


Wie gesagt interessant ist nur die eigentliche data funktion. Das runterladen habe ich bereits fertig!


Weiss jemand weiter, ist echt wichtig, in einer woche ist schon abgabe,und ich sitze schon seit 1 woche an diesem problem!!

anda_skoa
20-06-2005, 09:06
Habe hier ein Python beispiel, aber ich habe wahrlich keinen blassen schimmer wie ich das nun im guten alten c++ umsetzen soll, vorallem weil es keine 3-Argumentige Überladung von data() gibt :(

Hat eh nur zwei.
self ist das Äquivalent zu this, da hast du im C++ Objekt ohnehin.



Wie gesagt interessant ist nur die eigentliche data funktion. Das runterladen habe ich bereits fertig!


Wenn du vom gegebenen Pfad schon die Daten erhälts, brauchst du sie doch nur mehr als MimeSource zurückgeben.
Zum Beispiel im Falle eine Image als QImageDrag.

Wahrscheinlich kann man mit setData das entsprechende MimeSource Objekt in den internen Strukturen abspeichern und so das erneute Downloaden verhindern.

Ciao,
_