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( &currentX, &currentY );
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