1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/qt/window.cpp
3 // Author: Peter Most, Javier Torres, Mariano Reingart
4 // Copyright: (c) 2010 wxWidgets dev team
5 // Licence: wxWindows licence
6 /////////////////////////////////////////////////////////////////////////////
7
8 // For compilers that support precompilation, includes "wx.h".
9 #include "wx/wxprec.h"
10
11
12 #include <QtGui/QPicture>
13 #include <QtGui/QPainter>
14 #include <QtWidgets/QScrollBar>
15 #include <QtWidgets/QGridLayout>
16 #include <QtWidgets/QApplication>
17 #include <QtWidgets/QWidget>
18 #include <QtWidgets/QScrollArea>
19 #include <QtWidgets/QMenu>
20 #include <QtWidgets/QShortcut>
21
22 #ifndef WX_PRECOMP
23 #include "wx/dcclient.h"
24 #include "wx/frame.h"
25 #include "wx/log.h"
26 #include "wx/menu.h"
27 #include "wx/scrolbar.h"
28 #endif // WX_PRECOMP
29
30 #include "wx/window.h"
31 #include "wx/dnd.h"
32 #include "wx/tooltip.h"
33 #include "wx/qt/private/utils.h"
34 #include "wx/qt/private/converter.h"
35 #include "wx/qt/private/winevent.h"
36
37 #define VERT_SCROLLBAR_POSITION 0, 1
38 #define HORZ_SCROLLBAR_POSITION 1, 0
39
40 #define TRACE_QT_WINDOW "qtwindow"
41
42 // Base Widget helper (no scrollbar, used by wxWindow)
43
44 class wxQtWidget : public wxQtEventSignalHandler< QWidget, wxWindowQt >
45 {
46 public:
47 wxQtWidget( wxWindowQt *parent, wxWindowQt *handler );
48 };
49
wxQtWidget(wxWindowQt * parent,wxWindowQt * handler)50 wxQtWidget::wxQtWidget( wxWindowQt *parent, wxWindowQt *handler )
51 : wxQtEventSignalHandler< QWidget, wxWindowQt >( parent, handler )
52 {
53 }
54
55 // Scroll Area helper (container to show scroll bars for wxScrolledWindow):
56
57 class wxQtScrollArea : public wxQtEventSignalHandler< QScrollArea, wxWindowQt >
58 {
59 public:
60 wxQtScrollArea(wxWindowQt *parent, wxWindowQt *handler);
61
62 bool event(QEvent *e) wxOVERRIDE;
63 };
64
wxQtScrollArea(wxWindowQt * parent,wxWindowQt * handler)65 wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler )
66 : wxQtEventSignalHandler< QScrollArea, wxWindowQt >( parent, handler )
67 {
68 }
69
event(QEvent * e)70 bool wxQtScrollArea::event(QEvent *e)
71 {
72 wxWindowQt* handler = GetHandler();
73 if ( handler && handler->HasCapture() )
74 {
75 switch ( e->type() )
76 {
77 case QEvent::MouseButtonRelease:
78 case QEvent::MouseButtonDblClick:
79 case QEvent::MouseMove:
80 case QEvent::Wheel:
81 case QEvent::TouchUpdate:
82 case QEvent::TouchEnd:
83 return viewportEvent(e);
84 default:
85 break;
86 }
87 }
88 // QGesture events arrive without mouse capture
89 else if ( handler )
90 {
91 switch ( e->type() )
92 {
93 case QEvent::Gesture:
94 {
95 QScrollArea::event(e);
96
97 if ( QScrollBar *vBar = verticalScrollBar() )
98 vBar->triggerAction( QAbstractSlider::SliderMove );
99 if ( QScrollBar *hBar = horizontalScrollBar() )
100 hBar->triggerAction( QAbstractSlider::SliderMove );
101
102 return true;
103 }
104
105 default:
106 break;
107 }
108 }
109
110 return QScrollArea::event(e);
111 }
112
113 class wxQtInternalScrollBar : public wxQtEventSignalHandler< QScrollBar, wxWindowQt >
114 {
115 public:
116 wxQtInternalScrollBar(wxWindowQt *parent, wxWindowQt *handler );
~wxQtInternalScrollBar()117 ~wxQtInternalScrollBar()
118 {
119 disconnect( this, &QScrollBar::actionTriggered, this, &wxQtInternalScrollBar::actionTriggered );
120 disconnect( this, &QScrollBar::sliderReleased, this, &wxQtInternalScrollBar::sliderReleased );
121 }
122 void actionTriggered( int action );
123 void sliderReleased();
124 void valueChanged( int position );
125 };
126
wxQtInternalScrollBar(wxWindowQt * parent,wxWindowQt * handler)127 wxQtInternalScrollBar::wxQtInternalScrollBar( wxWindowQt *parent, wxWindowQt *handler )
128 : wxQtEventSignalHandler< QScrollBar, wxWindowQt >( parent, handler )
129 {
130 connect( this, &QScrollBar::actionTriggered, this, &wxQtInternalScrollBar::actionTriggered );
131 connect( this, &QScrollBar::sliderReleased, this, &wxQtInternalScrollBar::sliderReleased );
132 }
133
134
actionTriggered(int action)135 void wxQtInternalScrollBar::actionTriggered( int action )
136 {
137 wxEventType eventType = wxEVT_NULL;
138 switch( action )
139 {
140 case QAbstractSlider::SliderSingleStepAdd:
141 eventType = wxEVT_SCROLLWIN_LINEDOWN;
142 break;
143 case QAbstractSlider::SliderSingleStepSub:
144 eventType = wxEVT_SCROLLWIN_LINEUP;
145 break;
146 case QAbstractSlider::SliderPageStepAdd:
147 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
148 break;
149 case QAbstractSlider::SliderPageStepSub:
150 eventType = wxEVT_SCROLLWIN_PAGEUP;
151 break;
152 case QAbstractSlider::SliderToMinimum:
153 eventType = wxEVT_SCROLLWIN_TOP;
154 break;
155 case QAbstractSlider::SliderToMaximum:
156 eventType = wxEVT_SCROLLWIN_BOTTOM;
157 break;
158 case QAbstractSlider::SliderMove:
159 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
160 break;
161 default:
162 return;
163 }
164
165 if ( GetHandler() )
166 {
167 wxScrollWinEvent e( eventType, sliderPosition(), wxQtConvertOrientation( orientation() ) );
168 EmitEvent( e );
169 }
170 }
171
sliderReleased()172 void wxQtInternalScrollBar::sliderReleased()
173 {
174 if ( GetHandler() )
175 {
176 wxScrollWinEvent e( wxEVT_SCROLLWIN_THUMBRELEASE, sliderPosition(), wxQtConvertOrientation( orientation() ) );
177 EmitEvent( e );
178 }
179 }
180
181 #if wxUSE_ACCEL || defined( Q_MOC_RUN )
182 class wxQtShortcutHandler : public QObject, public wxQtSignalHandler< wxWindowQt >
183 {
184
185 public:
186 wxQtShortcutHandler( wxWindowQt *window );
187
188 public:
189 void activated();
190 };
191
wxQtShortcutHandler(wxWindowQt * window)192 wxQtShortcutHandler::wxQtShortcutHandler( wxWindowQt *window )
193 : wxQtSignalHandler< wxWindowQt >( window )
194 {
195 }
196
activated()197 void wxQtShortcutHandler::activated()
198 {
199 int command = sender()->property("wxQt_Command").toInt();
200
201 GetHandler()->QtHandleShortcut( command );
202 }
203 #endif // wxUSE_ACCEL
204
205 //##############################################################################
206
207 #ifdef __WXUNIVERSAL__
208 wxIMPLEMENT_ABSTRACT_CLASS(wxWindow, wxWindowBase);
209 #endif // __WXUNIVERSAL__
210
211 // We use the QObject property capabilities to store the wxWindow pointer, so we
212 // don't need to use a separate lookup table. We also want to use it in the proper
213 // way and not use/store store void pointers e.g.:
214 // qVariantSetValue( variant, static_cast< void * >( window ));
215 // static_cast< wxWindow * >( qVariantValue< void * >( variant ));
216 // so we declare the corresponding Qt meta type:
217
218 Q_DECLARE_METATYPE( const wxWindow * )
219
220 static const char WINDOW_POINTER_PROPERTY_NAME[] = "wxWindowPointer";
221
222 // We accept a 'const wxWindow *' to indicate that the pointer is only stored:
223
QtStoreWindowPointer(QWidget * widget,const wxWindowQt * window)224 /* static */ void wxWindowQt::QtStoreWindowPointer( QWidget *widget, const wxWindowQt *window )
225 {
226 QVariant variant;
227 qVariantSetValue( variant, window );
228 widget->setProperty( WINDOW_POINTER_PROPERTY_NAME, variant );
229 }
230
QtRetrieveWindowPointer(const QWidget * widget)231 /* static */ wxWindowQt *wxWindowQt::QtRetrieveWindowPointer( const QWidget *widget )
232 {
233 QVariant variant = widget->property( WINDOW_POINTER_PROPERTY_NAME );
234 return const_cast< wxWindowQt * >( ( variant.value< const wxWindow * >() ));
235 }
236
237 /* static */
QtSendSetCursorEvent(wxWindowQt * win,wxPoint posScreen)238 void wxWindowQt::QtSendSetCursorEvent(wxWindowQt* win, wxPoint posScreen)
239 {
240 wxWindowQt* w = win;
241 for ( ;; )
242 {
243 const wxPoint posClient = w->ScreenToClient(posScreen);
244 wxSetCursorEvent event(posClient.x, posClient.y);
245 event.SetEventObject(w);
246
247 const bool processedEvtSetCursor = w->ProcessWindowEvent(event);
248 if ( processedEvtSetCursor && event.HasCursor() )
249 {
250 win->SetCursor(event.GetCursor());
251 return;
252 }
253
254 w = w->GetParent();
255 if ( w == NULL )
256 break;
257 }
258 win->SetCursor(wxCursor(wxCURSOR_ARROW));
259 }
260
261 static wxWindowQt *s_capturedWindow = NULL;
262
DoFindFocus()263 /* static */ wxWindowQt *wxWindowBase::DoFindFocus()
264 {
265 wxWindowQt *window = NULL;
266 QWidget *qtWidget = QApplication::focusWidget();
267 if ( qtWidget != NULL )
268 window = wxWindowQt::QtRetrieveWindowPointer( qtWidget );
269
270 return window;
271 }
272
Init()273 void wxWindowQt::Init()
274 {
275 m_horzScrollBar = NULL;
276 m_vertScrollBar = NULL;
277
278 m_qtPicture = NULL;
279 m_qtPainter.reset(new QPainter());
280
281 m_mouseInside = false;
282
283 #if wxUSE_ACCEL
284 m_qtShortcutHandler.reset(new wxQtShortcutHandler(this));
285 m_processingShortcut = false;
286 #endif
287 m_qtWindow = NULL;
288 m_qtContainer = NULL;
289 }
290
wxWindowQt()291 wxWindowQt::wxWindowQt()
292 {
293 Init();
294
295 }
296
297
wxWindowQt(wxWindowQt * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)298 wxWindowQt::wxWindowQt(wxWindowQt *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
299 long style, const wxString& name)
300 {
301 Init();
302
303 Create( parent, id, pos, size, style, name );
304 }
305
306
~wxWindowQt()307 wxWindowQt::~wxWindowQt()
308 {
309 if ( !m_qtWindow )
310 {
311 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::~wxWindow %s m_qtWindow is NULL"), GetName());
312 return;
313 }
314
315 // Delete only if the qt widget was created or assigned to this base class
316 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::~wxWindow %s m_qtWindow=%p"), GetName(), m_qtWindow);
317
318 if ( !IsBeingDeleted() )
319 {
320 SendDestroyEvent();
321 }
322
323 // Avoid processing pending events which quite often would lead to crashes after this.
324 QCoreApplication::removePostedEvents(m_qtWindow);
325
326 // Block signals because the handlers access members of a derived class.
327 m_qtWindow->blockSignals(true);
328
329 if ( s_capturedWindow == this )
330 s_capturedWindow = NULL;
331
332 DestroyChildren(); // This also destroys scrollbars
333
334 if (m_qtWindow)
335 QtStoreWindowPointer( GetHandle(), NULL );
336
337 #if wxUSE_DRAG_AND_DROP
338 SetDropTarget(NULL);
339 #endif
340
341 delete m_qtWindow;
342 }
343
344
Create(wxWindowQt * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)345 bool wxWindowQt::Create( wxWindowQt * parent, wxWindowID id, const wxPoint & pos,
346 const wxSize & size, long style, const wxString &name )
347 {
348 // If the underlying control hasn't been created then this most probably means
349 // that a generic control, like wxPanel, is being created, so we need a very
350 // simple control as a base:
351
352 if ( GetHandle() == NULL )
353 {
354 if ( style & (wxHSCROLL | wxVSCROLL) )
355 {
356 m_qtContainer = new wxQtScrollArea( parent, this );
357 m_qtWindow = m_qtContainer;
358 // Create the scroll bars if needed:
359 if ( style & wxHSCROLL )
360 QtSetScrollBar( wxHORIZONTAL );
361 if ( style & wxVSCROLL )
362 QtSetScrollBar( wxVERTICAL );
363 }
364 else
365 m_qtWindow = new wxQtWidget( parent, this );
366 }
367
368 if ( !wxWindowBase::CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
369 return false;
370
371 parent->AddChild( this );
372
373 wxPoint p;
374 if ( pos != wxDefaultPosition )
375 p = pos;
376
377 DoMoveWindow( p.x, p.y, size.GetWidth(), size.GetHeight() );
378
379 PostCreation();
380
381 return ( true );
382 }
383
PostCreation(bool generic)384 void wxWindowQt::PostCreation(bool generic)
385 {
386 if ( m_qtWindow == NULL )
387 {
388 // store pointer to the QWidget subclass (to be used in the destructor)
389 m_qtWindow = GetHandle();
390 }
391 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::Create %s m_qtWindow=%p"), GetName(), m_qtWindow);
392
393 // set the background style after creation (not before like in wxGTK)
394 // (only for generic controls, to use qt defaults elsewere)
395 if (generic)
396 QtSetBackgroundStyle();
397 else
398 SetBackgroundStyle(wxBG_STYLE_SYSTEM);
399
400 // // Use custom Qt window flags (allow to turn on or off
401 // // the minimize/maximize/close buttons and title bar)
402 // Qt::WindowFlags qtFlags = GetHandle()->windowFlags();
403 //
404 // qtFlags |= Qt::CustomizeWindowHint;
405 // qtFlags |= Qt::WindowTitleHint;
406 // qtFlags |= Qt::WindowSystemMenuHint;
407 // qtFlags |= Qt::WindowMinMaxButtonsHint;
408 // qtFlags |= Qt::WindowCloseButtonHint;
409 //
410 // GetHandle()->setWindowFlags( qtFlags );
411 //
412 // SetWindowStyleFlag( style );
413 //
414
415 // Set the default color so Paint Event default handler clears the DC:
416 wxWindowBase::SetBackgroundColour(wxColour(GetHandle()->palette().background().color()));
417 wxWindowBase::SetForegroundColour(wxColour(GetHandle()->palette().foreground().color()));
418
419 GetHandle()->setFont( wxWindowBase::GetFont().GetHandle() );
420
421 // The window might have been hidden before Create() and it needs to remain
422 // hidden in this case, so do it (unfortunately there doesn't seem to be
423 // any way to create the window initially hidden with Qt).
424 GetHandle()->setVisible(m_isShown);
425
426 wxWindowCreateEvent event(this);
427 HandleWindowEvent(event);
428 }
429
AddChild(wxWindowBase * child)430 void wxWindowQt::AddChild( wxWindowBase *child )
431 {
432 // Make sure all children are children of the inner scroll area widget (if any):
433
434 if ( QtGetScrollBarsContainer() )
435 QtReparent( child->GetHandle(), QtGetScrollBarsContainer()->viewport() );
436
437 wxWindowBase::AddChild( child );
438 }
439
Show(bool show)440 bool wxWindowQt::Show( bool show )
441 {
442 if ( !wxWindowBase::Show( show ))
443 return false;
444
445 // Show can be called before the underlying window is created:
446
447 QWidget *qtWidget = GetHandle();
448 if ( qtWidget == NULL )
449 {
450 return false;
451 }
452
453 qtWidget->setVisible( show );
454
455 wxSizeEvent event(GetSize(), GetId());
456 event.SetEventObject(this);
457 HandleWindowEvent(event);
458
459 return true;
460 }
461
462
SetLabel(const wxString & label)463 void wxWindowQt::SetLabel(const wxString& label)
464 {
465 GetHandle()->setWindowTitle( wxQtConvertString( label ));
466 }
467
468
GetLabel() const469 wxString wxWindowQt::GetLabel() const
470 {
471 return ( wxQtConvertString( GetHandle()->windowTitle() ));
472 }
473
DoEnable(bool enable)474 void wxWindowQt::DoEnable(bool enable)
475 {
476 GetHandle()->setEnabled(enable);
477 }
478
SetFocus()479 void wxWindowQt::SetFocus()
480 {
481 GetHandle()->setFocus();
482 }
483
QtReparent(QWidget * child,QWidget * parent)484 /* static */ void wxWindowQt::QtReparent( QWidget *child, QWidget *parent )
485 {
486 // Backup the attributes which will be changed during the reparenting:
487
488 // QPoint position = child->pos();
489 // bool isVisible = child->isVisible();
490 Qt::WindowFlags windowFlags = child->windowFlags();
491
492 child->setParent( parent );
493
494 // Restore the attributes:
495
496 child->setWindowFlags( windowFlags );
497 // child->move( position );
498 // child->setVisible( isVisible );
499 }
500
Reparent(wxWindowBase * parent)501 bool wxWindowQt::Reparent( wxWindowBase *parent )
502 {
503 if ( !wxWindowBase::Reparent( parent ))
504 return false;
505
506 QtReparent( GetHandle(), static_cast<wxWindow*>(parent)->QtGetParentWidget() );
507
508 return true;
509 }
510
511
Raise()512 void wxWindowQt::Raise()
513 {
514 GetHandle()->raise();
515 }
516
Lower()517 void wxWindowQt::Lower()
518 {
519 GetHandle()->lower();
520 }
521
522
WarpPointer(int x,int y)523 void wxWindowQt::WarpPointer(int x, int y)
524 {
525 // QCursor::setPos takes global screen coordinates, so translate it:
526
527 ClientToScreen( &x, &y );
528 QCursor::setPos( x, y );
529 }
530
Update()531 void wxWindowQt::Update()
532 {
533 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::Update %s"), GetName());
534 // send the paint event to the inner widget in scroll areas:
535 if ( QtGetScrollBarsContainer() )
536 {
537 QtGetScrollBarsContainer()->viewport()->update();
538 } else {
539 GetHandle()->update();
540 }
541 }
542
Refresh(bool WXUNUSED (eraseBackground),const wxRect * rect)543 void wxWindowQt::Refresh( bool WXUNUSED( eraseBackground ), const wxRect *rect )
544 {
545 QWidget *widget;
546
547 // get the inner widget in scroll areas:
548 if ( QtGetScrollBarsContainer() )
549 {
550 widget = QtGetScrollBarsContainer()->viewport();
551 } else {
552 widget = GetHandle();
553 }
554
555 if ( widget != NULL )
556 {
557 if ( rect != NULL )
558 {
559 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::Refresh %s rect %d %d %d %d"),
560 GetName(),
561 rect->x, rect->y, rect->width, rect->height);
562 widget->update( wxQtConvertRect( *rect ));
563 }
564 else
565 {
566 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::Refresh %s"), GetName());
567 widget->update();
568 }
569 }
570 }
571
SetCursor(const wxCursor & cursor)572 bool wxWindowQt::SetCursor( const wxCursor &cursor )
573 {
574 if (!wxWindowBase::SetCursor(cursor))
575 return false;
576
577 if ( cursor.IsOk() )
578 GetHandle()->setCursor(cursor.GetHandle());
579 else
580 GetHandle()->unsetCursor();
581
582 return true;
583 }
584
SetFont(const wxFont & font)585 bool wxWindowQt::SetFont( const wxFont &font )
586 {
587 // SetFont may be called before Create, so the font is stored
588 // by the base class, and set in PostCreation
589
590 if (GetHandle())
591 {
592 GetHandle()->setFont( font.GetHandle() );
593 return true;
594 }
595
596 return wxWindowBase::SetFont(font);
597 }
598
599
GetCharHeight() const600 int wxWindowQt::GetCharHeight() const
601 {
602 return ( GetHandle()->fontMetrics().height() );
603 }
604
605
GetCharWidth() const606 int wxWindowQt::GetCharWidth() const
607 {
608 return ( GetHandle()->fontMetrics().averageCharWidth() );
609 }
610
DoGetTextExtent(const wxString & string,int * x,int * y,int * descent,int * externalLeading,const wxFont * font) const611 void wxWindowQt::DoGetTextExtent(const wxString& string, int *x, int *y, int *descent,
612 int *externalLeading, const wxFont *font ) const
613 {
614 QFontMetrics fontMetrics( font != NULL ? font->GetHandle() : GetHandle()->font() );
615
616 if ( x != NULL )
617 *x = fontMetrics.width( wxQtConvertString( string ));
618
619 if ( y != NULL )
620 *y = fontMetrics.height();
621
622 if ( descent != NULL )
623 *descent = fontMetrics.descent();
624
625 if ( externalLeading != NULL )
626 *externalLeading = fontMetrics.lineSpacing();
627 }
628
QtGetClientWidget() const629 QWidget *wxWindowQt::QtGetClientWidget() const
630 {
631 QWidget *qtWidget = NULL;
632 if ( m_qtContainer != NULL )
633 {
634 qtWidget = m_qtContainer->viewport();
635 }
636
637 if ( qtWidget == NULL )
638 {
639 // We don't have scrollbars or the QScrollArea has no children
640 qtWidget = GetHandle();
641 }
642
643 return qtWidget;
644 }
645
646 /* Returns a scrollbar for the given orientation, or NULL if the scrollbar
647 * has not been previously created and create is false */
QtGetScrollBar(int orientation) const648 QScrollBar *wxWindowQt::QtGetScrollBar( int orientation ) const
649 {
650 QScrollBar *scrollBar = NULL;
651
652 if ( orientation == wxHORIZONTAL )
653 scrollBar = m_horzScrollBar;
654 else
655 scrollBar = m_vertScrollBar;
656
657 return scrollBar;
658 }
659
660 /* Returns a new scrollbar for the given orientation, or set the scrollbar
661 * passed as parameter */
QtSetScrollBar(int orientation,QScrollBar * scrollBar)662 QScrollBar *wxWindowQt::QtSetScrollBar( int orientation, QScrollBar *scrollBar )
663 {
664 QScrollArea *scrollArea = QtGetScrollBarsContainer();
665 wxCHECK_MSG( scrollArea, NULL, "Window without scrolling area" );
666
667 // Create a new scrollbar if needed
668 if ( !scrollBar )
669 {
670 scrollBar = new wxQtInternalScrollBar(this, this);
671 scrollBar->setOrientation( orientation == wxHORIZONTAL ? Qt::Horizontal : Qt::Vertical );
672 }
673
674 // Let Qt handle layout
675 if ( orientation == wxHORIZONTAL )
676 {
677 scrollArea->setHorizontalScrollBar( scrollBar );
678 m_horzScrollBar = scrollBar;
679 }
680 else
681 {
682 scrollArea->setVerticalScrollBar( scrollBar );
683 m_vertScrollBar = scrollBar;
684 }
685 return scrollBar;
686 }
687
688
SetScrollbar(int orientation,int pos,int thumbvisible,int range,bool WXUNUSED (refresh))689 void wxWindowQt::SetScrollbar( int orientation, int pos, int thumbvisible, int range, bool WXUNUSED(refresh) )
690 {
691 wxCHECK_RET(GetHandle(), "Window has not been created");
692
693 //If not exist, create the scrollbar
694 QScrollBar *scrollBar = QtGetScrollBar( orientation );
695 if ( scrollBar == NULL )
696 scrollBar = QtSetScrollBar( orientation );
697
698 // Configure the scrollbar if it exists. If range is zero we can get here with
699 // scrollBar == NULL and it is not a problem
700 if ( scrollBar )
701 {
702 scrollBar->setRange( 0, range - thumbvisible );
703 scrollBar->setPageStep( thumbvisible );
704 scrollBar->blockSignals( true );
705 scrollBar->setValue(pos);
706 scrollBar->blockSignals( false );
707 scrollBar->show();
708
709 if ( HasFlag(wxALWAYS_SHOW_SB) && (range == 0) )
710 {
711 // Disable instead of hide
712 scrollBar->setEnabled( false );
713 }
714 else
715 scrollBar->setEnabled( true );
716 }
717
718 }
719
SetScrollPos(int orientation,int pos,bool WXUNUSED (refresh))720 void wxWindowQt::SetScrollPos( int orientation, int pos, bool WXUNUSED( refresh ))
721 {
722 QScrollBar *scrollBar = QtGetScrollBar( orientation );
723 if ( scrollBar )
724 scrollBar->setValue( pos );
725 }
726
GetScrollPos(int orientation) const727 int wxWindowQt::GetScrollPos( int orientation ) const
728 {
729 QScrollBar *scrollBar = QtGetScrollBar( orientation );
730 wxCHECK_MSG( scrollBar, 0, "Invalid scrollbar" );
731
732 return scrollBar->value();
733 }
734
GetScrollThumb(int orientation) const735 int wxWindowQt::GetScrollThumb( int orientation ) const
736 {
737 QScrollBar *scrollBar = QtGetScrollBar( orientation );
738 wxCHECK_MSG( scrollBar, 0, "Invalid scrollbar" );
739
740 return scrollBar->pageStep();
741 }
742
GetScrollRange(int orientation) const743 int wxWindowQt::GetScrollRange( int orientation ) const
744 {
745 QScrollBar *scrollBar = QtGetScrollBar( orientation );
746 wxCHECK_MSG( scrollBar, 0, "Invalid scrollbar" );
747
748 return scrollBar->maximum();
749 }
750
751 // scroll window to the specified position
ScrollWindow(int dx,int dy,const wxRect * rect)752 void wxWindowQt::ScrollWindow( int dx, int dy, const wxRect *rect )
753 {
754 // check if this is a scroll area (scroll only inner viewport)
755 QWidget *widget;
756 if ( QtGetScrollBarsContainer() )
757 widget = QtGetScrollBarsContainer()->viewport();
758 else
759 widget = GetHandle();
760 // scroll the widget or the specified rect (not children)
761 if ( rect != NULL )
762 widget->scroll( dx, dy, wxQtConvertRect( *rect ));
763 else
764 widget->scroll( dx, dy );
765 }
766
767
768 #if wxUSE_DRAG_AND_DROP
SetDropTarget(wxDropTarget * dropTarget)769 void wxWindowQt::SetDropTarget( wxDropTarget *dropTarget )
770 {
771 if ( m_dropTarget == dropTarget )
772 return;
773
774 if ( m_dropTarget != NULL )
775 {
776 m_dropTarget->Disconnect();
777 delete m_dropTarget;
778 }
779
780 m_dropTarget = dropTarget;
781
782 if ( m_dropTarget != NULL )
783 {
784 m_dropTarget->ConnectTo(m_qtWindow);
785 }
786 }
787 #endif
788
SetWindowStyleFlag(long style)789 void wxWindowQt::SetWindowStyleFlag( long style )
790 {
791 wxWindowBase::SetWindowStyleFlag( style );
792
793 // wxMISSING_IMPLEMENTATION( "wxWANTS_CHARS, wxTAB_TRAVERSAL" );
794 // // wxFULL_REPAINT_ON_RESIZE: Qt::WResizeNoErase (marked obsolete)
795 // // wxTRANSPARENT_WINDOW, wxCLIP_CHILDREN: Used in window for
796 // // performance, apparently not needed.
797 //
798 // // wxWANTS_CHARS: Need to reimplement event()
799 // // See: http://doc.qt.nokia.com/latest/qwidget.html#events
800 // // wxTAB_TRAVERSAL: reimplement focusNextPrevChild()
801 //
802 // Qt::WindowFlags qtFlags = GetHandle()->windowFlags();
803 //
804 // // For this to work Qt::CustomizeWindowHint must be set (done in Create())
805 // if ( HasFlag( wxCAPTION ) )
806 // {
807 // // Enable caption bar and all buttons. This behavious
808 // // is overwritten by subclasses (wxTopLevelWindow).
809 // qtFlags |= Qt::WindowTitleHint;
810 // qtFlags |= Qt::WindowSystemMenuHint;
811 // qtFlags |= Qt::WindowMinMaxButtonsHint;
812 // qtFlags |= Qt::WindowCloseButtonHint;
813 // }
814 // else
815 // {
816 // // Disable caption bar, include all buttons to be effective
817 // qtFlags &= ~Qt::WindowTitleHint;
818 // qtFlags &= ~Qt::WindowSystemMenuHint;
819 // qtFlags &= ~Qt::WindowMinMaxButtonsHint;
820 // qtFlags &= ~Qt::WindowCloseButtonHint;
821 // }
822 //
823 // GetHandle()->setWindowFlags( qtFlags );
824 //
825 // // Validate border styles
826 // int numberOfBorderStyles = 0;
827 // if ( HasFlag( wxBORDER_NONE ))
828 // numberOfBorderStyles++;
829 // if ( HasFlag( wxBORDER_STATIC ))
830 // numberOfBorderStyles++;
831 // if ( HasFlag( wxBORDER_SIMPLE ))
832 // numberOfBorderStyles++;
833 // if ( HasFlag( wxBORDER_RAISED ))
834 // numberOfBorderStyles++;
835 // if ( HasFlag( wxBORDER_SUNKEN ))
836 // numberOfBorderStyles++;
837 // if ( HasFlag( wxBORDER_THEME ))
838 // numberOfBorderStyles++;
839 // wxCHECK_RET( numberOfBorderStyles <= 1, "Only one border style can be specified" );
840 //
841 // // Borders only supported for QFrame's
842 // QFrame *qtFrame = qobject_cast< QFrame* >( QtGetContainer() );
843 // wxCHECK_RET( numberOfBorderStyles == 0 || qtFrame,
844 // "Borders not supported for this window type (not QFrame)" );
845 //
846 // if ( HasFlag( wxBORDER_NONE ) )
847 // {
848 // qtFrame->setFrameStyle( QFrame::NoFrame );
849 // }
850 // else if ( HasFlag( wxBORDER_STATIC ) )
851 // {
852 // wxMISSING_IMPLEMENTATION( "wxBORDER_STATIC" );
853 // }
854 // else if ( HasFlag( wxBORDER_SIMPLE ) )
855 // {
856 // qtFrame->setFrameStyle( QFrame::Panel );
857 // qtFrame->setFrameShadow( QFrame::Plain );
858 // }
859 // else if ( HasFlag( wxBORDER_RAISED ) )
860 // {
861 // qtFrame->setFrameStyle( QFrame::Panel );
862 // qtFrame->setFrameShadow( QFrame::Raised );
863 // }
864 // else if ( HasFlag( wxBORDER_SUNKEN ) )
865 // {
866 // qtFrame->setFrameStyle( QFrame::Panel );
867 // qtFrame->setFrameShadow( QFrame::Sunken );
868 // }
869 // else if ( HasFlag( wxBORDER_THEME ) )
870 // {
871 // qtFrame->setFrameStyle( QFrame::StyledPanel );
872 // qtFrame->setFrameShadow( QFrame::Plain );
873 // }
874
875 if ( !GetHandle() )
876 return;
877
878 Qt::WindowFlags qtFlags = GetHandle()->windowFlags();
879
880 if ( HasFlag( wxFRAME_NO_TASKBAR ) )
881 {
882 // qtFlags &= ~Qt::WindowType_Mask;
883 if ( (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER) ) {
884 qtFlags = Qt::ToolTip | Qt::FramelessWindowHint;
885 }
886 else
887 qtFlags |= Qt::Dialog;
888 }
889 else
890 if ( ( (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER) )
891 != qtFlags.testFlag( Qt::FramelessWindowHint ) )
892 {
893 qtFlags ^= Qt::FramelessWindowHint;
894 }
895
896 GetHandle()->setWindowFlags( qtFlags );
897 }
898
SetExtraStyle(long exStyle)899 void wxWindowQt::SetExtraStyle( long exStyle )
900 {
901 long exStyleOld = GetExtraStyle();
902 if ( exStyle == exStyleOld )
903 return;
904
905 // update the internal variable
906 wxWindowBase::SetExtraStyle(exStyle);
907
908 if (!m_qtWindow)
909 return;
910
911 Qt::WindowFlags flags = m_qtWindow->windowFlags();
912
913 if (!(exStyle & wxWS_EX_CONTEXTHELP) != !(flags & Qt::WindowContextHelpButtonHint))
914 {
915 flags ^= Qt::WindowContextHelpButtonHint;
916 m_qtWindow->setWindowFlags(flags);
917 }
918 }
919
920
921
DoClientToScreen(int * x,int * y) const922 void wxWindowQt::DoClientToScreen( int *x, int *y ) const
923 {
924 QPoint screenPosition = GetHandle()->mapToGlobal( QPoint( *x, *y ));
925 *x = screenPosition.x();
926 *y = screenPosition.y();
927 }
928
929
DoScreenToClient(int * x,int * y) const930 void wxWindowQt::DoScreenToClient( int *x, int *y ) const
931 {
932 QPoint clientPosition = GetHandle()->mapFromGlobal( QPoint( *x, *y ));
933 *x = clientPosition.x();
934 *y = clientPosition.y();
935 }
936
937
DoCaptureMouse()938 void wxWindowQt::DoCaptureMouse()
939 {
940 wxCHECK_RET( GetHandle() != NULL, wxT("invalid window") );
941 GetHandle()->grabMouse();
942 s_capturedWindow = this;
943 }
944
945
DoReleaseMouse()946 void wxWindowQt::DoReleaseMouse()
947 {
948 wxCHECK_RET( GetHandle() != NULL, wxT("invalid window") );
949 GetHandle()->releaseMouse();
950 s_capturedWindow = NULL;
951 }
952
GetCapture()953 wxWindowQt *wxWindowBase::GetCapture()
954 {
955 return s_capturedWindow;
956 }
957
958
DoGetPosition(int * x,int * y) const959 void wxWindowQt::DoGetPosition(int *x, int *y) const
960 {
961 QWidget *qtWidget = GetHandle();
962 *x = qtWidget->x();
963 *y = qtWidget->y();
964 }
965
966
DoGetSize(int * width,int * height) const967 void wxWindowQt::DoGetSize(int *width, int *height) const
968 {
969 QSize size = GetHandle()->frameSize();
970 QRect rect = GetHandle()->frameGeometry();
971 wxASSERT( size.width() == rect.width() );
972 wxASSERT( size.height() == rect.height() );
973
974 if (width) *width = rect.width();
975 if (height) *height = rect.height();
976 }
977
978
979
DoSetSize(int x,int y,int width,int height,int sizeFlags)980 void wxWindowQt::DoSetSize(int x, int y, int width, int height, int sizeFlags )
981 {
982 int currentX, currentY;
983 GetPosition( ¤tX, ¤tY );
984 if ( x == wxDefaultCoord && !( sizeFlags & wxSIZE_ALLOW_MINUS_ONE ))
985 x = currentX;
986 if ( y == wxDefaultCoord && !( sizeFlags & wxSIZE_ALLOW_MINUS_ONE ))
987 y = currentY;
988
989 // Should we use the best size:
990
991 if (( width == wxDefaultCoord && ( sizeFlags & wxSIZE_AUTO_WIDTH )) ||
992 ( height == wxDefaultCoord && ( sizeFlags & wxSIZE_AUTO_HEIGHT )))
993 {
994 const wxSize BEST_SIZE = GetBestSize();
995 if ( width == wxDefaultCoord && ( sizeFlags & wxSIZE_AUTO_WIDTH ))
996 width = BEST_SIZE.x;
997 if ( height == wxDefaultCoord && ( sizeFlags & wxSIZE_AUTO_HEIGHT ))
998 height = BEST_SIZE.y;
999 }
1000
1001 int w, h;
1002 GetSize(&w, &h);
1003 if (width == -1)
1004 width = w;
1005 if (height == -1)
1006 height = h;
1007
1008 DoMoveWindow( x, y, width, height );
1009
1010 // An annoying feature of Qt
1011 // if a control is created with size of zero, it is set as hidden by qt
1012 // if it is then resized, in some cases it remains hidden, so it
1013 // needs to be shown here
1014 if (m_qtWindow && !m_qtWindow->isVisible() && IsShown())
1015 m_qtWindow->show();
1016 }
1017
1018
DoGetClientSize(int * width,int * height) const1019 void wxWindowQt::DoGetClientSize(int *width, int *height) const
1020 {
1021 QWidget *qtWidget = QtGetClientWidget();
1022 wxCHECK_RET( qtWidget, "window must be created" );
1023
1024 const QRect geometry = qtWidget->geometry();
1025 if (width) *width = geometry.width();
1026 if (height) *height = geometry.height();
1027 }
1028
1029
DoSetClientSize(int width,int height)1030 void wxWindowQt::DoSetClientSize(int width, int height)
1031 {
1032 QWidget *qtWidget = QtGetClientWidget();
1033 wxCHECK_RET( qtWidget, "window must be created" );
1034
1035 QRect geometry = qtWidget->geometry();
1036 geometry.setWidth( width );
1037 geometry.setHeight( height );
1038 qtWidget->setGeometry( geometry );
1039 }
1040
DoMoveWindow(int x,int y,int width,int height)1041 void wxWindowQt::DoMoveWindow(int x, int y, int width, int height)
1042 {
1043 QWidget *qtWidget = GetHandle();
1044
1045 qtWidget->move( x, y );
1046
1047 // There doesn't seem to be any way to change Qt frame size directly, so
1048 // change the widget size, but take into account the extra margins
1049 // corresponding to the frame decorations.
1050 const QSize frameSize = qtWidget->frameSize();
1051 const QSize innerSize = qtWidget->geometry().size();
1052 const QSize frameSizeDiff = frameSize - innerSize;
1053
1054 const int clientWidth = std::max(width - frameSizeDiff.width(), 0);
1055 const int clientHeight = std::max(height - frameSizeDiff.height(), 0);
1056
1057 qtWidget->resize(clientWidth, clientHeight);
1058 }
1059
1060 #if wxUSE_TOOLTIPS
QtApplyToolTip(const wxString & text)1061 void wxWindowQt::QtApplyToolTip(const wxString& text)
1062 {
1063 GetHandle()->setToolTip(wxQtConvertString(text));
1064 }
1065
DoSetToolTip(wxToolTip * tip)1066 void wxWindowQt::DoSetToolTip( wxToolTip *tip )
1067 {
1068 if ( m_tooltip == tip )
1069 return;
1070
1071 wxWindowBase::DoSetToolTip( tip );
1072
1073 if ( m_tooltip )
1074 m_tooltip->SetWindow(this);
1075 else
1076 QtApplyToolTip(wxString());
1077 }
1078 #endif // wxUSE_TOOLTIPS
1079
1080
1081 #if wxUSE_MENUS
DoPopupMenu(wxMenu * menu,int x,int y)1082 bool wxWindowQt::DoPopupMenu(wxMenu *menu, int x, int y)
1083 {
1084 menu->UpdateUI();
1085 menu->GetHandle()->exec( GetHandle()->mapToGlobal( QPoint( x, y ) ) );
1086
1087 return true;
1088 }
1089 #endif // wxUSE_MENUS
1090
1091 #if wxUSE_ACCEL
SetAcceleratorTable(const wxAcceleratorTable & accel)1092 void wxWindowQt::SetAcceleratorTable( const wxAcceleratorTable& accel )
1093 {
1094 wxCHECK_RET(GetHandle(), "Window has not been created");
1095
1096 wxWindowBase::SetAcceleratorTable( accel );
1097
1098 // Disable previously set accelerators
1099 for ( wxVector<QShortcut*>::const_iterator it = m_qtShortcuts.begin();
1100 it != m_qtShortcuts.end(); ++it )
1101 {
1102 delete *it;
1103 }
1104
1105 m_qtShortcuts = accel.ConvertShortcutTable(GetHandle());
1106
1107 // Connect shortcuts to window
1108 for ( wxVector<QShortcut*>::const_iterator it = m_qtShortcuts.begin();
1109 it != m_qtShortcuts.end(); ++it )
1110 {
1111 QObject::connect( *it, &QShortcut::activated, m_qtShortcutHandler.get(), &wxQtShortcutHandler::activated );
1112 QObject::connect( *it, &QShortcut::activatedAmbiguously, m_qtShortcutHandler.get(), &wxQtShortcutHandler::activated );
1113 }
1114 }
1115 #endif // wxUSE_ACCEL
1116
SetBackgroundStyle(wxBackgroundStyle style)1117 bool wxWindowQt::SetBackgroundStyle(wxBackgroundStyle style)
1118 {
1119 if (!wxWindowBase::SetBackgroundStyle(style))
1120 return false;
1121 // NOTE this could be called before creation, so it will be delayed:
1122 return QtSetBackgroundStyle();
1123 }
1124
QtSetBackgroundStyle()1125 bool wxWindowQt::QtSetBackgroundStyle()
1126 {
1127 QWidget *widget;
1128 // if it is a scroll area, don't make transparent (invisible) scroll bars:
1129 if ( QtGetScrollBarsContainer() )
1130 widget = QtGetScrollBarsContainer()->viewport();
1131 else
1132 widget = GetHandle();
1133 // check if the control is created (wxGTK requires calling it before):
1134 if ( widget != NULL )
1135 {
1136 if (m_backgroundStyle == wxBG_STYLE_PAINT)
1137 {
1138 // wx paint handler will draw the invalidated region completely:
1139 widget->setAttribute(Qt::WA_OpaquePaintEvent);
1140 }
1141 else if (m_backgroundStyle == wxBG_STYLE_TRANSPARENT)
1142 {
1143 widget->setAttribute(Qt::WA_TranslucentBackground);
1144 // avoid a default background color (usually black):
1145 widget->setStyleSheet("background:transparent;");
1146 }
1147 else if (m_backgroundStyle == wxBG_STYLE_SYSTEM)
1148 {
1149 // let Qt erase the background by default
1150 // (note that wxClientDC will not work)
1151 //widget->setAutoFillBackground(true);
1152 // use system colors for background (default in Qt)
1153 widget->setAttribute(Qt::WA_NoSystemBackground, false);
1154 }
1155 else if (m_backgroundStyle == wxBG_STYLE_ERASE)
1156 {
1157 // erase events will be fired, if not handled, wx will clear the DC
1158 widget->setAttribute(Qt::WA_OpaquePaintEvent);
1159 // Qt should not clear the background (default):
1160 widget->setAutoFillBackground(false);
1161 }
1162 }
1163 return true;
1164 }
1165
1166
IsTransparentBackgroundSupported(wxString * WXUNUSED (reason)) const1167 bool wxWindowQt::IsTransparentBackgroundSupported(wxString* WXUNUSED(reason)) const
1168 {
1169 return true;
1170 }
1171
SetTransparent(wxByte alpha)1172 bool wxWindowQt::SetTransparent(wxByte alpha)
1173 {
1174 // For Qt, range is between 1 (opaque) and 0 (transparent)
1175 GetHandle()->setWindowOpacity(alpha/255.0);
1176 return true;
1177 }
1178
1179
1180 namespace
1181 {
1182
wxQtChangeRoleColour(QPalette::ColorRole role,QWidget * widget,const wxColour & colour)1183 void wxQtChangeRoleColour(QPalette::ColorRole role,
1184 QWidget* widget,
1185 const wxColour& colour)
1186 {
1187 QPalette palette = widget->palette();
1188 palette.setColor(role, colour.GetQColor());
1189 widget->setPalette(palette);
1190 }
1191
1192 } // anonymous namespace
1193
SetBackgroundColour(const wxColour & colour)1194 bool wxWindowQt::SetBackgroundColour(const wxColour& colour)
1195 {
1196 if ( !wxWindowBase::SetBackgroundColour(colour) )
1197 return false;
1198
1199 QWidget *widget = GetHandle();
1200 wxQtChangeRoleColour(widget->backgroundRole(), widget, colour);
1201
1202 return true;
1203 }
1204
SetForegroundColour(const wxColour & colour)1205 bool wxWindowQt::SetForegroundColour(const wxColour& colour)
1206 {
1207 if (!wxWindowBase::SetForegroundColour(colour))
1208 return false;
1209
1210 QWidget *widget = GetHandle();
1211 wxQtChangeRoleColour(widget->foregroundRole(), widget, colour);
1212
1213 return true;
1214 }
1215
QtHandlePaintEvent(QWidget * handler,QPaintEvent * event)1216 bool wxWindowQt::QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event )
1217 {
1218 /* If this window has scrollbars, only let wx handle the event if it is
1219 * for the client area (the scrolled part). Events for the whole window
1220 * (including scrollbars and maybe status or menu bars are handled by Qt */
1221
1222 if ( QtGetScrollBarsContainer() && handler != QtGetScrollBarsContainer() )
1223 {
1224 return false;
1225 }
1226 else
1227 {
1228 // use the Qt event region:
1229 m_updateRegion.QtSetRegion( event->region() );
1230
1231 // Prepare the Qt painter for wxWindowDC:
1232 bool ok = false;
1233 if ( QtGetScrollBarsContainer() )
1234 {
1235 // QScrollArea can only draw in the viewport:
1236 ok = m_qtPainter->begin( QtGetScrollBarsContainer()->viewport() );
1237 }
1238 if ( !ok )
1239 {
1240 // Start the paint in the widget itself
1241 ok = m_qtPainter->begin( GetHandle() );
1242 }
1243
1244 if ( ok )
1245 {
1246 bool handled;
1247
1248 if ( m_qtPicture == NULL )
1249 {
1250 // Real paint event (not for wxClientDC), prepare the background
1251 switch ( GetBackgroundStyle() )
1252 {
1253 case wxBG_STYLE_TRANSPARENT:
1254 if (IsTransparentBackgroundSupported())
1255 {
1256 // Set a transparent background, so that overlaying in parent
1257 // might indeed let see through where this child did not
1258 // explicitly paint. See wxBG_STYLE_SYSTEM for more comment
1259 }
1260 break;
1261 case wxBG_STYLE_ERASE:
1262 {
1263 // the background should be cleared by qt auto fill
1264 // send the erase event (properly creating a DC for it)
1265 wxPaintDC dc( this );
1266 dc.SetDeviceClippingRegion( m_updateRegion );
1267
1268 wxEraseEvent erase( GetId(), &dc );
1269 erase.SetEventObject(this);
1270 if ( ProcessWindowEvent(erase) )
1271 {
1272 // background erased, don't do it again
1273 break;
1274 }
1275 // Ensure DC is cleared if handler didn't and Qt will not do it
1276 if ( UseBgCol() && !GetHandle()->autoFillBackground() )
1277 {
1278 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::QtHandlePaintEvent %s clearing DC to %s"),
1279 GetName(), GetBackgroundColour().GetAsString()
1280 );
1281 dc.SetBackground(GetBackgroundColour());
1282 dc.Clear();
1283 }
1284 }
1285 // fall through
1286 case wxBG_STYLE_SYSTEM:
1287 if ( GetThemeEnabled() )
1288 {
1289 // let qt render the background:
1290 // commented out as this will cause recursive painting
1291 // this should be done outside using setBackgroundRole
1292 // setAutoFillBackground or setAttribute
1293 //wxWindowDC dc( (wxWindow*)this );
1294 //widget->render(m_qtPainter);
1295 }
1296 break;
1297 case wxBG_STYLE_PAINT:
1298 // nothing to do: window will be painted over in EVT_PAINT
1299 break;
1300
1301 case wxBG_STYLE_COLOUR:
1302 wxFAIL_MSG( "unsupported background style" );
1303 }
1304
1305 // send the paint event (wxWindowDC will draw directly):
1306 wxPaintEvent paint( this );
1307 handled = ProcessWindowEvent(paint);
1308 m_updateRegion.Clear();
1309 }
1310 else
1311 {
1312 // Data from wxClientDC, paint it
1313 m_qtPicture->play( m_qtPainter.get() );
1314 // Reset picture
1315 m_qtPicture->setData( NULL, 0 );
1316 handled = true;
1317 }
1318
1319 // commit changes of the painter to the widget
1320 m_qtPainter->end();
1321
1322 return handled;
1323 }
1324 else
1325 {
1326 // Painter didn't begun, not handled by wxWidgets:
1327 wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::QtHandlePaintEvent %s Qt widget painter begin failed"), GetName() );
1328 return false;
1329 }
1330 }
1331 }
1332
QtHandleResizeEvent(QWidget * WXUNUSED (handler),QResizeEvent * event)1333 bool wxWindowQt::QtHandleResizeEvent ( QWidget *WXUNUSED( handler ), QResizeEvent *event )
1334 {
1335 wxSizeEvent e( wxQtConvertSize( event->size() ) );
1336 e.SetEventObject(this);
1337
1338 return ProcessWindowEvent( e );
1339 }
1340
QtHandleWheelEvent(QWidget * WXUNUSED (handler),QWheelEvent * event)1341 bool wxWindowQt::QtHandleWheelEvent ( QWidget *WXUNUSED( handler ), QWheelEvent *event )
1342 {
1343 wxMouseEvent e( wxEVT_MOUSEWHEEL );
1344 e.SetPosition( wxQtConvertPoint( event->pos() ) );
1345 e.SetEventObject(this);
1346
1347 e.m_wheelAxis = ( event->orientation() == Qt::Vertical ) ? wxMOUSE_WHEEL_VERTICAL : wxMOUSE_WHEEL_HORIZONTAL;
1348 e.m_wheelRotation = event->delta();
1349 e.m_linesPerAction = 3;
1350 e.m_wheelDelta = 120;
1351
1352 return ProcessWindowEvent( e );
1353 }
1354
1355
QtHandleKeyEvent(QWidget * WXUNUSED (handler),QKeyEvent * event)1356 bool wxWindowQt::QtHandleKeyEvent ( QWidget *WXUNUSED( handler ), QKeyEvent *event )
1357 {
1358 // qt sends keyup and keydown events for autorepeat, but this is not
1359 // normal for wx which only sends repeated keydown events
1360 // discard repeated keyup events
1361 if ( event->isAutoRepeat() && event->type() == QEvent::KeyRelease )
1362 return true;
1363
1364 #if wxUSE_ACCEL
1365 if ( m_processingShortcut )
1366 {
1367 /* Enter here when a shortcut isn't handled by Qt.
1368 * Return true to avoid Qt-processing of the event
1369 * Instead, use the flag to indicate that it wasn't processed */
1370 m_processingShortcut = false;
1371
1372 return true;
1373 }
1374 #endif // wxUSE_ACCEL
1375
1376 bool handled = false;
1377
1378 // Build the event
1379 wxKeyEvent e( event->type() == QEvent::KeyPress ? wxEVT_KEY_DOWN : wxEVT_KEY_UP );
1380 e.SetEventObject(this);
1381 // TODO: m_x, m_y
1382 e.m_keyCode = wxQtConvertKeyCode( event->key(), event->modifiers() );
1383
1384 #if wxUSE_UNICODE
1385 if ( event->text().isEmpty() )
1386 e.m_uniChar = 0;
1387 else
1388 e.m_uniChar = event->text().at( 0 ).unicode();
1389 #endif // wxUSE_UNICODE
1390
1391 e.m_rawCode = event->nativeVirtualKey();
1392 e.m_rawFlags = event->nativeModifiers();
1393
1394 // Modifiers
1395 wxQtFillKeyboardModifiers( event->modifiers(), &e );
1396
1397 handled = ProcessWindowEvent( e );
1398
1399 // On key presses, send the EVT_CHAR event
1400 if ( !handled && event->type() == QEvent::KeyPress )
1401 {
1402 #if wxUSE_ACCEL
1403 // Check for accelerators
1404 if ( !m_processingShortcut )
1405 {
1406 /* The call to notify() will try to execute a shortcut. If it fails
1407 * it will call keyPressEvent() in our wxQtWidget which calls back
1408 * to this function. We use the m_processingShortcut flag to avoid
1409 * processing that recursive call and return back to this one. */
1410 m_processingShortcut = true;
1411
1412 QApplication::instance()->notify( GetHandle(), event );
1413
1414 handled = m_processingShortcut;
1415 m_processingShortcut = false;
1416
1417 if ( handled )
1418 return true;
1419 }
1420 #endif // wxUSE_ACCEL
1421
1422 e.SetEventType( wxEVT_CHAR );
1423 e.SetEventObject(this);
1424
1425 // Translated key code (including control + letter -> 1-26)
1426 int translated = 0;
1427 if ( !event->text().isEmpty() )
1428 translated = event->text().at( 0 ).toLatin1();
1429 if ( translated )
1430 e.m_keyCode = translated;
1431
1432 handled = ProcessWindowEvent( e );
1433 }
1434
1435 return handled;
1436 }
1437
QtHandleMouseEvent(QWidget * handler,QMouseEvent * event)1438 bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event )
1439 {
1440 // Convert event type
1441 wxEventType wxType = 0;
1442 switch ( event->type() )
1443 {
1444 case QEvent::MouseButtonDblClick:
1445 switch ( event->button() )
1446 {
1447 case Qt::LeftButton:
1448 wxType = wxEVT_LEFT_DCLICK;
1449 break;
1450 case Qt::RightButton:
1451 wxType = wxEVT_RIGHT_DCLICK;
1452 break;
1453 case Qt::MidButton:
1454 wxType = wxEVT_MIDDLE_DCLICK;
1455 break;
1456 case Qt::XButton1:
1457 wxType = wxEVT_AUX1_DCLICK;
1458 break;
1459 case Qt::XButton2:
1460 wxType = wxEVT_AUX2_DCLICK;
1461 break;
1462 case Qt::NoButton:
1463 case Qt::MouseButtonMask: // Not documented ?
1464 default:
1465 return false;
1466 }
1467 break;
1468 case QEvent::MouseButtonPress:
1469 switch ( event->button() )
1470 {
1471 case Qt::LeftButton:
1472 wxType = wxEVT_LEFT_DOWN;
1473 break;
1474 case Qt::RightButton:
1475 wxType = wxEVT_RIGHT_DOWN;
1476 break;
1477 case Qt::MidButton:
1478 wxType = wxEVT_MIDDLE_DOWN;
1479 break;
1480 case Qt::XButton1:
1481 wxType = wxEVT_AUX1_DOWN;
1482 break;
1483 case Qt::XButton2:
1484 wxType = wxEVT_AUX2_DOWN;
1485 break;
1486 case Qt::NoButton:
1487 case Qt::MouseButtonMask: // Not documented ?
1488 default:
1489 return false;
1490 }
1491 break;
1492 case QEvent::MouseButtonRelease:
1493 switch ( event->button() )
1494 {
1495 case Qt::LeftButton:
1496 wxType = wxEVT_LEFT_UP;
1497 break;
1498 case Qt::RightButton:
1499 wxType = wxEVT_RIGHT_UP;
1500 break;
1501 case Qt::MidButton:
1502 wxType = wxEVT_MIDDLE_UP;
1503 break;
1504 case Qt::XButton1:
1505 wxType = wxEVT_AUX1_UP;
1506 break;
1507 case Qt::XButton2:
1508 wxType = wxEVT_AUX2_UP;
1509 break;
1510 case Qt::NoButton:
1511 case Qt::MouseButtonMask: // Not documented ?
1512 default:
1513 return false;
1514 }
1515 break;
1516 case QEvent::MouseMove:
1517 wxType = wxEVT_MOTION;
1518 break;
1519 default:
1520 // Unknown event type
1521 wxFAIL_MSG( "Unknown mouse event type" );
1522 }
1523
1524 // Fill the event
1525
1526 // Use screen position as the event might originate from a different
1527 // Qt window than this one.
1528 wxPoint mousePos = ScreenToClient(wxQtConvertPoint(event->globalPos()));
1529
1530 wxMouseEvent e( wxType );
1531 e.SetEventObject(this);
1532 e.m_clickCount = -1;
1533 e.SetPosition(mousePos);
1534
1535 // Mouse buttons
1536 wxQtFillMouseButtons( event->buttons(), &e );
1537
1538 // Keyboard modifiers
1539 wxQtFillKeyboardModifiers( event->modifiers(), &e );
1540
1541 bool handled = ProcessWindowEvent( e );
1542
1543 // Determine if mouse is inside the widget
1544 bool mouseInside = true;
1545 if ( mousePos.x < 0 || mousePos.x > handler->width() ||
1546 mousePos.y < 0 || mousePos.y > handler->height() )
1547 mouseInside = false;
1548
1549 if ( e.GetEventType() == wxEVT_MOTION )
1550 {
1551 /* Qt doesn't emit leave/enter events while the mouse is grabbed
1552 * and it automatically grabs the mouse while dragging. In that cases
1553 * we emulate the enter and leave events */
1554
1555 // Mouse enter/leaves
1556 if ( m_mouseInside != mouseInside )
1557 {
1558 if ( mouseInside )
1559 e.SetEventType( wxEVT_ENTER_WINDOW );
1560 else
1561 e.SetEventType( wxEVT_LEAVE_WINDOW );
1562
1563 ProcessWindowEvent( e );
1564 }
1565
1566 QtSendSetCursorEvent(this, wxQtConvertPoint( event->globalPos()));
1567 }
1568
1569 m_mouseInside = mouseInside;
1570
1571 return handled;
1572 }
1573
QtHandleEnterEvent(QWidget * handler,QEvent * event)1574 bool wxWindowQt::QtHandleEnterEvent ( QWidget *handler, QEvent *event )
1575 {
1576 wxMouseEvent e( event->type() == QEvent::Enter ? wxEVT_ENTER_WINDOW : wxEVT_LEAVE_WINDOW );
1577 e.m_clickCount = 0;
1578 e.SetPosition( wxQtConvertPoint( handler->mapFromGlobal( QCursor::pos() ) ) );
1579 e.SetEventObject(this);
1580
1581 // Mouse buttons
1582 wxQtFillMouseButtons( QApplication::mouseButtons(), &e );
1583
1584 // Keyboard modifiers
1585 wxQtFillKeyboardModifiers( QApplication::keyboardModifiers(), &e );
1586
1587 return ProcessWindowEvent( e );
1588 }
1589
QtHandleMoveEvent(QWidget * handler,QMoveEvent * event)1590 bool wxWindowQt::QtHandleMoveEvent ( QWidget *handler, QMoveEvent *event )
1591 {
1592 if ( GetHandle() != handler )
1593 return false;
1594
1595 wxMoveEvent e( wxQtConvertPoint( event->pos() ), GetId() );
1596 e.SetEventObject(this);
1597
1598 return ProcessWindowEvent( e );
1599 }
1600
QtHandleShowEvent(QWidget * handler,QEvent * event)1601 bool wxWindowQt::QtHandleShowEvent ( QWidget *handler, QEvent *event )
1602 {
1603 if ( GetHandle() != handler )
1604 return false;
1605
1606 wxShowEvent e(GetId(), event->type() == QEvent::Show);
1607 e.SetEventObject(this);
1608
1609 return ProcessWindowEvent( e );
1610 }
1611
QtHandleChangeEvent(QWidget * handler,QEvent * event)1612 bool wxWindowQt::QtHandleChangeEvent ( QWidget *handler, QEvent *event )
1613 {
1614 if ( GetHandle() != handler )
1615 return false;
1616
1617 if ( event->type() == QEvent::ActivationChange )
1618 {
1619 wxActivateEvent e( wxEVT_ACTIVATE, handler->isActiveWindow(), GetId() );
1620 e.SetEventObject(this);
1621
1622 return ProcessWindowEvent( e );
1623 }
1624 else
1625 return false;
1626 }
1627
1628 // Returns true if the closing should be vetoed and false if the window should be closed.
QtHandleCloseEvent(QWidget * handler,QCloseEvent * WXUNUSED (event))1629 bool wxWindowQt::QtHandleCloseEvent ( QWidget *handler, QCloseEvent *WXUNUSED( event ) )
1630 {
1631 if ( GetHandle() != handler )
1632 return false;
1633
1634 // This is required as Qt will still send out close events when the window is disabled.
1635 if ( !IsEnabled() )
1636 return true;
1637
1638 return !Close();
1639 }
1640
QtHandleContextMenuEvent(QWidget * WXUNUSED (handler),QContextMenuEvent * event)1641 bool wxWindowQt::QtHandleContextMenuEvent ( QWidget *WXUNUSED( handler ), QContextMenuEvent *event )
1642 {
1643 const wxPoint pos =
1644 event->reason() == QContextMenuEvent::Keyboard
1645 ? wxDefaultPosition
1646 : wxQtConvertPoint( event->globalPos() );
1647 return WXSendContextMenuEvent(pos);
1648 }
1649
QtHandleFocusEvent(QWidget * WXUNUSED (handler),QFocusEvent * event)1650 bool wxWindowQt::QtHandleFocusEvent ( QWidget *WXUNUSED( handler ), QFocusEvent *event )
1651 {
1652 wxFocusEvent e( event->gotFocus() ? wxEVT_SET_FOCUS : wxEVT_KILL_FOCUS, GetId() );
1653 e.SetEventObject(this);
1654 e.SetWindow(event->gotFocus() ? this : FindFocus());
1655
1656 bool handled = ProcessWindowEvent( e );
1657
1658 wxWindowQt *parent = GetParent();
1659 if ( event->gotFocus() && parent )
1660 {
1661 wxChildFocusEvent childEvent( this );
1662 parent->ProcessWindowEvent( childEvent );
1663 }
1664
1665 return handled;
1666 }
1667
1668 #if wxUSE_ACCEL
QtHandleShortcut(int command)1669 void wxWindowQt::QtHandleShortcut ( int command )
1670 {
1671 if (command != -1)
1672 {
1673 wxCommandEvent menu_event( wxEVT_COMMAND_MENU_SELECTED, command );
1674 bool ret = ProcessWindowEvent( menu_event );
1675
1676 if ( !ret )
1677 {
1678 // if the accelerator wasn't handled as menu event, try
1679 // it as button click (for compatibility with other
1680 // platforms):
1681 wxCommandEvent button_event( wxEVT_COMMAND_BUTTON_CLICKED, command );
1682 button_event.SetEventObject(this);
1683 ProcessWindowEvent( button_event );
1684 }
1685 }
1686 }
1687 #endif // wxUSE_ACCEL
1688
GetHandle() const1689 QWidget *wxWindowQt::GetHandle() const
1690 {
1691 return m_qtWindow;
1692 }
1693
QtGetScrollBarsContainer() const1694 QScrollArea *wxWindowQt::QtGetScrollBarsContainer() const
1695 {
1696 return m_qtContainer;
1697 }
1698
QtSetPicture(QPicture * pict)1699 void wxWindowQt::QtSetPicture( QPicture* pict )
1700 {
1701 m_qtPicture = pict;
1702 }
1703
QtGetPainter()1704 QPainter *wxWindowQt::QtGetPainter()
1705 {
1706 return m_qtPainter.get();
1707 }
1708
EnableTouchEvents(int eventsMask)1709 bool wxWindowQt::EnableTouchEvents(int eventsMask)
1710 {
1711 wxCHECK_MSG( GetHandle(), false, "can't be called before creating the window" );
1712
1713 if ( eventsMask == wxTOUCH_NONE )
1714 {
1715 m_qtWindow->setAttribute(Qt::WA_AcceptTouchEvents, false);
1716 return true;
1717 }
1718
1719 if ( eventsMask & wxTOUCH_PRESS_GESTURES )
1720 {
1721 m_qtWindow->setAttribute(Qt::WA_AcceptTouchEvents, true);
1722 m_qtWindow->grabGesture(Qt::TapAndHoldGesture);
1723 QTapAndHoldGesture::setTimeout ( 1000 );
1724 }
1725 if ( eventsMask & wxTOUCH_PAN_GESTURES )
1726 {
1727 m_qtWindow->setAttribute(Qt::WA_AcceptTouchEvents, true);
1728 m_qtWindow->grabGesture(Qt::PanGesture);
1729 }
1730 if ( eventsMask & wxTOUCH_ZOOM_GESTURE )
1731 {
1732 m_qtWindow->setAttribute(Qt::WA_AcceptTouchEvents, true);
1733 m_qtWindow->grabGesture(Qt::PinchGesture);
1734 }
1735
1736 return true;
1737 }
1738