File indexing completed on 2024-04-28 04:20:13
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #ifndef KP_DOCUMENT_H 0030 #define KP_DOCUMENT_H 0031 0032 0033 #include <QObject> 0034 #include <QString> 0035 #include <QUrl> 0036 0037 #include "imagelib/kpImage.h" 0038 #include "pixmapfx/kpPixmapFX.h" 0039 #undef environ 0040 0041 class QImage; 0042 class QIODevice; 0043 class QPoint; 0044 class QRect; 0045 class QSize; 0046 0047 class kpColor; 0048 class kpDocumentEnvironment; 0049 class kpDocumentSaveOptions; 0050 class kpDocumentMetaInfo; 0051 class kpAbstractImageSelection; 0052 class kpAbstractSelection; 0053 class kpTextSelection; 0054 0055 0056 // REFACTOR: rearrange method order to make sense and reflect kpDocument_*.cpp split. 0057 class kpDocument : public QObject 0058 { 0059 Q_OBJECT 0060 0061 public: 0062 // REFACTOR: Hide constructor and have 2 factory methods: 0063 // 0064 // Method 1. Creates a blank document with dimensions <w>x<h>. 0065 // 0066 // Method 2. Calls open(). <w> and <h> (aka constructorWidth() 0067 // and constructorHeight()) need not be specified. 0068 // 0069 // ? 0070 kpDocument (int w, int h, kpDocumentEnvironment *environ); 0071 ~kpDocument () override; 0072 0073 kpDocumentEnvironment *environ () const; 0074 void setEnviron (kpDocumentEnvironment *environ); 0075 0076 0077 // 0078 // File I/O - Open 0079 // 0080 0081 0082 static QImage getPixmapFromFile (const QUrl &url, bool suppressDoesntExistDialog, 0083 QWidget *parent, 0084 kpDocumentSaveOptions *saveOptions = nullptr, 0085 kpDocumentMetaInfo *metaInfo = nullptr); 0086 // REFACTOR: fix: open*() should only be called once. 0087 // Create a new kpDocument() if you want to open again. 0088 void openNew (const QUrl &url); 0089 bool open (const QUrl &url, bool newDocSameNameIfNotExist = false); 0090 0091 static void getDataFromImage(const QImage &image, 0092 kpDocumentSaveOptions &saveOptions, 0093 kpDocumentMetaInfo &metaInfo); 0094 0095 // 0096 // File I/O - Save 0097 // 0098 0099 static bool lossyPromptContinue (const QImage &pixmap, 0100 const kpDocumentSaveOptions &saveOptions, 0101 QWidget *parent); 0102 static bool savePixmapToDevice (const QImage &pixmap, 0103 QIODevice *device, 0104 const kpDocumentSaveOptions &saveOptions, 0105 const kpDocumentMetaInfo &metaInfo, 0106 bool lossyPrompt, 0107 QWidget *parent, 0108 bool *userCancelled = nullptr); 0109 static bool savePixmapToFile (const QImage &pixmap, 0110 const QUrl &url, 0111 const kpDocumentSaveOptions &saveOptions, 0112 const kpDocumentMetaInfo &metaInfo, 0113 bool lossyPrompt, 0114 QWidget *parent); 0115 bool save (bool lossyPrompt = false); 0116 bool saveAs (const QUrl &url, 0117 const kpDocumentSaveOptions &saveOptions, 0118 bool lossyPrompt = true); 0119 0120 0121 // Returns whether save() or saveAs() have ever been called and returned true 0122 bool savedAtLeastOnceBefore () const; 0123 0124 QUrl url () const; 0125 void setURL (const QUrl &url, bool isFromExistingURL); 0126 0127 // Returns whether the document's image was successfully opened from 0128 // or saved to the URL returned by url(). This is not true for a 0129 // new kpDocument and in the case of open() being passed 0130 // "newDocSameNameIfNotExist = true" when the URL doesn't exist. 0131 // 0132 // If this returns true and the kpDocument hasn't been modified, 0133 // this gives a pretty good indication that the image stored at url() 0134 // is equal to image() (unless the something has happened to that url 0135 // outside of KolourPaint). 0136 // 0137 // e.g. If the user types "kolourpaint doesnotexist.png" to start 0138 // KolourPaint, this method will return false. 0139 bool isFromExistingURL () const; 0140 0141 // Checks whether @p url still exists 0142 bool urlExists (const QUrl &url) const; 0143 0144 // (will convert: empty Url --> "Untitled") 0145 QString prettyUrl () const; 0146 0147 // (will convert: empty Url --> "Untitled") 0148 QString prettyFilename () const; 0149 0150 // (guaranteed to return valid pointer) 0151 0152 const kpDocumentSaveOptions *saveOptions () const; 0153 void setSaveOptions (const kpDocumentSaveOptions &saveOptions); 0154 0155 const kpDocumentMetaInfo *metaInfo () const; 0156 void setMetaInfo (const kpDocumentMetaInfo &metaInfo); 0157 0158 0159 /* 0160 * Properties (modified, width, height, color depth...) 0161 */ 0162 0163 void setModified (bool yes = true); 0164 bool isModified () const; 0165 bool isEmpty () const; 0166 0167 // REFACTOR: Rename to originalWidth()? 0168 int constructorWidth () const; // as passed to the constructor 0169 int width (bool ofSelection = false) const; 0170 int oldWidth () const; // only valid in a slot connected to sizeChanged() 0171 void setWidth (int w, const kpColor &backgroundColor); 0172 0173 // REFACTOR: Rename to originalHeight()? 0174 int constructorHeight () const; // as passed to the constructor 0175 int height (bool ofSelection = false) const; 0176 int oldHeight () const; // only valid in a slot connected to sizeChanged() 0177 void setHeight (int h, const kpColor &backgroundColor); 0178 0179 QRect rect (bool ofSelection = false) const; 0180 0181 0182 // 0183 // Image access 0184 // 0185 0186 // Returns a copy of part of the document's image (not including the 0187 // selection). 0188 kpImage getImageAt (const QRect &rect) const; 0189 0190 void setImageAt (const kpImage &image, const QPoint &at); 0191 0192 // "image(false)" returns a copy of the document's image, ignoring any 0193 // floating selection. 0194 // 0195 // "image(true)" returns a copy of a floating image selection's base 0196 // image (i.e. before selection transparency is applied), which may be 0197 // null if the image selection is a just a border. 0198 // 0199 // ASSUMPTION: For <ofSelection> == true only, an image selection exists. 0200 kpImage image (bool ofSelection = false) const; 0201 kpImage *imagePointer () const; 0202 0203 void setImage (const kpImage &image); 0204 // ASSUMPTION: If setting the selection's image, the selection must be 0205 // an image selection. 0206 void setImage (bool ofSelection, const kpImage &image); 0207 0208 0209 // 0210 // Selections 0211 // 0212 0213 public: 0214 kpAbstractSelection *selection () const; 0215 kpAbstractImageSelection *imageSelection () const; 0216 kpTextSelection *textSelection () const; 0217 0218 // Sets the document's selection to the given one and changes to the 0219 // matching selection tool. Tool changes occur in the following situations: 0220 // 0221 // 1. Setting a <selection> when a selection tool is not active. 0222 // 0223 // 2. Setting an image <selection> when the text tool is active. 0224 // ASSUMPTION: There is no text selection active when calling this 0225 // method (push it onto the document before calling this, 0226 // to avoid this problem). 0227 // 0228 // 3. Setting a text <selection> when an image selection tool is active. 0229 // ASSUMPTION: There is no image selection active when calling this 0230 // method (push it onto the document before calling this, 0231 // to avoid this problem). 0232 // 0233 // The justification for the above assumptions are to reduce the complexity 0234 // of this method's implementation -- changing from an image selection tool 0235 // to a text selection tool, or vice-versa, calls the end() method of the 0236 // current tool, which pushes any active selection onto the document. Since 0237 // this method sets the selection, losing the old selection in the middle of 0238 // the method would be tricky to work around. 0239 // 0240 // WARNING: Before calling this, you must ensure that the UI (kpMainWindow) 0241 // has the <selection>'s selection transparency or 0242 // for a text selection, its text style, selected. 0243 // TODO: Why can't we change it for them, if we change tool automatically for them already? 0244 void setSelection (const kpAbstractSelection &selection); 0245 0246 // Returns the base image of the current image selection. If this is 0247 // null (because the selection is still a border), it extracts the 0248 // pixels of the document marked out by the border of the selection. 0249 // 0250 // ASSUMPTION: There is an imageSelection(). 0251 // 0252 // TODO: this always returns base image - need ver that applies selection 0253 // transparency. 0254 kpImage getSelectedBaseImage () const; 0255 0256 // Sets the base image of the current image selection to the pixels 0257 // of the document marked out by the border of the selection. 0258 // 0259 // ASSUMPTION: There is an imageSelection() that is just a border 0260 // (no base image). 0261 void imageSelectionPullFromDocument (const kpColor &backgroundColor); 0262 0263 // Deletes the current selection, if there is a selection(), else NOP 0264 void selectionDelete (); 0265 0266 // Stamps a copy of the selection onto the document. 0267 // 0268 // For image selections, <applySelTransparency> set to true, means that 0269 // the transparent image of the selection is used. If set to false, 0270 // the base image of the selection is used. This argument is ignored 0271 // for non-image selections. 0272 // 0273 // ASSUMPTION: There is a selection() with content, else NOP 0274 void selectionCopyOntoDocument (bool applySelTransparency = true); 0275 0276 // Same as selectionCopyOntoDocument() but deletes the selection 0277 // afterwards. 0278 void selectionPushOntoDocument (bool applySelTransparency = true); 0279 0280 // 0281 // Same as image() but returns a _copy_ of the document image 0282 // + any (even non-image) selection pasted on top. 0283 // 0284 // Even if the selection has no content, it is still pasted: 0285 // 0286 // 1. For an image selection, this makes no difference. 0287 // 0288 // 2. For a text selection: 0289 // 0290 // a) with an opaque background: the background rectangle is 0291 // included -- this is necessary since the rectangle is visually 0292 // there after all, and the intention of this method is to report 0293 // everything. 0294 // 0295 // b) with a transparent background: this makes no difference. 0296 // 0297 kpImage imageWithSelection () const; 0298 0299 0300 /* 0301 * Transformations 0302 * (convenience only - you could achieve the same effect (and more) with 0303 * kpPixmapFX: these functions do not affect the selection) 0304 */ 0305 0306 void fill (const kpColor &color); 0307 void resize (int w, int h, const kpColor &backgroundColor); 0308 0309 0310 public Q_SLOTS: 0311 // these will emit signals! 0312 void slotContentsChanged (const QRect &rect); 0313 void slotSizeChanged (const QSize &newSize); 0314 0315 Q_SIGNALS: 0316 void documentOpened (); 0317 void documentSaved (); 0318 0319 // Emitted whenever the isModified() flag changes from false to true. 0320 // This is the _only_ signal that may be emitted in addition to the others. 0321 void documentModified (); 0322 0323 void contentsChanged (const QRect &rect); 0324 void sizeChanged (int newWidth, int newHeight); // see oldWidth(), oldHeight() 0325 void sizeChanged (const QSize &newSize); 0326 0327 void selectionEnabled (bool on); 0328 0329 // Emitted when setSelection() is given a selection such that we change 0330 // from a non-text-selection tool to the text selection tool or vice-versa. 0331 // <isText> reports whether the new selection is text (and therefore, 0332 // whether we've switched to the text tool). 0333 void selectionIsTextChanged (bool isText); 0334 0335 private: 0336 int m_constructorWidth, m_constructorHeight; 0337 kpImage *m_image; 0338 0339 QUrl m_url; 0340 bool m_isFromExistingURL; 0341 bool m_savedAtLeastOnceBefore; 0342 0343 kpDocumentSaveOptions *m_saveOptions; 0344 kpDocumentMetaInfo *m_metaInfo; 0345 0346 bool m_modified; 0347 0348 kpAbstractSelection *m_selection; 0349 0350 int m_oldWidth, m_oldHeight; 0351 0352 // There is no need to maintain binary compatibility at this stage. 0353 // The d-pointer is just so that you can experiment without recompiling 0354 // the kitchen sink. 0355 struct kpDocumentPrivate *d; 0356 }; 0357 0358 0359 #endif // KP_DOCUMENT_H