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_dbaccess.hxx"
26 
27 #include "AppController.hxx"
28 #include "AppDetailView.hxx"
29 #include "AppView.hxx"
30 #include "dbaccess_slotid.hrc"
31 #include "dbu_app.hrc"
32 #include "dbustrings.hrc"
33 #include "defaultobjectnamecheck.hxx"
34 #include "dlgsave.hxx"
35 #include "UITools.hxx"
36 #include "subcomponentmanager.hxx"
37 
38 /** === begin UNO includes === **/
39 #include <com/sun/star/container/XChild.hpp>
40 #include <com/sun/star/container/XContainer.hpp>
41 #include <com/sun/star/container/XHierarchicalNameContainer.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/container/XNameContainer.hpp>
44 #include <com/sun/star/lang/XEventListener.hpp>
45 #include <com/sun/star/sdb/CommandType.hpp>
46 #include <com/sun/star/sdb/SQLContext.hpp>
47 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
48 #include <com/sun/star/sdbcx/XRename.hpp>
49 #include <com/sun/star/sdb/ErrorCondition.hpp>
50 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
51 #include <com/sun/star/sdb/SQLContext.hpp>
52 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
53 #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
54 #include <com/sun/star/ucb/Command.hpp>
55 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
56 #include <com/sun/star/ucb/XCommandProcessor.hpp>
57 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
58 #include <com/sun/star/uno/XNamingService.hpp>
59 #include <com/sun/star/util/XCloseable.hpp>
60 #include <com/sun/star/util/XRefreshable.hpp>
61 #include <com/sun/star/lang/XEventListener.hpp>
62 /** === end UNO includes === **/
63 
64 #include <cppuhelper/exc_hlp.hxx>
65 #include <connectivity/dbexception.hxx>
66 #include <connectivity/dbtools.hxx>
67 #include <connectivity/sqlerror.hxx>
68 #include <connectivity/dbexception.hxx>
69 #include <sfx2/mailmodelapi.hxx>
70 #include <svx/dbaexchange.hxx>
71 #include <toolkit/unohlp.hxx>
72 #include <tools/diagnose_ex.h>
73 #include <tools/urlobj.hxx>
74 #include <unotools/bootstrap.hxx>
75 #include <vcl/mnemonic.hxx>
76 #include <vcl/svapp.hxx>
77 #include <vcl/waitobj.hxx>
78 #include <vos/mutex.hxx>
79 
80 //........................................................................
81 namespace dbaui
82 {
83 using namespace ::dbtools;
84 using namespace ::connectivity;
85 using namespace ::svx;
86 using namespace ::com::sun::star;
87 using namespace ::com::sun::star::uno;
88 using namespace ::com::sun::star::awt;
89 using namespace ::com::sun::star::util;
90 using namespace ::com::sun::star::frame;
91 using namespace ::com::sun::star::lang;
92 using namespace ::com::sun::star::ui::dialogs;
93 using namespace ::com::sun::star::sdb;
94 using namespace ::com::sun::star::sdbc;
95 using namespace ::com::sun::star::sdbcx;
96 using namespace ::com::sun::star::beans;
97 using namespace ::com::sun::star::container;
98 using namespace ::com::sun::star::ucb;
99 
100 /** === begin UNO using === **/
101 using ::com::sun::star::util::XCloseable;
102 using ::com::sun::star::ui::XContextMenuInterceptor;
103 /** === end UNO using === **/
104 
105 namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
106 namespace ErrorCondition = ::com::sun::star::sdb::ErrorCondition;
107 
108 //........................................................................
109 // -----------------------------------------------------------------------------
110 
111 class CloseChecker : public ::cppu::WeakImplHelper1< com::sun::star::lang::XEventListener >
112 {
113     bool    m_bClosed;
114 
115 public:
CloseChecker()116     CloseChecker()
117         :m_bClosed( false )
118     {
119     }
120 
~CloseChecker()121     virtual ~CloseChecker()
122     {
123     }
124 
isClosed()125 	bool isClosed()
126 	{
127 		return true;
128 	}
129 
130 	// interface XEventListener
disposing(const EventObject &)131     virtual void SAL_CALL disposing( const EventObject& /*Source*/ ) throw( RuntimeException )
132     {
133         m_bClosed = true;
134     }
135 
136 };
137 // -----------------------------------------------------------------------------
convertToView(const::rtl::OUString & _sName)138 void OApplicationController::convertToView(const ::rtl::OUString& _sName)
139 {
140 	try
141 	{
142 		SharedConnection xConnection( getConnection() );
143 		Reference< XQueriesSupplier > xSup( xConnection, UNO_QUERY_THROW );
144 		Reference< XNameAccess > xQueries( xSup->getQueries(), UNO_QUERY_THROW );
145 		Reference< XPropertySet > xSourceObject( xQueries->getByName( _sName ), UNO_QUERY_THROW );
146 
147         Reference< XTablesSupplier > xTablesSup( xConnection, UNO_QUERY_THROW );
148 		Reference< XNameAccess > xTables( xTablesSup->getTables(), UNO_QUERY_THROW );
149 
150 		Reference< XDatabaseMetaData  > xMeta = xConnection->getMetaData();
151 
152 		String aName = String(ModuleRes(STR_TBL_TITLE));
153 		aName = aName.GetToken(0,' ');
154 		String aDefaultName = ::dbaui::createDefaultName(xMeta,xTables,aName);
155 
156         DynamicTableOrQueryNameCheck aNameChecker( xConnection, CommandType::TABLE );
157 		OSaveAsDlg aDlg( getView(), CommandType::TABLE, getORB(), xConnection, aDefaultName, aNameChecker );
158 		if ( aDlg.Execute() == RET_OK )
159 		{
160 			::rtl::OUString sName = aDlg.getName();
161 			::rtl::OUString sCatalog = aDlg.getCatalog();
162 			::rtl::OUString sSchema	 = aDlg.getSchema();
163 			::rtl::OUString sNewName(
164 			    ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sName, sal_False, ::dbtools::eInTableDefinitions ) );
165 			Reference<XPropertySet> xView = ::dbaui::createView(sNewName,xConnection,xSourceObject);
166 			if ( !xView.is() )
167 				throw SQLException(String(ModuleRes(STR_NO_TABLE_FORMAT_INSIDE)),*this,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")) ,0,Any());
168 			getContainer()->elementAdded(E_TABLE,sNewName,makeAny(xView));
169 		}
170 	}
171 	catch(const SQLException& )
172     {
173         showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
174     }
175 	catch( const Exception& )
176 	{
177         DBG_UNHANDLED_EXCEPTION();
178 	}
179 }
180 // -----------------------------------------------------------------------------
pasteFormat(sal_uInt32 _nFormatId)181 void OApplicationController::pasteFormat(sal_uInt32 _nFormatId)
182 {
183 	if ( _nFormatId )
184 	{
185 		try
186 		{
187 			const TransferableDataHelper& rClipboard = getViewClipboard();
188 			ElementType eType = getContainer()->getElementType();
189 			if ( eType == E_TABLE )
190             {
191                 m_aTableCopyHelper.pasteTable( _nFormatId, rClipboard, getDatabaseName(), ensureConnection() );
192             }
193 			else
194 				paste( eType, ODataAccessObjectTransferable::extractObjectDescriptor( rClipboard ) );
195 
196 		}
197 		catch( const Exception& )
198 		{
199             DBG_UNHANDLED_EXCEPTION();
200 		}
201 	}
202 }
203 // -----------------------------------------------------------------------------
openDataSourceAdminDialog()204 void OApplicationController::openDataSourceAdminDialog()
205 {
206 	openDialog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.DatasourceAdministrationDialog" ) ) );
207 }
208 
209 // -----------------------------------------------------------------------------
openDialog(const::rtl::OUString & _sServiceName)210 void OApplicationController::openDialog( const ::rtl::OUString& _sServiceName )
211 {
212 	try
213 	{
214 		::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
215 		::osl::MutexGuard aGuard( getMutex() );
216 		WaitObject aWO(getView());
217 
218 		Sequence< Any > aArgs(3);
219         sal_Int32 nArgPos = 0;
220 
221 		Reference< ::com::sun::star::awt::XWindow> xWindow = getTopMostContainerWindow();
222 		if ( !xWindow.is() )
223 		{
224 			DBG_ASSERT( getContainer(), "OApplicationController::Construct: have no view!" );
225 			if ( getContainer() )
226 				xWindow = VCLUnoHelper::GetInterface(getView()->Window::GetParent());
227 		}
228 		// the parent window
229 		aArgs[nArgPos++] <<= PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParentWindow")),
230 									0,
231 									makeAny(xWindow),
232 									PropertyState_DIRECT_VALUE);
233 
234 		// the initial selection
235 		::rtl::OUString sInitialSelection;
236 		if ( getContainer() )
237     		sInitialSelection = getDatabaseName();
238         if ( sInitialSelection.getLength() )
239         {
240 		    aArgs[ nArgPos++ ] <<= PropertyValue(
241 			    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InitialSelection" ) ), 0,
242 			    makeAny( sInitialSelection ), PropertyState_DIRECT_VALUE );
243         }
244 
245         SharedConnection xConnection( getConnection() );
246         if ( xConnection.is() )
247         {
248 			aArgs[ nArgPos++ ] <<= PropertyValue(
249 				PROPERTY_ACTIVE_CONNECTION, 0,
250 				makeAny( xConnection ), PropertyState_DIRECT_VALUE );
251         }
252         aArgs.realloc( nArgPos );
253 
254 		// create the dialog
255 		Reference< XExecutableDialog > xAdminDialog;
256 		xAdminDialog = Reference< XExecutableDialog >(
257 			getORB()->createInstanceWithArguments(_sServiceName,aArgs), UNO_QUERY);
258 
259 		// execute it
260 		if (xAdminDialog.is())
261 			xAdminDialog->execute();
262 	}
263 	catch( const Exception& )
264 	{
265         DBG_UNHANDLED_EXCEPTION();
266 	}
267 }
268 // -----------------------------------------------------------------------------
openTableFilterDialog()269 void OApplicationController::openTableFilterDialog()
270 {
271 	openDialog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.TableFilterDialog" ) ) );
272 }
273 
274 // -----------------------------------------------------------------------------
refreshTables()275 void OApplicationController::refreshTables()
276 {
277 	if ( getContainer() && getContainer()->getDetailView() )
278 	{
279 		WaitObject aWO(getView());
280 		OSL_ENSURE(getContainer()->getElementType() == E_TABLE,"Only allowed when the tables container is selected!");
281 		try
282 		{
283 			Reference<XRefreshable> xRefresh(getElements(E_TABLE),UNO_QUERY);
284 			if ( xRefresh.is() )
285 				xRefresh->refresh();
286 		}
287 		catch(const Exception&)
288 		{
289 			OSL_ENSURE(0,"Could not refresh tables!");
290 		}
291 
292 		getContainer()->getDetailView()->clearPages(sal_False);
293 		getContainer()->getDetailView()->createTablesPage( ensureConnection() );
294 	}
295 }
296 // -----------------------------------------------------------------------------
openDirectSQLDialog()297 void OApplicationController::openDirectSQLDialog()
298 {
299 	openDialog( SERVICE_SDB_DIRECTSQLDIALOG );
300 }
301 // -----------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)302 void SAL_CALL OApplicationController::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException)
303 {
304 	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
305 	::osl::MutexGuard aGuard( getMutex() );
306 	if ( evt.PropertyName == PROPERTY_USER )
307     {
308         m_bNeedToReconnect = sal_True;
309 		InvalidateFeature(SID_DB_APP_STATUS_USERNAME);
310     }
311 	else if ( evt.PropertyName == PROPERTY_URL )
312 	{
313         m_bNeedToReconnect = sal_True;
314 		InvalidateFeature(SID_DB_APP_STATUS_DBNAME);
315 		InvalidateFeature(SID_DB_APP_STATUS_TYPE);
316 		InvalidateFeature(SID_DB_APP_STATUS_HOSTNAME);
317 	}
318     else if ( PROPERTY_NAME == evt.PropertyName )
319     {
320         const ElementType eType = getContainer()->getElementType();
321         if ( eType == E_FORM || eType == E_REPORT )
322 		{
323             ::rtl::OUString sOldName,sNewName;
324             evt.OldValue >>= sOldName;
325             evt.NewValue >>= sNewName;
326 
327             // if the old name is empty, then this is a newly inserted content. We're notified of it via the
328             // elementInserted method, so there's no need to handle it here.
329 
330             if ( sOldName.getLength() )
331             {
332                 Reference<XChild> xChild(evt.Source,UNO_QUERY);
333                 if ( xChild.is() )
334                 {
335                     Reference<XContent> xContent(xChild->getParent(),UNO_QUERY);
336 			        if ( xContent.is() )
337 				        sOldName = xContent->getIdentifier()->getContentIdentifier() + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + sOldName;
338                 }
339 
340                 getContainer()->elementReplaced( eType , sOldName, sNewName );
341             }
342         }
343     }
344 
345 	EventObject aEvt;
346 	aEvt.Source = m_xModel;
347 	modified(aEvt);
348 }
349 
350 // -----------------------------------------------------------------------------
getDataSource()351 Reference< XDataSource > SAL_CALL OApplicationController::getDataSource() throw (RuntimeException)
352 {
353 	::osl::MutexGuard aGuard( getMutex() );
354     Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
355     return xDataSource;
356 }
357 
358 // -----------------------------------------------------------------------------
getApplicationMainWindow()359 Reference< XWindow > SAL_CALL OApplicationController::getApplicationMainWindow() throw (RuntimeException)
360 {
361 	::osl::MutexGuard aGuard( getMutex() );
362     Reference< XFrame > xFrame( getFrame(), UNO_QUERY_THROW );
363     Reference< XWindow > xWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
364     return xWindow;
365 }
366 
367 // -----------------------------------------------------------------------------
getSubComponents()368 Sequence< Reference< XComponent > > SAL_CALL OApplicationController::getSubComponents() throw (RuntimeException)
369 {
370 	::osl::MutexGuard aGuard( getMutex() );
371     return m_pSubComponentManager->getSubComponents();
372 }
373 
374 // -----------------------------------------------------------------------------
getActiveConnection()375 Reference< XConnection > SAL_CALL OApplicationController::getActiveConnection() throw (RuntimeException)
376 {
377 	::osl::MutexGuard aGuard( getMutex() );
378     return m_xDataSourceConnection.getTyped();
379 }
380 
381 // -----------------------------------------------------------------------------
isConnected()382 ::sal_Bool SAL_CALL OApplicationController::isConnected(  ) throw (RuntimeException)
383 {
384 	::osl::MutexGuard aGuard( getMutex() );
385     return m_xDataSourceConnection.is();
386 }
387 
388 // -----------------------------------------------------------------------------
connect()389 void SAL_CALL OApplicationController::connect(  ) throw (SQLException, RuntimeException)
390 {
391 	::vos::OGuard aSolarGuard(Application::GetSolarMutex());
392 	::osl::MutexGuard aGuard( getMutex() );
393 
394     SQLExceptionInfo aError;
395     SharedConnection xConnection = ensureConnection( &aError );
396     if ( !xConnection.is() )
397     {
398         if ( aError.isValid() )
399             aError.doThrow();
400 
401         // no particular error, but nonetheless could not connect -> throw a generic exception
402 		String sConnectingContext( ModuleRes( STR_COULDNOTCONNECT_DATASOURCE ) );
403 		sConnectingContext.SearchAndReplaceAscii( "$name$", getStrippedDatabaseName() );
404         ::dbtools::throwGenericSQLException( sConnectingContext, *this );
405     }
406 }
407 
408 // -----------------------------------------------------------------------------
identifySubComponent(const Reference<XComponent> & i_rSubComponent)409 beans::Pair< ::sal_Int32, ::rtl::OUString > SAL_CALL OApplicationController::identifySubComponent( const Reference< XComponent >& i_rSubComponent ) throw (IllegalArgumentException, RuntimeException)
410 {
411 	::osl::MutexGuard aGuard( getMutex() );
412 
413     sal_Int32 nType = -1;
414     ::rtl::OUString sName;
415 
416     if ( !m_pSubComponentManager->lookupSubComponent( i_rSubComponent, sName, nType ) )
417         throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
418 
419     if ( nType == SID_DB_APP_DSRELDESIGN )
420         // this is somewhat hacky ... we're expected to return a DatabaseObject value. However, there is no such
421         // value for the relation design. /me thinks we should change the API definition here ...
422         nType = -1;
423 
424     return beans::Pair< ::sal_Int32, ::rtl::OUString >( nType, sName );
425 }
426 
427 // -----------------------------------------------------------------------------
closeSubComponents()428 ::sal_Bool SAL_CALL OApplicationController::closeSubComponents(  ) throw (RuntimeException)
429 {
430 	::vos::OGuard aSolarGuard(Application::GetSolarMutex());
431 	::osl::MutexGuard aGuard( getMutex() );
432     return m_pSubComponentManager->closeSubComponents();
433 }
434 
435 
436 // -----------------------------------------------------------------------------
437 namespace
438 {
lcl_objectType2ElementType(const sal_Int32 _nObjectType)439     ElementType lcl_objectType2ElementType( const sal_Int32 _nObjectType )
440     {
441         ElementType eType( E_NONE );
442         switch ( _nObjectType )
443         {
444         case DatabaseObject::TABLE:  eType = E_TABLE;   break;
445         case DatabaseObject::QUERY:  eType = E_QUERY;   break;
446         case DatabaseObject::FORM:   eType = E_FORM;    break;
447         case DatabaseObject::REPORT: eType = E_REPORT;  break;
448         default:
449             OSL_ENSURE( false, "lcl_objectType2ElementType: unsupported object type!" );
450                 // this should have been caught earlier
451         }
452         return eType;
453     }
454 }
455 
456 // -----------------------------------------------------------------------------
impl_validateObjectTypeAndName_throw(const sal_Int32 _nObjectType,const::boost::optional<::rtl::OUString> & i_rObjectName)457 void OApplicationController::impl_validateObjectTypeAndName_throw( const sal_Int32 _nObjectType, const ::boost::optional< ::rtl::OUString >& i_rObjectName )
458 {
459     // ensure we're connected
460     if ( !isConnected() )
461     {
462         SQLError aError( getORB() );
463         aError.raiseException( ErrorCondition::DB_NOT_CONNECTED, *this );
464     }
465 
466     // ensure a proper object type
467     if  (   ( _nObjectType != DatabaseObject::TABLE )
468         &&  ( _nObjectType != DatabaseObject::QUERY )
469         &&  ( _nObjectType != DatabaseObject::FORM )
470         &&  ( _nObjectType != DatabaseObject::REPORT )
471         )
472         throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
473 
474     if ( !i_rObjectName )
475         return;
476 
477     // ensure an existing object
478     Reference< XNameAccess > xContainer( getElements( lcl_objectType2ElementType( _nObjectType ) ) );
479     if ( !xContainer.is() )
480         // all possible reasons for this (e.g. not being connected currently) should
481         // have been handled before
482         throw RuntimeException( ::rtl::OUString(), *this );
483 
484     bool bExistentObject = false;
485     switch ( _nObjectType )
486     {
487     case DatabaseObject::TABLE:
488     case DatabaseObject::QUERY:
489         bExistentObject = xContainer->hasByName( *i_rObjectName );
490         break;
491     case DatabaseObject::FORM:
492     case DatabaseObject::REPORT:
493     {
494         Reference< XHierarchicalNameAccess > xHierarchy( xContainer, UNO_QUERY_THROW );
495         bExistentObject = xHierarchy->hasByHierarchicalName( *i_rObjectName );
496     }
497     break;
498     }
499 
500     if ( !bExistentObject )
501         throw NoSuchElementException( *i_rObjectName, *this );
502 }
503 
504 // -----------------------------------------------------------------------------
loadComponent(::sal_Int32 _ObjectType,const::rtl::OUString & _ObjectName,::sal_Bool _ForEditing)505 Reference< XComponent > SAL_CALL OApplicationController::loadComponent( ::sal_Int32 _ObjectType,
506     const ::rtl::OUString& _ObjectName, ::sal_Bool _ForEditing ) throw (IllegalArgumentException, NoSuchElementException, SQLException, RuntimeException)
507 {
508     return loadComponentWithArguments( _ObjectType, _ObjectName, _ForEditing, Sequence< PropertyValue >() );
509 }
510 
511 // -----------------------------------------------------------------------------
loadComponentWithArguments(::sal_Int32 _ObjectType,const::rtl::OUString & _ObjectName,::sal_Bool _ForEditing,const Sequence<PropertyValue> & _Arguments)512 Reference< XComponent > SAL_CALL OApplicationController::loadComponentWithArguments( ::sal_Int32 _ObjectType,
513     const ::rtl::OUString& _ObjectName, ::sal_Bool _ForEditing, const Sequence< PropertyValue >& _Arguments ) throw (IllegalArgumentException, NoSuchElementException, SQLException, RuntimeException)
514 {
515 	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
516 	::osl::MutexGuard aGuard( getMutex() );
517 
518     impl_validateObjectTypeAndName_throw( _ObjectType, _ObjectName );
519 
520     Reference< XComponent > xComponent( openElementWithArguments(
521         _ObjectName,
522         lcl_objectType2ElementType( _ObjectType ),
523         _ForEditing ? E_OPEN_DESIGN : E_OPEN_NORMAL,
524         _ForEditing ? SID_DB_APP_EDIT : SID_DB_APP_OPEN,
525         ::comphelper::NamedValueCollection( _Arguments )
526     ) );
527 
528     return xComponent;
529 }
530 
531 // -----------------------------------------------------------------------------
createComponent(::sal_Int32 i_nObjectType,Reference<XComponent> & o_DocumentDefinition)532 Reference< XComponent > SAL_CALL OApplicationController::createComponent( ::sal_Int32 i_nObjectType, Reference< XComponent >& o_DocumentDefinition  ) throw (IllegalArgumentException, SQLException, RuntimeException)
533 {
534     return createComponentWithArguments( i_nObjectType, Sequence< PropertyValue >(), o_DocumentDefinition );
535 }
536 
537 // -----------------------------------------------------------------------------
createComponentWithArguments(::sal_Int32 i_nObjectType,const Sequence<PropertyValue> & i_rArguments,Reference<XComponent> & o_DocumentDefinition)538 Reference< XComponent > SAL_CALL OApplicationController::createComponentWithArguments( ::sal_Int32 i_nObjectType, const Sequence< PropertyValue >& i_rArguments, Reference< XComponent >& o_DocumentDefinition ) throw (IllegalArgumentException, SQLException, RuntimeException)
539 {
540 	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
541 	::osl::MutexGuard aGuard( getMutex() );
542 
543     impl_validateObjectTypeAndName_throw( i_nObjectType, ::boost::optional< ::rtl::OUString >() );
544 
545     Reference< XComponent > xComponent( newElement(
546         lcl_objectType2ElementType( i_nObjectType ),
547         ::comphelper::NamedValueCollection( i_rArguments ),
548         o_DocumentDefinition
549     ) );
550 
551     return xComponent;
552 }
553 
554 // -----------------------------------------------------------------------------
registerContextMenuInterceptor(const Reference<XContextMenuInterceptor> & _Interceptor)555 void SAL_CALL OApplicationController::registerContextMenuInterceptor( const Reference< XContextMenuInterceptor >& _Interceptor ) throw (RuntimeException)
556 {
557     if ( _Interceptor.is() )
558         m_aContextMenuInterceptors.addInterface( _Interceptor );
559 }
560 
561 // -----------------------------------------------------------------------------
releaseContextMenuInterceptor(const Reference<XContextMenuInterceptor> & _Interceptor)562 void SAL_CALL OApplicationController::releaseContextMenuInterceptor( const Reference< XContextMenuInterceptor >& _Interceptor ) throw (RuntimeException)
563 {
564     m_aContextMenuInterceptors.removeInterface( _Interceptor );
565 }
566 
567 // -----------------------------------------------------------------------------
previewChanged(sal_Int32 _nMode)568 void OApplicationController::previewChanged( sal_Int32 _nMode )
569 {
570 	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
571 	::osl::MutexGuard aGuard( getMutex() );
572 
573 	if ( m_xDataSource.is() && !isDataSourceReadOnly() )
574 	{
575 		try
576 		{
577             ::comphelper::NamedValueCollection aLayoutInfo( m_xDataSource->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) );
578             sal_Int32 nOldMode = aLayoutInfo.getOrDefault( "Preview", _nMode );
579             if ( nOldMode != _nMode )
580             {
581                 aLayoutInfo.put( "Preview", _nMode );
582 				m_xDataSource->setPropertyValue( PROPERTY_LAYOUTINFORMATION, makeAny( aLayoutInfo.getPropertyValues() ) );
583             }
584 		}
585 		catch ( const Exception& )
586 		{
587             DBG_UNHANDLED_EXCEPTION();
588 		}
589 	}
590 	InvalidateFeature(SID_DB_APP_DISABLE_PREVIEW);
591 	InvalidateFeature(SID_DB_APP_VIEW_DOCINFO_PREVIEW);
592 	InvalidateFeature(SID_DB_APP_VIEW_DOC_PREVIEW);
593 }
594 // -----------------------------------------------------------------------------
595 //void OApplicationController::updateTitle()
596 //{
597 //	::rtl::OUString sName = getStrippedDatabaseName();
598 //
599 //	String sTitle = String(ModuleRes(STR_APP_TITLE));
600 //	sName = sName + sTitle;
601 //#ifdef DBG_UTIL
602 //    ::rtl::OUString aDefault;
603 //	sName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ["));
604 //    sName += utl::Bootstrap::getBuildIdData( aDefault );
605 //	sName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("]"));
606 //#endif
607 //}
608 // -----------------------------------------------------------------------------
askToReconnect()609 void OApplicationController::askToReconnect()
610 {
611 	if ( m_bNeedToReconnect )
612 	{
613 		m_bNeedToReconnect = sal_False;
614 		sal_Bool bClear = sal_True;
615 		if ( !m_pSubComponentManager->empty() )
616 		{
617 			QueryBox aQry(getView(), ModuleRes(APP_CLOSEDOCUMENTS));
618 			switch (aQry.Execute())
619 			{
620 				case RET_YES:
621 					closeSubComponents();
622 					break;
623 				default:
624 					bClear = sal_False;
625 					break;
626 			}
627 		}
628 		if ( bClear )
629 		{
630 			ElementType eType = getContainer()->getElementType();
631 			disconnect();
632 			getContainer()->getDetailView()->clearPages(sal_False);
633 			getContainer()->selectContainer(E_NONE); // invalidate the old selection
634             m_eCurrentType = E_NONE;
635 			getContainer()->selectContainer(eType); // reselect the current one again
636 		}
637 	}
638 }
639 
640 // -----------------------------------------------------------------------------
getDatabaseName() const641 ::rtl::OUString OApplicationController::getDatabaseName() const
642 {
643     ::rtl::OUString sDatabaseName;
644     try
645     {
646         if ( m_xDataSource.is() )
647         {
648             OSL_VERIFY( m_xDataSource->getPropertyValue( PROPERTY_NAME ) >>= sDatabaseName );
649         }
650     }
651     catch ( const Exception& )
652     {
653         DBG_UNHANDLED_EXCEPTION();
654     }
655     return sDatabaseName;
656 }
657 
658 // -----------------------------------------------------------------------------
getStrippedDatabaseName() const659 ::rtl::OUString OApplicationController::getStrippedDatabaseName() const
660 {
661     ::rtl::OUString sDatabaseName;
662 	return ::dbaui::getStrippedDatabaseName( m_xDataSource, sDatabaseName );
663 }
664 
665 // -----------------------------------------------------------------------------
onDocumentOpened(const::rtl::OUString & _rName,const sal_Int32 _nType,const ElementOpenMode _eMode,const Reference<XComponent> & _xDocument,const Reference<XComponent> & _rxDefinition)666 void OApplicationController::onDocumentOpened( const ::rtl::OUString& _rName, const sal_Int32 _nType,
667         const ElementOpenMode _eMode, const Reference< XComponent >& _xDocument, const Reference< XComponent >& _rxDefinition )
668 {
669 	if ( !_xDocument.is() )
670         return;
671 
672     try
673     {
674         OSL_ENSURE( _xDocument.is(), "OApplicationController::onDocumentOpened: is there any *valid* scenario where this fails?" );
675         m_pSubComponentManager->onSubComponentOpened( _rName, _nType, _eMode, _xDocument.is() ? _xDocument : _rxDefinition );
676 
677         if ( _rxDefinition.is() )
678         {
679             Reference< XPropertySet > xProp( _rxDefinition, UNO_QUERY_THROW );
680             Reference< XPropertySetInfo > xPSI( xProp->getPropertySetInfo(), UNO_SET_THROW );
681             xProp->addPropertyChangeListener( PROPERTY_NAME, static_cast< XPropertyChangeListener* >( this ) );
682         }
683     }
684 	catch( const Exception& )
685 	{
686         DBG_UNHANDLED_EXCEPTION();
687 	}
688 }
689 // -----------------------------------------------------------------------------
insertHierachyElement(ElementType _eType,const String & _sParentFolder,sal_Bool _bCollection,const Reference<XContent> & _xContent,sal_Bool _bMove)690 sal_Bool OApplicationController::insertHierachyElement(ElementType _eType,const String& _sParentFolder,sal_Bool _bCollection,const Reference<XContent>& _xContent,sal_Bool _bMove)
691 {
692 	Reference<XHierarchicalNameContainer> xNames(getElements(_eType), UNO_QUERY);
693 	return dbaui::insertHierachyElement(getView()
694                            ,getORB()
695 						   ,xNames
696 						   ,_sParentFolder
697 						   ,_eType == E_FORM
698 						   ,_bCollection
699 						   ,_xContent
700 						   ,_bMove);
701 }
702 // -----------------------------------------------------------------------------
isRenameDeleteAllowed(ElementType _eType,sal_Bool _bDelete) const703 sal_Bool OApplicationController::isRenameDeleteAllowed(ElementType _eType,sal_Bool _bDelete) const
704 {
705 	ElementType eType = getContainer()->getElementType();
706 	sal_Bool bEnabled = !isDataSourceReadOnly() && eType == _eType;
707 	if ( bEnabled )
708 	{
709 
710 		if ( E_TABLE == eType )
711 			bEnabled = !isConnectionReadOnly() && getContainer()->isALeafSelected();
712 
713 		sal_Bool bCompareRes = sal_False;
714 		if ( _bDelete )
715 			bCompareRes = getContainer()->getSelectionCount() > 0;
716 		else
717 		{
718 			bCompareRes = getContainer()->getSelectionCount() == 1;
719 			if ( bEnabled && bCompareRes && E_TABLE == eType )
720 			{
721 				::std::vector< ::rtl::OUString> aList;
722 				getSelectionElementNames(aList);
723 
724 				try
725 				{
726 					Reference< XNameAccess > xContainer = const_cast<OApplicationController*>(this)->getElements(eType);
727                     bEnabled = (xContainer.is() && xContainer->hasByName(*aList.begin()));
728 					if ( bEnabled )
729 						bEnabled = Reference<XRename>(xContainer->getByName(*aList.begin()),UNO_QUERY).is();
730 				}
731 				catch(Exception&)
732 				{
733 					bEnabled = sal_False;
734 				}
735 			}
736 		}
737 
738 		bEnabled = bEnabled && bCompareRes;
739 	}
740 	return bEnabled;
741 }
742 // -----------------------------------------------------------------------------
onLoadedMenu(const Reference<::com::sun::star::frame::XLayoutManager> & _xLayoutManager)743 void OApplicationController::onLoadedMenu(const Reference< ::com::sun::star::frame::XLayoutManager >& _xLayoutManager)
744 {
745 
746 	if ( _xLayoutManager.is() )
747 	{
748 		static ::rtl::OUString s_sStatusbar(RTL_CONSTASCII_USTRINGPARAM("private:resource/statusbar/statusbar"));
749 		_xLayoutManager->createElement( s_sStatusbar );
750 		_xLayoutManager->requestElement( s_sStatusbar );
751 
752 	    if ( getContainer() )
753         {
754             // we need to share the "mnemonic space":
755             MnemonicGenerator aMnemonicGenerator;
756             // - the menu already has mnemonics
757             SystemWindow* pSystemWindow = getContainer()->GetSystemWindow();
758             MenuBar* pMenu = pSystemWindow ? pSystemWindow->GetMenuBar() : NULL;
759             if ( pMenu )
760             {
761                 sal_uInt16 nMenuItems = pMenu->GetItemCount();
762                 for ( sal_uInt16 i = 0; i < nMenuItems; ++i )
763                     aMnemonicGenerator.RegisterMnemonic( pMenu->GetItemText( pMenu->GetItemId( i ) ) );
764             }
765             // - the icons should use automatic ones
766     	    getContainer()->createIconAutoMnemonics( aMnemonicGenerator );
767             // - as well as the entries in the task pane
768             getContainer()->setTaskExternalMnemonics( aMnemonicGenerator );
769         }
770 
771 	    Execute( SID_DB_APP_VIEW_FORMS, Sequence< PropertyValue >() );
772 		InvalidateAll();
773 	}
774 }
775 // -----------------------------------------------------------------------------
doAction(sal_uInt16 _nId,ElementOpenMode _eOpenMode)776 void OApplicationController::doAction(sal_uInt16 _nId ,ElementOpenMode _eOpenMode)
777 {
778 	::std::vector< ::rtl::OUString> aList;
779 	getSelectionElementNames(aList);
780 	ElementType eType = getContainer()->getElementType();
781     ::comphelper::NamedValueCollection aArguments;
782     ElementOpenMode eOpenMode = _eOpenMode;
783     if ( eType == E_REPORT && E_OPEN_FOR_MAIL == _eOpenMode )
784     {
785         aArguments.put("Hidden",true);
786         eOpenMode = E_OPEN_NORMAL;
787     }
788 
789 	::std::vector< ::std::pair< ::rtl::OUString ,Reference< XModel > > > aCompoments;
790 	::std::vector< ::rtl::OUString>::iterator aEnd = aList.end();
791 	for (::std::vector< ::rtl::OUString>::iterator aIter = aList.begin(); aIter != aEnd; ++aIter)
792 	{
793 		if ( SID_DB_APP_CONVERTTOVIEW == _nId )
794 			convertToView(*aIter);
795 		else
796         {
797             Reference< XModel > xModel( openElementWithArguments( *aIter, eType, eOpenMode, _nId,aArguments ), UNO_QUERY );
798 			aCompoments.push_back( ::std::pair< ::rtl::OUString, Reference< XModel > >( *aIter, xModel ) );
799         }
800 	}
801 
802 	// special handling for mail, if more than one document is selected attach them all
803 	if ( _eOpenMode == E_OPEN_FOR_MAIL )
804 	{
805 
806 		::std::vector< ::std::pair< ::rtl::OUString ,Reference< XModel > > >::iterator componentIter = aCompoments.begin();
807 		::std::vector< ::std::pair< ::rtl::OUString ,Reference< XModel > > >::iterator componentEnd = aCompoments.end();
808         ::rtl::OUString aDocTypeString;
809         SfxMailModel aSendMail;
810 		SfxMailModel::SendMailResult eResult = SfxMailModel::SEND_MAIL_OK;
811 		for (; componentIter != componentEnd && SfxMailModel::SEND_MAIL_OK == eResult; ++componentIter)
812         {
813             try
814             {
815 			    Reference< XModel > xModel(componentIter->second,UNO_QUERY);
816 
817                 // Send document as e-Mail using stored/default type
818                 eResult = aSendMail.AttachDocument(aDocTypeString,xModel,componentIter->first);
819                 ::comphelper::disposeComponent(xModel);
820             }
821             catch(const Exception&)
822             {
823                 DBG_UNHANDLED_EXCEPTION();
824             }
825 		}
826 		if ( !aSendMail.IsEmpty() )
827 			aSendMail.Send( getFrame() );
828 	}
829 }
830 // -----------------------------------------------------------------------------
getElementType(const Reference<XContainer> & _xContainer) const831 ElementType OApplicationController::getElementType(const Reference< XContainer >& _xContainer) const
832 {
833 	ElementType eRet = E_NONE;
834 	Reference<XServiceInfo> xServiceInfo(_xContainer,UNO_QUERY);
835 	if ( xServiceInfo.is() )
836 	{
837 		if ( xServiceInfo->supportsService(SERVICE_SDBCX_TABLES) )
838 			eRet = E_TABLE;
839 		else if ( xServiceInfo->supportsService(SERVICE_NAME_FORM_COLLECTION) )
840 			eRet = E_FORM;
841 		else if ( xServiceInfo->supportsService(SERVICE_NAME_REPORT_COLLECTION) )
842 			eRet = E_REPORT;
843 		else
844 			eRet = E_QUERY;
845 	}
846 	return eRet;
847 }
848 
849 //........................................................................
850 }	// namespace dbaui
851 //........................................................................
852