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_dbui.hxx"
26 
27 #include "dbexchange.hxx"
28 #include <sot/formats.hxx>
29 #include <sot/storage.hxx>
30 #include <osl/diagnose.h>
31 #include <com/sun/star/sdb/CommandType.hpp>
32 #include <com/sun/star/sdb/XResultSetAccess.hpp>
33 #include "TokenWriter.hxx"
34 #include "dbustrings.hrc"
35 #include <comphelper/uno3.hxx>
36 #include <svx/dataaccessdescriptor.hxx>
37 #include "UITools.hxx"
38 
39 
40 namespace dbaui
41 {
42 	using namespace ::com::sun::star::uno;
43 	using namespace ::com::sun::star::beans;
44 	using namespace ::com::sun::star::sdb;
45 	using namespace ::com::sun::star::beans;
46 	using namespace ::com::sun::star::lang;
47 	using namespace ::com::sun::star::util;
48 	using namespace ::com::sun::star::sdbc;
49 	using namespace ::com::sun::star::datatransfer;
50 	using namespace ::svx;
51 
52 	namespace
53 	{
lcl_setListener(const Reference<T> & _xComponent,const Reference<XEventListener> & i_rListener,const bool i_bAdd)54 		template<class T > void lcl_setListener(const Reference<T>& _xComponent, const Reference< XEventListener >& i_rListener, const bool i_bAdd )
55 		{
56 			if ( !_xComponent.is() )
57                 return;
58 
59             Reference< XComponent> xCom( _xComponent, UNO_QUERY );
60             OSL_ENSURE( xCom.is(), "lcl_setListener: no component!" );
61 			if ( !xCom.is() )
62                 return;
63 
64             i_bAdd ? xCom->addEventListener( i_rListener ) : xCom->removeEventListener( i_rListener );
65 		}
66 	}
67 
68 	// -----------------------------------------------------------------------------
ODataClipboard(const::rtl::OUString & _rDatasource,const sal_Int32 _nCommandType,const::rtl::OUString & _rCommand,const Reference<XConnection> & _rxConnection,const Reference<XNumberFormatter> & _rxFormatter,const Reference<XMultiServiceFactory> & _rxORB)69 	ODataClipboard::ODataClipboard(
70 					const ::rtl::OUString&	_rDatasource,
71 					const sal_Int32			_nCommandType,
72 					const ::rtl::OUString&	_rCommand,
73 					const Reference< XConnection >& _rxConnection,
74 					const Reference< XNumberFormatter >& _rxFormatter,
75 					const Reference< XMultiServiceFactory >& _rxORB)
76 					:ODataAccessObjectTransferable( _rDatasource,::rtl::OUString(), _nCommandType, _rCommand, _rxConnection )
77 		,m_pHtml(NULL)
78 		,m_pRtf(NULL)
79 	{
80 		osl_incrementInterlockedCount( &m_refCount );
81 		lcl_setListener( _rxConnection, this, true );
82 
83 		m_pHtml.set( new OHTMLImportExport( getDescriptor(), _rxORB, _rxFormatter ) );
84 		m_pRtf.set( new ORTFImportExport( getDescriptor(), _rxORB, _rxFormatter ) );
85 
86         osl_decrementInterlockedCount( &m_refCount );
87 	}
88 
89 	// -----------------------------------------------------------------------------
ODataClipboard(const::rtl::OUString & _rDatasource,const sal_Int32 _nCommandType,const::rtl::OUString & _rCommand,const Reference<XNumberFormatter> & _rxFormatter,const Reference<XMultiServiceFactory> & _rxORB)90 	ODataClipboard::ODataClipboard(
91 					const ::rtl::OUString&	_rDatasource,
92 					const sal_Int32			_nCommandType,
93 					const ::rtl::OUString&	_rCommand,
94 					const Reference< XNumberFormatter >& _rxFormatter,
95 					const Reference< XMultiServiceFactory >& _rxORB)
96 		:ODataAccessObjectTransferable( _rDatasource, ::rtl::OUString(),_nCommandType, _rCommand)
97 		,m_pHtml(NULL)
98 		,m_pRtf(NULL)
99 	{
100 		m_pHtml.set( new OHTMLImportExport( getDescriptor(),_rxORB, _rxFormatter ) );
101 		m_pRtf.set( new ORTFImportExport( getDescriptor(),_rxORB, _rxFormatter ) );
102 	}
103 
104 	// -----------------------------------------------------------------------------
ODataClipboard(const Reference<XPropertySet> & i_rAliveForm,const Sequence<Any> & i_rSelectedRows,const sal_Bool i_bBookmarkSelection,const Reference<XMultiServiceFactory> & i_rORB)105     ODataClipboard::ODataClipboard(	const Reference< XPropertySet >& i_rAliveForm,
106                                     const Sequence< Any >& i_rSelectedRows,
107                                     const sal_Bool i_bBookmarkSelection,
108                                     const Reference< XMultiServiceFactory >& i_rORB )
109         :ODataAccessObjectTransferable( i_rAliveForm )
110         ,m_pHtml(NULL)
111         ,m_pRtf(NULL)
112     {
113         OSL_PRECOND( i_rORB.is(), "ODataClipboard::ODataClipboard: having no factory is not good ..." );
114 
115         osl_incrementInterlockedCount( &m_refCount );
116 
117         Reference<XConnection> xConnection;
118         getDescriptor()[ daConnection ] >>= xConnection;
119         lcl_setListener( xConnection, this, true );
120 
121         // do not pass the form itself as source result set, since the client might operate on the form, which
122         // might lead to undesired effects. Instead, use a clone.
123         Reference< XResultSet > xResultSetClone;
124 		Reference< XResultSetAccess > xResultSetAccess( i_rAliveForm, UNO_QUERY );
125 		if ( xResultSetAccess.is() )
126 			xResultSetClone = xResultSetAccess->createResultSet();
127         OSL_ENSURE( xResultSetClone.is(), "ODataClipboard::ODataClipboard: could not clone the form's result set" );
128         lcl_setListener( xResultSetClone, this, true );
129 
130         getDescriptor()[daCursor]			<<= xResultSetClone;
131         getDescriptor()[daSelection]		<<= i_rSelectedRows;
132         getDescriptor()[daBookmarkSelection]<<= i_bBookmarkSelection;
133         addCompatibleSelectionDescription( i_rSelectedRows );
134 
135         if ( xConnection.is() && i_rORB.is() )
136         {
137             Reference< XNumberFormatter > xFormatter( getNumberFormatter( xConnection, i_rORB ) );
138             if ( xFormatter.is() )
139             {
140                 m_pHtml.set( new OHTMLImportExport( getDescriptor(), i_rORB, xFormatter ) );
141                 m_pRtf.set( new ORTFImportExport( getDescriptor(), i_rORB, xFormatter ) );
142             }
143         }
144 
145         osl_decrementInterlockedCount( &m_refCount );
146     }
147 
148 	// -----------------------------------------------------------------------------
WriteObject(SotStorageStreamRef & rxOStm,void * pUserObject,sal_uInt32 nUserObjectId,const::com::sun::star::datatransfer::DataFlavor &)149 	sal_Bool ODataClipboard::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const ::com::sun::star::datatransfer::DataFlavor& /*rFlavor*/ )
150 	{
151 		if (nUserObjectId == SOT_FORMAT_RTF || nUserObjectId == SOT_FORMATSTR_ID_HTML )
152 		{
153 			ODatabaseImportExport* pExport = reinterpret_cast<ODatabaseImportExport*>(pUserObject);
154 			if ( pExport && rxOStm.Is() )
155 			{
156 				pExport->setStream(&rxOStm);
157 				return pExport->Write();
158 			}
159 		}
160 		return sal_False;
161 	}
162 
163 	// -----------------------------------------------------------------------------
AddSupportedFormats()164 	void ODataClipboard::AddSupportedFormats()
165 	{
166 		if ( m_pRtf.is() )
167 			AddFormat( SOT_FORMAT_RTF );
168 
169 		if ( m_pHtml.is() )
170 			AddFormat( SOT_FORMATSTR_ID_HTML );
171 
172 		ODataAccessObjectTransferable::AddSupportedFormats();
173 	}
174 
175 	// -----------------------------------------------------------------------------
GetData(const DataFlavor & rFlavor)176 	sal_Bool ODataClipboard::GetData( const DataFlavor& rFlavor )
177 	{
178 		const sal_uLong nFormat = SotExchange::GetFormat(rFlavor);
179 		switch (nFormat)
180 		{
181 			case SOT_FORMAT_RTF:
182                 if ( m_pRtf.is() )
183 				    m_pRtf->initialize(getDescriptor());
184 			    return m_pRtf.is() && SetObject( m_pRtf.get(), SOT_FORMAT_RTF, rFlavor );
185 
186             case SOT_FORMATSTR_ID_HTML:
187                 if ( m_pHtml.is() )
188 				    m_pHtml->initialize(getDescriptor());
189 			    return m_pHtml.is() && SetObject( m_pHtml.get(), SOT_FORMATSTR_ID_HTML, rFlavor );
190 		}
191 
192 		return ODataAccessObjectTransferable::GetData( rFlavor );
193 	}
194 
195 	// -----------------------------------------------------------------------------
ObjectReleased()196 	void ODataClipboard::ObjectReleased()
197 	{
198         if ( m_pHtml.is() )
199         {
200             m_pHtml->dispose();
201 		    m_pHtml.clear();
202         }
203 
204         if ( m_pRtf.is() )
205         {
206             m_pRtf->dispose();
207 		    m_pRtf.clear();
208         }
209 
210         if ( getDescriptor().has( daConnection ) )
211         {
212             Reference<XConnection> xConnection( getDescriptor()[daConnection], UNO_QUERY );
213 			lcl_setListener( xConnection, this, false );
214         }
215 
216 		if ( getDescriptor().has( daCursor ) )
217         {
218             Reference< XResultSet > xResultSet( getDescriptor()[ daCursor ], UNO_QUERY );
219 			lcl_setListener( xResultSet, this, false );
220         }
221 
222 		ODataAccessObjectTransferable::ObjectReleased( );
223 	}
224 
225 	// -----------------------------------------------------------------------------
disposing(const::com::sun::star::lang::EventObject & i_rSource)226 	void SAL_CALL ODataClipboard::disposing( const ::com::sun::star::lang::EventObject& i_rSource ) throw (::com::sun::star::uno::RuntimeException)
227 	{
228         ODataAccessDescriptor& rDescriptor( getDescriptor() );
229 
230 		if ( rDescriptor.has( daConnection ) )
231         {
232             Reference< XConnection > xConnection( rDescriptor[daConnection], UNO_QUERY );
233             if ( xConnection == i_rSource.Source )
234             {
235                 rDescriptor.erase( daConnection );
236             }
237         }
238 
239 		if ( rDescriptor.has( daCursor ) )
240         {
241             Reference< XResultSet > xResultSet( rDescriptor[ daCursor ], UNO_QUERY );
242             if ( xResultSet == i_rSource.Source )
243             {
244                 rDescriptor.erase( daCursor );
245                 // Selection and BookmarkSelection are meaningless without a result set
246                 if ( rDescriptor.has( daSelection ) )
247                     rDescriptor.erase( daSelection );
248                 if ( rDescriptor.has( daBookmarkSelection ) )
249                     rDescriptor.erase( daBookmarkSelection );
250             }
251         }
252 
253         // no matter whether it was the source connection or the source result set which died,
254         // we cannot provide the data anymore.
255         ClearFormats();
256 	}
257 }
258 
259 
260