source: vendor/trolltech/current/src/kernel/qdragobject.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 43.7 KB
Line 
1/****************************************************************************
2** $Id: qdragobject.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of Drag and Drop support
5**
6** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
7**
8** This file is part of the kernel module of the Qt GUI Toolkit.
9**
10** This file may be distributed under the terms of the Q Public License
11** as defined by Trolltech AS of Norway and appearing in the file
12** LICENSE.QPL included in the packaging of this file.
13**
14** This file may be distributed and/or modified under the terms of the
15** GNU General Public License version 2 as published by the Free Software
16** Foundation and appearing in the file LICENSE.GPL included in the
17** packaging of this file.
18**
19** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
20** licenses may use this file in accordance with the Qt Commercial License
21** Agreement provided with the Software.
22**
23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25**
26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27** information about Qt Commercial License Agreements.
28** See http://www.trolltech.com/qpl/ for QPL licensing information.
29** See http://www.trolltech.com/gpl/ for GPL licensing information.
30**
31** Contact info@trolltech.com if any conditions of this licensing are
32** not clear to you.
33**
34**********************************************************************/
35
36#include "qplatformdefs.h"
37
38// POSIX Large File Support redefines open -> open64
39#if defined(open)
40# undef open
41#endif
42
43#ifndef QT_NO_MIME
44
45#include "qdragobject.h"
46#include "qtextcodec.h"
47#include "qapplication.h"
48#include "qpoint.h"
49#include "qwidget.h"
50#include "qbuffer.h"
51#include "qgif.h"
52#include "qregexp.h"
53#include "qdir.h"
54#include <ctype.h>
55
56// both a struct for storing stuff in and a wrapper to avoid polluting
57// the name space
58
59class QDragObjectData
60{
61public:
62 QDragObjectData(): hot(0,0) {}
63 QPixmap pixmap;
64 QPoint hot;
65 // store default cursors
66 QPixmap *pm_cursor;
67};
68
69static QWidget* last_target;
70
71/*!
72 After the drag completes, this function will return the QWidget
73 which received the drop, or 0 if the data was dropped on another
74 application.
75
76 This can be useful for detecting the case where drag and drop is
77 to and from the same widget.
78*/
79QWidget * QDragObject::target()
80{
81 return last_target;
82}
83
84/*!
85 \internal
86 Sets the target.
87*/
88void QDragObject::setTarget(QWidget* t)
89{
90 last_target = t;
91}
92
93class QStoredDragData
94{
95public:
96 QStoredDragData() {}
97 const char* fmt;
98 QByteArray enc;
99};
100
101
102// These pixmaps approximate the images in the Windows User Interface Guidelines.
103
104// XPM
105
106static const char * const move_xpm[] = {
107"11 20 3 1",
108". c None",
109#if defined(Q_WS_WIN)
110"a c #000000",
111"X c #FFFFFF", // Windows cursor is traditionally white
112#else
113"a c #FFFFFF",
114"X c #000000", // X11 cursor is traditionally black
115#endif
116"aa.........",
117"aXa........",
118"aXXa.......",
119"aXXXa......",
120"aXXXXa.....",
121"aXXXXXa....",
122"aXXXXXXa...",
123"aXXXXXXXa..",
124"aXXXXXXXXa.",
125"aXXXXXXXXXa",
126"aXXXXXXaaaa",
127"aXXXaXXa...",
128"aXXaaXXa...",
129"aXa..aXXa..",
130"aa...aXXa..",
131"a.....aXXa.",
132"......aXXa.",
133".......aXXa",
134".......aXXa",
135"........aa."};
136
137/* XPM */
138static const char * const copy_xpm[] = {
139"24 30 3 1",
140". c None",
141"a c #000000",
142"X c #FFFFFF",
143#if defined(Q_WS_WIN) // Windows cursor is traditionally white
144"aa......................",
145"aXa.....................",
146"aXXa....................",
147"aXXXa...................",
148"aXXXXa..................",
149"aXXXXXa.................",
150"aXXXXXXa................",
151"aXXXXXXXa...............",
152"aXXXXXXXXa..............",
153"aXXXXXXXXXa.............",
154"aXXXXXXaaaa.............",
155"aXXXaXXa................",
156"aXXaaXXa................",
157"aXa..aXXa...............",
158"aa...aXXa...............",
159"a.....aXXa..............",
160"......aXXa..............",
161".......aXXa.............",
162".......aXXa.............",
163"........aa...aaaaaaaaaaa",
164#else
165"XX......................",
166"XaX.....................",
167"XaaX....................",
168"XaaaX...................",
169"XaaaaX..................",
170"XaaaaaX.................",
171"XaaaaaaX................",
172"XaaaaaaaX...............",
173"XaaaaaaaaX..............",
174"XaaaaaaaaaX.............",
175"XaaaaaaXXXX.............",
176"XaaaXaaX................",
177"XaaXXaaX................",
178"XaX..XaaX...............",
179"XX...XaaX...............",
180"X.....XaaX..............",
181"......XaaX..............",
182".......XaaX.............",
183".......XaaX.............",
184"........XX...aaaaaaaaaaa",
185#endif
186".............aXXXXXXXXXa",
187".............aXXXXXXXXXa",
188".............aXXXXaXXXXa",
189".............aXXXXaXXXXa",
190".............aXXaaaaaXXa",
191".............aXXXXaXXXXa",
192".............aXXXXaXXXXa",
193".............aXXXXXXXXXa",
194".............aXXXXXXXXXa",
195".............aaaaaaaaaaa"};
196
197/* XPM */
198static const char * const link_xpm[] = {
199"24 30 3 1",
200". c None",
201"a c #000000",
202"X c #FFFFFF",
203#if defined(Q_WS_WIN) // Windows cursor is traditionally white
204"aa......................",
205"aXa.....................",
206"aXXa....................",
207"aXXXa...................",
208"aXXXXa..................",
209"aXXXXXa.................",
210"aXXXXXXa................",
211"aXXXXXXXa...............",
212"aXXXXXXXXa..............",
213"aXXXXXXXXXa.............",
214"aXXXXXXaaaa.............",
215"aXXXaXXa................",
216"aXXaaXXa................",
217"aXa..aXXa...............",
218"aa...aXXa...............",
219"a.....aXXa..............",
220"......aXXa..............",
221".......aXXa.............",
222".......aXXa.............",
223"........aa...aaaaaaaaaaa",
224#else
225"XX......................",
226"XaX.....................",
227"XaaX....................",
228"XaaaX...................",
229"XaaaaX..................",
230"XaaaaaX.................",
231"XaaaaaaX................",
232"XaaaaaaaX...............",
233"XaaaaaaaaX..............",
234"XaaaaaaaaaX.............",
235"XaaaaaaXXXX.............",
236"XaaaXaaX................",
237"XaaXXaaX................",
238"XaX..XaaX...............",
239"XX...XaaX...............",
240"X.....XaaX..............",
241"......XaaX..............",
242".......XaaX.............",
243".......XaaX.............",
244"........XX...aaaaaaaaaaa",
245#endif
246".............aXXXXXXXXXa",
247".............aXXXaaaaXXa",
248".............aXXXXaaaXXa",
249".............aXXXaaaaXXa",
250".............aXXaaaXaXXa",
251".............aXXaaXXXXXa",
252".............aXXaXXXXXXa",
253".............aXXXaXXXXXa",
254".............aXXXXXXXXXa",
255".............aaaaaaaaaaa"};
256
257#ifndef QT_NO_DRAGANDDROP
258
259// the universe's only drag manager
260QDragManager * qt_dnd_manager = 0;
261
262
263QDragManager::QDragManager()
264 : QObject( qApp, "global drag manager" )
265{
266 n_cursor = 3;
267 pm_cursor = new QPixmap[n_cursor];
268 pm_cursor[0] = QPixmap((const char **)move_xpm);
269 pm_cursor[1] = QPixmap((const char **)copy_xpm);
270 pm_cursor[2] = QPixmap((const char **)link_xpm);
271 object = 0;
272 dragSource = 0;
273 dropWidget = 0;
274 if ( !qt_dnd_manager )
275 qt_dnd_manager = this;
276 beingCancelled = FALSE;
277 restoreCursor = FALSE;
278 willDrop = FALSE;
279}
280
281
282QDragManager::~QDragManager()
283{
284#ifndef QT_NO_CURSOR
285 if ( restoreCursor )
286 QApplication::restoreOverrideCursor();
287#endif
288 qt_dnd_manager = 0;
289 delete [] pm_cursor;
290}
291
292#endif
293
294
295/*!
296 Constructs a drag object called \a name, which is a child of \a
297 dragSource.
298
299 Note that the drag object will be deleted when \a dragSource is
300 deleted.
301*/
302
303QDragObject::QDragObject( QWidget * dragSource, const char * name )
304 : QObject( dragSource, name )
305{
306 d = new QDragObjectData();
307 d->pm_cursor = 0;
308#ifndef QT_NO_DRAGANDDROP
309 if ( !qt_dnd_manager && qApp )
310 (void)new QDragManager();
311#endif
312}
313
314
315/*!
316 Destroys the drag object, canceling any drag and drop operation in
317 which it is involved, and frees up the storage used.
318*/
319
320QDragObject::~QDragObject()
321{
322#ifndef QT_NO_DRAGANDDROP
323 if ( qt_dnd_manager && qt_dnd_manager->object == this )
324 qt_dnd_manager->cancel( FALSE );
325 if ( d->pm_cursor ) {
326 for ( int i = 0; i < qt_dnd_manager->n_cursor; i++ )
327 qt_dnd_manager->pm_cursor[i] = d->pm_cursor[i];
328 delete [] d->pm_cursor;
329 }
330#endif
331 delete d;
332}
333
334#ifndef QT_NO_DRAGANDDROP
335/*!
336 Set the pixmap \a pm to display while dragging the object. The
337 platform-specific implementation will use this where it can - so
338 provide a small masked pixmap, and do not assume that the user
339 will actually see it. For example, cursors on Windows 95 are of
340 limited size.
341
342 The \a hotspot is the point on (or off) the pixmap that should be
343 under the cursor as it is dragged. It is relative to the top-left
344 pixel of the pixmap.
345
346 \warning We have seen problems with drag cursors on different
347 graphics hardware and driver software on Windows. Setting the
348 graphics acceleration in the display settings down one tick solved
349 the problems in all cases.
350*/
351void QDragObject::setPixmap(QPixmap pm, const QPoint& hotspot)
352{
353 d->pixmap = pm;
354 d->hot = hotspot;
355 if ( qt_dnd_manager && qt_dnd_manager->object == this )
356 qt_dnd_manager->updatePixmap();
357}
358
359/*!
360 \overload
361 Uses a hotspot that positions the pixmap below and to the right of
362 the mouse pointer. This allows the user to clearly see the point
363 on the window which they are dragging the data onto.
364*/
365void QDragObject::setPixmap(QPixmap pm)
366{
367 setPixmap(pm,QPoint(-10, -10));
368}
369
370/*!
371 Returns the currently set pixmap (which \link QPixmap::isNull()
372 isNull()\endlink if none is set).
373*/
374QPixmap QDragObject::pixmap() const
375{
376 return d->pixmap;
377}
378
379/*!
380 Returns the currently set pixmap hotspot.
381*/
382QPoint QDragObject::pixmapHotSpot() const
383{
384 return d->hot;
385}
386
387#if 0
388
389// ## reevaluate for Qt 4
390/*!
391 Set the \a cursor used when dragging in mode \a m.
392 Note: X11 only allow bitmaps for cursors.
393*/
394void QDragObject::setCursor( DragMode m, const QPixmap &cursor )
395{
396 if ( d->pm_cursor == 0 ) {
397 // safe default cursors
398 d->pm_cursor = new QPixmap[qt_dnd_manager->n_cursor];
399 for ( int i = 0; i < qt_dnd_manager->n_cursor; i++ )
400 d->pm_cursor[i] = qt_dnd_manager->pm_cursor[i];
401 }
402
403 int index;
404 switch ( m ) {
405 case DragCopy:
406 index = 1;
407 break;
408 case DragLink:
409 index = 2;
410 break;
411 default:
412 index = 0;
413 break;
414 }
415
416 // override default cursor
417 for ( index = 0; index < qt_dnd_manager->n_cursor; index++ )
418 qt_dnd_manager->pm_cursor[index] = cursor;
419}
420
421/*!
422 Returns the cursor used when dragging in mode \a m, or null if no cursor
423 has been set for that mode.
424*/
425QPixmap *QDragObject::cursor( DragMode m ) const
426{
427 if ( !d->pm_cursor )
428 return 0;
429
430 int index;
431 switch ( m ) {
432 case DragCopy:
433 index = 1;
434 break;
435 case DragLink:
436 index = 2;
437 break;
438 default:
439 index = 0;
440 break;
441 }
442
443 return qt_dnd_manager->pm_cursor+index;
444}
445
446#endif // 0
447
448/*!
449 Starts a drag operation using the contents of this object, using
450 DragDefault mode.
451
452 The function returns TRUE if the caller should delete the original
453 copy of the dragged data (but see target()); otherwise returns
454 FALSE.
455
456 If the drag contains \e references to information (e.g. file names
457 in a QUriDrag are references) then the return value should always
458 be ignored, as the target is expected to manipulate the
459 referred-to content directly. On X11 the return value should
460 always be correct anyway, but on Windows this is not necessarily
461 the case (e.g. the file manager starts a background process to
462 move files, so the source \e{must not} delete the files!)
463
464 Note that on Windows the drag operation will spin a blocking modal
465 event loop that will not dispatch any QTimers.
466*/
467bool QDragObject::drag()
468{
469 return drag( DragDefault );
470}
471
472
473/*!
474 Starts a drag operation using the contents of this object, using
475 \c DragMove mode. Be sure to read the constraints described in
476 drag().
477
478 \sa drag() dragCopy() dragLink()
479*/
480bool QDragObject::dragMove()
481{
482 return drag( DragMove );
483}
484
485
486/*!
487 Starts a drag operation using the contents of this object, using
488 \c DragCopy mode. Be sure to read the constraints described in
489 drag().
490
491 \sa drag() dragMove() dragLink()
492*/
493void QDragObject::dragCopy()
494{
495 (void)drag( DragCopy );
496}
497
498/*!
499 Starts a drag operation using the contents of this object, using
500 \c DragLink mode. Be sure to read the constraints described in
501 drag().
502
503 \sa drag() dragCopy() dragMove()
504*/
505void QDragObject::dragLink()
506{
507 (void)drag( DragLink );
508}
509
510
511/*!
512 \enum QDragObject::DragMode
513
514 This enum describes the possible drag modes.
515
516 \value DragDefault The mode is determined heuristically.
517 \value DragCopy The data is copied, never moved.
518 \value DragMove The data is moved, if dragged at all.
519 \value DragLink The data is linked, if dragged at all.
520 \value DragCopyOrMove The user chooses the mode by using a
521 control key to switch from the default.
522*/
523
524
525/*!
526 \overload
527 Starts a drag operation using the contents of this object.
528
529 At this point, the object becomes owned by Qt, not the
530 application. You should not delete the drag object or anything it
531 references. The actual transfer of data to the target application
532 will be done during future event processing - after that time the
533 drag object will be deleted.
534
535 Returns TRUE if the dragged data was dragged as a \e move,
536 indicating that the caller should remove the original source of
537 the data (the drag object must continue to have a copy); otherwise
538 returns FALSE.
539
540 The \a mode specifies the drag mode (see
541 \l{QDragObject::DragMode}.) Normally one of the simpler drag(),
542 dragMove(), or dragCopy() functions would be used instead.
543*/
544bool QDragObject::drag( DragMode mode )
545{
546 if ( qt_dnd_manager )
547 return qt_dnd_manager->drag( this, mode );
548 else
549 return FALSE;
550}
551
552#endif
553
554
555/*!
556 Returns a pointer to the drag source where this object originated.
557*/
558
559QWidget * QDragObject::source()
560{
561 if ( parent() && parent()->isWidgetType() )
562 return (QWidget *)parent();
563 else
564 return 0;
565}
566
567
568/*!
569 \class QDragObject qdragobject.h
570
571 \brief The QDragObject class encapsulates MIME-based data
572 transfer.
573
574 \ingroup draganddrop
575
576 QDragObject is the base class for all data that needs to be
577 transferred between and within applications, both for drag and
578 drop and for the \link qclipboard.html clipboard\endlink.
579
580 See the \link dnd.html Drag-and-drop documentation\endlink for an
581 overview of how to provide drag and drop in your application.
582
583 See the QClipboard documentation for an overview of how to provide
584 cut-and-paste in your application.
585
586 The drag() function is used to start a drag operation. You can
587 specify the \l DragMode in the call or use one of the convenience
588 functions dragCopy(), dragMove() or dragLink(). The drag source
589 where the data originated is retrieved with source(). If the data
590 was dropped on a widget within the application, target() will
591 return a pointer to that widget. Specify the pixmap to display
592 during the drag with setPixmap().
593*/
594
595static
596void stripws(QCString& s)
597{
598 int f;
599 while ( (f=s.find(' ')) >= 0 )
600 s.remove(f,1);
601}
602
603static
604const char * staticCharset(int i)
605{
606 static QCString localcharset;
607
608 switch ( i ) {
609 case 0:
610 return "UTF-8";
611 case 1:
612 return "ISO-10646-UCS-2";
613 case 2:
614 return ""; // in the 3rd place - some Xdnd targets might only look at 3
615 case 3:
616 if ( localcharset.isNull() ) {
617 QTextCodec *localCodec = QTextCodec::codecForLocale();
618 if ( localCodec ) {
619 localcharset = localCodec->name();
620 localcharset = localcharset.lower();
621 stripws(localcharset);
622 } else {
623 localcharset = "";
624 }
625 }
626 return localcharset;
627 }
628 return 0;
629}
630
631
632class QTextDragPrivate {
633public:
634 QTextDragPrivate();
635
636 enum { nfmt=4 };
637
638 QString txt;
639 QCString fmt[nfmt];
640 QCString subtype;
641
642 void setSubType(const QCString & st)
643 {
644 subtype = st.lower();
645 for ( int i=0; i<nfmt; i++ ) {
646 fmt[i] = "text/";
647 fmt[i].append(subtype);
648 QCString cs = staticCharset(i);
649 if ( !cs.isEmpty() ) {
650 fmt[i].append(";charset=");
651 fmt[i].append(cs);
652 }
653 }
654 }
655};
656
657inline QTextDragPrivate::QTextDragPrivate()
658{
659 setSubType("plain");
660}
661
662/*!
663 Sets the MIME subtype of the text being dragged to \a st. The
664 default subtype is "plain", so the default MIME type of the text
665 is "text/plain". You might use this to declare that the text is
666 "text/html" by calling setSubtype("html").
667*/
668void QTextDrag::setSubtype( const QCString & st)
669{
670 d->setSubType(st);
671}
672
673/*!
674 \class QTextDrag qdragobject.h
675
676 \brief The QTextDrag class is a drag and drop object for
677 transferring plain and Unicode text.
678
679 \ingroup draganddrop
680
681 Plain text is passed in a QString which may contain multiple lines
682 (i.e. may contain newline characters). The drag target will receive
683 the newlines according to the runtime environment, e.g. LF on Unix,
684 and CRLF on Windows.
685
686 Qt provides no built-in mechanism for delivering only a single-line.
687
688 For more information about drag and drop, see the QDragObject class
689 and the \link dnd.html drag and drop documentation\endlink.
690*/
691
692
693/*!
694 Constructs a text drag object and sets its data to \a text. \a
695 dragSource must be the drag source; \a name is the object name.
696*/
697
698QTextDrag::QTextDrag( const QString &text,
699 QWidget * dragSource, const char * name )
700 : QDragObject( dragSource, name )
701{
702 d = new QTextDragPrivate;
703 setText( text );
704}
705
706
707/*!
708 Constructs a default text drag object. \a dragSource must be the
709 drag source; \a name is the object name.
710*/
711
712QTextDrag::QTextDrag( QWidget * dragSource, const char * name )
713 : QDragObject( dragSource, name )
714{
715 d = new QTextDragPrivate;
716}
717
718
719/*!
720 Destroys the text drag object and frees up all allocated
721 resources.
722*/
723QTextDrag::~QTextDrag()
724{
725 delete d;
726}
727
728
729/*!
730 Sets the text to be dragged to \a text. You will need to call this
731 if you did not pass the text during construction.
732*/
733void QTextDrag::setText( const QString &text )
734{
735 d->txt = text;
736}
737
738
739/*!
740 \reimp
741*/
742const char * QTextDrag::format(int i) const
743{
744 if ( i >= d->nfmt )
745 return 0;
746 return d->fmt[i];
747}
748
749QTextCodec* qt_findcharset(const QCString& mimetype)
750{
751 int i=mimetype.find("charset=");
752 if ( i >= 0 ) {
753 QCString cs = mimetype.mid(i+8);
754 stripws(cs);
755 i = cs.find(';');
756 if ( i >= 0 )
757 cs = cs.left(i);
758 // win98 often has charset=utf16, and we need to get the correct codec for
759 // it to be able to get Unicode text drops.
760 if ( cs == "utf16" )
761 cs = "ISO-10646-UCS-2";
762 // May return 0 if unknown charset
763 return QTextCodec::codecForName(cs);
764 }
765 // no charset=, use locale
766 return QTextCodec::codecForLocale();
767}
768
769static QTextCodec *codecForHTML(const QCString &ba)
770{
771 // determine charset
772 int mib = 0;
773 int pos;
774 QTextCodec *c = 0;
775
776 if (ba.size() > 1 && (((uchar)ba[0] == 0xfe && (uchar)ba[1] == 0xff)
777 || ((uchar)ba[0] == 0xff && (uchar)ba[1] == 0xfe))) {
778 mib = 1000; // utf16
779 } else if (ba.size() > 2
780 && (uchar)ba[0] == 0xef
781 && (uchar)ba[1] == 0xbb
782 && (uchar)ba[2] == 0xbf) {
783 mib = 106; // utf-8
784 } else {
785 pos = 0;
786 while ((pos = ba.find("<meta http-equiv=", pos, FALSE)) != -1) {
787 int end = ba.find('>', pos+1);
788 if (end == -1)
789 break;
790 pos = ba.find("charset=", pos, FALSE) + strlen("charset=");
791 if (pos != -1 && pos < end) {
792 int pos2 = ba.find('\"', pos+1);
793 QCString cs = ba.mid(pos, pos2-pos);
794 c = QTextCodec::codecForName(cs);
795 if (c)
796 return c;
797 }
798 pos = end;
799 }
800 }
801 if (mib)
802 c = QTextCodec::codecForMib(mib);
803
804 return c;
805}
806
807static
808QTextCodec* findcodec(const QMimeSource* e)
809{
810 QTextCodec* r = 0;
811 const char* f;
812 int i;
813 for ( i=0; (f=e->format(i)); i++ ) {
814 bool html = !qstrnicmp(f, "text/html", 9);
815 if (html)
816 r = codecForHTML(QCString(e->encodedData(f)));
817 if (!r)
818 r = qt_findcharset(QCString(f).lower());
819 if (r)
820 return r;
821 }
822 return 0;
823}
824
825
826
827/*!
828 \reimp
829*/
830QByteArray QTextDrag::encodedData(const char* mime) const
831{
832 QCString r;
833 if ( 0==qstrnicmp(mime,"text/",5) ) {
834 QCString m(mime);
835 m = m.lower();
836 QTextCodec *codec = qt_findcharset(m);
837 if ( !codec )
838 return r;
839 QString text( d->txt );
840#if defined(Q_WS_WIN)
841 int index = text.find( QString::fromLatin1("\r\n"), 0 );
842 while ( index != -1 ) {
843 text.replace( index, 2, QChar('\n') );
844 index = text.find( "\r\n", index );
845 }
846#endif
847 r = codec->fromUnicode(text);
848 if (!codec || codec->mibEnum() != 1000) {
849 // Don't include NUL in size (QCString::resize() adds NUL)
850#if defined(Q_WS_WIN)
851 // This is needed to ensure the \0 isn't lost on Windows 95
852 if ( qWinVersion() & Qt::WV_DOS_based )
853 ((QByteArray&)r).resize(r.length()+1);
854 else
855#endif
856 ((QByteArray&)r).resize(r.length());
857 }
858 }
859 return r;
860}
861
862/*!
863 Returns TRUE if the information in \a e can be decoded into a
864 QString; otherwise returns FALSE.
865
866 \sa decode()
867*/
868bool QTextDrag::canDecode( const QMimeSource* e )
869{
870 const char* f;
871 for (int i=0; (f=e->format(i)); i++) {
872 if ( 0==qstrnicmp(f,"text/",5) ) {
873 return findcodec(e) != 0;
874 }
875 }
876 return 0;
877}
878
879/*!
880 \overload
881
882 Attempts to decode the dropped information in \a e into \a str.
883 Returns TRUE if successful; otherwise returns FALSE. If \a subtype
884 is null, any text subtype is accepted; otherwise only the
885 specified \a subtype is accepted.
886
887 \sa canDecode()
888*/
889bool QTextDrag::decode( const QMimeSource* e, QString& str, QCString& subtype )
890{
891 if(!e)
892 return FALSE;
893
894 if ( e->cacheType == QMimeSource::Text ) {
895 str = *e->cache.txt.str;
896 subtype = *e->cache.txt.subtype;
897 return TRUE;
898 }
899
900 const char* mime;
901 for (int i=0; (mime = e->format(i)); i++) {
902 if ( 0==qstrnicmp(mime,"text/",5) ) {
903 QCString m(mime);
904 m = m.lower();
905 int semi = m.find(';');
906 if ( semi < 0 )
907 semi = m.length();
908 QCString foundst = m.mid(5,semi-5);
909 if ( subtype.isNull() || foundst == subtype ) {
910 bool html = !qstrnicmp(mime, "text/html", 9);
911 QTextCodec* codec = 0;
912 if (html)
913 // search for the charset tag in the HTML
914 codec = codecForHTML(QCString(e->encodedData(mime)));
915 if (!codec)
916 codec = qt_findcharset(m);
917 if ( codec ) {
918 QByteArray payload;
919
920 payload = e->encodedData(mime);
921 if ( payload.size() ) {
922 int l;
923 if ( codec->mibEnum() != 1000) {
924 // length is at NUL or payload.size()
925 l = 0;
926 while ( l < (int)payload.size() && payload[l] )
927 l++;
928 } else {
929 l = payload.size();
930 }
931
932 str = codec->toUnicode(payload,l);
933
934 if ( subtype.isNull() )
935 subtype = foundst;
936
937 QMimeSource *m = (QMimeSource*)e;
938 m->clearCache();
939 m->cacheType = QMimeSource::Text;
940 m->cache.txt.str = new QString( str );
941 m->cache.txt.subtype = new QCString( subtype );
942
943 return TRUE;
944 }
945 }
946 }
947 }
948 }
949 return FALSE;
950}
951
952/*!
953 Attempts to decode the dropped information in \a e into \a str.
954 Returns TRUE if successful; otherwise returns FALSE.
955
956 \sa canDecode()
957*/
958bool QTextDrag::decode( const QMimeSource* e, QString& str )
959{
960 QCString st;
961 return decode(e,str,st);
962}
963
964
965/*
966 QImageDrag could use an internal MIME type for communicating QPixmaps
967 and QImages rather than always converting to raw data. This is available
968 for that purpose and others. It is not currently used.
969*/
970class QImageDragData
971{
972public:
973};
974
975
976/*!
977 \class QImageDrag qdragobject.h
978
979 \brief The QImageDrag class provides a drag and drop object for
980 transferring images.
981
982 \ingroup draganddrop
983
984 Images are offered to the receiving application in multiple
985 formats, determined by Qt's \link QImage::outputFormats() output
986 formats\endlink.
987
988 For more information about drag and drop, see the QDragObject
989 class and the \link dnd.html drag and drop documentation\endlink.
990*/
991
992/*!
993 Constructs an image drag object and sets its data to \a image. \a
994 dragSource must be the drag source; \a name is the object name.
995*/
996
997QImageDrag::QImageDrag( QImage image,
998 QWidget * dragSource, const char * name )
999 : QDragObject( dragSource, name ),
1000 d(0)
1001{
1002 setImage( image );
1003}
1004
1005/*!
1006 Constructs a default image drag object. \a dragSource must be the
1007 drag source; \a name is the object name.
1008*/
1009
1010QImageDrag::QImageDrag( QWidget * dragSource, const char * name )
1011 : QDragObject( dragSource, name ),
1012 d(0)
1013{
1014}
1015
1016
1017/*!
1018 Destroys the image drag object and frees up all allocated
1019 resources.
1020*/
1021
1022QImageDrag::~QImageDrag()
1023{
1024 // nothing
1025}
1026
1027
1028/*!
1029 Sets the image to be dragged to \a image. You will need to call
1030 this if you did not pass the image during construction.
1031*/
1032void QImageDrag::setImage( QImage image )
1033{
1034 img = image; // ### detach?
1035 ofmts = QImage::outputFormats();
1036 ofmts.remove("PBM"); // remove non-raw PPM
1037 if ( image.depth()!=32 ) {
1038 // BMP better than PPM for paletted images
1039 if ( ofmts.remove("BMP") ) // move to front
1040 ofmts.insert(0,"BMP");
1041 }
1042 // PNG is best of all
1043 if ( ofmts.remove("PNG") ) // move to front
1044 ofmts.insert(0,"PNG");
1045
1046 if(cacheType == QMimeSource::NoCache) { //cache it
1047 cacheType = QMimeSource::Graphics;
1048 cache.gfx.img = new QImage( img );
1049 cache.gfx.pix = 0;
1050 }
1051}
1052
1053/*!
1054 \reimp
1055*/
1056const char * QImageDrag::format(int i) const
1057{
1058 if ( i < (int)ofmts.count() ) {
1059 static QCString str;
1060 str.sprintf("image/%s",(((QImageDrag*)this)->ofmts).at(i));
1061 str = str.lower();
1062 if ( str == "image/pbmraw" )
1063 str = "image/ppm";
1064 return str;
1065 } else {
1066 return 0;
1067 }
1068}
1069
1070/*!
1071 \reimp
1072*/
1073QByteArray QImageDrag::encodedData(const char* fmt) const
1074{
1075 if ( qstrnicmp( fmt, "image/", 6 )==0 ) {
1076 QCString f = fmt+6;
1077 QByteArray data;
1078 QBuffer w( data );
1079 w.open( IO_WriteOnly );
1080 QImageIO io( &w, f.upper() );
1081 io.setImage( img );
1082 if ( !io.write() )
1083 return QByteArray();
1084 w.close();
1085 return data;
1086 } else {
1087 return QByteArray();
1088 }
1089}
1090
1091/*!
1092 Returns TRUE if the information in mime source \a e can be decoded
1093 into an image; otherwise returns FALSE.
1094
1095 \sa decode()
1096*/
1097bool QImageDrag::canDecode( const QMimeSource* e ) {
1098 QStrList fileFormats = QImageIO::inputFormats();
1099
1100 fileFormats.first();
1101 while ( fileFormats.current()) {
1102 QCString format = fileFormats.current();
1103 QCString type = "image/" + format.lower();
1104 if ( e->provides(type.data()))
1105 return TRUE;
1106 fileFormats.next();
1107 }
1108
1109 return FALSE;
1110}
1111
1112/*!
1113 Attempts to decode the dropped information in mime source \a e
1114 into \a img. Returns TRUE if successful; otherwise returns FALSE.
1115
1116 \sa canDecode()
1117*/
1118bool QImageDrag::decode( const QMimeSource* e, QImage& img )
1119{
1120 if ( !e )
1121 return FALSE;
1122 if ( e->cacheType == QMimeSource::Graphics ) {
1123 img = *e->cache.gfx.img;
1124 return TRUE;
1125 }
1126
1127 QByteArray payload;
1128 QStrList fileFormats = QImageIO::inputFormats();
1129 // PNG is best of all
1130 if ( fileFormats.remove("PNG") ) // move to front
1131 fileFormats.insert(0,"PNG");
1132 fileFormats.first();
1133 while ( fileFormats.current() ) {
1134 QCString format = fileFormats.current();
1135 fileFormats.next();
1136
1137 QCString type = "image/" + format.lower();
1138 if ( ! e->provides( type.data() ) ) continue;
1139 payload = e->encodedData( type.data() );
1140 if ( !payload.isEmpty() )
1141 break;
1142 }
1143
1144 if ( payload.isEmpty() )
1145 return FALSE;
1146
1147 img.loadFromData(payload);
1148 if ( img.isNull() )
1149 return FALSE;
1150 QMimeSource *m = (QMimeSource*)e;
1151 m->clearCache();
1152 m->cacheType = QMimeSource::Graphics;
1153 m->cache.gfx.img = new QImage( img );
1154 m->cache.gfx.pix = 0;
1155 return TRUE;
1156}
1157
1158/*!
1159 \overload
1160
1161 Attempts to decode the dropped information in mime source \a e
1162 into pixmap \a pm. Returns TRUE if successful; otherwise returns
1163 FALSE.
1164
1165 This is a convenience function that converts to a QPixmap via a
1166 QImage.
1167
1168 \sa canDecode()
1169*/
1170bool QImageDrag::decode( const QMimeSource* e, QPixmap& pm )
1171{
1172 if ( !e )
1173 return FALSE;
1174
1175 if ( e->cacheType == QMimeSource::Graphics && e->cache.gfx.pix) {
1176 pm = *e->cache.gfx.pix;
1177 return TRUE;
1178 }
1179
1180 QImage img;
1181 // We avoid dither, since the image probably came from this display
1182 if ( decode( e, img ) ) {
1183 if ( !pm.convertFromImage( img, AvoidDither ) )
1184 return FALSE;
1185 // decode initialized the cache for us
1186
1187 QMimeSource *m = (QMimeSource*)e;
1188 m->cache.gfx.pix = new QPixmap( pm );
1189 return TRUE;
1190 }
1191 return FALSE;
1192}
1193
1194
1195
1196
1197/*!
1198 \class QStoredDrag qdragobject.h
1199 \brief The QStoredDrag class provides a simple stored-value drag object for arbitrary MIME data.
1200
1201 \ingroup draganddrop
1202
1203 When a block of data has only one representation, you can use a
1204 QStoredDrag to hold it.
1205
1206 For more information about drag and drop, see the QDragObject
1207 class and the \link dnd.html drag and drop documentation\endlink.
1208*/
1209
1210/*!
1211 Constructs a QStoredDrag. The \a dragSource and \a name are passed
1212 to the QDragObject constructor, and the format is set to \a
1213 mimeType.
1214
1215 The data will be unset. Use setEncodedData() to set it.
1216*/
1217QStoredDrag::QStoredDrag( const char* mimeType, QWidget * dragSource, const char * name ) :
1218 QDragObject(dragSource,name)
1219{
1220 d = new QStoredDragData();
1221 d->fmt = qstrdup(mimeType);
1222}
1223
1224/*!
1225 Destroys the drag object and frees up all allocated resources.
1226*/
1227QStoredDrag::~QStoredDrag()
1228{
1229 delete [] (char*)d->fmt;
1230 delete d;
1231}
1232
1233/*!
1234 \reimp
1235*/
1236const char * QStoredDrag::format(int i) const
1237{
1238 if ( i==0 )
1239 return d->fmt;
1240 else
1241 return 0;
1242}
1243
1244
1245/*!
1246 Sets the encoded data of this drag object to \a encodedData. The
1247 encoded data is what's delivered to the drop sites. It must be in
1248 a strictly defined and portable format.
1249
1250 The drag object can't be dropped (by the user) until this function
1251 has been called.
1252*/
1253
1254void QStoredDrag::setEncodedData( const QByteArray & encodedData )
1255{
1256 d->enc = encodedData.copy();
1257}
1258
1259/*!
1260 Returns the stored data. \a m contains the data's format.
1261
1262 \sa setEncodedData()
1263*/
1264QByteArray QStoredDrag::encodedData(const char* m) const
1265{
1266 if ( !qstricmp(m,d->fmt) )
1267 return d->enc;
1268 else
1269 return QByteArray();
1270}
1271
1272
1273/*!
1274 \class QUriDrag qdragobject.h
1275 \brief The QUriDrag class provides a drag object for a list of URI references.
1276
1277 \ingroup draganddrop
1278
1279 URIs are a useful way to refer to files that may be distributed
1280 across multiple machines. A URI will often refer to a file on a
1281 machine local to both the drag source and the drop target, so the
1282 URI can be equivalent to passing a file name but is more
1283 extensible.
1284
1285 Use URIs in Unicode form so that the user can comfortably edit and
1286 view them. For use in HTTP or other protocols, use the correctly
1287 escaped ASCII form.
1288
1289 You can convert a list of file names to file URIs using
1290 setFileNames(), or into human-readble form with setUnicodeUris().
1291
1292 Static functions are provided to convert between filenames and
1293 URIs, e.g. uriToLocalFile() and localFileToUri(), and to and from
1294 human-readable form, e.g. uriToUnicodeUri(), unicodeUriToUri().
1295 You can also decode URIs from a mimesource into a list with
1296 decodeLocalFiles() and decodeToUnicodeUris().
1297*/
1298
1299/*!
1300 Constructs an object to drag the list of URIs in \a uris. The \a
1301 dragSource and \a name arguments are passed on to QStoredDrag.
1302 Note that URIs are always in escaped UTF8 encoding.
1303*/
1304QUriDrag::QUriDrag( QStrList uris,
1305 QWidget * dragSource, const char * name ) :
1306 QStoredDrag( "text/uri-list", dragSource, name )
1307{
1308 setUris(uris);
1309}
1310
1311/*!
1312 Constructs an object to drag. You must call setUris() before you
1313 start the drag(). Passes \a dragSource and \a name to the
1314 QStoredDrag constructor.
1315*/
1316QUriDrag::QUriDrag( QWidget * dragSource, const char * name ) :
1317 QStoredDrag( "text/uri-list", dragSource, name )
1318{
1319}
1320
1321/*!
1322 Destroys the object.
1323*/
1324QUriDrag::~QUriDrag()
1325{
1326}
1327
1328/*!
1329 Changes the list of \a uris to be dragged.
1330
1331 Note that URIs are always in escaped UTF8 encoding.
1332*/
1333void QUriDrag::setUris( QStrList uris )
1334{
1335 QByteArray a;
1336 int c=0;
1337 for ( const char* s = uris.first(); s; s = uris.next() ) {
1338 int l = qstrlen(s);
1339 a.resize(c+l+2);
1340 memcpy(a.data()+c,s,l);
1341 memcpy(a.data()+c+l,"\r\n",2);
1342 c+=l+2;
1343 }
1344 a.resize(c+1);
1345 a[c] = 0;
1346 setEncodedData(a);
1347}
1348
1349
1350/*!
1351 Returns TRUE if decode() would be able to decode \a e; otherwise
1352 returns FALSE.
1353*/
1354bool QUriDrag::canDecode( const QMimeSource* e )
1355{
1356 return e->provides( "text/uri-list" );
1357}
1358
1359/*!
1360 Decodes URIs from \a e, placing the result in \a l (which is first
1361 cleared).
1362
1363 Returns TRUE if \a e contained a valid list of URIs; otherwise
1364 returns FALSE.
1365*/
1366bool QUriDrag::decode( const QMimeSource* e, QStrList& l )
1367{
1368 QByteArray payload = e->encodedData( "text/uri-list" );
1369 if ( payload.size() ) {
1370 l.clear();
1371 l.setAutoDelete(TRUE);
1372 uint c=0;
1373 const char* d = payload.data();
1374 while (c < payload.size() && d[c]) {
1375 uint f = c;
1376 // Find line end
1377 while (c < payload.size() && d[c] && d[c]!='\r'
1378 && d[c] != '\n')
1379 c++;
1380 QCString s(d+f,c-f+1);
1381 if ( s[0] != '#' ) // non-comment?
1382 l.append( s );
1383 // Skip junk
1384 while (c < payload.size() && d[c] &&
1385 (d[c]=='\n' || d[c]=='\r'))
1386 c++;
1387 }
1388 return TRUE;
1389 }
1390 return FALSE;
1391}
1392
1393static uint htod( int h )
1394{
1395 if ( isdigit(h) )
1396 return h - '0';
1397 return tolower( h ) - 'a' + 10;
1398}
1399
1400/*!
1401 \fn QUriDrag::setFilenames( const QStringList & )
1402 \obsolete
1403
1404 Use setFileNames() instead (notice the N).
1405*/
1406
1407/*!
1408 Sets the URIs to be the local-file URIs equivalent to \a fnames.
1409
1410 \sa localFileToUri(), setUris()
1411*/
1412void QUriDrag::setFileNames( const QStringList & fnames )
1413{
1414 QStrList uris;
1415 for ( QStringList::ConstIterator i = fnames.begin();
1416 i != fnames.end(); ++i ) {
1417 QCString fileUri = localFileToUri(*i);
1418 if (!fileUri.isEmpty())
1419 uris.append(fileUri);
1420 }
1421 setUris( uris );
1422}
1423
1424/*!
1425 Sets the URIs in \a uuris to be the Unicode URIs (only useful for
1426 displaying to humans).
1427
1428 \sa localFileToUri(), setUris()
1429*/
1430void QUriDrag::setUnicodeUris( const QStringList & uuris )
1431{
1432 QStrList uris;
1433 for ( QStringList::ConstIterator i = uuris.begin();
1434 i != uuris.end(); ++i )
1435 uris.append( unicodeUriToUri(*i) );
1436 setUris( uris );
1437}
1438
1439/*!
1440 Returns the URI equivalent of the Unicode URI given in \a uuri
1441 (only useful for displaying to humans).
1442
1443 \sa uriToLocalFile()
1444*/
1445QCString QUriDrag::unicodeUriToUri(const QString& uuri)
1446{
1447 QCString utf8 = uuri.utf8();
1448 QCString escutf8;
1449 int n = utf8.length();
1450 for (int i=0; i<n; i++) {
1451 if ( utf8[i] >= 'a' && utf8[i] <= 'z'
1452 || utf8[i] == '/'
1453 || utf8[i] >= '0' && utf8[i] <= '9'
1454 || utf8[i] >= 'A' && utf8[i] <= 'Z'
1455
1456 || utf8[i] == '-' || utf8[i] == '_'
1457 || utf8[i] == '.' || utf8[i] == '!'
1458 || utf8[i] == '~' || utf8[i] == '*'
1459 || utf8[i] == '(' || utf8[i] == ')'
1460 || utf8[i] == '\''
1461
1462 // Allow this through, so that all URI-references work.
1463 || utf8[i] == '#'
1464
1465 || utf8[i] == ';'
1466 || utf8[i] == '?' || utf8[i] == ':'
1467 || utf8[i] == '@' || utf8[i] == '&'
1468 || utf8[i] == '=' || utf8[i] == '+'
1469 || utf8[i] == '$' || utf8[i] == ',' )
1470 {
1471 escutf8 += utf8[i];
1472 } else {
1473 // Everything else is escaped as %HH
1474 QCString s(4);
1475 s.sprintf("%%%02x",(uchar)utf8[i]);
1476 escutf8 += s;
1477 }
1478 }
1479 return escutf8;
1480}
1481
1482/*!
1483 Returns the URI equivalent to the absolute local file \a filename.
1484
1485 \sa uriToLocalFile()
1486*/
1487QCString QUriDrag::localFileToUri(const QString& filename)
1488{
1489 QString r = filename;
1490
1491 //check that it is an absolute file
1492 if (QDir::isRelativePath(r))
1493 return QCString();
1494
1495#ifdef Q_WS_WIN
1496
1497
1498 bool hasHost = false;
1499 // convert form network path
1500 if (r.left(2) == "\\\\" || r.left(2) == "//") {
1501 r.remove(0, 2);
1502 hasHost = true;
1503 }
1504
1505 // Slosh -> Slash
1506 int slosh;
1507 while ( (slosh=r.find('\\')) >= 0 ) {
1508 r[slosh] = '/';
1509 }
1510
1511 // Drive
1512 if ( r[0] != '/' && !hasHost)
1513 r.insert(0,'/');
1514
1515#endif
1516#if defined ( Q_WS_X11 ) && 0
1517 // URL without the hostname is considered to be errorneous by XDnD.
1518 // See: http://www.newplanetsoftware.com/xdnd/dragging_files.html
1519 // This feature is not active because this would break dnd between old and new qt apps.
1520 char hostname[257];
1521 if ( gethostname( hostname, 255 ) == 0 ) {
1522 hostname[256] = '\0';
1523 r.prepend( QString::fromLatin1( hostname ) );
1524 }
1525#endif
1526 return unicodeUriToUri(QString("file://" + r));
1527}
1528
1529/*!
1530 Returns the Unicode URI (only useful for displaying to humans)
1531 equivalent of \a uri.
1532
1533 Note that URIs are always in escaped UTF8 encoding.
1534
1535 \sa localFileToUri()
1536*/
1537QString QUriDrag::uriToUnicodeUri(const char* uri)
1538{
1539 QCString utf8;
1540
1541 while (*uri) {
1542 switch (*uri) {
1543 case '%': {
1544 uint ch = (uchar) uri[1];
1545 if ( ch && uri[2] ) {
1546 ch = htod( ch ) * 16 + htod( (uchar) uri[2] );
1547 utf8 += (char) ch;
1548 uri += 2;
1549 }
1550 }
1551 break;
1552 default:
1553 utf8 += *uri;
1554 }
1555 ++uri;
1556 }
1557
1558 return QString::fromUtf8(utf8);
1559}
1560
1561/*!
1562 Returns the name of a local file equivalent to \a uri or a null
1563 string if \a uri is not a local file.
1564
1565 Note that URIs are always in escaped UTF8 encoding.
1566
1567 \sa localFileToUri()
1568*/
1569QString QUriDrag::uriToLocalFile(const char* uri)
1570{
1571 QString file;
1572
1573 if (!uri)
1574 return file;
1575 if (0==qstrnicmp(uri,"file:/",6)) // It is a local file uri
1576 uri += 6;
1577 else if (QString(uri).find(":/") != -1) // It is a different scheme uri
1578 return file;
1579
1580 bool local = uri[0] != '/' || ( uri[0] != '\0' && uri[1] == '/' );
1581#ifdef Q_WS_X11
1582 // do we have a hostname?
1583 if ( !local && uri[0] == '/' && uri[2] != '/' ) {
1584 // then move the pointer to after the 'hostname/' part of the uri
1585 const char* hostname_end = strchr( uri+1, '/' );
1586 if ( hostname_end != NULL ) {
1587 char hostname[ 257 ];
1588 if ( gethostname( hostname, 255 ) == 0 ) {
1589 hostname[ 256 ] = '\0';
1590 if ( qstrncmp( uri+1, hostname, hostname_end - ( uri+1 )) == 0 ) {
1591 uri = hostname_end + 1; // point after the slash
1592 local = TRUE;
1593 }
1594 }
1595 }
1596 }
1597#endif
1598 if ( local ) {
1599 file = uriToUnicodeUri(uri);
1600 if ( uri[1] == '/' ) {
1601 file.remove((uint)0,1);
1602 } else {
1603 file.insert(0,'/');
1604 }
1605#ifdef Q_WS_WIN
1606 if ( file.length() > 2 && file[0] == '/' && file[2] == '|' ) {
1607 file[2] = ':';
1608 file.remove(0,1);
1609 } else if (file.length() > 2 && file[0] == '/' && file[1].isLetter() && file[2] == ':') {
1610 file.remove(0, 1);
1611 }
1612 // Leave slash as slashes.
1613#endif
1614 }
1615#ifdef Q_WS_WIN
1616 else {
1617 file = uriToUnicodeUri(uri);
1618 // convert to network path
1619 file.insert(1, '/'); // leave as forward slashes
1620 }
1621#endif
1622
1623 return file;
1624}
1625
1626/*!
1627 Decodes URIs from the mime source event \a e, converts them to
1628 local files if they refer to local files, and places them in \a l
1629 (which is first cleared).
1630
1631 Returns TRUE if \e contained a valid list of URIs; otherwise
1632 returns FALSE. The list will be empty if no URIs were local files.
1633*/
1634bool QUriDrag::decodeLocalFiles( const QMimeSource* e, QStringList& l )
1635{
1636 QStrList u;
1637 if ( !decode( e, u ) )
1638 return FALSE;
1639
1640 l.clear();
1641 for (const char* s=u.first(); s; s=u.next()) {
1642 QString lf = uriToLocalFile(s);
1643 if ( !lf.isNull() )
1644 l.append( lf );
1645 }
1646 return TRUE;
1647}
1648
1649/*!
1650 Decodes URIs from the mime source event \a e, converts them to
1651 Unicode URIs (only useful for displaying to humans), placing them
1652 in \a l (which is first cleared).
1653
1654 Returns TRUE if \e contained a valid list of URIs; otherwise
1655 returns FALSE.
1656*/
1657bool QUriDrag::decodeToUnicodeUris( const QMimeSource* e, QStringList& l )
1658{
1659 QStrList u;
1660 if ( !decode( e, u ) )
1661 return FALSE;
1662
1663 l.clear();
1664 for (const char* s=u.first(); s; s=u.next())
1665 l.append( uriToUnicodeUri(s) );
1666
1667 return TRUE;
1668}
1669
1670
1671#ifndef QT_NO_DRAGANDDROP
1672/*!
1673 If the source of the drag operation is a widget in this
1674 application, this function returns that source, otherwise it
1675 returns 0. The source of the operation is the first parameter to
1676 drag object subclasses.
1677
1678 This is useful if your widget needs special behavior when dragging
1679 to itself, etc.
1680
1681 See QDragObject::QDragObject() and subclasses.
1682*/
1683QWidget* QDropEvent::source() const
1684{
1685 return qt_dnd_manager ? qt_dnd_manager->dragSource : 0;
1686}
1687#endif
1688
1689/*!
1690 \class QColorDrag qdragobject.h
1691
1692 \brief The QColorDrag class provides a drag and drop object for
1693 transferring colors.
1694
1695 \ingroup draganddrop
1696
1697 This class provides a drag object which can be used to transfer data
1698 about colors for drag and drop and in the clipboard. For example, it
1699 is used in QColorDialog.
1700
1701 The color is set in the constructor but can be changed with
1702 setColor().
1703
1704 For more information about drag and drop, see the QDragObject class
1705 and the \link dnd.html drag and drop documentation\endlink.
1706*/
1707
1708/*!
1709 Constructs a color drag object with the color \a col. Passes \a
1710 dragsource and \a name to the QStoredDrag constructor.
1711*/
1712
1713QColorDrag::QColorDrag( const QColor &col, QWidget *dragsource, const char *name )
1714 : QStoredDrag( "application/x-color", dragsource, name )
1715{
1716 setColor( col );
1717}
1718
1719/*!
1720 Constructs a color drag object with a white color. Passes \a
1721 dragsource and \a name to the QStoredDrag constructor.
1722*/
1723
1724QColorDrag::QColorDrag( QWidget *dragsource, const char *name )
1725 : QStoredDrag( "application/x-color", dragsource, name )
1726{
1727 setColor( Qt::white );
1728}
1729
1730/*!
1731 Sets the color of the color drag to \a col.
1732*/
1733
1734void QColorDrag::setColor( const QColor &col )
1735{
1736 short r = (col.red() << 8) | col.red();
1737 short g = (col.green() << 8) | col.green();
1738 short b = (col.blue() << 8) | col.blue();
1739
1740 // make sure we transmit data in network order
1741 r = htons(r);
1742 g = htons(g);
1743 b = htons(b);
1744
1745 ushort rgba[4] = {
1746 r, g, b,
1747 0xffff // Alpha not supported yet.
1748 };
1749 QByteArray data(sizeof(rgba));
1750 memcpy(data.data(), rgba, sizeof(rgba));
1751 setEncodedData(data);
1752}
1753
1754/*!
1755 Returns TRUE if the color drag object can decode the mime source
1756 \a e; otherwise returns FALSE.
1757*/
1758
1759bool QColorDrag::canDecode( QMimeSource *e )
1760{
1761 return e->provides( "application/x-color" );
1762}
1763
1764/*!
1765 Decodes the mime source \a e and sets the decoded values to \a
1766 col.
1767*/
1768
1769bool QColorDrag::decode( QMimeSource *e, QColor &col )
1770{
1771 QByteArray data = e->encodedData("application/x-color");
1772 ushort rgba[4];
1773 if (data.size() != sizeof(rgba))
1774 return FALSE;
1775
1776 memcpy(rgba, data.data(), sizeof(rgba));
1777
1778 short r = rgba[0];
1779 short g = rgba[1];
1780 short b = rgba[2];
1781
1782 // data is in network order
1783 r = ntohs(r);
1784 g = ntohs(g);
1785 b = ntohs(b);
1786
1787 r = (r >> 8) & 0xff;
1788 g = (g >> 8) & 0xff;
1789 b = (b >> 8) & 0xff;
1790
1791 col.setRgb(r, g, b);
1792 return TRUE;
1793}
1794
1795#endif // QT_NO_MIME
Note: See TracBrowser for help on using the repository browser.