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