1 /***************************************************************************
2 **
3 ** Copyright (C) 2011 - 2012 Research In Motion
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #if !defined(QT_NO_CLIPBOARD)
41
42 #include "qqnxclipboard.h"
43
44 #include <QtGui/QColor>
45
46 #include <QtCore/QDebug>
47 #include <QtCore/QMimeData>
48 #include <QtCore/QStringList>
49 #include <QtCore/QUrl>
50
51 #include <clipboard/clipboard.h>
52 #include <errno.h>
53
54 #if defined(QQNXCLIPBOARD_DEBUG)
55 #define qClipboardDebug qDebug
56 #else
57 #define qClipboardDebug QT_NO_QDEBUG_MACRO
58 #endif
59
60 QT_BEGIN_NAMESPACE
61
62 // null terminated array
63 static const char *typeList[] = {"text/html", "text/plain", "image/png", "image/jpeg", "application/x-color", 0};
64
readClipboardBuff(const char * type)65 static QByteArray readClipboardBuff(const char *type)
66 {
67 char *pbuffer;
68 if (is_clipboard_format_present(type) == 0) {
69 int size = get_clipboard_data(type, &pbuffer);
70 if (size != -1 && pbuffer) {
71 const QByteArray result = QByteArray(pbuffer, size);
72 free(pbuffer);
73 return result;
74 }
75 }
76
77 return QByteArray();
78 }
79
80 class QQnxClipboard::MimeData : public QMimeData
81 {
82 Q_OBJECT
83 public:
MimeData(QQnxClipboard * clipboard)84 MimeData(QQnxClipboard *clipboard)
85 : QMimeData(),
86 m_clipboard(clipboard),
87 m_userMimeData(0)
88 {
89 Q_ASSERT(clipboard);
90
91 for (int i = 0; typeList[i] != 0; ++i) {
92 m_formatsToCheck << QString::fromUtf8(typeList[i]);
93 }
94 }
95
~MimeData()96 ~MimeData()
97 {
98 delete m_userMimeData;
99 }
100
addFormatToCheck(const QString & format)101 void addFormatToCheck(const QString &format) {
102 m_formatsToCheck << format;
103 qClipboardDebug() << "formats=" << m_formatsToCheck;
104 }
105
hasFormat(const QString & mimetype) const106 bool hasFormat(const QString &mimetype) const override
107 {
108 const bool result = is_clipboard_format_present(mimetype.toUtf8().constData()) == 0;
109 qClipboardDebug() << "mimetype=" << mimetype << "result=" << result;
110 return result;
111 }
112
formats() const113 QStringList formats() const override
114 {
115 QStringList result;
116
117 Q_FOREACH (const QString &format, m_formatsToCheck) {
118 if (is_clipboard_format_present(format.toUtf8().constData()) == 0)
119 result << format;
120 }
121
122 qClipboardDebug() << "result=" << result;
123 return result;
124 }
125
setUserMimeData(QMimeData * userMimeData)126 void setUserMimeData(QMimeData *userMimeData)
127 {
128 delete m_userMimeData;
129 m_userMimeData = userMimeData;
130
131 // system clipboard API doesn't allow detection of changes by other applications
132 // simulate an owner change through delayed invocation
133 // basically transfer ownership of data to the system clipboard once event processing resumes
134 if (m_userMimeData)
135 QMetaObject::invokeMethod(this, "releaseOwnership", Qt::QueuedConnection);
136 }
137
userMimeData()138 QMimeData *userMimeData()
139 {
140 return m_userMimeData;
141 }
142
143 protected:
retrieveData(const QString & mimetype,QVariant::Type preferredType) const144 QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const override
145 {
146 qClipboardDebug() << "mimetype=" << mimetype << "preferredType=" << preferredType;
147 if (is_clipboard_format_present(mimetype.toUtf8().constData()) != 0)
148 return QMimeData::retrieveData(mimetype, preferredType);
149
150 const QByteArray data = readClipboardBuff(mimetype.toUtf8().constData());
151 return QVariant::fromValue(data);
152 }
153
154 private Q_SLOTS:
releaseOwnership()155 void releaseOwnership()
156 {
157 if (m_userMimeData) {
158 qClipboardDebug() << "user data formats=" << m_userMimeData->formats() << "system formats=" << formats();
159 delete m_userMimeData;
160 m_userMimeData = 0;
161 m_clipboard->emitChanged(QClipboard::Clipboard);
162 }
163 }
164
165 private:
166 QQnxClipboard * const m_clipboard;
167
168 QSet<QString> m_formatsToCheck;
169 QMimeData *m_userMimeData;
170 };
171
QQnxClipboard()172 QQnxClipboard::QQnxClipboard()
173 : m_mimeData(new MimeData(this))
174 {
175 }
176
~QQnxClipboard()177 QQnxClipboard::~QQnxClipboard()
178 {
179 delete m_mimeData;
180 }
181
setMimeData(QMimeData * data,QClipboard::Mode mode)182 void QQnxClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
183 {
184 if (mode != QClipboard::Clipboard)
185 return;
186
187 if (m_mimeData == data)
188 return;
189
190 if (m_mimeData->userMimeData() && m_mimeData->userMimeData() == data)
191 return;
192
193 empty_clipboard();
194
195 m_mimeData->clear();
196 m_mimeData->setUserMimeData(data);
197
198 if (data == 0) {
199 emitChanged(QClipboard::Clipboard);
200 return;
201 }
202
203 const QStringList formats = data->formats();
204 qClipboardDebug() << "formats=" << formats;
205
206 Q_FOREACH (const QString &format, formats) {
207 const QByteArray buf = data->data(format);
208
209 if (buf.isEmpty())
210 continue;
211
212 int ret = set_clipboard_data(format.toUtf8().data(), buf.size(), buf.data());
213 qClipboardDebug() << "set " << format << "to clipboard, size=" << buf.size() << ";ret=" << ret;
214 if (ret)
215 m_mimeData->addFormatToCheck(format);
216 }
217
218 emitChanged(QClipboard::Clipboard);
219 }
220
mimeData(QClipboard::Mode mode)221 QMimeData *QQnxClipboard::mimeData(QClipboard::Mode mode)
222 {
223 if (mode != QClipboard::Clipboard)
224 return 0;
225
226 if (m_mimeData->userMimeData())
227 return m_mimeData->userMimeData();
228
229 m_mimeData->clear();
230
231 return m_mimeData;
232 }
233
234 QT_END_NAMESPACE
235
236 #include "qqnxclipboard.moc"
237
238 #endif //QT_NO_CLIPBOARD
239