1 /* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "config.h" 29 #include "ClipboardQt.h" 30 31 #include "CachedImage.h" 32 #include "CSSHelper.h" 33 #include "Document.h" 34 #include "Element.h" 35 #include "FileList.h" 36 #include "Frame.h" 37 #include "HTMLNames.h" 38 #include "Image.h" 39 #include "IntPoint.h" 40 #include "KURL.h" 41 #include "markup.h" 42 #include "NotImplemented.h" 43 #include "PlatformString.h" 44 #include "Range.h" 45 #include "RenderImage.h" 46 #include "StringHash.h" 47 48 #include <QList> 49 #include <QMimeData> 50 #include <QStringList> 51 #include <QUrl> 52 #include <QApplication> 53 #include <QClipboard> 54 #include <qdebug.h> 55 56 #define methodDebug() qDebug("ClipboardQt: %s", __FUNCTION__) 57 58 namespace WebCore { 59 60 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, const QMimeData* readableClipboard) 61 : Clipboard(policy, true) 62 , m_readableData(readableClipboard) 63 , m_writableData(0) 64 { 65 Q_ASSERT(policy == ClipboardReadable || policy == ClipboardTypesReadable); 66 } 67 68 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, bool forDragging) 69 : Clipboard(policy, forDragging) 70 , m_readableData(0) 71 , m_writableData(0) 72 { 73 Q_ASSERT(policy == ClipboardReadable || policy == ClipboardWritable || policy == ClipboardNumb); 74 75 #ifndef QT_NO_CLIPBOARD 76 if (policy != ClipboardWritable) { 77 Q_ASSERT(!forDragging); 78 m_readableData = QApplication::clipboard()->mimeData(); 79 } 80 #endif 81 } 82 83 ClipboardQt::~ClipboardQt() 84 { 85 if (m_writableData && !isForDragging()) 86 m_writableData = 0; 87 else 88 delete m_writableData; 89 m_readableData = 0; 90 } 91 92 void ClipboardQt::clearData(const String& type) 93 { 94 if (policy() != ClipboardWritable) 95 return; 96 97 if (m_writableData) { 98 m_writableData->removeFormat(type); 99 if (m_writableData->formats().isEmpty()) { 100 if (isForDragging()) 101 delete m_writableData; 102 m_writableData = 0; 103 } 104 } 105 #ifndef QT_NO_CLIPBOARD 106 if (!isForDragging()) 107 QApplication::clipboard()->setMimeData(m_writableData); 108 #endif 109 } 110 111 void ClipboardQt::clearAllData() 112 { 113 if (policy() != ClipboardWritable) 114 return; 115 116 #ifndef QT_NO_CLIPBOARD 117 if (!isForDragging()) 118 QApplication::clipboard()->setMimeData(0); 119 else 120 #endif 121 delete m_writableData; 122 m_writableData = 0; 123 } 124 125 String ClipboardQt::getData(const String& type, bool& success) const 126 { 127 128 if (policy() != ClipboardReadable) { 129 success = false; 130 return String(); 131 } 132 133 ASSERT(m_readableData); 134 QByteArray data = m_readableData->data(QString(type)); 135 success = !data.isEmpty(); 136 return String(data.data(), data.size()); 137 } 138 139 bool ClipboardQt::setData(const String& type, const String& data) 140 { 141 if (policy() != ClipboardWritable) 142 return false; 143 144 if (!m_writableData) 145 m_writableData = new QMimeData; 146 QByteArray array(reinterpret_cast<const char*>(data.characters()), 147 data.length()*2); 148 m_writableData->setData(QString(type), array); 149 #ifndef QT_NO_CLIPBOARD 150 if (!isForDragging()) 151 QApplication::clipboard()->setMimeData(m_writableData); 152 #endif 153 return true; 154 } 155 156 // extensions beyond IE's API 157 HashSet<String> ClipboardQt::types() const 158 { 159 if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) 160 return HashSet<String>(); 161 162 ASSERT(m_readableData); 163 HashSet<String> result; 164 QStringList formats = m_readableData->formats(); 165 for (int i = 0; i < formats.count(); ++i) 166 result.add(formats.at(i)); 167 return result; 168 } 169 170 PassRefPtr<FileList> ClipboardQt::files() const 171 { 172 notImplemented(); 173 return 0; 174 } 175 176 void ClipboardQt::setDragImage(CachedImage* image, const IntPoint& point) 177 { 178 setDragImage(image, 0, point); 179 } 180 181 void ClipboardQt::setDragImageElement(Node* node, const IntPoint& point) 182 { 183 setDragImage(0, node, point); 184 } 185 186 void ClipboardQt::setDragImage(CachedImage* image, Node *node, const IntPoint &loc) 187 { 188 if (policy() != ClipboardImageWritable && policy() != ClipboardWritable) 189 return; 190 191 if (m_dragImage) 192 m_dragImage->removeClient(this); 193 m_dragImage = image; 194 if (m_dragImage) 195 m_dragImage->addClient(this); 196 197 m_dragLoc = loc; 198 m_dragImageElement = node; 199 } 200 201 DragImageRef ClipboardQt::createDragImage(IntPoint& dragLoc) const 202 { 203 if (!m_dragImage) 204 return 0; 205 dragLoc = m_dragLoc; 206 return m_dragImage->image()->nativeImageForCurrentFrame(); 207 } 208 209 210 static CachedImage* getCachedImage(Element* element) 211 { 212 // Attempt to pull CachedImage from element 213 ASSERT(element); 214 RenderObject* renderer = element->renderer(); 215 if (!renderer || !renderer->isImage()) 216 return 0; 217 218 RenderImage* image = toRenderImage(renderer); 219 if (image->cachedImage() && !image->cachedImage()->errorOccurred()) 220 return image->cachedImage(); 221 222 return 0; 223 } 224 225 void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame) 226 { 227 ASSERT(frame); 228 229 //WebCore::writeURL(m_writableDataObject.get(), url, title, true, false); 230 if (!m_writableData) 231 m_writableData = new QMimeData; 232 233 CachedImage* cachedImage = getCachedImage(element); 234 if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded()) 235 return; 236 QPixmap *pixmap = cachedImage->image()->nativeImageForCurrentFrame(); 237 if (pixmap) 238 m_writableData->setImageData(*pixmap); 239 240 AtomicString imageURL = element->getAttribute(HTMLNames::srcAttr); 241 if (imageURL.isEmpty()) 242 return; 243 244 KURL fullURL = frame->document()->completeURL(deprecatedParseURL(imageURL)); 245 if (fullURL.isEmpty()) 246 return; 247 248 QList<QUrl> urls; 249 urls.append(url); 250 urls.append(fullURL); 251 252 m_writableData->setText(title); 253 m_writableData->setUrls(urls); 254 #ifndef QT_NO_CLIPBOARD 255 if (!isForDragging()) 256 QApplication::clipboard()->setMimeData(m_writableData); 257 #endif 258 } 259 260 void ClipboardQt::writeURL(const KURL& url, const String& title, Frame* frame) 261 { 262 ASSERT(frame); 263 264 QList<QUrl> urls; 265 urls.append(frame->document()->completeURL(url.string())); 266 if (!m_writableData) 267 m_writableData = new QMimeData; 268 m_writableData->setUrls(urls); 269 m_writableData->setText(title); 270 #ifndef QT_NO_CLIPBOARD 271 if (!isForDragging()) 272 QApplication::clipboard()->setMimeData(m_writableData); 273 #endif 274 } 275 276 void ClipboardQt::writeRange(Range* range, Frame* frame) 277 { 278 ASSERT(range); 279 ASSERT(frame); 280 281 if (!m_writableData) 282 m_writableData = new QMimeData; 283 QString text = frame->selectedText(); 284 text.replace(QChar(0xa0), QLatin1Char(' ')); 285 m_writableData->setText(text); 286 m_writableData->setHtml(createMarkup(range, 0, AnnotateForInterchange)); 287 #ifndef QT_NO_CLIPBOARD 288 if (!isForDragging()) 289 QApplication::clipboard()->setMimeData(m_writableData); 290 #endif 291 } 292 293 void ClipboardQt::writePlainText(const String& str) 294 { 295 if (!m_writableData) 296 m_writableData = new QMimeData; 297 QString text = str; 298 text.replace(QChar(0xa0), QLatin1Char(' ')); 299 m_writableData->setText(text); 300 #ifndef QT_NO_CLIPBOARD 301 if (!isForDragging()) 302 QApplication::clipboard()->setMimeData(m_writableData); 303 #endif 304 } 305 306 bool ClipboardQt::hasData() 307 { 308 const QMimeData *data = m_readableData ? m_readableData : m_writableData; 309 if (!data) 310 return false; 311 return data->formats().count() > 0; 312 } 313 314 } 315