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 * Copyright (C) 2010 Sencha, Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "ClipboardQt.h"
32 #include "CachedImage.h"
33 #include "DataTransferItemsQt.h"
39 #include "HTMLNames.h"
40 #include "HTMLParserIdioms.h"
44 #include "NotImplemented.h"
45 #include "PlatformString.h"
47 #include "RenderImage.h"
49 #include <wtf/text/StringHash.h>
51 #include <QApplication>
55 #include <QStringList>
60 #define methodDebug() qDebug("ClipboardQt: %s", __FUNCTION__)
64 static bool isTextMimeType(const String& type)
66 return type == "text/plain" || type.startsWith("text/plain;");
69 static bool isHtmlMimeType(const String& type)
71 return type == "text/html" || type.startsWith("text/html;");
74 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
76 return ClipboardQt::create(policy, dragData->platformData(), frame);
79 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, const QMimeData* readableClipboard, Frame* frame)
80 : Clipboard(policy, DragAndDrop)
81 , m_readableData(readableClipboard)
85 Q_ASSERT(policy == ClipboardReadable || policy == ClipboardTypesReadable);
88 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, ClipboardType clipboardType, Frame* frame)
89 : Clipboard(policy, clipboardType)
94 Q_ASSERT(policy == ClipboardReadable || policy == ClipboardWritable || policy == ClipboardNumb);
96 #ifndef QT_NO_CLIPBOARD
97 if (policy != ClipboardWritable) {
98 Q_ASSERT(isForCopyAndPaste());
99 m_readableData = QApplication::clipboard()->mimeData();
104 ClipboardQt::~ClipboardQt()
106 if (m_writableData && isForCopyAndPaste())
109 delete m_writableData;
113 void ClipboardQt::clearData(const String& type)
115 if (policy() != ClipboardWritable)
118 if (m_writableData) {
119 m_writableData->removeFormat(type);
120 if (m_writableData->formats().isEmpty()) {
121 if (isForDragAndDrop())
122 delete m_writableData;
126 #ifndef QT_NO_CLIPBOARD
127 if (isForCopyAndPaste())
128 QApplication::clipboard()->setMimeData(m_writableData);
132 void ClipboardQt::clearAllData()
134 if (policy() != ClipboardWritable)
137 #ifndef QT_NO_CLIPBOARD
138 if (isForCopyAndPaste())
139 QApplication::clipboard()->setMimeData(0);
142 delete m_writableData;
146 String ClipboardQt::getData(const String& type, bool& success) const
149 if (policy() != ClipboardReadable) {
154 if (isHtmlMimeType(type) && m_readableData->hasHtml()) {
156 return m_readableData->html();
159 if (isTextMimeType(type) && m_readableData->hasText()) {
161 return m_readableData->text();
164 ASSERT(m_readableData);
165 QByteArray rawData = m_readableData->data(type);
166 QString data = QTextCodec::codecForName("UTF-16")->toUnicode(rawData);
167 success = !data.isEmpty();
171 bool ClipboardQt::setData(const String& type, const String& data)
173 if (policy() != ClipboardWritable)
177 m_writableData = new QMimeData;
179 if (isTextMimeType(type))
180 m_writableData->setText(QString(data));
181 else if (isHtmlMimeType(type))
182 m_writableData->setHtml(QString(data));
184 QByteArray array(reinterpret_cast<const char*>(data.characters()), data.length() * 2);
185 m_writableData->setData(QString(type), array);
188 #ifndef QT_NO_CLIPBOARD
189 if (isForCopyAndPaste())
190 QApplication::clipboard()->setMimeData(m_writableData);
195 // extensions beyond IE's API
196 HashSet<String> ClipboardQt::types() const
198 if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
199 return HashSet<String>();
201 ASSERT(m_readableData);
202 HashSet<String> result;
203 QStringList formats = m_readableData->formats();
204 for (int i = 0; i < formats.count(); ++i)
205 result.add(formats.at(i));
209 PassRefPtr<FileList> ClipboardQt::files() const
211 if (policy() != ClipboardReadable || !m_readableData->hasUrls())
212 return FileList::create();
214 RefPtr<FileList> fileList = FileList::create();
215 QList<QUrl> urls = m_readableData->urls();
217 for (int i = 0; i < urls.size(); i++) {
219 if (url.scheme() != QLatin1String("file"))
221 fileList->append(File::create(url.toLocalFile()));
224 return fileList.release();
227 void ClipboardQt::setDragImage(CachedImage* image, const IntPoint& point)
229 setDragImage(image, 0, point);
232 void ClipboardQt::setDragImageElement(Node* node, const IntPoint& point)
234 setDragImage(0, node, point);
237 void ClipboardQt::setDragImage(CachedImage* image, Node *node, const IntPoint &loc)
239 if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
243 m_dragImage->removeClient(this);
246 m_dragImage->addClient(this);
249 m_dragImageElement = node;
252 DragImageRef ClipboardQt::createDragImage(IntPoint& dragLoc) const
257 return m_dragImage->image()->nativeImageForCurrentFrame();
261 static CachedImage* getCachedImage(Element* element)
263 // Attempt to pull CachedImage from element
265 RenderObject* renderer = element->renderer();
266 if (!renderer || !renderer->isImage())
269 RenderImage* image = toRenderImage(renderer);
270 if (image->cachedImage() && !image->cachedImage()->errorOccurred())
271 return image->cachedImage();
276 void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
280 // WebCore::writeURL(m_writableDataObject.get(), url, title, true, false);
282 m_writableData = new QMimeData;
284 CachedImage* cachedImage = getCachedImage(element);
285 if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
287 QPixmap* pixmap = cachedImage->image()->nativeImageForCurrentFrame();
289 m_writableData->setImageData(*pixmap);
294 m_writableData->setText(title);
295 m_writableData->setUrls(urls);
296 m_writableData->setHtml(createMarkup(element, IncludeNode, 0, ResolveAllURLs));
297 #ifndef QT_NO_CLIPBOARD
298 if (isForCopyAndPaste())
299 QApplication::clipboard()->setMimeData(m_writableData);
303 void ClipboardQt::writeURL(const KURL& url, const String& title, Frame* frame)
308 urls.append(frame->document()->completeURL(url.string()));
310 m_writableData = new QMimeData;
311 m_writableData->setUrls(urls);
312 m_writableData->setText(title);
313 #ifndef QT_NO_CLIPBOARD
314 if (isForCopyAndPaste())
315 QApplication::clipboard()->setMimeData(m_writableData);
319 void ClipboardQt::writeRange(Range* range, Frame* frame)
325 m_writableData = new QMimeData;
326 QString text = frame->editor()->selectedText();
327 text.replace(QChar(0xa0), QLatin1Char(' '));
328 m_writableData->setText(text);
329 m_writableData->setHtml(createMarkup(range, 0, AnnotateForInterchange, false, ResolveNonLocalURLs));
330 #ifndef QT_NO_CLIPBOARD
331 if (isForCopyAndPaste())
332 QApplication::clipboard()->setMimeData(m_writableData);
336 void ClipboardQt::writePlainText(const String& str)
339 m_writableData = new QMimeData;
341 text.replace(QChar(0xa0), QLatin1Char(' '));
342 m_writableData->setText(text);
343 #ifndef QT_NO_CLIPBOARD
344 if (isForCopyAndPaste())
345 QApplication::clipboard()->setMimeData(m_writableData);
349 bool ClipboardQt::hasData()
351 const QMimeData *data = m_readableData ? m_readableData : m_writableData;
354 return data->formats().count() > 0;
357 #if ENABLE(DATA_TRANSFER_ITEMS)
358 PassRefPtr<DataTransferItems> ClipboardQt::items()
361 if (!m_frame && !m_frame->document())
364 RefPtr<DataTransferItemsQt> items = DataTransferItemsQt::create(this, m_frame->document()->scriptExecutionContext());
369 if (isForCopyAndPaste() && policy() == ClipboardReadable) {
370 const QStringList types = m_readableData->formats();
371 for (int i = 0; i < types.count(); ++i)
372 items->addPasteboardItem(types.at(i));