kpDocument_Open.cpp 8.64 KB
Newer Older
1 2

/*
3
   Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   1. Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
   2. Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#define DEBUG_KP_DOCUMENT 0


#include <kpDocument.h>
#include <kpDocumentPrivate.h>

#include <math.h>

#include <qcolor.h>
#include <qimage.h>

#include <kdebug.h>
#include <kglobal.h>
#include <kimageio.h>
#include <kio/netaccess.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kmimetype.h>  // TODO: isn't this in KIO?
#include <ktemporaryfile.h>

49 50 51
#include <kpColor.h>
#include <kpColorToolBar.h>
#include <kpDefs.h>
52
#include <kpDocumentEnvironment.h>
53 54
#include <kpDocumentSaveOptions.h>
#include <kpDocumentMetaInfo.h>
55
#include <kpEffectReduceColors.h>
56 57
#include <kpPixmapFX.h>
#include <kpTool.h>
58
#include <kpUrlFormatter.h>
59
#include <kpViewManager.h>
60

61
//---------------------------------------------------------------------
62

63 64 65
void kpDocument::getDataFromImage(const QImage &image,
                                  kpDocumentSaveOptions &saveOptions,
                                  kpDocumentMetaInfo &metaInfo)
66
{
67 68
  saveOptions.setColorDepth(image.depth());
  saveOptions.setDither(false);  // avoid double dithering when saving
69

70 71 72
  metaInfo.setDotsPerMeterX(image.dotsPerMeterX());
  metaInfo.setDotsPerMeterY(image.dotsPerMeterY());
  metaInfo.setOffset(image.offset());
73

74 75 76
  QStringList keys = image.textKeys();
  for (int i = 0; i < keys.count(); i++)
    metaInfo.setText(keys[i], image.text(keys[i]));
77 78
}

79
//---------------------------------------------------------------------
80 81

// public static
Christoph Feck's avatar
Christoph Feck committed
82
QImage kpDocument::getPixmapFromFile(const QUrl &url, bool suppressDoesntExistDialog,
83 84 85
                                     QWidget *parent,
                                     kpDocumentSaveOptions *saveOptions,
                                     kpDocumentMetaInfo *metaInfo)
86 87
{
#if DEBUG_KP_DOCUMENT
88
    kDebug () << "kpDocument::getPixmapFromFile(" << url << "," << parent << ")";
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
#endif

    if (saveOptions)
        *saveOptions = kpDocumentSaveOptions ();

    if (metaInfo)
        *metaInfo = kpDocumentMetaInfo ();

    QString tempFile;
    if (url.isEmpty () || !KIO::NetAccess::download (url, tempFile, parent))
    {
        if (!suppressDoesntExistDialog)
        {
            // TODO: Use "Cannot" instead of "Could not" in all dialogs in KolourPaint.
            //       Or at least choose one consistently.
            //
            // TODO: Have captions for all dialogs in KolourPaint.
            KMessageBox::sorry (parent,
                                i18n ("Could not open \"%1\".",
108
                                      kpUrlFormatter::PrettyFilename (url)));
109 110
        }

111
        return QImage ();
112 113 114 115 116 117
    }

    QImage image;

    // sync: remember to "KIO::NetAccess::removeTempFile (tempFile)" in all exit paths
    {
118 119 120 121 122 123 124
        QString detectedMimeType;

        KMimeType::Ptr detectedMimeTypePtr = KMimeType::findByUrl (url);
        if(detectedMimeTypePtr &&
            detectedMimeTypePtr != KMimeType::defaultMimeTypePtr ())
        {
            detectedMimeType = detectedMimeTypePtr->name ();
125 126 127 128 129 130 131
        } else {
            detectedMimeTypePtr = KMimeType::findByPath (tempFile);
            if(detectedMimeTypePtr &&
                detectedMimeTypePtr != KMimeType::defaultMimeTypePtr ())
            {
                detectedMimeType = detectedMimeTypePtr->name ();
            }
132 133
        }

134 135 136 137
        if (saveOptions)
            saveOptions->setMimeType (detectedMimeType);

    #if DEBUG_KP_DOCUMENT
138 139 140
        kDebug () << "\ttempFile=" << tempFile;
        kDebug () << "\tmimetype=" << detectedMimeType;
        kDebug () << "\tsrc=" << url.path ();
141 142 143 144 145 146
    #endif

        if (detectedMimeType.isEmpty ())
        {
            KMessageBox::sorry (parent,
                                i18n ("Could not open \"%1\" - unknown mimetype.",
147
                                    kpUrlFormatter::PrettyFilename (url)));
148
            KIO::NetAccess::removeTempFile (tempFile);
149
            return QImage ();
150 151 152
        }


153 154 155 156 157 158 159 160 161 162 163
        // TODO: <detectedMimeType> might be different.
        //       Should we feed it into QImage to solve this problem?
        //
        //       If so, should we have used KMimeType::findByContent()
        //       instead?  Are some image types not detectable by findByContent()
        //       (e.g. image types that are only detected by extension)?
        //
        //       Currently, opening a PNG with a ".jpg" extension does not
        //       work -- QImage and findByUrl() both think it's a JPG based
        //       on the extension, but findByContent() correctly detects
        //       it as a PNG.
164 165 166 167 168 169 170 171 172
        image = QImage (tempFile);
        KIO::NetAccess::removeTempFile (tempFile);
    }

    if (image.isNull ())
    {
        KMessageBox::sorry (parent,
                            i18n ("Could not open \"%1\" - unsupported image format.\n"
                                  "The file may be corrupt.",
173
                                  kpUrlFormatter::PrettyFilename (url)));
174
        return QImage ();
175 176 177
    }

#if DEBUG_KP_DOCUMENT
178 179
    kDebug () << "\tpixmap: depth=" << image.depth ()
                << " hasAlphaChannel=" << image.hasAlphaChannel ()
180 181 182
                << endl;
#endif

183 184
    if ( saveOptions  && metaInfo )
      getDataFromImage(image, *saveOptions, *metaInfo);
185

186 187 188 189 190 191
    // make sure we always have Format_ARGB32_Premultiplied as this is the fastest to draw on
    // and Qt can not draw onto Format_Indexed8 (Qt-4.7)
    if ( image.format() != QImage::Format_ARGB32_Premultiplied )
      image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);

    return image;
192 193
}

194 195
//---------------------------------------------------------------------

Christoph Feck's avatar
Christoph Feck committed
196
void kpDocument::openNew (const QUrl &url)
197 198
{
#if DEBUG_KP_DOCUMENT
199
    kDebug () << "kpDocument::openNew (" << url << ")";
200 201
#endif

202
    m_image->fill(QColor(Qt::white).rgb());
203 204

    setURL (url, false/*not from url*/);
