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 58namespace WebCore { 59 60ClipboardQt::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 68ClipboardQt::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 83ClipboardQt::~ClipboardQt() 84{ 85 if (m_writableData && !isForDragging()) 86 m_writableData = 0; 87 else 88 delete m_writableData; 89 m_readableData = 0; 90} 91 92void 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 111void 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 125String 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 139bool 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 157HashSet<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 170PassRefPtr<FileList> ClipboardQt::files() const 171{ 172 notImplemented(); 173 return 0; 174} 175 176void ClipboardQt::setDragImage(CachedImage* image, const IntPoint& point) 177{ 178 setDragImage(image, 0, point); 179} 180 181void ClipboardQt::setDragImageElement(Node* node, const IntPoint& point) 182{ 183 setDragImage(0, node, point); 184} 185 186void 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 201DragImageRef 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 210static 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 225void 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 260void 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 276void 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 293void 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 306bool 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