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 <QtCore/QMimeData>
18 #include <QtCore/QUrl>
20 #include <Qt5DragAndDrop.hxx>
21 #include <Qt5Frame.hxx>
22 #include <Qt5Widget.hxx>
24 using namespace com::sun::star
;
25 using namespace com::sun::star::uno
;
26 using namespace com::sun::star::lang
;
28 Qt5DnDTransferable::Qt5DnDTransferable(const QMimeData
* pMimeData
)
29 : Qt5Transferable(QClipboard::Clipboard
)
30 , m_pMimeData(pMimeData
)
34 css::uno::Any
Qt5DnDTransferable::getTransferData(const css::datatransfer::DataFlavor
&)
39 // FIXME: not sure if we should support more mimetypes here
40 // (how to carry out external DnD with anything else than [file] URL?)
41 if (m_pMimeData
->hasUrls())
43 QList
<QUrl
> urlList
= m_pMimeData
->urls();
45 if (urlList
.size() > 0)
49 // transfer data is list of URLs
50 for (int i
= 0; i
< urlList
.size(); ++i
)
52 QString url
= urlList
.at(i
).path();
53 aStr
+= url
.toStdString();
54 // separated by newline if more than 1
55 if (i
< urlList
.size() - 1)
59 Sequence
<sal_Int8
> aSeq(reinterpret_cast<const sal_Int8
*>(aStr
.c_str()), aStr
.length());
66 std::vector
<css::datatransfer::DataFlavor
> Qt5DnDTransferable::getTransferDataFlavorsAsVector()
68 std::vector
<css::datatransfer::DataFlavor
> aVector
;
69 css::datatransfer::DataFlavor aFlavor
;
73 for (QString
& rMimeType
: m_pMimeData
->formats())
75 // filter out non-MIME types such as TARGETS, MULTIPLE, TIMESTAMP
76 if (rMimeType
.indexOf('/') == -1)
79 if (rMimeType
.startsWith("text/plain"))
81 aFlavor
.MimeType
= "text/plain;charset=utf-16";
82 aFlavor
.DataType
= cppu::UnoType
<OUString
>::get();
83 aVector
.push_back(aFlavor
);
87 aFlavor
.MimeType
= toOUString(rMimeType
);
88 aFlavor
.DataType
= cppu::UnoType
<Sequence
<sal_Int8
>>::get();
89 aVector
.push_back(aFlavor
);
97 bool Qt5DragSource::m_bDropSuccessSet
= false;
98 bool Qt5DragSource::m_bDropSuccess
= false;
100 Qt5DragSource::~Qt5DragSource()
103 // m_pFrame->deregisterDragSource(this);
106 void Qt5DragSource::deinitialize() { m_pFrame
= nullptr; }
108 sal_Bool
Qt5DragSource::isDragImageSupported() { return true; }
110 sal_Int32
Qt5DragSource::getDefaultCursor(sal_Int8
) { return 0; }
112 void Qt5DragSource::initialize(const css::uno::Sequence
<css::uno::Any
>& rArguments
)
114 if (rArguments
.getLength() < 2)
116 throw RuntimeException("DragSource::initialize: Cannot install window event handler",
117 static_cast<OWeakObject
*>(this));
120 sal_IntPtr nFrame
= 0;
121 rArguments
.getConstArray()[1] >>= nFrame
;
125 throw RuntimeException("DragSource::initialize: missing SalFrame",
126 static_cast<OWeakObject
*>(this));
129 m_pFrame
= reinterpret_cast<Qt5Frame
*>(nFrame
);
130 m_pFrame
->registerDragSource(this);
133 void Qt5DragSource::startDrag(
134 const datatransfer::dnd::DragGestureEvent
& /*rEvent*/, sal_Int8 sourceActions
,
135 sal_Int32
/*cursor*/, sal_Int32
/*image*/,
136 const css::uno::Reference
<css::datatransfer::XTransferable
>& rTrans
,
137 const css::uno::Reference
<css::datatransfer::dnd::XDragSourceListener
>& rListener
)
139 m_xListener
= rListener
;
144 Qt5Widget
* qw
= static_cast<Qt5Widget
*>(m_pFrame
->GetQWidget());
145 m_ActiveDragSource
= this;
146 m_bDropSuccessSet
= false;
147 m_bDropSuccess
= false;
148 qw
->startDrag(sourceActions
);
154 void Qt5DragSource::dragFailed()
156 if (m_xListener
.is())
158 datatransfer::dnd::DragSourceDropEvent aEv
;
159 aEv
.DropAction
= datatransfer::dnd::DNDConstants::ACTION_NONE
;
160 aEv
.DropSuccess
= false;
161 auto xListener
= m_xListener
;
163 xListener
->dragDropEnd(aEv
);
167 void Qt5DragSource::fire_dragEnd(sal_Int8 nAction
)
169 if (m_xListener
.is())
171 datatransfer::dnd::DragSourceDropEvent aEv
;
172 aEv
.DropAction
= nAction
;
174 // internal DnD can accept the drop
175 // but still fail in Qt5DropTarget::dropComplete
176 if (m_bDropSuccessSet
)
177 aEv
.DropSuccess
= m_bDropSuccess
;
179 aEv
.DropSuccess
= true;
181 auto xListener
= m_xListener
;
183 xListener
->dragDropEnd(aEv
);
185 m_ActiveDragSource
= nullptr;
188 OUString SAL_CALL
Qt5DragSource::getImplementationName()
190 return OUString("com.sun.star.datatransfer.dnd.VclQt5DragSource");
193 sal_Bool SAL_CALL
Qt5DragSource::supportsService(OUString
const& ServiceName
)
195 return cppu::supportsService(this, ServiceName
);
198 css::uno::Sequence
<OUString
> SAL_CALL
Qt5DragSource::getSupportedServiceNames()
200 Sequence
<OUString
> aRet
{ "com.sun.star.datatransfer.dnd.Qt5DragSource" };
204 Qt5DropTarget::Qt5DropTarget()
205 : WeakComponentImplHelper(m_aMutex
)
208 , m_nDefaultActions(0)
212 OUString SAL_CALL
Qt5DropTarget::getImplementationName()
214 return OUString("com.sun.star.datatransfer.dnd.VclQt5DropTarget");
217 sal_Bool SAL_CALL
Qt5DropTarget::supportsService(OUString
const& ServiceName
)
219 return cppu::supportsService(this, ServiceName
);
222 css::uno::Sequence
<OUString
> SAL_CALL
Qt5DropTarget::getSupportedServiceNames()
224 Sequence
<OUString
> aRet
{ "com.sun.star.datatransfer.dnd.Qt5DropTarget" };
228 Qt5DropTarget::~Qt5DropTarget()
231 //m_pFrame->deregisterDropTarget(this);
234 void Qt5DropTarget::deinitialize()
240 void Qt5DropTarget::initialize(const Sequence
<Any
>& rArguments
)
242 if (rArguments
.getLength() < 2)
244 throw RuntimeException("DropTarget::initialize: Cannot install window event handler",
245 static_cast<OWeakObject
*>(this));
248 sal_IntPtr nFrame
= 0;
249 rArguments
.getConstArray()[1] >>= nFrame
;
253 throw RuntimeException("DropTarget::initialize: missing SalFrame",
254 static_cast<OWeakObject
*>(this));
257 mnDragAction
= datatransfer::dnd::DNDConstants::ACTION_NONE
;
258 mnDropAction
= datatransfer::dnd::DNDConstants::ACTION_NONE
;
260 m_pFrame
= reinterpret_cast<Qt5Frame
*>(nFrame
);
261 m_pFrame
->registerDropTarget(this);
265 void Qt5DropTarget::addDropTargetListener(
266 const Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
)
268 ::osl::Guard
<::osl::Mutex
> aGuard(m_aMutex
);
270 m_aListeners
.push_back(xListener
);
273 void Qt5DropTarget::removeDropTargetListener(
274 const Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
)
276 ::osl::Guard
<::osl::Mutex
> aGuard(m_aMutex
);
278 m_aListeners
.erase(std::remove(m_aListeners
.begin(), m_aListeners
.end(), xListener
),
282 sal_Bool
Qt5DropTarget::isActive() { return m_bActive
; }
284 void Qt5DropTarget::setActive(sal_Bool bActive
) { m_bActive
= bActive
; }
286 sal_Int8
Qt5DropTarget::getDefaultActions() { return m_nDefaultActions
; }
288 void Qt5DropTarget::setDefaultActions(sal_Int8 nDefaultActions
)
290 m_nDefaultActions
= nDefaultActions
;
293 void Qt5DropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtde
)
295 osl::ClearableGuard
<::osl::Mutex
> aGuard(m_aMutex
);
296 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
300 for (auto const& listener
: aListeners
)
302 listener
->dragEnter(dtde
);
306 void Qt5DropTarget::fire_dragOver(const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtde
)
308 osl::ClearableGuard
<::osl::Mutex
> aGuard(m_aMutex
);
309 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
313 for (auto const& listener
: aListeners
)
315 listener
->dragOver(dtde
);
319 void Qt5DropTarget::fire_drop(const css::datatransfer::dnd::DropTargetDropEvent
& dtde
)
321 osl::ClearableGuard
<osl::Mutex
> aGuard(m_aMutex
);
322 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(
326 for (auto const& listener
: aListeners
)
328 listener
->drop(dtde
);
332 void Qt5DropTarget::acceptDrag(sal_Int8 dragOperation
)
334 mnDragAction
= dragOperation
;
338 void Qt5DropTarget::rejectDrag()
344 void Qt5DropTarget::acceptDrop(sal_Int8 dropOperation
)
346 mnDropAction
= dropOperation
;
350 void Qt5DropTarget::rejectDrop()
356 void Qt5DropTarget::dropComplete(sal_Bool success
)
359 if (Qt5DragSource::m_ActiveDragSource
)
361 Qt5DragSource::m_bDropSuccessSet
= true;
362 Qt5DragSource::m_bDropSuccess
= success
;
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */