diff --git a/include/wx/qt/menuitem.h b/include/wx/qt/menuitem.h index c173d4c6b1..673eb93bf5 100644 --- a/include/wx/qt/menuitem.h +++ b/include/wx/qt/menuitem.h @@ -12,7 +12,6 @@ #include "wx/bitmap.h" class QAction; -class wxQtAction; class WXDLLIMPEXP_FWD_CORE wxMenu; @@ -35,8 +34,6 @@ public: virtual void Check(bool check = true) override; virtual bool IsChecked() const override; - virtual void SetBitmap(const wxBitmapBundle& bitmap) override; - virtual QAction *GetHandle() const; virtual void SetFont(const wxFont& font); @@ -46,9 +43,12 @@ public: virtual void ClearExtraAccels() override; #endif // wxUSE_ACCEL + // implementation + void QtCreateAction(wxMenu* parentMenu); + private: // Qt is using an action instead of a menu item. - wxQtAction *m_qtAction; + QAction *m_qtAction = nullptr; wxDECLARE_DYNAMIC_CLASS( wxMenuItem ); }; diff --git a/include/wx/qt/private/winevent.h b/include/wx/qt/private/winevent.h index fb1fc431e1..66e6692087 100644 --- a/include/wx/qt/private/winevent.h +++ b/include/wx/qt/private/winevent.h @@ -30,21 +30,17 @@ class QPaintEvent; class wxQtSignalHandler { protected: - wxQtSignalHandler( wxEvtHandler *handler ) + explicit wxQtSignalHandler( wxWindow *handler ) : m_handler(handler) { - m_handler = handler; } bool EmitEvent( wxEvent &event ) const { - // We're only called with the objects of class (or derived from) - // wxWindow, so the cast is safe. - wxWindow* const handler = static_cast(GetHandler()); - event.SetEventObject( handler ); - return handler->HandleWindowEvent( event ); + event.SetEventObject( m_handler ); + return m_handler->HandleWindowEvent( event ); } - virtual wxEvtHandler *GetHandler() const + virtual wxWindow *GetHandler() const { return m_handler; } @@ -54,22 +50,18 @@ protected: // event if the control has wxTE_PROCESS_ENTER flag. bool HandleKeyPressEvent(QWidget* widget, QKeyEvent* e) { - // We're only called with the objects of class (or derived from) - // wxWindow, so the cast is safe. - wxWindow* const handler = static_cast(GetHandler()); - - if ( handler->HasFlag(wxTE_PROCESS_ENTER) ) + if ( m_handler->HasFlag(wxTE_PROCESS_ENTER) ) { if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) { - wxCommandEvent event( wxEVT_TEXT_ENTER, handler->GetId() ); + wxCommandEvent event( wxEVT_TEXT_ENTER, m_handler->GetId() ); event.SetString( GetValueForProcessEnter() ); - event.SetEventObject( handler ); - return handler->HandleWindowEvent( event ); + event.SetEventObject( m_handler ); + return m_handler->HandleWindowEvent( event ); } } - return handler->QtHandleKeyEvent(widget, e); + return m_handler->QtHandleKeyEvent(widget, e); } // Controls supporting wxTE_PROCESS_ENTER flag (e.g. wxTextCtrl, wxComboBox and wxSpinCtrl) @@ -77,7 +69,7 @@ protected: virtual wxString GetValueForProcessEnter() { return wxString(); } private: - wxEvtHandler *m_handler; + wxWindow* const m_handler; }; template < typename Widget, typename Handler > diff --git a/src/qt/menu.cpp b/src/qt/menu.cpp index 4e577fc884..f5d646f2e8 100644 --- a/src/qt/menu.cpp +++ b/src/qt/menu.cpp @@ -25,13 +25,12 @@ static void ApplyStyle( QMenu *qtMenu, long style ) // wxQtActionGroup: an exclusive group which synchronizes QActions in // QActionGroup with their wx wrappers. -class wxQtActionGroup : public QActionGroup, public wxQtSignalHandler +class wxQtActionGroup : public QActionGroup { public: explicit wxQtActionGroup( wxMenu* handler ) - : QActionGroup( handler->GetHandle() ), - wxQtSignalHandler( handler ) + : QActionGroup( handler->GetHandle() ) { setExclusive(true); @@ -44,7 +43,16 @@ public: } private: - void triggered ( QAction* action ); + void triggered ( QAction* action ) + { + if ( action != m_activeAction ) + { + if ( m_activeAction->isCheckable() ) + m_activeAction->setChecked(false); + + m_activeAction = action; + } + } QAction* m_activeAction; }; @@ -168,6 +176,8 @@ wxMenuItem *wxMenu::DoAppend(wxMenuItem *item) if ( wxMenuBase::DoAppend( item ) == nullptr ) return nullptr; + item->QtCreateAction( this ); + InsertMenuItemAction( this, previousItem, item, successiveItem ); return item; @@ -185,6 +195,8 @@ wxMenuItem *wxMenu::DoInsert(size_t insertPosition, wxMenuItem *item) if ( wxMenuBase::DoInsert( insertPosition, item ) == nullptr ) return nullptr; + item->QtCreateAction( this ); + InsertMenuItemAction( this, previousItem, item, successiveItem ); return item; @@ -342,14 +354,3 @@ QWidget *wxMenuBar::GetHandle() const { return m_qtMenuBar; } - -void wxQtActionGroup::triggered( QAction* action ) -{ - if ( action != m_activeAction ) - { - if ( m_activeAction->isCheckable() ) - m_activeAction->setChecked(false); - - m_activeAction = action; - } -} diff --git a/src/qt/menuitem.cpp b/src/qt/menuitem.cpp index 65006a3bd4..4860623358 100644 --- a/src/qt/menuitem.cpp +++ b/src/qt/menuitem.cpp @@ -18,12 +18,12 @@ #include #include -class wxQtAction : public QAction, public wxQtSignalHandler +class wxQtAction : public QAction { public: wxQtAction( wxMenu *handler, int id, const wxString &text, const wxString &help, - wxItemKind kind, wxMenu *subMenu, wxMenuItem *menuItem ); + wxItemKind kind, wxMenu *subMenu, wxMenuItem *menuItem ); // Set the action shortcut to correspond to the accelerator specified by // the given label. They set the primary shortcut the first time they are @@ -32,11 +32,6 @@ public: void UpdateShortcuts(const wxString& text); void UpdateShortcutsFromLabel(const wxString& text); - wxMenu* GetMenu() const - { - return static_cast(wxQtSignalHandler::GetHandler()); - } - // Convert hyphenated shortcuts to use the plus sign (+) which Qt understands. // Example: [ Ctrl-Shift-- ] should be converted to [ Ctrl+Shift+- ] static wxString Normalize(const wxString& text) @@ -47,9 +42,17 @@ public: } private: - void onActionToggled( bool checked ); - void onActionTriggered( bool checked ); + void onActionToggled( bool checked ) + { + m_handler->Check(m_mitemId, checked); + } + void onActionTriggered( bool checked ) + { + m_handler->SendEvent(m_mitemId, m_isCheckable ? checked : -1); + } + + wxMenu* m_handler; const wxWindowID m_mitemId; const bool m_isCheckable; }; @@ -67,11 +70,27 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu, int id, const wxString& text, const wxString& help, wxItemKind kind, wxMenu *subMenu) : wxMenuItemBase( parentMenu, id, text, help, kind, subMenu ) { - m_qtAction = new wxQtAction( parentMenu, id, - wxQtAction::Normalize( text ), - help, kind, subMenu, this ); } +void wxMenuItem::QtCreateAction(wxMenu* parentMenu) +{ + wxASSERT_MSG( parentMenu, "invalid parent" ); + + m_qtAction = new wxQtAction( parentMenu, GetId(), + wxQtAction::Normalize( GetItemLabel() ), + GetHelp(), GetKind(), GetSubMenu(), this ); + + if ( m_bitmap.IsOk() && m_kind == wxITEM_NORMAL ) + { + m_qtAction->setIcon( QIcon(*GetBitmapFromBundle(m_bitmap).GetHandle()) ); + } + +#if wxUSE_ACCEL + auto qtAction = static_cast(m_qtAction); + for ( const auto accel : m_extraAccels ) + qtAction->UpdateShortcuts( accel.ToRawString() ); +#endif +} void wxMenuItem::SetItemLabel( const wxString &label ) @@ -80,15 +99,21 @@ void wxMenuItem::SetItemLabel( const wxString &label ) wxMenuItemBase::SetItemLabel( qtlabel ); - m_qtAction->UpdateShortcutsFromLabel( qtlabel ); + if ( m_qtAction ) + { + auto qtAction = static_cast(m_qtAction); - m_qtAction->setText( wxQtConvertString( qtlabel )); + qtAction->UpdateShortcutsFromLabel( qtlabel ); + qtAction->setText( wxQtConvertString( qtlabel )); + } } void wxMenuItem::SetCheckable( bool checkable ) { + wxCHECK_RET( m_qtAction, "invalid menu item" ); + wxMenuItemBase::SetCheckable( checkable ); m_qtAction->setCheckable( checkable ); @@ -98,6 +123,8 @@ void wxMenuItem::SetCheckable( bool checkable ) void wxMenuItem::Enable( bool enable ) { + wxCHECK_RET( m_qtAction, "invalid menu item" ); + wxMenuItemBase::Enable( enable ); m_qtAction->setEnabled( enable ); @@ -107,6 +134,8 @@ void wxMenuItem::Enable( bool enable ) bool wxMenuItem::IsEnabled() const { + wxCHECK_MSG( m_qtAction, false, "invalid menu item" ); + bool isEnabled = m_qtAction->isEnabled(); // Make sure the enabled stati are in synch: @@ -119,6 +148,8 @@ bool wxMenuItem::IsEnabled() const void wxMenuItem::Check( bool checked ) { + wxCHECK_RET( m_qtAction, "invalid menu item" ); + wxMenuItemBase::Check( checked ); m_qtAction->setChecked( checked ); @@ -128,6 +159,11 @@ void wxMenuItem::Check( bool checked ) bool wxMenuItem::IsChecked() const { + wxCHECK_MSG( m_qtAction, false, "invalid menu item" ); + + wxCHECK_MSG( IsCheckable(), false, + "can't get state of uncheckable item!" ); + bool isChecked = m_qtAction->isChecked(); // Make sure the checked stati are in synch: @@ -137,24 +173,10 @@ bool wxMenuItem::IsChecked() const } -void wxMenuItem::SetBitmap(const wxBitmapBundle& bitmap) -{ - if ( m_kind == wxITEM_NORMAL ) - { - m_bitmap = bitmap; - if ( m_bitmap.IsOk() ) - { - m_qtAction->setIcon( QIcon(*GetBitmapFromBundle(m_bitmap).GetHandle()) ); - } - } - else - { - wxFAIL_MSG("only normal menu items can have bitmaps"); - } -} - void wxMenuItem::SetFont(const wxFont& font) { + wxCHECK_RET( m_qtAction, "invalid menu item" ); + m_qtAction->setFont(font.GetHandle()); } @@ -168,23 +190,25 @@ void wxMenuItem::AddExtraAccel(const wxAcceleratorEntry& accel) { wxMenuItemBase::AddExtraAccel(accel); - m_qtAction->UpdateShortcuts( accel.ToRawString() ); + if ( m_qtAction ) + static_cast(m_qtAction)->UpdateShortcuts( accel.ToRawString() ); } void wxMenuItem::ClearExtraAccels() { wxMenuItemBase::ClearExtraAccels(); - m_qtAction->UpdateShortcuts( wxString() ); + if ( m_qtAction ) + static_cast(m_qtAction)->UpdateShortcuts( wxString() ); } #endif // wxUSE_ACCEL //============================================================================= wxQtAction::wxQtAction( wxMenu *handler, int id, const wxString &text, const wxString &help, - wxItemKind kind, wxMenu *subMenu, wxMenuItem *menuItem ) + wxItemKind kind, wxMenu *subMenu, wxMenuItem *menuItem ) : QAction( wxQtConvertString( text ), handler->GetHandle() ), - wxQtSignalHandler( handler ), + m_handler(handler), m_mitemId(menuItem->GetId()), m_isCheckable(menuItem->IsCheckable()) { setStatusTip( wxQtConvertString( help )); @@ -259,13 +283,3 @@ void wxQtAction::UpdateShortcuts(const wxString& text) wxUnusedVar(text); #endif // wxUSE_ACCEL } - -void wxQtAction::onActionToggled( bool checked ) -{ - GetMenu()->Check(m_mitemId, checked); -} - -void wxQtAction::onActionTriggered( bool checked ) -{ - GetMenu()->SendEvent(m_mitemId, m_isCheckable ? checked : -1 ); -} diff --git a/src/qt/window.cpp b/src/qt/window.cpp index c88fca784d..16974f8b2e 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -218,27 +218,24 @@ void wxQtScrollArea::OnSliderReleased() } #if wxUSE_ACCEL || defined( Q_MOC_RUN ) -class wxQtShortcutHandler : public QObject, public wxQtSignalHandler + +class wxQtShortcutHandler : public QObject { - public: - wxQtShortcutHandler( wxWindowQt *window ); + explicit wxQtShortcutHandler( wxWindow *handler ) : m_handler(handler) { } -public: - void activated(); + void activated() + { + const int command = sender()->property("wxQt_Command").toInt(); + + m_handler->QtHandleShortcut( command ); + } + +private: + + wxWindow* const m_handler; }; -wxQtShortcutHandler::wxQtShortcutHandler( wxWindowQt *window ) - : wxQtSignalHandler( window ) -{ -} - -void wxQtShortcutHandler::activated() -{ - int command = sender()->property("wxQt_Command").toInt(); - - static_cast(GetHandler())->QtHandleShortcut( command ); -} #endif // wxUSE_ACCEL //##############################################################################