1 /*
2 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
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 "Pasteboard.h"
30
31 #include "DocumentFragment.h"
32 #include "Editor.h"
33 #include "Frame.h"
34 #include "Image.h"
35 #include "RenderImage.h"
36 #include "markup.h"
37 #include <qapplication.h>
38 #include <qclipboard.h>
39 #include <qdebug.h>
40 #include <qmimedata.h>
41 #include <qurl.h>
42
43 #define methodDebug() qDebug() << "PasteboardQt: " << __FUNCTION__;
44
45 namespace WebCore {
46
Pasteboard()47 Pasteboard::Pasteboard()
48 : m_selectionMode(false)
49 {
50 }
51
generalPasteboard()52 Pasteboard* Pasteboard::generalPasteboard()
53 {
54 static Pasteboard* pasteboard = 0;
55 if (!pasteboard)
56 pasteboard = new Pasteboard();
57 return pasteboard;
58 }
59
writeSelection(Range * selectedRange,bool canSmartCopyOrDelete,Frame * frame)60 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
61 {
62 QMimeData* md = new QMimeData;
63 QString text = frame->editor()->selectedText();
64 text.replace(QChar(0xa0), QLatin1Char(' '));
65 md->setText(text);
66
67 QString markup = createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs);
68 #ifdef Q_OS_MAC
69 markup.prepend(QLatin1String("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><body>"));
70 markup.append(QLatin1String("</body></html>"));
71 md->setData(QLatin1String("text/html"), markup.toUtf8());
72 #else
73 md->setHtml(markup);
74 #endif
75
76 #ifndef QT_NO_CLIPBOARD
77 QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
78 #endif
79 if (canSmartCopyOrDelete)
80 md->setData(QLatin1String("application/vnd.qtwebkit.smartpaste"), QByteArray());
81 }
82
canSmartReplace()83 bool Pasteboard::canSmartReplace()
84 {
85 #ifndef QT_NO_CLIPBOARD
86 if (QApplication::clipboard()->mimeData()->hasFormat((QLatin1String("application/vnd.qtwebkit.smartpaste"))))
87 return true;
88 #endif
89 return false;
90 }
91
plainText(Frame *)92 String Pasteboard::plainText(Frame*)
93 {
94 #ifndef QT_NO_CLIPBOARD
95 return QApplication::clipboard()->text(m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
96 #else
97 return String();
98 #endif
99 }
100
documentFragment(Frame * frame,PassRefPtr<Range> context,bool allowPlainText,bool & chosePlainText)101 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
102 bool allowPlainText, bool& chosePlainText)
103 {
104 #ifndef QT_NO_CLIPBOARD
105 const QMimeData* mimeData = QApplication::clipboard()->mimeData(
106 m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
107
108 chosePlainText = false;
109
110 if (mimeData->hasHtml()) {
111 QString html = mimeData->html();
112 if (!html.isEmpty()) {
113 RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed);
114 if (fragment)
115 return fragment.release();
116 }
117 }
118
119 if (allowPlainText && mimeData->hasText()) {
120 chosePlainText = true;
121 RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), mimeData->text());
122 if (fragment)
123 return fragment.release();
124 }
125 #endif
126 return 0;
127 }
128
writePlainText(const String & text)129 void Pasteboard::writePlainText(const String& text)
130 {
131 #ifndef QT_NO_CLIPBOARD
132 QMimeData* md = new QMimeData;
133 QString qtext = text;
134 qtext.replace(QChar(0xa0), QLatin1Char(' '));
135 md->setText(qtext);
136 QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
137 #endif
138 }
139
writeURL(const KURL & url,const String &,Frame *)140 void Pasteboard::writeURL(const KURL& url, const String&, Frame*)
141 {
142 ASSERT(!url.isEmpty());
143
144 #ifndef QT_NO_CLIPBOARD
145 QMimeData* md = new QMimeData;
146 QString urlString = url.string();
147 md->setText(urlString);
148 md->setUrls(QList<QUrl>() << url);
149 QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
150 #endif
151 }
152
writeImage(Node * node,const KURL &,const String &)153 void Pasteboard::writeImage(Node* node, const KURL&, const String&)
154 {
155 ASSERT(node && node->renderer() && node->renderer()->isImage());
156
157 #ifndef QT_NO_CLIPBOARD
158 CachedImage* cachedImage = toRenderImage(node->renderer())->cachedImage();
159 if (!cachedImage || cachedImage->errorOccurred())
160 return;
161
162 Image* image = cachedImage->image();
163 ASSERT(image);
164
165 QPixmap* pixmap = image->nativeImageForCurrentFrame();
166 if (!pixmap)
167 return;
168 QApplication::clipboard()->setPixmap(*pixmap, QClipboard::Clipboard);
169 #endif
170 }
171
172 /* This function is called from Editor::tryDHTMLCopy before actually set the clipboard
173 * It introduce a race condition with klipper, which will try to grab the clipboard
174 * It's not required to clear it anyway, since QClipboard take care about replacing the clipboard
175 */
clear()176 void Pasteboard::clear()
177 {
178 }
179
isSelectionMode() const180 bool Pasteboard::isSelectionMode() const
181 {
182 return m_selectionMode;
183 }
184
setSelectionMode(bool selectionMode)185 void Pasteboard::setSelectionMode(bool selectionMode)
186 {
187 m_selectionMode = selectionMode;
188 }
189
190 }
191