Merge branch 'qt-fixes'

A multitude of miscellaneous Qt fixes and improvements.

See https://github.com/wxWidgets/wxWidgets/pull/1552
This commit is contained in:
Vadim Zeitlin 2019-09-27 19:18:11 +02:00
commit 04949050b2
20 changed files with 392 additions and 183 deletions

View File

@ -56,6 +56,9 @@ public:
protected:
virtual void DoGetClientSize(int *width, int *height) const wxOVERRIDE;
virtual void DoSetClientSize(int width, int height) wxOVERRIDE;
virtual QWidget* QtGetParentWidget() const wxOVERRIDE;
private:
// Common part of all ctors.

View File

@ -60,7 +60,7 @@ public:
virtual QWidget *GetHandle() const wxOVERRIDE;
void QtSendEvent(wxEventType evtType, const QModelIndex &index, bool selected);
void QtSendEvent(wxEventType evtType, int rowIndex, bool selected);
protected:
virtual void DoSetFirstItem(int n) wxOVERRIDE;

View File

@ -12,6 +12,7 @@
#include "wx/bitmap.h"
class QAction;
class wxQtAction;
class WXDLLIMPEXP_FWD_CORE wxMenu;
@ -41,7 +42,7 @@ public:
private:
// Qt is using an action instead of a menu item.
QAction *m_qtAction;
wxQtAction *m_qtAction;
wxBitmap m_bitmap;
wxDECLARE_DYNAMIC_CLASS( wxMenuItem );

View File

@ -11,6 +11,7 @@
#define _WX_QT_PRIVATE_TREEITEM_DELEGATE_H
#include <QtWidgets/QStyledItemDelegate>
#include <QtWidgets/QToolTip>
#include "wx/app.h"
#include "wx/textctrl.h"
@ -67,6 +68,28 @@ public:
QStyledItemDelegate::setModelData(editor, model, index);
}
bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if ( event->type() == QEvent::ToolTip )
{
const QRect &itemRect = view->visualRect(index);
const QSize &bestSize = sizeHint(option, index);
if ( itemRect.width() < bestSize.width() )
{
const QString &value = index.data(Qt::DisplayRole).toString();
QToolTip::showText(event->globalPos(), value, view);
}
else
{
QToolTip::hideText();
}
return true;
}
return QStyledItemDelegate::helpEvent(event, view, option, index);
}
private:
wxWindow* m_parent;
mutable wxTextCtrl* m_textCtrl;

View File

@ -61,6 +61,7 @@ public:
QObject::connect( this, &QObject::destroyed, this,
&wxQtEventSignalHandler::HandleDestroyedSignal );
Widget::setMouseTracking(true);
}
void HandleDestroyedSignal()
@ -104,7 +105,7 @@ protected:
if ( !this->GetHandler()->QtHandleCloseEvent(this, event) )
Widget::closeEvent(event);
else
event->accept();
event->ignore();
}
//wxContextMenuEvent

View File

@ -168,6 +168,7 @@ public:
static void QtStoreWindowPointer( QWidget *widget, const wxWindowQt *window );
static wxWindowQt *QtRetrieveWindowPointer( const QWidget *widget );
static void QtSendSetCursorEvent(wxWindowQt* win, wxPoint posClient);
#if wxUSE_ACCEL
virtual void QtHandleShortcut ( int command );
@ -215,6 +216,12 @@ protected:
virtual bool DoPopupMenu(wxMenu *menu, int x, int y) wxOVERRIDE;
#endif // wxUSE_MENUS
// Return the parent to use for children being reparented to us: this is
// overridden in wxFrame to use its central widget rather than the frame
// itself.
virtual QWidget* QtGetParentWidget() const { return GetHandle(); }
QWidget *m_qtWindow;
private:
@ -224,6 +231,11 @@ private:
QScrollBar *m_horzScrollBar; // owned by m_qtWindow when allocated
QScrollBar *m_vertScrollBar; // owned by m_qtWindow when allocated
// Return the viewport of m_qtContainer, if it's used, or just m_qtWindow.
//
// Always returns non-null pointer if the window has been already created.
QWidget *QtGetClientWidget() const;
QScrollBar *QtGetScrollBar( int orientation ) const;
QScrollBar *QtSetScrollBar( int orientation, QScrollBar *scrollBar=NULL );

