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