File indexing completed on 2024-04-28 04:20:13
0001 /* 0002 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0003 All rights reserved. 0004 0005 Redistribution and use in source and binary forms, with or without 0006 modification, are permitted provided that the following conditions 0007 are met: 0008 0009 1. Redistributions of source code must retain the above copyright 0010 notice, this list of conditions and the following disclaimer. 0011 2. Redistributions in binary form must reproduce the above copyright 0012 notice, this list of conditions and the following disclaimer in the 0013 documentation and/or other materials provided with the distribution. 0014 0015 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0016 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0017 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0018 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0019 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0020 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0022 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0024 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 0027 0028 #define DEBUG_KP_DOCUMENT 0 0029 0030 0031 #include "kpDocument.h" 0032 #include "kpDocumentPrivate.h" 0033 0034 #include "imagelib/kpColor.h" 0035 #include "widgets/toolbars/kpColorToolBar.h" 0036 #include "kpDefs.h" 0037 #include "environments/document/kpDocumentEnvironment.h" 0038 #include "document/kpDocumentSaveOptions.h" 0039 #include "imagelib/kpDocumentMetaInfo.h" 0040 #include "imagelib/effects/kpEffectReduceColors.h" 0041 #include "pixmapfx/kpPixmapFX.h" 0042 #include "tools/kpTool.h" 0043 #include "lgpl/generic/kpUrlFormatter.h" 0044 #include "views/manager/kpViewManager.h" 0045 0046 0047 #include <QColor> 0048 #include <QImage> 0049 #include <QMimeDatabase> 0050 #include <QImageReader> 0051 #include <QBuffer> 0052 0053 #include <KJobWidgets> 0054 #include "kpLogCategories.h" 0055 #include <KLocalizedString> 0056 #include <KIO/StoredTransferJob> 0057 #include <KMessageBox> 0058 0059 //--------------------------------------------------------------------- 0060 0061 void kpDocument::getDataFromImage(const QImage &image, 0062 kpDocumentSaveOptions &saveOptions, 0063 kpDocumentMetaInfo &metaInfo) 0064 { 0065 saveOptions.setColorDepth(image.depth()); 0066 saveOptions.setDither(false); // avoid double dithering when saving 0067 0068 metaInfo.setDotsPerMeterX(image.dotsPerMeterX()); 0069 metaInfo.setDotsPerMeterY(image.dotsPerMeterY()); 0070 metaInfo.setOffset(image.offset()); 0071 0072 QStringList keys = image.textKeys(); 0073 for (int i = 0; i < keys.count(); i++) { 0074 metaInfo.setText(keys[i], image.text(keys[i])); 0075 } 0076 } 0077 0078 //--------------------------------------------------------------------- 0079 0080 // public static 0081 QImage kpDocument::getPixmapFromFile(const QUrl &url, bool suppressDoesntExistDialog, 0082 QWidget *parent, 0083 kpDocumentSaveOptions *saveOptions, 0084 kpDocumentMetaInfo *metaInfo) 0085 { 0086 #if DEBUG_KP_DOCUMENT 0087 qCDebug(kpLogDocument) << "kpDocument::getPixmapFromFile(" << url << "," << parent << ")"; 0088 #endif 0089 0090 if (saveOptions) { 0091 *saveOptions = kpDocumentSaveOptions (); 0092 } 0093 0094 if (metaInfo) { 0095 *metaInfo = kpDocumentMetaInfo (); 0096 } 0097 0098 if (url.isEmpty ()) { 0099 return {}; 0100 } 0101 0102 KIO::StoredTransferJob *job = KIO::storedGet (url); 0103 KJobWidgets::setWindow(job, parent); 0104 0105 if (!job->exec()) 0106 { 0107 if (!suppressDoesntExistDialog) 0108 { 0109 // TODO: Use "Cannot" instead of "Could not" in all dialogs in KolourPaint. 0110 // Or at least choose one consistently. 0111 // 0112 // TODO: Have captions for all dialogs in KolourPaint. 0113 KMessageBox::error (parent, 0114 i18n ("Could not open \"%1\".", 0115 kpUrlFormatter::PrettyFilename (url))); 0116 } 0117 0118 return {}; 0119 } 0120 QByteArray data = job->data(); 0121 0122 QMimeDatabase db; 0123 QMimeType mimeType = db.mimeTypeForFileNameAndData(url.fileName(), data); 0124 0125 if (saveOptions) { 0126 saveOptions->setMimeType(mimeType.name()); 0127 } 0128 0129 #if DEBUG_KP_DOCUMENT 0130 qCDebug(kpLogDocument) << "\tmimetype=" << mimeType.name(); 0131 qCDebug(kpLogDocument) << "\tsrc=" << url.path (); 0132 #endif 0133 0134 QBuffer buffer(&data); 0135 buffer.open(QIODevice::ReadOnly); 0136 QImageReader reader(&buffer); 0137 reader.setAutoTransform(true); 0138 reader.setDecideFormatFromContent(true); 0139 0140 // Do *NOT* convert to 0141 // QImage image = reader.read(); 0142 // this variant is more lenient on errors and we may get something that we would not otherwise 0143 // e.g. image from https://bugs.kde.org/show_bug.cgi?id=441554 0144 QImage image; 0145 reader.read(&image); 0146 0147 if (image.isNull ()) 0148 { 0149 KMessageBox::error (parent, 0150 i18n ("Could not open \"%1\" - unsupported image format.\n" 0151 "The file may be corrupt.", 0152 kpUrlFormatter::PrettyFilename (url))); 0153 return {}; 0154 } 0155 0156 #if DEBUG_KP_DOCUMENT 0157 qCDebug(kpLogDocument) << "\tpixmap: depth=" << image.depth () 0158 << " hasAlphaChannel=" << image.hasAlphaChannel (); 0159 #endif 0160 0161 if ( saveOptions && metaInfo ) { 0162 getDataFromImage(image, *saveOptions, *metaInfo); 0163 } 0164 0165 // make sure we always have Format_ARGB32_Premultiplied as this is the fastest to draw on 0166 // and Qt can not draw onto Format_Indexed8 (Qt-4.7) 0167 if ( image.format() != QImage::Format_ARGB32_Premultiplied ) { 0168 image.convertTo(QImage::Format_ARGB32_Premultiplied); 0169 } 0170 0171 return image; 0172 } 0173 0174 //--------------------------------------------------------------------- 0175 0176 void kpDocument::openNew (const QUrl &url) 0177 { 0178 #if DEBUG_KP_DOCUMENT 0179 qCDebug(kpLogDocument) << "kpDocument::openNew (" << url << ")"; 0180 #endif 0181 0182 m_image->fill(QColor(Qt::white).rgb()); 0183 0184 setURL (url, false/*not from url*/); 0185 0186 *m_saveOptions = kpDocumentSaveOptions (); 0187 0188 if ( !url.isEmpty() ) 0189 { 0190 // guess the mimetype from url's filename extension. 0191 // 0192 // That way "kolourpaint doesnotexist.bmp" automatically 0193 // selects the BMP file format when the save dialog comes up for 0194 // the first time. 0195 0196 QMimeDatabase mimeDb; 0197 m_saveOptions->setMimeType(mimeDb.mimeTypeForUrl(url).name()); 0198 } 0199 0200 *m_metaInfo = kpDocumentMetaInfo (); 0201 m_modified = false; 0202 0203 Q_EMIT documentOpened (); 0204 } 0205 0206 //--------------------------------------------------------------------- 0207 0208 bool kpDocument::open (const QUrl &url, bool newDocSameNameIfNotExist) 0209 { 0210 #if DEBUG_KP_DOCUMENT 0211 qCDebug(kpLogDocument) << "kpDocument::open (" << url << ")"; 0212 #endif 0213 0214 kpDocumentSaveOptions newSaveOptions; 0215 kpDocumentMetaInfo newMetaInfo; 0216 QImage newPixmap = kpDocument::getPixmapFromFile (url, 0217 newDocSameNameIfNotExist/*suppress "doesn't exist" dialog*/, 0218 d->environ->dialogParent (), 0219 &newSaveOptions, 0220 &newMetaInfo); 0221 0222 if (!newPixmap.isNull ()) 0223 { 0224 delete m_image; 0225 m_image = new kpImage (newPixmap); 0226 0227 setURL (url, true/*is from url*/); 0228 *m_saveOptions = newSaveOptions; 0229 *m_metaInfo = newMetaInfo; 0230 m_modified = false; 0231 0232 Q_EMIT documentOpened (); 0233 return true; 0234 } 0235 0236 if (newDocSameNameIfNotExist) 0237 { 0238 if (urlExists (url)) // not just a permission error? 0239 { 0240 openNew (url); 0241 } 0242 else 0243 { 0244 openNew (QUrl ()); 0245 } 0246 0247 return true; 0248 } 0249 0250 return false; 0251 0252 } 0253 0254 //---------------------------------------------------------------------