View File

@ -848,7 +848,7 @@ void wxAuiManager::UpdateHintWindowConfig()
if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) && can_do_transparent)
{
// Make a window to use for a transparent hint
#if defined(__WXMSW__) || defined(__WXGTK__)
#if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXQT__)
m_hintWnd = new wxFrame(m_frame, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxSize(1,1),
wxFRAME_TOOL_WINDOW |

View File

@ -85,8 +85,9 @@ wxAnyButton::wxAnyButton() :
void wxAnyButton::QtCreate(wxWindow *parent)
{
// create the default push button (used in button and bmp button)
m_qtPushButton = new wxQtPushButton( parent, this );
// create the basic push button (used in button and bmp button)
m_qtPushButton = new wxQtPushButton(parent, this);
m_qtPushButton->setAutoDefault(false);
}
void wxAnyButton::QtSetBitmap( const wxBitmap &bitmap )

View File

@ -16,10 +16,10 @@
#include "wx/qt/private/converter.h"
#include <QDrag>
#include <QWidget>
#include <QMimeData>
#include <QCloseEvent>
#include <QtGui/QDrag>
#include <QtWidgets/QWidget>
#include <QtCore/QMimeData>
#include <QtGui/QCloseEvent>
namespace
{

View File

@ -563,7 +563,7 @@ void wxNativeFontInfo::SetFamily(wxFontFamily family)
{
m_qtFont.setStyleHint(ConvertFontFamily(family));
// reset the face name to force qt to choose a new font
m_qtFont.setFamily("");
m_qtFont.setFamily(m_qtFont.defaultFamily());
}
void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))

View File

@ -134,15 +134,16 @@ void wxFrame::SetWindowStyleFlag( long style )
{
wxWindow::SetWindowStyleFlag( style );
QMainWindow *qtFrame = GetQMainWindow();
Qt::WindowFlags qtFlags = qtFrame->windowFlags();
qtFlags |= Qt::CustomizeWindowHint;
Qt::WindowFlags qtFlags = Qt::CustomizeWindowHint;
if ( HasFlag( wxFRAME_TOOL_WINDOW ) )
{
qtFlags &= ~Qt::WindowType_Mask;
qtFlags |= Qt::Tool;
}
else
{
qtFlags |= Qt::Window;
}
if ( HasFlag(wxCAPTION) )
{
@ -183,15 +184,19 @@ void wxFrame::SetWindowStyleFlag( long style )
qtFlags |= Qt::FramelessWindowHint;
}
qtFrame->setWindowFlags(qtFlags);
GetQMainWindow()->setWindowFlags(qtFlags);
}
QWidget* wxFrame::QtGetParentWidget() const
{
return GetQMainWindow()->centralWidget();
}
void wxFrame::AddChild( wxWindowBase *child )
{
// Make sure all children are children of the central widget:
QtReparent( child->GetHandle(), GetQMainWindow()->centralWidget() );
QtReparent( child->GetHandle(), QtGetParentWidget() );
wxFrameBase::AddChild( child );
}
@ -226,6 +231,19 @@ void wxFrame::DoGetClientSize(int *width, int *height) const
}
}
void wxFrame::DoSetClientSize(int width, int height)
{
wxWindow::DoSetClientSize(width, height);
int adjustedWidth, adjustedHeight;
DoGetClientSize(&adjustedWidth, &adjustedHeight);
QWidget *centralWidget = GetQMainWindow()->centralWidget();
QRect geometry = centralWidget->geometry();
geometry.setSize(QSize(adjustedWidth, adjustedHeight));
centralWidget->setGeometry(geometry);
}
QMainWindow *wxFrame::GetQMainWindow() const
{
return static_cast<QMainWindow*>(m_qtWindow);

View File

@ -19,31 +19,51 @@ public:
wxQtListWidget( wxWindow *parent, wxListBox *handler );
private:
void clicked( const QModelIndex &index );
void OnCurrentItemChange(QListWidgetItem *current, QListWidgetItem *previous);
void doubleClicked( const QModelIndex &index );
void itemChanged(QListWidgetItem *item);
};
wxQtListWidget::wxQtListWidget( wxWindow *parent, wxListBox *handler )
: wxQtEventSignalHandler< QListWidget, wxListBox >( parent, handler )
{
connect(this, &QListWidget::clicked, this, &wxQtListWidget::clicked);
connect(this, &QListWidget::currentItemChanged, this, &wxQtListWidget::OnCurrentItemChange);
connect(this, &QListWidget::doubleClicked, this, &wxQtListWidget::doubleClicked);
connect(this, &QListWidget::itemChanged, this, &wxQtListWidget::itemChanged);
}
void wxQtListWidget::clicked(const QModelIndex &index )
void wxQtListWidget::OnCurrentItemChange(QListWidgetItem *current, QListWidgetItem *)
{
if ( !current )
return;
wxListBox *handler = GetHandler();
if ( handler )
handler->QtSendEvent(wxEVT_LISTBOX, index, true);
{
const QModelIndex &index = indexFromItem(current);
handler->QtSendEvent(wxEVT_LISTBOX, index.row(), true);
}
}
void wxQtListWidget::doubleClicked( const QModelIndex &index )
{
wxListBox *handler = GetHandler();
if ( handler )
handler->QtSendEvent(wxEVT_LISTBOX_DCLICK, index, true);
handler->QtSendEvent(wxEVT_LISTBOX_DCLICK, index.row(), true);
}
void wxQtListWidget::itemChanged(QListWidgetItem *item)
{
if ( item->flags() & Qt::ItemIsUserCheckable )
{
wxListBox *handler = GetHandler();
if ( handler )
{
int rowIndex = this->row(item);
handler->QtSendEvent(wxEVT_CHECKLISTBOX, rowIndex, true);
}
}
}
wxListBox::wxListBox() :
m_qtListWidget(NULL)
@ -282,9 +302,9 @@ QWidget *wxListBox::GetHandle() const
return m_qtListWidget;
}
void wxListBox::QtSendEvent(wxEventType evtType, const QModelIndex &index, bool selected)
void wxListBox::QtSendEvent(wxEventType evtType, int rowIndex, bool selected)
{
SendEvent(evtType, index.row(), selected);
SendEvent(evtType, rowIndex, selected);
}
QScrollArea *wxListBox::QtGetScrollBarsContainer() const

