File indexing completed on 2024-05-12 04:19:37

0001 /*
0002 Gwenview: an image viewer
0003 Copyright 2007 Aurélien Gâteau <agateau@kde.org>
0004 
0005 This program is free software; you can redistribute it and/or
0006 modify it under the terms of the GNU General Public License
0007 as published by the Free Software Foundation; either version 2
0008 of the License, or (at your option) any later version.
0009 
0010 This program is distributed in the hope that it will be useful,
0011 but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 GNU General Public License for more details.
0014 
0015 You should have received a copy of the GNU General Public License
0016 along with this program; if not, write to the Free Software
0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0018 
0019 */
0020 #ifndef DOCUMENT_H
0021 #define DOCUMENT_H
0022 
0023 #include <lib/gwenviewlib_export.h>
0024 
0025 // STL
0026 #include <memory>
0027 
0028 // Qt
0029 #include <QObject>
0030 #include <QSharedData>
0031 #include <QSize>
0032 
0033 // Local
0034 #include <lib/cms/cmsprofile.h>
0035 #include <lib/mimetypeutils.h>
0036 
0037 class QImage;
0038 class QRect;
0039 class QSvgRenderer;
0040 class QUndoStack;
0041 
0042 class KJob;
0043 class QUrl;
0044 
0045 namespace Exiv2
0046 {
0047 class Image;
0048 }
0049 
0050 namespace Gwenview
0051 {
0052 class AbstractDocumentEditor;
0053 class AbstractDocumentImpl;
0054 class DocumentJob;
0055 class DocumentFactory;
0056 struct DocumentPrivate;
0057 class ImageMetaInfoModel;
0058 
0059 /**
0060  * This class represents an image.
0061  *
0062  * It handles loading and saving the image, applying operations and maintaining
0063  * the document undo stack.
0064  *
0065  * It is capable of loading down sampled versions of an image using
0066  * prepareDownSampledImageForZoom() and downSampledImageForZoom(). Down sampled
0067  * images load much faster than the full image but you need to load the full
0068  * image to manipulate it (use startLoadingFullImage() to do so).
0069  *
0070  * To get a Document instance for url, ask for one with
0071  * DocumentFactory::instance()->load(url);
0072  */
0073 class GWENVIEWLIB_EXPORT Document : public QObject, public QSharedData
0074 {
0075     Q_OBJECT
0076 public:
0077     /**
0078      * Document won't produce down sampled images for any zoom value higher than maxDownSampledZoom().
0079      *
0080      * Note: We can't use the enum {} trick to declare this constant, that's
0081      * why it's defined as a static method
0082      */
0083     static qreal maxDownSampledZoom();
0084 
0085     enum LoadingState {
0086         Loading, ///< Image is loading
0087         KindDetermined, ///< Image is still loading, but kind has been determined
0088         MetaInfoLoaded, ///< Image is still loading, but meta info has been loaded
0089         Loaded, ///< Full image has been loaded
0090         LoadingFailed, ///< Image loading has failed
0091     };
0092 
0093     using Ptr = QExplicitlySharedDataPointer<Document>;
0094     ~Document() override;
0095 
0096     /**
0097      * Returns a message for the last error which happened
0098      */
0099     QString errorString() const;
0100 
0101     void reload();
0102 
0103     void startLoadingFullImage();
0104 
0105     /**
0106      * Prepare a version of the image down sampled to be a bit bigger than
0107      * size() * @a zoom.
0108      * Do not ask for a down sampled image for @a zoom >= to MaxDownSampledZoom.
0109      *
0110      * @return true if the image is ready, false if not. In this case the
0111      * downSampledImageReady() signal will be emitted.
0112      */
0113     bool prepareDownSampledImageForZoom(qreal zoom);
0114 
0115     LoadingState loadingState() const;
0116 
0117     MimeTypeUtils::Kind kind() const;
0118 
0119     bool isModified() const;
0120 
0121     const QImage &image() const;
0122 
0123     const QImage &downSampledImageForZoom(qreal zoom) const;
0124 
0125     /**
0126      * Returns an implementation of AbstractDocumentEditor if this document can
0127      * be edited.
0128      */
0129     AbstractDocumentEditor *editor();
0130 
0131     QUrl url() const;
0132 
0133     DocumentJob *save(const QUrl &url, const QByteArray &format);
0134 
0135     QByteArray format() const;
0136 
0137     void waitUntilLoaded();
0138 
0139     QSize size() const;
0140 
0141     int width() const
0142     {
0143         return size().width();
0144     }
0145 
0146     int height() const
0147     {
0148         return size().height();
0149     }
0150 
0151     bool hasAlphaChannel() const;
0152 
0153     ImageMetaInfoModel *metaInfo() const;
0154 
0155     QUndoStack *undoStack() const;
0156 
0157     void setKeepRawData(bool);
0158 
0159     bool keepRawData() const;
0160 
0161     /**
0162      * Returns how much bytes the document is using
0163      */
0164     int memoryUsage() const;
0165 
0166     /**
0167      * Returns the compressed version of the document, if it is still
0168      * available.
0169      */
0170     QByteArray rawData() const;
0171 
0172     Cms::Profile::Ptr cmsProfile() const;
0173 
0174     /**
0175      * Returns a QSvgRenderer which can be used to render this document if it is
0176      * an SVG image. Returns a NULL pointer otherwise.
0177      */
0178     QSvgRenderer *svgRenderer() const;
0179 
0180     /**
0181      * Returns true if the image can be edited.
0182      * You must ensure it has been fully loaded with startLoadingFullImage() first.
0183      */
0184     bool isEditable() const;
0185 
0186     /**
0187      * Returns true if the image is animated (eg: gif or mng format)
0188      */
0189     bool isAnimated() const;
0190 
0191     /**
0192      * Starts animation. Only sensible if isAnimated() returns true.
0193      */
0194     void startAnimation();
0195 
0196     /**
0197      * Stops animation. Only sensible if isAnimated() returns true.
0198      */
0199     void stopAnimation();
0200 
0201     void enqueueJob(DocumentJob *);
0202 
0203     void imageOperationCompleted();
0204 
0205     /**
0206      * Returns true if there are queued tasks for this document.
0207      */
0208     bool isBusy() const;
0209 
0210 Q_SIGNALS:
0211     void downSampledImageReady();
0212     void imageRectUpdated(const QRect &);
0213     void kindDetermined(const QUrl &);
0214     void metaInfoLoaded(const QUrl &);
0215     void loaded(const QUrl &);
0216     void loadingFailed(const QUrl &);
0217     void saved(const QUrl &oldUrl, const QUrl &newUrl);
0218     void modified(const QUrl &);
0219     void metaInfoUpdated();
0220     void isAnimatedUpdated();
0221     void busyChanged(const QUrl &, bool);
0222     void allTasksDone();
0223 
0224 private Q_SLOTS:
0225     void emitMetaInfoLoaded();
0226     void emitLoaded();
0227     void emitLoadingFailed();
0228     void slotSaveResult(KJob *);
0229     void slotJobFinished(KJob *);
0230 
0231 private:
0232     friend class AbstractDocumentImpl;
0233     friend class DocumentFactory;
0234     friend struct DocumentPrivate;
0235     friend class DownSamplingJob;
0236 
0237     void setImageInternal(const QImage &);
0238     void setKind(MimeTypeUtils::Kind);
0239     void setFormat(const QByteArray &);
0240     void setSize(const QSize &);
0241     void setExiv2Image(std::unique_ptr<Exiv2::Image>);
0242     void setDownSampledImage(const QImage &, int invertedZoom);
0243     void switchToImpl(AbstractDocumentImpl *impl);
0244     void setErrorString(const QString &);
0245     void setCmsProfile(const Cms::Profile::Ptr &);
0246 
0247     Document(const QUrl &);
0248     DocumentPrivate *const d;
0249 };
0250 
0251 } // namespace
0252 
0253 #endif /* DOCUMENT_H */