00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #undef CACHE_DEBUG
00028
00029 #include <assert.h>
00030
00031 #include "loader.h"
00032
00033
00034 #define MAXCACHEABLE 40*1024
00035
00036 #define DEFCACHESIZE 512*1024
00037
00038 #include <qasyncio.h>
00039 #include <qasyncimageio.h>
00040 #include <qpainter.h>
00041 #include <qbitmap.h>
00042 #include <qmovie.h>
00043 #include <qwidget.h>
00044
00045 #include <kapplication.h>
00046 #include <kio/job.h>
00047 #include <kio/jobclasses.h>
00048 #include <kglobal.h>
00049 #include <kimageio.h>
00050 #include <kcharsets.h>
00051 #include <kiconloader.h>
00052 #include <scheduler.h>
00053 #include <kdebug.h>
00054 #include "khtml_factory.h"
00055 #include "khtml_part.h"
00056
00057 #include "html/html_documentimpl.h"
00058 #include "css/css_stylesheetimpl.h"
00059 #include "xml/dom_docimpl.h"
00060
00061 using namespace khtml;
00062 using namespace DOM;
00063
00064 void CachedObject::finish()
00065 {
00066 if( m_size > MAXCACHEABLE )
00067 m_status = Uncacheable;
00068 else
00069 m_status = Cached;
00070 KURL url(m_url.string());
00071 if (m_expireDateChanged && url.protocol().startsWith("http"))
00072 {
00073 m_expireDateChanged = false;
00074 KIO::http_update_cache(url, false, m_expireDate);
00075 #ifdef CACHE_DEBUG
00076 kdDebug(6060) << " Setting expire date for image "<<m_url.string()<<" to " << m_expireDate << endl;
00077 #endif
00078 }
00079 #ifdef CACHE_DEBUG
00080 else kdDebug(6060) << " No expire date for image "<<m_url.string()<<endl;
00081 #endif
00082 }
00083
00084 void CachedObject::setExpireDate(time_t _expireDate, bool changeHttpCache)
00085 {
00086 if ( _expireDate == m_expireDate)
00087 return;
00088
00089 if (m_status == Uncacheable || m_status == Cached)
00090 {
00091 finish();
00092 }
00093 m_expireDate = _expireDate;
00094 if (changeHttpCache && m_expireDate)
00095 m_expireDateChanged = true;
00096 }
00097
00098 bool CachedObject::isExpired() const
00099 {
00100 if (!m_expireDate) return false;
00101 time_t now = time(0);
00102 return (difftime(now, m_expireDate) >= 0);
00103 }
00104
00105 void CachedObject::setRequest(Request *_request)
00106 {
00107 if ( _request && !m_request )
00108 m_status = Pending;
00109 m_request = _request;
00110 }
00111
00112
00113
00114 CachedCSSStyleSheet::CachedCSSStyleSheet(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy, time_t _expireDate, const QString& charset)
00115 : CachedObject(url, CSSStyleSheet, _cachePolicy, _expireDate)
00116 {
00117
00118 setAccept( QString::fromLatin1("text/css") );
00119
00120 Cache::loader()->load(dl, this, false);
00121 m_loading = true;
00122 bool b;
00123 if(!charset.isEmpty())
00124 {
00125 m_codec = KGlobal::charsets()->codecForName(charset, b);
00126 if(m_codec->mibEnum() == 11) {
00127
00128 m_codec = QTextCodec::codecForName("iso8859-8-i");
00129 }
00130 }
00131 else
00132 m_codec = QTextCodec::codecForMib(4);
00133 }
00134
00135 CachedCSSStyleSheet::CachedCSSStyleSheet(const DOMString &url, const QString &stylesheet_data)
00136 : CachedObject(url, CSSStyleSheet, KIO::CC_Verify, 0)
00137 {
00138 m_loading = false;
00139 m_status = Persistent;
00140 m_codec = 0;
00141 m_size = stylesheet_data.length();
00142 m_sheet = DOMString(stylesheet_data);
00143 }
00144
00145
00146 CachedCSSStyleSheet::~CachedCSSStyleSheet()
00147 {
00148 }
00149
00150 void CachedCSSStyleSheet::ref(CachedObjectClient *c)
00151 {
00152
00153 m_clients.remove(c);
00154 m_clients.append(c);
00155
00156 if(!m_loading) c->setStyleSheet( m_url, m_sheet );
00157 }
00158
00159 void CachedCSSStyleSheet::deref(CachedObjectClient *c)
00160 {
00161 Cache::flush();
00162 m_clients.remove(c);
00163 }
00164
00165 void CachedCSSStyleSheet::data( QBuffer &buffer, bool eof )
00166 {
00167 if(!eof) return;
00168 buffer.close();
00169 m_size = buffer.buffer().size();
00170 QString data = m_codec->toUnicode( buffer.buffer().data(), m_size );
00171 m_sheet = DOMString(data);
00172 m_loading = false;
00173
00174 checkNotify();
00175 }
00176
00177 void CachedCSSStyleSheet::checkNotify()
00178 {
00179 if(m_loading) return;
00180
00181 #ifdef CACHE_DEBUG
00182 kdDebug( 6060 ) << "CachedCSSStyleSheet:: finishedLoading " << m_url.string() << endl;
00183 #endif
00184
00185
00186
00187 for (QPtrListIterator<CachedObjectClient> it( m_clients ); it.current();)
00188 it()->setStyleSheet( m_url, m_sheet );
00189 }
00190
00191
00192 void CachedCSSStyleSheet::error( int , const char * )
00193 {
00194 m_loading = false;
00195 checkNotify();
00196 }
00197
00198
00199
00200 CachedScript::CachedScript(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy, time_t _expireDate, const QString& charset)
00201 : CachedObject(url, Script, _cachePolicy, _expireDate)
00202 {
00203
00204
00205
00206 setAccept( QString::fromLatin1("*/*") );
00207
00208 Cache::loader()->load(dl, this, false);
00209 m_loading = true;
00210 bool b;
00211 if(!charset.isEmpty()) {
00212 m_codec = KGlobal::charsets()->codecForName(charset, b);
00213 if(m_codec->mibEnum() == 11) {
00214
00215 m_codec = QTextCodec::codecForName("iso8859-8-i");
00216 }
00217 }
00218 else
00219 m_codec = QTextCodec::codecForMib(4);
00220 }
00221
00222 CachedScript::CachedScript(const DOMString &url, const QString &script_data)
00223 : CachedObject(url, Script, KIO::CC_Verify, 0)
00224 {
00225 m_loading = false;
00226 m_status = Persistent;
00227 m_codec = 0;
00228 m_size = script_data.length();
00229 m_script = DOMString(script_data);
00230 }
00231
00232 CachedScript::~CachedScript()
00233 {
00234 }
00235
00236 void CachedScript::ref(CachedObjectClient *c)
00237 {
00238
00239 m_clients.remove(c);
00240 m_clients.append(c);
00241
00242 if(!m_loading) c->notifyFinished(this);
00243 }
00244
00245 void CachedScript::deref(CachedObjectClient *c)
00246 {
00247 Cache::flush();
00248 m_clients.remove(c);
00249 }
00250
00251 void CachedScript::data( QBuffer &buffer, bool eof )
00252 {
00253 if(!eof) return;
00254 buffer.close();
00255 m_size = buffer.buffer().size();
00256 QString data = m_codec->toUnicode( buffer.buffer().data(), m_size );
00257 m_script = DOMString(data);
00258 m_loading = false;
00259 checkNotify();
00260 }
00261
00262 void CachedScript::checkNotify()
00263 {
00264 if(m_loading) return;
00265
00266 for (QPtrListIterator<CachedObjectClient> it( m_clients); it.current();)
00267 it()->notifyFinished(this);
00268 }
00269
00270
00271 void CachedScript::error( int , const char * )
00272 {
00273 m_loading = false;
00274 checkNotify();
00275 }
00276
00277
00278
00279 namespace khtml
00280 {
00281
00282 class ImageSource : public QDataSource
00283 {
00284 public:
00285 ImageSource(QByteArray buf);
00286
00291 int readyToSend();
00292
00296 void sendTo(QDataSink*, int count);
00297
00301 void setEOF( bool state );
00302
00306 bool rewindable() const;
00307
00311 void enableRewind(bool on);
00312
00313
00314
00315
00316 void rewind();
00317
00318
00319
00320
00321
00322 void cleanBuffer();
00323
00324 QByteArray buffer;
00325 unsigned int pos;
00326 private:
00327 bool eof : 1;
00328 bool rew : 1;
00329 bool rewable : 1;
00330 };
00331 }
00332
00333
00334 ImageSource::ImageSource(QByteArray buf)
00335 {
00336 buffer = buf;
00337 rew = false;
00338 pos = 0;
00339 eof = false;
00340 rewable = true;
00341 }
00342
00343 int ImageSource::readyToSend()
00344 {
00345 if(eof && pos == buffer.size())
00346 return -1;
00347
00348 return buffer.size() - pos;
00349 }
00350
00351 void ImageSource::sendTo(QDataSink* sink, int n)
00352 {
00353 sink->receive((const uchar*)&buffer.at(pos), n);
00354
00355 pos += n;
00356
00357
00358 if(eof && pos == buffer.size() && !rewable)
00359 {
00360 buffer.resize(0);
00361 pos = 0;
00362 }
00363 }
00364
00365 void ImageSource::setEOF( bool state )
00366 {
00367 eof = state;
00368 }
00369
00370
00371 bool ImageSource::rewindable() const
00372 {
00373 return rewable;
00374 }
00375
00376
00377 void ImageSource::enableRewind(bool on)
00378 {
00379 rew = on;
00380 }
00381
00382
00383 void ImageSource::rewind()
00384 {
00385 pos = 0;
00386 if (!rew) {
00387 QDataSource::rewind();
00388 } else
00389 ready();
00390 }
00391
00392 void ImageSource::cleanBuffer()
00393 {
00394
00395 if(rew)
00396 return;
00397
00398 rewable = false;
00399
00400
00401 if(eof && pos == buffer.size())
00402 {
00403 buffer.resize(0);
00404 pos = 0;
00405 }
00406 }
00407
00408 static QString buildAcceptHeader()
00409 {
00410 QString result = KImageIO::mimeTypes( KImageIO::Reading ).join(", ");
00411 if (result.right(2) == ", ")
00412 result = result.left(result.length()-2);
00413 return result;
00414 }
00415
00416 static bool crossDomain(const QString &a, const QString &b)
00417 {
00418 if (a == b) return false;
00419
00420 QStringList l1 = QStringList::split('.', a);
00421 QStringList l2 = QStringList::split('.', b);
00422
00423 while(l1.count() > l2.count())
00424 l1.pop_front();
00425
00426 while(l2.count() > l1.count())
00427 l2.pop_front();
00428
00429 while(l2.count() >= 2)
00430 {
00431 if (l1 == l2)
00432 return false;
00433
00434 l1.pop_front();
00435 l2.pop_front();
00436 }
00437 return true;
00438 }
00439
00440
00441
00442 CachedImage::CachedImage(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy, time_t _expireDate)
00443 : QObject(), CachedObject(url, Image, _cachePolicy, _expireDate)
00444 {
00445 static const QString &acceptHeader = KGlobal::staticQString( buildAcceptHeader() );
00446
00447 m = 0;
00448 p = 0;
00449 pixPart = 0;
00450 bg = 0;
00451 bgColor = qRgba( 0, 0, 0, 0xFF );
00452 typeChecked = false;
00453 isFullyTransparent = false;
00454 errorOccured = false;
00455 monochrome = false;
00456 formatType = 0;
00457 m_status = Unknown;
00458 m_size = 0;
00459 imgSource = 0;
00460 setAccept( acceptHeader );
00461 m_showAnimations = dl->showAnimations();
00462 }
00463
00464 CachedImage::~CachedImage()
00465 {
00466 clear();
00467 }
00468
00469 void CachedImage::ref( CachedObjectClient *c )
00470 {
00471 #ifdef CACHE_DEBUG
00472 kdDebug( 6060 ) << this << " CachedImage::ref(" << c << ") pixmap.isNull()=" << pixmap().isNull() << " valid_rect.isNull()=" << valid_rect().isNull()<< " status=" << m_status << endl;
00473 #endif
00474
00475
00476 m_clients.remove(c);
00477 m_clients.append(c);
00478
00479 if( m ) {
00480 m->unpause();
00481 if( m->finished() || m_clients.count() == 1 )
00482 m->restart();
00483 }
00484
00485
00486 if ( m_status >= Persistent && !valid_rect().isNull() )
00487 c->setPixmap( pixmap(), valid_rect(), this);
00488 }
00489
00490 void CachedImage::deref( CachedObjectClient *c )
00491 {
00492 #ifdef CACHE_DEBUG
00493 kdDebug( 6060 ) << this << " CachedImage::deref(" << c << ") " << endl;
00494 #endif
00495 Cache::flush();
00496 m_clients.remove( c );
00497 if(m && m_clients.isEmpty() && m->running())
00498 m->pause();
00499 }
00500
00501 #define BGMINWIDTH 32
00502 #define BGMINHEIGHT 32
00503
00504 class KHTMLPixmap : public QPixmap
00505 {
00506 public:
00507 #ifdef Q_WS_X11
00508 bool hasAlphaImage() const { return data->alphapm; }
00509 #else
00510 bool hasAlphaImage() const { return false; }
00511 #endif
00512 };
00513
00514 const QPixmap &CachedImage::tiled_pixmap(const QColor& newc)
00515 {
00516 static QRgb bgTransparant = qRgba( 0, 0, 0, 0xFF );
00517 if ( (bgColor != bgTransparant) && (bgColor != newc.rgb()) ) {
00518 delete bg; bg = 0;
00519 }
00520
00521 if (bg)
00522 return *bg;
00523
00524 const QPixmap &r = pixmap();
00525
00526 if (r.isNull()) return r;
00527
00528
00529 if(errorOccured) return *Cache::nullPixmap;
00530
00531 bool isvalid = newc.isValid();
00532 QSize s(pixmap_size());
00533 int w = r.width();
00534 int h = r.height();
00535 if ( w*h < 8192 )
00536 {
00537 if ( r.width() < BGMINWIDTH )
00538 w = ((BGMINWIDTH / s.width())+1) * s.width();
00539 if ( r.height() < BGMINHEIGHT )
00540 h = ((BGMINHEIGHT / s.height())+1) * s.height();
00541 }
00542 if ( !static_cast<const KHTMLPixmap*>( &r )->hasAlphaImage() &&
00543 ( (w != r.width()) || (h != r.height()) || (isvalid && r.mask())) )
00544 {
00545 QPixmap pix = r;
00546 if ( w != r.width() || (isvalid && pix.mask()))
00547 {
00548 bg = new QPixmap(w, r.height());
00549 QPainter p(bg);
00550 if(isvalid) p.fillRect(0, 0, w, r.height(), newc);
00551 p.drawTiledPixmap(0, 0, w, r.height(), pix);
00552 if(!isvalid && pix.mask())
00553 {
00554
00555
00556 QBitmap newmask(w, r.height());
00557 QPainter pm(&newmask);
00558 pm.drawTiledPixmap(0, 0, w, r.height(), *pix.mask());
00559 bg->setMask(newmask);
00560 bgColor = bgTransparant;
00561 }
00562 else
00563 bgColor= newc.rgb();
00564 pix = *bg;
00565 }
00566 if ( h != r.height() )
00567 {
00568 delete bg;
00569 bg = new QPixmap(w, h);
00570 QPainter p(bg);
00571 if(isvalid) p.fillRect(0, 0, w, h, newc);
00572 p.drawTiledPixmap(0, 0, w, h, pix);
00573 if(!isvalid && pix.mask())
00574 {
00575
00576
00577 QBitmap newmask(w, h);
00578 QPainter pm(&newmask);
00579 pm.drawTiledPixmap(0, 0, w, h, *pix.mask());
00580 bg->setMask(newmask);
00581 bgColor = bgTransparant;
00582 }
00583 else
00584 bgColor= newc.rgb();
00585 }
00586 return *bg;
00587 }
00588
00589 return r;
00590 }
00591
00592 const QPixmap &CachedImage::pixmap( ) const
00593 {
00594 if(errorOccured)
00595 return *Cache::brokenPixmap;
00596
00597 if(m)
00598 {
00599 if(m->framePixmap().size() != m->getValidRect().size() && m->getValidRect().size().isValid())
00600 {
00601
00602
00603
00604 if(!pixPart) pixPart = new QPixmap(m->getValidRect().size());
00605
00606 (*pixPart) = m->framePixmap();
00607 pixPart->resize(m->getValidRect().size());
00608 return *pixPart;
00609 }
00610 else
00611 return m->framePixmap();
00612 }
00613 else if(p)
00614 return *p;
00615
00616 return *Cache::nullPixmap;
00617 }
00618
00619
00620 QSize CachedImage::pixmap_size() const
00621 {
00622 return (m ? m->framePixmap().size() : ( p ? p->size() : QSize()));
00623 }
00624
00625
00626 QRect CachedImage::valid_rect() const
00627 {
00628 return m ? m->getValidRect() : ( p ? p->rect() : QRect());
00629 }
00630
00631
00632 void CachedImage::do_notify(const QPixmap& p, const QRect& r)
00633 {
00634 CachedObjectClient *c;
00635
00636 for ( c = m_clients.first(); c != 0; c = m_clients.next() )
00637 c->setPixmap( p, r, this);
00638 }
00639
00640
00641 void CachedImage::movieUpdated( const QRect& r )
00642 {
00643 #ifdef CACHE_DEBUG
00644 qDebug("movie updated %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
00645 m->framePixmap().size().width(), m->framePixmap().size().height());
00646 #endif
00647
00648 do_notify(m->framePixmap(), r);
00649 }
00650
00651 void CachedImage::movieStatus(int status)
00652 {
00653 #ifdef CACHE_DEBUG
00654 qDebug("movieStatus(%d)", status);
00655 #endif
00656
00657
00658
00659
00660
00661
00662
00663 if(status == QMovie::EndOfFrame)
00664 {
00665 const QImage& im = m->frameImage();
00666 monochrome = ( ( im.depth() <= 8 ) && ( im.numColors() - int( im.hasAlphaBuffer() ) <= 2 ) );
00667 for (int i = 0; monochrome && i < im.numColors(); ++i)
00668 if (im.colorTable()[i] != qRgb(0xff, 0xff, 0xff) &&
00669 im.colorTable()[i] != qRgb(0x00, 0x00, 0x00))
00670 monochrome = false;
00671 if( (im.width() < 5 || im.height() < 5) && im.hasAlphaBuffer())
00672 {
00673 QImage am = im.createAlphaMask();
00674 if(am.depth() == 1)
00675 {
00676 bool solid = false;
00677 for(int y = 0; y < am.height(); y++)
00678 for(int x = 0; x < am.width(); x++)
00679 if(am.pixelIndex(x, y)) {
00680 solid = true;
00681 break;
00682 }
00683 isFullyTransparent = (!solid);
00684 }
00685 }
00686
00687
00688
00689 delete bg;
00690 bg = 0;
00691 }
00692
00693 if((status == QMovie::EndOfMovie && (!m || m->frameNumber() <= 1)) ||
00694 ((status == QMovie::EndOfLoop) && (m_showAnimations == KHTMLSettings::KAnimationLoopOnce)) ||
00695 ((status == QMovie::EndOfFrame) && (m_showAnimations == KHTMLSettings::KAnimationDisabled))
00696 )
00697 {
00698 if(imgSource)
00699 {
00700 setShowAnimations( KHTMLSettings::KAnimationDisabled );
00701
00702
00703
00704 if (p && monochrome && p->depth() > 1 )
00705 {
00706 QPixmap* pix = new QPixmap;
00707 pix->convertFromImage( p->convertToImage().convertDepth( 1 ), MonoOnly|AvoidDither );
00708 if ( p->mask() )
00709 pix->setMask( *p->mask() );
00710 delete p;
00711 p = pix;
00712 monochrome = false;
00713 }
00714 }
00715 for (QPtrListIterator<CachedObjectClient> it( m_clients ); it.current();)
00716 it()->notifyFinished(this);
00717 }
00718
00719 #if 0
00720 if((status == QMovie::EndOfFrame) || (status == QMovie::EndOfMovie))
00721 {
00722 #ifdef CACHE_DEBUG
00723 QRect r(valid_rect());
00724 qDebug("movie Status frame update %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
00725 pixmap().size().width(), pixmap().size().height());
00726 #endif
00727 do_notify(pixmap(), valid_rect());
00728 }
00729 #endif
00730 }
00731
00732 void CachedImage::movieResize(const QSize& )
00733 {
00734
00735 }
00736
00737 void CachedImage::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations )
00738 {
00739 m_showAnimations = showAnimations;
00740 if ( (m_showAnimations == KHTMLSettings::KAnimationDisabled) && imgSource ) {
00741 imgSource->cleanBuffer();
00742 delete p;
00743 p = new QPixmap(m->framePixmap());
00744
00745 m->disconnectUpdate( this, SLOT( movieUpdated( const QRect &) ));
00746 m->disconnectStatus( this, SLOT( movieStatus( int ) ));
00747 m->disconnectResize( this, SLOT( movieResize( const QSize& ) ) );
00748 QTimer::singleShot(0, this, SLOT( deleteMovie()));
00749 imgSource = 0;
00750 }
00751 }
00752
00753 void CachedImage::deleteMovie()
00754 {
00755 delete m; m = 0;
00756 }
00757
00758 void CachedImage::clear()
00759 {
00760 delete m; m = 0;
00761 delete p; p = 0;
00762 delete bg; bg = 0;
00763 bgColor = qRgba( 0, 0, 0, 0xff );
00764 delete pixPart; pixPart = 0;
00765
00766 formatType = 0;
00767
00768 typeChecked = false;
00769 m_size = 0;
00770
00771
00772 imgSource = 0;
00773 }
00774
00775 void CachedImage::data ( QBuffer &_buffer, bool eof )
00776 {
00777 #ifdef CACHE_DEBUG
00778 kdDebug( 6060 ) << this << "in CachedImage::data(buffersize " << _buffer.buffer().size() <<", eof=" << eof << endl;
00779 #endif
00780 if ( !typeChecked )
00781 {
00782 formatType = QImageDecoder::formatName( (const uchar*)_buffer.buffer().data(), _buffer.size());
00783 typeChecked = true;
00784
00785 if ( formatType )
00786 {
00787 imgSource = new ImageSource( _buffer.buffer());
00788 m = new QMovie( imgSource, 8192 );
00789 m->connectUpdate( this, SLOT( movieUpdated( const QRect &) ));
00790 m->connectStatus( this, SLOT( movieStatus(int)));
00791 m->connectResize( this, SLOT( movieResize( const QSize& ) ) );
00792 }
00793 }
00794
00795 if ( imgSource )
00796 {
00797 imgSource->setEOF(eof);
00798 imgSource->maybeReady();
00799 }
00800
00801 if(eof)
00802 {
00803
00804
00805
00806 if(typeChecked && !formatType)
00807 {
00808 #ifdef CACHE_DEBUG
00809 kdDebug(6060) << "CachedImage::data(): reloading as pixmap:" << endl;
00810 #endif
00811 p = new QPixmap( _buffer.buffer() );
00812
00813 #ifdef CACHE_DEBUG
00814 kdDebug(6060) << "CachedImage::data(): image is null: " << p->isNull() << endl;
00815 #endif
00816 if(p->isNull())
00817 {
00818 errorOccured = true;
00819 do_notify(pixmap(), QRect(0, 0, 16, 16));
00820 }
00821 else
00822 do_notify(*p, p->rect());
00823 }
00824
00825 QSize s = pixmap_size();
00826 m_size = s.width() * s.height() * 2;
00827 }
00828 }
00829
00830 void CachedImage::finish()
00831 {
00832 Status oldStatus = m_status;
00833 CachedObject::finish();
00834 if ( oldStatus != m_status ) {
00835 const QPixmap &pm = pixmap();
00836 do_notify( pm, pm.rect() );
00837 }
00838 }
00839
00840
00841 void CachedImage::error( int , const char * )
00842 {
00843 #ifdef CACHE_DEBUG
00844 kdDebug(6060) << "CahcedImage::error" << endl;
00845 #endif
00846
00847 clear();
00848 typeChecked = true;
00849 errorOccured = true;
00850 do_notify(pixmap(), QRect(0, 0, 16, 16));
00851 }
00852
00853
00854
00855 Request::Request(DocLoader* dl, CachedObject *_object, bool _incremental)
00856 {
00857 object = _object;
00858 object->setRequest(this);
00859 incremental = _incremental;
00860 m_docLoader = dl;
00861 }
00862
00863 Request::~Request()
00864 {
00865 object->setRequest(0);
00866 }
00867
00868
00869
00870 DocLoader::DocLoader(KHTMLPart* part, DocumentImpl* doc)
00871 {
00872 m_cachePolicy = KIO::CC_Verify;
00873 m_expireDate = 0;
00874 m_creationDate = time(0);
00875 m_bautoloadImages = true;
00876 m_showAnimations = KHTMLSettings::KAnimationEnabled;
00877 m_part = part;
00878 m_doc = doc;
00879
00880 Cache::docloader->append( this );
00881 }
00882
00883 DocLoader::~DocLoader()
00884 {
00885 Cache::loader()->cancelRequests( this );
00886 Cache::docloader->remove( this );
00887 }
00888
00889 void DocLoader::setCacheCreationDate(time_t _creationDate)
00890 {
00891 if (_creationDate)
00892 m_creationDate = _creationDate;
00893 else
00894 m_creationDate = time(0);
00895 }
00896
00897 void DocLoader::setExpireDate(time_t _expireDate, bool relative)
00898 {
00899 if (relative)
00900 m_expireDate = _expireDate + m_creationDate;
00901 else
00902 m_expireDate = _expireDate;
00903 #ifdef CACHE_DEBUG
00904 kdDebug(6061) << "docLoader: " << m_expireDate - time(0) << " seconds left until reload required.\n";
00905 #endif
00906 }
00907
00908 bool DocLoader::needReload(const KURL &fullURL)
00909 {
00910 bool reload = false;
00911 if (m_cachePolicy == KIO::CC_Verify)
00912 {
00913 if (!m_reloadedURLs.contains(fullURL.url()))
00914 {
00915 CachedObject *existing = Cache::cache->find(fullURL.url());
00916 if (existing && existing->isExpired())
00917 {
00918 Cache::removeCacheEntry(existing);
00919 m_reloadedURLs.append(fullURL.url());
00920 reload = true;
00921 }
00922 }
00923 }
00924 else if ((m_cachePolicy == KIO::CC_Reload) || (m_cachePolicy == KIO::CC_Refresh))
00925 {
00926 if (!m_reloadedURLs.contains(fullURL.url()))
00927 {
00928 CachedObject *existing = Cache::cache->find(fullURL.url());
00929 if (existing)
00930 {
00931 Cache::removeCacheEntry(existing);
00932 }
00933 m_reloadedURLs.append(fullURL.url());
00934 reload = true;
00935 }
00936 }
00937 return reload;
00938 }
00939
00940 CachedImage *DocLoader::requestImage( const DOM::DOMString &url)
00941 {
00942 KURL fullURL = m_doc->completeURL( url.string() );
00943 if ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file") return 0;
00944 if ( kapp && m_doc && !kapp->authorizeURLAction("redirect", m_doc->URL(), fullURL.url())) return 0;
00945
00946 bool reload = needReload(fullURL);
00947
00948 return Cache::requestImage(this, url, reload, m_expireDate);
00949 }
00950
00951 CachedCSSStyleSheet *DocLoader::requestStyleSheet( const DOM::DOMString &url, const QString& charset)
00952 {
00953 KURL fullURL = m_doc->completeURL( url.string() );
00954 if ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file") return 0;
00955 if ( kapp && m_doc && !kapp->authorizeURLAction("redirect", m_doc->URL(), fullURL.url())) return 0;
00956
00957 bool reload = needReload(fullURL);
00958
00959 return Cache::requestStyleSheet(this, url, reload, m_expireDate, charset);
00960 }
00961
00962 CachedScript *DocLoader::requestScript( const DOM::DOMString &url, const QString& charset)
00963 {
00964 KURL fullURL = m_doc->completeURL( url.string() );
00965 if ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file") return 0;
00966 if ( kapp && m_doc && !kapp->authorizeURLAction("redirect", m_doc->URL(), fullURL.url())) return 0;
00967
00968 bool reload = needReload(fullURL);
00969
00970 return Cache::requestScript(this, url, reload, m_expireDate, charset);
00971 }
00972
00973 void DocLoader::setAutoloadImages( bool enable )
00974 {
00975 if ( enable == m_bautoloadImages )
00976 return;
00977
00978 m_bautoloadImages = enable;
00979
00980 if ( !m_bautoloadImages ) return;
00981
00982 for ( const CachedObject* co=m_docObjects.first(); co; co=m_docObjects.next() )
00983 if ( co->type() == CachedObject::Image )
00984 {
00985 CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( co ) );
00986
00987 CachedObject::Status status = img->status();
00988 if ( status != CachedObject::Unknown )
00989 continue;
00990
00991 Cache::loader()->load(this, img, true);
00992 }
00993 }
00994
00995 void DocLoader::setCachePolicy( KIO::CacheControl cachePolicy )
00996 {
00997 m_cachePolicy = cachePolicy;
00998 }
00999
01000 void DocLoader::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations )
01001 {
01002 if ( showAnimations == m_showAnimations ) return;
01003 m_showAnimations = showAnimations;
01004
01005 const CachedObject* co;
01006 for ( co=m_docObjects.first(); co; co=m_docObjects.next() )
01007 if ( co->type() == CachedObject::Image )
01008 {
01009 CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( co ) );
01010
01011 img->setShowAnimations( showAnimations );
01012 }
01013 }
01014
01015 void DocLoader::removeCachedObject( CachedObject* o ) const
01016 {
01017 m_docObjects.removeRef( o );
01018 }
01019
01020
01021
01022 Loader::Loader() : QObject()
01023 {
01024 m_requestsPending.setAutoDelete( true );
01025 m_requestsLoading.setAutoDelete( true );
01026 }
01027
01028 Loader::~Loader()
01029 {
01030 }
01031
01032 void Loader::load(DocLoader* dl, CachedObject *object, bool incremental)
01033 {
01034 Request *req = new Request(dl, object, incremental);
01035 m_requestsPending.append(req);
01036
01037 emit requestStarted( req->m_docLoader, req->object );
01038
01039 QTimer::singleShot( 0, this, SLOT( servePendingRequests() ) );
01040 }
01041
01042 void Loader::servePendingRequests()
01043 {
01044 if ( m_requestsPending.count() == 0 )
01045 return;
01046
01047
01048 Request *req = m_requestsPending.take(0);
01049
01050 #ifdef CACHE_DEBUG
01051 kdDebug( 6060 ) << "starting Loader url=" << req->object->url().string() << endl;
01052 #endif
01053
01054 KURL u(req->object->url().string());
01055 KIO::TransferJob* job = KIO::get( u, false, false );
01056
01057 job->addMetaData("cache", KIO::getCacheControlString(req->object->cachePolicy()));
01058 if (!req->object->accept().isEmpty())
01059 job->addMetaData("accept", req->object->accept());
01060 if ( req->m_docLoader ) {
01061 KURL r = req->m_docLoader->doc()->URL();
01062 r.setRef(QString::null);
01063 r.setUser(QString::null);
01064 r.setPass(QString::null);
01065 if ( r.protocol().startsWith( "http" ) && r.path().isEmpty() )
01066 r.setPath( "/" );
01067 job->addMetaData("referrer", r.url());
01068 QString domain = r.host();
01069 if (req->m_docLoader->doc()->isHTMLDocument())
01070 domain = static_cast<HTMLDocumentImpl*>(req->m_docLoader->doc())->domain().string();
01071 if (crossDomain(u.host(), domain))
01072 job->addMetaData("cross-domain", "true");
01073
01074 KHTMLPart *part = req->m_docLoader->part();
01075 if (part && part->widget() && part->widget()->topLevelWidget())
01076 job->setWindow (part->widget()->topLevelWidget());
01077 }
01078
01079 connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinished( KIO::Job * ) ) );
01080 connect( job, SIGNAL( data( KIO::Job*, const QByteArray &)),
01081 SLOT( slotData( KIO::Job*, const QByteArray &)));
01082
01083 if ( req->object->schedule() )
01084 KIO::Scheduler::scheduleJob( job );
01085
01086 m_requestsLoading.insert(job, req);
01087 }
01088
01089 void Loader::slotFinished( KIO::Job* job )
01090 {
01091 Request *r = m_requestsLoading.take( job );
01092 KIO::TransferJob* j = static_cast<KIO::TransferJob*>(job);
01093
01094 if ( !r )
01095 return;
01096
01097 if (j->error() || j->isErrorPage())
01098 {
01099 #ifdef CACHE_DEBUG
01100 kdDebug(6060) << "Loader::slotFinished, with error. job->error()= " << j->error() << " job->isErrorPage()=" << j->isErrorPage() << endl;
01101 #endif
01102 r->object->error( job->error(), job->errorText().ascii() );
01103 emit requestFailed( r->m_docLoader, r->object );
01104 }
01105 else
01106 {
01107 r->object->data(r->m_buffer, true);
01108 emit requestDone( r->m_docLoader, r->object );
01109 time_t expireDate = j->queryMetaData("expire-date").toLong();
01110 #ifdef CACHE_DEBUG
01111 kdDebug(6060) << "Loader::slotFinished, url = " << j->url().url() << " expires " << ctime(&expireDate) << endl;
01112 #endif
01113 r->object->setExpireDate(expireDate, false);
01114 }
01115
01116 r->object->finish();
01117
01118 #ifdef CACHE_DEBUG
01119 kdDebug( 6060 ) << "Loader:: JOB FINISHED " << r->object << ": " << r->object->url().string() << endl;
01120 #endif
01121
01122 delete r;
01123 QTimer::singleShot( 0, this, SLOT( servePendingRequests() ) );
01124 }
01125
01126 void Loader::slotData( KIO::Job*job, const QByteArray &data )
01127 {
01128 Request *r = m_requestsLoading[job];
01129 if(!r) {
01130 kdDebug( 6060 ) << "got data for unknown request!" << endl;
01131 return;
01132 }
01133
01134 if ( !r->m_buffer.isOpen() )
01135 r->m_buffer.open( IO_WriteOnly );
01136
01137 r->m_buffer.writeBlock( data.data(), data.size() );
01138
01139 if(r->incremental)
01140 r->object->data( r->m_buffer, false );
01141 }
01142
01143 int Loader::numRequests( DocLoader* dl ) const
01144 {
01145 int res = 0;
01146
01147 QPtrListIterator<Request> pIt( m_requestsPending );
01148 for (; pIt.current(); ++pIt )
01149 if ( pIt.current()->m_docLoader == dl )
01150 res++;
01151
01152 QPtrDictIterator<Request> lIt( m_requestsLoading );
01153 for (; lIt.current(); ++lIt )
01154 if ( lIt.current()->m_docLoader == dl )
01155 res++;
01156
01157 return res;
01158 }
01159
01160 void Loader::cancelRequests( DocLoader* dl )
01161 {
01162
01163
01164 QPtrListIterator<Request> pIt( m_requestsPending );
01165 while ( pIt.current() )
01166 {
01167 if ( pIt.current()->m_docLoader == dl )
01168 {
01169 #ifdef CACHE_DEBUG
01170 kdDebug( 6060 ) << "cancelling pending request for " << pIt.current()->object->url().string() << endl;
01171 #endif
01172
01173 Cache::removeCacheEntry( pIt.current()->object );
01174 m_requestsPending.remove( pIt );
01175 }
01176 else
01177 ++pIt;
01178 }
01179
01180
01181
01182 QPtrDictIterator<Request> lIt( m_requestsLoading );
01183 while ( lIt.current() )
01184 {
01185 if ( lIt.current()->m_docLoader == dl )
01186 {
01187
01188 KIO::Job *job = static_cast<KIO::Job *>( lIt.currentKey() );
01189 Cache::removeCacheEntry( lIt.current()->object );
01190 m_requestsLoading.remove( lIt.currentKey() );
01191 job->kill();
01192
01193 }
01194 else
01195 ++lIt;
01196 }
01197 }
01198
01199 KIO::Job *Loader::jobForRequest( const DOM::DOMString &url ) const
01200 {
01201 QPtrDictIterator<Request> it( m_requestsLoading );
01202
01203 for (; it.current(); ++it )
01204 {
01205 CachedObject *obj = it.current()->object;
01206
01207 if ( obj && obj->url() == url )
01208 return static_cast<KIO::Job *>( it.currentKey() );
01209 }
01210
01211 return 0;
01212 }
01213
01214
01215
01216
01217 QDict<CachedObject> *Cache::cache = 0;
01218 QPtrList<DocLoader>* Cache::docloader = 0;
01219 QPtrList<CachedObject> *Cache::freeList = 0;
01220 Cache::LRUList *Cache::lru = 0;
01221 Loader *Cache::m_loader = 0;
01222
01223 int Cache::maxSize = DEFCACHESIZE;
01224 int Cache::flushCount = 0;
01225 int Cache::cacheSize = 0;
01226
01227 QPixmap *Cache::nullPixmap = 0;
01228 QPixmap *Cache::brokenPixmap = 0;
01229
01230 void Cache::init()
01231 {
01232 if ( !cache )
01233 cache = new QDict<CachedObject>(401, true);
01234
01235 if ( !lru )
01236 lru = new LRUList;
01237
01238 if ( !docloader )
01239 docloader = new QPtrList<DocLoader>;
01240
01241 if ( !nullPixmap )
01242 nullPixmap = new QPixmap;
01243
01244 if ( !brokenPixmap )
01245 brokenPixmap = new QPixmap(KHTMLFactory::instance()->iconLoader()->loadIcon("file_broken", KIcon::Desktop, 16, KIcon::DisabledState));
01246
01247 if ( !m_loader )
01248 m_loader = new Loader();
01249
01250 if ( !freeList ) {
01251 freeList = new QPtrList<CachedObject>;
01252 freeList->setAutoDelete(true);
01253 }
01254 }
01255
01256 void Cache::flushFreeList()
01257 {
01258 for ( CachedObject* p = freeList->first(); p; p = freeList->next() )
01259 if (p->canDelete())
01260 freeList->remove();
01261 }
01262
01263 void Cache::clear()
01264 {
01265 if ( !cache ) return;
01266 #ifdef CACHE_DEBUG
01267 kdDebug( 6060 ) << "Cache: CLEAR!" << endl;
01268 statistics();
01269 #endif
01270 cache->setAutoDelete( true );
01271
01272 #if 0
01273 for (QDictIterator<CachedObject> it(*cache); it.current(); ++it)
01274 assert(it.current()->canDelete());
01275 for (QPtrListIterator<CachedObject> it(*freeList); it.current(); ++it)
01276 assert(it.current()->canDelete());
01277 #endif
01278
01279 delete cache; cache = 0;
01280 delete lru; lru = 0;
01281 delete nullPixmap; nullPixmap = 0;
01282 delete brokenPixmap; brokenPixmap = 0;
01283 delete m_loader; m_loader = 0;
01284 delete docloader; docloader = 0;
01285 delete freeList; freeList = 0;
01286 }
01287
01288 CachedImage *Cache::requestImage( DocLoader* dl, const DOMString & url, bool reload, time_t _expireDate )
01289 {
01290
01291 KURL kurl;
01292 KIO::CacheControl cachePolicy;
01293 if ( dl )
01294 {
01295 kurl = dl->m_doc->completeURL( url.string() );
01296 cachePolicy = dl->cachePolicy();
01297 }
01298 else
01299 {
01300 kurl = url.string();
01301 cachePolicy = KIO::CC_Verify;
01302 }
01303
01304 if( kurl.isMalformed() )
01305 {
01306 #ifdef CACHE_DEBUG
01307 kdDebug( 6060 ) << "Cache: Malformed url: " << kurl.url() << endl;
01308 #endif
01309 return 0;
01310 }
01311
01312 CachedObject *o = 0;
01313 if (!reload)
01314 o = cache->find(kurl.url());
01315 if(!o)
01316 {
01317 #ifdef CACHE_DEBUG
01318 kdDebug( 6060 ) << "Cache: new: " << kurl.url() << endl;
01319 #endif
01320 CachedImage *im = new CachedImage(dl, kurl.url(), cachePolicy, _expireDate);
01321 cache->insert( kurl.url(), im );
01322 lru->prepend( kurl.url() );
01323 o = im;
01324 }
01325
01326 if (o->status() == CachedObject::Unknown && dl && dl->autoloadImages())
01327 Cache::loader()->load(dl, o, true);
01328
01329 o->setExpireDate(_expireDate, true);
01330
01331 if(!(o->type() == CachedObject::Image))
01332 {
01333 #ifdef CACHE_DEBUG
01334 kdDebug( 6060 ) << "Cache::Internal Error in requestImage url=" << kurl.url() << "!" << endl;
01335 #endif
01336 return 0;
01337 }
01338
01339 #ifdef CACHE_DEBUG
01340 if( o->status() == CachedObject::Pending )
01341 kdDebug( 6060 ) << "Cache: loading in progress: " << kurl.url() << endl;
01342 else
01343 kdDebug( 6060 ) << "Cache: using cached: " << kurl.url() << ", status " << o->status() << endl;
01344 #endif
01345
01346 lru->touch( kurl.url() );
01347 if ( dl ) {
01348 dl->m_docObjects.remove( o );
01349 dl->m_docObjects.append( o );
01350 }
01351 return static_cast<CachedImage *>(o);
01352 }
01353
01354 CachedCSSStyleSheet *Cache::requestStyleSheet( DocLoader* dl, const DOMString & url, bool , time_t _expireDate, const QString& charset)
01355 {
01356
01357 KURL kurl;
01358 KIO::CacheControl cachePolicy;
01359 if ( dl )
01360 {
01361 kurl = dl->m_doc->completeURL( url.string() );
01362 cachePolicy = dl->cachePolicy();
01363 }
01364 else
01365 {
01366 kurl = url.string();
01367 cachePolicy = KIO::CC_Verify;
01368 }
01369
01370 if( kurl.isMalformed() )
01371 {
01372 kdDebug( 6060 ) << "Cache: Malformed url: " << kurl.url() << endl;
01373 return 0;
01374 }
01375
01376 CachedObject *o = cache->find(kurl.url());
01377 if(!o)
01378 {
01379 #ifdef CACHE_DEBUG
01380 kdDebug( 6060 ) << "Cache: new: " << kurl.url() << endl;
01381 #endif
01382 CachedCSSStyleSheet *sheet = new CachedCSSStyleSheet(dl, kurl.url(), cachePolicy, _expireDate, charset);
01383 cache->insert( kurl.url(), sheet );
01384 lru->prepend( kurl.url() );
01385 o = sheet;
01386 }
01387
01388 o->setExpireDate(_expireDate, true);
01389
01390 if(!(o->type() == CachedObject::CSSStyleSheet))
01391 {
01392 #ifdef CACHE_DEBUG
01393 kdDebug( 6060 ) << "Cache::Internal Error in requestStyleSheet url=" << kurl.url() << "!" << endl;
01394 #endif
01395 return 0;
01396 }
01397
01398 #ifdef CACHE_DEBUG
01399 if( o->status() == CachedObject::Pending )
01400 kdDebug( 6060 ) << "Cache: loading in progress: " << kurl.url() << endl;
01401 else
01402 kdDebug( 6060 ) << "Cache: using cached: " << kurl.url() << endl;
01403 #endif
01404
01405 lru->touch( kurl.url() );
01406 if ( dl ) {
01407 dl->m_docObjects.remove( o );
01408 dl->m_docObjects.append( o );
01409 }
01410 return static_cast<CachedCSSStyleSheet *>(o);
01411 }
01412
01413 void Cache::preloadStyleSheet( const QString &url, const QString &stylesheet_data)
01414 {
01415 CachedObject *o = cache->find(url);
01416 if(o)
01417 removeCacheEntry(o);
01418
01419 CachedCSSStyleSheet *stylesheet = new CachedCSSStyleSheet(url, stylesheet_data);
01420 cache->insert( url, stylesheet );
01421 }
01422
01423 CachedScript *Cache::requestScript( DocLoader* dl, const DOM::DOMString &url, bool , time_t _expireDate, const QString& charset)
01424 {
01425
01426 KURL kurl;
01427 KIO::CacheControl cachePolicy;
01428 if ( dl )
01429 {
01430 kurl = dl->m_doc->completeURL( url.string() );
01431 cachePolicy = dl->cachePolicy();
01432 }
01433 else
01434 {
01435 kurl = url.string();
01436 cachePolicy = KIO::CC_Verify;
01437 }
01438
01439 if( kurl.isMalformed() )
01440 {
01441 kdDebug( 6060 ) << "Cache: Malformed url: " << kurl.url() << endl;
01442 return 0;
01443 }
01444
01445 CachedObject *o = cache->find(kurl.url());
01446 if(!o)
01447 {
01448 #ifdef CACHE_DEBUG
01449 kdDebug( 6060 ) << "Cache: new: " << kurl.url() << endl;
01450 #endif
01451 CachedScript *script = new CachedScript(dl, kurl.url(), cachePolicy, _expireDate, charset);
01452 cache->insert( kurl.url(), script );
01453 lru->prepend( kurl.url() );
01454 o = script;
01455 }
01456
01457 o->setExpireDate(_expireDate, true);
01458
01459 if(!(o->type() == CachedObject::Script))
01460 {
01461 #ifdef CACHE_DEBUG
01462 kdDebug( 6060 ) << "Cache::Internal Error in requestScript url=" << kurl.url() << "!" << endl;
01463 #endif
01464 return 0;
01465 }
01466
01467 #ifdef CACHE_DEBUG
01468 if( o->status() == CachedObject::Pending )
01469 kdDebug( 6060 ) << "Cache: loading in progress: " << kurl.url() << endl;
01470 else
01471 kdDebug( 6060 ) << "Cache: using cached: " << kurl.url() << endl;
01472 #endif
01473
01474 lru->touch( kurl.url() );
01475 if ( dl ) {
01476 dl->m_docObjects.remove( o );
01477 dl->m_docObjects.append( o );
01478 }
01479 return static_cast<CachedScript *>(o);
01480 }
01481
01482 void Cache::preloadScript( const QString &url, const QString &script_data)
01483 {
01484 CachedObject *o = cache->find(url);
01485 if(o)
01486 removeCacheEntry(o);
01487
01488 CachedScript *script = new CachedScript(url, script_data);
01489 cache->insert( url, script );
01490 }
01491
01492 void Cache::flush(bool force)
01493 {
01494 if (force)
01495 flushCount = 0;
01496
01497 if (!lru || (lru->count() < (uint) flushCount))
01498 return;
01499
01500 init();
01501
01502 flushFreeList();
01503
01504 #ifdef CACHE_DEBUG
01505 statistics();
01506 kdDebug( 6060 ) << "Cache: flush()" << endl;
01507 #endif
01508
01509 int _cacheSize = 0;
01510
01511 for ( QStringList::Iterator it = lru->fromLast(); it != lru->end(); )
01512 {
01513 QString url = *it;
01514 --it;
01515 CachedObject *o = cache->find( url );
01516
01517 if( !o->canDelete() || o->status() == CachedObject::Persistent ) {
01518 continue;
01519
01520 }
01521
01522 if( o->status() != CachedObject::Uncacheable )
01523 {
01524 _cacheSize += o->size();
01525
01526 if( _cacheSize < maxSize )
01527 continue;
01528 }
01529 removeCacheEntry( o );
01530 }
01531 Cache::cacheSize = _cacheSize;
01532
01533 flushCount = lru->count()+10;
01534 #ifdef CACHE_DEBUG
01535
01536 #endif
01537 }
01538
01539 void Cache::setSize( int bytes )
01540 {
01541 maxSize = bytes;
01542
01543 flushCount = 0;
01544 flush(true);
01545 }
01546
01547 void Cache::statistics()
01548 {
01549 CachedObject *o;
01550
01551 init();
01552
01553 int size = 0;
01554 int msize = 0;
01555 int movie = 0;
01556 int images = 0;
01557 int scripts = 0;
01558 int stylesheets = 0;
01559 QDictIterator<CachedObject> it(*cache);
01560 for(it.toFirst(); it.current(); ++it)
01561 {
01562 o = it.current();
01563 switch(o->type()) {
01564 case CachedObject::Image:
01565 {
01566 CachedImage *im = static_cast<CachedImage *>(o);
01567 images++;
01568 if(im->m != 0)
01569 {
01570 qDebug("found image with movie: %p", im);
01571
01572 movie++;
01573 msize += im->size();
01574 }
01575 break;
01576 }
01577 case CachedObject::CSSStyleSheet:
01578 stylesheets++;
01579 break;
01580 case CachedObject::Script:
01581 scripts++;
01582 break;
01583 }
01584 size += o->size();
01585 }
01586 size /= 1024;
01587
01588 kdDebug( 6060 ) << "------------------------- image cache statistics -------------------" << endl;
01589 kdDebug( 6060 ) << "Number of items in cache: " << cache->count() << endl;
01590 kdDebug( 6060 ) << "Number of items in lru : " << lru->count() << endl;
01591 kdDebug( 6060 ) << "Number of cached images: " << images << endl;
01592 kdDebug( 6060 ) << "Number of cached movies: " << movie << endl;
01593 kdDebug( 6060 ) << "Number of cached scripts: " << scripts << endl;
01594 kdDebug( 6060 ) << "Number of cached stylesheets: " << stylesheets << endl;
01595 kdDebug( 6060 ) << "pixmaps: allocated space approx. " << size << " kB" << endl;
01596 kdDebug( 6060 ) << "movies : allocated space approx. " << msize/1024 << " kB" << endl;
01597 kdDebug( 6060 ) << "--------------------------------------------------------------------" << endl;
01598 }
01599
01600 void Cache::removeCacheEntry( CachedObject *object )
01601 {
01602 QString key = object->url().string();
01603
01604 cache->remove( key );
01605 lru->remove( key );
01606
01607 const DocLoader* dl;
01608 for ( dl=docloader->first(); dl; dl=docloader->next() )
01609 dl->removeCachedObject( object );
01610
01611 object->setFree();
01612 }
01613
01614
01615
01616
01617 void CachedObjectClient::setPixmap(const QPixmap &, const QRect&, CachedImage *) {}
01618 void CachedObjectClient::setStyleSheet(const DOM::DOMString &, const DOM::DOMString &) {}
01619 void CachedObjectClient::notifyFinished(CachedObject * ) {}
01620
01621
01622 #include "loader.moc"