Implement initial try of wxDropTarget.

The drop target needs to use an event filter to capture drag-and-drop events from the window.
This commit is contained in:
Jay Nabonne 2019-01-29 16:13:41 +00:00
parent 0dc1654ab6
commit 323cbdabdb
5 changed files with 211 additions and 19 deletions

View File

@ -10,22 +10,30 @@
#define wxDROP_ICON(name) wxICON(name)
class QMimeData;
class WXDLLIMPEXP_CORE wxDropTarget : public wxDropTargetBase
{
public:
wxDropTarget(wxDataObject *dataObject = NULL);
virtual bool OnDrop(wxCoord x, wxCoord y);
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def);
virtual bool GetData();
virtual bool OnDrop(wxCoord x, wxCoord y) wxOVERRIDE;
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) wxOVERRIDE;
virtual bool GetData() wxOVERRIDE;
wxDataFormat GetMatchingPair();
protected:
void OnQtEnter(QEvent* event);
void OnQtLeave(QEvent* event);
void OnQtMove(QEvent* event);
void OnQtDrop(QEvent* event);
private:
};
class PendingMimeDataSetter;
friend class PendingMimeDataSetter;
const QMimeData* m_pendingMimeData;
};
class WXDLLIMPEXP_CORE wxDropSource: public wxDropSourceBase
{

View File

@ -10,6 +10,7 @@
#define _WX_QT_WINDOW_H_
#include <list>
#include <QObject>
class QShortcut;
template < class T > class QList;
@ -216,6 +217,16 @@ protected:
QWidget *m_qtWindow;
private:
class DnDEventAdapter : public QObject
{
public:
DnDEventAdapter();
virtual bool eventFilter(QObject* watched, QEvent* event);
void SetDropTarget(wxDropTarget* dropTarget, QWidget* window);
private:
wxDropTarget *m_dropTarget;
};
void Init();
QScrollArea *m_qtContainer;
@ -238,6 +249,10 @@ private:
bool m_processingShortcut;
#endif // wxUSE_ACCEL
#if wxUSE_DRAG_AND_DROP
DnDEventAdapter dnd_event_adapter;
#endif
wxDECLARE_DYNAMIC_CLASS_NO_COPY( wxWindowQt );
};

View File

@ -102,6 +102,12 @@ bool wxDataFormat::operator!=(wxDataFormatId format) const
bool wxDataFormat::operator==(const wxDataFormat& format) const
{
// If mime types match, then that's good enough.
// (Could be comparing a standard constructed format to a
// custom constructed one, where both are actually the same.)
if (!m_mimeType.empty() && m_mimeType == format.m_mimeType)
return true;
return m_mimeType == format.m_mimeType
&& m_formatId == format.m_formatId;
}

View File

@ -18,6 +18,7 @@
#include <QDrag>
#include <QWidget>
#include <QMimeData>
#include <QCloseEvent>
namespace
{
@ -38,6 +39,21 @@ namespace
}
}
Qt::DropAction DragResultToDropAction(wxDragResult result)
{
switch ( result )
{
case wxDragCopy:
return Qt::CopyAction;
case wxDragMove:
return Qt::MoveAction;
case wxDragLink:
return Qt::LinkAction;
default:
return Qt::IgnoreAction;
}
}
void AddDataFormat(wxDataObject* dataObject, QMimeData* mimeData, const wxDataFormat& format)
{
const size_t data_size = dataObject->GetDataSize(format);
@ -66,29 +82,120 @@ namespace
}
}
wxDropTarget::wxDropTarget(wxDataObject *WXUNUSED(dataObject))
class wxDropTarget::PendingMimeDataSetter
{
public:
PendingMimeDataSetter(wxDropTarget* dropTarget, const QMimeData* mimeData)
: m_dropTarget(dropTarget)
{
m_dropTarget->m_pendingMimeData = mimeData;
}
~PendingMimeDataSetter()
{
m_dropTarget->m_pendingMimeData = NULL;
}
private:
wxDropTarget* m_dropTarget;
};
wxDropTarget::wxDropTarget(wxDataObject *dataObject)
: wxDropTargetBase(dataObject),
m_pendingMimeData(NULL)
{
}
bool wxDropTarget::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
{
return false;
return !GetMatchingPair().GetMimeType().empty();
}
wxDragResult wxDropTarget::OnData(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResult WXUNUSED(def))
wxDragResult wxDropTarget::OnData(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResult default_drag_result)
{
return wxDragResult();
GetData();
return default_drag_result;
}
bool wxDropTarget::GetData()
{
const wxDataFormat droppedFormat = GetMatchingPair();
const wxString mimeType = droppedFormat.GetMimeType();
if ( mimeType.empty() )
return false;
const QByteArray data = m_pendingMimeData->data(wxQtConvertString(mimeType));
return m_dataObject->SetData(droppedFormat, data.size(), data.data());
}
wxDataFormat wxDropTarget::GetMatchingPair()
{
wxFAIL_MSG("wxDropTarget::GetMatchingPair() not implemented in src/qt/dnd.cpp");
return wxDF_INVALID;
if ( m_pendingMimeData == NULL || m_dataObject == NULL )
return wxFormatInvalid;
const QStringList formats = m_pendingMimeData->formats();
for ( int i = 0; i < formats.count(); ++i )
{
const wxDataFormat format(wxQtConvertString(formats[i]));
if ( m_dataObject->IsSupportedFormat(format) )
{
return format;
}
}
return wxFormatInvalid;
}
void wxDropTarget::OnQtEnter(QEvent* event)
{
event->accept();
QDragEnterEvent *e = static_cast<QDragEnterEvent*>(event);
const QPoint where = e->pos();
PendingMimeDataSetter setter(this, e->mimeData());
wxDragResult result = OnEnter(where.x(), where.y(), DropActionToDragResult(e->proposedAction()));
e->setDropAction(DragResultToDropAction(result));
}
void wxDropTarget::OnQtLeave(QEvent* event)
{
event->accept();
OnLeave();
}
void wxDropTarget::OnQtMove(QEvent* event)
{
event->accept();
QDragMoveEvent *e = static_cast<QDragMoveEvent*>(event);
const QPoint where = e->pos();
PendingMimeDataSetter setter(this, e->mimeData());
wxDragResult result = OnDragOver(where.x(), where.y(), DropActionToDragResult(e->proposedAction()));
e->setDropAction(DragResultToDropAction(result));
}
void wxDropTarget::OnQtDrop(QEvent* event)
{
event->accept();
const QDropEvent *e = static_cast<QDropEvent*>(event);
const QPoint where = e->pos();
PendingMimeDataSetter setter(this, e->mimeData());
if ( OnDrop(where.x(), where.y()) )
{
OnData(where.x(), where.y(), DropActionToDragResult(e->dropAction()));
}
}
//##############################################################################

View File

@ -31,12 +31,12 @@
#endif // WX_PRECOMP
#include "wx/window.h"
#include "wx/dnd.h"
#include "wx/tooltip.h"
#include "wx/qt/private/utils.h"
#include "wx/qt/private/converter.h"
#include "wx/qt/private/winevent.h"
#define VERT_SCROLLBAR_POSITION 0, 1
#define HORZ_SCROLLBAR_POSITION 1, 0
@ -193,9 +193,6 @@ static const char WINDOW_POINTER_PROPERTY_NAME[] = "wxWindowPointer";
return const_cast< wxWindowQt * >( ( variant.value< const wxWindow * >() ));
}
static wxWindowQt *s_capturedWindow = NULL;
/* static */ wxWindowQt *wxWindowBase::DoFindFocus()
@ -225,6 +222,8 @@ void wxWindowQt::Init()
#endif
m_qtWindow = NULL;
m_qtContainer = NULL;
m_dropTarget = NULL;
}
wxWindowQt::wxWindowQt()
@ -688,9 +687,9 @@ void wxWindowQt::ScrollWindow( int dx, int dy, const wxRect *rect )
#if wxUSE_DRAG_AND_DROP
void wxWindowQt::SetDropTarget( wxDropTarget * WXUNUSED( dropTarget ) )
void wxWindowQt::SetDropTarget( wxDropTarget *dropTarget )
{
wxMISSING_IMPLEMENTATION( __FUNCTION__ );
dnd_event_adapter.SetDropTarget(dropTarget, m_qtWindow);
}
#endif
@ -1543,3 +1542,60 @@ QPainter *wxWindowQt::QtGetPainter()
{
return m_qtPainter;
}
//##############################################################################
// DnDEventAdapter
//##############################################################################
wxWindow::DnDEventAdapter::DnDEventAdapter() : m_dropTarget(NULL)
{
}
bool wxWindow::DnDEventAdapter::eventFilter(QObject* watched, QEvent* event)
{
if ( m_dropTarget != NULL )
{
switch ( event->type() )
{
case QEvent::Drop:
m_dropTarget->OnQtDrop(event);
return true;
case QEvent::DragEnter:
m_dropTarget->OnQtEnter(event);
return true;
case QEvent::DragMove:
m_dropTarget->OnQtMove(event);
return true;
case QEvent::DragLeave:
m_dropTarget->OnQtLeave(event);
return true;
default:
break;
}
}
return QObject::eventFilter(watched, event);
}
void wxWindow::DnDEventAdapter::SetDropTarget(wxDropTarget* dropTarget, QWidget* window)
{
if ( m_dropTarget == dropTarget )
return;
m_dropTarget = dropTarget;
if ( m_dropTarget == NULL )
{
window->removeEventFilter(this);
window->setAcceptDrops(false);
}
else
{
window->installEventFilter(this);
window->setAcceptDrops(true);
}
}