/* This file is part of the KDE libraries Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) Copyright (C) 2001-2003 Dirk Mueller Copyright (C) 2003 Apple Computer, Inc This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. This class provides all functionality needed for loading images, style sheets and html pages from the web. It has a memory cache for these objects. */ #ifndef _khtml_loader_h #define _khtml_loader_h #ifdef HAVE_CONFIG_H #include #endif #include #include "loader_client.h" #ifdef HAVE_LIBJPEG #include "loader_jpeg.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include class TQMovie; class KHTMLPart; namespace TDEIO { class Job; class TransferJob; } namespace DOM { class CSSStyleSheetImpl; class DocumentImpl; } namespace khtml { class CachedObject; class Request; class DocLoader; /** * @internal * * A cached object. Classes who want to use this object should derive * from CachedObjectClient, to get the function calls in case the requested data has arrived. * * This class also does the actual communication with kio and loads the file. */ class CachedObject { public: enum Type { Image, CSSStyleSheet, Script }; enum Status { Unknown, // let imagecache decide what to do with it New, // inserting new image Pending, // only partially loaded Persistent, // never delete this pixmap Cached // regular case }; CachedObject(const DOM::DOMString &url, Type type, TDEIO::CacheControl _cachePolicy, int size) : m_url(url), m_type(type), m_cachePolicy(_cachePolicy), m_expireDate(0), m_size(size) { m_status = Pending; m_accessCount = 0; m_cachePolicy = _cachePolicy; m_request = 0; m_deleted = false; m_free = false; m_hadError = false; m_wasBlocked = false; m_prev = m_next = 0; } virtual ~CachedObject(); virtual void data( TQBuffer &buffer, bool eof) = 0; virtual void error( int err, const char *text ) = 0; const DOM::DOMString &url() const { return m_url; } Type type() const { return m_type; } virtual void ref(CachedObjectClient *consumer); virtual void deref(CachedObjectClient *consumer); int count() const { return m_clients.count(); } int accessCount() const { return m_accessCount; } void setStatus(Status s) { m_status = s; } Status status() const { return m_status; } virtual void setCharset( const TQString& /*charset*/ ) {} TQTextCodec* codecForBuffer( const TQString& charset, const TQByteArray& buffer ) const; int size() const { return m_size; } bool isLoaded() const { return !m_loading; } bool free() const { return m_free; } TDEIO::CacheControl cachePolicy() const { return m_cachePolicy; } void setRequest(Request *_request); bool canDelete() const { return (m_clients.count() == 0 && !m_request); } void setExpireDate(time_t _expireDate) { m_expireDate = _expireDate; } bool isExpired() const; virtual bool schedule() const { return false; } virtual void finish(); /** * List of acceptable mimetypes separated by ",". A mimetype may contain a wildcard. */ // e.g. "text/*" TQString accept() const { return m_accept; } void setAccept(const TQString &_accept) { m_accept = _accept; } protected: void setSize(int size); TQPtrDict m_clients; DOM::DOMString m_url; TQString m_accept; Request *m_request; Type m_type; Status m_status; int m_accessCount; TDEIO::CacheControl m_cachePolicy; time_t m_expireDate; int m_size; bool m_deleted : 1; bool m_loading : 1; bool m_free : 1; bool m_hadError : 1; bool m_wasBlocked : 1; private: bool allowInLRUList() const { return canDelete() && !m_free && status() != Persistent; } CachedObject* m_next; CachedObject* m_prev; friend class Cache; friend class ::KHTMLPart; }; /** * a cached style sheet. also used for loading xml documents. * * ### rename to CachedTextDoc or something since it's more generic than just for css */ class CachedCSSStyleSheet : public CachedObject { public: CachedCSSStyleSheet(DocLoader* dl, const DOM::DOMString &url, TDEIO::CacheControl cachePolicy, const char *accept); CachedCSSStyleSheet(const DOM::DOMString &url, const TQString &stylesheet_data); const DOM::DOMString &sheet() const { return m_sheet; } virtual void ref(CachedObjectClient *consumer); virtual void data( TQBuffer &buffer, bool eof ); virtual void error( int err, const char *text ); virtual bool schedule() const { return true; } void setCharsetHint( const TQString& charset ) { m_charsetHint = charset; } void setCharset( const TQString& charset ) { m_charset = charset; } protected: void checkNotify(); DOM::DOMString m_sheet; TQString m_charset; TQString m_charsetHint; int m_err; TQString m_errText; }; /** * a cached script */ class CachedScript : public CachedObject { public: CachedScript(DocLoader* dl, const DOM::DOMString &url, TDEIO::CacheControl cachePolicy, const char* accept ); CachedScript(const DOM::DOMString &url, const TQString &script_data); const DOM::DOMString &script() const { return m_script; } virtual void ref(CachedObjectClient *consumer); virtual void data( TQBuffer &buffer, bool eof ); virtual void error( int err, const char *text ); virtual bool schedule() const { return false; } void checkNotify(); bool isLoaded() const { return !m_loading; } void setCharset( const TQString& charset ) { m_charset = charset; } protected: TQString m_charset; DOM::DOMString m_script; }; class ImageSource; /** * a cached image */ class CachedImage : public TQObject, public CachedObject { Q_OBJECT public: CachedImage(DocLoader* dl, const DOM::DOMString &url, TDEIO::CacheControl cachePolicy, const char* accept); virtual ~CachedImage(); const TQPixmap &pixmap() const; const TQPixmap &scaled_pixmap(int xWidth, int xHeight); const TQPixmap &tiled_pixmap(const TQColor& bg, int xWidth = -1, int xHeight = -1); TQSize pixmap_size() const; // returns the size of the complete (i.e. when finished) loading TQRect valid_rect() const; // returns the rectangle of pixmap that has been loaded already bool canRender() const { return !isErrorImage() && pixmap_size().width() > 0 && pixmap_size().height() > 0; } void ref(CachedObjectClient *consumer); virtual void deref(CachedObjectClient *consumer); virtual void data( TQBuffer &buffer, bool eof ); virtual void error( int err, const char *text ); bool isTransparent() const { return isFullyTransparent; } bool isErrorImage() const { return m_hadError; } bool isBlockedImage() const { return m_wasBlocked; } const TQString& suggestedFilename() const { return m_suggestedFilename; } void setSuggestedFilename( const TQString& s ) { m_suggestedFilename = s; } #ifdef IMAGE_TITLES const TQString& suggestedTitle() const { return m_suggestedTitle; } void setSuggestedTitle( const TQString& s ) { m_suggestedTitle = s; } #else const TQString& suggestedTitle() const { return m_suggestedFilename; } #endif void setShowAnimations( KHTMLSettings::KAnimationAdvice ); void pauseAnimations(); void resumeAnimations(); virtual bool schedule() const { return true; } virtual void finish(); protected: void clear(); private slots: /** * gets called, whenever a TQMovie changes frame */ void movieUpdated( const TQRect &rect ); void movieStatus(int); void movieResize(const TQSize&); void deleteMovie(); private: void do_notify(const TQPixmap& p, const TQRect& r); TQString m_suggestedFilename; #ifdef IMAGE_TITLES TQString m_suggestedTitle; #endif TQMovie* m; TQPixmap* p; TQPixmap* scaled; TQPixmap* bg; QRgb bgColor; TQSize bgSize; mutable TQPixmap* pixPart; ImageSource* imgSource; const char* formatType; // Is the name of the movie format type int width; int height; // Is set if movie format type ( incremental/animation) was checked bool typeChecked : 1; bool isFullyTransparent : 1; bool monochrome : 1; KHTMLSettings::KAnimationAdvice m_showAnimations : 2; friend class Cache; friend class ::KHTMLPart; }; /** * @internal * * Manages the loading of scripts/images/stylesheets for a particular document */ class DocLoader { public: DocLoader(KHTMLPart*, DOM::DocumentImpl*); ~DocLoader(); CachedImage *requestImage( const DOM::DOMString &url); CachedCSSStyleSheet *requestStyleSheet( const DOM::DOMString &url, const TQString& charsetHint, const char *accept = "text/css", bool userSheet = false ); CachedScript *requestScript( const DOM::DOMString &url, const TQString& charset); bool autoloadImages() const { return m_bautoloadImages; } TDEIO::CacheControl cachePolicy() const { return m_cachePolicy; } KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; } time_t expireDate() const { return m_expireDate; } KHTMLPart* part() const { return m_part; } DOM::DocumentImpl* doc() const { return m_doc; } void setCacheCreationDate( time_t ); void setExpireDate( time_t, bool relative ); void setAutoloadImages( bool ); void setCachePolicy( TDEIO::CacheControl cachePolicy ) { m_cachePolicy = cachePolicy; } void setShowAnimations( KHTMLSettings::KAnimationAdvice ); void pauseAnimations(); void resumeAnimations(); void insertCachedObject( CachedObject* o ) const; void removeCachedObject( CachedObject* o) const { m_docObjects.remove( o ); } private: bool needReload(CachedObject *existing, const TQString &fullUrl); friend class Cache; friend class DOM::DocumentImpl; friend class ::KHTMLPart; TQStringList m_reloadedURLs; mutable TQPtrDict m_docObjects; time_t m_expireDate; time_t m_creationDate; TDEIO::CacheControl m_cachePolicy; bool m_bautoloadImages : 1; KHTMLSettings::KAnimationAdvice m_showAnimations : 2; KHTMLPart* m_part; DOM::DocumentImpl* m_doc; }; /** * @internal */ class Request { public: Request(DocLoader* dl, CachedObject *_object, bool _incremental); ~Request(); bool incremental; TQBuffer m_buffer; CachedObject *object; DocLoader* m_docLoader; }; /** * @internal */ class Loader : public TQObject { Q_OBJECT public: Loader(); void load(DocLoader* dl, CachedObject *object, bool incremental = true); int numRequests( DocLoader* dl ) const; void cancelRequests( DocLoader* dl ); // may return 0L TDEIO::Job *jobForRequest( const DOM::DOMString &url ) const; signals: void requestStarted( khtml::DocLoader* dl, khtml::CachedObject* obj ); void requestDone( khtml::DocLoader* dl, khtml::CachedObject *obj ); void requestFailed( khtml::DocLoader* dl, khtml::CachedObject *obj ); protected slots: void slotFinished( TDEIO::Job * ); void slotData( TDEIO::Job *, const TQByteArray & ); void servePendingRequests(); protected: TQPtrList m_requestsPending; TQPtrDict m_requestsLoading; #ifdef HAVE_LIBJPEG KJPEGFormatType m_jpegloader; #endif TQTimer m_timer; }; /** * @internal * * Provides a cache/loader for objects needed for displaying the html page. * At the moment these are stylesheets, scripts and images */ class Cache { friend class DocLoader; template static CachedObjectType* requestObject( DocLoader* dl, const KURL& kurl, const char* accept ); public: /** * init the cache in case it's not already. This needs to get called once * before using it. */ KDE_EXPORT static void init(); /** * Ask the cache for some url. Will return a cachedObject, and * load the requested data in case it's not cached * if the DocLoader is zero, the url must be full-qualified. * Otherwise, it is automatically base-url expanded */ // static CachedImage *requestImage(const KURL& url) // { return Cache::requestObject( 0, url, 0 ); } /** * Pre-loads a stylesheet into the cache. */ static void preloadStyleSheet(const TQString &url, const TQString &stylesheet_data); /** * Pre-loads a script into the cache. */ static void preloadScript(const TQString &url, const TQString &script_data); static void setSize( int bytes ); static int size() { return maxSize; }; static void statistics(); KDE_EXPORT static void flush(bool force=false); /** * clears the cache * Warning: call this only at the end of your program, to clean * up memory (useful for finding memory holes) */ KDE_EXPORT static void clear(); static Loader *loader() { return m_loader; } static TQPixmap *nullPixmap; static TQPixmap *brokenPixmap; static TQPixmap *blockedPixmap; static int cacheSize; static void removeCacheEntry( CachedObject *object ); private: static void checkLRUAndUncacheableListIntegrity(); friend class CachedObject; static TQDict *cache; static TQPtrList* docloader; static TQPtrList *freeList; static void insertInLRUList(CachedObject*); static void removeFromLRUList(CachedObject*); static int totalSizeOfLRU; static int maxSize; static Loader *m_loader; }; } // namespace #endif