View File

@ -25,6 +25,10 @@ public:
wxQtAction( wxMenu *parent, int id, const wxString &text, const wxString &help,
wxItemKind kind, wxMenu *subMenu, wxMenuItem *handler );
// Set the action shortcut to correspond to the accelerator specified by
// the given label.
void UpdateShortcutsFromLabel(const wxString& text);
private:
void onActionTriggered( bool checked );
};
@ -51,6 +55,8 @@ void wxMenuItem::SetItemLabel( const wxString &label )
{
wxMenuItemBase::SetItemLabel( label );
m_qtAction->UpdateShortcutsFromLabel( label );
m_qtAction->setText( wxQtConvertString( label ));
}
@ -161,8 +167,20 @@ wxQtAction::wxQtAction( wxMenu *parent, int id, const wxString &text, const wxSt
}
connect( this, &QAction::triggered, this, &wxQtAction::onActionTriggered );
UpdateShortcutsFromLabel( text );
}
void wxQtAction::UpdateShortcutsFromLabel(const wxString& text)
{
#if wxUSE_ACCEL
const wxString accelStr = text.AfterFirst('\t');
if ( !accelStr.empty() )
{
setShortcut( QKeySequence( wxQtConvertString(accelStr) ) );
}
#endif // wxUSE_ACCEL
}
void wxQtAction::onActionTriggered( bool checked )
{

View File

@ -14,6 +14,7 @@
#include "wx/qt/private/winevent.h"
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QTabBar>
class wxQtTabWidget : public wxQtEventSignalHandler< QTabWidget, wxNotebook >
{
@ -162,7 +163,10 @@ bool wxNotebook::InsertPage(size_t n, wxWindow *page, const wxString& text,
wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
{
return sizePage;
QTabBar *tabBar = m_qtTabWidget->tabBar();
const QSize &tabBarSize = tabBar->size();
return wxSize(sizePage.GetWidth(),
sizePage.GetHeight() + tabBarSize.height());
}
bool wxNotebook::DeleteAllPages()
@ -192,8 +196,8 @@ int wxNotebook::SetSelection(size_t page)
int selOld = GetSelection();
// change the QTabWidget selected page:
m_selection = page;
m_qtTabWidget->setCurrentIndex( page );
m_selection = page;
return selOld;
}

View File

@ -80,6 +80,7 @@ bool wxSlider::Create(wxWindow *parent,
m_qtSlider->blockSignals(true);
SetRange( minValue, maxValue );
m_qtSlider->blockSignals(false);
SetPageSize(wxMax(1, (maxValue - minValue) / 10));
#if 0 // there are not normally ticks for a wxSlider
// draw ticks marks (default bellow if horizontal, right if vertical):

View File

@ -47,7 +47,6 @@ bool wxStaticText::Create(wxWindow *parent,
const wxString &name)
{
m_qtLabel = new wxQtStaticText( parent, this );
m_qtLabel->setText( wxQtConvertString( label ) );
// Set the buddy to itself to get the mnemonic key but ensure that we don't have
// any unwanted side effects, so disable the interaction:
@ -64,7 +63,12 @@ bool wxStaticText::Create(wxWindow *parent,
else
m_qtLabel->setAlignment(Qt::AlignLeft);
return QtCreateControl( parent, id, pos, size, style, wxDefaultValidator, name );
if ( !QtCreateControl(parent, id, pos, size, style, wxDefaultValidator, name) )
return false;
SetLabel(label);
return true;
}
void wxStaticText::SetLabel(const wxString& label)

View File

@ -23,6 +23,7 @@
#include <QtWidgets/QTreeWidget>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QScrollBar>
#include <QtGui/QPainter>
namespace
@ -142,6 +143,8 @@ public:
this, &wxQTreeWidget::OnItemCollapsed);
connect(this, &QTreeWidget::itemExpanded,
this, &wxQTreeWidget::OnItemExpanded);
connect(verticalScrollBar(), &QScrollBar::valueChanged,
this, &wxQTreeWidget::OnTreeScrolled);
setItemDelegate(&m_item_delegate);
setDragEnabled(true);
@ -244,6 +247,12 @@ public:
return m_placeHolderImage;
}
void select(QTreeWidgetItem* item, QItemSelectionModel::SelectionFlag selectionFlag)
{
const QModelIndex &index = indexFromItem(item);
selectionModel()->select(index, selectionFlag);
}
protected:
virtual void drawRow(
QPainter *painter,
@ -432,6 +441,12 @@ private:
EmitEvent(expandedEvent);
}
void OnTreeScrolled(int)
{
if ( GetEditControl() != NULL )
closeEditor(GetEditControl()->GetHandle(), QAbstractItemDelegate::RevertModelCache);
}
void tryStartDrag(const QMouseEvent *event)
{
wxEventType command = event->buttons() & Qt::RightButton
@ -448,14 +463,14 @@ private:
tree_event.SetPoint(wxQtConvertPoint(event->pos()));
// Vetoed unless explicitly accepted.
// Client must explicitly accept drag and drop. Vetoed by default.
tree_event.Veto();
EmitEvent(tree_event);
if ( !tree_event.IsAllowed() )
{
setState(DragSelectingState);
setState(NoState);
}
}
@ -1158,25 +1173,19 @@ void wxTreeCtrl::Toggle(const wxTreeItemId& item)
wxCHECK_RET(item.IsOk(), "invalid tree item");
QTreeWidgetItem *qTreeItem = wxQtConvertTreeItem(item);
qTreeItem->setSelected(!qTreeItem->isSelected());
qTreeItem->setExpanded(!qTreeItem->isExpanded());
}
void wxTreeCtrl::Unselect()
{
QTreeWidgetItem *current = m_qtTreeWidget->currentItem();
if ( current != NULL )
current->setSelected(false);
m_qtTreeWidget->select(current, QItemSelectionModel::Deselect);
}
void wxTreeCtrl::UnselectAll()
{
QList<QTreeWidgetItem *> selections = m_qtTreeWidget->selectedItems();
const size_t selectedCount = selections.size();
for ( size_t i = 0; i < selectedCount; ++i)
{
selections[i]->setSelected(false);
}
m_qtTreeWidget->selectionModel()->clearSelection();
}
void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
@ -1189,7 +1198,15 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
}
QTreeWidgetItem *qTreeItem = wxQtConvertTreeItem(item);
qTreeItem->setSelected(select);
if ( qTreeItem )
{
m_qtTreeWidget->select(qTreeItem, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
if ( select && m_qtTreeWidget->selectionMode() == QTreeWidget::SingleSelection )
{
m_qtTreeWidget->setCurrentItem(qTreeItem);
}
}
}
void wxTreeCtrl::SelectChildren(const wxTreeItemId& parent)
@ -1201,7 +1218,7 @@ void wxTreeCtrl::SelectChildren(const wxTreeItemId& parent)
for ( int i = 0; i < childCount; ++i )
{
qTreeItem->child(i)->setSelected(true);
m_qtTreeWidget->select(qTreeItem->child(i), QItemSelectionModel::Select);
}
}

