1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #include "dbexchange.hxx"
32 #include "dbtreelistbox.hxx"
33 #include "dbtreemodel.hxx"
34 #include "dbtreeview.hxx"
35 #include "dbu_brw.hrc"
36 #include "dbustrings.hrc"
37 #include "QEnumTypes.hxx"
38 #include "UITools.hxx"
39 #include "unodatbr.hxx"
40 
41 /** === begin UNO includes === **/
42 #include <com/sun/star/frame/XStorable.hpp>
43 #include <com/sun/star/sdb/CommandType.hpp>
44 #include <com/sun/star/sdbc/XConnection.hpp>
45 /** === end UNO includes === **/
46 
47 #include <connectivity/dbexception.hxx>
48 #include <connectivity/dbtools.hxx>
49 #include <cppuhelper/exc_hlp.hxx>
50 #include <svtools/treelist.hxx>
51 #include <svx/dataaccessdescriptor.hxx>
52 #include <tools/diagnose_ex.h>
53 
54 #include <functional>
55 // .........................................................................
56 namespace dbaui
57 {
58 // .........................................................................
59 
60 	using namespace ::com::sun::star::uno;
61 	using namespace ::com::sun::star::sdb;
62 	using namespace ::com::sun::star::sdbc;
63 	using namespace ::com::sun::star::sdbcx;
64 	using namespace ::com::sun::star::beans;
65 	using namespace ::com::sun::star::util;
66 	using namespace ::com::sun::star::frame;
67 	using namespace ::com::sun::star::container;
68 	using namespace ::com::sun::star::lang;
69 	using namespace ::com::sun::star::form;
70 	using namespace ::com::sun::star::io;
71 	using namespace ::com::sun::star::i18n;
72 	using namespace ::com::sun::star::task;
73 	using namespace ::com::sun::star::datatransfer;
74 	using namespace ::dbtools;
75 	using namespace ::svx;
76 
77 	// -----------------------------------------------------------------------------
78 	TransferableHelper* SbaTableQueryBrowser::implCopyObject( SvLBoxEntry* _pApplyTo, sal_Int32 _nCommandType, sal_Bool _bAllowConnection )
79 	{
80 		try
81 		{
82 			::rtl::OUString aName = GetEntryText( _pApplyTo );
83 			::rtl::OUString aDSName = getDataSourceAcessor( m_pTreeView->getListBox().GetRootLevelParent( _pApplyTo ) );
84 
85 			ODataClipboard* pData = NULL;
86 			SharedConnection xConnection;
87 			if ( CommandType::QUERY != _nCommandType )
88 			{
89 				if ( _bAllowConnection && !ensureConnection( _pApplyTo, xConnection) )
90 					return NULL;
91 				pData = new ODataClipboard(aDSName, _nCommandType, aName, xConnection, getNumberFormatter(), getORB());
92 			}
93 			else
94 				pData = new ODataClipboard(aDSName, _nCommandType, aName, getNumberFormatter(), getORB());
95 
96 			// the owner ship goes to ODataClipboards
97 			return pData;
98 		}
99 		catch(const SQLException& )
100 		{
101             showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
102 		}
103         catch( const Exception& )
104         {
105             DBG_UNHANDLED_EXCEPTION();
106         }
107 		return NULL;
108 	}
109 	// -----------------------------------------------------------------------------
110 	sal_Int8 SbaTableQueryBrowser::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
111 	{
112         // check if we're a table or query container
113 		SvLBoxEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rEvt.maPosPixel );
114 
115 		if ( pHitEntry ) // no drop if no entry was hit ....
116 		{
117 			// it must be a container
118 			EntryType eEntryType = getEntryType( pHitEntry );
119             SharedConnection xConnection;
120 			if ( eEntryType == etTableContainer && ensureConnection( pHitEntry, xConnection ) && xConnection.is() )
121 			{
122                 Reference<XChild> xChild(xConnection,UNO_QUERY);
123                 Reference<XStorable> xStore(xChild.is() ? getDataSourceOrModel(xChild->getParent()) : Reference<XInterface>(),UNO_QUERY);
124 				// check for the concrete type
125 				if ( xStore.is() && !xStore->isReadonly() && ::std::find_if(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(E_TABLE,sal_True)) != _rFlavors.end())
126 					return DND_ACTION_COPY;
127 			}
128 		}
129 
130 		return DND_ACTION_NONE;
131 	}
132 	// -----------------------------------------------------------------------------
133 	sal_Int8 SbaTableQueryBrowser::executeDrop( const ExecuteDropEvent& _rEvt )
134 	{
135         SvLBoxEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rEvt.maPosPixel );
136 		EntryType eEntryType = getEntryType( pHitEntry );
137 		if (!isContainer(eEntryType))
138 		{
139 			DBG_ERROR("SbaTableQueryBrowser::executeDrop: what the hell did queryDrop do?");
140 				// queryDrop shoud not have allowed us to reach this situation ....
141 			return DND_ACTION_NONE;
142 		}
143 		// a TransferableDataHelper for accessing the dropped data
144 	    TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
145 
146 
147 	    // reset the data of the previous async drop (if any)
148 	    if ( m_nAsyncDrop )
149 		    Application::RemoveUserEvent(m_nAsyncDrop);
150 
151 
152 	    m_nAsyncDrop = 0;
153 	    m_aAsyncDrop.aDroppedData.clear();
154         m_aAsyncDrop.nType			= E_TABLE;
155 	    m_aAsyncDrop.nAction		= _rEvt.mnAction;
156 	    m_aAsyncDrop.bError			= sal_False;
157 	    m_aAsyncDrop.bHtml			= sal_False;
158         m_aAsyncDrop.pDroppedAt		= NULL;
159 	    m_aAsyncDrop.aUrl			= ::rtl::OUString();
160 
161 
162 	    // loop through the available formats and see what we can do ...
163 	    // first we have to check if it is our own format, if not we have to copy the stream :-(
164 	    if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
165 	    {
166             m_aAsyncDrop.aDroppedData	= ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
167 			m_aAsyncDrop.pDroppedAt		= pHitEntry;
168 
169 		    // asyncron because we some dialogs and we aren't allowed to show them while in D&D
170 		    m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop));
171 		    return DND_ACTION_COPY;
172 	    }
173 	    else
174 	    {
175             SharedConnection xDestConnection;
176 		    if (  ensureConnection( pHitEntry, xDestConnection )
177                && xDestConnection.is()
178                && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xDestConnection )
179                )
180             {
181                 m_aAsyncDrop.pDroppedAt	= pHitEntry;
182 
183 			    // asyncron because we some dialogs and we aren't allowed to show them while in D&D
184 			    m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop));
185 			    return DND_ACTION_COPY;
186 		    }
187 	    }
188 
189 	    return DND_ACTION_NONE;
190 	}
191 
192 	// -----------------------------------------------------------------------------
193 	sal_Bool SbaTableQueryBrowser::requestDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
194 	{
195 		// get the affected list entry
196 		// ensure that the entry which the user clicked at is selected
197 		SvLBoxEntry* pHitEntry = m_pTreeView->getListBox().GetEntry( _rPosPixel );
198 		if (!pHitEntry)
199 			// no drag of no entry was hit ....
200 			return sal_False;
201 
202 		// it must be a query/table
203 		EntryType eEntryType = getEntryType( pHitEntry );
204 		if (!isObject(eEntryType))
205 			return DND_ACTION_NONE;
206 
207 		TransferableHelper* pTransfer = implCopyObject( pHitEntry, ( etTableOrView == eEntryType ) ? CommandType::TABLE : CommandType::QUERY);
208 		Reference< XTransferable> xEnsureDelete = pTransfer;
209 
210 		if (pTransfer)
211 			pTransfer->StartDrag( &m_pTreeView->getListBox(), DND_ACTION_COPY );
212 
213 		return NULL != pTransfer;
214 	}
215 	// -----------------------------------------------------------------------------
216 	IMPL_LINK(SbaTableQueryBrowser, OnCopyEntry, void*, /*NOTINTERESIN*/)
217 	{
218         SvLBoxEntry* pSelected = m_pTreeView->getListBox().FirstSelected();
219 		if( isEntryCopyAllowed( pSelected ) )
220 			copyEntry( pSelected );
221 		return 0;
222 	}
223 	// -----------------------------------------------------------------------------
224 	sal_Bool SbaTableQueryBrowser::isEntryCopyAllowed(SvLBoxEntry* _pEntry) const
225 	{
226 		EntryType eType = getEntryType(_pEntry);
227 		return  ( eType == etTableOrView || eType == etQuery );
228 	}
229 	// -----------------------------------------------------------------------------
230 	void SbaTableQueryBrowser::copyEntry(SvLBoxEntry* _pEntry)
231 	{
232 		TransferableHelper* pTransfer = NULL;
233 		Reference< XTransferable> aEnsureDelete;
234 		EntryType eType = getEntryType(_pEntry);
235 		pTransfer		= implCopyObject( _pEntry, eType == etQuery ? CommandType::QUERY : CommandType::TABLE);
236 		aEnsureDelete	= pTransfer;
237 		if (pTransfer)
238 			pTransfer->CopyToClipboard(getView());
239 	}
240     // -----------------------------------------------------------------------------
241     IMPL_LINK( SbaTableQueryBrowser, OnAsyncDrop, void*, /*NOTINTERESTEDIN*/ )
242     {
243 	    m_nAsyncDrop = 0;
244 	    ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
245 	    ::osl::MutexGuard aGuard( getMutex() );
246 
247 	    if ( m_aAsyncDrop.nType == E_TABLE )
248 	    {
249             SharedConnection xDestConnection;
250 		    if ( ensureConnection( m_aAsyncDrop.pDroppedAt, xDestConnection ) && xDestConnection.is() )
251             {
252                 SvLBoxEntry* pDataSourceEntry = m_pTreeView->getListBox().GetRootLevelParent(m_aAsyncDrop.pDroppedAt);
253 		        m_aTableCopyHelper.asyncCopyTagTable( m_aAsyncDrop, getDataSourceAcessor( pDataSourceEntry ), xDestConnection );
254             }
255 	    }
256 
257 	    m_aAsyncDrop.aDroppedData.clear();
258 
259 	    return 0L;
260     }
261     // -----------------------------------------------------------------------------
262 	void SbaTableQueryBrowser::clearTreeModel()
263 	{
264 		if (m_pTreeModel)
265 		{
266 			// clear the user data of the tree model
267 			SvLBoxEntry* pEntryLoop = m_pTreeModel->First();
268 			while (pEntryLoop)
269 			{
270 				DBTreeListUserData* pData = static_cast<DBTreeListUserData*>(pEntryLoop->GetUserData());
271 				if(pData)
272 				{
273 					pEntryLoop->SetUserData(NULL);
274 					Reference< XContainer > xContainer(pData->xContainer, UNO_QUERY);
275 					if (xContainer.is())
276 						xContainer->removeContainerListener(this);
277 
278 					if ( pData->xConnection.is() )
279 					{
280                         DBG_ASSERT( impl_isDataSourceEntry( pEntryLoop ), "SbaTableQueryBrowser::clearTreeModel: no data source entry, but a connection?" );
281                         // connections are to be stored *only* at the data source entries
282                         impl_releaseConnection( pData->xConnection );
283 					}
284 
285 					delete pData;
286 				}
287 				pEntryLoop = m_pTreeModel->Next(pEntryLoop);
288 			}
289 		}
290 		m_pCurrentlyDisplayed = NULL;
291 	}
292 // .........................................................................
293 }	// namespace dbaui
294 // .........................................................................
295 
296