source: trunk/examples/tetrix/qdragapp.cpp

Last change on this file was 160, checked in by dmik, 19 years ago

Imported table and iconview modules and a bunch of dependent examples from the official release 3.3.1 from Trolltech.

  • Property svn:keywords set to Id
File size: 11.7 KB
Line 
1/****************************************************************************
2** $Id: qdragapp.cpp 160 2006-12-11 20:15:57Z dmik $
3**
4** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
5**
6** This file is part of an example program for Qt. This example
7** program may be used, distributed and modified without limitation.
8**
9*****************************************************************************/
10
11#include "qdragapp.h"
12#include "qptrlist.h"
13#include "qintdict.h"
14#include "qpopupmenu.h"
15#include "qguardedptr.h"
16#include "qcolor.h"
17#include "qwidget.h"
18#include "qfontmetrics.h"
19#include "qcursor.h"
20#include "qobjectlist.h"
21
22QWidget *cursorWidget( QPoint * = 0 );
23
24class QDragger;
25
26
27class DropWindow : public QWidget
28{
29 Q_OBJECT
30public:
31 void paintEvent( QPaintEvent * );
32 void closeEvent( QCloseEvent * );
33
34 QDragger *master;
35};
36
37
38struct DropInfo {
39 DropInfo() { w=0; }
40 ~DropInfo() { delete w; }
41 DropWindow *w;
42 bool userOpened;
43};
44
45struct DraggedInfo {
46 QWidget *w;
47 QWidget *mother;
48 QPoint pos;
49};
50
51
52class QDragger : public QObject
53{
54 Q_OBJECT
55public:
56 QDragger();
57 ~QDragger();
58
59 bool notify( QObject *, QEvent * ); // event filter
60 void closeDropWindow( DropWindow * );
61public slots:
62 void openDropWindow();
63 void killDropWindow();
64 void killAllDropWindows();
65 void sendChildHome();
66 void sendAllChildrenHome();
67private:
68 bool isParentToDragged( QWidget * );
69 bool noWidgets( QWidget * );
70 void killDropWindow( DropInfo * );
71 void killAllDropWindows( bool );
72 void sendChildHome( DraggedInfo * );
73 void sendAllChildrenHome( QWidget * );
74 QWidget *openDropWindow( const QRect&, bool );
75
76 bool startGrab();
77 void grabFinished();
78 bool dragEvent( QWidget *, QMouseEvent * );
79 bool killDropEvent( QMouseEvent * );
80 bool sendChildEvent( QMouseEvent * );
81
82 bool killingDrop;
83 bool sendingChild;
84 QWidget *clickedWidget;
85 QGuardedPtr<QWidget> hostWidget;
86 QCursor cursor;
87
88 QPopupMenu* menu;
89 QPoint clickOffset;
90 QColor dragBackground;
91 QColor dragForeground;
92 DraggedInfo dragInfo;
93 QIntDict<DraggedInfo> draggedDict;
94 QIntDict<DropInfo> dropDict;
95};
96
97
98QDragApplication::QDragApplication( int &argc, char **argv )
99 : QApplication( argc, argv ), dragger( 0 )
100{
101 dragger = new QDragger;
102}
103
104QDragApplication::~QDragApplication()
105{
106 delete dragger;
107}
108
109bool QDragApplication::notify( QObject *o, QEvent *e )
110{
111 if ( dragger && !dragger->notify( o, e ) )
112 return QApplication::notify( o, e );
113 else
114 return FALSE;
115}
116
117void DropWindow::paintEvent( QPaintEvent * )
118{
119 const char *msg = "Drag widgets and drop them here or anywhere!";
120 int startX = ( width() - fontMetrics().width( msg ) )/2;
121 startX = startX < 0 ? 0 : startX;
122
123 drawText( startX, height()/2, msg );
124}
125
126void DropWindow::closeEvent( QCloseEvent *e )
127{
128 master->closeDropWindow( this );
129 e->ignore();
130}
131
132QDragger::QDragger()
133{
134 dragInfo.w = 0;
135 killingDrop = FALSE;
136 sendingChild = FALSE;
137 draggedDict.setAutoDelete( TRUE );
138 dropDict .setAutoDelete( TRUE );
139
140 menu = new QPopupMenu;
141 menu->insertItem( "Open drop window", 1 );
142 menu->insertItem( "Kill drop window", 2 );
143 menu->insertItem( "Kill all drop windows", 3 );
144 menu->insertSeparator();
145// menu->insertItem( "Send child home", 4 );
146 menu->insertItem( "Send all children home", 5 );
147
148 menu->connectItem( 1, this, SLOT(openDropWindow()) );
149 menu->connectItem( 2, this, SLOT(killDropWindow()) );
150 menu->connectItem( 3, this, SLOT(killAllDropWindows()) );
151// menu->connectItem( 4, this, SLOT(sendChildHome()) );
152 menu->connectItem( 5, this, SLOT(sendAllChildrenHome()) );
153}
154
155QDragger::~QDragger()
156{
157 delete menu;
158}
159
160
161bool QDragger::notify( QObject *o, QEvent *e )
162{
163 if ( !o->isWidgetType() || o == menu )
164 return FALSE;
165 switch( e->type() ) {
166 case QEvent::MouseMove:
167 {
168 QMouseEvent *tmp = (QMouseEvent*) e;
169 if ( killingDrop )
170 return killDropEvent( tmp );
171 if ( sendingChild )
172 return sendChildEvent( tmp );
173 if ( tmp->state() & QMouseEvent::RightButton )
174 return dragEvent( (QWidget*) o, tmp );
175 break;
176 }
177 case QEvent::MouseButtonPress:
178 case QEvent::MouseButtonRelease:
179 case QEvent::MouseButtonDblClick:
180 {
181 QMouseEvent *tmp = (QMouseEvent*) e;
182 if ( killingDrop )
183 return killDropEvent( tmp );
184 if ( sendingChild )
185 return sendChildEvent( tmp );
186 if ( tmp->button() == QMouseEvent::RightButton )
187 return dragEvent( (QWidget*) o, tmp );
188 }
189 break;
190 default:
191 break;
192 }
193 return FALSE;
194}
195
196bool QDragger::isParentToDragged( QWidget *w )
197{
198 QIntDictIterator<DraggedInfo> iter( draggedDict );
199
200 DraggedInfo *tmp;
201 while( (tmp = iter.current()) ) {
202 ++iter;
203 if ( tmp->mother == w )
204 return TRUE;
205 }
206 return FALSE;
207}
208
209bool QDragger::noWidgets( QWidget *w )
210{
211 const QObjectList *l = w->children();
212 if ( !l )
213 return TRUE;
214 QObjectListIt iter( *l );
215 QObject *tmp;
216 while( (tmp = iter.current()) ) {
217 ++iter;
218 if ( tmp->isWidgetType() )
219 return FALSE;
220 }
221 return TRUE;
222}
223
224void QDragger::sendAllChildrenHome( QWidget *w )
225{
226 const QObjectList *l = w->children();
227 if ( !l )
228 return;
229 QObjectListIt iter( *l );
230 QObject *tmp;
231 while( (tmp = iter.current()) ) {
232 ++iter;
233 if ( tmp->isWidgetType() ) {
234 sendAllChildrenHome( (QWidget*) tmp );
235 DraggedInfo *di = draggedDict.find( (long) tmp );
236 if ( di )
237 sendChildHome( di );
238 }
239 }
240}
241
242bool QDragger::dragEvent( QWidget *w, QMouseEvent *e )
243{
244 switch( e->type() ) {
245 case QEvent::MouseButtonDblClick:
246 case QEvent::MouseButtonPress: {
247 if ( !noWidgets( w ) || // has widget children
248 isParentToDragged( w ) || // has had widget children
249 w->parentWidget() == 0 ) { // is top level window
250 hostWidget = w;
251 menu->popup( w->mapToGlobal( e->pos() ) );
252 return TRUE;
253 }
254 if ( !draggedDict.find( (long) w ) ) {
255 DraggedInfo *tmp = new DraggedInfo;
256 tmp->w = w;
257 tmp->mother = w->parentWidget();
258 tmp->pos = w->frameGeometry().topLeft();
259 draggedDict.insert( (long) w, tmp );
260 }
261 dragBackground = w->backgroundColor();
262 dragForeground = w->foregroundColor();
263 dragInfo.w = w;
264 dragInfo.mother = w->parentWidget();
265 dragInfo.pos = w->frameGeometry().topLeft();
266 clickOffset = e->pos();
267 dragInfo.w = w;
268 QPoint p = w->mapToGlobal(QPoint(0,0));
269 w->reparent( 0, WType_Popup, p, TRUE );
270
271 return TRUE;
272 }
273 case QEvent::MouseButtonRelease:
274 case QEvent::MouseMove: {
275 if ( dragInfo.w != 0 ) {
276 QPoint p = QCursor::pos() - clickOffset;
277 dragInfo.w->move( p );
278 if ( e->type() == QEvent::MouseMove )
279 return TRUE;
280 } else {
281 return FALSE;
282 }
283 if ( !dragInfo.w )
284 return FALSE;
285 if ( w != dragInfo.w )
286 w = dragInfo.w;
287 dragInfo.w = 0;
288 w->hide();
289 QPoint pos;
290 QWidget *target = cursorWidget( &pos );
291 pos = pos - clickOffset;
292 QPoint p;
293 if ( !target ) {
294 target = openDropWindow( QRect( pos, w->size() ),
295 FALSE);
296 p = QPoint( 0, 0 );
297 }
298 else
299 p = target->mapFromGlobal( pos );
300 w->reparent( target, 0, p, TRUE );
301 DropInfo *tmp = dropDict.find( (long) dragInfo.mother );
302 if ( tmp ) {
303 if ( !tmp->userOpened && noWidgets( tmp->w ) )
304 dropDict.remove( (long) tmp->w );
305 }
306 if ( !target->isVisible() )
307 target->show();
308 }
309 return TRUE;
310 default:
311 return FALSE;
312 }
313}
314
315bool QDragger::killDropEvent( QMouseEvent *e )
316{
317 switch( e->type() ) {
318 case QEvent::MouseButtonDblClick:
319 case QEvent::MouseButtonPress:
320 clickedWidget = cursorWidget();
321 return TRUE;
322 case QEvent::MouseButtonRelease:
323 hostWidget->releaseMouse();
324 if ( clickedWidget ) {
325 DropInfo *tmp = dropDict.find( (long) clickedWidget );
326 if( tmp ) {
327 killDropWindow( tmp );
328 dropDict.remove( (long) tmp->w );
329 }
330 }
331 grabFinished();
332 return TRUE;
333 case QEvent::MouseMove:
334 return TRUE;
335 default:
336 break;
337 }
338 return FALSE;
339}
340
341bool QDragger::sendChildEvent( QMouseEvent *e )
342{
343 switch( e->type() ) {
344 case QEvent::MouseButtonDblClick:
345 case QEvent::MouseButtonPress:
346 clickedWidget = cursorWidget();
347 return TRUE;
348 case QEvent::MouseButtonRelease:
349 hostWidget->releaseMouse();
350 if ( clickedWidget ) {
351 DraggedInfo *tmp = draggedDict.find((long) clickedWidget);
352 if( tmp ) {
353 QWidget *parent = tmp->w->parentWidget();
354 sendChildHome( tmp );
355 DropInfo *dri = dropDict.find( (long) parent );
356 if ( dri && noWidgets(dri->w) && !dri->userOpened ) {
357 killDropWindow( dri );
358 dropDict.remove( (long) dri );
359 }
360 }
361 grabFinished();
362 }
363 return TRUE;
364 case QEvent::MouseMove:
365 return TRUE;
366 default:
367 break;
368 }
369 return FALSE;
370}
371
372bool QDragger::startGrab()
373{
374 if ( !hostWidget )
375 return FALSE;
376 clickedWidget = 0;
377 cursor = hostWidget->cursor();
378 hostWidget->grabMouse();
379 hostWidget->setCursor( QCursor( CrossCursor ) );
380 return TRUE;
381}
382
383void QDragger::grabFinished()
384{
385 killingDrop = FALSE;
386 sendingChild = FALSE;
387 if(hostWidget)
388 hostWidget->setCursor( cursor );
389}
390
391void QDragger::closeDropWindow( DropWindow *w )
392{
393 DropInfo *tmp = dropDict.find( (long) w);
394 if( tmp )
395 killDropWindow( tmp );
396}
397
398void QDragger::openDropWindow()
399{
400 QWidget *tmp = openDropWindow( QRect(100, 100, 300, 200), TRUE );
401 tmp->show();
402}
403
404QWidget *QDragger::openDropWindow( const QRect &r, bool user )
405{
406 DropInfo *tmp = new DropInfo;
407 DropWindow *w = new DropWindow;
408 if ( user ) {
409 tmp->userOpened = TRUE;
410 w->setCaption( "Drop window" );
411 } else {
412 tmp->userOpened = FALSE;
413 w->setCaption( "Auto drop window" );
414 }
415 tmp->w = w;
416 w->master = this;
417 w->setGeometry( r );
418 dropDict.insert( (long) w, tmp );
419 w->show();
420 return w;
421}
422
423void QDragger::killDropWindow()
424{
425 if ( startGrab() )
426 killingDrop = TRUE;
427}
428
429void QDragger::killDropWindow( DropInfo *di )
430{
431 const QObjectList *l = di->w->children();
432 if ( !l )
433 return;
434 QObjectListIt iter( *l );
435 QObject *tmp;
436 while( (tmp = iter.current()) ) {
437 ++iter;
438 if ( tmp->isWidgetType() ) {
439 DraggedInfo *dri = draggedDict.find( (long) tmp );
440 if ( dri ) {
441 sendChildHome( dri );
442 draggedDict.remove( (long) tmp );
443 }
444 }
445 }
446 di->w->hide();
447}
448
449void QDragger::killAllDropWindows()
450{
451 killAllDropWindows( FALSE );
452}
453
454void QDragger::killAllDropWindows( bool autoOnly )
455{
456 QIntDictIterator<DropInfo> iter( dropDict );
457
458 DropInfo *tmp;
459 while( (tmp = iter.current()) ) {
460 ++iter;
461 if( !autoOnly || !tmp->userOpened ) {
462 killDropWindow( tmp );
463 dropDict.remove( (long) tmp->w );
464 }
465 }
466}
467
468void QDragger::sendChildHome( DraggedInfo *i )
469{
470 i->w->reparent( i->mother, 0, i->pos, TRUE );
471}
472
473void QDragger::sendChildHome()
474{
475 if ( startGrab() )
476 sendingChild = TRUE;
477}
478
479void QDragger::sendAllChildrenHome()
480{
481 QIntDictIterator<DraggedInfo> iter( draggedDict );
482
483 DraggedInfo *tmp;
484 while( (tmp = iter.current()) ) {
485 ++iter;
486 sendChildHome( tmp );
487 draggedDict.remove( (long) tmp->w );
488 }
489 killAllDropWindows( TRUE );
490 draggedDict.clear();
491}
492
493
494QWidget *cursorWidget( QPoint *p )
495{
496 QPoint curpos = QCursor::pos();
497 if ( p )
498 *p = curpos;
499 return QApplication::widgetAt( curpos );
500}
501
502
503#include "qdragapp.moc"
Note: See TracBrowser for help on using the repository browser.