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  *
      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