205 206 207 208 209 210
    // TODO: Maybe we should guess the mimetype from "url"'s filename
    //       extension.
    //
    //       That way "kolourpaint doesnotexist.bmp" would automatically
    //       select the BMP file format when the save dialog comes up for
    //       the first time.
211 212 213 214 215 216 217
    *m_saveOptions = kpDocumentSaveOptions ();
    *m_metaInfo = kpDocumentMetaInfo ();
    m_modified = false;

    emit documentOpened ();
}

218 219
//---------------------------------------------------------------------

Christoph Feck's avatar
Christoph Feck committed
220
bool kpDocument::open (const QUrl &url, bool newDocSameNameIfNotExist)
221 222
{
#if DEBUG_KP_DOCUMENT
223
    kDebug () << "kpDocument::open (" << url << ")";
224 225 226 227
#endif

    kpDocumentSaveOptions newSaveOptions;
    kpDocumentMetaInfo newMetaInfo;
228
    QImage newPixmap = kpDocument::getPixmapFromFile (url,
229
        newDocSameNameIfNotExist/*suppress "doesn't exist" dialog*/,
230
        d->environ->dialogParent (),
231 232 233 234 235
        &newSaveOptions,
        &newMetaInfo);

    if (!newPixmap.isNull ())
    {
236 237
        delete m_image;
        m_image = new kpImage (newPixmap);
238 239 240 241 242 243 244 245 246 247 248 249 250 251

        setURL (url, true/*is from url*/);
        *m_saveOptions = newSaveOptions;
        *m_metaInfo = newMetaInfo;
        m_modified = false;

        emit documentOpened ();
        return true;
    }

    if (newDocSameNameIfNotExist)
    {
        if (!url.isEmpty () &&
            // not just a permission error?
252
            !KIO::NetAccess::exists (url, KIO::NetAccess::SourceSide/*open*/, d->environ->dialogParent ()))
253 254 255 256 257
        {
            openNew (url);
        }
        else
        {
Christoph Feck's avatar
Christoph Feck committed
258
            openNew (QUrl ());
259 260 261 262 263 264 265 266 267 268
        }

        return true;
    }
    else
    {
        return false;
    }
}

269
//---------------------------------------------------------------------