initial import
[vuplus_webkit] / Source / WebCore / platform / qt / ClipboardQt.cpp
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  * Copyright (C) 2010 Sencha, Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
15  *
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.
27  */
28
29 #include "config.h"
30 #include "ClipboardQt.h"
31
32 #include "CachedImage.h"
33 #include "DataTransferItemsQt.h"
34 #include "Document.h"
35 #include "DragData.h"
36 #include "Element.h"
37 #include "FileList.h"
38 #include "Frame.h"
39 #include "HTMLNames.h"
40 #include "HTMLParserIdioms.h"
41 #include "Image.h"
42 #include "IntPoint.h"
43 #include "KURL.h"
44 #include "NotImplemented.h"
45 #include "PlatformString.h"
46 #include "Range.h"
47 #include "RenderImage.h"
48 #include "markup.h"
49 #include <wtf/text/StringHash.h>
50
51 #include <QApplication>
52 #include <QClipboard>
53 #include <QList>
54 #include <QMimeData>
55 #include <QStringList>
56 #include <QTextCodec>
57 #include <QUrl>
58 #include <qdebug.h>
59
60 #define methodDebug() qDebug("ClipboardQt: %s", __FUNCTION__)
61
62 namespace WebCore {
63
64 static bool isTextMimeType(const String& type)
65 {
66     return type == "text/plain" || type.startsWith("text/plain;");
67 }
68
69 static bool isHtmlMimeType(const String& type)
70 {
71     return type == "text/html" || type.startsWith("text/html;");
72 }
73
74 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
75 {
76     return ClipboardQt::create(policy, dragData->platformData(), frame);
77 }
78
79 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, const QMimeData* readableClipboard, Frame* frame)
80     : Clipboard(policy, DragAndDrop)
81     , m_readableData(readableClipboard)
82     , m_writableData(0)
83     , m_frame(frame)
84 {
85     Q_ASSERT(policy == ClipboardReadable || policy == ClipboardTypesReadable);
86 }
87
88 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, ClipboardType clipboardType, Frame* frame)
89     : Clipboard(policy, clipboardType)
90     , m_readableData(0)
91     , m_writableData(0)
92     , m_frame(frame)
93 {
94     Q_ASSERT(policy == ClipboardReadable || policy == ClipboardWritable || policy == ClipboardNumb);
95
96 #ifndef QT_NO_CLIPBOARD
97     if (policy != ClipboardWritable) {
98         Q_ASSERT(isForCopyAndPaste());
99         m_readableData = QApplication::clipboard()->mimeData();
100     }
101 #endif
102 }
103
104 ClipboardQt::~ClipboardQt()
105 {
106     if (m_writableData && isForCopyAndPaste())
107         m_writableData = 0;
108     else
109         delete m_writableData;
110     m_readableData = 0;
111 }
112
113 void ClipboardQt::clearData(const String& type)
114 {
115     if (policy() != ClipboardWritable)
116         return;
117
118     if (m_writableData) {
119         m_writableData->removeFormat(type);
120         if (m_writableData->formats().isEmpty()) {
121             if (isForDragAndDrop())
122                 delete m_writableData;
123             m_writableData = 0;
124         }
125     }
126 #ifndef QT_NO_CLIPBOARD
127     if (isForCopyAndPaste())
128         QApplication::clipboard()->setMimeData(m_writableData);
129 #endif
130 }
131
132 void ClipboardQt::clearAllData()
133 {
134     if (policy() != ClipboardWritable)
135         return;
136
137 #ifndef QT_NO_CLIPBOARD
138     if (isForCopyAndPaste())
139         QApplication::clipboard()->setMimeData(0);
140     else
141 #endif
142         delete m_writableData;
143     m_writableData = 0;
144 }
145
146 String ClipboardQt::getData(const String& type, bool& success) const
147 {
148
149     if (policy() != ClipboardReadable) {
150         success = false;
151         return String();
152     }
153
154     if (isHtmlMimeType(type) && m_readableData->hasHtml()) {
155         success = true;
156         return m_readableData->html();
157     }
158
159     if (isTextMimeType(type) && m_readableData->hasText()) {
160         success = true;
161         return m_readableData->text();
162     }
163
164     ASSERT(m_readableData);
165     QByteArray rawData = m_readableData->data(type);
166     QString data = QTextCodec::codecForName("UTF-16")->toUnicode(rawData);
167     success = !data.isEmpty();
168     return data;
169 }
170
171 bool ClipboardQt::setData(const String& type, const String& data)
172 {
173     if (policy() != ClipboardWritable)
174         return false;
175
176     if (!m_writableData)
177         m_writableData = new QMimeData;
178
179     if (isTextMimeType(type))
180         m_writableData->setText(QString(data));
181     else if (isHtmlMimeType(type))
182         m_writableData->setHtml(QString(data));
183     else {
184         QByteArray array(reinterpret_cast<const char*>(data.characters()), data.length() * 2);
185         m_writableData->setData(QString(type), array);
186     }
187
188 #ifndef QT_NO_CLIPBOARD
189     if (isForCopyAndPaste())
190         QApplication::clipboard()->setMimeData(m_writableData);
191 #endif
192     return true;
193 }
194
195 // extensions beyond IE's API
196 HashSet<String> ClipboardQt::types() const
197 {
198     if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
199         return HashSet<String>();
200
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));
206     return result;
207 }
208
209 PassRefPtr<FileList> ClipboardQt::files() const
210 {
211     if (policy() != ClipboardReadable || !m_readableData->hasUrls())
212         return FileList::create();
213
214     RefPtr<FileList> fileList = FileList::create();
215     QList<QUrl> urls = m_readableData->urls();
216
217     for (int i = 0; i < urls.size(); i++) {
218         QUrl url = urls[i];
219         if (url.scheme() != QLatin1String("file"))
220             continue;
221         fileList->append(File::create(url.toLocalFile()));
222     }
223
224     return fileList.release();
225 }
226
227 void ClipboardQt::setDragImage(CachedImage* image, const IntPoint& point)
228 {
229     setDragImage(image, 0, point);
230 }
231
232 void ClipboardQt::setDragImageElement(Node* node, const IntPoint& point)
233 {
234     setDragImage(0, node, point);
235 }
236
237 void ClipboardQt::setDragImage(CachedImage* image, Node *node, const IntPoint &loc)
238 {
239     if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
240         return;
241
242     if (m_dragImage)
243         m_dragImage->removeClient(this);
244     m_dragImage = image;
245     if (m_dragImage)
246         m_dragImage->addClient(this);
247
248     m_dragLoc = loc;
249     m_dragImageElement = node;
250 }
251
252 DragImageRef ClipboardQt::createDragImage(IntPoint& dragLoc) const
253 {
254     if (!m_dragImage)
255         return 0;
256     dragLoc = m_dragLoc;
257     return m_dragImage->image()->nativeImageForCurrentFrame();
258 }
259
260
261 static CachedImage* getCachedImage(Element* element)
262 {
263     // Attempt to pull CachedImage from element
264     ASSERT(element);
265     RenderObject* renderer = element->renderer();
266     if (!renderer || !renderer->isImage())
267         return 0;
268
269     RenderImage* image = toRenderImage(renderer);
270     if (image->cachedImage() && !image->cachedImage()->errorOccurred())
271         return image->cachedImage();
272
273     return 0;
274 }
275
276 void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
277 {
278     ASSERT(frame);
279
280     // WebCore::writeURL(m_writableDataObject.get(), url, title, true, false);
281     if (!m_writableData)
282         m_writableData = new QMimeData;
283
284     CachedImage* cachedImage = getCachedImage(element);
285     if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
286         return;
287     QPixmap* pixmap = cachedImage->image()->nativeImageForCurrentFrame();
288     if (pixmap)
289         m_writableData->setImageData(*pixmap);
290
291     QList<QUrl> urls;
292     urls.append(url);
293
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);
300 #endif
301 }
302
303 void ClipboardQt::writeURL(const KURL& url, const String& title, Frame* frame)
304 {
305     ASSERT(frame);
306
307     QList<QUrl> urls;
308     urls.append(frame->document()->completeURL(url.string()));
309     if (!m_writableData)
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);
316 #endif
317 }
318
319 void ClipboardQt::writeRange(Range* range, Frame* frame)
320 {
321     ASSERT(range);
322     ASSERT(frame);
323
324     if (!m_writableData)
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);
333 #endif
334 }
335
336 void ClipboardQt::writePlainText(const String& str)
337 {
338     if (!m_writableData)
339         m_writableData = new QMimeData;
340     QString text = str;
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);
346 #endif
347 }
348
349 bool ClipboardQt::hasData()
350 {
351     const QMimeData *data = m_readableData ? m_readableData : m_writableData;
352     if (!data)
353         return false;
354     return data->formats().count() > 0;
355 }
356
357 #if ENABLE(DATA_TRANSFER_ITEMS)
358 PassRefPtr<DataTransferItems> ClipboardQt::items()
359 {
360
361     if (!m_frame && !m_frame->document())
362         return 0;
363
364     RefPtr<DataTransferItemsQt> items = DataTransferItemsQt::create(this, m_frame->document()->scriptExecutionContext());
365
366     if (!m_readableData)
367         return items;
368
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));
373     }
374     return items;
375 }
376 #endif
377
378 }