1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <memory>
21 #include "AppController.hxx"
22 #include <core_resource.hxx>
23 #include <stringconstants.hxx>
24 #include <advancedsettingsdlg.hxx>
25 #include "subcomponentmanager.hxx"
26 #include <uiservices.hxx>
27 
28 #include <com/sun/star/beans/NamedValue.hpp>
29 #include <com/sun/star/container/XChild.hpp>
30 #include <com/sun/star/container/XContainer.hpp>
31 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
32 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
33 #include <com/sun/star/container/XHierarchicalNameContainer.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/frame/XStorable.hpp>
36 #include <com/sun/star/sdb/CommandType.hpp>
37 #include <com/sun/star/sdb/ErrorMessageDialog.hpp>
38 #include <com/sun/star/sdb/SQLContext.hpp>
39 #include <com/sun/star/sdb/XBookmarksSupplier.hpp>
40 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
41 #include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
42 #include <com/sun/star/sdbc/XDataSource.hpp>
43 #include <com/sun/star/sdbcx/XAlterView.hpp>
44 #include <com/sun/star/sdbcx/XAppend.hpp>
45 #include <com/sun/star/sdbcx/XRename.hpp>
46 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
47 #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
48 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
49 #include <com/sun/star/uno/XNamingService.hpp>
50 #include <com/sun/star/util/XFlushable.hpp>
51 #include <com/sun/star/util/XModifiable.hpp>
52 #include <com/sun/star/util/XModifyBroadcaster.hpp>
53 #include <com/sun/star/util/XNumberFormatter.hpp>
54 #include <com/sun/star/util/XURLTransformer.hpp>
55 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
56 #include <com/sun/star/document/XEmbeddedScripts.hpp>
57 #include <com/sun/star/frame/XModel2.hpp>
58 #include <com/sun/star/awt/XTopWindow.hpp>
59 #include <com/sun/star/task/XInteractionHandler.hpp>
60 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
61 #include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
62 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
63 #include <com/sun/star/container/XHierarchicalName.hpp>
64 #include <tools/diagnose_ex.h>
65 #include <osl/diagnose.h>
66 
67 #include <svl/urihelper.hxx>
68 #include <svl/filenotation.hxx>
69 #include <vcl/treelistbox.hxx>
70 #include <vcl/transfer.hxx>
71 #include <svtools/cliplistener.hxx>
72 #include <vcl/svlbitm.hxx>
73 #include <svtools/insdlg.hxx>
74 
75 #include <comphelper/sequence.hxx>
76 #include <comphelper/uno3.hxx>
77 #include <comphelper/types.hxx>
78 #include <comphelper/interaction.hxx>
79 #include <comphelper/processfactory.hxx>
80 
81 #include <vcl/stdtext.hxx>
82 #include <vcl/svapp.hxx>
83 #include <vcl/menu.hxx>
84 #include <vcl/weld.hxx>
85 
86 #include <unotools/closeveto.hxx>
87 #include <unotools/pathoptions.hxx>
88 #include <unotools/tempfile.hxx>
89 #include <unotools/moduleoptions.hxx>
90 #include <unotools/historyoptions.hxx>
91 
92 #include <sfx2/mailmodelapi.hxx>
93 #include <sfx2/filedlghelper.hxx>
94 #include <sfx2/docfilt.hxx>
95 #include <sfx2/QuerySaveDocument.hxx>
96 
97 #include <cppuhelper/typeprovider.hxx>
98 #include <cppuhelper/exc_hlp.hxx>
99 
100 #include <connectivity/dbtools.hxx>
101 #include <connectivity/dbexception.hxx>
102 
103 #include <svx/dbaexchange.hxx>
104 #include <svx/dbaobjectex.hxx>
105 #include <svx/svxdlg.hxx>
106 
107 #include <osl/mutex.hxx>
108 #include "AppView.hxx"
109 #include <browserids.hxx>
110 #include <dbu_reghelper.hxx>
111 #include <strings.hrc>
112 #include <defaultobjectnamecheck.hxx>
113 #include <databaseobjectview.hxx>
114 #include <listviewitems.hxx>
115 #include "AppDetailView.hxx"
116 #include <linkeddocuments.hxx>
117 #include <sqlmessage.hxx>
118 #include <UITools.hxx>
119 #include <dsntypes.hxx>
120 #include <dlgsave.hxx>
121 #include <dbaccess_slotid.hrc>
122 
123 #include <functional>
124 
createRegistryInfo_ODBApplication()125 extern "C" void createRegistryInfo_ODBApplication()
126 {
127     static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OApplicationController > aAutoRegistration;
128 }
129 
130 namespace dbaui
131 {
132 using namespace ::dbtools;
133 using namespace ::svx;
134 using namespace ::com::sun::star;
135 using namespace ::com::sun::star::uno;
136 using namespace ::com::sun::star::ucb;
137 using namespace ::com::sun::star::view;
138 using namespace ::com::sun::star::util;
139 using namespace ::com::sun::star::beans;
140 using namespace ::com::sun::star::lang;
141 using namespace ::com::sun::star::frame;
142 using namespace ::com::sun::star::container;
143 using namespace ::com::sun::star::sdb;
144 using namespace ::com::sun::star::sdbc;
145 using namespace ::com::sun::star::sdbcx;
146 using namespace ::com::sun::star::datatransfer;
147 using namespace ::com::sun::star::ui::dialogs;
148 using namespace ::com::sun::star::task;
149 using ::com::sun::star::document::XEmbeddedScripts;
150 using ::com::sun::star::document::XDocumentEventBroadcaster;
151 using ::com::sun::star::sdb::application::NamedDatabaseObject;
152 
153 namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
154 namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
155 
getImplementationName()156 OUString SAL_CALL OApplicationController::getImplementationName()
157 {
158     return getImplementationName_Static();
159 }
160 
getImplementationName_Static()161 OUString OApplicationController::getImplementationName_Static()
162 {
163     return SERVICE_SDB_APPLICATIONCONTROLLER;
164 }
165 
getSupportedServiceNames_Static()166 Sequence< OUString> OApplicationController::getSupportedServiceNames_Static()
167 {
168     Sequence<OUString> aSupported { "com.sun.star.sdb.application.DefaultViewController" };
169     return aSupported;
170 }
171 
getSupportedServiceNames()172 Sequence< OUString> SAL_CALL OApplicationController::getSupportedServiceNames()
173 {
174     return getSupportedServiceNames_Static();
175 }
176 
Create(const Reference<XMultiServiceFactory> & _rxFactory)177 Reference< XInterface > OApplicationController::Create(const Reference<XMultiServiceFactory >& _rxFactory)
178 {
179     return *(new OApplicationController( comphelper::getComponentContext(_rxFactory)));
180 }
181 
182 // OApplicationController
183 class SelectionNotifier
184 {
185 private:
186     ::comphelper::OInterfaceContainerHelper2   m_aSelectionListeners;
187     ::cppu::OWeakObject&                m_rContext;
188     sal_Int32                           m_nSelectionNestingLevel;
189 
190 public:
SelectionNotifier(::osl::Mutex & _rMutex,::cppu::OWeakObject & _rContext)191     SelectionNotifier( ::osl::Mutex& _rMutex, ::cppu::OWeakObject& _rContext )
192         :m_aSelectionListeners( _rMutex )
193         ,m_rContext( _rContext )
194         ,m_nSelectionNestingLevel( 0 )
195     {
196     }
197 
198     SelectionNotifier(const SelectionNotifier&) = delete;
199     const SelectionNotifier& operator=(const SelectionNotifier&) = delete;
200 
addListener(const Reference<XSelectionChangeListener> & Listener)201     void addListener( const Reference< XSelectionChangeListener >& Listener )
202     {
203         m_aSelectionListeners.addInterface( Listener );
204     }
205 
removeListener(const Reference<XSelectionChangeListener> & Listener)206     void removeListener( const Reference< XSelectionChangeListener >& Listener )
207     {
208         m_aSelectionListeners.removeInterface( Listener );
209     }
210 
disposing()211     void disposing()
212     {
213         EventObject aEvent( m_rContext );
214         m_aSelectionListeners.disposeAndClear( aEvent );
215     }
216 
SelectionGuardAccessdbaui::SelectionNotifier::SelectionGuardAccess217     struct SelectionGuardAccess { friend class SelectionGuard; private: SelectionGuardAccess() { }  };
218 
219     /** enters a block which modifies the selection of our owner.
220 
221         Can be called multiple times, the only important thing is to call leaveSelection
222         equally often.
223     */
enterSelection(SelectionGuardAccess)224     void    enterSelection( SelectionGuardAccess )
225     {
226         ++m_nSelectionNestingLevel;
227     }
228 
229     /** leaves a block which modifies the selection of our owner
230 
231         Must be paired with enterSelection calls.
232 
233         When the last block is left, i.e. the last leaveSelection call is made on the current stack,
234         then our SelectionChangeListeners are notified
235     */
leaveSelection(SelectionGuardAccess)236     void    leaveSelection( SelectionGuardAccess )
237     {
238         if ( --m_nSelectionNestingLevel == 0 )
239         {
240             EventObject aEvent( m_rContext );
241             m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent );
242         }
243     }
244 };
245 
246 class SelectionGuard
247 {
248 public:
SelectionGuard(SelectionNotifier & _rNotifier)249     explicit SelectionGuard( SelectionNotifier& _rNotifier )
250         :m_rNotifier( _rNotifier )
251     {
252         m_rNotifier.enterSelection( SelectionNotifier::SelectionGuardAccess() );
253     }
254 
~SelectionGuard()255     ~SelectionGuard()
256     {
257         m_rNotifier.leaveSelection( SelectionNotifier::SelectionGuardAccess() );
258     }
259 
260     SelectionGuard(const SelectionGuard&) = delete;
261     const SelectionGuard& operator=(const SelectionGuard&) = delete;
262 
263 private:
264     SelectionNotifier&  m_rNotifier;
265 };
266 
267 // OApplicationController
OApplicationController(const Reference<XComponentContext> & _rxORB)268 OApplicationController::OApplicationController(const Reference< XComponentContext >& _rxORB)
269     :OGenericUnoController( _rxORB )
270     ,m_aContextMenuInterceptors( getMutex() )
271     ,m_pSubComponentManager( new SubComponentManager( *this, getSharedMutex() ) )
272     ,m_aTypeCollection( _rxORB )
273     ,m_aTableCopyHelper(this)
274     ,m_nAsyncDrop(nullptr)
275     ,m_aSelectContainerEvent( LINK( this, OApplicationController, OnSelectContainer ) )
276     ,m_ePreviewMode(E_PREVIEWNONE)
277     ,m_eCurrentType(E_NONE)
278     ,m_bNeedToReconnect(false)
279     ,m_bSuspended( false )
280     ,m_pSelectionNotifier( new SelectionNotifier( getMutex(), *this ) )
281 {
282 }
283 
~OApplicationController()284 OApplicationController::~OApplicationController()
285 {
286     if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
287     {
288         OSL_FAIL("Please check who doesn't dispose this component!");
289         // increment ref count to prevent double call of Dtor
290         osl_atomic_increment( &m_refCount );
291         dispose();
292     }
293     clearView();
294 }
295 
IMPLEMENT_FORWARD_XTYPEPROVIDER2(OApplicationController,OGenericUnoController,OApplicationController_Base)296 IMPLEMENT_FORWARD_XTYPEPROVIDER2(OApplicationController,OGenericUnoController,OApplicationController_Base)
297 IMPLEMENT_FORWARD_XINTERFACE2(OApplicationController,OGenericUnoController,OApplicationController_Base)
298 void OApplicationController::disconnect()
299 {
300     if ( m_xDataSourceConnection.is() )
301         stopConnectionListening( m_xDataSourceConnection );
302 
303     try
304     {
305         // temporary (hopefully!) hack for #i55274#
306         Reference< XFlushable > xFlush( m_xDataSourceConnection, UNO_QUERY );
307         if ( xFlush.is() && m_xMetaData.is() && !m_xMetaData->isReadOnly() )
308             xFlush->flush();
309     }
310     catch( const Exception& )
311     {
312         DBG_UNHANDLED_EXCEPTION("dbaccess");
313     }
314 
315     m_xDataSourceConnection.clear();
316     m_xMetaData.clear();
317 
318     InvalidateAll();
319 }
320 
disposing()321 void SAL_CALL OApplicationController::disposing()
322 {
323     for( const auto& rContainerListener : m_aCurrentContainers )
324     {
325         if( rContainerListener.is() )
326         {
327             rContainerListener->removeContainerListener( this );
328         }
329     }
330 
331     m_aCurrentContainers.clear();
332     m_pSubComponentManager->disposing();
333     m_pSelectionNotifier->disposing();
334 
335     if ( getView() )
336     {
337         getContainer()->showPreview(nullptr);
338         m_pClipboardNotifier->ClearCallbackLink();
339         m_pClipboardNotifier->RemoveListener( getView() );
340         m_pClipboardNotifier.clear();
341     }
342 
343     disconnect();
344     try
345     {
346         Reference < XFrame > xFrame;
347         attachFrame( xFrame );
348 
349         if ( m_xDataSource.is() )
350         {
351             m_xDataSource->removePropertyChangeListener(OUString(), this);
352             m_xDataSource->removePropertyChangeListener(PROPERTY_INFO, this);
353             m_xDataSource->removePropertyChangeListener(PROPERTY_URL, this);
354             m_xDataSource->removePropertyChangeListener(PROPERTY_ISPASSWORDREQUIRED, this);
355             m_xDataSource->removePropertyChangeListener(PROPERTY_LAYOUTINFORMATION, this);
356             m_xDataSource->removePropertyChangeListener(PROPERTY_SUPPRESSVERSIONCL, this);
357             m_xDataSource->removePropertyChangeListener(PROPERTY_TABLEFILTER, this);
358             m_xDataSource->removePropertyChangeListener(PROPERTY_TABLETYPEFILTER, this);
359             m_xDataSource->removePropertyChangeListener(PROPERTY_USER, this);
360             m_xDataSource = nullptr;
361         }
362 
363         Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
364         if ( xBroadcaster.is() )
365             xBroadcaster->removeModifyListener(static_cast<XModifyListener*>(this));
366 
367         if ( m_xModel.is() )
368         {
369             OUString sUrl = m_xModel->getURL();
370             if ( !sUrl.isEmpty() )
371             {
372                 ::comphelper::NamedValueCollection aArgs( m_xModel->getArgs() );
373                 if ( aArgs.getOrDefault( "PickListEntry", true ) )
374                 {
375                     OUString     aFilter;
376                     INetURLObject       aURL( m_xModel->getURL() );
377                     std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
378                     if ( pFilter )
379                         aFilter = pFilter->GetFilterName();
380 
381                     // add to svtool history options
382                     SvtHistoryOptions().AppendItem( ePICKLIST,
383                             aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
384                             aFilter,
385                             getStrippedDatabaseName(),
386                             boost::none);
387 
388                     // add to recent document list
389                     if ( aURL.GetProtocol() == INetProtocol::File )
390                         Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
391                                                               pFilter ? pFilter->GetMimeType() : OUString(),
392                                                               pFilter ? pFilter->GetServiceName() : OUString() );
393                 }
394             }
395 
396             m_xModel->disconnectController( this );
397 
398             m_xModel.clear();
399         }
400     }
401     catch(const Exception&)
402     {
403         DBG_UNHANDLED_EXCEPTION("dbaccess");
404     }
405 
406     clearView();
407     OGenericUnoController::disposing(); // here the m_refCount must be equal 5
408 }
409 
Construct(vcl::Window * _pParent)410 bool OApplicationController::Construct(vcl::Window* _pParent)
411 {
412     setView( VclPtr<OApplicationView>::Create( _pParent, getORB(), *this, m_ePreviewMode ) );
413 
414     // late construction
415     bool bSuccess = false;
416     try
417     {
418         getContainer()->Construct();
419         bSuccess = true;
420     }
421     catch(const SQLException&)
422     {
423     }
424     catch(const Exception&)
425     {
426         OSL_FAIL("OApplicationController::Construct : the construction of UnoDataBrowserView failed !");
427     }
428 
429     if ( !bSuccess )
430     {
431         clearView();
432         return false;
433     }
434 
435     // now that we have a view we can create the clipboard listener
436     m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() );
437     m_aSystemClipboard.StartClipboardListening( );
438 
439     m_pClipboardNotifier = new TransferableClipboardListener( LINK( this, OApplicationController, OnClipboardChanged ) );
440     m_pClipboardNotifier->AddListener( getView() );
441 
442     OGenericUnoController::Construct( _pParent );
443     getView()->Show();
444 
445     return true;
446 }
447 
disposing(const EventObject & _rSource)448 void SAL_CALL OApplicationController::disposing(const EventObject& _rSource)
449 {
450     ::osl::MutexGuard aGuard( getMutex() );
451     Reference<XConnection> xCon(_rSource.Source, UNO_QUERY);
452     if ( xCon.is() )
453     {
454         OSL_ENSURE( m_xDataSourceConnection == xCon,
455             "OApplicationController::disposing: which connection does this come from?" );
456 
457         if ( getContainer() && getContainer()->getElementType() == E_TABLE )
458             getContainer()->clearPages();
459         if ( m_xDataSourceConnection == xCon )
460         {
461             m_xMetaData.clear();
462             m_xDataSourceConnection.clear();
463         }
464     }
465     else if ( _rSource.Source == m_xModel )
466     {
467         m_xModel.clear();
468     }
469     else if ( _rSource.Source == m_xDataSource )
470     {
471         m_xDataSource = nullptr;
472     }
473     else
474     {
475         Reference<XContainer> xContainer( _rSource.Source, UNO_QUERY );
476         if ( xContainer.is() )
477         {
478             TContainerVector::iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer);
479             if ( aFind != m_aCurrentContainers.end() )
480                 m_aCurrentContainers.erase(aFind);
481         }
482         OGenericUnoController::disposing( _rSource );
483     }
484 }
485 
suspend(sal_Bool bSuspend)486 sal_Bool SAL_CALL OApplicationController::suspend(sal_Bool bSuspend)
487 {
488     // notify the OnPrepareViewClosing event (before locking any mutex)
489     Reference< XDocumentEventBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
490     if ( xBroadcaster.is() )
491     {
492         xBroadcaster->notifyDocumentEvent(
493             "OnPrepareViewClosing",
494             this,
495             Any()
496         );
497     }
498 
499     SolarMutexGuard aSolarGuard;
500     ::osl::MutexGuard aGuard( getMutex() );
501 
502     if ( getView() && getView()->IsInModalMode() )
503         return false;
504 
505     bool bCanSuspend = true;
506 
507     if ( m_bSuspended != bool(bSuspend) )
508     {
509         if ( bSuspend && !closeSubComponents() )
510             return false;
511 
512         Reference<XModifiable> xModi(m_xModel,UNO_QUERY);
513         Reference<XStorable> xStor(getModel(),UNO_QUERY);
514 
515         if  (   bSuspend
516             &&  xStor.is()
517             &&  !xStor->isReadonly()
518             &&  (   xModi.is()
519                 &&  xModi->isModified()
520                 )
521             )
522         {
523             switch (ExecuteQuerySaveDocument(getFrameWeld(), getStrippedDatabaseName()))
524             {
525                 case RET_YES:
526                     Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
527                     bCanSuspend = !xModi->isModified();
528                     // when we save the document this must be false else some press cancel
529                     break;
530                 case RET_CANCEL:
531                     bCanSuspend = false;
532                     break;
533                 default:
534                     break;
535             }
536         }
537     }
538 
539     if ( bCanSuspend )
540         m_bSuspended = bSuspend;
541 
542     return bCanSuspend;
543 }
544 
GetState(sal_uInt16 _nId) const545 FeatureState OApplicationController::GetState(sal_uInt16 _nId) const
546 {
547     FeatureState aReturn;
548     aReturn.bEnabled = false;
549     // check this first
550     if ( !getContainer() || m_bReadOnly )
551         return aReturn;
552 
553     try
554     {
555         switch (_nId)
556         {
557             case SID_OPENURL:
558                 aReturn.bEnabled = true;
559                 if ( m_xModel.is() )
560                     aReturn.sTitle = m_xModel->getURL();
561                 break;
562             case ID_BROWSER_COPY:
563                 {
564                     sal_Int32 nCount = getContainer()->getSelectionCount();
565                     aReturn.bEnabled = nCount >= 1;
566                     if ( aReturn.bEnabled && nCount == 1 && getContainer()->getElementType() == E_TABLE )
567                         aReturn.bEnabled = getContainer()->isALeafSelected();
568                 }
569                 break;
570             case ID_BROWSER_CUT:
571                 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() >= 1;
572                 aReturn.bEnabled = aReturn.bEnabled && (getContainer()->getElementType() != E_TABLE || getContainer()->isCutAllowed());
573                 break;
574             case ID_BROWSER_PASTE:
575                 switch( getContainer()->getElementType() )
576                 {
577                     case E_TABLE:
578                         aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
579                         break;
580                     case E_QUERY:
581                         aReturn.bEnabled = !isDataSourceReadOnly() && getViewClipboard().HasFormat(SotClipboardFormatId::DBACCESS_QUERY);
582                         break;
583                     default:
584                         aReturn.bEnabled = !isDataSourceReadOnly() && OComponentTransferable::canExtractComponentDescriptor(getViewClipboard().GetDataFlavorExVector(),getContainer()->getElementType() == E_FORM);
585                 }
586                 break;
587             case SID_DB_APP_PASTE_SPECIAL:
588                 aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
589                 break;
590             case SID_OPENDOC:
591                 aReturn.bEnabled = true;
592                 break;
593             case ID_BROWSER_SAVEDOC:
594                 aReturn.bEnabled = !isDataSourceReadOnly();
595                 break;
596             case ID_BROWSER_SAVEASDOC:
597                 aReturn.bEnabled = true;
598                 break;
599             case ID_BROWSER_SORTUP:
600                 aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
601                 aReturn.bChecked = aReturn.bEnabled && getContainer()->isSortUp();
602                 break;
603             case ID_BROWSER_SORTDOWN:
604                 aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
605                 aReturn.bChecked = aReturn.bEnabled && !getContainer()->isSortUp();
606                 break;
607 
608             case SID_NEWDOC:
609             case SID_APP_NEW_FORM:
610             case ID_DOCUMENT_CREATE_REPWIZ:
611                 aReturn.bEnabled = !isDataSourceReadOnly() && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER);
612                 break;
613             case SID_APP_NEW_REPORT:
614                 aReturn.bEnabled = !isDataSourceReadOnly()
615                                     && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER);
616                 if ( aReturn.bEnabled )
617                 {
618                     Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
619                     aReturn.bEnabled = xEnumAccess.is();
620                     if ( aReturn.bEnabled )
621                     {
622                         const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext);
623                         aReturn.bEnabled = !sReportEngineServiceName.isEmpty();
624                         if ( aReturn.bEnabled )
625                         {
626                             const Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
627                             aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
628                         }
629                     }
630                 }
631                 break;
632             case SID_DB_APP_VIEW_TABLES:
633                 aReturn.bEnabled = true;
634                 aReturn.bChecked = getContainer()->getElementType() == E_TABLE;
635                 break;
636             case SID_DB_APP_VIEW_QUERIES:
637                 aReturn.bEnabled = true;
638                 aReturn.bChecked = getContainer()->getElementType() == E_QUERY;
639                 break;
640             case SID_DB_APP_VIEW_FORMS:
641                 aReturn.bEnabled = true;
642                 aReturn.bChecked = getContainer()->getElementType() == E_FORM;
643                 break;
644             case SID_DB_APP_VIEW_REPORTS:
645                 aReturn.bEnabled = true;
646                 aReturn.bChecked = getContainer()->getElementType() == E_REPORT;
647                 break;
648             case ID_NEW_QUERY_DESIGN:
649             case ID_NEW_QUERY_SQL:
650             case ID_APP_NEW_QUERY_AUTO_PILOT:
651             case SID_DB_FORM_NEW_PILOT:
652                 aReturn.bEnabled = !isDataSourceReadOnly();
653                 break;
654             case ID_NEW_VIEW_DESIGN:
655             case SID_DB_NEW_VIEW_SQL:
656             case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
657                 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
658                 if ( aReturn.bEnabled )
659                 {
660                     Reference<XViewsSupplier> xViewsSup( getConnection(), UNO_QUERY );
661                     aReturn.bEnabled = xViewsSup.is();
662                 }
663                 break;
664             case ID_NEW_TABLE_DESIGN:
665             case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
666                 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
667                 break;
668             case ID_DIRECT_SQL:
669                 aReturn.bEnabled = true;
670                 break;
671             case SID_APP_NEW_FOLDER:
672                 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() <= 1;
673                 if ( aReturn.bEnabled )
674                 {
675                     const ElementType eType = getContainer()->getElementType();
676                     aReturn.bEnabled = eType == E_REPORT || eType == E_FORM;
677                 }
678                 break;
679             case SID_FORM_CREATE_REPWIZ_PRE_SEL:
680             case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
681             case SID_APP_NEW_REPORT_PRE_SEL:
682                 aReturn.bEnabled = !isDataSourceReadOnly()
683                                     && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER)
684                                     && getContainer()->isALeafSelected();
685                 if ( aReturn.bEnabled )
686                 {
687                     ElementType eType = getContainer()->getElementType();
688                     aReturn.bEnabled = eType == E_QUERY || eType == E_TABLE;
689                     if ( aReturn.bEnabled && SID_APP_NEW_REPORT_PRE_SEL == _nId )
690                     {
691                         Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
692                         aReturn.bEnabled = xEnumAccess.is();
693                         if ( aReturn.bEnabled )
694                         {
695                             static const char s_sReportDesign[] = "org.libreoffice.report.pentaho.SOReportJobFactory";
696                             Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(s_sReportDesign);
697                             aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
698                         }
699                     }
700                 }
701                 break;
702             case SID_DB_APP_DELETE:
703             case SID_DB_APP_RENAME:
704                 aReturn.bEnabled = isRenameDeleteAllowed(getContainer()->getElementType(), _nId == SID_DB_APP_DELETE);
705                 break;
706             case SID_DB_APP_TABLE_DELETE:
707             case SID_DB_APP_TABLE_RENAME:
708                 aReturn.bEnabled = isRenameDeleteAllowed(E_TABLE, _nId == SID_DB_APP_TABLE_DELETE);
709                 break;
710             case SID_DB_APP_QUERY_DELETE:
711             case SID_DB_APP_QUERY_RENAME:
712                 aReturn.bEnabled = isRenameDeleteAllowed(E_QUERY, _nId == SID_DB_APP_QUERY_DELETE);
713                 break;
714             case SID_DB_APP_FORM_DELETE:
715             case SID_DB_APP_FORM_RENAME:
716                 aReturn.bEnabled = isRenameDeleteAllowed(E_FORM, _nId == SID_DB_APP_FORM_DELETE);
717                 break;
718             case SID_DB_APP_REPORT_DELETE:
719             case SID_DB_APP_REPORT_RENAME:
720                 aReturn.bEnabled = isRenameDeleteAllowed(E_REPORT, _nId == SID_DB_APP_REPORT_DELETE);
721                 break;
722 
723             case SID_SELECTALL:
724                 aReturn.bEnabled = getContainer()->getElementCount() > 0 && getContainer()->getSelectionCount() != getContainer()->getElementCount();
725                 break;
726             case SID_DB_APP_EDIT:
727             case SID_DB_APP_TABLE_EDIT:
728             case SID_DB_APP_QUERY_EDIT:
729             case SID_DB_APP_FORM_EDIT:
730             case SID_DB_APP_REPORT_EDIT:
731                 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() > 0
732                                     && getContainer()->isALeafSelected();
733                 break;
734             case SID_DB_APP_EDIT_SQL_VIEW:
735                 if ( isDataSourceReadOnly() )
736                     aReturn.bEnabled = false;
737                 else
738                 {
739                     switch ( getContainer()->getElementType() )
740                     {
741                     case E_QUERY:
742                         aReturn.bEnabled =  ( getContainer()->getSelectionCount() > 0 )
743                                         &&  ( getContainer()->isALeafSelected() );
744                         break;
745                     case E_TABLE:
746                         aReturn.bEnabled = false;
747                         // there's one exception: views which support altering their underlying
748                         // command can be edited in SQL view, too
749                         if  (   ( getContainer()->getSelectionCount() > 0 )
750                             &&  ( getContainer()->isALeafSelected() )
751                             )
752                         {
753                             std::vector< OUString > aSelected;
754                             getSelectionElementNames( aSelected );
755                             bool bAlterableViews = true;
756                             for (auto const& selectedName : aSelected)
757                             {
758                                 bAlterableViews &= impl_isAlterableView_nothrow(selectedName);
759                                 if (!bAlterableViews)
760                                     break;
761                             }
762                             aReturn.bEnabled = bAlterableViews;
763                         }
764                         break;
765                     default:
766                         break;
767                     }
768                 }
769                 break;
770             case SID_DB_APP_OPEN:
771             case SID_DB_APP_TABLE_OPEN:
772             case SID_DB_APP_QUERY_OPEN:
773             case SID_DB_APP_FORM_OPEN:
774             case SID_DB_APP_REPORT_OPEN:
775                 aReturn.bEnabled = getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
776                 break;
777             case SID_DB_APP_DSUSERADMIN:
778                 aReturn.bEnabled = !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
779                 break;
780             case SID_DB_APP_DSRELDESIGN:
781                 aReturn.bEnabled = true;
782                 break;
783             case SID_DB_APP_TABLEFILTER:
784                 aReturn.bEnabled = !isDataSourceReadOnly();
785                 break;
786             case SID_DB_APP_REFRESH_TABLES:
787                 aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && isConnected();
788                 break;
789             case SID_DB_APP_DSPROPS:
790                 aReturn.bEnabled = m_xDataSource.is() && dbaccess::ODsnTypeCollection::isShowPropertiesEnabled(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
791                 break;
792             case SID_DB_APP_DSCONNECTION_TYPE:
793                 aReturn.bEnabled = !isDataSourceReadOnly() && m_xDataSource.is() && !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
794                 break;
795             case SID_DB_APP_DSADVANCED_SETTINGS:
796                 aReturn.bEnabled = m_xDataSource.is() && AdvancedSettingsDialog::doesHaveAnyAdvancedSettings( m_aTypeCollection.getType(::comphelper::getString( m_xDataSource->getPropertyValue( PROPERTY_URL ) )) );
797                 break;
798             case SID_DB_APP_CONVERTTOVIEW:
799                 aReturn.bEnabled = !isDataSourceReadOnly();
800                 if ( aReturn.bEnabled )
801                 {
802                     ElementType eType = getContainer()->getElementType();
803                     aReturn.bEnabled = eType == E_QUERY && getContainer()->getSelectionCount() > 0;
804                     if ( aReturn.bEnabled )
805                     {
806                         Reference<XViewsSupplier> xViewSup( getConnection(), UNO_QUERY );
807                         aReturn.bEnabled = xViewSup.is() && Reference<XAppend>(xViewSup->getViews(),UNO_QUERY).is();
808                     }
809                 }
810                 break;
811             case SID_DB_APP_DISABLE_PREVIEW:
812                 aReturn.bEnabled = true;
813                 aReturn.bChecked = getContainer()->getPreviewMode() == E_PREVIEWNONE;
814                 break;
815             case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
816                 {
817                     ElementType eType = getContainer()->getElementType();
818                     aReturn.bEnabled = (E_REPORT == eType || E_FORM == eType);
819                     aReturn.bChecked = getContainer()->getPreviewMode() == E_DOCUMENTINFO;
820                 }
821                 break;
822             case SID_DB_APP_VIEW_DOC_PREVIEW:
823                 aReturn.bEnabled = true;
824                 aReturn.bChecked = getContainer()->getPreviewMode() == E_DOCUMENT;
825                 break;
826             case ID_BROWSER_UNDO:
827                 aReturn.bEnabled = false;
828                 break;
829             case SID_MAIL_SENDDOC:
830                 aReturn.bEnabled = true;
831                 break;
832             case SID_DB_APP_SENDREPORTASMAIL:
833                 {
834                     ElementType eType = getContainer()->getElementType();
835                     aReturn.bEnabled = E_REPORT == eType && getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
836                 }
837                 break;
838             case SID_DB_APP_SENDREPORTTOWRITER:
839             case SID_DB_APP_DBADMIN:
840                 aReturn.bEnabled = false;
841                 break;
842             case SID_DB_APP_STATUS_TYPE:
843                 aReturn.bEnabled = m_xDataSource.is();
844                 if ( aReturn.bEnabled )
845                 {
846                     OUString sURL;
847                     m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
848                     OUString sDSTypeName;
849                     if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase( sURL ) )
850                     {
851                         sDSTypeName = DBA_RES(RID_STR_EMBEDDED_DATABASE);
852                     }
853                     else
854                     {
855                         sDSTypeName = m_aTypeCollection.getTypeDisplayName(sURL);
856                     }
857                     aReturn.sTitle = sDSTypeName;
858                 }
859                 break;
860             case SID_DB_APP_STATUS_DBNAME:
861                 aReturn.bEnabled = m_xDataSource.is();
862                 if ( aReturn.bEnabled )
863                 {
864                     OUString sURL;
865                     m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
866                     OUString sDatabaseName;
867                     OUString sHostName;
868                     sal_Int32 nPortNumber( -1 );
869 
870                     m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
871 
872                     if ( sDatabaseName.isEmpty() )
873                         sDatabaseName = m_aTypeCollection.cutPrefix( sURL );
874                     if ( m_aTypeCollection.isFileSystemBased(sURL) )
875                     {
876                         sDatabaseName = SvtPathOptions().SubstituteVariable( sDatabaseName );
877                         if ( !sDatabaseName.isEmpty() )
878                         {
879                             ::svt::OFileNotation aFileNotation(sDatabaseName);
880                             // set this decoded URL as text
881                             sDatabaseName = aFileNotation.get(::svt::OFileNotation::N_SYSTEM);
882                         }
883                     }
884 
885                     if ( sDatabaseName.isEmpty() )
886                         sDatabaseName = m_aTypeCollection.getTypeDisplayName( sURL );
887 
888                     aReturn.sTitle = sDatabaseName;
889                 }
890                 break;
891             case SID_DB_APP_STATUS_USERNAME:
892                 aReturn.bEnabled = m_xDataSource.is();
893                 if ( aReturn.bEnabled )
894                     m_xDataSource->getPropertyValue( PROPERTY_USER ) >>= aReturn.sTitle;
895                 break;
896             case SID_DB_APP_STATUS_HOSTNAME:
897                 aReturn.bEnabled = m_xDataSource.is();
898                 if ( aReturn.bEnabled )
899                 {
900                     OUString sURL;
901                     m_xDataSource->getPropertyValue( PROPERTY_URL ) >>= sURL;
902 
903                     OUString sHostName, sDatabaseName;
904                     sal_Int32 nPortNumber = -1;
905                     m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
906                     aReturn.sTitle = sHostName;
907                 }
908                 break;
909             default:
910                 aReturn = OGenericUnoController::GetState(_nId);
911         }
912     }
913     catch(const Exception& )
914     {
915         DBG_UNHANDLED_EXCEPTION("dbaccess");
916     }
917     return aReturn;
918 }
919 
920 namespace
921 {
lcl_handleException_nothrow(const Reference<XModel> & _rxDocument,const Any & _rException)922     bool lcl_handleException_nothrow( const Reference< XModel >& _rxDocument, const Any& _rException )
923     {
924         bool bHandled = false;
925 
926         // try handling the error with an interaction handler
927         ::comphelper::NamedValueCollection aArgs( _rxDocument->getArgs() );
928         Reference< XInteractionHandler > xHandler( aArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
929         if ( xHandler.is() )
930         {
931             rtl::Reference pRequest( new ::comphelper::OInteractionRequest( _rException ) );
932             rtl::Reference pApprove( new ::comphelper::OInteractionApprove );
933             pRequest->addContinuation( pApprove.get() );
934 
935             try
936             {
937                 xHandler->handle( pRequest.get() );
938             }
939             catch( const Exception& )
940             {
941                 DBG_UNHANDLED_EXCEPTION("dbaccess");
942             }
943 
944             bHandled = pApprove->wasSelected();
945         }
946         return bHandled;
947     }
948 }
949 
Execute(sal_uInt16 _nId,const Sequence<PropertyValue> & aArgs)950 void OApplicationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
951 {
952     SolarMutexGuard aSolarGuard;
953     ::osl::MutexGuard aGuard( getMutex() );
954 
955     if ( isUserDefinedFeature( _nId ) )
956     {
957         OGenericUnoController::Execute( _nId, aArgs );
958         return;
959     }
960 
961     if ( !getContainer() || m_bReadOnly )
962         return; // return without execution
963 
964     try
965     {
966         switch(_nId)
967         {
968             case ID_BROWSER_CUT:
969                 getContainer()->cut();
970                 break;
971             case ID_BROWSER_COPY:
972                 {
973                     rtl::Reference<TransferableHelper> pTransfer = copyObject();
974                     if ( pTransfer )
975                         pTransfer->CopyToClipboard(getView());
976                 }
977                 break;
978             case ID_BROWSER_PASTE:
979                 {
980                     const TransferableDataHelper& rTransferData( getViewClipboard() );
981                     ElementType eType = getContainer()->getElementType();
982 
983                     switch( eType )
984                     {
985                         case E_TABLE:
986                             {
987                                 // get the selected tablename
988                                 std::vector< OUString > aList;
989                                 getSelectionElementNames( aList );
990                                 if ( !aList.empty() )
991                                     m_aTableCopyHelper.SetTableNameForAppend( *aList.begin() );
992                                 else
993                                     m_aTableCopyHelper.ResetTableNameForAppend();
994 
995                                 m_aTableCopyHelper.pasteTable( rTransferData , getDatabaseName(), ensureConnection() );
996                             }
997                             break;
998 
999                         case E_QUERY:
1000                             if ( rTransferData.HasFormat(SotClipboardFormatId::DBACCESS_QUERY) )
1001                                 paste( E_QUERY, ODataAccessObjectTransferable::extractObjectDescriptor( rTransferData ) );
1002                             break;
1003                         default:
1004                             {
1005                                 std::vector< OUString> aList;
1006                                 getSelectionElementNames(aList);
1007                                 OUString sFolderNameToInsertInto;
1008                                 if ( !aList.empty() )
1009                                 {
1010                                     Reference< XHierarchicalNameAccess > xContainer(getElements(eType),UNO_QUERY);
1011                                     if ( xContainer.is()
1012                                         && xContainer->hasByHierarchicalName(*aList.begin())
1013                                         && (xContainer->getByHierarchicalName(*aList.begin()) >>= xContainer)
1014                                         && xContainer.is()
1015                                         )
1016                                         sFolderNameToInsertInto = *aList.begin();
1017                                 }
1018                                 paste( eType, OComponentTransferable::extractComponentDescriptor( rTransferData ),
1019                                     sFolderNameToInsertInto );
1020                             }
1021                             break;
1022                     }
1023                 }
1024                 break;
1025             case SID_DB_APP_PASTE_SPECIAL:
1026                 {
1027                     if ( !aArgs.hasElements() )
1028                     {
1029                         SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1030                         ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(getFrameWeld()));
1031                         std::vector<SotClipboardFormatId> aFormatIds;
1032                         getSupportedFormats(getContainer()->getElementType(),aFormatIds);
1033                         for (auto const& formatId : aFormatIds)
1034                             pDlg->Insert(formatId,"");
1035 
1036                         const TransferableDataHelper& rClipboard = getViewClipboard();
1037                         pasteFormat(pDlg->GetFormat(rClipboard.GetTransferable()));
1038                     }
1039                     else
1040                     {
1041                         const PropertyValue* pIter = aArgs.getConstArray();
1042                         const PropertyValue* pEnd  = pIter + aArgs.getLength();
1043                         for( ; pIter != pEnd ; ++pIter)
1044                         {
1045                             if ( pIter->Name == "FormatStringId" )
1046                             {
1047                                 sal_uLong nTmp;
1048                                 if ( pIter->Value >>= nTmp )
1049                                     pasteFormat(static_cast<SotClipboardFormatId>(nTmp));
1050                                 break;
1051                             }
1052                         }
1053                     }
1054                 }
1055                 break;
1056             case SID_OPENDOC:
1057                 {
1058                     Reference < XDispatchProvider > xProv( getFrame(), UNO_QUERY );
1059                     if ( xProv.is() )
1060                     {
1061                         URL aURL;
1062                         aURL.Complete = ".uno:Open";
1063 
1064                         if ( m_xUrlTransformer.is() )
1065                             m_xUrlTransformer->parseStrict( aURL );
1066                         Reference < XDispatch > xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
1067                         if ( xDisp.is() )
1068                             xDisp->dispatch( aURL, Sequence < PropertyValue >() );
1069                     }
1070                 }
1071                 break;
1072             case ID_BROWSER_SAVEDOC:
1073                 {
1074                     Reference< XStorable > xStore( m_xModel, UNO_QUERY_THROW );
1075                     try
1076                     {
1077                         xStore->store();
1078                     }
1079                     catch( const Exception& )
1080                     {
1081                         lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
1082                     }
1083                 }
1084                 break;
1085 
1086             case ID_BROWSER_SAVEASDOC:
1087                 {
1088                     OUString sUrl;
1089                     if ( m_xModel.is() )
1090                         sUrl = m_xModel->getURL();
1091                     if ( sUrl.isEmpty() )
1092                         sUrl = SvtPathOptions().GetWorkPath();
1093 
1094                     ::sfx2::FileDialogHelper aFileDlg(
1095                         ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
1096                         FileDialogFlags::NONE, getFrameWeld());
1097                     aFileDlg.SetDisplayDirectory( sUrl );
1098 
1099                     std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
1100                     if ( pFilter )
1101                     {
1102                         aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension());
1103                         aFileDlg.SetCurrentFilter(pFilter->GetUIName());
1104                     }
1105 
1106                     if ( aFileDlg.Execute() != ERRCODE_NONE )
1107                         break;
1108 
1109                     Reference<XStorable> xStore( m_xModel, UNO_QUERY_THROW );
1110                     INetURLObject aURL( aFileDlg.GetPath() );
1111                     try
1112                     {
1113                         xStore->storeAsURL( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Sequence< PropertyValue >() );
1114                     }
1115                     catch( const Exception& )
1116                     {
1117                         lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
1118                     }
1119 
1120                     /*updateTitle();*/
1121                     m_bCurrentlyModified = false;
1122                     InvalidateFeature(ID_BROWSER_SAVEDOC);
1123                     if ( getContainer()->getElementType() == E_NONE )
1124                     {
1125                         getContainer()->selectContainer(E_NONE);
1126                         getContainer()->selectContainer(E_TABLE);
1127                         // #i95524#
1128                         getContainer()->Invalidate();
1129                         refreshTables();
1130                     }
1131 
1132                 }
1133                 break;
1134             case ID_BROWSER_SORTUP:
1135                 getContainer()->sortUp();
1136                 InvalidateFeature(ID_BROWSER_SORTDOWN);
1137                 break;
1138             case ID_BROWSER_SORTDOWN:
1139                 getContainer()->sortDown();
1140                 InvalidateFeature(ID_BROWSER_SORTUP);
1141                 break;
1142 
1143             case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
1144             case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
1145             case ID_APP_NEW_QUERY_AUTO_PILOT:
1146             case SID_DB_FORM_NEW_PILOT:
1147             case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
1148             case SID_APP_NEW_REPORT_PRE_SEL:
1149             case SID_FORM_CREATE_REPWIZ_PRE_SEL:
1150             case ID_DOCUMENT_CREATE_REPWIZ:
1151             case SID_APP_NEW_FORM:
1152             case SID_APP_NEW_REPORT:
1153             case ID_NEW_QUERY_SQL:
1154             case ID_NEW_QUERY_DESIGN:
1155             case ID_NEW_TABLE_DESIGN:
1156                 {
1157                     ElementType eType = E_TABLE;
1158                     bool bAutoPilot = false;
1159                     ::comphelper::NamedValueCollection aCreationArgs;
1160 
1161                     switch( _nId )
1162                     {
1163                         case SID_DB_FORM_NEW_PILOT:
1164                         case SID_FORM_CREATE_REPWIZ_PRE_SEL:
1165                             bAutoPilot = true;
1166                             [[fallthrough]];
1167                         case SID_APP_NEW_FORM:
1168                             eType = E_FORM;
1169                             break;
1170                         case ID_DOCUMENT_CREATE_REPWIZ:
1171                         case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
1172                             bAutoPilot = true;
1173                             [[fallthrough]];
1174                         case SID_APP_NEW_REPORT:
1175                         case SID_APP_NEW_REPORT_PRE_SEL:
1176                             eType = E_REPORT;
1177                             break;
1178                         case ID_APP_NEW_QUERY_AUTO_PILOT:
1179                             bAutoPilot = true;
1180                             eType = E_QUERY;
1181                             break;
1182                         case ID_NEW_QUERY_DESIGN:
1183                             aCreationArgs.put( OUString(PROPERTY_GRAPHICAL_DESIGN), true );
1184                             [[fallthrough]];
1185                         case ID_NEW_QUERY_SQL:
1186                             eType = E_QUERY;
1187                             break;
1188                          case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
1189                              bAutoPilot = true;
1190                              [[fallthrough]];
1191                         case ID_NEW_TABLE_DESIGN:
1192                             break;
1193                         default:
1194                             OSL_FAIL("illegal switch call!");
1195                     }
1196                     if ( bAutoPilot )
1197                         getContainer()->PostUserEvent( LINK( this, OApplicationController, OnCreateWithPilot ), reinterpret_cast< void* >( eType ) );
1198                     else
1199                     {
1200                         Reference< XComponent > xDocDefinition;
1201                         newElement( eType, aCreationArgs, xDocDefinition );
1202                     }
1203                 }
1204                 break;
1205             case SID_APP_NEW_FOLDER:
1206                 {
1207                     ElementType eType = getContainer()->getElementType();
1208                     OUString sName = getContainer()->getQualifiedName( nullptr );
1209                     insertHierachyElement(eType,sName);
1210                 }
1211                 break;
1212             case ID_NEW_VIEW_DESIGN:
1213             case SID_DB_NEW_VIEW_SQL:
1214                 {
1215                     SharedConnection xConnection( ensureConnection() );
1216                     if ( xConnection.is() )
1217                     {
1218                         QueryDesigner aDesigner( getORB(), this, getFrame(), true );
1219 
1220                         ::comphelper::NamedValueCollection aCreationArgs;
1221                         aCreationArgs.put( OUString(PROPERTY_GRAPHICAL_DESIGN), ID_NEW_VIEW_DESIGN == _nId );
1222 
1223                         const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1224                         const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource, aCreationArgs );
1225                         onDocumentOpened( OUString(), E_QUERY, E_OPEN_DESIGN, xComponent, nullptr );
1226                     }
1227                 }
1228                 break;
1229             case SID_DB_APP_DELETE:
1230             case SID_DB_APP_TABLE_DELETE:
1231             case SID_DB_APP_QUERY_DELETE:
1232             case SID_DB_APP_FORM_DELETE:
1233             case SID_DB_APP_REPORT_DELETE:
1234                 deleteEntries();
1235                 break;
1236             case SID_DB_APP_RENAME:
1237             case SID_DB_APP_TABLE_RENAME:
1238             case SID_DB_APP_QUERY_RENAME:
1239             case SID_DB_APP_FORM_RENAME:
1240             case SID_DB_APP_REPORT_RENAME:
1241                 renameEntry();
1242                 break;
1243             case SID_DB_APP_EDIT:
1244             case SID_DB_APP_EDIT_SQL_VIEW:
1245             case SID_DB_APP_TABLE_EDIT:
1246             case SID_DB_APP_QUERY_EDIT:
1247             case SID_DB_APP_FORM_EDIT:
1248             case SID_DB_APP_REPORT_EDIT:
1249                 doAction( _nId, E_OPEN_DESIGN );
1250                 break;
1251             case SID_DB_APP_OPEN:
1252             case SID_DB_APP_TABLE_OPEN:
1253             case SID_DB_APP_QUERY_OPEN:
1254             case SID_DB_APP_FORM_OPEN:
1255             case SID_DB_APP_REPORT_OPEN:
1256                 doAction( _nId, E_OPEN_NORMAL );
1257                 break;
1258             case SID_DB_APP_CONVERTTOVIEW:
1259                 doAction( _nId, E_OPEN_NORMAL );
1260                 break;
1261             case SID_SELECTALL:
1262                 getContainer()->selectAll();
1263                 InvalidateAll();
1264                 break;
1265             case SID_DB_APP_DSRELDESIGN:
1266             {
1267                 Reference< XComponent > xRelationDesigner;
1268                 if ( !m_pSubComponentManager->activateSubFrame( OUString(), SID_DB_APP_DSRELDESIGN, E_OPEN_DESIGN, xRelationDesigner ) )
1269                 {
1270                     SharedConnection xConnection( ensureConnection() );
1271                     if ( xConnection.is() )
1272                     {
1273                         RelationDesigner aDesigner( getORB(), this, m_aCurrentFrame.getFrame() );
1274 
1275                         const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1276                         const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource );
1277                         onDocumentOpened( OUString(), SID_DB_APP_DSRELDESIGN, E_OPEN_DESIGN, xComponent, nullptr );
1278                     }
1279                 }
1280             }
1281             break;
1282             case SID_DB_APP_DSUSERADMIN:
1283                 {
1284                     SharedConnection xConnection( ensureConnection() );
1285                     if ( xConnection.is() )
1286                         openDialog("com.sun.star.sdb.UserAdministrationDialog");
1287                 }
1288                 break;
1289             case SID_DB_APP_TABLEFILTER:
1290                 // opens the table filter dialog for the selected data source
1291                 openDialog( "com.sun.star.sdb.TableFilterDialog" );
1292                 askToReconnect();
1293                 break;
1294             case SID_DB_APP_REFRESH_TABLES:
1295                 refreshTables();
1296                 break;
1297             case SID_DB_APP_DSPROPS:
1298                 // opens the administration dialog for the selected data source
1299                 openDialog( "com.sun.star.sdb.DatasourceAdministrationDialog" );
1300                 askToReconnect();
1301                 break;
1302             case SID_DB_APP_DSADVANCED_SETTINGS:
1303                 openDialog("com.sun.star.sdb.AdvancedDatabaseSettingsDialog");
1304                 askToReconnect();
1305                 break;
1306             case SID_DB_APP_DSCONNECTION_TYPE:
1307                 openDialog("com.sun.star.sdb.DataSourceTypeChangeDialog");
1308                 askToReconnect();
1309                 break;
1310             case ID_DIRECT_SQL:
1311                 {
1312                     SharedConnection xConnection( ensureConnection() );
1313                     if ( xConnection.is() )
1314                         // opens the DirectSQLDialog to execute hand made sql statements.
1315                         openDialog( SERVICE_SDB_DIRECTSQLDIALOG );
1316                 }
1317                 break;
1318             case SID_DB_APP_VIEW_TABLES:
1319                 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_TABLE ) );
1320                 break;
1321             case SID_DB_APP_VIEW_QUERIES:
1322                 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_QUERY ) );
1323                 break;
1324             case SID_DB_APP_VIEW_FORMS:
1325                 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_FORM ) );
1326                 break;
1327             case SID_DB_APP_VIEW_REPORTS:
1328                 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_REPORT ) );
1329                 break;
1330             case SID_DB_APP_DISABLE_PREVIEW:
1331                 m_ePreviewMode = E_PREVIEWNONE;
1332                 getContainer()->switchPreview(m_ePreviewMode);
1333                 break;
1334             case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
1335                 m_ePreviewMode = E_DOCUMENTINFO;
1336                 getContainer()->switchPreview(m_ePreviewMode);
1337                 break;
1338             case SID_DB_APP_VIEW_DOC_PREVIEW:
1339                 m_ePreviewMode = E_DOCUMENT;
1340                 getContainer()->switchPreview(m_ePreviewMode);
1341                 break;
1342             case SID_MAIL_SENDDOC:
1343                 {
1344                     SfxMailModel aSendMail;
1345                     if ( aSendMail.AttachDocument(getModel(), OUString()) == SfxMailModel::SEND_MAIL_OK )
1346                         aSendMail.Send( getFrame() );
1347                 }
1348                 break;
1349             case SID_DB_APP_SENDREPORTASMAIL:
1350                 doAction( _nId, E_OPEN_FOR_MAIL );
1351                 break;
1352         }
1353     }
1354     catch( const Exception& )
1355     {
1356         DBG_UNHANDLED_EXCEPTION("dbaccess");
1357     }
1358     InvalidateFeature(_nId);
1359 }
1360 
describeSupportedFeatures()1361 void OApplicationController::describeSupportedFeatures()
1362 {
1363     OGenericUnoController::describeSupportedFeatures();
1364 
1365     implDescribeSupportedFeature( ".uno:Save",               ID_BROWSER_SAVEDOC,        CommandGroup::DOCUMENT );
1366     implDescribeSupportedFeature( ".uno:SaveAs",             ID_BROWSER_SAVEASDOC,      CommandGroup::DOCUMENT );
1367     implDescribeSupportedFeature( ".uno:SendMail",           SID_MAIL_SENDDOC,          CommandGroup::DOCUMENT );
1368     implDescribeSupportedFeature( ".uno:DBSendReportAsMail",SID_DB_APP_SENDREPORTASMAIL,
1369                                                                                         CommandGroup::DOCUMENT );
1370     implDescribeSupportedFeature( ".uno:DBSendReportToWriter",SID_DB_APP_SENDREPORTTOWRITER,
1371                                                                                         CommandGroup::DOCUMENT );
1372     implDescribeSupportedFeature( ".uno:DBNewForm",          SID_APP_NEW_FORM,          CommandGroup::INSERT );
1373     implDescribeSupportedFeature( ".uno:DBNewFolder",        SID_APP_NEW_FOLDER,        CommandGroup::INSERT );
1374     implDescribeSupportedFeature( ".uno:DBNewFormAutoPilot", SID_DB_FORM_NEW_PILOT,     CommandGroup::INSERT );
1375     implDescribeSupportedFeature( ".uno:DBNewFormAutoPilotWithPreSelection",
1376                                                              SID_FORM_CREATE_REPWIZ_PRE_SEL,
1377                                                                                         CommandGroup::APPLICATION );
1378 
1379     implDescribeSupportedFeature( ".uno:DBNewReport",        SID_APP_NEW_REPORT,        CommandGroup::INSERT );
1380     implDescribeSupportedFeature( ".uno:DBNewReportAutoPilot",
1381                                                              ID_DOCUMENT_CREATE_REPWIZ, CommandGroup::INSERT );
1382     implDescribeSupportedFeature( ".uno:DBNewReportAutoPilotWithPreSelection",
1383                                                              SID_REPORT_CREATE_REPWIZ_PRE_SEL,
1384                                                                                         CommandGroup::APPLICATION );
1385     implDescribeSupportedFeature( ".uno:DBNewQuery",         ID_NEW_QUERY_DESIGN,       CommandGroup::INSERT );
1386     implDescribeSupportedFeature( ".uno:DBNewQuerySql",      ID_NEW_QUERY_SQL,          CommandGroup::INSERT );
1387     implDescribeSupportedFeature( ".uno:DBNewQueryAutoPilot",ID_APP_NEW_QUERY_AUTO_PILOT,
1388                                                                                         CommandGroup::INSERT );
1389     implDescribeSupportedFeature( ".uno:DBNewTable",         ID_NEW_TABLE_DESIGN,       CommandGroup::INSERT );
1390     implDescribeSupportedFeature( ".uno:DBNewTableAutoPilot",ID_NEW_TABLE_DESIGN_AUTO_PILOT,
1391                                                                                         CommandGroup::INSERT );
1392     implDescribeSupportedFeature( ".uno:DBNewView",          ID_NEW_VIEW_DESIGN,        CommandGroup::INSERT );
1393     implDescribeSupportedFeature( ".uno:DBNewViewSQL",       SID_DB_NEW_VIEW_SQL,       CommandGroup::INSERT );
1394 
1395     implDescribeSupportedFeature( ".uno:DBDelete",           SID_DB_APP_DELETE,         CommandGroup::EDIT );
1396     implDescribeSupportedFeature( ".uno:Delete",             SID_DB_APP_DELETE,         CommandGroup::EDIT );
1397     implDescribeSupportedFeature( ".uno:DBRename",           SID_DB_APP_RENAME,         CommandGroup::EDIT );
1398     implDescribeSupportedFeature( ".uno:DBEdit",             SID_DB_APP_EDIT,           CommandGroup::EDIT );
1399     implDescribeSupportedFeature( ".uno:DBEditSqlView",      SID_DB_APP_EDIT_SQL_VIEW,  CommandGroup::EDIT );
1400     implDescribeSupportedFeature( ".uno:DBOpen",             SID_DB_APP_OPEN,           CommandGroup::EDIT );
1401 
1402     implDescribeSupportedFeature( ".uno:DBTableDelete",      SID_DB_APP_TABLE_DELETE,   CommandGroup::EDIT );
1403     implDescribeSupportedFeature( ".uno:DBTableRename",      SID_DB_APP_TABLE_RENAME,   CommandGroup::EDIT );
1404     implDescribeSupportedFeature( ".uno:DBTableEdit",        SID_DB_APP_TABLE_EDIT,     CommandGroup::EDIT );
1405     implDescribeSupportedFeature( ".uno:DBTableOpen",        SID_DB_APP_TABLE_OPEN,     CommandGroup::EDIT );
1406 
1407     implDescribeSupportedFeature( ".uno:DBQueryDelete",      SID_DB_APP_QUERY_DELETE,   CommandGroup::EDIT );
1408     implDescribeSupportedFeature( ".uno:DBQueryRename",      SID_DB_APP_QUERY_RENAME,   CommandGroup::EDIT );
1409     implDescribeSupportedFeature( ".uno:DBQueryEdit",        SID_DB_APP_QUERY_EDIT,     CommandGroup::EDIT );
1410     implDescribeSupportedFeature( ".uno:DBQueryOpen",        SID_DB_APP_QUERY_OPEN,     CommandGroup::EDIT );
1411 
1412     implDescribeSupportedFeature( ".uno:DBFormDelete",       SID_DB_APP_FORM_DELETE,    CommandGroup::EDIT );
1413     implDescribeSupportedFeature( ".uno:DBFormRename",       SID_DB_APP_FORM_RENAME,    CommandGroup::EDIT );
1414     implDescribeSupportedFeature( ".uno:DBFormEdit",         SID_DB_APP_FORM_EDIT,      CommandGroup::EDIT );
1415     implDescribeSupportedFeature( ".uno:DBFormOpen",         SID_DB_APP_FORM_OPEN,      CommandGroup::EDIT );
1416 
1417     implDescribeSupportedFeature( ".uno:DBReportDelete",     SID_DB_APP_REPORT_DELETE,  CommandGroup::EDIT );
1418     implDescribeSupportedFeature( ".uno:DBReportRename",     SID_DB_APP_REPORT_RENAME,  CommandGroup::EDIT );
1419     implDescribeSupportedFeature( ".uno:DBReportEdit",       SID_DB_APP_REPORT_EDIT,    CommandGroup::EDIT );
1420     implDescribeSupportedFeature( ".uno:DBReportOpen",       SID_DB_APP_REPORT_OPEN,    CommandGroup::EDIT );
1421 
1422     implDescribeSupportedFeature( ".uno:SelectAll",          SID_SELECTALL,             CommandGroup::EDIT );
1423     implDescribeSupportedFeature( ".uno:Undo",               ID_BROWSER_UNDO,           CommandGroup::EDIT );
1424 
1425     implDescribeSupportedFeature( ".uno:Sortup",             ID_BROWSER_SORTUP,         CommandGroup::VIEW );
1426     implDescribeSupportedFeature( ".uno:SortDown",           ID_BROWSER_SORTDOWN,       CommandGroup::VIEW );
1427     implDescribeSupportedFeature( ".uno:DBRelationDesign",   SID_DB_APP_DSRELDESIGN,    CommandGroup::APPLICATION );
1428     implDescribeSupportedFeature( ".uno:DBUserAdmin",        SID_DB_APP_DSUSERADMIN,    CommandGroup::APPLICATION );
1429     implDescribeSupportedFeature( ".uno:DBTableFilter",      SID_DB_APP_TABLEFILTER,    CommandGroup::APPLICATION );
1430     implDescribeSupportedFeature( ".uno:DBDSProperties",     SID_DB_APP_DSPROPS,        CommandGroup::EDIT );
1431     implDescribeSupportedFeature( ".uno:DBDSConnectionType", SID_DB_APP_DSCONNECTION_TYPE,
1432                                                                                         CommandGroup::EDIT );
1433     implDescribeSupportedFeature( ".uno:DBDSAdvancedSettings",
1434                                                              SID_DB_APP_DSADVANCED_SETTINGS,
1435                                                                                         CommandGroup::EDIT );
1436     implDescribeSupportedFeature( ".uno:PasteSpecial",       SID_DB_APP_PASTE_SPECIAL,  CommandGroup::EDIT );
1437     implDescribeSupportedFeature( ".uno:DBConvertToView",    SID_DB_APP_CONVERTTOVIEW,  CommandGroup::EDIT );
1438     implDescribeSupportedFeature( ".uno:DBRefreshTables",    SID_DB_APP_REFRESH_TABLES, CommandGroup::APPLICATION );
1439     implDescribeSupportedFeature( ".uno:DBDirectSQL",        ID_DIRECT_SQL,             CommandGroup::APPLICATION );
1440     implDescribeSupportedFeature( ".uno:DBViewTables",       SID_DB_APP_VIEW_TABLES,    CommandGroup::VIEW );
1441     implDescribeSupportedFeature( ".uno:DBViewQueries",      SID_DB_APP_VIEW_QUERIES,   CommandGroup::VIEW );
1442     implDescribeSupportedFeature( ".uno:DBViewForms",        SID_DB_APP_VIEW_FORMS,     CommandGroup::VIEW );
1443     implDescribeSupportedFeature( ".uno:DBViewReports",      SID_DB_APP_VIEW_REPORTS,   CommandGroup::VIEW );
1444     implDescribeSupportedFeature( ".uno:DBDisablePreview",   SID_DB_APP_DISABLE_PREVIEW,CommandGroup::VIEW );
1445     implDescribeSupportedFeature( ".uno:DBShowDocInfoPreview",
1446                                                              SID_DB_APP_VIEW_DOCINFO_PREVIEW,
1447                                                                                         CommandGroup::VIEW );
1448     implDescribeSupportedFeature( ".uno:DBShowDocPreview",   SID_DB_APP_VIEW_DOC_PREVIEW,
1449                                                                                         CommandGroup::VIEW );
1450 
1451     implDescribeSupportedFeature( ".uno:OpenUrl",            SID_OPENURL,               CommandGroup::APPLICATION );
1452 
1453     // this one should not appear under Tools->Customize->Keyboard
1454     implDescribeSupportedFeature( ".uno:DBNewReportWithPreSelection",
1455                                                              SID_APP_NEW_REPORT_PRE_SEL );
1456     implDescribeSupportedFeature( ".uno:DBDSImport",         SID_DB_APP_DSIMPORT);
1457     implDescribeSupportedFeature( ".uno:DBDSExport",         SID_DB_APP_DSEXPORT);
1458     implDescribeSupportedFeature( ".uno:DBDBAdmin",          SID_DB_APP_DBADMIN);
1459 
1460     // status info
1461     implDescribeSupportedFeature( ".uno:DBStatusType",       SID_DB_APP_STATUS_TYPE);
1462     implDescribeSupportedFeature( ".uno:DBStatusDBName",     SID_DB_APP_STATUS_DBNAME);
1463     implDescribeSupportedFeature( ".uno:DBStatusUserName",   SID_DB_APP_STATUS_USERNAME);
1464     implDescribeSupportedFeature( ".uno:DBStatusHostName",   SID_DB_APP_STATUS_HOSTNAME);
1465 }
1466 
getContainer() const1467 OApplicationView*   OApplicationController::getContainer() const
1468 {
1469     return static_cast< OApplicationView* >( getView() );
1470 }
1471 
1472 // css::container::XContainerListener
elementInserted(const ContainerEvent & _rEvent)1473 void SAL_CALL OApplicationController::elementInserted( const ContainerEvent& _rEvent )
1474 {
1475     SolarMutexGuard aSolarGuard;
1476     ::osl::MutexGuard aGuard( getMutex() );
1477 
1478     Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1479     if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) != m_aCurrentContainers.end() )
1480     {
1481         OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1482         if ( getContainer() )
1483         {
1484             OUString sName;
1485             _rEvent.Accessor >>= sName;
1486             ElementType eType = getElementType(xContainer);
1487 
1488             switch( eType )
1489             {
1490                 case E_TABLE:
1491                     ensureConnection();
1492                     break;
1493                 case E_FORM:
1494                 case E_REPORT:
1495                     {
1496                         Reference< XContainer > xSubContainer(_rEvent.Element,UNO_QUERY);
1497                         if ( xSubContainer.is() )
1498                             containerFound(xSubContainer);
1499                     }
1500                     break;
1501                 default:
1502                     break;
1503             }
1504             getContainer()->elementAdded(eType,sName,_rEvent.Element);
1505         }
1506     }
1507 }
1508 
elementRemoved(const ContainerEvent & _rEvent)1509 void SAL_CALL OApplicationController::elementRemoved( const ContainerEvent& _rEvent )
1510 {
1511     SolarMutexGuard aSolarGuard;
1512     ::osl::MutexGuard aGuard( getMutex() );
1513 
1514     Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1515     if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) != m_aCurrentContainers.end() )
1516     {
1517         OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1518         OUString sName;
1519         _rEvent.Accessor >>= sName;
1520         ElementType eType = getElementType(xContainer);
1521         switch( eType )
1522         {
1523             case E_TABLE:
1524                 ensureConnection();
1525                 break;
1526             case E_FORM:
1527             case E_REPORT:
1528                 {
1529                     Reference<XContent> xContent(xContainer,UNO_QUERY);
1530                     if ( xContent.is() )
1531                     {
1532                         sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
1533                     }
1534                 }
1535                 break;
1536             default:
1537                 break;
1538         }
1539         getContainer()->elementRemoved(eType,sName);
1540     }
1541 }
1542 
elementReplaced(const ContainerEvent & _rEvent)1543 void SAL_CALL OApplicationController::elementReplaced( const ContainerEvent& _rEvent )
1544 {
1545     SolarMutexGuard aSolarGuard;
1546     ::osl::MutexGuard aGuard( getMutex() );
1547 
1548     Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1549     if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) != m_aCurrentContainers.end() )
1550     {
1551         OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1552         OUString sName;
1553         try
1554         {
1555             _rEvent.Accessor >>= sName;
1556             Reference<XPropertySet> xProp(_rEvent.Element,UNO_QUERY);
1557             OUString sNewName;
1558 
1559             ElementType eType = getElementType(xContainer);
1560             switch( eType )
1561             {
1562                 case E_TABLE:
1563                 {
1564                     ensureConnection();
1565                     if ( xProp.is() && m_xMetaData.is() )
1566                         sNewName = ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
1567                 }
1568                 break;
1569                 case E_FORM:
1570                 case E_REPORT:
1571                     {
1572                         Reference<XContent> xContent(xContainer,UNO_QUERY);
1573                         if ( xContent.is() )
1574                         {
1575                             sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
1576                         }
1577                     }
1578                     break;
1579                 default:
1580                     break;
1581             }
1582             //  getContainer()->elementReplaced(getContainer()->getElementType(),sName,sNewName);
1583         }
1584         catch( Exception& )
1585         {
1586             DBG_UNHANDLED_EXCEPTION("dbaccess");
1587         }
1588     }
1589 }
1590 
1591 namespace
1592 {
lcl_getToolBarResource(ElementType _eType)1593     OUString lcl_getToolBarResource(ElementType _eType)
1594     {
1595         OUString sToolbar;
1596         switch(_eType)
1597         {
1598             case E_TABLE:
1599                 sToolbar = "private:resource/toolbar/tableobjectbar";
1600                 break;
1601             case E_QUERY:
1602                 sToolbar = "private:resource/toolbar/queryobjectbar";
1603                 break;
1604             case E_FORM:
1605                 sToolbar = "private:resource/toolbar/formobjectbar";
1606                 break;
1607             case E_REPORT:
1608                 sToolbar = "private:resource/toolbar/reportobjectbar";
1609                 break;
1610             case E_NONE:
1611                 break;
1612             default:
1613                 OSL_FAIL("Invalid ElementType!");
1614                 break;
1615         }
1616         return sToolbar;
1617     }
1618 }
1619 
onContainerSelect(ElementType _eType)1620 bool OApplicationController::onContainerSelect(ElementType _eType)
1621 {
1622     OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1623 
1624     if ( m_eCurrentType != _eType && _eType != E_NONE )
1625     {
1626         SelectionGuard aSelGuard( *m_pSelectionNotifier );
1627 
1628         if ( _eType == E_TABLE )
1629         {
1630             try
1631             {
1632                 SharedConnection xConnection( ensureConnection() );
1633                 if ( xConnection.is() && getContainer()->getDetailView() )
1634                 {
1635                     getContainer()->getDetailView()->createTablesPage(xConnection);
1636                     Reference<XTablesSupplier> xTabSup(xConnection,UNO_QUERY);
1637                     if ( xTabSup.is() )
1638                         addContainerListener(xTabSup->getTables());
1639                 }
1640                 else
1641                 {
1642                     return false;
1643                 }
1644             }
1645             catch( const Exception& )
1646             {
1647                 return false;
1648             }
1649         }
1650         else if ( _eType == E_QUERY )
1651         {
1652             // tdf#126578: retrieve connection to be able to call "Create as View"
1653             ensureConnection();
1654         }
1655         Reference< XLayoutManager > xLayoutManager = getLayoutManager( getFrame() );
1656         if ( xLayoutManager.is() )
1657         {
1658             OUString sToolbar = lcl_getToolBarResource(_eType);
1659             OUString sDestroyToolbar = lcl_getToolBarResource(m_eCurrentType);
1660 
1661             xLayoutManager->lock();
1662             xLayoutManager->destroyElement( sDestroyToolbar );
1663             if ( !sToolbar.isEmpty() )
1664             {
1665                 xLayoutManager->createElement( sToolbar );
1666                 xLayoutManager->requestElement( sToolbar );
1667             }
1668             xLayoutManager->unlock();
1669             xLayoutManager->doLayout();
1670         }
1671 
1672         if ( _eType != E_TABLE && getContainer()->getDetailView() )
1673         {
1674             Reference< XNameAccess > xContainer = getElements(_eType);
1675             addContainerListener(xContainer);
1676             getContainer()->getDetailView()->createPage(_eType,xContainer);
1677         }
1678 
1679         SelectionByElementType::const_iterator pendingSelection = m_aPendingSelection.find( _eType );
1680         if ( pendingSelection != m_aPendingSelection.end() )
1681         {
1682             getContainer()->selectElements( comphelper::containerToSequence(pendingSelection->second) );
1683 
1684             m_aPendingSelection.erase( pendingSelection );
1685         }
1686 
1687         InvalidateAll();
1688     }
1689     m_eCurrentType = _eType;
1690 
1691     return true;
1692 }
1693 
onEntryDoubleClick(SvTreeListBox const & _rTree)1694 bool OApplicationController::onEntryDoubleClick( SvTreeListBox const & _rTree )
1695 {
1696     if ( getContainer() && getContainer()->isLeaf( _rTree.GetHdlEntry() ) )
1697     {
1698         try
1699         {
1700             // opens a new frame with either the table or the query or report or form or view
1701             openElementWithArguments(
1702                 getContainer()->getQualifiedName( _rTree.GetHdlEntry() ),
1703                 getContainer()->getElementType(),
1704                 E_OPEN_NORMAL,
1705                 0,
1706                 ::comphelper::NamedValueCollection() );
1707             return true;    // handled
1708         }
1709         catch(const Exception&)
1710         {
1711             DBG_UNHANDLED_EXCEPTION("dbaccess");
1712         }
1713     }
1714     return false;   // not handled
1715 }
1716 
impl_isAlterableView_nothrow(const OUString & _rTableOrViewName) const1717 bool OApplicationController::impl_isAlterableView_nothrow( const OUString& _rTableOrViewName ) const
1718 {
1719     OSL_PRECOND( m_xDataSourceConnection.is(), "OApplicationController::impl_isAlterableView_nothrow: no connection!" );
1720 
1721     bool bIsAlterableView( false );
1722     try
1723     {
1724         Reference< XViewsSupplier > xViewsSupp( m_xDataSourceConnection, UNO_QUERY );
1725         Reference< XNameAccess > xViews;
1726         if ( xViewsSupp.is() )
1727             xViews = xViewsSupp->getViews();
1728 
1729         Reference< XAlterView > xAsAlterableView;
1730         if ( xViews.is() && xViews->hasByName( _rTableOrViewName ) )
1731             xAsAlterableView.set( xViews->getByName( _rTableOrViewName ), UNO_QUERY );
1732 
1733         bIsAlterableView = xAsAlterableView.is();
1734     }
1735     catch( const Exception& )
1736     {
1737         DBG_UNHANDLED_EXCEPTION("dbaccess");
1738     }
1739     return bIsAlterableView;
1740 }
1741 
openElementWithArguments(const OUString & _sName,ElementType _eType,ElementOpenMode _eOpenMode,sal_uInt16 _nInstigatorCommand,const::comphelper::NamedValueCollection & _rAdditionalArguments)1742 Reference< XComponent > OApplicationController::openElementWithArguments( const OUString& _sName, ElementType _eType,
1743     ElementOpenMode _eOpenMode, sal_uInt16 _nInstigatorCommand, const ::comphelper::NamedValueCollection& _rAdditionalArguments )
1744 {
1745     OSL_PRECOND( getContainer(), "OApplicationController::openElementWithArguments: no view!" );
1746     if ( !getContainer() )
1747         return nullptr;
1748 
1749     Reference< XComponent > xRet;
1750     if ( _eOpenMode == E_OPEN_DESIGN )
1751     {
1752         // https://bz.apache.org/ooo/show_bug.cgi?id=30382
1753         getContainer()->showPreview(nullptr);
1754     }
1755 
1756     bool isStandaloneDocument = false;
1757     switch ( _eType )
1758     {
1759     case E_REPORT:
1760         if ( _eOpenMode != E_OPEN_DESIGN )
1761         {
1762             // reports which are opened in a mode other than design are no sub components of our application
1763             // component, but standalone documents.
1764             isStandaloneDocument = true;
1765         }
1766         [[fallthrough]];
1767     case E_FORM:
1768     {
1769         if ( isStandaloneDocument || !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
1770         {
1771             std::unique_ptr< OLinkedDocumentsAccess > aHelper = getDocumentsAccess( _eType );
1772             if ( !aHelper->isConnected() )
1773                 break;
1774 
1775             Reference< XComponent > xDefinition;
1776             xRet = aHelper->open( _sName, xDefinition, _eOpenMode, _rAdditionalArguments );
1777 
1778             if ( !isStandaloneDocument )
1779                 onDocumentOpened( _sName, _eType, _eOpenMode, xRet, xDefinition );
1780         }
1781     }
1782     break;
1783 
1784     case E_QUERY:
1785     case E_TABLE:
1786     {
1787         if ( !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
1788         {
1789             SharedConnection xConnection( ensureConnection() );
1790             if ( !xConnection.is() )
1791                 break;
1792 
1793             std::unique_ptr< DatabaseObjectView > pDesigner;
1794             ::comphelper::NamedValueCollection aArguments( _rAdditionalArguments );
1795 
1796             Any aDataSource;
1797             if ( _eOpenMode == E_OPEN_DESIGN )
1798             {
1799                 bool bAddViewTypeArg = false;
1800 
1801                 if ( _eType == E_TABLE )
1802                 {
1803                     if ( impl_isAlterableView_nothrow( _sName ) )
1804                     {
1805                         pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), true ) );
1806                         bAddViewTypeArg = true;
1807                     }
1808                     else
1809                     {
1810                         pDesigner.reset( new TableDesigner( getORB(), this, m_aCurrentFrame.getFrame() ) );
1811                     }
1812                 }
1813                 else if ( _eType == E_QUERY )
1814                 {
1815                     pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), false ) );
1816                     bAddViewTypeArg = true;
1817                 }
1818                 aDataSource <<= m_xDataSource;
1819 
1820                 if ( bAddViewTypeArg )
1821                 {
1822                     const bool bQueryGraphicalMode =( _nInstigatorCommand != SID_DB_APP_EDIT_SQL_VIEW );
1823                     aArguments.put( OUString(PROPERTY_GRAPHICAL_DESIGN), bQueryGraphicalMode );
1824                 }
1825 
1826             }
1827             else
1828             {
1829                 pDesigner.reset( new ResultSetBrowser( getORB(), this, m_aCurrentFrame.getFrame(), _eType == E_TABLE ) );
1830 
1831                 if ( !aArguments.has( OUString(PROPERTY_SHOWMENU) ) )
1832                     aArguments.put( OUString(PROPERTY_SHOWMENU), makeAny( true ) );
1833 
1834                 aDataSource <<= getDatabaseName();
1835             }
1836 
1837             xRet.set( pDesigner->openExisting( aDataSource, _sName, aArguments ) );
1838             onDocumentOpened( _sName, _eType, _eOpenMode, xRet, nullptr );
1839         }
1840     }
1841     break;
1842 
1843     default:
1844         OSL_FAIL( "OApplicationController::openElement: illegal object type!" );
1845         break;
1846     }
1847     return xRet;
1848 }
1849 
IMPL_LINK(OApplicationController,OnSelectContainer,void *,_pType,void)1850 IMPL_LINK( OApplicationController, OnSelectContainer, void*, _pType, void )
1851 {
1852     ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
1853     if (getContainer())
1854         getContainer()->selectContainer(eType);
1855 }
1856 
IMPL_LINK(OApplicationController,OnCreateWithPilot,void *,_pType,void)1857 IMPL_LINK( OApplicationController, OnCreateWithPilot, void*, _pType, void )
1858 {
1859     ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
1860     newElementWithPilot( eType );
1861 }
1862 
newElementWithPilot(ElementType _eType)1863 void OApplicationController::newElementWithPilot( ElementType _eType )
1864 {
1865     utl::CloseVeto aKeepDoc( getFrame() );
1866         // prevent the document being closed while the wizard is open
1867 
1868     OSL_ENSURE( getContainer(), "OApplicationController::newElementWithPilot: without a view?" );
1869 
1870     switch ( _eType )
1871     {
1872         case E_REPORT:
1873         case E_FORM:
1874         {
1875             std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
1876             if ( aHelper->isConnected() )
1877             {
1878                 sal_Int32 nCommandType = -1;
1879                 const OUString sCurrentSelected( getCurrentlySelectedName( nCommandType ) );
1880                 if ( E_REPORT == _eType )
1881                     aHelper->newReportWithPilot( nCommandType, sCurrentSelected );
1882                 else
1883                     aHelper->newFormWithPilot( nCommandType, sCurrentSelected );
1884             }
1885         }
1886         break;
1887         case E_QUERY:
1888         case E_TABLE:
1889          {
1890             std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
1891             if ( aHelper->isConnected() )
1892             {
1893                 if ( E_QUERY == _eType )
1894                     aHelper->newQueryWithPilot();
1895                 else
1896                     aHelper->newTableWithPilot();
1897             }
1898          }
1899          break;
1900         case E_NONE:
1901             break;
1902     }
1903 
1904     // no need for onDocumentOpened, the table wizard opens the created table by using
1905     // XDatabaseDocumentUI::loadComponent method.
1906 }
1907 
newElement(ElementType _eType,const::comphelper::NamedValueCollection & i_rAdditionalArguments,Reference<XComponent> & o_rDocumentDefinition)1908 Reference< XComponent > OApplicationController::newElement( ElementType _eType, const ::comphelper::NamedValueCollection& i_rAdditionalArguments,
1909                                                            Reference< XComponent >& o_rDocumentDefinition )
1910 {
1911     OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1912 
1913     Reference< XComponent > xComponent;
1914     o_rDocumentDefinition.clear();
1915 
1916     switch ( _eType )
1917     {
1918         case E_FORM:
1919         case E_REPORT:
1920         {
1921             std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess( _eType );
1922             if ( !aHelper->isConnected() )
1923                 break;
1924 
1925             xComponent = aHelper->newDocument( _eType == E_FORM ? ID_FORM_NEW_TEXT : ID_REPORT_NEW_TEXT, i_rAdditionalArguments, o_rDocumentDefinition );
1926         }
1927         break;
1928 
1929         case E_QUERY:
1930         case E_TABLE:
1931         {
1932             std::unique_ptr< DatabaseObjectView > pDesigner;
1933             SharedConnection xConnection( ensureConnection() );
1934             if ( !xConnection.is() )
1935                 break;
1936 
1937             if ( _eType == E_TABLE )
1938             {
1939                 pDesigner.reset( new TableDesigner( getORB(), this, getFrame() ) );
1940             }
1941             else if ( _eType == E_QUERY )
1942             {
1943                 pDesigner.reset( new QueryDesigner( getORB(), this, getFrame(), false ) );
1944             }
1945 
1946             Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1947             xComponent = pDesigner->createNew( xDataSource, i_rAdditionalArguments );
1948         }
1949         break;
1950 
1951         default:
1952             OSL_FAIL( "OApplicationController::newElement: illegal type!" );
1953             break;
1954     }
1955 
1956     if ( xComponent.is() )
1957         onDocumentOpened( OUString(), _eType, E_OPEN_DESIGN, xComponent, o_rDocumentDefinition );
1958 
1959     return xComponent;
1960 }
1961 
addContainerListener(const Reference<XNameAccess> & _xCollection)1962 void OApplicationController::addContainerListener(const Reference<XNameAccess>& _xCollection)
1963 {
1964     try
1965     {
1966         Reference< XContainer > xCont(_xCollection, UNO_QUERY);
1967         if ( xCont.is() )
1968         {
1969             // add as listener to get notified if elements are inserted or removed
1970             TContainerVector::const_iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xCont);
1971             if ( aFind == m_aCurrentContainers.end() )
1972             {
1973                 xCont->addContainerListener(this);
1974                 m_aCurrentContainers.push_back(xCont);
1975             }
1976         }
1977     }
1978     catch( const Exception& )
1979     {
1980         DBG_UNHANDLED_EXCEPTION("dbaccess");
1981     }
1982 }
1983 
renameEntry()1984 void OApplicationController::renameEntry()
1985 {
1986     SolarMutexGuard aSolarGuard;
1987     ::osl::MutexGuard aGuard( getMutex() );
1988 
1989     OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1990     std::vector< OUString> aList;
1991     getSelectionElementNames(aList);
1992 
1993     Reference< XNameAccess > xContainer = getElements(getContainer()->getElementType());
1994     OSL_ENSURE(aList.size() == 1,"Invalid rename call here. More than one element!");
1995     if ( aList.empty() )
1996         return;
1997 
1998     try
1999     {
2000         if ( xContainer.is() )
2001         {
2002             std::unique_ptr< IObjectNameCheck > pNameChecker;
2003             std::unique_ptr<OSaveAsDlg> xDialog;
2004 
2005             Reference<XRename> xRename;
2006             const ElementType eType = getContainer()->getElementType();
2007             switch( eType )
2008             {
2009                 case E_FORM:
2010                 case E_REPORT:
2011                     {
2012                         Reference<XHierarchicalNameContainer> xHNames(xContainer, UNO_QUERY);
2013                         if ( xHNames.is() )
2014                         {
2015                             OUString sLabel;
2016                             if ( eType == E_FORM )
2017                                 sLabel = DBA_RES(STR_FRM_LABEL);
2018                             else
2019                                 sLabel = DBA_RES(STR_RPT_LABEL);
2020 
2021                             OUString sName = *aList.begin();
2022                             if ( xHNames->hasByHierarchicalName(sName) )
2023                             {
2024                                 xRename.set(xHNames->getByHierarchicalName(sName),UNO_QUERY);
2025                                 Reference<XChild> xChild(xRename,UNO_QUERY);
2026                                 if ( xChild.is() )
2027                                 {
2028                                     Reference<XHierarchicalNameContainer> xParent(xChild->getParent(),UNO_QUERY);
2029                                     if ( xParent.is() )
2030                                     {
2031                                         xHNames = xParent;
2032                                         Reference<XPropertySet>(xRename,UNO_QUERY_THROW)->getPropertyValue(PROPERTY_NAME) >>= sName;
2033                                     }
2034                                 }
2035                                 pNameChecker.reset( new HierarchicalNameCheck( xHNames.get(), OUString() ) );
2036                                 xDialog.reset(new OSaveAsDlg(
2037                                     getFrameWeld(), getORB(), sName, sLabel, *pNameChecker, SADFlags::TitleRename));
2038                             }
2039                         }
2040                     }
2041                     break;
2042                 case E_TABLE:
2043                     ensureConnection();
2044                     if ( !getConnection().is() )
2045                         break;
2046                     [[fallthrough]];
2047                 case E_QUERY:
2048                     if ( xContainer->hasByName(*aList.begin()) )
2049                     {
2050                         xRename.set(xContainer->getByName(*aList.begin()),UNO_QUERY);
2051                         sal_Int32 nCommandType = eType == E_QUERY ? CommandType::QUERY : CommandType::TABLE;
2052 
2053                         ensureConnection();
2054                         pNameChecker.reset( new DynamicTableOrQueryNameCheck( getConnection(), nCommandType ) );
2055                         xDialog.reset(new OSaveAsDlg(getFrameWeld(), nCommandType, getORB(), getConnection(),
2056                                 *aList.begin(), *pNameChecker, SADFlags::TitleRename));
2057                     }
2058                     break;
2059                 default:
2060                     break;
2061             }
2062 
2063             if (xRename.is() && xDialog)
2064             {
2065 
2066                 bool bTryAgain = true;
2067                 while( bTryAgain )
2068                 {
2069                     if (xDialog->run() == RET_OK)
2070                     {
2071                         try
2072                         {
2073                             OUString sNewName;
2074                             if ( eType == E_TABLE )
2075                             {
2076                                 OUString sName = xDialog->getName();
2077                                 OUString sCatalog = xDialog->getCatalog();
2078                                 OUString sSchema  = xDialog->getSchema();
2079 
2080                                 sNewName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sName, false, ::dbtools::EComposeRule::InDataManipulation );
2081                             }
2082                             else
2083                                 sNewName = xDialog->getName();
2084 
2085                             OUString sOldName = *aList.begin();
2086                             if ( eType == E_FORM || eType == E_REPORT )
2087                             {
2088                                 Reference<XContent> xContent(xRename,UNO_QUERY);
2089                                 if ( xContent.is() )
2090                                 {
2091                                     sOldName = xContent->getIdentifier()->getContentIdentifier();
2092                                 }
2093                             }
2094 
2095                             xRename->rename(sNewName);
2096 
2097                             if ( eType == E_TABLE )
2098                             {
2099                                 Reference<XPropertySet> xProp(xRename,UNO_QUERY);
2100                                 sNewName = ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
2101                             }
2102                             getContainer()->elementReplaced( eType , sOldName, sNewName );
2103 
2104                             bTryAgain = false;
2105                         }
2106                         catch(const SQLException& )
2107                         {
2108                             showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
2109 
2110                         }
2111                         catch(const ElementExistException& e)
2112                         {
2113                             OUString sMsg(DBA_RES(STR_NAME_ALREADY_EXISTS));
2114                             showError(SQLExceptionInfo(SQLException(sMsg.replaceAll("#", e.Message), e.Context, "S1000", 0, Any())));
2115                         }
2116                         catch(const Exception& )
2117                         {
2118                             DBG_UNHANDLED_EXCEPTION("dbaccess");
2119                         }
2120                     }
2121                     else
2122                         bTryAgain = false;
2123                 }
2124             }
2125         }
2126     }
2127     catch(const Exception& )
2128     {
2129         DBG_UNHANDLED_EXCEPTION("dbaccess");
2130     }
2131 }
2132 
onSelectionChanged()2133 void OApplicationController::onSelectionChanged()
2134 {
2135     InvalidateAll();
2136 
2137     SelectionGuard aSelGuard( *m_pSelectionNotifier );
2138 
2139     OApplicationView* pView = getContainer();
2140     if ( !pView )
2141         return;
2142 
2143     if ( pView->getSelectionCount() == 1 )
2144     {
2145         const ElementType eType = pView->getElementType();
2146         if ( pView->isALeafSelected() )
2147         {
2148             const OUString sName = pView->getQualifiedName( nullptr /* means 'first selected' */ );
2149             showPreviewFor( eType, sName );
2150         }
2151     }
2152 }
2153 
showPreviewFor(const ElementType _eType,const OUString & _sName)2154 void OApplicationController::showPreviewFor(const ElementType _eType,const OUString& _sName)
2155 {
2156     if ( m_ePreviewMode == E_PREVIEWNONE )
2157         return;
2158 
2159     OApplicationView* pView = getContainer();
2160     if ( !pView )
2161         return;
2162 
2163     try
2164     {
2165         switch( _eType )
2166         {
2167             case E_FORM:
2168             case E_REPORT:
2169             {
2170                 Reference< XHierarchicalNameAccess > xContainer( getElements( _eType ), UNO_QUERY_THROW );
2171                 Reference< XContent> xContent( xContainer->getByHierarchicalName( _sName ), UNO_QUERY_THROW );
2172                 pView->showPreview( xContent );
2173             }
2174             break;
2175 
2176             case E_TABLE:
2177             case E_QUERY:
2178                 {
2179                     SharedConnection xConnection( ensureConnection() );
2180                     if ( xConnection.is() )
2181                         pView->showPreview( getDatabaseName(), xConnection, _sName, _eType == E_TABLE );
2182                 }
2183                 return;
2184 
2185             default:
2186                 OSL_FAIL( "OApplicationController::showPreviewFor: unexpected element type!" );
2187                 break;
2188         }
2189     }
2190     catch( const SQLException& )
2191     {
2192         showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
2193     }
2194     catch(const Exception& )
2195     {
2196         DBG_UNHANDLED_EXCEPTION("dbaccess");
2197     }
2198 }
2199 
IMPL_LINK_NOARG(OApplicationController,OnClipboardChanged,TransferableDataHelper *,void)2200 IMPL_LINK_NOARG(OApplicationController, OnClipboardChanged, TransferableDataHelper*, void)
2201 {
2202     OnInvalidateClipboard();
2203 }
2204 
OnInvalidateClipboard()2205 void OApplicationController::OnInvalidateClipboard()
2206 {
2207     InvalidateFeature(ID_BROWSER_CUT);
2208     InvalidateFeature(ID_BROWSER_COPY);
2209     InvalidateFeature(ID_BROWSER_PASTE);
2210     InvalidateFeature(SID_DB_APP_PASTE_SPECIAL);
2211 }
2212 
onCopyEntry()2213 void OApplicationController::onCopyEntry()
2214 {
2215     Execute(ID_BROWSER_COPY,Sequence<PropertyValue>());
2216 }
2217 
onPasteEntry()2218 void OApplicationController::onPasteEntry()
2219 {
2220     Execute(ID_BROWSER_PASTE,Sequence<PropertyValue>());
2221 }
2222 
onDeleteEntry()2223 void OApplicationController::onDeleteEntry()
2224 {
2225     ElementType eType = getContainer()->getElementType();
2226     sal_uInt16 nId = 0;
2227     switch(eType)
2228     {
2229         case E_TABLE:
2230             nId = SID_DB_APP_TABLE_DELETE;
2231             break;
2232         case E_QUERY:
2233             nId = SID_DB_APP_QUERY_DELETE;
2234             break;
2235         case E_FORM:
2236             nId = SID_DB_APP_FORM_DELETE;
2237             break;
2238         case E_REPORT:
2239             nId = SID_DB_APP_REPORT_DELETE;
2240             break;
2241         default:
2242             OSL_FAIL("Invalid ElementType!");
2243             break;
2244     }
2245     executeChecked(nId,Sequence<PropertyValue>());
2246 }
2247 
getContextMenuResourceName(Control &) const2248 OUString OApplicationController::getContextMenuResourceName( Control& /*_rControl*/ ) const
2249 {
2250     return "edit";
2251 }
2252 
getCommandController()2253 IController& OApplicationController::getCommandController()
2254 {
2255     return *this;
2256 }
2257 
getContextMenuInterceptors()2258 ::comphelper::OInterfaceContainerHelper2* OApplicationController::getContextMenuInterceptors()
2259 {
2260     return &m_aContextMenuInterceptors;
2261 }
2262 
getCurrentSelection(Control & _rControl) const2263 Any OApplicationController::getCurrentSelection( Control& _rControl ) const
2264 {
2265     Sequence< NamedDatabaseObject > aSelection;
2266     getContainer()->describeCurrentSelectionForControl( _rControl, aSelection );
2267     return makeAny( aSelection );
2268 }
2269 
requestQuickHelp(const SvTreeListEntry *,OUString &) const2270 bool OApplicationController::requestQuickHelp( const SvTreeListEntry* /*_pEntry*/, OUString& /*_rText*/ ) const
2271 {
2272     return false;
2273 }
2274 
requestDrag(const Point &)2275 bool OApplicationController::requestDrag(  const Point& /*_rPosPixel*/ )
2276 {
2277     rtl::Reference<TransferableHelper> pTransfer;
2278     if ( getContainer() && getContainer()->getSelectionCount() )
2279     {
2280         try
2281         {
2282             pTransfer = copyObject( );
2283 
2284             if ( pTransfer && getContainer()->getDetailView() )
2285             {
2286                 ElementType eType = getContainer()->getElementType();
2287                 pTransfer->StartDrag( getContainer()->getDetailView()->getTreeWindow(), ((eType == E_FORM || eType == E_REPORT) ? DND_ACTION_COPYMOVE : DND_ACTION_COPY) );
2288             }
2289         }
2290         catch(const Exception& )
2291         {
2292             DBG_UNHANDLED_EXCEPTION("dbaccess");
2293         }
2294     }
2295 
2296     return pTransfer.is();
2297 }
2298 
queryDrop(const AcceptDropEvent & _rEvt,const DataFlavorExVector & _rFlavors)2299 sal_Int8 OApplicationController::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
2300 {
2301     sal_Int8 nActionAskedFor = _rEvt.mnAction;
2302     // check if we're a table or query container
2303     OApplicationView* pView = getContainer();
2304     if ( pView && !isDataSourceReadOnly() )
2305     {
2306         ElementType eType = pView->getElementType();
2307         if ( eType != E_NONE && (eType != E_TABLE || !isConnectionReadOnly()) )
2308         {
2309             // check for the concrete type
2310             if(std::any_of(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(eType)))
2311                 return DND_ACTION_COPY;
2312             if ( eType == E_FORM || eType == E_REPORT )
2313             {
2314                 sal_Int8 nAction = OComponentTransferable::canExtractComponentDescriptor(_rFlavors,eType == E_FORM) ? DND_ACTION_COPY : DND_ACTION_NONE;
2315                 if ( nAction != DND_ACTION_NONE )
2316                 {
2317                     SvTreeListEntry* pHitEntry = pView->getEntry(_rEvt.maPosPixel);
2318                     OUString sName;
2319                     if ( pHitEntry )
2320                     {
2321                         sName = pView->getQualifiedName( pHitEntry );
2322                         if ( !sName.isEmpty() )
2323                         {
2324                             Reference< XHierarchicalNameAccess > xContainer(getElements(pView->getElementType()),UNO_QUERY);
2325                             if ( xContainer.is() && xContainer->hasByHierarchicalName(sName) )
2326                             {
2327                                 Reference< XHierarchicalNameAccess > xHitObject(xContainer->getByHierarchicalName(sName),UNO_QUERY);
2328                                 if ( xHitObject.is() )
2329                                     nAction = nActionAskedFor & DND_ACTION_COPYMOVE;
2330                             }
2331                             else
2332                                 nAction = DND_ACTION_NONE;
2333                         }
2334                     }
2335                 }
2336                 return nAction;
2337             }
2338         }
2339     }
2340 
2341     return DND_ACTION_NONE;
2342 }
2343 
executeDrop(const ExecuteDropEvent & _rEvt)2344 sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt )
2345 {
2346     OApplicationView* pView = getContainer();
2347     if ( !pView || pView->getElementType() == E_NONE )
2348     {
2349         OSL_FAIL("OApplicationController::executeDrop: what the hell did queryDrop do?");
2350             // queryDrop should not have allowed us to reach this situation...
2351         return DND_ACTION_NONE;
2352     }
2353 
2354     // a TransferableDataHelper for accessing the dropped data
2355     TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
2356 
2357     // reset the data of the previous async drop (if any)
2358     if ( m_nAsyncDrop )
2359         Application::RemoveUserEvent(m_nAsyncDrop);
2360 
2361     m_nAsyncDrop = nullptr;
2362     m_aAsyncDrop.aDroppedData.clear();
2363     m_aAsyncDrop.nType          = pView->getElementType();
2364     m_aAsyncDrop.nAction        = _rEvt.mnAction;
2365     m_aAsyncDrop.bError         = false;
2366     m_aAsyncDrop.bHtml          = false;
2367     m_aAsyncDrop.aUrl.clear();
2368 
2369     // loop through the available formats and see what we can do...
2370     // first we have to check if it is our own format, if not we have to copy the stream :-(
2371     if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
2372     {
2373         m_aAsyncDrop.aDroppedData   = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
2374 
2375         // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2376         m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2377         return DND_ACTION_COPY;
2378     }
2379     else if ( OComponentTransferable::canExtractComponentDescriptor(aDroppedData.GetDataFlavorExVector(),m_aAsyncDrop.nType == E_FORM) )
2380     {
2381         m_aAsyncDrop.aDroppedData = OComponentTransferable::extractComponentDescriptor(aDroppedData);
2382         SvTreeListEntry* pHitEntry = pView->getEntry(_rEvt.maPosPixel);
2383         if ( pHitEntry )
2384             m_aAsyncDrop.aUrl = pView->getQualifiedName( pHitEntry );
2385 
2386         sal_Int8 nAction = _rEvt.mnAction;
2387         Reference<XContent> xContent;
2388         m_aAsyncDrop.aDroppedData[DataAccessDescriptorProperty::Component] >>= xContent;
2389         if ( xContent.is() )
2390         {
2391             OUString sName = xContent->getIdentifier()->getContentIdentifier();
2392             sName = sName.copy(sName.indexOf('/') + 1);
2393             if ( m_aAsyncDrop.aUrl.getLength() >= sName.getLength() && m_aAsyncDrop.aUrl.startsWith(sName) )
2394             {
2395                 m_aAsyncDrop.aDroppedData.clear();
2396                 return DND_ACTION_NONE;
2397             }
2398 
2399             // check if move is allowed, if another object with the same name exists only copy is allowed
2400             Reference< XHierarchicalNameAccess > xContainer(getElements(m_aAsyncDrop.nType),UNO_QUERY);
2401             Reference<XNameAccess> xNameAccess(xContainer,UNO_QUERY);
2402 
2403             if ( !m_aAsyncDrop.aUrl.isEmpty() && xContainer.is() && xContainer->hasByHierarchicalName(m_aAsyncDrop.aUrl) )
2404                 xNameAccess.set(xContainer->getByHierarchicalName(m_aAsyncDrop.aUrl),UNO_QUERY);
2405 
2406             if ( xNameAccess.is() )
2407             {
2408                 Reference<XPropertySet> xProp(xContent,UNO_QUERY);
2409                 if ( xProp.is() )
2410                 {
2411                     xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
2412                     if ( xNameAccess.is() && xNameAccess->hasByName(sName) )
2413                         nAction &= ~DND_ACTION_MOVE;
2414                 }
2415                 else
2416                     nAction &= ~DND_ACTION_MOVE;
2417             }
2418         }
2419         if ( nAction != DND_ACTION_NONE )
2420         {
2421             m_aAsyncDrop.nAction = nAction;
2422             // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2423             m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2424         }
2425         else
2426             m_aAsyncDrop.aDroppedData.clear();
2427         return nAction;
2428     }
2429     else
2430     {
2431         SharedConnection xConnection( ensureConnection() );
2432         if ( xConnection.is() && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xConnection ) )
2433         {
2434             // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2435             m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2436             return DND_ACTION_COPY;
2437         }
2438     }
2439 
2440     return DND_ACTION_NONE;
2441 }
2442 
getModel()2443 Reference< XModel >  SAL_CALL OApplicationController::getModel()
2444 {
2445     return m_xModel;
2446 }
2447 
onAttachedFrame()2448 void OApplicationController::onAttachedFrame()
2449 {
2450     sal_Int32 nConnectedControllers( 0 );
2451     try
2452     {
2453         Reference< XModel2 > xModel( m_xModel, UNO_QUERY_THROW );
2454         Reference< XEnumeration > xEnumControllers( xModel->getControllers(), UNO_SET_THROW );
2455         while ( xEnumControllers->hasMoreElements() )
2456         {
2457             Reference< XController > xController( xEnumControllers->nextElement(), UNO_QUERY_THROW );
2458             ++nConnectedControllers;
2459         }
2460     }
2461     catch( const Exception& )
2462     {
2463         DBG_UNHANDLED_EXCEPTION("dbaccess");
2464     }
2465 
2466     if ( nConnectedControllers > 1 )
2467     {   // we are not the first connected controller, there were already others
2468         return;
2469     }
2470 
2471     OnFirstControllerConnected();
2472 }
2473 
OnFirstControllerConnected()2474 void OApplicationController::OnFirstControllerConnected()
2475 {
2476     if ( !m_xModel.is() )
2477     {
2478         OSL_FAIL( "OApplicationController::OnFirstControllerConnected: too late!" );
2479     }
2480 
2481     // if we have forms or reports which contain macros/scripts, then show a warning
2482     // which suggests the user to migrate them to the database document
2483     Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
2484     if ( xDocumentScripts.is() )
2485     {
2486         // no need to show this warning, obviously the document supports embedding scripts
2487         // into itself, so there are no "old-style" forms/reports which have macros/scripts
2488         // themselves
2489         return;
2490     }
2491 
2492     try
2493     {
2494         // If the migration just happened, but was not successful, the document is reloaded.
2495         // In this case, we should not show the warning, again.
2496         ::comphelper::NamedValueCollection aModelArgs( m_xModel->getArgs() );
2497         if ( aModelArgs.getOrDefault( "SuppressMigrationWarning", false ) )
2498             return;
2499 
2500         // also, if the document is read-only, then no migration is possible, and the
2501         // respective menu entry is hidden. So, don't show the warning in this case, too.
2502         if ( Reference< XStorable >( m_xModel, UNO_QUERY_THROW )->isReadonly() )
2503             return;
2504 
2505         SQLWarning aWarning;
2506         aWarning.Message = DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS);
2507         SQLException aDetail;
2508         aDetail.Message = DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS_DETAIL);
2509         aWarning.NextException <<= aDetail;
2510 
2511         Reference< XExecutableDialog > xDialog = ErrorMessageDialog::create( getORB(), "", nullptr, makeAny( aWarning ) );
2512         xDialog->execute();
2513     }
2514     catch( const Exception& )
2515     {
2516         DBG_UNHANDLED_EXCEPTION("dbaccess");
2517     }
2518 }
2519 
attachFrame(const Reference<XFrame> & i_rxFrame)2520 void SAL_CALL OApplicationController::attachFrame( const Reference< XFrame > & i_rxFrame )
2521 {
2522     SolarMutexGuard aSolarGuard; // avoid deadlock in XModel calls
2523     ::osl::MutexGuard aGuard( getMutex() );
2524 
2525     OGenericUnoController::attachFrame( i_rxFrame );
2526     if ( getFrame().is() )
2527         onAttachedFrame();
2528 }
2529 
attachModel(const Reference<XModel> & _rxModel)2530 sal_Bool SAL_CALL OApplicationController::attachModel(const Reference< XModel > & _rxModel)
2531 {
2532     ::osl::MutexGuard aGuard( getMutex() );
2533     const Reference< XOfficeDatabaseDocument > xOfficeDoc( _rxModel, UNO_QUERY );
2534     const Reference< XModifiable > xDocModify( _rxModel, UNO_QUERY );
2535     if ( ( !xOfficeDoc.is() || !xDocModify.is() ) && _rxModel.is() )
2536     {
2537         OSL_FAIL( "OApplicationController::attachModel: invalid model!" );
2538         return false;
2539     }
2540 
2541     if ( m_xModel.is() && ( m_xModel != _rxModel ) && ( _rxModel.is() ) )
2542     {
2543         OSL_ENSURE( false, "OApplicationController::attachModel: missing implementation: setting a new model while we have another one!" );
2544         // we'd need to completely update our view here, close sub components, and the like
2545         return false;
2546     }
2547 
2548     const OUString aPropertyNames[] =
2549     {
2550         OUString(PROPERTY_URL), OUString(PROPERTY_USER)
2551     };
2552 
2553     // disconnect from old model
2554     try
2555     {
2556         if ( m_xDataSource.is() )
2557         {
2558             for (const auto & aPropertyName : aPropertyNames)
2559             {
2560                 m_xDataSource->removePropertyChangeListener( aPropertyName, this );
2561             }
2562         }
2563 
2564         Reference< XModifyBroadcaster >  xBroadcaster( m_xModel, UNO_QUERY );
2565         if ( xBroadcaster.is() )
2566             xBroadcaster->removeModifyListener( this );
2567     }
2568     catch( const Exception& )
2569     {
2570         DBG_UNHANDLED_EXCEPTION("dbaccess");
2571     }
2572 
2573     m_xModel = _rxModel;
2574     m_xDataSource.set( xOfficeDoc.is() ? xOfficeDoc->getDataSource() : Reference< XDataSource >(), UNO_QUERY );
2575 
2576     // connect to new model
2577     try
2578     {
2579         if ( m_xDataSource.is() )
2580         {
2581             for (const auto & aPropertyName : aPropertyNames)
2582             {
2583                 m_xDataSource->addPropertyChangeListener( aPropertyName, this );
2584             }
2585         }
2586 
2587         Reference< XModifyBroadcaster >  xBroadcaster( m_xModel, UNO_QUERY_THROW );
2588         xBroadcaster->addModifyListener( this );
2589 
2590     }
2591     catch( const Exception& )
2592     {
2593         DBG_UNHANDLED_EXCEPTION("dbaccess");
2594     }
2595 
2596     // initial preview mode
2597     if ( m_xDataSource.is() )
2598     {
2599         try
2600         {
2601             // to get the 'modified' for the data source
2602             ::comphelper::NamedValueCollection aLayoutInfo( m_xDataSource->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) );
2603             if ( aLayoutInfo.has( OUString(INFO_PREVIEW) ) )
2604             {
2605                 const sal_Int32 nPreviewMode( aLayoutInfo.getOrDefault( INFO_PREVIEW, sal_Int32(0) ) );
2606                 m_ePreviewMode = static_cast< PreviewMode >( nPreviewMode );
2607                 if ( getView() )
2608                     getContainer()->switchPreview( m_ePreviewMode );
2609             }
2610         }
2611         catch( const Exception& )
2612         {
2613             DBG_UNHANDLED_EXCEPTION("dbaccess");
2614         }
2615     }
2616 
2617     return true;
2618 }
2619 
containerFound(const Reference<XContainer> & _xContainer)2620 void OApplicationController::containerFound( const Reference< XContainer >& _xContainer)
2621 {
2622     try
2623     {
2624         if ( _xContainer.is() )
2625         {
2626             m_aCurrentContainers.push_back(_xContainer);
2627             _xContainer->addContainerListener(this);
2628         }
2629     }
2630     catch(const Exception&)
2631     {
2632         DBG_UNHANDLED_EXCEPTION("dbaccess");
2633     }
2634 }
2635 
getCurrentlySelectedName(sal_Int32 & _rnCommandType) const2636 OUString OApplicationController::getCurrentlySelectedName(sal_Int32& _rnCommandType) const
2637 {
2638     _rnCommandType = ( (getContainer()->getElementType() == E_QUERY)
2639                                 ? CommandType::QUERY : ( (getContainer()->getElementType() == E_TABLE) ? CommandType::TABLE : -1 ));
2640 
2641     OUString sName;
2642     if ( _rnCommandType != -1 )
2643     {
2644         try
2645         {
2646             sName = getContainer()->getQualifiedName( nullptr );
2647             OSL_ENSURE( !sName.isEmpty(), "OApplicationController::getCurrentlySelectedName: no name given!" );
2648         }
2649         catch( const Exception& )
2650         {
2651             DBG_UNHANDLED_EXCEPTION("dbaccess");
2652         }
2653     }
2654     return sName;
2655 }
2656 
addSelectionChangeListener(const Reference<view::XSelectionChangeListener> & Listener)2657 void SAL_CALL OApplicationController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
2658 {
2659     m_pSelectionNotifier->addListener( Listener );
2660 }
2661 
removeSelectionChangeListener(const Reference<view::XSelectionChangeListener> & Listener)2662 void SAL_CALL OApplicationController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
2663 {
2664     m_pSelectionNotifier->removeListener( Listener );
2665 }
2666 
select(const Any & _aSelection)2667 sal_Bool SAL_CALL OApplicationController::select( const Any& _aSelection )
2668 {
2669     SolarMutexGuard aSolarGuard;
2670     ::osl::MutexGuard aGuard( getMutex() );
2671     Sequence< OUString> aSelection;
2672     if ( !_aSelection.hasValue() || !getView() )
2673     {
2674         getContainer()->selectElements(aSelection);
2675         return true;
2676     }
2677 
2678     // BEGIN compatibility
2679     Sequence< NamedValue > aCurrentSelection;
2680     if ( (_aSelection >>= aCurrentSelection) && aCurrentSelection.hasElements() )
2681     {
2682         ElementType eType = E_NONE;
2683         const NamedValue* pIter = aCurrentSelection.getConstArray();
2684         const NamedValue* pEnd  = pIter + aCurrentSelection.getLength();
2685         for(;pIter != pEnd;++pIter)
2686         {
2687             if ( pIter->Name == "Type" )
2688             {
2689                 sal_Int32 nType = 0;
2690                 pIter->Value >>= nType;
2691                 if ( nType < DatabaseObject::TABLE || nType > DatabaseObject::REPORT )
2692                     throw IllegalArgumentException();
2693                 eType = static_cast< ElementType >( nType );
2694             }
2695             else if ( pIter->Name == "Selection" )
2696                 pIter->Value >>= aSelection;
2697         }
2698 
2699         m_aSelectContainerEvent.CancelCall();   // just in case the async select request was running
2700         getContainer()->selectContainer(eType);
2701         getContainer()->selectElements(aSelection);
2702         return true;
2703     }
2704     // END compatibility
2705 
2706     Sequence< NamedDatabaseObject > aSelectedObjects;
2707     if ( !( _aSelection >>= aSelectedObjects ) )
2708     {
2709         aSelectedObjects.realloc( 1 );
2710         if ( !( _aSelection >>= aSelectedObjects[0] ) )
2711             throw IllegalArgumentException();
2712     }
2713 
2714     SelectionByElementType aSelectedElements;
2715     ElementType eSelectedCategory = E_NONE;
2716     for (   const NamedDatabaseObject* pObject = aSelectedObjects.getConstArray();
2717             pObject != aSelectedObjects.getConstArray() + aSelectedObjects.getLength();
2718             ++pObject
2719         )
2720     {
2721         switch ( pObject->Type )
2722         {
2723             case DatabaseObject::TABLE:
2724             case DatabaseObjectContainer::SCHEMA:
2725             case DatabaseObjectContainer::CATALOG:
2726                 aSelectedElements[ E_TABLE ].push_back( pObject->Name );
2727                 break;
2728             case DatabaseObject::QUERY:
2729                 aSelectedElements[ E_QUERY ].push_back( pObject->Name );
2730                 break;
2731             case DatabaseObject::FORM:
2732             case DatabaseObjectContainer::FORMS_FOLDER:
2733                 aSelectedElements[ E_FORM ].push_back( pObject->Name );
2734                 break;
2735             case DatabaseObject::REPORT:
2736             case DatabaseObjectContainer::REPORTS_FOLDER:
2737                 aSelectedElements[ E_REPORT ].push_back( pObject->Name );
2738                 break;
2739             case DatabaseObjectContainer::TABLES:
2740             case DatabaseObjectContainer::QUERIES:
2741             case DatabaseObjectContainer::FORMS:
2742             case DatabaseObjectContainer::REPORTS:
2743                 if ( eSelectedCategory != E_NONE )
2744                     throw IllegalArgumentException(
2745                         DBA_RES(RID_STR_NO_DIFF_CAT),
2746                         *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ) );
2747                 eSelectedCategory =
2748                         ( pObject->Type == DatabaseObjectContainer::TABLES )  ? E_TABLE
2749                     :   ( pObject->Type == DatabaseObjectContainer::QUERIES ) ? E_QUERY
2750                     :   ( pObject->Type == DatabaseObjectContainer::FORMS )   ? E_FORM
2751                     :   ( pObject->Type == DatabaseObjectContainer::REPORTS ) ? E_REPORT
2752                     :   E_NONE;
2753                 break;
2754 
2755             default:
2756             case DatabaseObjectContainer::DATA_SOURCE:
2757             {
2758                 OUString sMessage(
2759                         DBA_RES(RID_STR_UNSUPPORTED_OBJECT_TYPE).
2760                     replaceFirst("$type$", OUString::number(pObject->Type)));
2761                 throw IllegalArgumentException(sMessage, *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ));
2762             }
2763         }
2764     }
2765     for (auto const& selectedElement : aSelectedElements)
2766     {
2767         if ( selectedElement.first == m_eCurrentType )
2768         {
2769             getContainer()->selectElements( comphelper::containerToSequence(selectedElement.second) );
2770         }
2771         else
2772         {
2773             m_aPendingSelection[ selectedElement.first ] = selectedElement.second;
2774         }
2775     }
2776 
2777     m_aSelectContainerEvent.CancelCall();   // just in case the async select request was running
2778     getContainer()->selectContainer( eSelectedCategory );
2779 
2780     return true;
2781 }
2782 
getSelection()2783 Any SAL_CALL OApplicationController::getSelection(  )
2784 {
2785     SolarMutexGuard aSolarGuard;
2786     ::osl::MutexGuard aGuard( getMutex() );
2787 
2788     Sequence< NamedDatabaseObject > aCurrentSelection;
2789     const ElementType eType( getContainer()->getElementType() );
2790     if ( eType != E_NONE )
2791     {
2792         getContainer()->describeCurrentSelectionForType( eType, aCurrentSelection );
2793         if ( !aCurrentSelection.hasElements() )
2794         {   // if no objects are selected, add an entry to the sequence which describes the overall category
2795             // which is selected currently
2796             aCurrentSelection.realloc(1);
2797             aCurrentSelection[0].Name = getDatabaseName();
2798             switch ( eType )
2799             {
2800             case E_TABLE:   aCurrentSelection[0].Type = DatabaseObjectContainer::TABLES;   break;
2801             case E_QUERY:   aCurrentSelection[0].Type = DatabaseObjectContainer::QUERIES;  break;
2802             case E_FORM:    aCurrentSelection[0].Type = DatabaseObjectContainer::FORMS;    break;
2803             case E_REPORT:  aCurrentSelection[0].Type = DatabaseObjectContainer::REPORTS;  break;
2804             default:
2805                 OSL_FAIL( "OApplicationController::getSelection: unexpected current element type!" );
2806                 break;
2807             }
2808         }
2809     }
2810     return makeAny( aCurrentSelection );
2811 }
2812 
2813 }   // namespace dbaui
2814 
2815 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2816