1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <com/sun/star/awt/MouseButton.hpp>
12 #include <com/sun/star/datatransfer/DataFlavor.hpp>
13 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
14 #include <cppuhelper/supportsservice.hxx>
15 #include <sal/log.hxx>
17 #include <Qt5DragAndDrop.hxx>
18 #include <Qt5Frame.hxx>
19 #include <Qt5Transferable.hxx>
20 #include <Qt5Widget.hxx>
22 #include <QtGui/QDrag>
24 using namespace com::sun::star
;
26 Qt5DragSource::~Qt5DragSource() {}
28 void Qt5DragSource::deinitialize() { m_pFrame
= nullptr; }
30 sal_Bool
Qt5DragSource::isDragImageSupported() { return true; }
32 sal_Int32
Qt5DragSource::getDefaultCursor(sal_Int8
) { return 0; }
34 void Qt5DragSource::initialize(const css::uno::Sequence
<css::uno::Any
>& rArguments
)
36 if (rArguments
.getLength() < 2)
38 throw uno::RuntimeException("DragSource::initialize: Cannot install window event handler",
39 static_cast<OWeakObject
*>(this));
42 sal_IntPtr nFrame
= 0;
43 rArguments
.getConstArray()[1] >>= nFrame
;
47 throw uno::RuntimeException("DragSource::initialize: missing SalFrame",
48 static_cast<OWeakObject
*>(this));
51 m_pFrame
= reinterpret_cast<Qt5Frame
*>(nFrame
);
52 m_pFrame
->registerDragSource(this);
55 void Qt5DragSource::startDrag(
56 const datatransfer::dnd::DragGestureEvent
& /*rEvent*/, sal_Int8 sourceActions
,
57 sal_Int32
/*cursor*/, sal_Int32
/*image*/,
58 const css::uno::Reference
<css::datatransfer::XTransferable
>& rTrans
,
59 const css::uno::Reference
<css::datatransfer::dnd::XDragSourceListener
>& rListener
)
61 m_xListener
= rListener
;
65 QDrag
* drag
= new QDrag(m_pFrame
->GetQWidget());
66 drag
->setMimeData(new Qt5MimeData(rTrans
));
67 // just a reminder that exec starts a nested event loop, so everything after
68 // this call is just executed, after D'n'D has finished!
69 drag
->exec(toQtDropActions(sourceActions
), getPreferredDropAction(sourceActions
));
72 // the drop will eventually call fire_dragEnd, which will clear the listener.
73 // if D'n'D ends without success, we just get a leave event without any indicator,
74 // but the event loop will be terminated, so we have to try to inform the source of
75 // a failure in any way.
76 fire_dragEnd(datatransfer::dnd::DNDConstants::ACTION_NONE
, false);
79 void Qt5DragSource::fire_dragEnd(sal_Int8 nAction
, bool bDropSuccessful
)
81 if (!m_xListener
.is())
84 datatransfer::dnd::DragSourceDropEvent aEv
;
85 aEv
.DropAction
= nAction
;
86 aEv
.DropSuccess
= bDropSuccessful
;
88 auto xListener
= m_xListener
;
90 xListener
->dragDropEnd(aEv
);
93 OUString SAL_CALL
Qt5DragSource::getImplementationName()
95 return "com.sun.star.datatransfer.dnd.VclQt5DragSource";
98 sal_Bool SAL_CALL
Qt5DragSource::supportsService(OUString
const& ServiceName
)
100 return cppu::supportsService(this, ServiceName
);
103 css::uno::Sequence
<OUString
> SAL_CALL
Qt5DragSource::getSupportedServiceNames()
105 return { "com.sun.star.datatransfer.dnd.Qt5DragSource" };
108 Qt5DropTarget::Qt5DropTarget()
109 : WeakComponentImplHelper(m_aMutex
)
112 , m_nDefaultActions(0)
116 OUString SAL_CALL
Qt5DropTarget::getImplementationName()
118 return "com.sun.star.datatransfer.dnd.VclQt5DropTarget";
121 sal_Bool SAL_CALL
Qt5DropTarget::supportsService(OUString
const& ServiceName
)
123 return cppu::supportsService(this, ServiceName
);
126 css::uno::Sequence
<OUString
> SAL_CALL
Qt5DropTarget::getSupportedServiceNames()
128 return { "com.sun.star.datatransfer.dnd.Qt5DropTarget" };
131 Qt5DropTarget::~Qt5DropTarget() {}
133 void Qt5DropTarget::deinitialize()
139 void Qt5DropTarget::initialize(const uno::Sequence
<uno::Any
>& rArguments
)
141 if (rArguments
.getLength() < 2)
143 throw uno::RuntimeException("DropTarget::initialize: Cannot install window event handler",
144 static_cast<OWeakObject
*>(this));
147 sal_IntPtr nFrame
= 0;
148 rArguments
.getConstArray()[1] >>= nFrame
;
152 throw uno::RuntimeException("DropTarget::initialize: missing SalFrame",
153 static_cast<OWeakObject
*>(this));
156 m_nDropAction
= datatransfer::dnd::DNDConstants::ACTION_NONE
;
158 m_pFrame
= reinterpret_cast<Qt5Frame
*>(nFrame
);
159 m_pFrame
->registerDropTarget(this);
163 void Qt5DropTarget::addDropTargetListener(
164 const uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
)
166 ::osl::Guard
<::osl::Mutex
> aGuard(m_aMutex
);
168 m_aListeners
.push_back(xListener
);
171 void Qt5DropTarget::removeDropTargetListener(
172 const uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
)
174 ::osl::Guard
<::osl::Mutex
> aGuard(m_aMutex
);
176 m_aListeners
.erase(std::remove(m_aListeners
.begin(), m_aListeners
.end(), xListener
),
180 sal_Bool
Qt5DropTarget::isActive() { return m_bActive
; }
182 void Qt5DropTarget::setActive(sal_Bool bActive
) { m_bActive
= bActive
; }
184 sal_Int8
Qt5DropTarget::getDefaultActions() { return m_nDefaultActions
; }
186 void Qt5DropTarget::setDefaultActions(sal_Int8 nDefaultActions
)
188 m_nDefaultActions
= nDefaultActions
;
191 void Qt5DropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtde
)
193 osl::ClearableGuard
<::osl::Mutex
> aGuard(m_aMutex
);
194 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
198 for (auto const& listener
: aListeners
)
200 listener
->dragEnter(dtde
);
204 void Qt5DropTarget::fire_dragOver(const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtde
)
206 osl::ClearableGuard
<::osl::Mutex
> aGuard(m_aMutex
);
207 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
211 for (auto const& listener
: aListeners
)
212 listener
->dragOver(dtde
);
215 void Qt5DropTarget::fire_drop(const css::datatransfer::dnd::DropTargetDropEvent
& dtde
)
217 m_bDropSuccessful
= true;
219 osl::ClearableGuard
<osl::Mutex
> aGuard(m_aMutex
);
220 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
224 for (auto const& listener
: aListeners
)
225 listener
->drop(dtde
);
228 void Qt5DropTarget::fire_dragExit(const css::datatransfer::dnd::DropTargetEvent
& dte
)
230 osl::ClearableGuard
<::osl::Mutex
> aGuard(m_aMutex
);
231 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
235 for (auto const& listener
: aListeners
)
236 listener
->dragExit(dte
);
239 void Qt5DropTarget::acceptDrag(sal_Int8 dragOperation
) { m_nDropAction
= dragOperation
; }
241 void Qt5DropTarget::rejectDrag() { m_nDropAction
= 0; }
243 void Qt5DropTarget::acceptDrop(sal_Int8 dropOperation
) { m_nDropAction
= dropOperation
; }
245 void Qt5DropTarget::rejectDrop() { m_nDropAction
= 0; }
247 void Qt5DropTarget::dropComplete(sal_Bool success
)
249 m_bDropSuccessful
= (m_bDropSuccessful
&& success
);
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */