1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 
27 //_________________________________________________________________________________________________________________
28 //	my own includes
29 //_________________________________________________________________________________________________________________
30 #include <classes/droptargetlistener.hxx>
31 #include <threadhelp/readguard.hxx>
32 #include <threadhelp/writeguard.hxx>
33 #include <targets.h>
34 #include <services.h>
35 
36 //_________________________________________________________________________________________________________________
37 //	interface includes
38 //_________________________________________________________________________________________________________________
39 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
40 #include <com/sun/star/frame/XDispatch.hpp>
41 #include <com/sun/star/frame/XDispatchProvider.hpp>
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <com/sun/star/util/XURLTransformer.hpp>
44 
45 //_________________________________________________________________________________________________________________
46 //	includes of other projects
47 //_________________________________________________________________________________________________________________
48 #include <svtools/transfer.hxx>
49 #include <unotools/localfilehelper.hxx>
50 #include <sot/filelist.hxx>
51 
52 #include <osl/file.hxx>
53 #include <vcl/svapp.hxx>
54 
55 //_________________________________________________________________________________________________________________
56 //	namespace
57 //_________________________________________________________________________________________________________________
58 
59 namespace framework
60 {
61 
DropTargetListener(const css::uno::Reference<css::lang::XMultiServiceFactory> & xFactory,const css::uno::Reference<css::frame::XFrame> & xFrame)62 DropTargetListener::DropTargetListener( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory,
63                                         const css::uno::Reference< css::frame::XFrame >&              xFrame  )
64         : ThreadHelpBase  ( &Application::GetSolarMutex() )
65         , m_xFactory      ( xFactory                      )
66         , m_xTargetFrame  ( xFrame                        )
67         , m_pFormats      ( new DataFlavorExVector        )
68 {
69 }
70 
71 // -----------------------------------------------------------------------------
72 
~DropTargetListener()73 DropTargetListener::~DropTargetListener()
74 {
75     m_xTargetFrame = css::uno::WeakReference< css::frame::XFrame >();
76     m_xFactory     = css::uno::Reference< css::lang::XMultiServiceFactory >();
77     delete m_pFormats;
78     m_pFormats = NULL;
79 }
80 
81 // -----------------------------------------------------------------------------
82 
disposing(const css::lang::EventObject &)83 void SAL_CALL DropTargetListener::disposing( const css::lang::EventObject& ) throw( css::uno::RuntimeException )
84 {
85     m_xTargetFrame = css::uno::WeakReference< css::frame::XFrame >();
86     m_xFactory     = css::uno::Reference< css::lang::XMultiServiceFactory >();
87 }
88 
89 // -----------------------------------------------------------------------------
90 
drop(const css::datatransfer::dnd::DropTargetDropEvent & dtde)91 void SAL_CALL DropTargetListener::drop( const css::datatransfer::dnd::DropTargetDropEvent& dtde ) throw( css::uno::RuntimeException )
92 {
93 	const sal_Int8 nAction = dtde.DropAction;
94 
95 	try
96 	{
97 		if ( css::datatransfer::dnd::DNDConstants::ACTION_NONE != nAction )
98 		{
99 			TransferableDataHelper aHelper( dtde.Transferable );
100 			sal_Bool bFormatFound = sal_False;
101 			FileList aFileList;
102 
103 			// at first check filelist format
104 			if ( aHelper.GetFileList( SOT_FORMAT_FILE_LIST, aFileList ) )
105 			{
106 				sal_uLong i, nCount = aFileList.Count();
107 				for ( i = 0; i < nCount; ++i )
108                     implts_OpenFile( aFileList.GetFile(i) );
109 				bFormatFound = sal_True;
110 			}
111 
112 			// then, if necessary, the file format
113 			String aFilePath;
114 			if ( !bFormatFound && aHelper.GetString( SOT_FORMAT_FILE, aFilePath ) )
115                 implts_OpenFile( aFilePath );
116 		}
117         dtde.Context->dropComplete( css::datatransfer::dnd::DNDConstants::ACTION_NONE != nAction );
118 	}
119 	catch( const ::com::sun::star::uno::Exception& )
120 	{
121 	}
122 }
123 
124 // -----------------------------------------------------------------------------
125 
dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent & dtdee)126 void SAL_CALL DropTargetListener::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEvent& dtdee ) throw( css::uno::RuntimeException )
127 {
128 	try
129 	{
130         implts_BeginDrag( dtdee.SupportedDataFlavors );
131 	}
132 	catch( const ::com::sun::star::uno::Exception& )
133 	{
134 	}
135 
136 	dragOver( dtdee );
137 }
138 
139 // -----------------------------------------------------------------------------
140 
dragExit(const css::datatransfer::dnd::DropTargetEvent &)141 void SAL_CALL DropTargetListener::dragExit( const css::datatransfer::dnd::DropTargetEvent& ) throw( css::uno::RuntimeException )
142 {
143 	try
144 	{
145         implts_EndDrag();
146 	}
147 	catch( const ::com::sun::star::uno::Exception& )
148 	{
149 	}
150 }
151 
152 // -----------------------------------------------------------------------------
153 
dragOver(const css::datatransfer::dnd::DropTargetDragEvent & dtde)154 void SAL_CALL DropTargetListener::dragOver( const css::datatransfer::dnd::DropTargetDragEvent& dtde ) throw( css::uno::RuntimeException )
155 {
156 	try
157 	{
158         sal_Bool bAccept = ( implts_IsDropFormatSupported( SOT_FORMAT_FILE ) ||
159                              implts_IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) );
160 
161 		if ( !bAccept )
162 			dtde.Context->rejectDrag();
163 		else
164 			dtde.Context->acceptDrag( css::datatransfer::dnd::DNDConstants::ACTION_COPY );
165 	}
166 	catch( const ::com::sun::star::uno::Exception& )
167 	{
168 	}
169 }
170 
171 // -----------------------------------------------------------------------------
172 
dropActionChanged(const css::datatransfer::dnd::DropTargetDragEvent &)173 void SAL_CALL DropTargetListener::dropActionChanged( const css::datatransfer::dnd::DropTargetDragEvent& ) throw( css::uno::RuntimeException )
174 {
175 }
176 
implts_BeginDrag(const css::uno::Sequence<css::datatransfer::DataFlavor> & rSupportedDataFlavors)177 void DropTargetListener::implts_BeginDrag( const css::uno::Sequence< css::datatransfer::DataFlavor >& rSupportedDataFlavors )
178 {
179     /* SAFE { */
180     WriteGuard aWriteLock(m_aLock);
181     m_pFormats->clear();
182     TransferableDataHelper::FillDataFlavorExVector(rSupportedDataFlavors,*m_pFormats);
183     aWriteLock.unlock();
184     /* } SAFE */
185 }
186 
implts_EndDrag()187 void DropTargetListener::implts_EndDrag()
188 {
189     /* SAFE { */
190     WriteGuard aWriteLock(m_aLock);
191 	m_pFormats->clear();
192     aWriteLock.unlock();
193     /* } SAFE */
194 }
195 
implts_IsDropFormatSupported(SotFormatStringId nFormat)196 sal_Bool DropTargetListener::implts_IsDropFormatSupported( SotFormatStringId nFormat )
197 {
198     /* SAFE { */
199     ReadGuard aReadLock(m_aLock);
200 	DataFlavorExVector::iterator aIter( m_pFormats->begin() ), aEnd( m_pFormats->end() );
201 	sal_Bool bRet = sal_False;
202 
203 	while ( aIter != aEnd )
204 	{
205 		if ( nFormat == (*aIter++).mnSotId )
206 		{
207 			bRet = sal_True;
208 			aIter = aEnd;
209 		}
210 	}
211     aReadLock.unlock();
212     /* } SAFE */
213 
214 	return bRet;
215 }
216 
implts_OpenFile(const String & rFilePath)217 void DropTargetListener::implts_OpenFile( const String& rFilePath )
218 {
219 	String aFileURL;
220     if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( rFilePath, aFileURL ) )
221 		aFileURL = rFilePath;
222 
223     ::osl::FileStatus aStatus( FileStatusMask_FileURL );
224     ::osl::DirectoryItem aItem;
225     if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) &&
226         ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) )
227             aFileURL = aStatus.getFileURL();
228 
229 	// open file
230     /* SAFE { */
231     ReadGuard aReadLock(m_aLock);
232     css::uno::Reference< css::frame::XFrame >         xTargetFrame( m_xTargetFrame.get()                                  , css::uno::UNO_QUERY );
233     css::uno::Reference< css::util::XURLTransformer > xParser     ( m_xFactory->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY );
234     aReadLock.unlock();
235     /* } SAFE */
236     if (xTargetFrame.is() && xParser.is())
237 	{
238 		css::util::URL aURL;
239 		aURL.Complete = aFileURL;
240         xParser->parseStrict(aURL);
241 
242 		css::uno::Reference < css::frame::XDispatchProvider > xProvider( xTargetFrame, css::uno::UNO_QUERY );
243         css::uno::Reference< css::frame::XDispatch > xDispatcher = xProvider->queryDispatch( aURL, SPECIALTARGET_DEFAULT, 0 );
244 		if ( xDispatcher.is() )
245 			xDispatcher->dispatch( aURL, css::uno::Sequence < css::beans::PropertyValue >() );
246 	}
247 }
248 
249 }
250 
251