bump product version to 6.3.0.0.beta1
[LibreOffice.git] / vcl / qt5 / Qt5DragAndDrop.cxx
blob42e61074a824cd806ea2a08ccbeb93d905e20b5f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 */
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&)
36 uno::Any aAny;
37 assert(m_pMimeData);
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)
47 std::string aStr;
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)
56 aStr += "\n";
59 Sequence<sal_Int8> aSeq(reinterpret_cast<const sal_Int8*>(aStr.c_str()), aStr.length());
60 aAny <<= aSeq;
63 return aAny;
66 std::vector<css::datatransfer::DataFlavor> Qt5DnDTransferable::getTransferDataFlavorsAsVector()
68 std::vector<css::datatransfer::DataFlavor> aVector;
69 css::datatransfer::DataFlavor aFlavor;
71 if (m_pMimeData)
73 for (QString& rMimeType : m_pMimeData->formats())
75 // filter out non-MIME types such as TARGETS, MULTIPLE, TIMESTAMP
76 if (rMimeType.indexOf('/') == -1)
77 continue;
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);
85 else
87 aFlavor.MimeType = toOUString(rMimeType);
88 aFlavor.DataType = cppu::UnoType<Sequence<sal_Int8>>::get();
89 aVector.push_back(aFlavor);
94 return aVector;
97 bool Qt5DragSource::m_bDropSuccessSet = false;
98 bool Qt5DragSource::m_bDropSuccess = false;
100 Qt5DragSource::~Qt5DragSource()
102 //if (m_pFrame)
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;
123 if (!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;
140 m_xTrans = rTrans;
142 if (m_pFrame)
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);
150 else
151 dragFailed();
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;
162 m_xListener.clear();
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;
178 else
179 aEv.DropSuccess = true;
181 auto xListener = m_xListener;
182 m_xListener.clear();
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" };
201 return aRet;
204 Qt5DropTarget::Qt5DropTarget()
205 : WeakComponentImplHelper(m_aMutex)
206 , m_pFrame(nullptr)
207 , m_bActive(false)
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" };
225 return aRet;
228 Qt5DropTarget::~Qt5DropTarget()
230 //if (m_pFrame)
231 //m_pFrame->deregisterDropTarget(this);
234 void Qt5DropTarget::deinitialize()
236 m_pFrame = nullptr;
237 m_bActive = false;
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;
251 if (!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);
262 m_bActive = true;
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),
279 m_aListeners.end());
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(
297 m_aListeners);
298 aGuard.clear();
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(
310 m_aListeners);
311 aGuard.clear();
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(
323 m_aListeners);
324 aGuard.clear();
326 for (auto const& listener : aListeners)
328 listener->drop(dtde);
332 void Qt5DropTarget::acceptDrag(sal_Int8 dragOperation)
334 mnDragAction = dragOperation;
335 return;
338 void Qt5DropTarget::rejectDrag()
340 mnDragAction = 0;
341 return;
344 void Qt5DropTarget::acceptDrop(sal_Int8 dropOperation)
346 mnDropAction = dropOperation;
347 return;
350 void Qt5DropTarget::rejectDrop()
352 mnDropAction = 0;
353 return;
356 void Qt5DropTarget::dropComplete(sal_Bool success)
358 // internal DnD
359 if (Qt5DragSource::m_ActiveDragSource)
361 Qt5DragSource::m_bDropSuccessSet = true;
362 Qt5DragSource::m_bDropSuccess = success;
365 return;
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */