1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "AppController.hxx"
21 #include "AppDetailView.hxx"
22 #include "AppView.hxx"
23 #include <core_resource.hxx>
24 #include <dbaccess_slotid.hrc>
25 #include <strings.hrc>
26 #include <strings.hxx>
27 #include <defaultobjectnamecheck.hxx>
28 #include <dlgsave.hxx>
29 #include <UITools.hxx>
30 #include "subcomponentmanager.hxx"
32 #include <com/sun/star/container/XChild.hpp>
33 #include <com/sun/star/container/XContainer.hpp>
34 #include <com/sun/star/container/XHierarchicalNameContainer.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/sdb/CommandType.hpp>
37 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
38 #include <com/sun/star/sdbcx/XRename.hpp>
39 #include <com/sun/star/sdb/ErrorCondition.hpp>
40 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
41 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
42 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
43 #include <com/sun/star/util/XRefreshable.hpp>
45 #include <cppuhelper/exc_hlp.hxx>
46 #include <comphelper/types.hxx>
47 #include <connectivity/dbexception.hxx>
48 #include <connectivity/dbtools.hxx>
49 #include <connectivity/sqlerror.hxx>
50 #include <sfx2/mailmodelapi.hxx>
51 #include <svx/dbaexchange.hxx>
52 #include <toolkit/helper/vclunohelper.hxx>
53 #include <comphelper/diagnose_ex.hxx>
54 #include <osl/diagnose.h>
55 #include <vcl/mnemonic.hxx>
56 #include <vcl/svapp.hxx>
57 #include <vcl/syswin.hxx>
58 #include <vcl/weld.hxx>
59 #include <osl/mutex.hxx>
63 using namespace ::dbtools
;
64 using namespace ::connectivity
;
65 using namespace ::svx
;
66 using namespace ::com::sun::star
;
67 using namespace ::com::sun::star::uno
;
68 using namespace ::com::sun::star::awt
;
69 using namespace ::com::sun::star::util
;
70 using namespace ::com::sun::star::frame
;
71 using namespace ::com::sun::star::lang
;
72 using namespace ::com::sun::star::ui::dialogs
;
73 using namespace ::com::sun::star::sdb
;
74 using namespace ::com::sun::star::sdbc
;
75 using namespace ::com::sun::star::sdbcx
;
76 using namespace ::com::sun::star::beans
;
77 using namespace ::com::sun::star::container
;
78 using namespace ::com::sun::star::ucb
;
80 using ::com::sun::star::ui::XContextMenuInterceptor
;
82 namespace DatabaseObject
= ::com::sun::star::sdb::application::DatabaseObject
;
83 namespace ErrorCondition
= ::com::sun::star::sdb::ErrorCondition
;
85 void OApplicationController::convertToView(const OUString
& _sName
)
89 SharedConnection
xConnection( getConnection() );
90 Reference
< XQueriesSupplier
> xSup( xConnection
, UNO_QUERY_THROW
);
91 Reference
< XNameAccess
> xQueries( xSup
->getQueries(), UNO_SET_THROW
);
92 Reference
< XPropertySet
> xSourceObject( xQueries
->getByName( _sName
), UNO_QUERY_THROW
);
94 Reference
< XTablesSupplier
> xTablesSup( xConnection
, UNO_QUERY_THROW
);
95 Reference
< XNameAccess
> xTables( xTablesSup
->getTables(), UNO_SET_THROW
);
97 Reference
< XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
99 const OUString aDefaultName
= ::dbaui::createDefaultName(xMeta
, xTables
, DBA_RES(STR_TBL_TITLE
).getToken(0, ' '));
101 DynamicTableOrQueryNameCheck
aNameChecker( xConnection
, CommandType::TABLE
);
102 OSaveAsDlg
aDlg(getFrameWeld(), CommandType::TABLE
, getORB(), xConnection
, aDefaultName
, aNameChecker
, SADFlags::NONE
);
103 if (aDlg
.run() == RET_OK
)
105 const OUString
& sName
= aDlg
.getName();
106 OUString sCatalog
= aDlg
.getCatalog();
107 OUString sSchema
= aDlg
.getSchema();
109 ::dbtools::composeTableName( xMeta
, sCatalog
, sSchema
, sName
, false, ::dbtools::EComposeRule::InTableDefinitions
) );
110 Reference
<XPropertySet
> xView
= ::dbaui::createView(sNewName
,xConnection
,xSourceObject
);
112 throw SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE
),*this, u
"S1000"_ustr
,0,Any());
113 getContainer()->elementAdded(E_TABLE
,sNewName
,Any(xView
));
116 catch(const SQLException
& )
118 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
120 catch( const Exception
& )
122 DBG_UNHANDLED_EXCEPTION("dbaccess");
126 void OApplicationController::pasteFormat(SotClipboardFormatId _nFormatId
)
128 if ( _nFormatId
== SotClipboardFormatId::NONE
)
133 const TransferableDataHelper
& rClipboard
= getViewClipboard();
134 ElementType eType
= getContainer()->getElementType();
135 if ( eType
== E_TABLE
)
137 m_aTableCopyHelper
.pasteTable( _nFormatId
, rClipboard
, getDatabaseName(), ensureConnection() );
140 paste( eType
, ODataAccessObjectTransferable::extractObjectDescriptor( rClipboard
) );
143 catch( const Exception
& )
145 DBG_UNHANDLED_EXCEPTION("dbaccess");
149 void OApplicationController::openDialog( const OUString
& _sServiceName
)
153 SolarMutexGuard aSolarGuard
;
154 ::osl::MutexGuard
aGuard( getMutex() );
155 weld::WaitObject
aWO(getFrameWeld());
157 Sequence
< Any
> aArgs(3);
158 auto pArgs
= aArgs
.getArray();
159 sal_Int32 nArgPos
= 0;
161 Reference
< css::awt::XWindow
> xWindow
= getTopMostContainerWindow();
164 OSL_ENSURE( getContainer(), "OApplicationController::Construct: have no view!" );
165 if ( getContainer() )
166 xWindow
= VCLUnoHelper::GetInterface(getView()->Window::GetParent());
169 pArgs
[nArgPos
++] <<= PropertyValue( u
"ParentWindow"_ustr
,
172 PropertyState_DIRECT_VALUE
);
174 // the initial selection
175 OUString sInitialSelection
;
176 if ( getContainer() )
177 sInitialSelection
= getDatabaseName();
178 if ( !sInitialSelection
.isEmpty() )
180 pArgs
[ nArgPos
++ ] <<= PropertyValue(
181 u
"InitialSelection"_ustr
, 0,
182 Any( sInitialSelection
), PropertyState_DIRECT_VALUE
);
185 SharedConnection
xConnection( getConnection() );
186 if ( xConnection
.is() )
188 pArgs
[ nArgPos
++ ] <<= PropertyValue(
189 PROPERTY_ACTIVE_CONNECTION
, 0,
190 makeAny( xConnection
), PropertyState_DIRECT_VALUE
);
192 aArgs
.realloc( nArgPos
);
195 Reference
< XExecutableDialog
> xAdminDialog
;
197 getORB()->getServiceManager()->createInstanceWithArgumentsAndContext(_sServiceName
, aArgs
, getORB()),
201 if (xAdminDialog
.is())
202 xAdminDialog
->execute();
204 catch( const Exception
& )
206 DBG_UNHANDLED_EXCEPTION("dbaccess");
210 void OApplicationController::refreshTables()
212 if ( !(getContainer() && getContainer()->getDetailView()) )
215 weld::WaitObject
aWO(getFrameWeld());
216 OSL_ENSURE(getContainer()->getElementType() == E_TABLE
,"Only allowed when the tables container is selected!");
219 Reference
<XRefreshable
> xRefresh(getElements(E_TABLE
),UNO_QUERY
);
223 catch(const Exception
&)
225 OSL_FAIL("Could not refresh tables!");
228 getContainer()->getDetailView()->clearPages(false);
229 getContainer()->getDetailView()->createTablesPage( ensureConnection() );
232 void SAL_CALL
OApplicationController::propertyChange( const PropertyChangeEvent
& evt
)
234 SolarMutexGuard aSolarGuard
;
235 ::osl::MutexGuard
aGuard( getMutex() );
236 if ( evt
.PropertyName
== PROPERTY_USER
)
238 m_bNeedToReconnect
= true;
239 InvalidateFeature(SID_DB_APP_STATUS_USERNAME
);
241 else if ( evt
.PropertyName
== PROPERTY_URL
)
243 m_bNeedToReconnect
= true;
244 InvalidateFeature(SID_DB_APP_STATUS_DBNAME
);
245 InvalidateFeature(SID_DB_APP_STATUS_TYPE
);
246 InvalidateFeature(SID_DB_APP_STATUS_HOSTNAME
);
248 else if ( PROPERTY_NAME
== evt
.PropertyName
)
250 const ElementType eType
= getContainer()->getElementType();
251 if ( eType
== E_FORM
|| eType
== E_REPORT
)
253 OUString sOldName
,sNewName
;
254 evt
.OldValue
>>= sOldName
;
255 evt
.NewValue
>>= sNewName
;
257 // if the old name is empty, then this is a newly inserted content. We're notified of it via the
258 // elementInserted method, so there's no need to handle it here.
260 if ( !sOldName
.isEmpty() )
262 Reference
<XChild
> xChild(evt
.Source
,UNO_QUERY
);
265 Reference
<XContent
> xContent(xChild
->getParent(),UNO_QUERY
);
267 sOldName
= xContent
->getIdentifier()->getContentIdentifier() + "/" + sOldName
;
270 getContainer()->elementReplaced( eType
, sOldName
, sNewName
);
276 aEvt
.Source
= m_xModel
;
280 Reference
< XDataSource
> SAL_CALL
OApplicationController::getDataSource()
282 ::osl::MutexGuard
aGuard( getMutex() );
283 Reference
< XDataSource
> xDataSource( m_xDataSource
, UNO_QUERY
);
287 Reference
< XWindow
> SAL_CALL
OApplicationController::getApplicationMainWindow()
289 ::osl::MutexGuard
aGuard( getMutex() );
290 Reference
< XFrame
> xFrame( getFrame(), UNO_SET_THROW
);
291 Reference
< XWindow
> xWindow( xFrame
->getContainerWindow(), UNO_SET_THROW
);
295 Sequence
< Reference
< XComponent
> > SAL_CALL
OApplicationController::getSubComponents()
297 ::osl::MutexGuard
aGuard( getMutex() );
298 return m_pSubComponentManager
->getSubComponents();
301 Reference
< XConnection
> SAL_CALL
OApplicationController::getActiveConnection()
303 ::osl::MutexGuard
aGuard( getMutex() );
304 return m_xDataSourceConnection
.getTyped();
307 sal_Bool SAL_CALL
OApplicationController::isConnected( )
309 ::osl::MutexGuard
aGuard( getMutex() );
310 return m_xDataSourceConnection
.is();
313 void SAL_CALL
OApplicationController::connect( )
315 SQLExceptionInfo aError
;
316 SharedConnection xConnection
= ensureConnection( &aError
);
317 if ( !xConnection
.is() )
319 if ( aError
.isValid() )
322 // no particular error, but nonetheless could not connect -> throw a generic exception
323 OUString
sConnectingContext( DBA_RES( STR_COULDNOTCONNECT_DATASOURCE
) );
324 OUString sDatabaseName
;
325 ::dbtools::throwGenericSQLException( sConnectingContext
.replaceFirst( "$name$", ::dbaui::getStrippedDatabaseName(m_xDataSource
, sDatabaseName
) ), *this );
329 beans::Pair
< ::sal_Int32
, OUString
> SAL_CALL
OApplicationController::identifySubComponent( const Reference
< XComponent
>& i_rSubComponent
)
331 ::osl::MutexGuard
aGuard( getMutex() );
333 sal_Int32 nType
= -1;
336 if ( !m_pSubComponentManager
->lookupSubComponent( i_rSubComponent
, sName
, nType
) )
337 throw IllegalArgumentException( OUString(), *this, 1 );
339 if ( nType
== SID_DB_APP_DSRELDESIGN
)
340 // this is somewhat hacky ... we're expected to return a DatabaseObject value. However, there is no such
341 // value for the relation design. /me thinks we should change the API definition here ...
344 return beans::Pair
< ::sal_Int32
, OUString
>( nType
, sName
);
347 sal_Bool SAL_CALL
OApplicationController::closeSubComponents( )
349 SolarMutexGuard aSolarGuard
;
350 ::osl::MutexGuard
aGuard( getMutex() );
351 return m_pSubComponentManager
->closeSubComponents();
356 ElementType
lcl_objectType2ElementType( const sal_Int32 _nObjectType
)
358 ElementType
eType( E_NONE
);
359 switch ( _nObjectType
)
361 case DatabaseObject::TABLE
: eType
= E_TABLE
; break;
362 case DatabaseObject::QUERY
: eType
= E_QUERY
; break;
363 case DatabaseObject::FORM
: eType
= E_FORM
; break;
364 case DatabaseObject::REPORT
: eType
= E_REPORT
; break;
366 OSL_FAIL( "lcl_objectType2ElementType: unsupported object type!" );
367 // this should have been caught earlier
373 void OApplicationController::impl_validateObjectTypeAndName_throw( const sal_Int32 _nObjectType
, const ::std::optional
< OUString
>& i_rObjectName
)
375 // ensure we're connected
376 if ( !isConnected() )
379 aError
.raiseException( ErrorCondition::DB_NOT_CONNECTED
, *this );
382 // ensure a proper object type
383 if ( ( _nObjectType
!= DatabaseObject::TABLE
)
384 && ( _nObjectType
!= DatabaseObject::QUERY
)
385 && ( _nObjectType
!= DatabaseObject::FORM
)
386 && ( _nObjectType
!= DatabaseObject::REPORT
)
388 throw IllegalArgumentException( OUString(), *this, 1 );
390 if ( !i_rObjectName
)
393 // ensure an existing object
394 Reference
< XNameAccess
> xContainer( getElements( lcl_objectType2ElementType( _nObjectType
) ) );
395 if ( !xContainer
.is() )
396 // all possible reasons for this (e.g. not being connected currently) should
397 // have been handled before
398 throw RuntimeException( OUString(), *this );
400 bool bExistentObject
= false;
401 switch ( _nObjectType
)
403 case DatabaseObject::TABLE
:
404 case DatabaseObject::QUERY
:
405 bExistentObject
= xContainer
->hasByName( *i_rObjectName
);
407 case DatabaseObject::FORM
:
408 case DatabaseObject::REPORT
:
410 Reference
< XHierarchicalNameAccess
> xHierarchy( xContainer
, UNO_QUERY_THROW
);
411 bExistentObject
= xHierarchy
->hasByHierarchicalName( *i_rObjectName
);
416 if ( !bExistentObject
)
417 throw NoSuchElementException( *i_rObjectName
, *this );
420 Reference
< XComponent
> SAL_CALL
OApplicationController::loadComponent( ::sal_Int32 ObjectType
,
421 const OUString
& ObjectName
, sal_Bool ForEditing
)
423 return loadComponentWithArguments( ObjectType
, ObjectName
, ForEditing
, Sequence
< PropertyValue
>() );
426 Reference
< XComponent
> SAL_CALL
OApplicationController::loadComponentWithArguments( ::sal_Int32 ObjectType
,
427 const OUString
& ObjectName
, sal_Bool ForEditing
, const Sequence
< PropertyValue
>& Arguments
)
429 SolarMutexGuard aSolarGuard
;
430 ::osl::MutexGuard
aGuard( getMutex() );
432 impl_validateObjectTypeAndName_throw( ObjectType
, ObjectName
);
434 Reference
< XComponent
> xComponent( openElementWithArguments(
436 lcl_objectType2ElementType( ObjectType
),
437 ForEditing
? ElementOpenMode::Design
: ElementOpenMode::Normal
,
438 ForEditing
? SID_DB_APP_EDIT
: SID_DB_APP_OPEN
,
439 ::comphelper::NamedValueCollection( Arguments
)
445 Reference
< XComponent
> SAL_CALL
OApplicationController::createComponent( ::sal_Int32 i_nObjectType
, Reference
< XComponent
>& o_DocumentDefinition
)
447 return createComponentWithArguments( i_nObjectType
, Sequence
< PropertyValue
>(), o_DocumentDefinition
);
450 Reference
< XComponent
> SAL_CALL
OApplicationController::createComponentWithArguments( ::sal_Int32 i_nObjectType
, const Sequence
< PropertyValue
>& i_rArguments
, Reference
< XComponent
>& o_DocumentDefinition
)
452 SolarMutexGuard aSolarGuard
;
453 ::osl::MutexGuard
aGuard( getMutex() );
455 impl_validateObjectTypeAndName_throw( i_nObjectType
, ::std::optional
< OUString
>() );
457 Reference
< XComponent
> xComponent( newElement(
458 lcl_objectType2ElementType( i_nObjectType
),
459 ::comphelper::NamedValueCollection( i_rArguments
),
466 void SAL_CALL
OApplicationController::registerContextMenuInterceptor( const Reference
< XContextMenuInterceptor
>& Interceptor
)
468 if ( Interceptor
.is() )
469 m_aContextMenuInterceptors
.addInterface( Interceptor
);
472 void SAL_CALL
OApplicationController::releaseContextMenuInterceptor( const Reference
< XContextMenuInterceptor
>& Interceptor
)
474 m_aContextMenuInterceptors
.removeInterface( Interceptor
);
477 void OApplicationController::previewChanged( sal_Int32 _nMode
)
479 SolarMutexGuard aSolarGuard
;
480 ::osl::MutexGuard
aGuard( getMutex() );
482 if ( m_xDataSource
.is() && !isDataSourceReadOnly() )
486 ::comphelper::NamedValueCollection
aLayoutInfo( m_xDataSource
->getPropertyValue( PROPERTY_LAYOUTINFORMATION
) );
487 sal_Int32 nOldMode
= aLayoutInfo
.getOrDefault( u
"Preview"_ustr
, _nMode
);
488 if ( nOldMode
!= _nMode
)
490 aLayoutInfo
.put( u
"Preview"_ustr
, _nMode
);
491 m_xDataSource
->setPropertyValue( PROPERTY_LAYOUTINFORMATION
, Any( aLayoutInfo
.getPropertyValues() ) );
494 catch ( const Exception
& )
496 DBG_UNHANDLED_EXCEPTION("dbaccess");
499 InvalidateFeature(SID_DB_APP_DISABLE_PREVIEW
);
500 InvalidateFeature(SID_DB_APP_VIEW_DOCINFO_PREVIEW
);
501 InvalidateFeature(SID_DB_APP_VIEW_DOC_PREVIEW
);
504 void OApplicationController::askToReconnect()
506 if ( !m_bNeedToReconnect
)
509 m_bNeedToReconnect
= false;
511 if ( !m_pSubComponentManager
->empty() )
513 std::unique_ptr
<weld::MessageDialog
> xQry(Application::CreateMessageDialog(getFrameWeld(),
514 VclMessageType::Question
, VclButtonsType::YesNo
,
515 DBA_RES(STR_QUERY_CLOSEDOCUMENTS
)));
519 closeSubComponents();
528 ElementType eType
= getContainer()->getElementType();
530 getContainer()->getDetailView()->clearPages(false);
531 getContainer()->selectContainer(E_NONE
); // invalidate the old selection
532 m_eCurrentType
= E_NONE
;
533 getContainer()->selectContainer(eType
); // reselect the current one again
537 OUString
OApplicationController::getDatabaseName() const
539 OUString sDatabaseName
;
542 if ( m_xDataSource
.is() )
544 OSL_VERIFY( m_xDataSource
->getPropertyValue( PROPERTY_NAME
) >>= sDatabaseName
);
547 catch ( const Exception
& )
549 DBG_UNHANDLED_EXCEPTION("dbaccess");
551 return sDatabaseName
;
554 void OApplicationController::onDocumentOpened( const OUString
& _rName
, const sal_Int32 _nType
,
555 const ElementOpenMode _eMode
, const Reference
< XComponent
>& _xDocument
, const Reference
< XComponent
>& _rxDefinition
)
557 if ( !_xDocument
.is() )
562 OSL_ENSURE( _xDocument
.is(), "OApplicationController::onDocumentOpened: is there any *valid* scenario where this fails?" );
563 m_pSubComponentManager
->onSubComponentOpened( _rName
, _nType
, _eMode
, _xDocument
.is() ? _xDocument
: _rxDefinition
);
565 if ( _rxDefinition
.is() )
567 Reference
< XPropertySet
> xProp( _rxDefinition
, UNO_QUERY_THROW
);
568 Reference
< XPropertySetInfo
> xPSI( xProp
->getPropertySetInfo(), UNO_SET_THROW
);
569 xProp
->addPropertyChangeListener( PROPERTY_NAME
, static_cast< XPropertyChangeListener
* >( this ) );
572 catch( const Exception
& )
574 DBG_UNHANDLED_EXCEPTION("dbaccess");
578 bool OApplicationController::insertHierarchyElement(ElementType _eType
, const OUString
& _sParentFolder
, bool _bCollection
, const Reference
<XContent
>& _xContent
, bool _bMove
)
580 Reference
<XHierarchicalNameContainer
> xNames(getElements(_eType
), UNO_QUERY
);
581 return dbaui::insertHierarchyElement(getFrameWeld()
591 bool OApplicationController::isRenameDeleteAllowed(ElementType _eType
, bool _bDelete
) const
593 ElementType eType
= getContainer()->getElementType();
594 bool bEnabled
= !isDataSourceReadOnly() && eType
== _eType
;
598 if ( E_TABLE
== eType
)
599 bEnabled
= !isConnectionReadOnly() && getContainer()->isALeafSelected();
601 bool bCompareRes
= false;
603 bCompareRes
= getContainer()->getSelectionCount() > 0;
606 bCompareRes
= getContainer()->getSelectionCount() == 1;
607 if ( bEnabled
&& bCompareRes
&& E_TABLE
== eType
)
609 std::vector
< OUString
> aList
;
610 getSelectionElementNames(aList
);
614 Reference
< XNameAccess
> xContainer
= const_cast<OApplicationController
*>(this)->getElements(eType
);
615 bEnabled
= (xContainer
.is() && xContainer
->hasByName(*aList
.begin()));
617 bEnabled
= Reference
<XRename
>(xContainer
->getByName(*aList
.begin()),UNO_QUERY
).is();
626 bEnabled
= bEnabled
&& bCompareRes
;
631 void OApplicationController::onLoadedMenu(const Reference
< css::frame::XLayoutManager
>& _xLayoutManager
)
634 if ( !_xLayoutManager
.is() )
637 static constexpr OUString s_sStatusbar
= u
"private:resource/statusbar/statusbar"_ustr
;
638 _xLayoutManager
->createElement( s_sStatusbar
);
639 _xLayoutManager
->requestElement( s_sStatusbar
);
641 if ( getContainer() )
643 // we need to share the "mnemonic space":
644 MnemonicGenerator aMnemonicGenerator
;
645 // - the menu already has mnemonics
646 if (SystemWindow
* pSystemWindow
= getContainer()->GetSystemWindow())
647 pSystemWindow
->CollectMenuBarMnemonics(aMnemonicGenerator
);
648 // - the icons should use automatic ones
649 getContainer()->createIconAutoMnemonics( aMnemonicGenerator
);
650 // - as well as the entries in the task pane
651 getContainer()->setTaskExternalMnemonics( aMnemonicGenerator
);
654 Execute( SID_DB_APP_VIEW_FORMS
, Sequence
< PropertyValue
>() );
658 void OApplicationController::doAction(sal_uInt16 _nId
, const ElementOpenMode _eOpenMode
)
660 std::vector
< OUString
> aList
;
661 getSelectionElementNames(aList
);
662 ElementType eType
= getContainer()->getElementType();
663 ::comphelper::NamedValueCollection aArguments
;
664 ElementOpenMode eOpenMode
= _eOpenMode
;
665 if ( eType
== E_REPORT
&& ElementOpenMode::Mail
== _eOpenMode
)
667 aArguments
.put(u
"Hidden"_ustr
,true);
668 eOpenMode
= ElementOpenMode::Normal
;
671 std::vector
< std::pair
< OUString
,Reference
< XModel
> > > aComponents
;
672 for (auto const& elem
: aList
)
674 if ( SID_DB_APP_CONVERTTOVIEW
== _nId
)
678 Reference
< XModel
> xModel( openElementWithArguments( elem
, eType
, eOpenMode
, _nId
,aArguments
), UNO_QUERY
);
679 aComponents
.emplace_back( elem
, xModel
);
683 // special handling for mail, if more than one document is selected attach them all
684 if ( _eOpenMode
!= ElementOpenMode::Mail
)
688 SfxMailModel aSendMail
;
689 SfxMailModel::SendMailResult eResult
= SfxMailModel::SEND_MAIL_OK
;
690 for (auto const& component
: aComponents
)
694 Reference
< XModel
> xModel
= component
.second
;
696 // Send document as e-Mail using stored/default type
697 eResult
= aSendMail
.AttachDocument(xModel
,component
.first
);
698 ::comphelper::disposeComponent(xModel
);
699 if (eResult
!= SfxMailModel::SEND_MAIL_OK
)
702 catch(const Exception
&)
704 DBG_UNHANDLED_EXCEPTION("dbaccess");
707 if ( !aSendMail
.IsEmpty() )
708 aSendMail
.Send( getFrame() );
711 ElementType
OApplicationController::getElementType(const Reference
< XContainer
>& _xContainer
)
713 ElementType eRet
= E_NONE
;
714 Reference
<XServiceInfo
> xServiceInfo(_xContainer
,UNO_QUERY
);
715 if ( xServiceInfo
.is() )
717 if ( xServiceInfo
->supportsService(SERVICE_SDBCX_TABLES
) )
719 else if ( xServiceInfo
->supportsService(SERVICE_NAME_FORM_COLLECTION
) )
721 else if ( xServiceInfo
->supportsService(SERVICE_NAME_REPORT_COLLECTION
) )
731 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */