There are two ways to add drag and drop to a plug-in's GUI depending on what items need to be handled.
bool CustomWindow::accept(SessionItem *pItem) const { return dynamic_cast<RasterElement*>(pItem) != NULL; }
The first signal's argument is a SessionItem pointer and is emitted once for each SessionItem in the event, not just SessionItems accepted by the drop filter. The second signal's argument is a std::vector of SessionItem pointers containing all SessionItems in the event, not just SessionItems accepted by the drop filter.
An example event handler is presented below. This handler is attached to the Window::signalSessionItemDropped() signal.
void CustomWindow::dropSessionItem(Subject& subject, const string& signal, const boost::any& value) { RasterElement* pRaster = dynamic_cast<RasterElement*>(boost::any_cast<SessionItem*>(value)); if(pRaster != NULL) { watchNewRasterElement(pRaster); } }
First, the drop target needs an event handler installed and drops need to be enabled. The drop target can be any QWidget, including widgets which the plug-in does not implement such as SpatialDataView as in the example below.
CustomWidget::CustomWidget()
{
std::vector<Window*> windows;
Service<DesktopServices>()->getWindows(SPATIAL_DATA_WINDOW, windows);
for(std::vector<Window*>::iterator window = windows.begin(); window != windows.end(); ++window)
{
SpatialDataWindow* pWindow = static_cast<SpatialDataWindow*>(*window);
if(pWindow != NULL)
{
pWindow->getWidget()->installEventFilter(this);
pWindow->getWidget()->setAcceptDrops(true);
}
}
}
CustomWidget::~CustomWidget()
{
std::vector<Window*> windows;
Service<DesktopServices>()->getWindows(SPATIAL_DATA_WINDOW, windows);
for(std::vector<Window*>::iterator window = windows.begin(); window != windows.end(); ++window)
{
SpatialDataWindow* pWindow = static_cast<SpatialDataWindow*>(*window);
if(pWindow != NULL)
{
pWindow->getWidget()->removeEventFilter(this);
}
}
}
The event filter should handle DragEnter and Drop events as in the below example.
bool CustomWidget::eventFilter(QObject *pObj, QEvent *pEvent) { SpatialDataView* pView = dynamic_cast<SpatialDataView*>(pObj); switch(pEvent->type()) { case QEvent::DragEnter: windowDragEnterEvent(pView, static_cast<QDragEnterEvent*>(pEvent)); return pEvent->isAccepted(); case QEvent::Drop: windowDropEvent(pView, static_cast<QDropEvent*>(pEvent)); return pEvent->isAccepted(); } return false; } void CustomWidget::windowDragEnterEvent(SpatialDataView *pView, QDragEnterEvent *pEvent) { if(pEvent != NULL && pEvent->mimeData()->hasFormat("text/x-session-id")) { pEvent->acceptProposedAction(); } } void CustomWidget::windowDropEvent(SpatialDataView *pView, QDropEvent *pEvent) { VERIFYNRV(pEvent && pView); QString sessionId(pEvent->mimeData()->data("text/x-session-id")); SessionItem* pSessionItem = Service<SessionManager>()->getSessionItem(sessionId); if(pSessionItem != NULL) { watchSessionItem(pSessionItem); pEvent->accept(); } }
This example accepts drops with the text/x-session-id MIME type. This is the MIME type emitted by the session explorer on session item drags and is normally handled by Dropping session items into a custom window.. The MIME type accepted can be text/x-session-id, any standard Qt drag-and-drop MIME type, or a custom MIME type emitted by a plug-in widget. See the Qt documentation on drag-and-drop for information on generating drag events.