krita/ui

kis_clipboard.cc

Go to the documentation of this file.
00001 /*
00002  *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "kis_clipboard.h"
00020 
00021 #include <QApplication>
00022 #include <QClipboard>
00023 #include <QMimeData>
00024 #include <QObject>
00025 #include <QImage>
00026 #include <QMessageBox>
00027 #include <QBuffer>
00028 
00029 #include <klocale.h>
00030 #include <kglobal.h>
00031 
00032 #include "KoColorSpace.h"
00033 #include "KoStore.h"
00034 #include <KoColorSpaceRegistry.h>
00035 #include <colorprofiles/KoIccColorProfile.h>
00036 
00037 // kritaimage
00038 #include <kis_types.h>
00039 #include <kis_paint_device.h>
00040 #include <kis_debug.h>
00041 #include <kis_annotation.h>
00042 
00043 // local
00044 #include "kis_factory2.h"
00045 #include "kis_config.h"
00046 
00047 KisClipboard::KisClipboard()
00048 {
00049     m_pushedClipboard = false;
00050     m_hasClip = false;
00051     m_clip = 0;
00052 
00053     // Check that we don't already have a clip ready
00054     clipboardDataChanged();
00055 
00056     // Make sure we are notified when clipboard changes
00057     connect(QApplication::clipboard(), SIGNAL(dataChanged()),
00058             this, SLOT(clipboardDataChanged()));
00059 
00060 
00061 }
00062 
00063 KisClipboard::~KisClipboard()
00064 {
00065     dbgRegistry << "deleting KisClipBoard";
00066 }
00067 
00068 KisClipboard* KisClipboard::instance()
00069 {
00070     K_GLOBAL_STATIC(KisClipboard, s_instance);
00071     qAddPostRoutine(s_instance.destroy); // make sure we get destroyed first.
00072     return s_instance;
00073 }
00074 
00075 void KisClipboard::setClip(KisPaintDeviceSP selection)
00076 {
00077     m_clip = selection;
00078 
00079     if (!selection)
00080         return;
00081 
00082     m_hasClip = true;
00083 
00084     // We'll create a store (ZIP format) in memory
00085     QBuffer buffer;
00086     QByteArray mimeType("application/x-krita-selection");
00087     KoStore* store = KoStore::createStore(&buffer, KoStore::Write, mimeType);
00088     Q_ASSERT(store);
00089     Q_ASSERT(!store->bad());
00090 
00091     // Layer data
00092     if (store->open("layerdata")) {
00093         if (!selection->write(store)) {
00094             selection->disconnect();
00095             store->close();
00096             return;
00097         }
00098         store->close();
00099     }
00100 
00101     // ColorSpace id of layer data
00102     if (store->open("colorspace")) {
00103         QString csName = selection->colorSpace()->id();
00104         store->write(csName.toAscii(), strlen(csName.toAscii()));
00105         store->close();
00106     }
00107 
00108     if (selection->colorSpace()->profile()) {
00109         const KoColorProfile *profile = selection->colorSpace()->profile();
00110         KisAnnotationSP annotation;
00111         if (profile) {
00112             const KoIccColorProfile* iccprofile = dynamic_cast<const KoIccColorProfile*>(profile);
00113             if (iccprofile && !iccprofile->rawData().isEmpty())
00114                 annotation = new  KisAnnotation("icc", iccprofile->name(), iccprofile->rawData());
00115         }
00116         if (annotation) {
00117             // save layer profile
00118             if (store->open("profile.icc")) {
00119                 store->write(annotation->annotation());
00120                 store->close();
00121             }
00122         }
00123     }
00124 
00125     delete store;
00126 
00127     // We also create a QImage so we can interchange with other applications
00128     QImage qimg;
00129     KisConfig cfg;
00130     QString monitorProfileName = cfg.monitorProfile();
00131     const KoColorProfile *  monitorProfile = KoColorSpaceRegistry::instance()->profileByName(monitorProfileName);
00132     qimg = selection->convertToQImage(monitorProfile);
00133 
00134     QMimeData *mimeData = new QMimeData;
00135     Q_CHECK_PTR(mimeData);
00136 
00137     if (mimeData) {
00138         if (!qimg.isNull()) {
00139             mimeData->setImageData(qimg);
00140         }
00141 
00142         mimeData->setData(mimeType, buffer.buffer());
00143 
00144         m_pushedClipboard = true;
00145         QClipboard *cb = QApplication::clipboard();
00146         cb->setMimeData(mimeData);
00147     }
00148 }
00149 
00150 KisPaintDeviceSP KisClipboard::clip()
00151 {
00152     QClipboard *cb = QApplication::clipboard();
00153     QByteArray mimeType("application/x-krita-selection");
00154     const QMimeData *cbData = cb->mimeData();
00155 
00156     if (cbData && cbData->hasFormat(mimeType)) {
00157         QByteArray encodedData = cbData->data(mimeType);
00158         QBuffer buffer(&encodedData);
00159         KoStore* store = KoStore::createStore(&buffer, KoStore::Read, mimeType);
00160         KoColorProfile *profile = 0;
00161 
00162         if (store->hasFile("profile.icc")) {
00163             QByteArray data;
00164             store->open("profile.icc");
00165             data = store->read(store->size());
00166             store->close();
00167             profile = new KoIccColorProfile(data);
00168         }
00169 
00170         QString csName;
00171         // ColorSpace id of layer data
00172         if (store->hasFile("colorspace")) {
00173             store->open("colorspace");
00174             csName = QString(store->read(store->size()));
00175             store->close();
00176         }
00177 
00178         const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(csName, profile);
00179 
00180         m_clip = new KisPaintDevice(cs);
00181 
00182         if (store->hasFile("layerdata")) {
00183             store->open("layerdata");
00184             m_clip->read(store);
00185             store->close();
00186         }
00187         delete store;
00188     } else {
00189         QImage qimg = cb->image();
00190 
00191         if (qimg.isNull())
00192             return KisPaintDeviceSP(0);
00193 
00194         KisConfig cfg;
00195 
00196         quint32 behaviour = cfg.pasteBehaviour();
00197 
00198         if (behaviour == PASTE_ASK) {
00199             // Ask user each time
00200             behaviour = QMessageBox::question(0, i18n("Pasting data from simple source"), i18n("The image data you are trying to paste has no color profile information.\n\nOn the web and in simple applications the data are supposed to be in sRGB color format.\nImporting as web will show it as it is supposed to look.\nMost monitors are not perfect though so if you made the image yourself\nyou might want to import it as it looked on you monitor.\n\nHow do you want to interpret these data?"), i18n("As &Web"), i18n("As on &Monitor"));
00201         }
00202 
00203         const KoColorSpace * cs;
00204         QString profileName("");
00205         if (behaviour == PASTE_ASSUME_MONITOR)
00206             profileName = cfg.monitorProfile();
00207 
00208         cs = KoColorSpaceRegistry::instance() ->colorSpace("RGBA", profileName);
00209         if (!cs) {
00210             cs = KoColorSpaceRegistry::instance()->rgb8();
00211             profileName = cs->profile()->name();
00212         }
00213 
00214         m_clip = new KisPaintDevice(cs);
00215         Q_CHECK_PTR(m_clip);
00216         m_clip->convertFromQImage(qimg, profileName);
00217     }
00218 
00219     return m_clip;
00220 }
00221 
00222 void KisClipboard::clipboardDataChanged()
00223 {
00224     if (!m_pushedClipboard) {
00225         m_hasClip = false;
00226         QClipboard *cb = QApplication::clipboard();
00227         QImage qimg = cb->image();
00228         const QMimeData *cbData = cb->mimeData();
00229         QByteArray mimeType("application/x-krita-selection");
00230 
00231         if (cbData && cbData->hasFormat(mimeType))
00232             m_hasClip = true;
00233 
00234         if (!qimg.isNull())
00235             m_hasClip = true;
00236     }
00237 
00238     m_pushedClipboard = false;
00239 }
00240 
00241 
00242 bool KisClipboard::hasClip()
00243 {
00244     return m_hasClip;
00245 }
00246 
00247 QSize KisClipboard::clipSize()
00248 {
00249 
00250     QClipboard *cb = QApplication::clipboard();
00251     QByteArray mimeType("application/x-krita-selection");
00252     const QMimeData *cbData = cb->mimeData();
00253 
00254     KisPaintDeviceSP clip;
00255 
00256     if (cbData && cbData->hasFormat(mimeType)) {
00257         QByteArray encodedData = cbData->data(mimeType);
00258         QBuffer buffer(&encodedData);
00259         KoStore* store = KoStore::createStore(&buffer, KoStore::Read, mimeType);
00260         KoColorProfile *profile = 0;
00261 
00262         if (store->hasFile("profile.icc")) {
00263             QByteArray data;
00264             store->open("profile.icc");
00265             data = store->read(store->size());
00266             store->close();
00267             profile = new KoIccColorProfile(data);
00268         }
00269 
00270         QString csName;
00271         // ColorSpace id of layer data
00272         if (store->hasFile("colorspace")) {
00273             store->open("colorspace");
00274             csName = QString(store->read(store->size()));
00275             store->close();
00276         }
00277 
00278         const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(csName, profile);
00279 
00280         clip = new KisPaintDevice(cs);
00281 
00282         if (store->hasFile("layerdata")) {
00283             store->open("layerdata");
00284             clip->read(store);
00285             store->close();
00286         }
00287         delete store;
00288 
00289         return clip->exactBounds().size();
00290     } else {
00291         QImage qimg = cb->image();
00292         return qimg.size();
00293     }
00294 }
00295 
00296 #include "kis_clipboard.moc"