View File

@ -59,9 +59,10 @@ wxQtWidget::wxQtWidget( wxWindowQt *parent, wxWindowQt *handler )
class wxQtScrollArea : public wxQtEventSignalHandler< QScrollArea, wxWindowQt >
{
public:
wxQtScrollArea(wxWindowQt *parent, wxWindowQt *handler);
public:
wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler );
bool event(QEvent *e) wxOVERRIDE;
};
wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler )
@ -69,6 +70,27 @@ wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler )
{
}
bool wxQtScrollArea::event(QEvent *e)
{
wxWindowQt* handler = GetHandler();
if ( handler && handler->HasCapture() )
{
switch ( e->type() )
{
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::Wheel:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
return viewportEvent(e);
default:
break;
}
}
return QScrollArea::event(e);
}
class wxQtInternalScrollBar : public wxQtEventSignalHandler< QScrollBar, wxWindowQt >
{
public:
@ -193,6 +215,30 @@ static const char WINDOW_POINTER_PROPERTY_NAME[] = "wxWindowPointer";
return const_cast< wxWindowQt * >( ( variant.value< const wxWindow * >() ));
}
/* static */
void wxWindowQt::QtSendSetCursorEvent(wxWindowQt* win, wxPoint posScreen)
{
wxWindowQt* w = win;
for ( ;; )
{
const wxPoint posClient = w->ScreenToClient(posScreen);
wxSetCursorEvent event(posClient.x, posClient.y);
event.SetEventObject(w);
const bool processedEvtSetCursor = w->ProcessWindowEvent(event);
if ( processedEvtSetCursor && event.HasCursor() )
{
win->SetCursor(event.GetCursor());
return;
}
w = w->GetParent();
if ( w == NULL )
break;
}
win->SetCursor(wxCursor(wxCURSOR_ARROW));
}
static wxWindowQt *s_capturedWindow = NULL;
/* static */ wxWindowQt *wxWindowBase::DoFindFocus()
@ -297,8 +343,6 @@ bool wxWindowQt::Create( wxWindowQt * parent, wxWindowID id, const wxPoint & pos
m_qtWindow = new wxQtWidget( parent, this );
}
GetHandle()->setMouseTracking(true);
if ( !wxWindowBase::CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
return false;
@ -437,7 +481,7 @@ bool wxWindowQt::Reparent( wxWindowBase *parent )
if ( !wxWindowBase::Reparent( parent ))
return false;
QtReparent( GetHandle(), parent->GetHandle() );
QtReparent( GetHandle(), static_cast<wxWindow*>(parent)->QtGetParentWidget() );
return true;
}
@ -560,6 +604,23 @@ void wxWindowQt::DoGetTextExtent(const wxString& string, int *x, int *y, int *de
*externalLeading = fontMetrics.lineSpacing();
}
QWidget *wxWindowQt::QtGetClientWidget() const
{
QWidget *qtWidget = NULL;
if ( m_qtContainer != NULL )
{
qtWidget = m_qtContainer->viewport();
}
if ( qtWidget == NULL )
{
// We don't have scrollbars or the QScrollArea has no children
qtWidget = GetHandle();
}
return qtWidget;
}
/* Returns a scrollbar for the given orientation, or NULL if the scrollbar
* has not been previously created and create is false */
QScrollBar *wxWindowQt::QtGetScrollBar( int orientation ) const
@ -935,7 +996,10 @@ void wxWindowQt::DoSetSize(int x, int y, int width, int height, int sizeFlags )
void wxWindowQt::DoGetClientSize(int *width, int *height) const
{
QRect geometry = GetHandle()->geometry();
QWidget *qtWidget = QtGetClientWidget();
wxCHECK_RET( qtWidget, "window must be created" );
const QRect geometry = qtWidget->geometry();
if (width) *width = geometry.width();
if (height) *height = geometry.height();
}
@ -943,7 +1007,9 @@ void wxWindowQt::DoGetClientSize(int *width, int *height) const
void wxWindowQt::DoSetClientSize(int width, int height)
{
QWidget *qtWidget = GetHandle();
QWidget *qtWidget = QtGetClientWidget();
wxCHECK_RET( qtWidget, "window must be created" );
QRect geometry = qtWidget->geometry();
geometry.setWidth( width );
geometry.setHeight( height );
@ -955,9 +1021,19 @@ void wxWindowQt::DoMoveWindow(int x, int y, int width, int height)
QWidget *qtWidget = GetHandle();
qtWidget->move( x, y );
qtWidget->resize( width, height );
}
// There doesn't seem to be any way to change Qt frame size directly, so
// change the widget size, but take into account the extra margins
// corresponding to the frame decorations.
const QSize frameSize = qtWidget->frameSize();
const QSize innerSize = qtWidget->geometry().size();
const QSize frameSizeDiff = frameSize - innerSize;
const int clientWidth = std::max(width - frameSizeDiff.width(), 0);
const int clientHeight = std::max(height - frameSizeDiff.height(), 0);
qtWidget->resize(clientWidth, clientHeight);
}
#if wxUSE_TOOLTIPS
void wxWindowQt::QtApplyToolTip(const wxString& text)
@ -983,9 +1059,10 @@ void wxWindowQt::DoSetToolTip( wxToolTip *tip )
#if wxUSE_MENUS
bool wxWindowQt::DoPopupMenu(wxMenu *menu, int x, int y)
{
menu->UpdateUI();
menu->GetHandle()->exec( GetHandle()->mapToGlobal( QPoint( x, y ) ) );
return ( true );
return true;
}
#endif // wxUSE_MENUS
@ -1424,11 +1501,15 @@ bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event )
}
// Fill the event
QPoint mousePos = event->pos();
// Use screen position as the event might originate from a different
// Qt window than this one.
wxPoint mousePos = ScreenToClient(wxQtConvertPoint(event->globalPos()));
wxMouseEvent e( wxType );
e.SetEventObject(this);
e.m_clickCount = -1;
e.SetPosition( wxQtConvertPoint( mousePos ) );
e.SetPosition(mousePos);
// Mouse buttons
wxQtFillMouseButtons( event->buttons(), &e );
@ -1440,8 +1521,8 @@ bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event )
// Determine if mouse is inside the widget
bool mouseInside = true;
if ( mousePos.x() < 0 || mousePos.x() > handler->width() ||
mousePos.y() < 0 || mousePos.y() > handler->height() )
if ( mousePos.x < 0 || mousePos.x > handler->width() ||
mousePos.y < 0 || mousePos.y > handler->height() )
mouseInside = false;
if ( e.GetEventType() == wxEVT_MOTION )
@ -1460,6 +1541,8 @@ bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event )
ProcessWindowEvent( e );
}
QtSendSetCursorEvent(this, wxQtConvertPoint( event->globalPos()));
}
m_mouseInside = mouseInside;
@ -1521,18 +1604,27 @@ bool wxWindowQt::QtHandleChangeEvent ( QWidget *handler, QEvent *event )
return false;
}
// Returns true if the closing should be vetoed and false if the window should be closed.
bool wxWindowQt::QtHandleCloseEvent ( QWidget *handler, QCloseEvent *WXUNUSED( event ) )
{
if ( GetHandle() != handler )
return false;
return Close();
// This is required as Qt will still send out close events when the window is disabled.
if ( !IsEnabled() )
return true;
return !Close();
}
bool wxWindowQt::QtHandleContextMenuEvent ( QWidget *WXUNUSED( handler ), QContextMenuEvent *event )
{
wxContextMenuEvent e( wxEVT_CONTEXT_MENU, GetId() );
e.SetPosition( wxQtConvertPoint( event->globalPos() ) );
e.SetPosition(
event->reason() == QContextMenuEvent::Keyboard
? wxDefaultPosition
: wxQtConvertPoint( event->globalPos() )
);
e.SetEventObject(this);
return ProcessWindowEvent( e );

View File

@ -21,78 +21,36 @@
#include "wx/window.h"
#endif // WX_PRECOMP
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
#include "wx/scopedptr.h"
class ClientSizeTestCase : public CppUnit::TestCase
{
public:
ClientSizeTestCase() { }
virtual void setUp() wxOVERRIDE;
virtual void tearDown() wxOVERRIDE;
private:
CPPUNIT_TEST_SUITE( ClientSizeTestCase );
CPPUNIT_TEST( ClientToWindow );
CPPUNIT_TEST( ClientSizeNotNegative );
CPPUNIT_TEST( WindowToClient );
CPPUNIT_TEST_SUITE_END();
void ClientToWindow();
void ClientSizeNotNegative();
void WindowToClient();
wxWindow *m_win;
wxDECLARE_NO_COPY_CLASS(ClientSizeTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( ClientSizeTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ClientSizeTestCase, "ClientSizeTestCase" );
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void ClientSizeTestCase::setUp()
{
m_win = wxTheApp->GetTopWindow();
}
void ClientSizeTestCase::tearDown()
{
m_win = NULL;
}
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// tests themselves
// ----------------------------------------------------------------------------
void ClientSizeTestCase::ClientToWindow()
TEST_CASE("wxWindow::ClientWindowSizeRoundTrip", "[window][client-size]")
{
CPPUNIT_ASSERT(m_win->GetSize() ==
m_win->ClientToWindowSize(m_win->GetClientSize()));
wxWindow* const w = wxTheApp->GetTopWindow();
REQUIRE( w );
const wxSize sizeWindow = w->GetSize();
const wxSize sizeClient = w->GetClientSize();
INFO("client size: " << sizeClient);
CHECK( sizeWindow == w->ClientToWindowSize(sizeClient) );
INFO("window size: " << sizeWindow);
CHECK( sizeClient == w->WindowToClientSize(sizeWindow) );
}
void ClientSizeTestCase::ClientSizeNotNegative()
TEST_CASE("wxWindow::MinClientSize", "[window][client-size]")
{
wxWindow* w = new wxWindow(wxTheApp->GetTopWindow(), -1,
wxDefaultPosition, wxDefaultSize,
wxBORDER_THEME);
wxScopedPtr<wxWindow> w(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxBORDER_THEME));
w->SetSize(wxSize(1,1));
const wxSize szw = w->GetClientSize();
CPPUNIT_ASSERT(szw.GetWidth() >= 0);
CPPUNIT_ASSERT(szw.GetHeight() >= 0);
w->Destroy();
}
void ClientSizeTestCase::WindowToClient()
{
CPPUNIT_ASSERT(m_win->GetClientSize() ==
m_win->WindowToClientSize(m_win->GetSize()));
CHECK(szw.GetWidth() >= 0);
CHECK(szw.GetHeight() >= 0);
}

View File

@ -18,100 +18,136 @@
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/frame.h"
#include "wx/window.h"
#endif // WX_PRECOMP
#include "wx/scopedptr.h"
#include "wx/stopwatch.h"
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test class
// tests helpers
// ----------------------------------------------------------------------------
class SetSizeTestCase : public CppUnit::TestCase
namespace
{
// Helper class overriding DoGetBestSize() for testing purposes.
class MyWindow : public wxWindow
{
public:
SetSizeTestCase() { }
virtual void setUp() wxOVERRIDE;
virtual void tearDown() wxOVERRIDE;
private:
CPPUNIT_TEST_SUITE( SetSizeTestCase );
CPPUNIT_TEST( SetSize );
CPPUNIT_TEST( SetSizeLessThanMinSize );
CPPUNIT_TEST( BestSize );
CPPUNIT_TEST_SUITE_END();
void SetSize();
void SetSizeLessThanMinSize();
void BestSize();
// Helper class overriding DoGetBestSize() for testing purposes.
class MyWindow : public wxWindow
MyWindow(wxWindow* parent)
: wxWindow(parent, wxID_ANY)
{
public:
MyWindow(wxWindow* parent)
: wxWindow(parent, wxID_ANY)
{
}
}
protected:
virtual wxSize DoGetBestSize() const wxOVERRIDE { return wxSize(50, 250); }
};
wxWindow *m_win;
wxDECLARE_NO_COPY_CLASS(SetSizeTestCase);
protected:
virtual wxSize DoGetBestSize() const wxOVERRIDE { return wxSize(50, 250); }
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( SetSizeTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SetSizeTestCase, "SetSizeTestCase" );
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void SetSizeTestCase::setUp()
// Class used to check if we received the (first) paint event.
class WaitForPaint
{
m_win = new MyWindow(wxTheApp->GetTopWindow());
public:
// Note that we have to use a pointer here, i.e. we can't just store the
// flag inside the class itself because it's going to be cloned inside wx
// and querying the flag of the original copy is not going to work.
explicit WaitForPaint(bool* painted)
: m_painted(*painted)
{
m_painted = false;
}
void operator()(wxPaintEvent& event)
{
event.Skip();
m_painted = true;
}
private:
bool& m_painted;
};
// This function should be used to show the window and wait until we can get
// its real geometry.
void ShowAndWaitForPaint(wxWindow* w)
{
// Unfortunately showing the window is asynchronous, at least when using
// X11, so we have to wait for some time before retrieving its true
// geometry. And it's not clear how long should we wait, so we do it until
// we get the first paint event -- by then the window really should have
// its final size.
bool painted;
WaitForPaint waitForPaint(&painted);
w->Bind(wxEVT_PAINT, waitForPaint);
w->Show();
wxStopWatch sw;
while ( !painted )
{
wxYield();
if ( sw.Time() > 250 )
{
WARN("Didn't get a paint event until timeout expiration");
break;
}
}
}
void SetSizeTestCase::tearDown()
{
delete m_win;
m_win = NULL;
}
} // anonymous namespace
// ----------------------------------------------------------------------------
// tests themselves
// ----------------------------------------------------------------------------
void SetSizeTestCase::SetSize()
TEST_CASE("wxWindow::SetSize", "[window][size]")
{
const wxSize size(127, 35);
m_win->SetSize(size);
CPPUNIT_ASSERT_EQUAL( size, m_win->GetSize() );
wxScopedPtr<wxWindow> w(new MyWindow(wxTheApp->GetTopWindow()));
SECTION("Simple")
{
const wxSize size(127, 35);
w->SetSize(size);
CHECK( size == w->GetSize() );
}
SECTION("With min size")
{
w->SetMinSize(wxSize(100, 100));
const wxSize size(200, 50);
w->SetSize(size);
CHECK( size == w->GetSize() );
}
}
void SetSizeTestCase::SetSizeLessThanMinSize()
TEST_CASE("wxWindow::GetBestSize", "[window][size][best-size]")
{
m_win->SetMinSize(wxSize(100, 100));
wxScopedPtr<wxWindow> w(new MyWindow(wxTheApp->GetTopWindow()));
const wxSize size(200, 50);
m_win->SetSize(size);
CPPUNIT_ASSERT_EQUAL( size, m_win->GetSize() );
CHECK( wxSize(50, 250) == w->GetBestSize() );
w->SetMinSize(wxSize(100, 100));
CHECK( wxSize(100, 250) == w->GetBestSize() );
w->SetMaxSize(wxSize(200, 200));
CHECK( wxSize(100, 200) == w->GetBestSize() );
}
void SetSizeTestCase::BestSize()
TEST_CASE("wxWindow::MovePreservesSize", "[window][size][move]")
{
CPPUNIT_ASSERT_EQUAL( wxSize(50, 250), m_win->GetBestSize() );
wxScopedPtr<wxWindow>
w(new wxFrame(wxTheApp->GetTopWindow(), wxID_ANY, "Test child frame"));
m_win->SetMinSize(wxSize(100, 100));
CPPUNIT_ASSERT_EQUAL( wxSize(100, 250), m_win->GetBestSize() );
ShowAndWaitForPaint(w.get());
m_win->SetMaxSize(wxSize(200, 200));
CPPUNIT_ASSERT_EQUAL( wxSize(100, 200), m_win->GetBestSize() );
const wxRect rectOrig = w->GetRect();
// Check that moving the window doesn't change its size.
w->Move(rectOrig.GetPosition() + wxPoint(100, 100));
CHECK( w->GetSize() == rectOrig.GetSize() );
}