File indexing completed on 2024-05-12 16:39:36
0001 /* This file is part of the KDE project 0002 Copyright (C) 2005 Jarosław Staniek <staniek@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #ifndef KEXIBLOBBUFFER_H 0021 #define KEXIBLOBBUFFER_H 0022 0023 #include <QObject> 0024 #include <QPixmap> 0025 #include <QUrl> 0026 0027 #include "kexicore_export.h" 0028 0029 class KDbConnection; 0030 0031 //! Application-wide buffer for local BLOB data like pixmaps. 0032 /*! For now only pixmaps are supported 0033 @todo support any KPart-compatible objects and more... 0034 0035 Use this class by acessing to its singleton: KexiBLOBBuffer::self(). 0036 0037 This class is used for buffering BLOB data, 0038 to avoid duplicating object's data in memory and a need for loading (decoding) 0039 the same object many times. 0040 The data is always local, what means database storage is not employed here. 0041 0042 Each BLOB instance is identified by an unsigned integer number (Id_t type), 0043 uniquely generated on BLOB loading. Each BLOB can have assigned source url 0044 it has been loaded from (the url can be empty though, e.g. for data coming from clipboard). 0045 0046 References to KexiBLOBBuffer are counted, so when last reference is lost, data is freed 0047 and the integer identifier is no longer pointing any valid data. 0048 KexiBLOBBuffer::Handle is value-based class that describes handle based in an identifier. 0049 Objects of this class are obtained e.g. from insertPixmap() method. 0050 0051 There are two kinds of identifiers: 0052 - integers assigned for BLOBs already saved to a db backend, 0053 when KexiBLOBBuffer::Handle::stored() is true 0054 - temporary integers assigned for new BLOBs not yet saved to a db backend, 0055 when KexiBLOBBuffer::Handle::stored() is false 0056 KexiBLOBBuffer::Handle::setStoredWidthID() can be used to switch from unstored to stored state. 0057 Among others, the state has effect on saving forms: only unstored BLOBs will be saved back 0058 to the database; when a BLOB needs to be removed, only it will be physically removed only if it was stored. 0059 0060 KexiBLOBBuffer is also useful for two more reasons: 0061 - Property editor's item for "image" property displays a preview of pixmap contents. 0062 Without buffering, it would be needed to load pixmap data again: what if the file 0063 it is loaded from is located remote and connection is slow? Memory would be also unnecessary doubled. 0064 - Undo/Redo framework requires to store previous property values. Having a reference defined 0065 by a single interger, memory can be handled more effectively. 0066 0067 Example use cases: 0068 A large pixmap file "abc.jpg" is loaded as QByteArray <b>once</b> and buffered: 0069 integer identifier is returned. 0070 Then, multiple image widgets are using "abc.jpg" for displaying. 0071 Duplicating an image widget means only duplicating it's properties 0072 like position and BLOB's id: BLOB itself (data of "abc.jpg") is not duplicated. 0073 Creating a new image widget and assiging the same "abc.jpg" pixmap, means only 0074 referencing KexiBLOBBuffer using the same identifier. 0075 */ 0076 class KEXICORE_EXPORT KexiBLOBBuffer : public QObject 0077 { 0078 Q_OBJECT 0079 0080 private: 0081 class Item; 0082 public: 0083 //! long integer for unique identifying blobs 0084 //! @todo Qt4: will be changed 0085 typedef long Id_t; 0086 0087 //! Access to KexiBLOBBuffer singleton 0088 static KexiBLOBBuffer* self(); 0089 0090 static void setConnection(KDbConnection *conn); 0091 0092 //! Object handle used by KexiBLOBBuffer 0093 class KEXICORE_EXPORT Handle 0094 { 0095 public: 0096 //! Constructs a null handle. 0097 //! Null handles have empty pixap and data members, id == 0 and cast to boolean false. 0098 Handle(); 0099 0100 //! Constructs a copy of \a handle. 0101 Handle(const Handle& handle); 0102 0103 ~Handle(); 0104 0105 Id_t id() const { 0106 return m_item ? m_item->id : 0; 0107 } 0108 0109 /*! \return true if this BLOB data pointed by this handle is stored at the db backend 0110 or false if it is kept in memory. Null handles return false. */ 0111 bool stored() const { 0112 return m_item ? m_item->stored : false; 0113 } 0114 0115 //! \return true if this is null handle (i.e. one not pointing to any data) 0116 operator bool() const { 0117 return m_item; 0118 } 0119 0120 Handle& operator=(const Handle& handle); 0121 0122 QByteArray data() const { 0123 return m_item ? m_item->data() : QByteArray(); 0124 } 0125 0126 QPixmap pixmap() const { 0127 return m_item ? m_item->pixmap() : QPixmap(); 0128 } 0129 0130 /*! Sets "stored" flag to true by setting non-temporary identifier. 0131 Only call this method for unstored (in memory) BLOBs */ 0132 void setStoredWidthID(Id_t id); 0133 0134 QString originalFileName() const { 0135 return m_item ? m_item->name : QString(); 0136 } 0137 0138 QString mimeType() const { 0139 return m_item ? m_item->mimeType : QString(); 0140 } 0141 0142 Id_t folderId() const { 0143 return m_item ? m_item->folderId : 0; 0144 } 0145 0146 protected: 0147 //! Constructs a handle based on \a item. Null handle is constructed for null \a item. 0148 explicit Handle(Item* item); 0149 private: 0150 Item* m_item; 0151 friend class KexiBLOBBuffer; 0152 }; 0153 0154 //! @internal 0155 KexiBLOBBuffer(); 0156 0157 ~KexiBLOBBuffer(); 0158 0159 /*! Inserts a new pixmap loaded from a file at \a url. 0160 If the same file has already been loaded before, it can be found in cache 0161 and returned instantly. It is assumed that the BLOB is unstored, because it is loaded from 0162 external source, so stored() will be equal to false for returned handle. 0163 \return handle to the pixmap data or a null handle if such pixmap could not be loaded. */ 0164 Handle insertPixmap(const QUrl &url); 0165 0166 /*! Inserts a new BLOB data. 0167 @param data The data for BLOB object. 0168 @param name The name for the object, usually a file name or empty 0169 @param caption The more friendly than name, can be based on file name or empty or 0170 defined by a user (this case is not yet used) 0171 @param mimeType The mimeType for the object for easier and mor accurate decoding. 0172 @param identifier Object's identifier. If positive, the "stored" flag for the data 0173 will be set to true with \a identifer, otherwise (the default) the BLOB data will 0174 have "stored" flag set to false, and a new temporary identifier will be assigned. */ 0175 Handle insertObject(const QByteArray& data, const QString& name, 0176 const QString& caption, const QString& mimeType, Id_t identifier = 0); 0177 0178 /*! Inserts a new pixmap available in memory, e.g. coming from clipboard. */ 0179 Handle insertPixmap(const QPixmap& pixmap); 0180 0181 /*! \return an object for a given \a id. If \a stored is true, stored BLOBs buffer 0182 is browsed, otherwise unstored (in memory) BLOBs buffer is browsed. 0183 If no object is cached for this id, null handle is returned. */ 0184 Handle objectForId(Id_t id, bool stored); 0185 0186 /*! \return an object for a given \a id. First, unstored object is checked, then unstored, 0187 if stored was not found. */ 0188 Handle objectForId(Id_t id); 0189 0190 protected: 0191 /*! Removes an object for a given \a id. If \a stored is true, stored BLOB is removed, 0192 otherwise unstored (in memory) BLOB is removed. */ 0193 void removeItem(Id_t id, bool stored); 0194 0195 /*! Takes an object for a \a item out of the buffer. */ 0196 void takeItem(Item* item); 0197 0198 /*! Inserts an object for a given \a id into the buffer. */ 0199 void insertItem(Item* item); 0200 0201 private: 0202 class KEXICORE_EXPORT Item 0203 { 0204 public: 0205 Item(const QByteArray& data, Id_t ident, 0206 bool stored, 0207 const QString& name = QString(), 0208 const QString& caption = QString(), 0209 const QString& mimeType = QString(), 0210 Id_t folderId = 0, 0211 const QPixmap& pixmap = QPixmap()); 0212 ~Item(); 0213 QPixmap pixmap() const; 0214 QByteArray data() const; 0215 QString name; 0216 QString caption; //!< @todo for future use within image gallery 0217 QString mimeType; 0218 int refs; 0219 Id_t id; 0220 Id_t folderId; 0221 bool stored; 0222 QString prettyURL; //!< helper 0223 private: 0224 QByteArray *m_data; 0225 QPixmap *m_pixmap; 0226 bool *m_pixmapLoaded; //!< *m_pixmapLoaded will be set in Info::pixmap(), 0227 //!< to avoid multiple pixmap decoding when it previously failed 0228 friend class KexiBLOBBuffer; 0229 }; 0230 class Private; 0231 Private * const d; 0232 friend class Handle; 0233 }; 0234 0235 #endif