]> Creatis software - clitk.git/blob - vv/QVTKWidget.cxx
Fixed compilation with VC++ 9
[clitk.git] / vv / QVTKWidget.cxx
1 /*
2
3  * Copyright 2004 Sandia Corporation.
4
5  * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
6
7  * license for use of this work by or on behalf of the
8
9  * U.S. Government. Redistribution and use in source and binary forms, with
10
11  * or without modification, are permitted provided that this Notice and any
12
13  * statement of authorship are reproduced on all copies.
14
15  */
16
17
18
19 /*========================================================================
20
21  For general information about using VTK and Qt, see:
22
23  http://www.trolltech.com/products/3rdparty/vtksupport.html
24
25 =========================================================================*/
26
27
28
29 /*========================================================================
30
31  !!! WARNING for those who want to contribute code to this file.
32
33  !!! If you use a commercial edition of Qt, you can modify this code.
34
35  !!! If you use an open source version of Qt, you are free to modify
36
37  !!! and use this code within the guidelines of the GPL license.
38
39  !!! Unfortunately, you cannot contribute the changes back into this
40
41  !!! file.  Doing so creates a conflict between the GPL and BSD-like VTK
42
43  !!! license.
44
45 =========================================================================*/
46
47
48
49 #ifdef _MSC_VER
50
51 // Disable warnings that Qt headers give.
52
53 #pragma warning(disable:4127)
54
55 #pragma warning(disable:4512)
56
57 #endif
58
59
60
61 #include "QVTKWidget.h"
62
63
64
65 #include "qevent.h"
66
67 #include "qapplication.h"
68
69 #include "qpainter.h"
70
71 #include "qsignalmapper.h"
72
73 #include "qtimer.h"
74
75 #if QT_VERSION >= 0x040000 && defined(Q_WS_X11)
76
77 #include "qx11info_x11.h"
78
79 #endif
80
81
82
83 #include "vtkstd/map"
84
85 #include "vtkInteractorStyleTrackballCamera.h"
86
87 #include "vtkRenderWindow.h"
88
89 #if defined(Q_WS_MAC)
90
91 #  include "vtkCarbonRenderWindow.h"
92
93 #endif
94
95 #include "vtkCommand.h"
96
97 #include "vtkOStrStreamWrapper.h"
98
99 #include "vtkObjectFactory.h"
100
101 #include "vtkCallbackCommand.h"
102
103 #include "vtkConfigure.h"
104
105 #include "vtkToolkits.h"
106
107 #include "vtkUnsignedCharArray.h"
108
109
110
111
112
113 // function to get VTK keysyms from ascii characters
114
115 static const char* ascii_to_key_sym(int);
116
117 // function to get VTK keysyms from Qt keys
118
119 static const char* qt_key_to_key_sym(Qt::Key);
120
121
122
123 // function to dirty cache when a render occurs.
124
125 static void dirty_cache(vtkObject *, unsigned long, void *, void *);
126
127
128
129
130
131
132
133 #if QT_VERSION < 0x040000
134
135 /*! constructor */
136
137 QVTKWidget::QVTKWidget(QWidget* parent, const char* name, Qt::WFlags f)
138
139 #if QT_VERSION < 0x030000
140
141         :
142         QWidget(parent, name, f | 0x10000000)  // WWinOwnDC
143
144 #else
145
146         : QWidget(parent, name, f | Qt::WWinOwnDC )
147
148 #endif
149
150         , mRenWin(NULL),
151
152         cachedImageCleanFlag(false),
153
154         automaticImageCache(false), maxImageCacheRenderRate(1.0)
155
156 {
157
158     // no background
159
160     this->setBackgroundMode( Qt::NoBackground );
161
162
163
164     // default to strong focus
165
166     this->setFocusPolicy(QWidget::StrongFocus);
167
168
169
170     // default to enable mouse events when a mouse button isn't down
171
172     // so we can send enter/leave events to VTK
173
174     this->setMouseTracking(true);
175
176
177
178     // set expanding to take up space for better default layouts
179
180     this->setSizePolicy(
181
182         QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding )
183
184     );
185
186
187
188     this->mCachedImage = vtkUnsignedCharArray::New();
189
190 }
191
192 #endif
193
194
195
196
197
198 #if QT_VERSION >= 0x040000
199
200 /*! constructor */
201
202 QVTKWidget::QVTKWidget(QWidget* p, Qt::WFlags f)
203
204         : QWidget(p, f | Qt::MSWindowsOwnDC), mRenWin(NULL),
205
206         cachedImageCleanFlag(false),
207
208         automaticImageCache(false), maxImageCacheRenderRate(1.0)
209
210
211
212 {
213
214     // no background
215
216     this->setAttribute(Qt::WA_NoBackground);
217
218     // no double buffering
219
220     this->setAttribute(Qt::WA_PaintOnScreen);
221
222
223
224     // default to strong focus
225
226     this->setFocusPolicy(Qt::StrongFocus);
227
228
229
230     // default to enable mouse events when a mouse button isn't down
231
232     // so we can send enter/leave events to VTK
233
234     this->setMouseTracking(true);
235
236
237
238     // set expanding to take up space for better default layouts
239
240     this->setSizePolicy(
241
242         QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding )
243
244     );
245
246
247
248     this->mCachedImage = vtkUnsignedCharArray::New();
249
250
251
252 #if defined(Q_WS_MAC)
253
254     this->DirtyRegionHandler = 0;
255
256     this->DirtyRegionHandlerUPP = 0;
257
258 #endif
259
260
261
262 }
263
264 #endif
265
266
267
268
269
270 /*! destructor */
271
272
273
274 QVTKWidget::~QVTKWidget()
275
276 {
277
278     // get rid of the VTK window
279
280     this->SetRenderWindow(NULL);
281
282
283
284     this->mCachedImage->Delete();
285
286 }
287
288
289
290 /*! get the render window
291
292  */
293
294 vtkRenderWindow* QVTKWidget::GetRenderWindow()
295
296 {
297
298     if (!this->mRenWin)
299
300     {
301
302         // create a default vtk window
303
304         vtkRenderWindow* win = vtkRenderWindow::New();
305
306         this->SetRenderWindow(win);
307
308         win->Delete();
309
310     }
311
312
313
314     return this->mRenWin;
315
316 }
317
318
319
320
321
322
323
324 /*! set the render window
325
326   this will bind a VTK window with the Qt window
327
328   it'll also replace an existing VTK window
329
330 */
331
332 void QVTKWidget::SetRenderWindow(vtkRenderWindow* w)
333
334 {
335
336     // do nothing if we don't have to
337
338     if (w == this->mRenWin)
339
340     {
341
342         return;
343
344     }
345
346
347
348     // unregister previous window
349
350     if (this->mRenWin)
351
352     {
353
354         //clean up window as one could remap it
355
356         if (this->mRenWin->GetMapped())
357
358         {
359
360             this->mRenWin->Finalize();
361
362         }
363
364         this->mRenWin->SetDisplayId(NULL);
365
366         this->mRenWin->SetParentId(NULL);
367
368         this->mRenWin->SetWindowId(NULL);
369
370         this->mRenWin->UnRegister(NULL);
371
372     }
373
374
375
376     // now set the window
377
378     this->mRenWin = w;
379
380
381
382     if (this->mRenWin)
383
384     {
385
386         // register new window
387
388         this->mRenWin->Register(NULL);
389
390
391
392         // if it is mapped somewhere else, unmap it
393
394         if (this->mRenWin->GetMapped())
395
396         {
397
398             this->mRenWin->Finalize();
399
400         }
401
402
403
404 #ifdef Q_WS_X11
405
406         // give the qt display id to the vtk window
407
408 #if QT_VERSION < 0x040000
409
410         this->mRenWin->SetDisplayId( this->x11Display() );
411
412 #else
413
414         this->mRenWin->SetDisplayId(QX11Info::display());
415
416 #endif
417
418 #endif
419
420
421
422         // special x11 setup
423
424         x11_setup_window();
425
426
427
428         // give the qt window id to the vtk window
429
430         this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
431
432
433
434         // mac compatibility issues
435
436 #if defined(Q_WS_MAC) && (QT_VERSION < 0x040000)
437
438         this->mRenWin->SetWindowId( NULL );
439
440         static_cast<vtkCarbonRenderWindow*>(this->mRenWin)->SetRootWindow(
441
442             reinterpret_cast<WindowPtr>(this->handle()));
443
444 #endif
445
446
447
448
449
450         // tell the vtk window what the size of this window is
451
452         this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height());
453
454         this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y());
455
456
457
458         // have VTK start this window and create the necessary graphics resources
459
460         if (isVisible())
461
462         {
463
464             this->mRenWin->Start();
465
466 #if defined (Q_WS_MAC) && (QT_VERSION < 0x040000)
467
468             macFixRect();
469
470 #endif
471
472         }
473
474
475
476         // if an interactor wasn't provided, we'll make one by default
477
478         if (!this->mRenWin->GetInteractor())
479
480         {
481
482             // create a default interactor
483
484             QVTKInteractor* iren = QVTKInteractor::New();
485
486             this->mRenWin->SetInteractor(iren);
487
488             iren->Initialize();
489
490
491
492             // now set the default style
493
494             vtkInteractorStyle* s = vtkInteractorStyleTrackballCamera::New();
495
496             iren->SetInteractorStyle(s);
497
498
499
500             iren->Delete();
501
502             s->Delete();
503
504         }
505
506
507
508         // tell the interactor the size of this window
509
510         this->mRenWin->GetInteractor()->SetSize(this->width(), this->height());
511
512
513
514         // Add an observer to monitor when the image changes.  Should work most
515
516         // of the time.  The application will have to call
517
518         // markCachedImageAsDirty for any other case.
519
520         vtkCallbackCommand *cbc = vtkCallbackCommand::New();
521
522         cbc->SetClientData(this);
523
524         cbc->SetCallback(dirty_cache);
525
526         this->mRenWin->AddObserver(vtkCommand::EndEvent, cbc);
527
528         cbc->Delete();
529
530     }
531
532
533
534 #if defined(Q_WS_MAC) && QT_VERSION >= 0x040000
535
536     if (mRenWin && !this->DirtyRegionHandlerUPP)
537
538     {
539
540         this->DirtyRegionHandlerUPP = NewEventHandlerUPP(QVTKWidget::DirtyRegionProcessor);
541
542         static EventTypeSpec events[] = { {'cute', 20} };
543
544         // kEventClassQt, kEventQtRequestWindowChange from qt_mac_p.h
545
546         // Suggested by Sam Magnuson at Trolltech as best portabile hack
547
548         // around Apple's missing functionality in HI Toolbox.
549
550         InstallEventHandler(GetApplicationEventTarget(), this->DirtyRegionHandlerUPP,
551
552                             GetEventTypeCount(events), events,
553
554                             reinterpret_cast<void*>(this), &this->DirtyRegionHandler);
555
556     }
557
558     else if (!mRenWin && this->DirtyRegionHandlerUPP)
559
560     {
561
562         RemoveEventHandler(this->DirtyRegionHandler);
563
564         DisposeEventHandlerUPP(this->DirtyRegionHandlerUPP);
565
566         this->DirtyRegionHandler = 0;
567
568         this->DirtyRegionHandlerUPP = 0;
569
570     }
571
572 #endif
573
574 }
575
576
577
578
579
580
581
582 /*! get the Qt/VTK interactor
583
584  */
585
586 QVTKInteractor* QVTKWidget::GetInteractor()
587
588 {
589
590     return QVTKInteractor
591
592            ::SafeDownCast(this->GetRenderWindow()->GetInteractor());
593
594 }
595
596
597
598 void QVTKWidget::markCachedImageAsDirty()
599
600 {
601
602     if (this->cachedImageCleanFlag)
603
604     {
605
606         this->cachedImageCleanFlag = false;
607
608         emit cachedImageDirty();
609
610     }
611
612 }
613
614
615
616 void QVTKWidget::saveImageToCache()
617
618 {
619
620     if (this->cachedImageCleanFlag)
621
622     {
623
624         return;
625
626     }
627
628
629
630     this->mRenWin->GetPixelData(0, 0, this->width()-1, this->height()-1, 1,
631
632                                 this->mCachedImage);
633
634     this->cachedImageCleanFlag = true;
635
636     emit cachedImageClean();
637
638 }
639
640
641
642 void QVTKWidget::setAutomaticImageCacheEnabled(bool flag)
643
644 {
645
646     this->automaticImageCache = flag;
647
648     if (!flag)
649
650     {
651
652         this->mCachedImage->Initialize();
653
654     }
655
656 }
657
658 bool QVTKWidget::isAutomaticImageCacheEnabled() const
659
660 {
661
662     return this->automaticImageCache;
663
664 }
665
666
667
668 void QVTKWidget::setMaxRenderRateForImageCache(double rate)
669
670 {
671
672     this->maxImageCacheRenderRate = rate;
673
674 }
675
676 double QVTKWidget::maxRenderRateForImageCache() const
677
678 {
679
680     return this->maxImageCacheRenderRate;
681
682 }
683
684
685
686 vtkUnsignedCharArray* QVTKWidget::cachedImage()
687
688 {
689
690     // Make sure image is up to date.
691
692     this->paintEvent(NULL);
693
694     this->saveImageToCache();
695
696
697
698     return this->mCachedImage;
699
700 }
701
702
703
704 /*! overloaded Qt's event handler to capture additional keys that Qt has
705
706   default behavior for (for example the Tab and Shift-Tab key)
707
708 */
709
710 bool QVTKWidget::event(QEvent* e)
711
712 {
713
714 #if QT_VERSION >= 0x040000
715
716     if (e->type() == QEvent::ParentAboutToChange)
717
718     {
719
720         this->markCachedImageAsDirty();
721
722         if (this->mRenWin)
723
724         {
725
726             // Finalize the window to remove graphics resources associated with
727
728             // this window
729
730             if (this->mRenWin->GetMapped())
731
732             {
733
734                 this->mRenWin->Finalize();
735
736             }
737
738         }
739
740     }
741
742     else if (e->type() == QEvent::ParentChange)
743
744     {
745
746         if (this->mRenWin)
747
748         {
749
750             x11_setup_window();
751
752             // connect to new window
753
754             this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
755
756
757
758             // start up the window to create graphics resources for this window
759
760             if (isVisible())
761
762             {
763
764                 this->mRenWin->Start();
765
766             }
767
768         }
769
770     }
771
772 #endif
773
774
775
776     if (QObject::event(e))
777
778     {
779
780         return TRUE;
781
782     }
783
784
785
786     if (e->type() == QEvent::KeyPress)
787
788     {
789
790         QKeyEvent* ke = static_cast<QKeyEvent*>(e);
791
792         this->keyPressEvent(ke);
793
794         return ke->isAccepted();
795
796     }
797
798
799
800     return QWidget::event(e);
801
802 }
803
804
805
806
807
808 /*! handle resize event
809
810  */
811
812 void QVTKWidget::resizeEvent(QResizeEvent* e)
813
814 {
815
816     QWidget::resizeEvent(e);
817
818
819
820     if (!this->mRenWin)
821
822     {
823
824         return;
825
826     }
827
828
829
830     // give the size to the interactor and vtk window
831
832     this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height());
833
834     if (this->mRenWin->GetInteractor())
835
836     {
837
838         this->mRenWin->GetInteractor()->SetSize(this->width(), this->height());
839
840     }
841
842     this->markCachedImageAsDirty();
843
844
845
846 #if defined (Q_WS_MAC) && (QT_VERSION < 0x040000)
847
848     macFixRect();
849
850 #endif
851
852 }
853
854
855
856 void QVTKWidget::moveEvent(QMoveEvent* e)
857
858 {
859
860     QWidget::moveEvent(e);
861
862
863
864     if (!this->mRenWin)
865
866     {
867
868         return;
869
870     }
871
872
873
874     // give the size to the interactor and vtk window
875
876     this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y());
877
878
879
880 #if defined (Q_WS_MAC) && (QT_VERSION < 0x040000)
881
882     macFixRect();
883
884 #endif
885
886 }
887
888
889
890 /*! handle paint event
891
892  */
893
894 void QVTKWidget::paintEvent(QPaintEvent* )
895
896 {
897
898     vtkRenderWindowInteractor* iren = NULL;
899
900     if (this->mRenWin)
901
902     {
903
904         iren = this->mRenWin->GetInteractor();
905
906     }
907
908
909
910     if (!iren || !iren->GetEnabled())
911
912     {
913
914         return;
915
916     }
917
918
919
920
921
922     // if we have a saved image, use it
923
924     if (this->cachedImageCleanFlag)
925
926     {
927
928         // put cached image into back buffer if we can
929
930         this->mRenWin->SetPixelData(0, 0, this->width()-1, this->height()-1,
931
932                                     this->mCachedImage,
933
934                                     !this->mRenWin->GetDoubleBuffer());
935
936         // swap buffers, if double buffering
937
938         this->mRenWin->Frame();
939
940         // or should we just put it on the front buffer?
941
942         return;
943
944     }
945
946
947
948     iren->Render();
949
950
951
952     // In Qt 4.1+ let's support redirected painting
953
954 #if QT_VERSION >= 0x040100
955
956     // if redirected, let's grab the image from VTK, and paint it to the device
957
958     QPaintDevice* device = QPainter::redirected(this);
959
960     if (device != NULL && device != this)
961
962     {
963
964         int w = this->width();
965
966         int h = this->height();
967
968         QImage img(w, h, QImage::Format_RGB32);
969
970         vtkUnsignedCharArray* pixels = vtkUnsignedCharArray::New();
971
972         pixels->SetArray(img.bits(), w*h*4, 1);
973
974         this->mRenWin->GetRGBACharPixelData(0, 0, w-1, h-1, 1, pixels);
975
976         pixels->Delete();
977
978         img = img.rgbSwapped();
979
980         img = img.mirrored();
981
982
983
984         QPainter painter(this);
985
986         painter.drawImage(QPointF(0.0,0.0), img);
987
988         return;
989
990     }
991
992 #endif
993
994 }
995
996
997
998 /*! handle mouse press event
999
1000  */
1001
1002 void QVTKWidget::mousePressEvent(QMouseEvent* e)
1003
1004 {
1005
1006
1007
1008     // Emit a mouse press event for anyone who might be interested
1009
1010     emit mouseEvent(e);
1011
1012
1013
1014     vtkRenderWindowInteractor* iren = NULL;
1015
1016     if (this->mRenWin)
1017
1018     {
1019
1020         iren = this->mRenWin->GetInteractor();
1021
1022     }
1023
1024
1025
1026     if (!iren || !iren->GetEnabled())
1027
1028     {
1029
1030         return;
1031
1032     }
1033
1034
1035
1036     // give interactor the event information
1037
1038 #if QT_VERSION < 0x040000
1039
1040     iren->SetEventInformationFlipY(e->x(), e->y(),
1041
1042                                    (e->state() & Qt::ControlButton) > 0 ? 1 : 0,
1043
1044                                    (e->state() & Qt::ShiftButton ) > 0 ? 1 : 0, 0,
1045
1046                                    e->type() == QEvent::MouseButtonDblClick ? 1 : 0);
1047
1048 #else
1049
1050     iren->SetEventInformationFlipY(e->x(), e->y(),
1051
1052                                    (e->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0,
1053
1054                                    (e->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0,
1055
1056                                    0,
1057
1058                                    e->type() == QEvent::MouseButtonDblClick ? 1 : 0);
1059
1060 #endif
1061
1062
1063
1064     // invoke appropriate vtk event
1065
1066     switch (e->button())
1067
1068     {
1069
1070     case Qt::LeftButton:
1071
1072         iren->InvokeEvent(vtkCommand::LeftButtonPressEvent, e);
1073
1074         break;
1075
1076
1077
1078     case Qt::MidButton:
1079
1080         iren->InvokeEvent(vtkCommand::MiddleButtonPressEvent, e);
1081
1082         break;
1083
1084
1085
1086     case Qt::RightButton:
1087
1088         iren->InvokeEvent(vtkCommand::RightButtonPressEvent, e);
1089
1090         break;
1091
1092
1093
1094     default:
1095
1096         break;
1097
1098     }
1099
1100 }
1101
1102
1103
1104 /*! handle mouse move event
1105
1106  */
1107
1108 void QVTKWidget::mouseMoveEvent(QMouseEvent* e)
1109
1110 {
1111
1112     vtkRenderWindowInteractor* iren = NULL;
1113
1114     if (this->mRenWin)
1115
1116     {
1117
1118         iren = this->mRenWin->GetInteractor();
1119
1120     }
1121
1122
1123
1124     if (!iren || !iren->GetEnabled())
1125
1126     {
1127
1128         return;
1129
1130     }
1131
1132
1133
1134     // give interactor the event information
1135
1136 #if QT_VERSION < 0x040000
1137
1138     iren->SetEventInformationFlipY(e->x(), e->y(),
1139
1140                                    (e->state() & Qt::ControlButton) > 0 ? 1 : 0,
1141
1142                                    (e->state() & Qt::ShiftButton ) > 0 ? 1 : 0);
1143
1144 #else
1145
1146     iren->SetEventInformationFlipY(e->x(), e->y(),
1147
1148                                    (e->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0,
1149
1150                                    (e->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0);
1151
1152 #endif
1153
1154
1155
1156     // invoke vtk event
1157
1158     iren->InvokeEvent(vtkCommand::MouseMoveEvent, e);
1159
1160 }
1161
1162
1163
1164
1165
1166 /*! handle enter event
1167
1168  */
1169
1170 void QVTKWidget::enterEvent(QEvent* e)
1171
1172 {
1173
1174     vtkRenderWindowInteractor* iren = NULL;
1175
1176     if (this->mRenWin)
1177
1178     {
1179
1180         iren = this->mRenWin->GetInteractor();
1181
1182     }
1183
1184
1185
1186     if (!iren || !iren->GetEnabled())
1187
1188     {
1189
1190         return;
1191
1192     }
1193
1194     this->setFocus();
1195
1196     iren->InvokeEvent(vtkCommand::EnterEvent, e);
1197
1198 }
1199
1200
1201
1202 /*! handle leave event
1203
1204  */
1205
1206 void QVTKWidget::leaveEvent(QEvent* e)
1207
1208 {
1209
1210     vtkRenderWindowInteractor* iren = NULL;
1211
1212     if (this->mRenWin)
1213
1214     {
1215
1216         iren = this->mRenWin->GetInteractor();
1217
1218     }
1219
1220
1221
1222     if (!iren || !iren->GetEnabled())
1223
1224     {
1225
1226         return;
1227
1228     }
1229
1230
1231
1232     iren->InvokeEvent(vtkCommand::LeaveEvent, e);
1233
1234 }
1235
1236
1237
1238 /*! handle mouse release event
1239
1240  */
1241
1242 void QVTKWidget::mouseReleaseEvent(QMouseEvent* e)
1243
1244 {
1245
1246     vtkRenderWindowInteractor* iren = NULL;
1247
1248     if (this->mRenWin)
1249
1250     {
1251
1252         iren = this->mRenWin->GetInteractor();
1253
1254     }
1255
1256
1257
1258     if (!iren || !iren->GetEnabled())
1259
1260     {
1261
1262         return;
1263
1264     }
1265
1266
1267
1268     // give vtk event information
1269
1270 #if QT_VERSION < 0x040000
1271
1272     iren->SetEventInformationFlipY(e->x(), e->y(),
1273
1274                                    (e->state() & Qt::ControlButton) > 0 ? 1 : 0,
1275
1276                                    (e->state() & Qt::ShiftButton ) > 0 ? 1 : 0);
1277
1278 #else
1279
1280     iren->SetEventInformationFlipY(e->x(), e->y(),
1281
1282                                    (e->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0,
1283
1284                                    (e->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0);
1285
1286 #endif
1287
1288
1289
1290     // invoke appropriate vtk event
1291
1292     switch (e->button())
1293
1294     {
1295
1296     case Qt::LeftButton:
1297
1298         iren->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, e);
1299
1300         break;
1301
1302
1303
1304     case Qt::MidButton:
1305
1306         iren->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, e);
1307
1308         break;
1309
1310
1311
1312     case Qt::RightButton:
1313
1314         iren->InvokeEvent(vtkCommand::RightButtonReleaseEvent, e);
1315
1316         break;
1317
1318
1319
1320     default:
1321
1322         break;
1323
1324     }
1325
1326 }
1327
1328
1329
1330 /*! handle key press event
1331
1332  */
1333
1334 void QVTKWidget::keyPressEvent(QKeyEvent* e)
1335
1336 {
1337
1338     vtkRenderWindowInteractor* iren = NULL;
1339
1340     if (this->mRenWin)
1341
1342     {
1343
1344         iren = this->mRenWin->GetInteractor();
1345
1346     }
1347
1348
1349
1350     if (!iren || !iren->GetEnabled())
1351
1352     {
1353
1354         return;
1355
1356     }
1357
1358
1359
1360     // get key and keysym information
1361
1362 #if QT_VERSION < 0x040000
1363
1364     int ascii_key = e->text().length() ? e->text().unicode()->latin1() : 0;
1365
1366 #else
1367
1368     int ascii_key = e->text().length() ? e->text().unicode()->toLatin1() : 0;
1369
1370 #endif
1371
1372     const char* keysym = ascii_to_key_sym(ascii_key);
1373
1374     if (!keysym)
1375
1376     {
1377
1378         // get virtual keys
1379
1380         keysym = qt_key_to_key_sym(static_cast<Qt::Key>(e->key()));
1381
1382     }
1383
1384
1385
1386     if (!keysym)
1387
1388     {
1389
1390         keysym = "None";
1391
1392     }
1393
1394
1395
1396     // give interactor event information
1397
1398 #if QT_VERSION < 0x040000
1399
1400     iren->SetKeyEventInformation(
1401
1402         (e->state() & Qt::ControlButton),
1403
1404         (e->state() & Qt::ShiftButton),
1405
1406         ascii_key, e->count(), keysym);
1407
1408 #else
1409
1410     iren->SetKeyEventInformation(
1411
1412         (e->modifiers() & Qt::ControlModifier),
1413
1414         (e->modifiers() & Qt::ShiftModifier),
1415
1416         ascii_key, e->count(), keysym);
1417
1418 #endif
1419
1420
1421
1422     // invoke vtk event
1423
1424     iren->InvokeEvent(vtkCommand::KeyPressEvent, e);
1425
1426
1427
1428     // invoke char event only for ascii characters
1429
1430     if (ascii_key)
1431
1432     {
1433
1434         iren->InvokeEvent(vtkCommand::CharEvent, e);
1435
1436     }
1437
1438 }
1439
1440
1441
1442 /*! handle key release event
1443
1444  */
1445
1446 void QVTKWidget::keyReleaseEvent(QKeyEvent* e)
1447
1448 {
1449
1450
1451
1452     vtkRenderWindowInteractor* iren = NULL;
1453
1454     if (this->mRenWin)
1455
1456     {
1457
1458         iren = this->mRenWin->GetInteractor();
1459
1460     }
1461
1462
1463
1464     if (!iren || !iren->GetEnabled())
1465
1466     {
1467
1468         return;
1469
1470     }
1471
1472
1473
1474     // get key and keysym info
1475
1476 #if QT_VERSION < 0x040000
1477
1478     int ascii_key = e->text().length() ? e->text().unicode()->latin1() : 0;
1479
1480 #else
1481
1482     int ascii_key = e->text().length() ? e->text().unicode()->toLatin1() : 0;
1483
1484 #endif
1485
1486     const char* keysym = ascii_to_key_sym(ascii_key);
1487
1488     if (!keysym)
1489
1490     {
1491
1492         // get virtual keys
1493
1494         keysym = qt_key_to_key_sym((Qt::Key)e->key());
1495
1496     }
1497
1498
1499
1500     if (!keysym)
1501
1502     {
1503
1504         keysym = "None";
1505
1506     }
1507
1508
1509
1510     // give event information to interactor
1511
1512 #if QT_VERSION < 0x040000
1513
1514     iren->SetKeyEventInformation(
1515
1516         (e->state() & Qt::ControlButton),
1517
1518         (e->state() & Qt::ShiftButton),
1519
1520         ascii_key, e->count(), keysym);
1521
1522 #else
1523
1524     iren->SetKeyEventInformation(
1525
1526         (e->modifiers() & Qt::ControlModifier),
1527
1528         (e->modifiers() & Qt::ShiftModifier),
1529
1530         ascii_key, e->count(), keysym);
1531
1532 #endif
1533
1534
1535
1536     // invoke vtk event
1537
1538     iren->InvokeEvent(vtkCommand::KeyReleaseEvent, e);
1539
1540 }
1541
1542
1543
1544 #ifndef QT_NO_WHEELEVENT
1545
1546 void QVTKWidget::wheelEvent(QWheelEvent* e)
1547
1548 {
1549
1550     vtkRenderWindowInteractor* iren = NULL;
1551
1552     if (this->mRenWin)
1553
1554     {
1555
1556         iren = this->mRenWin->GetInteractor();
1557
1558     }
1559
1560
1561
1562     if (!iren || !iren->GetEnabled())
1563
1564     {
1565
1566         return;
1567
1568     }
1569
1570
1571
1572 // VTK supports wheel mouse events only in version 4.5 or greater
1573
1574     // give event information to interactor
1575
1576 #if QT_VERSION < 0x040000
1577
1578     iren->SetEventInformationFlipY(e->x(), e->y(),
1579
1580                                    (e->state() & Qt::ControlButton) > 0 ? 1 : 0,
1581
1582                                    (e->state() & Qt::ShiftButton ) > 0 ? 1 : 0);
1583
1584 #else
1585
1586     iren->SetEventInformationFlipY(e->x(), e->y(),
1587
1588                                    (e->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0,
1589
1590                                    (e->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0);
1591
1592 #endif
1593
1594
1595
1596     // invoke vtk event
1597
1598     // if delta is positive, it is a forward wheel event
1599
1600     if (e->delta() > 0)
1601
1602     {
1603
1604         iren->InvokeEvent(vtkCommand::MouseWheelForwardEvent, e);
1605
1606     }
1607
1608     else
1609
1610     {
1611
1612         iren->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, e);
1613
1614     }
1615
1616 }
1617
1618 #endif
1619
1620
1621
1622 void QVTKWidget::focusInEvent(QFocusEvent*)
1623
1624 {
1625
1626     // These prevent updates when the window
1627
1628     // gains or loses focus.  By default, Qt
1629
1630     // does an update because the color group's
1631
1632     // active status changes.  We don't even use
1633
1634     // color groups so we do nothing here.
1635
1636 }
1637
1638
1639
1640 void QVTKWidget::focusOutEvent(QFocusEvent*)
1641
1642 {
1643
1644     // These prevent updates when the window
1645
1646     // gains or loses focus.  By default, Qt
1647
1648     // does an update because the color group's
1649
1650     // active status changes.  We don't even use
1651
1652     // color groups so we do nothing here.
1653
1654 }
1655
1656
1657
1658
1659
1660 void QVTKWidget::contextMenuEvent(QContextMenuEvent* e)
1661
1662 {
1663
1664     vtkRenderWindowInteractor* iren = NULL;
1665
1666     if (this->mRenWin)
1667
1668     {
1669
1670         iren = this->mRenWin->GetInteractor();
1671
1672     }
1673
1674
1675
1676     if (!iren || !iren->GetEnabled())
1677
1678     {
1679
1680         return;
1681
1682     }
1683
1684
1685
1686     // give interactor the event information
1687
1688 #if QT_VERSION < 0x040000
1689
1690     iren->SetEventInformationFlipY(e->x(), e->y(),
1691
1692                                    (e->state() & Qt::ControlButton) > 0 ? 1 : 0,
1693
1694                                    (e->state() & Qt::ShiftButton ) > 0 ? 1 : 0);
1695
1696 #else
1697
1698     iren->SetEventInformationFlipY(e->x(), e->y(),
1699
1700                                    (e->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0,
1701
1702                                    (e->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0);
1703
1704 #endif
1705
1706
1707
1708     // invoke event and pass qt event for additional data as well
1709
1710     iren->InvokeEvent(QVTKWidget::ContextMenuEvent, e);
1711
1712
1713
1714 }
1715
1716
1717
1718 void QVTKWidget::dragEnterEvent(QDragEnterEvent* e)
1719
1720 {
1721
1722     vtkRenderWindowInteractor* iren = NULL;
1723
1724     if (this->mRenWin)
1725
1726     {
1727
1728         iren = this->mRenWin->GetInteractor();
1729
1730     }
1731
1732
1733
1734     if (!iren || !iren->GetEnabled())
1735
1736     {
1737
1738         return;
1739
1740     }
1741
1742
1743
1744     // invoke event and pass qt event for additional data as well
1745
1746     iren->InvokeEvent(QVTKWidget::DragEnterEvent, e);
1747
1748 }
1749
1750
1751
1752 void QVTKWidget::dragMoveEvent(QDragMoveEvent* e)
1753
1754 {
1755
1756     vtkRenderWindowInteractor* iren = NULL;
1757
1758     if (this->mRenWin)
1759
1760     {
1761
1762         iren = this->mRenWin->GetInteractor();
1763
1764     }
1765
1766
1767
1768     if (!iren || !iren->GetEnabled())
1769
1770     {
1771
1772         return;
1773
1774     }
1775
1776
1777
1778     // give interactor the event information
1779
1780     iren->SetEventInformationFlipY(e->pos().x(), e->pos().y());
1781
1782
1783
1784     // invoke event and pass qt event for additional data as well
1785
1786     iren->InvokeEvent(QVTKWidget::DragMoveEvent, e);
1787
1788 }
1789
1790
1791
1792 void QVTKWidget::dragLeaveEvent(QDragLeaveEvent* e)
1793
1794 {
1795
1796     vtkRenderWindowInteractor* iren = NULL;
1797
1798     if (this->mRenWin)
1799
1800     {
1801
1802         iren = this->mRenWin->GetInteractor();
1803
1804     }
1805
1806
1807
1808     if (!iren || !iren->GetEnabled())
1809
1810     {
1811
1812         return;
1813
1814     }
1815
1816
1817
1818     // invoke event and pass qt event for additional data as well
1819
1820     iren->InvokeEvent(QVTKWidget::DragLeaveEvent, e);
1821
1822 }
1823
1824
1825
1826 void QVTKWidget::dropEvent(QDropEvent* e)
1827
1828 {
1829
1830     vtkRenderWindowInteractor* iren = NULL;
1831
1832     if (this->mRenWin)
1833
1834     {
1835
1836         iren = this->mRenWin->GetInteractor();
1837
1838     }
1839
1840
1841
1842     if (!iren || !iren->GetEnabled())
1843
1844     {
1845
1846         return;
1847
1848     }
1849
1850
1851
1852     // give interactor the event information
1853
1854     iren->SetEventInformationFlipY(e->pos().x(), e->pos().y());
1855
1856
1857
1858     // invoke event and pass qt event for additional data as well
1859
1860     iren->InvokeEvent(QVTKWidget::DropEvent, e);
1861
1862 }
1863
1864
1865
1866
1867
1868 /*! handle reparenting of widgets
1869
1870  */
1871
1872 #if QT_VERSION < 0x040000
1873
1874 void QVTKWidget::reparent(QWidget* parent, Qt::WFlags f, const QPoint& p, bool showit)
1875
1876 {
1877
1878     this->markCachedImageAsDirty();
1879
1880
1881
1882     if (this->mRenWin)
1883
1884     {
1885
1886         // Finalize the window to remove graphics resources associated with
1887
1888         // this window
1889
1890         if (this->mRenWin->GetMapped())
1891
1892         {
1893
1894             this->mRenWin->Finalize();
1895
1896         }
1897
1898
1899
1900         // have QWidget reparent as normal, but don't show
1901
1902         QWidget::reparent(parent, f, p, false);
1903
1904
1905
1906         x11_setup_window();
1907
1908
1909
1910         // connect to new window
1911
1912 #if defined(Q_WS_MAC)
1913
1914         static_cast<vtkCarbonRenderWindow*>(this->mRenWin)->SetRootWindow(
1915
1916             reinterpret_cast<WindowPtr>(this->handle()));
1917
1918
1919
1920 #else
1921
1922         this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
1923
1924 #endif
1925
1926
1927
1928         // start up the window to create graphics resources for this window
1929
1930         if (isVisible())
1931
1932         {
1933
1934             this->mRenWin->Start();
1935
1936         }
1937
1938     }
1939
1940
1941
1942     // show if requested
1943
1944     if (showit)
1945
1946     {
1947
1948         show();
1949
1950     }
1951
1952 }
1953
1954 #endif
1955
1956
1957
1958 void QVTKWidget::showEvent(QShowEvent* e)
1959
1960 {
1961
1962     this->markCachedImageAsDirty();
1963
1964
1965
1966     QWidget::showEvent(e);
1967
1968 }
1969
1970
1971
1972 QPaintEngine* QVTKWidget::paintEngine() const
1973
1974 {
1975
1976     return NULL;
1977
1978 }
1979
1980
1981
1982 class QVTKInteractorInternal : public QObject
1983
1984 {
1985
1986 public:
1987
1988     QVTKInteractorInternal(QObject* p)
1989
1990             : QObject(p)
1991
1992     {
1993
1994         this->SignalMapper = new QSignalMapper(this);
1995
1996     }
1997
1998     ~QVTKInteractorInternal()
1999
2000     {
2001
2002     }
2003
2004     QSignalMapper* SignalMapper;
2005
2006     typedef vtkstd::map<int, QTimer*> TimerMap;
2007
2008     TimerMap Timers;
2009
2010 };
2011
2012
2013
2014
2015
2016 /*! allocation method for Qt/VTK interactor
2017
2018  */
2019
2020 vtkStandardNewMacro(QVTKInteractor);
2021
2022
2023
2024 /*! constructor for Qt/VTK interactor
2025
2026  */
2027
2028 QVTKInteractor::QVTKInteractor()
2029
2030 {
2031
2032     this->Internal = new QVTKInteractorInternal(this);
2033
2034     QObject::connect(this->Internal->SignalMapper, SIGNAL(mapped(int)), this, SLOT(TimerEvent(int)) );
2035
2036 }
2037
2038
2039
2040 /*! start method for interactor
2041
2042  */
2043
2044 void QVTKInteractor::Start()
2045
2046 {
2047
2048     vtkErrorMacro(<<"QVTKInteractor cannot control the event loop.");
2049
2050 }
2051
2052
2053
2054 /*! terminate the application
2055
2056  */
2057
2058 void QVTKInteractor::TerminateApp()
2059
2060 {
2061
2062     // we are in a GUI so let's terminate the GUI the normal way
2063
2064     //qApp->exit();
2065
2066 }
2067
2068
2069
2070
2071
2072 /*! handle timer event
2073
2074  */
2075
2076 void QVTKInteractor::TimerEvent(int timerId)
2077
2078 {
2079
2080     if ( !this->GetEnabled() )
2081
2082     {
2083
2084         return;
2085
2086     }
2087
2088     this->InvokeEvent(vtkCommand::TimerEvent, (void*)&timerId);
2089
2090
2091
2092     if (this->IsOneShotTimer(timerId))
2093
2094     {
2095
2096         this->DestroyTimer(timerId);  // 'cause our Qt timers are always repeating
2097
2098     }
2099
2100 }
2101
2102
2103
2104 /*! constructor
2105
2106  */
2107
2108 QVTKInteractor::~QVTKInteractor()
2109
2110 {
2111
2112 }
2113
2114
2115
2116 /*! create Qt timer with an interval of 10 msec.
2117
2118  */
2119
2120 int QVTKInteractor::InternalCreateTimer(int timerId, int vtkNotUsed(timerType), unsigned long duration)
2121
2122 {
2123
2124     QTimer* timer = new QTimer(this);
2125
2126     timer->start(duration);
2127
2128     this->Internal->SignalMapper->setMapping(timer, timerId);
2129
2130     QObject::connect(timer, SIGNAL(timeout()), this->Internal->SignalMapper, SLOT(map()));
2131
2132     int platformTimerId = timer->timerId();
2133
2134     this->Internal->Timers.insert(QVTKInteractorInternal::TimerMap::value_type(platformTimerId, timer));
2135
2136     return platformTimerId;
2137
2138 }
2139
2140
2141
2142 /*! destroy timer
2143
2144  */
2145
2146 int QVTKInteractor::InternalDestroyTimer(int platformTimerId)
2147
2148 {
2149
2150     QVTKInteractorInternal::TimerMap::iterator iter = this->Internal->Timers.find(platformTimerId);
2151
2152     if (iter != this->Internal->Timers.end())
2153
2154     {
2155
2156         iter->second->stop();
2157
2158         delete iter->second;
2159
2160         this->Internal->Timers.erase(iter);
2161
2162         return 1;
2163
2164     }
2165
2166     return 0;
2167
2168 }
2169
2170
2171
2172
2173
2174 // ***** keysym stuff below  *****
2175
2176
2177
2178 static const char *AsciiToKeySymTable[] = {
2179
2180     0, 0, 0, 0, 0, 0, 0, 0, 0, "Tab", 0, 0, 0, 0, 0, 0,
2181
2182     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2183
2184     "space", "exclam", "quotedbl", "numbersign",
2185
2186     "dollar", "percent", "ampersand", "quoteright",
2187
2188     "parenleft", "parenright", "asterisk", "plus",
2189
2190     "comma", "minus", "period", "slash",
2191
2192     "0", "1", "2", "3", "4", "5", "6", "7",
2193
2194     "8", "9", "colon", "semicolon", "less", "equal", "greater", "question",
2195
2196     "at", "A", "B", "C", "D", "E", "F", "G",
2197
2198     "H", "I", "J", "K", "L", "M", "N", "O",
2199
2200     "P", "Q", "R", "S", "T", "U", "V", "W",
2201
2202     "X", "Y", "Z", "bracketleft",
2203
2204     "backslash", "bracketright", "asciicircum", "underscore",
2205
2206     "quoteleft", "a", "b", "c", "d", "e", "f", "g",
2207
2208     "h", "i", "j", "k", "l", "m", "n", "o",
2209
2210     "p", "q", "r", "s", "t", "u", "v", "w",
2211
2212     "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete",
2213
2214     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2215
2216     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2217
2218     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2219
2220     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2221
2222     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2223
2224     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2225
2226     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2227
2228     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2229 };
2230
2231
2232
2233 const char* ascii_to_key_sym(int i)
2234
2235 {
2236
2237     if (i >= 0)
2238
2239     {
2240
2241         return AsciiToKeySymTable[i];
2242
2243     }
2244
2245     return 0;
2246
2247 }
2248
2249
2250
2251 #define QVTK_HANDLE(x,y) \
2252   case x : \
2253     ret = y; \
2254     break;
2255
2256
2257
2258 const char* qt_key_to_key_sym(Qt::Key i)
2259
2260 {
2261
2262     const char* ret = 0;
2263
2264     switch (i)
2265
2266     {
2267
2268         // Cancel
2269
2270         QVTK_HANDLE(Qt::Key_Backspace, "BackSpace")
2271
2272         QVTK_HANDLE(Qt::Key_Tab, "Tab")
2273
2274 #if QT_VERSION < 0x040000
2275
2276         QVTK_HANDLE(Qt::Key_BackTab, "Tab")
2277
2278 #else
2279
2280         QVTK_HANDLE(Qt::Key_Backtab, "Tab")
2281
2282 #endif
2283
2284         //QVTK_HANDLE(Qt::Key_Clear, "Clear")
2285
2286         QVTK_HANDLE(Qt::Key_Return, "Return")
2287
2288         QVTK_HANDLE(Qt::Key_Enter, "Return")
2289
2290         QVTK_HANDLE(Qt::Key_Shift, "Shift_L")
2291
2292         QVTK_HANDLE(Qt::Key_Control, "Control_L")
2293
2294         QVTK_HANDLE(Qt::Key_Alt, "Alt_L")
2295
2296         QVTK_HANDLE(Qt::Key_Pause, "Pause")
2297
2298         QVTK_HANDLE(Qt::Key_CapsLock, "Caps_Lock")
2299
2300         QVTK_HANDLE(Qt::Key_Escape, "Escape")
2301
2302         QVTK_HANDLE(Qt::Key_Space, "space")
2303
2304         //QVTK_HANDLE(Qt::Key_Prior, "Prior")
2305
2306         //QVTK_HANDLE(Qt::Key_Next, "Next")
2307
2308         QVTK_HANDLE(Qt::Key_End, "End")
2309
2310         QVTK_HANDLE(Qt::Key_Home, "Home")
2311
2312         QVTK_HANDLE(Qt::Key_Left, "Left")
2313
2314         QVTK_HANDLE(Qt::Key_Up, "Up")
2315
2316         QVTK_HANDLE(Qt::Key_Right, "Right")
2317
2318         QVTK_HANDLE(Qt::Key_Down, "Down")
2319
2320
2321
2322         // Select
2323
2324         // Execute
2325
2326         QVTK_HANDLE(Qt::Key_SysReq, "Snapshot")
2327
2328         QVTK_HANDLE(Qt::Key_Insert, "Insert")
2329
2330         QVTK_HANDLE(Qt::Key_Delete, "Delete")
2331
2332         QVTK_HANDLE(Qt::Key_Help, "Help")
2333
2334         QVTK_HANDLE(Qt::Key_0, "0")
2335
2336         QVTK_HANDLE(Qt::Key_1, "1")
2337
2338         QVTK_HANDLE(Qt::Key_2, "2")
2339
2340         QVTK_HANDLE(Qt::Key_3, "3")
2341
2342         QVTK_HANDLE(Qt::Key_4, "4")
2343
2344         QVTK_HANDLE(Qt::Key_5, "5")
2345
2346         QVTK_HANDLE(Qt::Key_6, "6")
2347
2348         QVTK_HANDLE(Qt::Key_7, "7")
2349
2350         QVTK_HANDLE(Qt::Key_8, "8")
2351
2352         QVTK_HANDLE(Qt::Key_9, "9")
2353
2354         QVTK_HANDLE(Qt::Key_A, "a")
2355
2356         QVTK_HANDLE(Qt::Key_B, "b")
2357
2358         QVTK_HANDLE(Qt::Key_C, "c")
2359
2360         QVTK_HANDLE(Qt::Key_D, "d")
2361
2362         QVTK_HANDLE(Qt::Key_E, "e")
2363
2364         QVTK_HANDLE(Qt::Key_F, "f")
2365
2366         QVTK_HANDLE(Qt::Key_G, "g")
2367
2368         QVTK_HANDLE(Qt::Key_H, "h")
2369
2370         QVTK_HANDLE(Qt::Key_I, "i")
2371
2372         QVTK_HANDLE(Qt::Key_J, "h")
2373
2374         QVTK_HANDLE(Qt::Key_K, "k")
2375
2376         QVTK_HANDLE(Qt::Key_L, "l")
2377
2378         QVTK_HANDLE(Qt::Key_M, "m")
2379
2380         QVTK_HANDLE(Qt::Key_N, "n")
2381
2382         QVTK_HANDLE(Qt::Key_O, "o")
2383
2384         QVTK_HANDLE(Qt::Key_P, "p")
2385
2386         QVTK_HANDLE(Qt::Key_Q, "q")
2387
2388         QVTK_HANDLE(Qt::Key_R, "r")
2389
2390         QVTK_HANDLE(Qt::Key_S, "s")
2391
2392         QVTK_HANDLE(Qt::Key_T, "t")
2393
2394         QVTK_HANDLE(Qt::Key_U, "u")
2395
2396         QVTK_HANDLE(Qt::Key_V, "v")
2397
2398         QVTK_HANDLE(Qt::Key_W, "w")
2399
2400         QVTK_HANDLE(Qt::Key_X, "x")
2401
2402         QVTK_HANDLE(Qt::Key_Y, "y")
2403
2404         QVTK_HANDLE(Qt::Key_Z, "z")
2405
2406         // KP_0 - KP_9
2407
2408         QVTK_HANDLE(Qt::Key_Asterisk, "asterisk")
2409
2410         QVTK_HANDLE(Qt::Key_Plus, "plus")
2411
2412         // bar
2413
2414         QVTK_HANDLE(Qt::Key_Minus, "minus")
2415
2416         QVTK_HANDLE(Qt::Key_Period, "period")
2417
2418         QVTK_HANDLE(Qt::Key_Slash, "slash")
2419
2420         QVTK_HANDLE(Qt::Key_F1, "F1")
2421
2422         QVTK_HANDLE(Qt::Key_F2, "F2")
2423
2424         QVTK_HANDLE(Qt::Key_F3, "F3")
2425
2426         QVTK_HANDLE(Qt::Key_F4, "F4")
2427
2428         QVTK_HANDLE(Qt::Key_F5, "F5")
2429
2430         QVTK_HANDLE(Qt::Key_F6, "F6")
2431
2432         QVTK_HANDLE(Qt::Key_F7, "F7")
2433
2434         QVTK_HANDLE(Qt::Key_F8, "F8")
2435
2436         QVTK_HANDLE(Qt::Key_F9, "F9")
2437
2438         QVTK_HANDLE(Qt::Key_F10, "F10")
2439
2440         QVTK_HANDLE(Qt::Key_F11, "F11")
2441
2442         QVTK_HANDLE(Qt::Key_F12, "F12")
2443
2444         QVTK_HANDLE(Qt::Key_F13, "F13")
2445
2446         QVTK_HANDLE(Qt::Key_F14, "F14")
2447
2448         QVTK_HANDLE(Qt::Key_F15, "F15")
2449
2450         QVTK_HANDLE(Qt::Key_F16, "F16")
2451
2452         QVTK_HANDLE(Qt::Key_F17, "F17")
2453
2454         QVTK_HANDLE(Qt::Key_F18, "F18")
2455
2456         QVTK_HANDLE(Qt::Key_F19, "F19")
2457
2458         QVTK_HANDLE(Qt::Key_F20, "F20")
2459
2460         QVTK_HANDLE(Qt::Key_F21, "F21")
2461
2462         QVTK_HANDLE(Qt::Key_F22, "F22")
2463
2464         QVTK_HANDLE(Qt::Key_F23, "F23")
2465
2466         QVTK_HANDLE(Qt::Key_F24, "F24")
2467
2468         QVTK_HANDLE(Qt::Key_NumLock, "Num_Lock")
2469
2470         QVTK_HANDLE(Qt::Key_ScrollLock, "Scroll_Lock")
2471
2472
2473
2474     default:
2475
2476         break;
2477
2478     }
2479
2480     return ret;
2481
2482 }
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492 // X11 stuff near the bottom of the file
2493
2494 // to prevent namespace collisions with Qt headers
2495
2496
2497
2498 #if defined Q_WS_X11
2499
2500 #if defined(VTK_USE_OPENGL_LIBRARY)
2501
2502 #include "vtkXOpenGLRenderWindow.h"
2503
2504 #endif
2505
2506 #ifdef VTK_USE_MANGLED_MESA
2507
2508 #include "vtkXMesaRenderWindow.h"
2509
2510 #endif
2511
2512 #endif
2513
2514
2515
2516
2517
2518 void QVTKWidget::x11_setup_window()
2519
2520 {
2521
2522 #if defined Q_WS_X11
2523
2524
2525
2526     // this whole function is to allow this window to have a
2527
2528     // different colormap and visual than the rest of the Qt application
2529
2530     // this is very important if Qt's default visual and colormap is
2531
2532     // not enough to get a decent graphics window
2533
2534
2535
2536
2537
2538     // save widget states
2539
2540     bool tracking = this->hasMouseTracking();
2541
2542 #if QT_VERSION < 0x040000
2543
2544     FocusPolicy focus_policy = focusPolicy();
2545
2546 #else
2547
2548     Qt::FocusPolicy focus_policy = focusPolicy();
2549
2550 #endif
2551
2552     bool visible = isVisible();
2553
2554     if (visible)
2555
2556     {
2557
2558         hide();
2559
2560     }
2561
2562
2563
2564
2565
2566     // get visual and colormap from VTK
2567
2568     XVisualInfo* vi = 0;
2569
2570     Colormap cmap = 0;
2571
2572     Display* display = reinterpret_cast<Display*>(mRenWin->GetGenericDisplayId());
2573
2574
2575
2576     // check ogl and mesa and get information we need to create a decent window
2577
2578 #if defined(VTK_USE_OPENGL_LIBRARY)
2579
2580     vtkXOpenGLRenderWindow* ogl_win = vtkXOpenGLRenderWindow::SafeDownCast(mRenWin);
2581
2582     if (ogl_win)
2583
2584     {
2585
2586         vi = ogl_win->GetDesiredVisualInfo();
2587
2588         cmap = ogl_win->GetDesiredColormap();
2589
2590     }
2591
2592 #endif
2593
2594 #ifdef VTK_USE_MANGLED_MESA
2595
2596     if (!vi)
2597
2598     {
2599
2600         vtkXMesaRenderWindow* mgl_win = vtkXMesaRenderWindow::SafeDownCast(mRenWin);
2601
2602         if (mgl_win)
2603
2604         {
2605
2606             vi = mgl_win->GetDesiredVisualInfo();
2607
2608             cmap = mgl_win->GetDesiredColormap();
2609
2610         }
2611
2612     }
2613
2614 #endif
2615
2616
2617
2618     // can't get visual, oh well.
2619
2620     // continue with Qt's default visual as it usually works
2621
2622     if (!vi)
2623
2624     {
2625
2626         if (visible)
2627
2628         {
2629
2630             show();
2631
2632         }
2633
2634         return;
2635
2636     }
2637
2638
2639
2640     // create the X window based on information VTK gave us
2641
2642     XSetWindowAttributes attrib;
2643
2644     attrib.colormap = cmap;
2645
2646     attrib.border_pixel = BlackPixel(display, DefaultScreen(display));
2647
2648
2649
2650     Window p = RootWindow(display, DefaultScreen(display));
2651
2652     if (parentWidget())
2653
2654     {
2655
2656         p = parentWidget()->winId();
2657
2658     }
2659
2660
2661
2662     XWindowAttributes a;
2663
2664     XGetWindowAttributes(display, this->winId(), &a);
2665
2666
2667
2668     Window win = XCreateWindow(display, p, a.x, a.y, a.width, a.height,
2669
2670                                0, vi->depth, InputOutput, vi->visual,
2671
2672                                CWBorderPixel|CWColormap, &attrib);
2673
2674
2675
2676     // backup colormap stuff
2677
2678     Window *cmw;
2679
2680     Window *cmwret;
2681
2682     int count;
2683
2684     if ( XGetWMColormapWindows(display, topLevelWidget()->winId(), &cmwret, &count) )
2685
2686     {
2687
2688         cmw = new Window[count+1];
2689
2690         memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count );
2691
2692         XFree( (char *)cmwret );
2693
2694         int i;
2695
2696         for ( i=0; i<count; i++ )
2697
2698         {
2699
2700             if ( cmw[i] == winId() )
2701
2702             {
2703
2704                 cmw[i] = win;
2705
2706                 break;
2707
2708             }
2709
2710         }
2711
2712         if ( i >= count )
2713
2714         {
2715
2716             cmw[count++] = win;
2717
2718         }
2719
2720     }
2721
2722     else
2723
2724     {
2725
2726         count = 1;
2727
2728         cmw = new Window[count];
2729
2730         cmw[0] = win;
2731
2732     }
2733
2734
2735
2736
2737
2738     // tell Qt to initialize anything it needs to for this window
2739
2740     create(win);
2741
2742
2743
2744     // restore colormaps
2745
2746     XSetWMColormapWindows( display, topLevelWidget()->winId(), cmw, count );
2747
2748
2749
2750     delete [] cmw;
2751
2752
2753
2754     XFlush(display);
2755
2756
2757
2758     // restore widget states
2759
2760     this->setMouseTracking(tracking);
2761
2762 #if QT_VERSION < 0x040000
2763
2764     this->setBackgroundMode( Qt::NoBackground );
2765
2766 #else
2767
2768     this->setAttribute(Qt::WA_NoBackground);
2769
2770     this->setAttribute(Qt::WA_PaintOnScreen);
2771
2772 #endif
2773
2774     this->setFocusPolicy(focus_policy);
2775
2776     if (visible)
2777
2778     {
2779
2780         show();
2781
2782     }
2783
2784
2785
2786 #endif
2787
2788 }
2789
2790
2791
2792 #if defined (Q_WS_MAC) && QT_VERSION >= 0x040000
2793
2794 OSStatus QVTKWidget::DirtyRegionProcessor(EventHandlerCallRef, EventRef event, void* wid)
2795
2796 {
2797
2798     QVTKWidget* widget = reinterpret_cast<QVTKWidget*>(wid);
2799
2800     UInt32 event_kind = GetEventKind(event);
2801
2802     UInt32 event_class = GetEventClass(event);
2803
2804     if (event_class == 'cute' && event_kind == 20)
2805
2806     {
2807
2808         static_cast<vtkCarbonRenderWindow*>(widget->GetRenderWindow())->UpdateGLRegion();
2809
2810     }
2811
2812     return eventNotHandledErr;
2813
2814 }
2815
2816
2817
2818 #endif
2819
2820
2821
2822 #if defined (Q_WS_MAC) && QT_VERSION < 0x040000
2823
2824
2825
2826 // gotta do some special stuff on the MAC to make it work right
2827
2828 // this stuff will need changing when using Qt4 with HIViews
2829
2830
2831
2832 #include <AGL/agl.h>
2833
2834
2835
2836 void QVTKWidget::macFixRect()
2837
2838 {
2839
2840     AGLContext context = static_cast<vtkCarbonRenderWindow*>(this->GetRenderWindow())->GetContextId();
2841
2842
2843
2844     if (!this->isTopLevel())
2845
2846     {
2847
2848         GLint bufRect[4];
2849
2850
2851
2852         // always do AGL_BUFFER_RECT if we have a parent
2853
2854         if (!aglIsEnabled(context, AGL_BUFFER_RECT))
2855
2856             aglEnable(context, AGL_BUFFER_RECT);
2857
2858
2859
2860         // get the clip region
2861
2862         QRegion clip = this->clippedRegion();
2863
2864         QRect clip_rect = clip.boundingRect();
2865
2866
2867
2868         // get the position of this widget with respect to the top level widget
2869
2870         QPoint mp(posInWindow(this));
2871
2872         int win_height = this->topLevelWidget()->height();
2873
2874         win_height -= win_height - this->topLevelWidget()->clippedRegion(FALSE).boundingRect().height();
2875
2876
2877
2878         // give the position and size to agl
2879
2880         bufRect[0] = mp.x();
2881
2882         bufRect[1] = win_height -(mp.y() + this->height());
2883
2884         bufRect[2] = this->width();
2885
2886         bufRect[3] = this->height();
2887
2888         aglSetInteger(context, AGL_BUFFER_RECT, bufRect);
2889
2890
2891
2892         if (clip_rect.isEmpty())
2893
2894         {
2895
2896             // no clipping, disable it
2897
2898             if (!aglIsEnabled(context, AGL_CLIP_REGION))
2899
2900                 aglDisable(context, AGL_CLIP_REGION);
2901
2902
2903
2904             bufRect[0] = 0;
2905
2906             bufRect[1] = 0;
2907
2908             bufRect[2] = 0;
2909
2910             bufRect[3] = 0;
2911
2912             aglSetInteger(context, AGL_BUFFER_RECT, bufRect);
2913
2914         }
2915
2916         else
2917
2918         {
2919
2920             // we are clipping, so lets enable it
2921
2922             if (!aglIsEnabled(context, AGL_CLIP_REGION))
2923
2924                 aglEnable(context, AGL_CLIP_REGION);
2925
2926
2927
2928             // give agl the clip region
2929
2930             aglSetInteger(context, AGL_CLIP_REGION, (const GLint*)clip.handle(TRUE));
2931
2932         }
2933
2934     }
2935
2936
2937
2938     // update the context
2939
2940     aglUpdateContext(context);
2941
2942 }
2943
2944
2945
2946 void QVTKWidget::setRegionDirty(bool b)
2947
2948 {
2949
2950     // the region is dirty and needs redrawn, but not yet
2951
2952     // signal that it needs to be done when it is possible
2953
2954     QWidget::setRegionDirty(b);
2955
2956     QTimer::singleShot(1, this, SLOT(internalMacFixRect()));
2957
2958
2959
2960 }
2961
2962
2963
2964 void QVTKWidget::macWidgetChangedWindow()
2965
2966 {
2967
2968     macFixRect();
2969
2970 }
2971
2972 #endif
2973
2974
2975
2976 // slot to update the draw region and draw the scene
2977
2978 void QVTKWidget::internalMacFixRect()
2979
2980 {
2981
2982 #if defined(Q_WS_MAC) && QT_VERSION < 0x040000
2983
2984     this->macFixRect();
2985
2986     this->update();
2987
2988 #endif
2989
2990 }
2991
2992
2993
2994 static void dirty_cache(vtkObject *caller, unsigned long,
2995
2996                         void *clientdata, void *)
2997
2998 {
2999
3000     QVTKWidget *widget = reinterpret_cast<QVTKWidget *>(clientdata);
3001
3002     widget->markCachedImageAsDirty();
3003
3004
3005
3006     vtkRenderWindow *renwin = vtkRenderWindow::SafeDownCast(caller);
3007
3008     if (renwin)
3009
3010     {
3011
3012         if (   widget->isAutomaticImageCacheEnabled()
3013
3014                 && (  renwin->GetDesiredUpdateRate()
3015
3016                       < widget->maxRenderRateForImageCache() ) )
3017
3018         {
3019
3020             widget->saveImageToCache();
3021
3022         }
3023
3024     }
3025
3026 }
3027
3028
3029