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