1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the gui module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "qplatformdefs.h"
36
#include "qtextcodec.h"
37
#include "qapplication.h"
45
#include "qimagereader.h"
46
#include "qimagewriter.h"
50
// These pixmaps approximate the images in the Windows User Interface Guidelines.
54
static const char * const move_xpm[] = {
59
"X c #FFFFFF", // Windows cursor is traditionally white
62
"X c #000000", // X11 cursor is traditionally black
86
static const char * const copy_xpm[] = {
91
#if defined(Q_WS_WIN) // Windows cursor is traditionally white
92
"aa......................",
93
"aXa.....................",
94
"aXXa....................",
95
"aXXXa...................",
96
"aXXXXa..................",
97
"aXXXXXa.................",
98
"aXXXXXXa................",
99
"aXXXXXXXa...............",
100
"aXXXXXXXXa..............",
101
"aXXXXXXXXXa.............",
102
"aXXXXXXaaaa.............",
103
"aXXXaXXa................",
104
"aXXaaXXa................",
105
"aXa..aXXa...............",
106
"aa...aXXa...............",
107
"a.....aXXa..............",
108
"......aXXa..............",
109
".......aXXa.............",
110
".......aXXa.............",
111
"........aa...aaaaaaaaaaa",
113
"XX......................",
114
"XaX.....................",
115
"XaaX....................",
116
"XaaaX...................",
117
"XaaaaX..................",
118
"XaaaaaX.................",
119
"XaaaaaaX................",
120
"XaaaaaaaX...............",
121
"XaaaaaaaaX..............",
122
"XaaaaaaaaaX.............",
123
"XaaaaaaXXXX.............",
124
"XaaaXaaX................",
125
"XaaXXaaX................",
126
"XaX..XaaX...............",
127
"XX...XaaX...............",
128
"X.....XaaX..............",
129
"......XaaX..............",
130
".......XaaX.............",
131
".......XaaX.............",
132
"........XX...aaaaaaaaaaa",
134
".............aXXXXXXXXXa",
135
".............aXXXXXXXXXa",
136
".............aXXXXaXXXXa",
137
".............aXXXXaXXXXa",
138
".............aXXaaaaaXXa",
139
".............aXXXXaXXXXa",
140
".............aXXXXaXXXXa",
141
".............aXXXXXXXXXa",
142
".............aXXXXXXXXXa",
143
".............aaaaaaaaaaa"};
146
static const char * const link_xpm[] = {
151
#if defined(Q_WS_WIN) // Windows cursor is traditionally white
152
"aa......................",
153
"aXa.....................",
154
"aXXa....................",
155
"aXXXa...................",
156
"aXXXXa..................",
157
"aXXXXXa.................",
158
"aXXXXXXa................",
159
"aXXXXXXXa...............",
160
"aXXXXXXXXa..............",
161
"aXXXXXXXXXa.............",
162
"aXXXXXXaaaa.............",
163
"aXXXaXXa................",
164
"aXXaaXXa................",
165
"aXa..aXXa...............",
166
"aa...aXXa...............",
167
"a.....aXXa..............",
168
"......aXXa..............",
169
".......aXXa.............",
170
".......aXXa.............",
171
"........aa...aaaaaaaaaaa",
173
"XX......................",
174
"XaX.....................",
175
"XaaX....................",
176
"XaaaX...................",
177
"XaaaaX..................",
178
"XaaaaaX.................",
179
"XaaaaaaX................",
180
"XaaaaaaaX...............",
181
"XaaaaaaaaX..............",
182
"XaaaaaaaaaX.............",
183
"XaaaaaaXXXX.............",
184
"XaaaXaaX................",
185
"XaaXXaaX................",
186
"XaX..XaaX...............",
187
"XX...XaaX...............",
188
"X.....XaaX..............",
189
"......XaaX..............",
190
".......XaaX.............",
191
".......XaaX.............",
192
"........XX...aaaaaaaaaaa",
194
".............aXXXXXXXXXa",
195
".............aXXXaaaaXXa",
196
".............aXXXXaaaXXa",
197
".............aXXXaaaaXXa",
198
".............aXXaaaXaXXa",
199
".............aXXaaXXXXXa",
200
".............aXXaXXXXXXa",
201
".............aXXXaXXXXXa",
202
".............aXXXXXXXXXa",
203
".............aaaaaaaaaaa"};
205
#ifndef QT_NO_DRAGANDDROP
210
QString dragActionsToString(Qt::DropActions actions)
213
if (actions == Qt::IgnoreAction) {
216
str += "IgnoreAction";
218
if (actions & Qt::LinkAction) {
223
if (actions & Qt::CopyAction) {
228
if (actions & Qt::MoveAction) {
233
if ((actions & Qt::TargetMoveAction) == Qt::TargetMoveAction ) {
236
str += "TargetMoveAction";
241
QString KeyboardModifiersToString(Qt::KeyboardModifiers moderfies)
244
if (moderfies & Qt::ControlModifier) {
247
str += Qt::ControlModifier;
249
if (moderfies & Qt::AltModifier) {
252
str += Qt::AltModifier;
254
if (moderfies & Qt::ShiftModifier) {
257
str += Qt::ShiftModifier;
264
// the universe's only drag manager
265
QDragManager *QDragManager::instance = 0;
268
QDragManager::QDragManager()
273
pm_cursor = new QPixmap[n_cursor];
274
pm_cursor[0] = QPixmap((const char **)move_xpm);
275
pm_cursor[1] = QPixmap((const char **)copy_xpm);
276
pm_cursor[2] = QPixmap((const char **)link_xpm);
278
beingCancelled = false;
279
restoreCursor = false;
282
dropData = new QDropData();
286
QDragManager::~QDragManager()
290
QApplication::restoreOverrideCursor();
297
QDragManager *QDragManager::self()
299
if (!instance && qApp && !qApp->closingDown())
300
instance = new QDragManager;
304
QPixmap QDragManager::dragCursor(Qt::DropAction action) const
306
QDragPrivate * d = dragPrivate();
307
if (d && d->customCursors.contains(action))
308
return d->customCursors[action];
309
else if (action == Qt::MoveAction)
311
else if (action == Qt::CopyAction)
313
else if (action == Qt::LinkAction)
318
bool QDragManager::hasCustomDragCursors() const
320
QDragPrivate * d = dragPrivate();
321
return d && !d->customCursors.isEmpty();
324
Qt::DropAction QDragManager::defaultAction(Qt::DropActions possibleActions,
325
Qt::KeyboardModifiers modifiers) const
327
Qt::DropAction defaultAction = Qt::CopyAction;
330
qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)");
331
qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1());
335
if (modifiers & Qt::ControlModifier && modifiers & Qt::AltModifier)
336
defaultAction = Qt::LinkAction;
337
else if (modifiers & Qt::AltModifier)
338
defaultAction = Qt::CopyAction;
340
defaultAction = Qt::MoveAction;
342
if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier)
343
defaultAction = Qt::LinkAction;
344
else if (modifiers & Qt::ControlModifier)
345
defaultAction = Qt::CopyAction;
346
else if (modifiers & Qt::ShiftModifier)
347
defaultAction = Qt::MoveAction;
348
else if (modifiers & Qt::AltModifier)
349
defaultAction = Qt::LinkAction;
352
// if the object is set take the list of possibles from it
354
possibleActions = object->d_func()->possible_actions;
357
qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1());
360
// Check if the action determined is allowed
361
if (!(possibleActions & defaultAction))
362
defaultAction = Qt::CopyAction;
365
qDebug("default action : %s", dragActionsToString(defaultAction).latin1());
368
return defaultAction;
373
static QStringList imageReadMimeFormats()
376
QList<QByteArray> imageFormats = QImageReader::supportedImageFormats();
377
for (int i = 0; i < imageFormats.size(); ++i) {
378
QString format = QLatin1String("image/");
379
format += QString::fromLatin1(imageFormats.at(i).toLower());
380
formats.append(format);
383
//put png at the front because it is best
384
int pngIndex = formats.indexOf(QLatin1String("image/png"));
385
if (pngIndex != -1 && pngIndex != 0)
386
formats.move(pngIndex, 0);
392
static QStringList imageWriteMimeFormats()
395
QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
396
for (int i = 0; i < imageFormats.size(); ++i) {
397
QString format = QLatin1String("image/");
398
format += QString::fromLatin1(imageFormats.at(i).toLower());
399
formats.append(format);
402
//put png at the front because it is best
403
int pngIndex = formats.indexOf(QLatin1String("image/png"));
404
if (pngIndex != -1 && pngIndex != 0)
405
formats.move(pngIndex, 0);
410
QInternalMimeData::QInternalMimeData()
415
QInternalMimeData::~QInternalMimeData()
419
bool QInternalMimeData::hasFormat(const QString &mimeType) const
421
bool foundFormat = hasFormat_sys(mimeType);
422
if (!foundFormat && mimeType == QLatin1String("application/x-qt-image")) {
423
QStringList imageFormats = imageReadMimeFormats();
424
for (int i = 0; i < imageFormats.size(); ++i) {
425
if ((foundFormat = hasFormat_sys(imageFormats.at(i))))
432
QStringList QInternalMimeData::formats() const
434
QStringList realFormats = formats_sys();
435
if (!realFormats.contains(QLatin1String("application/x-qt-image"))) {
436
QStringList imageFormats = imageReadMimeFormats();
437
for (int i = 0; i < imageFormats.size(); ++i) {
438
if (realFormats.contains(imageFormats.at(i))) {
439
realFormats += QLatin1String("application/x-qt-image");
447
QVariant QInternalMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
449
QVariant data = retrieveData_sys(mimeType, type);
450
if (mimeType == QLatin1String("application/x-qt-image")) {
451
if (data.isNull() || (data.type() == QVariant::ByteArray && data.toByteArray().isEmpty())) {
452
// try to find an image
453
QStringList imageFormats = imageReadMimeFormats();
454
for (int i = 0; i < imageFormats.size(); ++i) {
455
data = retrieveData_sys(imageFormats.at(i), type);
456
if (data.isNull() || (data.type() == QVariant::ByteArray && data.toByteArray().isEmpty()))
461
// we wanted some image type, but all we got was a byte array. Convert it to an image.
462
if (data.type() == QVariant::ByteArray
463
&& (type == QVariant::Image || type == QVariant::Pixmap || type == QVariant::Bitmap))
464
data = QImage::fromData(data.toByteArray());
466
} else if (mimeType == QLatin1String("application/x-color") && data.type() == QVariant::ByteArray) {
468
QByteArray ba = data.toByteArray();
469
if (ba.size() == 8) {
470
ushort * colBuf = (ushort *)ba.data();
471
c.setRgbF(qreal(colBuf[0]) / qreal(0xFFFF),
472
qreal(colBuf[1]) / qreal(0xFFFF),
473
qreal(colBuf[2]) / qreal(0xFFFF),
474
qreal(colBuf[3]) / qreal(0xFFFF));
477
qWarning("Invalid color format");
479
} else if (data.type() != type && data.type() == QVariant::ByteArray) {
480
// try to use mime data's internal conversion stuf.
481
QInternalMimeData *that = const_cast<QInternalMimeData *>(this);
482
that->setData(mimeType, data.toByteArray());
483
data = QMimeData::retrieveData(mimeType, type);
489
bool QInternalMimeData::canReadData(const QString &mimeType)
491
return imageReadMimeFormats().contains(mimeType);
494
// helper functions for rendering mimedata to the system, this is needed because QMimeData is in core.
495
QStringList QInternalMimeData::formatsHelper(const QMimeData *data)
497
QStringList realFormats = data->formats();
498
if (realFormats.contains(QLatin1String("application/x-qt-image"))) {
499
// add all supported image formats
500
QStringList imageFormats = imageWriteMimeFormats();
501
for (int i = 0; i < imageFormats.size(); ++i) {
502
if (!realFormats.contains(imageFormats.at(i)))
503
realFormats.append(imageFormats.at(i));
509
bool QInternalMimeData::hasFormatHelper(const QString &mimeType, const QMimeData *data)
512
bool foundFormat = data->hasFormat(mimeType);
514
if (mimeType == QLatin1String("application/x-qt-image")) {
515
// check all supported image formats
516
QStringList imageFormats = imageWriteMimeFormats();
517
for (int i = 0; i < imageFormats.size(); ++i) {
518
if ((foundFormat = data->hasFormat(imageFormats.at(i))))
521
} else if (mimeType.startsWith(QLatin1String("image/"))) {
522
return data->hasImage() && imageWriteMimeFormats().contains(mimeType);
528
QByteArray QInternalMimeData::renderDataHelper(const QString &mimeType, const QMimeData *data)
531
if (mimeType == QLatin1String("application/x-color")) {
532
/* QMimeData can only provide colors as QColor or the name
533
of a color as a QByteArray or a QString. So we need to do
534
the conversion to application/x-color here.
535
The application/x-color format is :
536
type: application/x-color
544
ushort * colBuf = (ushort *)ba.data();
545
QColor c = qvariant_cast<QColor>(data->colorData());
546
colBuf[0] = ushort(c.redF() * 0xFFFF);
547
colBuf[1] = ushort(c.greenF() * 0xFFFF);
548
colBuf[2] = ushort(c.blueF() * 0xFFFF);
549
colBuf[3] = ushort(c.alphaF() * 0xFFFF);
551
ba = data->data(mimeType);
553
if (mimeType == QLatin1String("application/x-qt-image") && data->hasImage()) {
554
QImage image = qvariant_cast<QImage>(data->imageData());
556
buf.open(QBuffer::WriteOnly);
557
// would there not be PNG ??
558
image.save(&buf, "PNG");
559
} else if (mimeType.startsWith(QLatin1String("image/")) && data->hasImage()) {
560
QImage image = qvariant_cast<QImage>(data->imageData());
562
buf.open(QBuffer::WriteOnly);
563
image.save(&buf, mimeType.mid(mimeType.indexOf('/') + 1).toLatin1().toUpper());
570
QDropData::QDropData()
571
: QInternalMimeData()
575
QDropData::~QDropData()