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 "databaseobjectview.hxx"
28  #include "dbustrings.hrc"
29  #include "asyncmodaldialog.hxx"
30  
31  /** === begin UNO includes === **/
32  #include <com/sun/star/lang/XSingleServiceFactory.hpp>
33  #include <com/sun/star/frame/XDispatchProvider.hpp>
34  #include <com/sun/star/frame/XFrame.hpp>
35  #include <com/sun/star/frame/XFrames.hpp>
36  #include <com/sun/star/frame/FrameSearchFlag.hpp>
37  #include <com/sun/star/sdb/CommandType.hpp>
38  #include <com/sun/star/sdb/application/XTableUIProvider.hpp>
39  #include <com/sun/star/beans/NamedValue.hpp>
40  #include <com/sun/star/awt/Rectangle.hpp>
41  /** === end UNO includes === **/
42  
43  #include <comphelper/extract.hxx>
44  #include <comphelper/sequence.hxx>
45  #include <connectivity/dbtools.hxx>
46  #include <osl/diagnose.h>
47  #include <toolkit/helper/vclunohelper.hxx>
48  #include <tools/diagnose_ex.h>
49  #include <vcl/window.hxx>
50  
51  // .........................................................................
52  namespace dbaui
53  {
54  // .........................................................................
55  
56  	using namespace ::com::sun::star::uno;
57  	using namespace ::com::sun::star::sdbc;
58  	using namespace ::com::sun::star::sdb;
59      using namespace ::com::sun::star::sdb::application;
60      using namespace ::com::sun::star::ui::dialogs;
61  	using namespace ::com::sun::star::frame;
62  	using namespace ::com::sun::star::lang;
63  	using namespace ::com::sun::star::beans;
64  	using namespace ::com::sun::star::awt;
65  
66  	//======================================================================
67  	//= DatabaseObjectView
68  	//======================================================================
DatabaseObjectView(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XDatabaseDocumentUI> & _rxApplication,const Reference<XFrame> & _rxParentFrame,const::rtl::OUString & _rComponentURL)69  	DatabaseObjectView::DatabaseObjectView( const Reference< XMultiServiceFactory >& _rxORB,
70              const Reference< XDatabaseDocumentUI >& _rxApplication,
71  			const Reference< XFrame >& _rxParentFrame,
72  			const ::rtl::OUString& _rComponentURL )
73  		:m_xORB             ( _rxORB            )
74  		,m_xParentFrame     ( _rxParentFrame    )
75          ,m_xFrameLoader     (                   )
76          ,m_xApplication     ( _rxApplication    )
77          ,m_sComponentURL    ( _rComponentURL    )
78  	{
79  		OSL_ENSURE( m_xORB.is(), "DatabaseObjectView::DatabaseObjectView: invalid service factory!" );
80          OSL_ENSURE( m_xApplication.is(), "DatabaseObjectView::DatabaseObjectView: invalid connection!" );
81  	}
82  
83  	//----------------------------------------------------------------------
getConnection() const84      Reference< XConnection > DatabaseObjectView::getConnection() const
85      {
86          Reference< XConnection > xConnection;
87          if ( m_xApplication.is() )
88              xConnection = m_xApplication->getActiveConnection();
89          return xConnection;
90      }
91  
92  	//----------------------------------------------------------------------
createNew(const Reference<XDataSource> & _xDataSource,const::comphelper::NamedValueCollection & i_rDispatchArgs)93  	Reference< XComponent > DatabaseObjectView::createNew( const Reference< XDataSource >& _xDataSource, const ::comphelper::NamedValueCollection& i_rDispatchArgs )
94  	{
95          return doCreateView( makeAny( _xDataSource ), ::rtl::OUString(), i_rDispatchArgs );
96  	}
97  
98  	//----------------------------------------------------------------------
openExisting(const Any & _rDataSource,const::rtl::OUString & _rName,const::comphelper::NamedValueCollection & i_rDispatchArgs)99  	Reference< XComponent > DatabaseObjectView::openExisting( const Any& _rDataSource, const ::rtl::OUString& _rName,
100              const ::comphelper::NamedValueCollection& i_rDispatchArgs )
101  	{
102          return doCreateView( _rDataSource, _rName, i_rDispatchArgs );
103  	}
104  
105  	//----------------------------------------------------------------------
doCreateView(const Any & _rDataSource,const::rtl::OUString & _rObjectName,const::comphelper::NamedValueCollection & i_rCreationArgs)106  	Reference< XComponent > DatabaseObjectView::doCreateView( const Any& _rDataSource, const ::rtl::OUString& _rObjectName,
107          const ::comphelper::NamedValueCollection& i_rCreationArgs )
108      {
109          ::comphelper::NamedValueCollection aDispatchArgs;
110  
111          aDispatchArgs.merge( i_rCreationArgs, false );    // false => do not overwrite
112          fillDispatchArgs( aDispatchArgs, _rDataSource, _rObjectName );
113          aDispatchArgs.merge( i_rCreationArgs, true );    // true => do overwrite
114  
115          return doDispatch( aDispatchArgs );
116      }
117  
118  	//----------------------------------------------------------------------
doDispatch(const::comphelper::NamedValueCollection & i_rDispatchArgs)119  	Reference< XComponent > DatabaseObjectView::doDispatch( const ::comphelper::NamedValueCollection& i_rDispatchArgs )
120  	{
121  		Reference< XComponent > xReturn;
122  		if ( m_xORB.is() )
123  		{
124  			try
125  			{
126  				// if we have no externally provided frame, create one
127  				if ( !m_xFrameLoader.is() )
128  				{
129  					Reference< XSingleServiceFactory > xFact(m_xORB->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.TaskCreator")), UNO_QUERY_THROW);
130  					Sequence< Any > lArgs(2);
131  					NamedValue      aProp;
132                      sal_Int32       nArg = 0;
133  
134  					aProp.Name    = ::rtl::OUString::createFromAscii("ParentFrame");
135  					aProp.Value <<= m_xParentFrame;
136  					lArgs[nArg++] <<= aProp;
137  
138  					aProp.Name    = ::rtl::OUString::createFromAscii("TopWindow");
139  					aProp.Value <<= sal_True;
140  					lArgs[nArg++] <<= aProp;
141  
142  					m_xFrameLoader.set(xFact->createInstanceWithArguments(lArgs), UNO_QUERY_THROW);
143  
144                      // everything we load can be considered a "top level document", so set the respective bit at the window.
145                      // This, amongst other things, triggers that the component in this task participates in the
146                      // "ThisComponent"-game for the global application Basic.
147                      const Reference< XFrame > xFrame( m_xFrameLoader, UNO_QUERY_THROW );
148                      const Reference< XWindow > xFrameWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
149                      Window* pContainerWindow = VCLUnoHelper::GetWindow( xFrameWindow );
150                      ENSURE_OR_THROW( pContainerWindow, "no implementation access to the frame's container window!" );
151                      pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT );
152  				}
153  
154  				Reference< XComponentLoader > xFrameLoader( m_xFrameLoader, UNO_QUERY_THROW );
155  				xReturn = xFrameLoader->loadComponentFromURL(
156  					m_sComponentURL,
157  					::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_self")),
158  					0,
159  					i_rDispatchArgs.getPropertyValues()
160  				);
161  			}
162              catch( const Exception& )
163              {
164                  DBG_UNHANDLED_EXCEPTION();
165              }
166  		}
167  		return xReturn;
168  	}
169  
170  	//----------------------------------------------------------------------
fillDispatchArgs(::comphelper::NamedValueCollection & i_rDispatchArgs,const Any & _aDataSource,const::rtl::OUString &)171  	void DatabaseObjectView::fillDispatchArgs(
172  			::comphelper::NamedValueCollection& i_rDispatchArgs,
173  			const Any& _aDataSource,
174              const ::rtl::OUString& /* _rName */
175  		)
176  	{
177  		::rtl::OUString sDataSource;
178  		Reference<XDataSource> xDataSource;
179  		if ( _aDataSource >>= sDataSource )
180  		{
181              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_DATASOURCENAME, sDataSource );
182  		}
183  		else if ( _aDataSource >>= xDataSource )
184  		{
185              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_DATASOURCE, xDataSource );
186  		}
187  
188          i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_ACTIVE_CONNECTION, getConnection() );
189  	}
190  
191  	//======================================================================
192  	//= QueryDesigner
193  	//======================================================================
194  	//----------------------------------------------------------------------
QueryDesigner(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XDatabaseDocumentUI> & _rxApplication,const Reference<XFrame> & _rxParentFrame,bool _bCreateView)195  	QueryDesigner::QueryDesigner( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication,
196  		const Reference< XFrame >& _rxParentFrame, bool _bCreateView )
197          :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, _bCreateView ? URL_COMPONENT_VIEWDESIGN : URL_COMPONENT_QUERYDESIGN )
198          ,m_nCommandType( _bCreateView ? CommandType::TABLE : CommandType::QUERY )
199  	{
200  	}
201  
202  	//----------------------------------------------------------------------
fillDispatchArgs(::comphelper::NamedValueCollection & i_rDispatchArgs,const Any & _aDataSource,const::rtl::OUString & _rObjectName)203  	void QueryDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
204  		const ::rtl::OUString& _rObjectName )
205  	{
206  		DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
207  
208  		const bool bIncludeQueryName = 0 != _rObjectName.getLength();
209          const bool bGraphicalDesign = i_rDispatchArgs.getOrDefault( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN, sal_True );
210          const bool bEditViewAsSQLCommand = ( m_nCommandType == CommandType::TABLE ) && !bGraphicalDesign;
211  
212          i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND_TYPE, m_nCommandType );
213  
214          if ( bIncludeQueryName )
215  		{
216              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND, _rObjectName );
217          }
218  
219          if ( bEditViewAsSQLCommand )
220          {
221              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, sal_False );
222          }
223  	}
224  
225  	//======================================================================
226  	//= TableDesigner
227  	//======================================================================
228  	//----------------------------------------------------------------------
TableDesigner(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XDatabaseDocumentUI> & _rxApplication,const Reference<XFrame> & _rxParentFrame)229  	TableDesigner::TableDesigner( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
230  		:DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast< ::rtl::OUString >( URL_COMPONENT_TABLEDESIGN ) )
231  	{
232  	}
233  
234  	//----------------------------------------------------------------------
fillDispatchArgs(::comphelper::NamedValueCollection & i_rDispatchArgs,const Any & _aDataSource,const::rtl::OUString & _rObjectName)235  	void TableDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
236  		const ::rtl::OUString& _rObjectName )
237  	{
238  		DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
239  
240          if ( 0 != _rObjectName.getLength() )
241  		{
242              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_CURRENTTABLE, _rObjectName );
243  		}
244  	}
245  
246  	//----------------------------------------------------------------------
doCreateView(const Any & _rDataSource,const::rtl::OUString & _rObjectName,const::comphelper::NamedValueCollection & i_rCreationArgs)247      Reference< XComponent > TableDesigner::doCreateView( const Any& _rDataSource, const ::rtl::OUString& _rObjectName,
248          const ::comphelper::NamedValueCollection& i_rCreationArgs )
249      {
250          bool bIsNewDesign = ( _rObjectName.getLength() == 0 );
251  
252          // let's see whether the connection can provide a dedicated table desginer
253          Reference< XInterface > xDesigner;
254          if ( !bIsNewDesign )
255              xDesigner = impl_getConnectionProvidedDesigner_nothrow( _rObjectName );
256  
257          if ( !xDesigner.is() )
258              return DatabaseObjectView::doCreateView( _rDataSource, _rObjectName, i_rCreationArgs );
259  
260          // try whether the designer is a dialog
261          Reference< XExecutableDialog > xDialog( xDesigner, UNO_QUERY_THROW );
262          if ( xDialog.is() )
263          {
264              try { AsyncDialogExecutor::executeModalDialogAsync( xDialog ); }
265              catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
266              return NULL;
267          }
268  
269          Reference< XComponent > xDesignerComponent( xDesigner, UNO_QUERY );
270          OSL_ENSURE( xDesignerComponent.is(), "TableDesigner::doCreateView: a designer which is no dialog and no component?" );
271          return xDesignerComponent;
272      }
273  
274  	//----------------------------------------------------------------------
impl_getConnectionProvidedDesigner_nothrow(const::rtl::OUString & _rTableName)275      Reference< XInterface > TableDesigner::impl_getConnectionProvidedDesigner_nothrow( const ::rtl::OUString& _rTableName )
276      {
277          Reference< XInterface > xDesigner;
278          try
279          {
280              Reference< XTableUIProvider > xTableUIProv( getConnection(), UNO_QUERY );
281              if ( xTableUIProv.is() )
282                  xDesigner = xTableUIProv->getTableEditor( getApplicationUI(), _rTableName );
283          }
284          catch( const Exception& )
285          {
286          	DBG_UNHANDLED_EXCEPTION();
287          }
288          return xDesigner;
289      }
290  
291      //======================================================================
292  	//= ResultSetBrowser
293  	//======================================================================
294  	//----------------------------------------------------------------------
ResultSetBrowser(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XDatabaseDocumentUI> & _rxApplication,const Reference<XFrame> & _rxParentFrame,sal_Bool _bTable)295  	ResultSetBrowser::ResultSetBrowser( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame,
296              sal_Bool _bTable )
297  		:DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast < ::rtl::OUString >( URL_COMPONENT_DATASOURCEBROWSER ) )
298  		,m_bTable(_bTable)
299  	{
300  	}
301  
302  	//----------------------------------------------------------------------
fillDispatchArgs(::comphelper::NamedValueCollection & i_rDispatchArgs,const Any & _aDataSource,const::rtl::OUString & _rQualifiedName)303  	void ResultSetBrowser::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
304  		const ::rtl::OUString& _rQualifiedName)
305  	{
306  		DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rQualifiedName );
307  		OSL_ENSURE( 0 != _rQualifiedName.getLength(),"A Table name must be set");
308  		::rtl::OUString sCatalog;
309  		::rtl::OUString sSchema;
310  		::rtl::OUString sTable;
311  		if ( m_bTable )
312  			::dbtools::qualifiedNameComponents( getConnection()->getMetaData(), _rQualifiedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
313  
314          i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND_TYPE, (m_bTable ? CommandType::TABLE : CommandType::QUERY) );
315          i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND, _rQualifiedName );
316          i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_ENABLE_BROWSER, sal_False );
317  
318  		if ( m_bTable )
319  		{
320              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_UPDATE_CATALOGNAME, sCatalog );
321              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_UPDATE_SCHEMANAME, sSchema );
322              i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_UPDATE_TABLENAME, sTable );
323  		}
324  	}
325  
326  	//======================================================================
327  	//= RelationDesigner
328  	//======================================================================
329  	//----------------------------------------------------------------------
RelationDesigner(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XDatabaseDocumentUI> & _rxApplication,const Reference<XFrame> & _rxParentFrame)330  	RelationDesigner::RelationDesigner( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
331          :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast< ::rtl::OUString >( URL_COMPONENT_RELATIONDESIGN ) )
332  	{
333  	}
334  // .........................................................................
335  }	// namespace dbaui
336  // .........................................................................
337  
338