calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / dbaccess / source / ui / app / AppController.cxx
blobbb16c0173ff4bd38d434989555e03100fa8985ec
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include "AppController.hxx"
22 #include <core_resource.hxx>
23 #include <dbexchange.hxx>
24 #include <strings.hxx>
25 #include <advancedsettingsdlg.hxx>
26 #include "subcomponentmanager.hxx"
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/frame/XStorable.hpp>
35 #include <com/sun/star/sdb/CommandType.hpp>
36 #include <com/sun/star/sdb/ErrorMessageDialog.hpp>
37 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
38 #include <com/sun/star/sdbc/SQLException.hpp>
39 #include <com/sun/star/sdbc/SQLWarning.hpp>
40 #include <com/sun/star/sdbc/XDataSource.hpp>
41 #include <com/sun/star/sdbcx/XAlterView.hpp>
42 #include <com/sun/star/sdbcx/XAppend.hpp>
43 #include <com/sun/star/sdbcx/XRename.hpp>
44 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
45 #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
46 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
47 #include <com/sun/star/util/XFlushable.hpp>
48 #include <com/sun/star/util/XModifiable.hpp>
49 #include <com/sun/star/util/XModifyBroadcaster.hpp>
50 #include <com/sun/star/util/XURLTransformer.hpp>
51 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
52 #include <com/sun/star/document/XEmbeddedScripts.hpp>
53 #include <com/sun/star/frame/XModel2.hpp>
54 #include <com/sun/star/task/XInteractionHandler.hpp>
55 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
56 #include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
57 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
58 #include <comphelper/diagnose_ex.hxx>
59 #include <tools/urlobj.hxx>
60 #include <osl/diagnose.h>
62 #include <svl/filenotation.hxx>
63 #include <vcl/transfer.hxx>
64 #include <svtools/cliplistener.hxx>
66 #include <comphelper/interfacecontainer3.hxx>
67 #include <comphelper/sequence.hxx>
68 #include <comphelper/uno3.hxx>
69 #include <comphelper/types.hxx>
70 #include <comphelper/interaction.hxx>
72 #include <vcl/svapp.hxx>
73 #include <vcl/weld.hxx>
75 #include <unotools/closeveto.hxx>
76 #include <unotools/pathoptions.hxx>
77 #include <unotools/moduleoptions.hxx>
78 #include <unotools/historyoptions.hxx>
80 #include <sfx2/mailmodelapi.hxx>
81 #include <sfx2/filedlghelper.hxx>
82 #include <sfx2/docfilt.hxx>
83 #include <sfx2/QuerySaveDocument.hxx>
85 #include <cppuhelper/exc_hlp.hxx>
87 #include <connectivity/dbtools.hxx>
88 #include <connectivity/dbexception.hxx>
90 #include <svx/dbaexchange.hxx>
91 #include <svx/dbaobjectex.hxx>
92 #include <svx/svxdlg.hxx>
94 #include <osl/mutex.hxx>
95 #include "AppView.hxx"
96 #include <browserids.hxx>
97 #include <strings.hrc>
98 #include <defaultobjectnamecheck.hxx>
99 #include <databaseobjectview.hxx>
100 #include <dbtreelistbox.hxx>
101 #include "AppDetailView.hxx"
102 #include <linkeddocuments.hxx>
103 #include <UITools.hxx>
104 #include <dsntypes.hxx>
105 #include <dlgsave.hxx>
106 #include <dbaccess_slotid.hrc>
108 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
109 org_openoffice_comp_dbu_OApplicationController_get_implementation(
110 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
112 return cppu::acquire(new ::dbaui::OApplicationController(context));
115 namespace dbaui
117 using namespace ::dbtools;
118 using namespace ::svx;
119 using namespace ::com::sun::star;
120 using namespace ::com::sun::star::uno;
121 using namespace ::com::sun::star::ucb;
122 using namespace ::com::sun::star::view;
123 using namespace ::com::sun::star::util;
124 using namespace ::com::sun::star::beans;
125 using namespace ::com::sun::star::lang;
126 using namespace ::com::sun::star::frame;
127 using namespace ::com::sun::star::container;
128 using namespace ::com::sun::star::sdb;
129 using namespace ::com::sun::star::sdbc;
130 using namespace ::com::sun::star::sdbcx;
131 using namespace ::com::sun::star::datatransfer;
132 using namespace ::com::sun::star::ui::dialogs;
133 using namespace ::com::sun::star::task;
134 using ::com::sun::star::document::XEmbeddedScripts;
135 using ::com::sun::star::document::XDocumentEventBroadcaster;
136 using ::com::sun::star::sdb::application::NamedDatabaseObject;
138 namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
139 namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
141 OUString SAL_CALL OApplicationController::getImplementationName()
143 return SERVICE_SDB_APPLICATIONCONTROLLER;
146 Sequence< OUString> SAL_CALL OApplicationController::getSupportedServiceNames()
148 return { "com.sun.star.sdb.application.DefaultViewController" };
151 namespace {
153 class SelectionGuard;
157 // OApplicationController
158 class SelectionNotifier
160 private:
161 ::comphelper::OInterfaceContainerHelper3<XSelectionChangeListener> m_aSelectionListeners;
162 ::cppu::OWeakObject& m_rContext;
163 sal_Int32 m_nSelectionNestingLevel;
165 public:
166 SelectionNotifier( ::osl::Mutex& _rMutex, ::cppu::OWeakObject& _rContext )
167 :m_aSelectionListeners( _rMutex )
168 ,m_rContext( _rContext )
169 ,m_nSelectionNestingLevel( 0 )
173 SelectionNotifier(const SelectionNotifier&) = delete;
174 const SelectionNotifier& operator=(const SelectionNotifier&) = delete;
176 void addListener( const Reference< XSelectionChangeListener >& Listener )
178 m_aSelectionListeners.addInterface( Listener );
181 void removeListener( const Reference< XSelectionChangeListener >& Listener )
183 m_aSelectionListeners.removeInterface( Listener );
186 void disposing()
188 EventObject aEvent( m_rContext );
189 m_aSelectionListeners.disposeAndClear( aEvent );
192 struct SelectionGuardAccess { friend SelectionGuard; private: SelectionGuardAccess() { } };
194 /** enters a block which modifies the selection of our owner.
196 Can be called multiple times, the only important thing is to call leaveSelection
197 equally often.
199 void enterSelection( SelectionGuardAccess )
201 ++m_nSelectionNestingLevel;
204 /** leaves a block which modifies the selection of our owner
206 Must be paired with enterSelection calls.
208 When the last block is left, i.e. the last leaveSelection call is made on the current stack,
209 then our SelectionChangeListeners are notified
211 void leaveSelection( SelectionGuardAccess )
213 if ( --m_nSelectionNestingLevel == 0 )
215 EventObject aEvent( m_rContext );
216 m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent );
221 namespace {
223 class SelectionGuard
225 public:
226 explicit SelectionGuard( SelectionNotifier& _rNotifier )
227 :m_rNotifier( _rNotifier )
229 m_rNotifier.enterSelection( SelectionNotifier::SelectionGuardAccess() );
232 ~SelectionGuard()
234 m_rNotifier.leaveSelection( SelectionNotifier::SelectionGuardAccess() );
237 SelectionGuard(const SelectionGuard&) = delete;
238 const SelectionGuard& operator=(const SelectionGuard&) = delete;
240 private:
241 SelectionNotifier& m_rNotifier;
246 // OApplicationController
247 OApplicationController::OApplicationController(const Reference< XComponentContext >& _rxORB)
248 :OGenericUnoController( _rxORB )
249 ,m_aContextMenuInterceptors( getMutex() )
250 ,m_pSubComponentManager( new SubComponentManager( *this, getSharedMutex() ) )
251 ,m_aTypeCollection( _rxORB )
252 ,m_aTableCopyHelper(this)
253 ,m_nAsyncDrop(nullptr)
254 ,m_aSelectContainerEvent( LINK( this, OApplicationController, OnSelectContainer ) )
255 ,m_ePreviewMode(PreviewMode::NONE)
256 ,m_eCurrentType(E_NONE)
257 ,m_bNeedToReconnect(false)
258 ,m_bSuspended( false )
259 ,m_pSelectionNotifier( new SelectionNotifier( getMutex(), *this ) )
263 OApplicationController::~OApplicationController()
265 if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
267 OSL_FAIL("Please check who doesn't dispose this component!");
268 // increment ref count to prevent double call of Dtor
269 osl_atomic_increment( &m_refCount );
270 dispose();
272 clearView();
275 IMPLEMENT_FORWARD_XTYPEPROVIDER2(OApplicationController,OGenericUnoController,OApplicationController_Base)
276 IMPLEMENT_FORWARD_XINTERFACE2(OApplicationController,OGenericUnoController,OApplicationController_Base)
277 void OApplicationController::disconnect()
279 if ( m_xDataSourceConnection.is() )
280 stopConnectionListening( m_xDataSourceConnection );
284 // temporary (hopefully!) hack for #i55274#
285 Reference< XFlushable > xFlush( m_xDataSourceConnection, UNO_QUERY );
286 if ( xFlush.is() && m_xMetaData.is() && !m_xMetaData->isReadOnly() )
287 xFlush->flush();
289 catch( const Exception& )
291 DBG_UNHANDLED_EXCEPTION("dbaccess");
294 m_xDataSourceConnection.clear();
295 m_xMetaData.clear();
297 InvalidateAll();
300 void SAL_CALL OApplicationController::disposing()
302 for( const auto& rContainerListener : m_aCurrentContainers )
304 if( rContainerListener.is() )
306 rContainerListener->removeContainerListener( this );
310 m_aCurrentContainers.clear();
311 m_pSubComponentManager->disposing();
312 m_pSelectionNotifier->disposing();
314 if ( getView() )
316 getContainer()->showPreview(nullptr);
317 m_pClipboardNotifier->ClearCallbackLink();
318 m_pClipboardNotifier->RemoveListener( getView() );
319 m_pClipboardNotifier.clear();
322 disconnect();
325 Reference < XFrame > xFrame;
326 attachFrame( xFrame );
328 if ( m_xDataSource.is() )
330 m_xDataSource->removePropertyChangeListener(OUString(), this);
331 m_xDataSource->removePropertyChangeListener(PROPERTY_INFO, this);
332 m_xDataSource->removePropertyChangeListener(PROPERTY_URL, this);
333 m_xDataSource->removePropertyChangeListener(PROPERTY_ISPASSWORDREQUIRED, this);
334 m_xDataSource->removePropertyChangeListener(PROPERTY_LAYOUTINFORMATION, this);
335 m_xDataSource->removePropertyChangeListener(PROPERTY_SUPPRESSVERSIONCL, this);
336 m_xDataSource->removePropertyChangeListener(PROPERTY_TABLEFILTER, this);
337 m_xDataSource->removePropertyChangeListener(PROPERTY_TABLETYPEFILTER, this);
338 m_xDataSource->removePropertyChangeListener(PROPERTY_USER, this);
339 m_xDataSource = nullptr;
342 Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
343 if ( xBroadcaster.is() )
344 xBroadcaster->removeModifyListener(static_cast<XModifyListener*>(this));
346 if ( m_xModel.is() )
348 OUString sUrl = m_xModel->getURL();
349 if ( !sUrl.isEmpty() )
351 if ( ::comphelper::NamedValueCollection::getOrDefault( m_xModel->getArgs(), u"PickListEntry", true ) )
353 OUString aFilter;
354 INetURLObject aURL( m_xModel->getURL() );
355 std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
356 if ( pFilter )
357 aFilter = pFilter->GetFilterName();
359 // add to svtool history options
360 SvtHistoryOptions::AppendItem( EHistoryType::PickList,
361 aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
362 aFilter,
363 getStrippedDatabaseName(),
364 std::nullopt, std::nullopt);
366 // add to recent document list
367 if ( aURL.GetProtocol() == INetProtocol::File )
368 Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
369 pFilter ? pFilter->GetMimeType() : OUString(),
370 pFilter ? pFilter->GetServiceName() : OUString() );
374 m_xModel->disconnectController( this );
376 m_xModel.clear();
379 catch(const Exception&)
381 DBG_UNHANDLED_EXCEPTION("dbaccess");
384 clearView();
385 OGenericUnoController::disposing(); // here the m_refCount must be equal 5
388 bool OApplicationController::Construct(vcl::Window* _pParent)
390 setView( VclPtr<OApplicationView>::Create( _pParent, getORB(), *this, m_ePreviewMode ) );
392 // late construction
393 bool bSuccess = false;
396 getContainer()->Construct();
397 bSuccess = true;
399 catch(const SQLException&)
402 catch(const Exception&)
404 OSL_FAIL("OApplicationController::Construct : the construction of UnoDataBrowserView failed !");
407 if ( !bSuccess )
409 clearView();
410 return false;
413 // now that we have a view we can create the clipboard listener
414 m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() );
415 m_aSystemClipboard.StartClipboardListening( );
417 m_pClipboardNotifier = new TransferableClipboardListener( LINK( this, OApplicationController, OnClipboardChanged ) );
418 m_pClipboardNotifier->AddListener( getView() );
420 OGenericUnoController::Construct( _pParent );
421 getView()->Show();
423 return true;
426 void SAL_CALL OApplicationController::disposing(const EventObject& _rSource)
428 ::osl::MutexGuard aGuard( getMutex() );
429 Reference<XConnection> xCon(_rSource.Source, UNO_QUERY);
430 if ( xCon.is() )
432 OSL_ENSURE( m_xDataSourceConnection == xCon,
433 "OApplicationController::disposing: which connection does this come from?" );
435 if ( getContainer() && getContainer()->getElementType() == E_TABLE )
436 getContainer()->clearPages();
437 if ( m_xDataSourceConnection == xCon )
439 m_xMetaData.clear();
440 m_xDataSourceConnection.clear();
443 else if ( _rSource.Source == m_xModel )
445 m_xModel.clear();
447 else if ( _rSource.Source == m_xDataSource )
449 m_xDataSource = nullptr;
451 else
453 Reference<XContainer> xContainer( _rSource.Source, UNO_QUERY );
454 if ( xContainer.is() )
456 TContainerVector::iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer);
457 if ( aFind != m_aCurrentContainers.end() )
458 m_aCurrentContainers.erase(aFind);
460 OGenericUnoController::disposing( _rSource );
464 sal_Bool SAL_CALL OApplicationController::suspend(sal_Bool bSuspend)
466 // notify the OnPrepareViewClosing event (before locking any mutex)
467 Reference< XDocumentEventBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
468 if ( xBroadcaster.is() )
470 xBroadcaster->notifyDocumentEvent(
471 "OnPrepareViewClosing",
472 this,
473 Any()
477 SolarMutexGuard aSolarGuard;
478 ::osl::MutexGuard aGuard( getMutex() );
480 if ( getView() && getView()->IsInModalMode() )
481 return false;
483 bool bCanSuspend = true;
485 if ( m_bSuspended != bool(bSuspend) )
487 if ( bSuspend && !closeSubComponents() )
488 return false;
490 Reference<XModifiable> xModi(m_xModel,UNO_QUERY);
491 Reference<XStorable> xStor(getModel(),UNO_QUERY);
493 if ( bSuspend
494 && xStor.is()
495 && !xStor->isReadonly()
496 && ( xModi.is()
497 && xModi->isModified()
501 switch (ExecuteQuerySaveDocument(getFrameWeld(), getStrippedDatabaseName()))
503 case RET_YES:
504 Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
505 bCanSuspend = !xModi->isModified();
506 // when we save the document this must be false else some press cancel
507 break;
508 case RET_CANCEL:
509 bCanSuspend = false;
510 break;
511 default:
512 break;
517 if ( bCanSuspend )
518 m_bSuspended = bSuspend;
520 return bCanSuspend;
523 FeatureState OApplicationController::GetState(sal_uInt16 _nId) const
525 FeatureState aReturn;
526 aReturn.bEnabled = false;
527 // check this first
528 if ( !getContainer() || m_bReadOnly )
529 return aReturn;
533 switch (_nId)
535 case SID_NEWDOCDIRECT:
536 aReturn.bEnabled = true;
537 aReturn.sTitle = "private:factory/sdatabase";
538 break;
539 case SID_OPENURL:
540 aReturn.bEnabled = true;
541 if ( m_xModel.is() )
542 aReturn.sTitle = m_xModel->getURL();
543 break;
544 case ID_BROWSER_COPY:
546 sal_Int32 nCount = getContainer()->getSelectionCount();
547 aReturn.bEnabled = nCount >= 1;
548 if ( aReturn.bEnabled && nCount == 1 && getContainer()->getElementType() == E_TABLE )
549 aReturn.bEnabled = getContainer()->isALeafSelected();
551 break;
552 case ID_BROWSER_CUT:
553 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() >= 1;
554 aReturn.bEnabled = aReturn.bEnabled && (getContainer()->getElementType() != E_TABLE || getContainer()->isCutAllowed());
555 break;
556 case ID_BROWSER_PASTE:
557 switch( getContainer()->getElementType() )
559 case E_TABLE:
560 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
561 break;
562 case E_QUERY:
563 aReturn.bEnabled = !isDataSourceReadOnly() && getViewClipboard().HasFormat(SotClipboardFormatId::DBACCESS_QUERY);
564 break;
565 default:
566 aReturn.bEnabled = !isDataSourceReadOnly() && OComponentTransferable::canExtractComponentDescriptor(getViewClipboard().GetDataFlavorExVector(),getContainer()->getElementType() == E_FORM);
568 break;
569 case SID_DB_APP_PASTE_SPECIAL:
570 aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
571 break;
572 case SID_OPENDOC:
573 aReturn.bEnabled = true;
574 break;
575 case ID_BROWSER_SAVEDOC:
576 aReturn.bEnabled = !isDataSourceReadOnly();
577 break;
578 case ID_BROWSER_SAVEASDOC:
579 aReturn.bEnabled = true;
580 break;
581 case ID_BROWSER_SORTUP:
582 aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
583 aReturn.bChecked = aReturn.bEnabled && getContainer()->isSortUp();
584 break;
585 case ID_BROWSER_SORTDOWN:
586 aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
587 aReturn.bChecked = aReturn.bEnabled && !getContainer()->isSortUp();
588 break;
590 case SID_NEWDOC:
591 case SID_APP_NEW_FORM:
592 case ID_DOCUMENT_CREATE_REPWIZ:
593 aReturn.bEnabled = !isDataSourceReadOnly() && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER);
594 break;
595 case SID_APP_NEW_REPORT:
596 aReturn.bEnabled = !isDataSourceReadOnly()
597 && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER);
598 if ( aReturn.bEnabled )
600 Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
601 aReturn.bEnabled = xEnumAccess.is();
602 if ( aReturn.bEnabled )
604 const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext);
605 aReturn.bEnabled = !sReportEngineServiceName.isEmpty();
606 if ( aReturn.bEnabled )
608 const Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
609 aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
613 break;
614 case SID_DB_APP_VIEW_TABLES:
615 aReturn.bEnabled = true;
616 aReturn.bChecked = getContainer()->getElementType() == E_TABLE;
617 break;
618 case SID_DB_APP_VIEW_QUERIES:
619 aReturn.bEnabled = true;
620 aReturn.bChecked = getContainer()->getElementType() == E_QUERY;
621 break;
622 case SID_DB_APP_VIEW_FORMS:
623 aReturn.bEnabled = true;
624 aReturn.bChecked = getContainer()->getElementType() == E_FORM;
625 break;
626 case SID_DB_APP_VIEW_REPORTS:
627 aReturn.bEnabled = true;
628 aReturn.bChecked = getContainer()->getElementType() == E_REPORT;
629 break;
630 case ID_NEW_QUERY_DESIGN:
631 case ID_NEW_QUERY_SQL:
632 case ID_APP_NEW_QUERY_AUTO_PILOT:
633 case SID_DB_FORM_NEW_PILOT:
634 aReturn.bEnabled = !isDataSourceReadOnly();
635 break;
636 case ID_NEW_VIEW_DESIGN:
637 case SID_DB_NEW_VIEW_SQL:
638 case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
639 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
640 if ( aReturn.bEnabled )
642 Reference<XViewsSupplier> xViewsSup( getConnection(), UNO_QUERY );
643 aReturn.bEnabled = xViewsSup.is();
645 break;
646 case ID_NEW_TABLE_DESIGN:
647 case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
648 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
649 break;
650 case ID_DIRECT_SQL:
651 aReturn.bEnabled = true;
652 break;
653 case SID_APP_NEW_FOLDER:
654 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() <= 1;
655 if ( aReturn.bEnabled )
657 const ElementType eType = getContainer()->getElementType();
658 aReturn.bEnabled = eType == E_REPORT || eType == E_FORM;
660 break;
661 case SID_FORM_CREATE_REPWIZ_PRE_SEL:
662 case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
663 case SID_APP_NEW_REPORT_PRE_SEL:
664 aReturn.bEnabled = !isDataSourceReadOnly()
665 && SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::WRITER)
666 && getContainer()->isALeafSelected();
667 if ( aReturn.bEnabled )
669 ElementType eType = getContainer()->getElementType();
670 aReturn.bEnabled = eType == E_QUERY || eType == E_TABLE;
671 if ( aReturn.bEnabled && SID_APP_NEW_REPORT_PRE_SEL == _nId )
673 Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
674 aReturn.bEnabled = xEnumAccess.is();
675 if ( aReturn.bEnabled )
677 static constexpr OUStringLiteral s_sReportDesign = u"org.libreoffice.report.pentaho.SOReportJobFactory";
678 Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(s_sReportDesign);
679 aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
683 break;
684 case SID_DB_APP_DELETE:
685 case SID_DB_APP_RENAME:
686 aReturn.bEnabled = isRenameDeleteAllowed(getContainer()->getElementType(), _nId == SID_DB_APP_DELETE);
687 break;
688 case SID_DB_APP_TABLE_DELETE:
689 case SID_DB_APP_TABLE_RENAME:
690 aReturn.bEnabled = isRenameDeleteAllowed(E_TABLE, _nId == SID_DB_APP_TABLE_DELETE);
691 break;
692 case SID_DB_APP_QUERY_DELETE:
693 case SID_DB_APP_QUERY_RENAME:
694 aReturn.bEnabled = isRenameDeleteAllowed(E_QUERY, _nId == SID_DB_APP_QUERY_DELETE);
695 break;
696 case SID_DB_APP_FORM_DELETE:
697 case SID_DB_APP_FORM_RENAME:
698 aReturn.bEnabled = isRenameDeleteAllowed(E_FORM, _nId == SID_DB_APP_FORM_DELETE);
699 break;
700 case SID_DB_APP_REPORT_DELETE:
701 case SID_DB_APP_REPORT_RENAME:
702 aReturn.bEnabled = isRenameDeleteAllowed(E_REPORT, _nId == SID_DB_APP_REPORT_DELETE);
703 break;
705 case SID_SELECTALL:
706 aReturn.bEnabled = getContainer()->getElementCount() > 0 && getContainer()->getSelectionCount() != getContainer()->getElementCount();
707 break;
708 case SID_DB_APP_EDIT:
709 case SID_DB_APP_TABLE_EDIT:
710 case SID_DB_APP_QUERY_EDIT:
711 case SID_DB_APP_FORM_EDIT:
712 case SID_DB_APP_REPORT_EDIT:
713 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() > 0
714 && getContainer()->isALeafSelected();
715 break;
716 case SID_DB_APP_EDIT_SQL_VIEW:
717 if ( isDataSourceReadOnly() )
718 aReturn.bEnabled = false;
719 else
721 switch ( getContainer()->getElementType() )
723 case E_QUERY:
724 aReturn.bEnabled = ( getContainer()->getSelectionCount() > 0 )
725 && ( getContainer()->isALeafSelected() );
726 break;
727 case E_TABLE:
728 aReturn.bEnabled = false;
729 // there's one exception: views which support altering their underlying
730 // command can be edited in SQL view, too
731 if ( ( getContainer()->getSelectionCount() > 0 )
732 && ( getContainer()->isALeafSelected() )
735 std::vector< OUString > aSelected;
736 getSelectionElementNames( aSelected );
737 bool bAlterableViews = true;
738 for (auto const& selectedName : aSelected)
740 bAlterableViews &= impl_isAlterableView_nothrow(selectedName);
741 if (!bAlterableViews)
742 break;
744 aReturn.bEnabled = bAlterableViews;
746 break;
747 default:
748 break;
751 break;
752 case SID_DB_APP_OPEN:
753 case SID_DB_APP_TABLE_OPEN:
754 case SID_DB_APP_QUERY_OPEN:
755 case SID_DB_APP_FORM_OPEN:
756 case SID_DB_APP_REPORT_OPEN:
757 aReturn.bEnabled = getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
758 break;
759 case SID_DB_APP_DSUSERADMIN:
760 aReturn.bEnabled = !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
761 break;
762 case SID_DB_APP_DSRELDESIGN:
763 aReturn.bEnabled = true;
764 break;
765 case SID_DB_APP_TABLEFILTER:
766 aReturn.bEnabled = !isDataSourceReadOnly();
767 break;
768 case SID_DB_APP_REFRESH_TABLES:
769 aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && isConnected();
770 break;
771 case SID_DB_APP_DSPROPS:
772 aReturn.bEnabled = m_xDataSource.is() && dbaccess::ODsnTypeCollection::isShowPropertiesEnabled(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
773 break;
774 case SID_DB_APP_DSCONNECTION_TYPE:
775 aReturn.bEnabled = !isDataSourceReadOnly() && m_xDataSource.is() && !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
776 break;
777 case SID_DB_APP_DSADVANCED_SETTINGS:
778 aReturn.bEnabled = m_xDataSource.is() && AdvancedSettingsDialog::doesHaveAnyAdvancedSettings( m_aTypeCollection.getType(::comphelper::getString( m_xDataSource->getPropertyValue( PROPERTY_URL ) )) );
779 break;
780 case SID_DB_APP_CONVERTTOVIEW:
781 aReturn.bEnabled = !isDataSourceReadOnly();
782 if ( aReturn.bEnabled )
784 ElementType eType = getContainer()->getElementType();
785 aReturn.bEnabled = eType == E_QUERY && getContainer()->getSelectionCount() > 0;
786 if ( aReturn.bEnabled )
788 Reference<XViewsSupplier> xViewSup( getConnection(), UNO_QUERY );
789 aReturn.bEnabled = xViewSup.is() && Reference<XAppend>(xViewSup->getViews(),UNO_QUERY).is();
792 break;
793 case SID_DB_APP_DISABLE_PREVIEW:
794 aReturn.bEnabled = true;
795 aReturn.bChecked = getContainer()->getPreviewMode() == PreviewMode::NONE;
796 break;
797 case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
799 ElementType eType = getContainer()->getElementType();
800 aReturn.bEnabled = (E_REPORT == eType || E_FORM == eType);
801 aReturn.bChecked = getContainer()->getPreviewMode() == PreviewMode::DocumentInfo;
803 break;
804 case SID_DB_APP_VIEW_DOC_PREVIEW:
805 aReturn.bEnabled = true;
806 aReturn.bChecked = getContainer()->getPreviewMode() == PreviewMode::Document;
807 break;
808 case ID_BROWSER_UNDO:
809 aReturn.bEnabled = false;
810 break;
811 case SID_MAIL_SENDDOC:
812 aReturn.bEnabled = true;
813 break;
814 case SID_DB_APP_SENDREPORTASMAIL:
816 ElementType eType = getContainer()->getElementType();
817 aReturn.bEnabled = E_REPORT == eType && getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
819 break;
820 case SID_DB_APP_SENDREPORTTOWRITER:
821 case SID_DB_APP_DBADMIN:
822 aReturn.bEnabled = false;
823 break;
824 case SID_DB_APP_STATUS_TYPE:
825 aReturn.bEnabled = m_xDataSource.is();
826 if ( aReturn.bEnabled )
828 OUString sURL;
829 m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
830 OUString sDSTypeName;
831 if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase( sURL ) )
833 sDSTypeName = DBA_RES(RID_STR_EMBEDDED_DATABASE);
835 else
837 sDSTypeName = m_aTypeCollection.getTypeDisplayName(sURL);
839 aReturn.sTitle = sDSTypeName;
841 break;
842 case SID_DB_APP_STATUS_DBNAME:
843 aReturn.bEnabled = m_xDataSource.is();
844 if ( aReturn.bEnabled )
846 OUString sURL;
847 m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
848 OUString sDatabaseName;
849 OUString sHostName;
850 sal_Int32 nPortNumber( -1 );
852 m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
854 if ( sDatabaseName.isEmpty() )
855 sDatabaseName = m_aTypeCollection.cutPrefix( sURL );
856 if ( m_aTypeCollection.isFileSystemBased(sURL) )
858 sDatabaseName = SvtPathOptions().SubstituteVariable( sDatabaseName );
859 if ( !sDatabaseName.isEmpty() )
861 ::svt::OFileNotation aFileNotation(sDatabaseName);
862 // set this decoded URL as text
863 sDatabaseName = aFileNotation.get(::svt::OFileNotation::N_SYSTEM);
867 if ( sDatabaseName.isEmpty() )
868 sDatabaseName = m_aTypeCollection.getTypeDisplayName( sURL );
870 aReturn.sTitle = sDatabaseName;
872 break;
873 case SID_DB_APP_STATUS_USERNAME:
874 aReturn.bEnabled = m_xDataSource.is();
875 if ( aReturn.bEnabled )
876 m_xDataSource->getPropertyValue( PROPERTY_USER ) >>= aReturn.sTitle;
877 break;
878 case SID_DB_APP_STATUS_HOSTNAME:
879 aReturn.bEnabled = m_xDataSource.is();
880 if ( aReturn.bEnabled )
882 OUString sURL;
883 m_xDataSource->getPropertyValue( PROPERTY_URL ) >>= sURL;
885 OUString sHostName, sDatabaseName;
886 sal_Int32 nPortNumber = -1;
887 m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
888 aReturn.sTitle = sHostName;
890 break;
891 default:
892 aReturn = OGenericUnoController::GetState(_nId);
895 catch(const Exception& )
897 DBG_UNHANDLED_EXCEPTION("dbaccess");
899 return aReturn;
902 namespace
904 bool lcl_handleException_nothrow( const Reference< XModel >& _rxDocument, const Any& _rException )
906 bool bHandled = false;
908 // try handling the error with an interaction handler
909 Reference< XInteractionHandler > xHandler = ::comphelper::NamedValueCollection::getOrDefault( _rxDocument->getArgs(), u"InteractionHandler", Reference< XInteractionHandler >() );
910 if ( xHandler.is() )
912 rtl::Reference pRequest( new ::comphelper::OInteractionRequest( _rException ) );
913 rtl::Reference pApprove( new ::comphelper::OInteractionApprove );
914 pRequest->addContinuation( pApprove );
918 xHandler->handle( pRequest );
920 catch( const Exception& )
922 DBG_UNHANDLED_EXCEPTION("dbaccess");
925 bHandled = pApprove->wasSelected();
927 return bHandled;
931 void OApplicationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
933 SolarMutexGuard aSolarGuard;
934 ::osl::MutexGuard aGuard( getMutex() );
936 if ( isUserDefinedFeature( _nId ) )
938 OGenericUnoController::Execute( _nId, aArgs );
939 return;
942 if ( !getContainer() || m_bReadOnly )
943 return; // return without execution
947 switch(_nId)
949 case ID_BROWSER_CUT:
950 getContainer()->cut();
951 break;
952 case ID_BROWSER_COPY:
954 rtl::Reference<TransferableHelper> pTransfer = copyObject();
955 if ( pTransfer )
956 pTransfer->CopyToClipboard(getView());
958 break;
959 case ID_BROWSER_PASTE:
961 const TransferableDataHelper& rTransferData( getViewClipboard() );
962 ElementType eType = getContainer()->getElementType();
964 switch( eType )
966 case E_TABLE:
968 // get the selected tablename
969 std::vector< OUString > aList;
970 getSelectionElementNames( aList );
971 if ( !aList.empty() )
972 m_aTableCopyHelper.SetTableNameForAppend( *aList.begin() );
973 else
974 m_aTableCopyHelper.ResetTableNameForAppend();
976 m_aTableCopyHelper.pasteTable( rTransferData , getDatabaseName(), ensureConnection() );
978 break;
980 case E_QUERY:
981 if ( rTransferData.HasFormat(SotClipboardFormatId::DBACCESS_QUERY) )
982 paste( E_QUERY, ODataAccessObjectTransferable::extractObjectDescriptor( rTransferData ) );
983 break;
984 default:
986 std::vector< OUString> aList;
987 getSelectionElementNames(aList);
988 OUString sFolderNameToInsertInto;
989 if ( !aList.empty() )
991 Reference< XHierarchicalNameAccess > xContainer(getElements(eType),UNO_QUERY);
992 if ( xContainer.is()
993 && xContainer->hasByHierarchicalName(*aList.begin())
994 && (xContainer->getByHierarchicalName(*aList.begin()) >>= xContainer)
995 && xContainer.is()
997 sFolderNameToInsertInto = *aList.begin();
999 paste( eType, OComponentTransferable::extractComponentDescriptor( rTransferData ),
1000 sFolderNameToInsertInto );
1002 break;
1005 break;
1006 case SID_DB_APP_PASTE_SPECIAL:
1008 if ( !aArgs.hasElements() )
1010 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1011 ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(getFrameWeld()));
1012 std::vector<SotClipboardFormatId> aFormatIds;
1013 getSupportedFormats(getContainer()->getElementType(),aFormatIds);
1014 for (auto const& formatId : aFormatIds)
1015 pDlg->Insert(formatId,"");
1017 const TransferableDataHelper& rClipboard = getViewClipboard();
1018 pasteFormat(pDlg->GetFormat(rClipboard.GetTransferable()));
1020 else
1022 const PropertyValue* pIter = aArgs.getConstArray();
1023 const PropertyValue* pEnd = pIter + aArgs.getLength();
1024 for( ; pIter != pEnd ; ++pIter)
1026 if ( pIter->Name == "FormatStringId" )
1028 sal_uLong nTmp;
1029 if ( pIter->Value >>= nTmp )
1030 pasteFormat(static_cast<SotClipboardFormatId>(nTmp));
1031 break;
1036 break;
1037 case SID_NEWDOCDIRECT:
1038 case SID_OPENDOC:
1040 Reference < XDispatchProvider > xProv( getFrame(), UNO_QUERY );
1041 if ( xProv.is() )
1043 URL aURL;
1044 OUString aTarget;
1045 if ( _nId == SID_NEWDOCDIRECT )
1047 aURL.Complete = "private:factory/sdatabase?Interactive";
1048 aTarget = "_default";
1050 else
1051 aURL.Complete = ".uno:Open";
1053 if ( m_xUrlTransformer.is() )
1054 m_xUrlTransformer->parseStrict( aURL );
1055 Reference < XDispatch > xDisp = xProv->queryDispatch( aURL, aTarget, 0 );
1056 if ( xDisp.is() )
1057 xDisp->dispatch( aURL, Sequence < PropertyValue >() );
1060 break;
1061 case ID_BROWSER_SAVEDOC:
1063 Reference< XStorable > xStore( m_xModel, UNO_QUERY_THROW );
1066 xStore->store();
1068 catch( const Exception& )
1070 lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
1073 break;
1075 case ID_BROWSER_SAVEASDOC:
1077 OUString sUrl;
1078 if ( m_xModel.is() )
1079 sUrl = m_xModel->getURL();
1081 ::sfx2::FileDialogHelper aFileDlg(
1082 ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
1083 FileDialogFlags::NONE, getFrameWeld());
1084 aFileDlg.SetContext(sfx2::FileDialogHelper::BaseSaveAs);
1085 if (!sUrl.isEmpty())
1086 aFileDlg.SetDisplayDirectory( sUrl );
1088 std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
1089 if ( pFilter )
1091 aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension());
1092 aFileDlg.SetCurrentFilter(pFilter->GetUIName());
1095 if ( aFileDlg.Execute() != ERRCODE_NONE )
1096 break;
1098 Reference<XStorable> xStore( m_xModel, UNO_QUERY_THROW );
1099 INetURLObject aURL( aFileDlg.GetPath() );
1102 xStore->storeAsURL( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Sequence< PropertyValue >() );
1104 catch( const Exception& )
1106 lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
1109 /*updateTitle();*/
1110 m_bCurrentlyModified = false;
1111 InvalidateFeature(ID_BROWSER_SAVEDOC);
1112 if ( getContainer()->getElementType() == E_NONE )
1114 getContainer()->selectContainer(E_NONE);
1115 getContainer()->selectContainer(E_TABLE);
1116 // #i95524#
1117 getContainer()->Invalidate();
1118 refreshTables();
1122 break;
1123 case ID_BROWSER_SORTUP:
1124 getContainer()->sortUp();
1125 InvalidateFeature(ID_BROWSER_SORTDOWN);
1126 break;
1127 case ID_BROWSER_SORTDOWN:
1128 getContainer()->sortDown();
1129 InvalidateFeature(ID_BROWSER_SORTUP);
1130 break;
1132 case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
1133 case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
1134 case ID_APP_NEW_QUERY_AUTO_PILOT:
1135 case SID_DB_FORM_NEW_PILOT:
1136 case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
1137 case SID_APP_NEW_REPORT_PRE_SEL:
1138 case SID_FORM_CREATE_REPWIZ_PRE_SEL:
1139 case ID_DOCUMENT_CREATE_REPWIZ:
1140 case SID_APP_NEW_FORM:
1141 case SID_APP_NEW_REPORT:
1142 case ID_NEW_QUERY_SQL:
1143 case ID_NEW_QUERY_DESIGN:
1144 case ID_NEW_TABLE_DESIGN:
1146 ElementType eType = E_TABLE;
1147 bool bAutoPilot = false;
1148 ::comphelper::NamedValueCollection aCreationArgs;
1150 switch( _nId )
1152 case SID_DB_FORM_NEW_PILOT:
1153 case SID_FORM_CREATE_REPWIZ_PRE_SEL:
1154 bAutoPilot = true;
1155 [[fallthrough]];
1156 case SID_APP_NEW_FORM:
1157 eType = E_FORM;
1158 break;
1159 case ID_DOCUMENT_CREATE_REPWIZ:
1160 case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
1161 bAutoPilot = true;
1162 [[fallthrough]];
1163 case SID_APP_NEW_REPORT:
1164 case SID_APP_NEW_REPORT_PRE_SEL:
1165 eType = E_REPORT;
1166 break;
1167 case ID_APP_NEW_QUERY_AUTO_PILOT:
1168 bAutoPilot = true;
1169 eType = E_QUERY;
1170 break;
1171 case ID_NEW_QUERY_DESIGN:
1172 aCreationArgs.put( PROPERTY_GRAPHICAL_DESIGN, true );
1173 [[fallthrough]];
1174 case ID_NEW_QUERY_SQL:
1175 eType = E_QUERY;
1176 break;
1177 case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
1178 bAutoPilot = true;
1179 [[fallthrough]];
1180 case ID_NEW_TABLE_DESIGN:
1181 break;
1182 default:
1183 OSL_FAIL("illegal switch call!");
1185 if ( bAutoPilot )
1186 getContainer()->PostUserEvent( LINK( this, OApplicationController, OnCreateWithPilot ), reinterpret_cast< void* >( eType ) );
1187 else
1189 Reference< XComponent > xDocDefinition;
1190 newElement( eType, aCreationArgs, xDocDefinition );
1193 break;
1194 case SID_APP_NEW_FOLDER:
1196 ElementType eType = getContainer()->getElementType();
1197 OUString sName = getContainer()->getQualifiedName( nullptr );
1198 insertHierarchyElement(eType,sName);
1200 break;
1201 case ID_NEW_VIEW_DESIGN:
1202 case SID_DB_NEW_VIEW_SQL:
1204 SharedConnection xConnection( ensureConnection() );
1205 if ( xConnection.is() )
1207 QueryDesigner aDesigner( getORB(), this, getFrame(), true );
1209 ::comphelper::NamedValueCollection aCreationArgs;
1210 aCreationArgs.put( PROPERTY_GRAPHICAL_DESIGN, ID_NEW_VIEW_DESIGN == _nId );
1212 const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1213 const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource, aCreationArgs );
1214 onDocumentOpened( OUString(), E_QUERY, ElementOpenMode::Design, xComponent, nullptr );
1217 break;
1218 case SID_DB_APP_DELETE:
1219 case SID_DB_APP_TABLE_DELETE:
1220 case SID_DB_APP_QUERY_DELETE:
1221 case SID_DB_APP_FORM_DELETE:
1222 case SID_DB_APP_REPORT_DELETE:
1223 deleteEntries();
1224 break;
1225 case SID_DB_APP_RENAME:
1226 case SID_DB_APP_TABLE_RENAME:
1227 case SID_DB_APP_QUERY_RENAME:
1228 case SID_DB_APP_FORM_RENAME:
1229 case SID_DB_APP_REPORT_RENAME:
1230 renameEntry();
1231 break;
1232 case SID_DB_APP_EDIT:
1233 case SID_DB_APP_EDIT_SQL_VIEW:
1234 case SID_DB_APP_TABLE_EDIT:
1235 case SID_DB_APP_QUERY_EDIT:
1236 case SID_DB_APP_FORM_EDIT:
1237 case SID_DB_APP_REPORT_EDIT:
1238 doAction( _nId, ElementOpenMode::Design );
1239 break;
1240 case SID_DB_APP_OPEN:
1241 case SID_DB_APP_TABLE_OPEN:
1242 case SID_DB_APP_QUERY_OPEN:
1243 case SID_DB_APP_FORM_OPEN:
1244 case SID_DB_APP_REPORT_OPEN:
1245 doAction( _nId, ElementOpenMode::Normal );
1246 break;
1247 case SID_DB_APP_CONVERTTOVIEW:
1248 doAction( _nId, ElementOpenMode::Normal );
1249 break;
1250 case SID_SELECTALL:
1251 getContainer()->selectAll();
1252 InvalidateAll();
1253 break;
1254 case SID_DB_APP_DSRELDESIGN:
1256 Reference< XComponent > xRelationDesigner;
1257 if ( !m_pSubComponentManager->activateSubFrame( OUString(), SID_DB_APP_DSRELDESIGN, ElementOpenMode::Design, xRelationDesigner ) )
1259 SharedConnection xConnection( ensureConnection() );
1260 if ( xConnection.is() )
1262 RelationDesigner aDesigner( getORB(), this, m_aCurrentFrame.getFrame() );
1264 const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1265 const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource );
1266 onDocumentOpened( OUString(), SID_DB_APP_DSRELDESIGN, ElementOpenMode::Design, xComponent, nullptr );
1270 break;
1271 case SID_DB_APP_DSUSERADMIN:
1273 SharedConnection xConnection( ensureConnection() );
1274 if ( xConnection.is() )
1275 openDialog("com.sun.star.sdb.UserAdministrationDialog");
1277 break;
1278 case SID_DB_APP_TABLEFILTER:
1279 // opens the table filter dialog for the selected data source
1280 openDialog( "com.sun.star.sdb.TableFilterDialog" );
1281 askToReconnect();
1282 break;
1283 case SID_DB_APP_REFRESH_TABLES:
1284 refreshTables();
1285 break;
1286 case SID_DB_APP_DSPROPS:
1287 // opens the administration dialog for the selected data source
1288 openDialog( "com.sun.star.sdb.DatasourceAdministrationDialog" );
1289 askToReconnect();
1290 break;
1291 case SID_DB_APP_DSADVANCED_SETTINGS:
1292 openDialog("com.sun.star.sdb.AdvancedDatabaseSettingsDialog");
1293 askToReconnect();
1294 break;
1295 case SID_DB_APP_DSCONNECTION_TYPE:
1296 openDialog("com.sun.star.sdb.DataSourceTypeChangeDialog");
1297 askToReconnect();
1298 break;
1299 case ID_DIRECT_SQL:
1301 SharedConnection xConnection( ensureConnection() );
1302 if ( xConnection.is() )
1303 // opens the DirectSQLDialog to execute hand made sql statements.
1304 openDialog( SERVICE_SDB_DIRECTSQLDIALOG );
1306 break;
1307 case SID_DB_APP_VIEW_TABLES:
1308 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_TABLE ) );
1309 break;
1310 case SID_DB_APP_VIEW_QUERIES:
1311 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_QUERY ) );
1312 break;
1313 case SID_DB_APP_VIEW_FORMS:
1314 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_FORM ) );
1315 break;
1316 case SID_DB_APP_VIEW_REPORTS:
1317 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_REPORT ) );
1318 break;
1319 case SID_DB_APP_DISABLE_PREVIEW:
1320 m_ePreviewMode = PreviewMode::NONE;
1321 getContainer()->switchPreview(m_ePreviewMode);
1322 break;
1323 case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
1324 m_ePreviewMode = PreviewMode::DocumentInfo;
1325 getContainer()->switchPreview(m_ePreviewMode);
1326 break;
1327 case SID_DB_APP_VIEW_DOC_PREVIEW:
1328 m_ePreviewMode = PreviewMode::Document;
1329 getContainer()->switchPreview(m_ePreviewMode);
1330 break;
1331 case SID_MAIL_SENDDOC:
1333 SfxMailModel aSendMail;
1334 if ( aSendMail.AttachDocument(getModel(), OUString()) == SfxMailModel::SEND_MAIL_OK )
1335 aSendMail.Send( getFrame() );
1337 break;
1338 case SID_DB_APP_SENDREPORTASMAIL:
1339 doAction( _nId, ElementOpenMode::Mail );
1340 break;
1343 catch( const Exception& )
1345 DBG_UNHANDLED_EXCEPTION("dbaccess");
1347 InvalidateFeature(_nId);
1350 void OApplicationController::describeSupportedFeatures()
1352 OGenericUnoController::describeSupportedFeatures();
1354 implDescribeSupportedFeature( ".uno:AddDirect", SID_NEWDOCDIRECT, CommandGroup::APPLICATION );
1355 implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC, CommandGroup::DOCUMENT );
1356 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
1357 implDescribeSupportedFeature( ".uno:SendMail", SID_MAIL_SENDDOC, CommandGroup::DOCUMENT );
1358 implDescribeSupportedFeature( ".uno:DBSendReportAsMail",SID_DB_APP_SENDREPORTASMAIL,
1359 CommandGroup::DOCUMENT );
1360 implDescribeSupportedFeature( ".uno:DBSendReportToWriter",SID_DB_APP_SENDREPORTTOWRITER,
1361 CommandGroup::DOCUMENT );
1362 implDescribeSupportedFeature( ".uno:DBNewForm", SID_APP_NEW_FORM, CommandGroup::INSERT );
1363 implDescribeSupportedFeature( ".uno:DBNewFolder", SID_APP_NEW_FOLDER, CommandGroup::INSERT );
1364 implDescribeSupportedFeature( ".uno:DBNewFormAutoPilot", SID_DB_FORM_NEW_PILOT, CommandGroup::INSERT );
1365 implDescribeSupportedFeature( ".uno:DBNewFormAutoPilotWithPreSelection",
1366 SID_FORM_CREATE_REPWIZ_PRE_SEL,
1367 CommandGroup::APPLICATION );
1369 implDescribeSupportedFeature( ".uno:DBNewReport", SID_APP_NEW_REPORT, CommandGroup::INSERT );
1370 implDescribeSupportedFeature( ".uno:DBNewReportAutoPilot",
1371 ID_DOCUMENT_CREATE_REPWIZ, CommandGroup::INSERT );
1372 implDescribeSupportedFeature( ".uno:DBNewReportAutoPilotWithPreSelection",
1373 SID_REPORT_CREATE_REPWIZ_PRE_SEL,
1374 CommandGroup::APPLICATION );
1375 implDescribeSupportedFeature( ".uno:DBNewQuery", ID_NEW_QUERY_DESIGN, CommandGroup::INSERT );
1376 implDescribeSupportedFeature( ".uno:DBNewQuerySql", ID_NEW_QUERY_SQL, CommandGroup::INSERT );
1377 implDescribeSupportedFeature( ".uno:DBNewQueryAutoPilot",ID_APP_NEW_QUERY_AUTO_PILOT,
1378 CommandGroup::INSERT );
1379 implDescribeSupportedFeature( ".uno:DBNewTable", ID_NEW_TABLE_DESIGN, CommandGroup::INSERT );
1380 implDescribeSupportedFeature( ".uno:DBNewTableAutoPilot",ID_NEW_TABLE_DESIGN_AUTO_PILOT,
1381 CommandGroup::INSERT );
1382 implDescribeSupportedFeature( ".uno:DBNewView", ID_NEW_VIEW_DESIGN, CommandGroup::INSERT );
1383 implDescribeSupportedFeature( ".uno:DBNewViewSQL", SID_DB_NEW_VIEW_SQL, CommandGroup::INSERT );
1385 implDescribeSupportedFeature( ".uno:DBDelete", SID_DB_APP_DELETE, CommandGroup::EDIT );
1386 implDescribeSupportedFeature( ".uno:Delete", SID_DB_APP_DELETE, CommandGroup::EDIT );
1387 implDescribeSupportedFeature( ".uno:DBRename", SID_DB_APP_RENAME, CommandGroup::EDIT );
1388 implDescribeSupportedFeature( ".uno:DBEdit", SID_DB_APP_EDIT, CommandGroup::EDIT );
1389 implDescribeSupportedFeature( ".uno:DBEditSqlView", SID_DB_APP_EDIT_SQL_VIEW, CommandGroup::EDIT );
1390 implDescribeSupportedFeature( ".uno:DBOpen", SID_DB_APP_OPEN, CommandGroup::EDIT );
1392 implDescribeSupportedFeature( ".uno:DBTableDelete", SID_DB_APP_TABLE_DELETE, CommandGroup::EDIT );
1393 implDescribeSupportedFeature( ".uno:DBTableRename", SID_DB_APP_TABLE_RENAME, CommandGroup::EDIT );
1394 implDescribeSupportedFeature( ".uno:DBTableEdit", SID_DB_APP_TABLE_EDIT, CommandGroup::EDIT );
1395 implDescribeSupportedFeature( ".uno:DBTableOpen", SID_DB_APP_TABLE_OPEN, CommandGroup::EDIT );
1397 implDescribeSupportedFeature( ".uno:DBQueryDelete", SID_DB_APP_QUERY_DELETE, CommandGroup::EDIT );
1398 implDescribeSupportedFeature( ".uno:DBQueryRename", SID_DB_APP_QUERY_RENAME, CommandGroup::EDIT );
1399 implDescribeSupportedFeature( ".uno:DBQueryEdit", SID_DB_APP_QUERY_EDIT, CommandGroup::EDIT );
1400 implDescribeSupportedFeature( ".uno:DBQueryOpen", SID_DB_APP_QUERY_OPEN, CommandGroup::EDIT );
1402 implDescribeSupportedFeature( ".uno:DBFormDelete", SID_DB_APP_FORM_DELETE, CommandGroup::EDIT );
1403 implDescribeSupportedFeature( ".uno:DBFormRename", SID_DB_APP_FORM_RENAME, CommandGroup::EDIT );
1404 implDescribeSupportedFeature( ".uno:DBFormEdit", SID_DB_APP_FORM_EDIT, CommandGroup::EDIT );
1405 implDescribeSupportedFeature( ".uno:DBFormOpen", SID_DB_APP_FORM_OPEN, CommandGroup::EDIT );
1407 implDescribeSupportedFeature( ".uno:DBReportDelete", SID_DB_APP_REPORT_DELETE, CommandGroup::EDIT );
1408 implDescribeSupportedFeature( ".uno:DBReportRename", SID_DB_APP_REPORT_RENAME, CommandGroup::EDIT );
1409 implDescribeSupportedFeature( ".uno:DBReportEdit", SID_DB_APP_REPORT_EDIT, CommandGroup::EDIT );
1410 implDescribeSupportedFeature( ".uno:DBReportOpen", SID_DB_APP_REPORT_OPEN, CommandGroup::EDIT );
1412 implDescribeSupportedFeature( ".uno:SelectAll", SID_SELECTALL, CommandGroup::EDIT );
1413 implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO, CommandGroup::EDIT );
1415 implDescribeSupportedFeature( ".uno:Sortup", ID_BROWSER_SORTUP, CommandGroup::VIEW );
1416 implDescribeSupportedFeature( ".uno:SortDown", ID_BROWSER_SORTDOWN, CommandGroup::VIEW );
1417 implDescribeSupportedFeature( ".uno:DBRelationDesign", SID_DB_APP_DSRELDESIGN, CommandGroup::APPLICATION );
1418 implDescribeSupportedFeature( ".uno:DBUserAdmin", SID_DB_APP_DSUSERADMIN, CommandGroup::APPLICATION );
1419 implDescribeSupportedFeature( ".uno:DBTableFilter", SID_DB_APP_TABLEFILTER, CommandGroup::APPLICATION );
1420 implDescribeSupportedFeature( ".uno:DBDSProperties", SID_DB_APP_DSPROPS, CommandGroup::EDIT );
1421 implDescribeSupportedFeature( ".uno:DBDSConnectionType", SID_DB_APP_DSCONNECTION_TYPE,
1422 CommandGroup::EDIT );
1423 implDescribeSupportedFeature( ".uno:DBDSAdvancedSettings",
1424 SID_DB_APP_DSADVANCED_SETTINGS,
1425 CommandGroup::EDIT );
1426 implDescribeSupportedFeature( ".uno:PasteSpecial", SID_DB_APP_PASTE_SPECIAL, CommandGroup::EDIT );
1427 implDescribeSupportedFeature( ".uno:DBConvertToView", SID_DB_APP_CONVERTTOVIEW, CommandGroup::EDIT );
1428 implDescribeSupportedFeature( ".uno:DBRefreshTables", SID_DB_APP_REFRESH_TABLES, CommandGroup::APPLICATION );
1429 implDescribeSupportedFeature( ".uno:DBDirectSQL", ID_DIRECT_SQL, CommandGroup::APPLICATION );
1430 implDescribeSupportedFeature( ".uno:DBViewTables", SID_DB_APP_VIEW_TABLES, CommandGroup::VIEW );
1431 implDescribeSupportedFeature( ".uno:DBViewQueries", SID_DB_APP_VIEW_QUERIES, CommandGroup::VIEW );
1432 implDescribeSupportedFeature( ".uno:DBViewForms", SID_DB_APP_VIEW_FORMS, CommandGroup::VIEW );
1433 implDescribeSupportedFeature( ".uno:DBViewReports", SID_DB_APP_VIEW_REPORTS, CommandGroup::VIEW );
1434 implDescribeSupportedFeature( ".uno:DBDisablePreview", SID_DB_APP_DISABLE_PREVIEW,CommandGroup::VIEW );
1435 implDescribeSupportedFeature( ".uno:DBShowDocInfoPreview",
1436 SID_DB_APP_VIEW_DOCINFO_PREVIEW,
1437 CommandGroup::VIEW );
1438 implDescribeSupportedFeature( ".uno:DBShowDocPreview", SID_DB_APP_VIEW_DOC_PREVIEW,
1439 CommandGroup::VIEW );
1441 implDescribeSupportedFeature( ".uno:OpenUrl", SID_OPENURL, CommandGroup::APPLICATION );
1443 // this one should not appear under Tools->Customize->Keyboard
1444 implDescribeSupportedFeature( ".uno:DBNewReportWithPreSelection",
1445 SID_APP_NEW_REPORT_PRE_SEL );
1446 implDescribeSupportedFeature( ".uno:DBDSImport", SID_DB_APP_DSIMPORT);
1447 implDescribeSupportedFeature( ".uno:DBDSExport", SID_DB_APP_DSEXPORT);
1448 implDescribeSupportedFeature( ".uno:DBDBAdmin", SID_DB_APP_DBADMIN);
1450 // status info
1451 implDescribeSupportedFeature( ".uno:DBStatusType", SID_DB_APP_STATUS_TYPE);
1452 implDescribeSupportedFeature( ".uno:DBStatusDBName", SID_DB_APP_STATUS_DBNAME);
1453 implDescribeSupportedFeature( ".uno:DBStatusUserName", SID_DB_APP_STATUS_USERNAME);
1454 implDescribeSupportedFeature( ".uno:DBStatusHostName", SID_DB_APP_STATUS_HOSTNAME);
1457 OApplicationView* OApplicationController::getContainer() const
1459 return static_cast< OApplicationView* >( getView() );
1462 // css::container::XContainerListener
1463 void SAL_CALL OApplicationController::elementInserted( const ContainerEvent& _rEvent )
1465 SolarMutexGuard aSolarGuard;
1466 ::osl::MutexGuard aGuard( getMutex() );
1468 Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1469 if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
1470 return;
1472 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1473 if ( !getContainer() )
1474 return;
1476 OUString sName;
1477 _rEvent.Accessor >>= sName;
1478 ElementType eType = getElementType(xContainer);
1480 switch( eType )
1482 case E_TABLE:
1483 ensureConnection();
1484 break;
1485 case E_FORM:
1486 case E_REPORT:
1488 Reference< XContainer > xSubContainer(_rEvent.Element,UNO_QUERY);
1489 if ( xSubContainer.is() )
1490 containerFound(xSubContainer);
1492 break;
1493 default:
1494 break;
1496 getContainer()->elementAdded(eType,sName,_rEvent.Element);
1499 void SAL_CALL OApplicationController::elementRemoved( const ContainerEvent& _rEvent )
1501 SolarMutexGuard aSolarGuard;
1502 ::osl::MutexGuard aGuard( getMutex() );
1504 Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1505 if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
1506 return;
1508 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1509 OUString sName;
1510 _rEvent.Accessor >>= sName;
1511 ElementType eType = getElementType(xContainer);
1512 switch( eType )
1514 case E_TABLE:
1515 ensureConnection();
1516 break;
1517 case E_FORM:
1518 case E_REPORT:
1520 Reference<XContent> xContent(xContainer,UNO_QUERY);
1521 if ( xContent.is() )
1523 sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
1526 break;
1527 default:
1528 break;
1530 getContainer()->elementRemoved(eType,sName);
1533 void SAL_CALL OApplicationController::elementReplaced( const ContainerEvent& _rEvent )
1535 SolarMutexGuard aSolarGuard;
1536 ::osl::MutexGuard aGuard( getMutex() );
1538 Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1539 if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
1540 return;
1542 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1543 OUString sName;
1546 _rEvent.Accessor >>= sName;
1547 Reference<XPropertySet> xProp(_rEvent.Element,UNO_QUERY);
1549 ElementType eType = getElementType(xContainer);
1550 switch( eType )
1552 case E_TABLE:
1554 ensureConnection();
1555 if ( xProp.is() && m_xMetaData.is() )
1556 //TODO: tdf#133497 "OApplicationController::elementReplaced effectively does
1557 // nothing":
1558 (void) ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
1560 break;
1561 case E_FORM:
1562 case E_REPORT:
1564 Reference<XContent> xContent(xContainer,UNO_QUERY);
1565 if ( xContent.is() )
1567 sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
1570 break;
1571 default:
1572 break;
1574 // getContainer()->elementReplaced(getContainer()->getElementType(),sName,sNewName);
1576 catch( Exception& )
1578 DBG_UNHANDLED_EXCEPTION("dbaccess");
1582 namespace
1584 OUString lcl_getToolBarResource(ElementType _eType)
1586 OUString sToolbar;
1587 switch(_eType)
1589 case E_TABLE:
1590 sToolbar = "private:resource/toolbar/tableobjectbar";
1591 break;
1592 case E_QUERY:
1593 sToolbar = "private:resource/toolbar/queryobjectbar";
1594 break;
1595 case E_FORM:
1596 sToolbar = "private:resource/toolbar/formobjectbar";
1597 break;
1598 case E_REPORT:
1599 sToolbar = "private:resource/toolbar/reportobjectbar";
1600 break;
1601 case E_NONE:
1602 break;
1603 default:
1604 OSL_FAIL("Invalid ElementType!");
1605 break;
1607 return sToolbar;
1611 bool OApplicationController::onContainerSelect(ElementType _eType)
1613 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1615 if ( m_eCurrentType != _eType && _eType != E_NONE )
1617 SelectionGuard aSelGuard( *m_pSelectionNotifier );
1619 if ( _eType == E_TABLE )
1623 SharedConnection xConnection( ensureConnection() );
1624 if ( xConnection.is() && getContainer()->getDetailView() )
1626 getContainer()->getDetailView()->createTablesPage(xConnection);
1627 Reference<XTablesSupplier> xTabSup(xConnection,UNO_QUERY);
1628 if ( xTabSup.is() )
1629 addContainerListener(xTabSup->getTables());
1631 else
1633 return false;
1636 catch( const Exception& )
1638 return false;
1641 else if ( _eType == E_QUERY )
1643 // tdf#126578: retrieve connection to be able to call "Create as View"
1644 ensureConnection();
1646 Reference< XLayoutManager > xLayoutManager = getLayoutManager( getFrame() );
1647 if ( xLayoutManager.is() )
1649 OUString sToolbar = lcl_getToolBarResource(_eType);
1650 OUString sDestroyToolbar = lcl_getToolBarResource(m_eCurrentType);
1652 xLayoutManager->lock();
1653 xLayoutManager->destroyElement( sDestroyToolbar );
1654 if ( !sToolbar.isEmpty() )
1656 xLayoutManager->createElement( sToolbar );
1657 xLayoutManager->requestElement( sToolbar );
1659 xLayoutManager->unlock();
1660 xLayoutManager->doLayout();
1663 if ( _eType != E_TABLE && getContainer()->getDetailView() )
1665 Reference< XNameAccess > xContainer = getElements(_eType);
1666 addContainerListener(xContainer);
1667 getContainer()->getDetailView()->createPage(_eType,xContainer);
1670 SelectionByElementType::const_iterator pendingSelection = m_aPendingSelection.find( _eType );
1671 if ( pendingSelection != m_aPendingSelection.end() )
1673 getContainer()->selectElements( comphelper::containerToSequence(pendingSelection->second) );
1675 m_aPendingSelection.erase( pendingSelection );
1678 InvalidateAll();
1680 m_eCurrentType = _eType;
1682 return true;
1685 bool OApplicationController::onEntryDoubleClick(const weld::TreeView& rTreeView)
1687 OApplicationView* pContainer = getContainer();
1688 if (!pContainer)
1689 return false; // not handled
1691 std::unique_ptr<weld::TreeIter> xHdlEntry = rTreeView.make_iterator();
1692 if (!rTreeView.get_cursor(xHdlEntry.get()))
1693 return false;
1695 if (!pContainer->isLeaf(rTreeView, *xHdlEntry))
1696 return false; // not handled
1700 // opens a new frame with either the table or the query or report or form or view
1701 openElementWithArguments(
1702 getContainer()->getQualifiedName(xHdlEntry.get()),
1703 getContainer()->getElementType(),
1704 ElementOpenMode::Normal,
1706 ::comphelper::NamedValueCollection() );
1707 return true; // handled
1709 catch(const Exception&)
1711 DBG_UNHANDLED_EXCEPTION("dbaccess");
1714 return false; // not handled
1717 bool OApplicationController::impl_isAlterableView_nothrow( const OUString& _rTableOrViewName ) const
1719 OSL_PRECOND( m_xDataSourceConnection.is(), "OApplicationController::impl_isAlterableView_nothrow: no connection!" );
1721 bool bIsAlterableView( false );
1724 Reference< XViewsSupplier > xViewsSupp( m_xDataSourceConnection, UNO_QUERY );
1725 Reference< XNameAccess > xViews;
1726 if ( xViewsSupp.is() )
1727 xViews = xViewsSupp->getViews();
1729 Reference< XAlterView > xAsAlterableView;
1730 if ( xViews.is() && xViews->hasByName( _rTableOrViewName ) )
1731 xAsAlterableView.set( xViews->getByName( _rTableOrViewName ), UNO_QUERY );
1733 bIsAlterableView = xAsAlterableView.is();
1735 catch( const Exception& )
1737 DBG_UNHANDLED_EXCEPTION("dbaccess");
1739 return bIsAlterableView;
1742 Reference< XComponent > OApplicationController::openElementWithArguments( const OUString& _sName, ElementType _eType,
1743 ElementOpenMode _eOpenMode, sal_uInt16 _nInstigatorCommand, const ::comphelper::NamedValueCollection& _rAdditionalArguments )
1745 OSL_PRECOND( getContainer(), "OApplicationController::openElementWithArguments: no view!" );
1746 if ( !getContainer() )
1747 return nullptr;
1749 Reference< XComponent > xRet;
1750 if ( _eOpenMode == ElementOpenMode::Design )
1752 // https://bz.apache.org/ooo/show_bug.cgi?id=30382
1753 getContainer()->showPreview(nullptr);
1756 bool isStandaloneDocument = false;
1757 switch ( _eType )
1759 case E_REPORT:
1760 if ( _eOpenMode != ElementOpenMode::Design )
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;
1766 [[fallthrough]];
1767 case E_FORM:
1769 if ( isStandaloneDocument || !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
1771 std::unique_ptr< OLinkedDocumentsAccess > aHelper = getDocumentsAccess( _eType );
1772 if ( !aHelper->isConnected() )
1773 break;
1775 Reference< XComponent > xDefinition;
1776 xRet = aHelper->open( _sName, xDefinition, _eOpenMode, _rAdditionalArguments );
1778 if ( !isStandaloneDocument )
1779 onDocumentOpened( _sName, _eType, _eOpenMode, xRet, xDefinition );
1782 break;
1784 case E_QUERY:
1785 case E_TABLE:
1787 if ( !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
1789 SharedConnection xConnection( ensureConnection() );
1790 if ( !xConnection.is() )
1791 break;
1793 std::unique_ptr< DatabaseObjectView > pDesigner;
1794 ::comphelper::NamedValueCollection aArguments( _rAdditionalArguments );
1796 Any aDataSource;
1797 if ( _eOpenMode == ElementOpenMode::Design )
1799 bool bAddViewTypeArg = false;
1801 if ( _eType == E_TABLE )
1803 if ( impl_isAlterableView_nothrow( _sName ) )
1805 pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), true ) );
1806 bAddViewTypeArg = true;
1808 else
1810 pDesigner.reset( new TableDesigner( getORB(), this, m_aCurrentFrame.getFrame() ) );
1813 else if ( _eType == E_QUERY )
1815 pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), false ) );
1816 bAddViewTypeArg = true;
1818 aDataSource <<= m_xDataSource;
1820 if ( bAddViewTypeArg )
1822 const bool bQueryGraphicalMode =( _nInstigatorCommand != SID_DB_APP_EDIT_SQL_VIEW );
1823 aArguments.put( PROPERTY_GRAPHICAL_DESIGN, bQueryGraphicalMode );
1827 else
1829 pDesigner.reset( new ResultSetBrowser( getORB(), this, m_aCurrentFrame.getFrame(), _eType == E_TABLE ) );
1831 if ( !aArguments.has( PROPERTY_SHOWMENU ) )
1832 aArguments.put( PROPERTY_SHOWMENU, Any( true ) );
1834 aDataSource <<= getDatabaseName();
1837 xRet.set( pDesigner->openExisting( aDataSource, _sName, aArguments ) );
1838 onDocumentOpened( _sName, _eType, _eOpenMode, xRet, nullptr );
1841 break;
1843 default:
1844 OSL_FAIL( "OApplicationController::openElement: illegal object type!" );
1845 break;
1847 return xRet;
1850 IMPL_LINK( OApplicationController, OnSelectContainer, void*, _pType, void )
1852 ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
1853 if (getContainer())
1854 getContainer()->selectContainer(eType);
1857 IMPL_LINK( OApplicationController, OnCreateWithPilot, void*, _pType, void )
1859 ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
1860 newElementWithPilot( eType );
1863 void OApplicationController::newElementWithPilot( ElementType _eType )
1865 utl::CloseVeto aKeepDoc( getFrame() );
1866 // prevent the document being closed while the wizard is open
1868 OSL_ENSURE( getContainer(), "OApplicationController::newElementWithPilot: without a view?" );
1870 switch ( _eType )
1872 case E_REPORT:
1873 case E_FORM:
1875 std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
1876 if ( aHelper->isConnected() )
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 );
1886 break;
1887 case E_QUERY:
1888 case E_TABLE:
1890 std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
1891 if ( aHelper->isConnected() )
1893 if ( E_QUERY == _eType )
1894 aHelper->newQueryWithPilot();
1895 else
1896 aHelper->newTableWithPilot();
1899 break;
1900 case E_NONE:
1901 break;
1904 // no need for onDocumentOpened, the table wizard opens the created table by using
1905 // XDatabaseDocumentUI::loadComponent method.
1908 Reference< XComponent > OApplicationController::newElement( ElementType _eType, const ::comphelper::NamedValueCollection& i_rAdditionalArguments,
1909 Reference< XComponent >& o_rDocumentDefinition )
1911 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1913 Reference< XComponent > xComponent;
1914 o_rDocumentDefinition.clear();
1916 switch ( _eType )
1918 case E_FORM:
1919 case E_REPORT:
1921 std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess( _eType );
1922 if ( !aHelper->isConnected() )
1923 break;
1925 xComponent = aHelper->newDocument( _eType == E_FORM ? ID_FORM_NEW_TEXT : ID_REPORT_NEW_TEXT, i_rAdditionalArguments, o_rDocumentDefinition );
1927 break;
1929 case E_QUERY:
1930 case E_TABLE:
1932 std::unique_ptr< DatabaseObjectView > pDesigner;
1933 SharedConnection xConnection( ensureConnection() );
1934 if ( !xConnection.is() )
1935 break;
1937 if ( _eType == E_TABLE )
1939 pDesigner.reset( new TableDesigner( getORB(), this, getFrame() ) );
1941 else if ( _eType == E_QUERY )
1943 pDesigner.reset( new QueryDesigner( getORB(), this, getFrame(), false ) );
1946 Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1947 xComponent = pDesigner->createNew( xDataSource, i_rAdditionalArguments );
1949 break;
1951 default:
1952 OSL_FAIL( "OApplicationController::newElement: illegal type!" );
1953 break;
1956 if ( xComponent.is() )
1957 onDocumentOpened( OUString(), _eType, ElementOpenMode::Design, xComponent, o_rDocumentDefinition );
1959 return xComponent;
1962 void OApplicationController::addContainerListener(const Reference<XNameAccess>& _xCollection)
1966 Reference< XContainer > xCont(_xCollection, UNO_QUERY);
1967 if ( xCont.is() )
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() )
1973 xCont->addContainerListener(this);
1974 m_aCurrentContainers.push_back(xCont);
1978 catch( const Exception& )
1980 DBG_UNHANDLED_EXCEPTION("dbaccess");
1984 void OApplicationController::renameEntry()
1986 SolarMutexGuard aSolarGuard;
1987 ::osl::MutexGuard aGuard( getMutex() );
1989 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1990 std::vector< OUString> aList;
1991 getSelectionElementNames(aList);
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;
2000 if ( xContainer.is() )
2002 std::unique_ptr< IObjectNameCheck > pNameChecker;
2003 std::unique_ptr<OSaveAsDlg> xDialog;
2005 Reference<XRename> xRename;
2006 const ElementType eType = getContainer()->getElementType();
2007 switch( eType )
2009 case E_FORM:
2010 case E_REPORT:
2012 Reference<XHierarchicalNameContainer> xHNames(xContainer, UNO_QUERY);
2013 if ( xHNames.is() )
2015 OUString sLabel;
2016 if ( eType == E_FORM )
2017 sLabel = DBA_RES(STR_FRM_LABEL);
2018 else
2019 sLabel = DBA_RES(STR_RPT_LABEL);
2021 OUString sName = *aList.begin();
2022 if ( xHNames->hasByHierarchicalName(sName) )
2024 xRename.set(xHNames->getByHierarchicalName(sName),UNO_QUERY);
2025 Reference<XChild> xChild(xRename,UNO_QUERY);
2026 if ( xChild.is() )
2028 Reference<XHierarchicalNameContainer> xParent(xChild->getParent(),UNO_QUERY);
2029 if ( xParent.is() )
2031 xHNames = xParent;
2032 Reference<XPropertySet>(xRename,UNO_QUERY_THROW)->getPropertyValue(PROPERTY_NAME) >>= sName;
2035 pNameChecker.reset( new HierarchicalNameCheck( xHNames, OUString() ) );
2036 xDialog.reset(new OSaveAsDlg(
2037 getFrameWeld(), getORB(), sName, sLabel, *pNameChecker, SADFlags::TitleRename));
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()) )
2050 xRename.set(xContainer->getByName(*aList.begin()),UNO_QUERY);
2051 sal_Int32 nCommandType = eType == E_QUERY ? CommandType::QUERY : CommandType::TABLE;
2053 ensureConnection();
2054 pNameChecker.reset( new DynamicTableOrQueryNameCheck( getConnection(), nCommandType ) );
2055 xDialog.reset(new OSaveAsDlg(getFrameWeld(), nCommandType, getORB(), getConnection(),
2056 *aList.begin(), *pNameChecker, SADFlags::TitleRename));
2058 break;
2059 default:
2060 break;
2063 if (xRename.is() && xDialog)
2066 bool bTryAgain = true;
2067 while( bTryAgain )
2069 if (xDialog->run() == RET_OK)
2073 OUString sNewName;
2074 if ( eType == E_TABLE )
2076 OUString sName = xDialog->getName();
2077 OUString sCatalog = xDialog->getCatalog();
2078 OUString sSchema = xDialog->getSchema();
2080 sNewName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sName, false, ::dbtools::EComposeRule::InDataManipulation );
2082 else
2083 sNewName = xDialog->getName();
2085 OUString sOldName = *aList.begin();
2086 if ( eType == E_FORM || eType == E_REPORT )
2088 Reference<XContent> xContent(xRename,UNO_QUERY);
2089 if ( xContent.is() )
2091 sOldName = xContent->getIdentifier()->getContentIdentifier();
2095 xRename->rename(sNewName);
2097 if ( eType == E_TABLE )
2099 Reference<XPropertySet> xProp(xRename,UNO_QUERY);
2100 sNewName = ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
2102 getContainer()->elementReplaced( eType , sOldName, sNewName );
2104 bTryAgain = false;
2106 catch(const SQLException& )
2108 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
2111 catch(const ElementExistException& e)
2113 OUString sMsg(DBA_RES(STR_NAME_ALREADY_EXISTS));
2114 showError(SQLExceptionInfo(SQLException(sMsg.replaceAll("#", e.Message), e.Context, "S1000", 0, Any())));
2116 catch(const Exception& )
2118 DBG_UNHANDLED_EXCEPTION("dbaccess");
2121 else
2122 bTryAgain = false;
2127 catch(const Exception& )
2129 DBG_UNHANDLED_EXCEPTION("dbaccess");
2133 void OApplicationController::onSelectionChanged()
2135 InvalidateAll();
2137 SelectionGuard aSelGuard( *m_pSelectionNotifier );
2139 OApplicationView* pView = getContainer();
2140 if ( !pView )
2141 return;
2143 if ( pView->getSelectionCount() == 1 )
2145 const ElementType eType = pView->getElementType();
2146 if ( pView->isALeafSelected() )
2148 const OUString sName = pView->getQualifiedName( nullptr /* means 'first selected' */ );
2149 showPreviewFor( eType, sName );
2154 void OApplicationController::showPreviewFor(const ElementType _eType,const OUString& _sName)
2156 if ( m_ePreviewMode == PreviewMode::NONE )
2157 return;
2159 OApplicationView* pView = getContainer();
2160 if ( !pView )
2161 return;
2165 switch( _eType )
2167 case E_FORM:
2168 case E_REPORT:
2170 Reference< XHierarchicalNameAccess > xContainer( getElements( _eType ), UNO_QUERY_THROW );
2171 Reference< XContent> xContent( xContainer->getByHierarchicalName( _sName ), UNO_QUERY_THROW );
2172 pView->showPreview( xContent );
2174 break;
2176 case E_TABLE:
2177 case E_QUERY:
2179 SharedConnection xConnection( ensureConnection() );
2180 if ( xConnection.is() )
2181 pView->showPreview( getDatabaseName(), xConnection, _sName, _eType == E_TABLE );
2183 return;
2185 default:
2186 OSL_FAIL( "OApplicationController::showPreviewFor: unexpected element type!" );
2187 break;
2190 catch( const SQLException& )
2192 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
2194 catch(const Exception& )
2196 DBG_UNHANDLED_EXCEPTION("dbaccess");
2200 IMPL_LINK_NOARG(OApplicationController, OnClipboardChanged, TransferableDataHelper*, void)
2202 OnInvalidateClipboard();
2205 void OApplicationController::OnInvalidateClipboard()
2207 InvalidateFeature(ID_BROWSER_CUT);
2208 InvalidateFeature(ID_BROWSER_COPY);
2209 InvalidateFeature(ID_BROWSER_PASTE);
2210 InvalidateFeature(SID_DB_APP_PASTE_SPECIAL);
2213 void OApplicationController::onCopyEntry()
2215 Execute(ID_BROWSER_COPY,Sequence<PropertyValue>());
2218 void OApplicationController::onPasteEntry()
2220 Execute(ID_BROWSER_PASTE,Sequence<PropertyValue>());
2223 void OApplicationController::onDeleteEntry()
2225 ElementType eType = getContainer()->getElementType();
2226 sal_uInt16 nId = 0;
2227 switch(eType)
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;
2245 executeChecked(nId,Sequence<PropertyValue>());
2248 OUString OApplicationController::getContextMenuResourceName() const
2250 return "edit";
2253 IController& OApplicationController::getCommandController()
2255 return *this;
2258 ::comphelper::OInterfaceContainerHelper2* OApplicationController::getContextMenuInterceptors()
2260 return &m_aContextMenuInterceptors;
2263 Any OApplicationController::getCurrentSelection(weld::TreeView& rControl) const
2265 Sequence< NamedDatabaseObject > aSelection;
2266 getContainer()->describeCurrentSelectionForControl(rControl, aSelection);
2267 return Any( aSelection );
2270 vcl::Window* OApplicationController::getMenuParent() const
2272 return getContainer()->getMenuParent();
2275 void OApplicationController::adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const
2277 getContainer()->adjustMenuPosition(rControl, rPos);
2280 bool OApplicationController::requestQuickHelp(const void* /*pUserData*/, OUString& /*rText*/) const
2282 return false;
2285 bool OApplicationController::requestDrag(const weld::TreeIter& /*rEntry*/)
2287 bool bSuccess = false;
2289 OApplicationView* pContainer = getContainer();
2290 if (pContainer && pContainer->getSelectionCount())
2294 if (getContainer()->getDetailView())
2296 TreeListBox* pTreeListBox = getContainer()->getDetailView()->getTreeWindow();
2298 ElementType eType = getContainer()->getElementType();
2299 if (eType == E_TABLE || eType == E_QUERY)
2301 ODataClipboard& rExchange = static_cast<ODataClipboard&>(pTreeListBox->GetDataTransfer());
2302 bSuccess = copySQLObject(rExchange);
2304 else
2306 svx::OComponentTransferable& rExchange = static_cast<svx::OComponentTransferable&>(pTreeListBox->GetDataTransfer());
2307 bSuccess = copyDocObject(rExchange);
2311 catch(const Exception& )
2313 DBG_UNHANDLED_EXCEPTION("dbaccess");
2317 return bSuccess;
2320 sal_Int8 OApplicationController::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
2322 sal_Int8 nActionAskedFor = _rEvt.mnAction;
2323 // check if we're a table or query container
2324 OApplicationView* pView = getContainer();
2325 if ( !pView || isDataSourceReadOnly() )
2326 return DND_ACTION_NONE;
2328 ElementType eType = pView->getElementType();
2329 if ( eType == E_NONE || (eType == E_TABLE && isConnectionReadOnly()) )
2330 return DND_ACTION_NONE;
2332 // check for the concrete type
2333 if(std::any_of(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(eType)))
2334 return DND_ACTION_COPY;
2336 if ( eType != E_FORM && eType != E_REPORT )
2337 return DND_ACTION_NONE;
2339 sal_Int8 nAction = OComponentTransferable::canExtractComponentDescriptor(_rFlavors,eType == E_FORM) ? DND_ACTION_COPY : DND_ACTION_NONE;
2340 if ( nAction == DND_ACTION_NONE )
2341 return DND_ACTION_NONE;
2343 auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
2344 if (xHitEntry)
2346 OUString sName = pView->getQualifiedName(xHitEntry.get());
2347 if ( !sName.isEmpty() )
2349 Reference< XHierarchicalNameAccess > xContainer(getElements(pView->getElementType()),UNO_QUERY);
2350 if ( xContainer.is() && xContainer->hasByHierarchicalName(sName) )
2352 Reference< XHierarchicalNameAccess > xHitObject(xContainer->getByHierarchicalName(sName),UNO_QUERY);
2353 if ( xHitObject.is() )
2354 nAction = nActionAskedFor & DND_ACTION_COPYMOVE;
2356 else
2357 nAction = DND_ACTION_NONE;
2360 return nAction;
2363 sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt )
2365 OApplicationView* pView = getContainer();
2366 if ( !pView || pView->getElementType() == E_NONE )
2368 OSL_FAIL("OApplicationController::executeDrop: what the hell did queryDrop do?");
2369 // queryDrop should not have allowed us to reach this situation...
2370 return DND_ACTION_NONE;
2373 // a TransferableDataHelper for accessing the dropped data
2374 TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
2376 // reset the data of the previous async drop (if any)
2377 if ( m_nAsyncDrop )
2378 Application::RemoveUserEvent(m_nAsyncDrop);
2380 m_nAsyncDrop = nullptr;
2381 m_aAsyncDrop.aDroppedData.clear();
2382 m_aAsyncDrop.nType = pView->getElementType();
2383 m_aAsyncDrop.nAction = _rEvt.mnAction;
2384 m_aAsyncDrop.bError = false;
2385 m_aAsyncDrop.bHtml = false;
2386 m_aAsyncDrop.aUrl.clear();
2388 // loop through the available formats and see what we can do...
2389 // first we have to check if it is our own format, if not we have to copy the stream :-(
2390 if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
2392 m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
2394 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2395 m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2396 return DND_ACTION_COPY;
2398 else if ( OComponentTransferable::canExtractComponentDescriptor(aDroppedData.GetDataFlavorExVector(),m_aAsyncDrop.nType == E_FORM) )
2400 m_aAsyncDrop.aDroppedData = OComponentTransferable::extractComponentDescriptor(aDroppedData);
2401 auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
2402 if ( xHitEntry )
2403 m_aAsyncDrop.aUrl = pView->getQualifiedName(xHitEntry.get());
2405 sal_Int8 nAction = _rEvt.mnAction;
2406 Reference<XContent> xContent;
2407 m_aAsyncDrop.aDroppedData[DataAccessDescriptorProperty::Component] >>= xContent;
2408 if ( xContent.is() )
2410 OUString sName = xContent->getIdentifier()->getContentIdentifier();
2411 sName = sName.copy(sName.indexOf('/') + 1);
2412 if ( m_aAsyncDrop.aUrl.getLength() >= sName.getLength() && m_aAsyncDrop.aUrl.startsWith(sName) )
2414 m_aAsyncDrop.aDroppedData.clear();
2415 return DND_ACTION_NONE;
2418 // check if move is allowed, if another object with the same name exists only copy is allowed
2419 Reference< XHierarchicalNameAccess > xContainer(getElements(m_aAsyncDrop.nType),UNO_QUERY);
2420 Reference<XNameAccess> xNameAccess(xContainer,UNO_QUERY);
2422 if ( !m_aAsyncDrop.aUrl.isEmpty() && xContainer.is() && xContainer->hasByHierarchicalName(m_aAsyncDrop.aUrl) )
2423 xNameAccess.set(xContainer->getByHierarchicalName(m_aAsyncDrop.aUrl),UNO_QUERY);
2425 if ( xNameAccess.is() )
2427 Reference<XPropertySet> xProp(xContent,UNO_QUERY);
2428 if ( xProp.is() )
2430 xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
2431 if ( xNameAccess.is() && xNameAccess->hasByName(sName) )
2432 nAction &= ~DND_ACTION_MOVE;
2434 else
2435 nAction &= ~DND_ACTION_MOVE;
2438 if ( nAction != DND_ACTION_NONE )
2440 m_aAsyncDrop.nAction = nAction;
2441 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2442 m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2444 else
2445 m_aAsyncDrop.aDroppedData.clear();
2446 return nAction;
2448 else
2450 SharedConnection xConnection( ensureConnection() );
2451 if ( xConnection.is() && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xConnection ) )
2453 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2454 m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2455 return DND_ACTION_COPY;
2459 return DND_ACTION_NONE;
2462 Reference< XModel > SAL_CALL OApplicationController::getModel()
2464 return m_xModel;
2467 void OApplicationController::onAttachedFrame()
2469 sal_Int32 nConnectedControllers( 0 );
2472 Reference< XModel2 > xModel( m_xModel, UNO_QUERY_THROW );
2473 Reference< XEnumeration > xEnumControllers( xModel->getControllers(), UNO_SET_THROW );
2474 while ( xEnumControllers->hasMoreElements() )
2476 Reference< XController > xController( xEnumControllers->nextElement(), UNO_QUERY_THROW );
2477 ++nConnectedControllers;
2480 catch( const Exception& )
2482 DBG_UNHANDLED_EXCEPTION("dbaccess");
2485 if ( nConnectedControllers > 1 )
2486 { // we are not the first connected controller, there were already others
2487 return;
2490 OnFirstControllerConnected();
2493 void OApplicationController::OnFirstControllerConnected()
2495 if ( !m_xModel.is() )
2497 OSL_FAIL( "OApplicationController::OnFirstControllerConnected: too late!" );
2500 // if we have forms or reports which contain macros/scripts, then show a warning
2501 // which suggests the user to migrate them to the database document
2502 Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
2503 if ( xDocumentScripts.is() )
2505 // no need to show this warning, obviously the document supports embedding scripts
2506 // into itself, so there are no "old-style" forms/reports which have macros/scripts
2507 // themselves
2508 return;
2513 // If the migration just happened, but was not successful, the document is reloaded.
2514 // In this case, we should not show the warning, again.
2515 if ( ::comphelper::NamedValueCollection::getOrDefault( m_xModel->getArgs(), u"SuppressMigrationWarning", false ) )
2516 return;
2518 // also, if the document is read-only, then no migration is possible, and the
2519 // respective menu entry is hidden. So, don't show the warning in this case, too.
2520 if ( Reference< XStorable >( m_xModel, UNO_QUERY_THROW )->isReadonly() )
2521 return;
2523 SQLWarning aWarning;
2524 aWarning.Message = DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS);
2525 SQLException aDetail;
2526 aDetail.Message = DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS_DETAIL);
2527 aWarning.NextException <<= aDetail;
2529 Reference< XExecutableDialog > xDialog = ErrorMessageDialog::create( getORB(), "", nullptr, Any( aWarning ) );
2530 xDialog->execute();
2532 catch( const Exception& )
2534 DBG_UNHANDLED_EXCEPTION("dbaccess");
2538 void SAL_CALL OApplicationController::attachFrame( const Reference< XFrame > & i_rxFrame )
2540 SolarMutexGuard aSolarGuard; // avoid deadlock in XModel calls
2541 ::osl::MutexGuard aGuard( getMutex() );
2543 OGenericUnoController::attachFrame( i_rxFrame );
2544 if ( getFrame().is() )
2545 onAttachedFrame();
2548 sal_Bool SAL_CALL OApplicationController::attachModel(const Reference< XModel > & _rxModel)
2550 ::osl::MutexGuard aGuard( getMutex() );
2551 const Reference< XOfficeDatabaseDocument > xOfficeDoc( _rxModel, UNO_QUERY );
2552 const Reference< XModifiable > xDocModify( _rxModel, UNO_QUERY );
2553 if ( ( !xOfficeDoc.is() || !xDocModify.is() ) && _rxModel.is() )
2555 OSL_FAIL( "OApplicationController::attachModel: invalid model!" );
2556 return false;
2559 if ( m_xModel.is() && ( m_xModel != _rxModel ) && ( _rxModel.is() ) )
2561 OSL_ENSURE( false, "OApplicationController::attachModel: missing implementation: setting a new model while we have another one!" );
2562 // we'd need to completely update our view here, close sub components, and the like
2563 return false;
2566 const OUString aPropertyNames[] =
2568 OUString(PROPERTY_URL), OUString(PROPERTY_USER)
2571 // disconnect from old model
2574 if ( m_xDataSource.is() )
2576 for (const auto & aPropertyName : aPropertyNames)
2578 m_xDataSource->removePropertyChangeListener( aPropertyName, this );
2582 Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
2583 if ( xBroadcaster.is() )
2584 xBroadcaster->removeModifyListener( this );
2586 catch( const Exception& )
2588 DBG_UNHANDLED_EXCEPTION("dbaccess");
2591 m_xModel = _rxModel;
2592 m_xDataSource.set( xOfficeDoc.is() ? xOfficeDoc->getDataSource() : Reference< XDataSource >(), UNO_QUERY );
2594 // connect to new model
2597 if ( m_xDataSource.is() )
2599 for (const auto & aPropertyName : aPropertyNames)
2601 m_xDataSource->addPropertyChangeListener( aPropertyName, this );
2605 Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY_THROW );
2606 xBroadcaster->addModifyListener( this );
2609 catch( const Exception& )
2611 DBG_UNHANDLED_EXCEPTION("dbaccess");
2614 // initial preview mode
2615 if ( !m_xDataSource )
2616 return true;
2620 // to get the 'modified' for the data source
2621 ::comphelper::NamedValueCollection aLayoutInfo( m_xDataSource->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) );
2622 if ( aLayoutInfo.has( INFO_PREVIEW ) )
2624 const sal_Int32 nPreviewMode( aLayoutInfo.getOrDefault( INFO_PREVIEW, sal_Int32(0) ) );
2625 m_ePreviewMode = static_cast< PreviewMode >( nPreviewMode );
2626 if ( getView() )
2627 getContainer()->switchPreview( m_ePreviewMode );
2630 catch( const Exception& )
2632 DBG_UNHANDLED_EXCEPTION("dbaccess");
2635 return true;
2638 void OApplicationController::containerFound( const Reference< XContainer >& _xContainer)
2642 if ( _xContainer.is() )
2644 m_aCurrentContainers.push_back(_xContainer);
2645 _xContainer->addContainerListener(this);
2648 catch(const Exception&)
2650 DBG_UNHANDLED_EXCEPTION("dbaccess");
2654 OUString OApplicationController::getCurrentlySelectedName(sal_Int32& _rnCommandType) const
2656 _rnCommandType = ( (getContainer()->getElementType() == E_QUERY)
2657 ? CommandType::QUERY : ( (getContainer()->getElementType() == E_TABLE) ? CommandType::TABLE : -1 ));
2659 OUString sName;
2660 if ( _rnCommandType != -1 )
2664 sName = getContainer()->getQualifiedName( nullptr );
2665 OSL_ENSURE( !sName.isEmpty(), "OApplicationController::getCurrentlySelectedName: no name given!" );
2667 catch( const Exception& )
2669 DBG_UNHANDLED_EXCEPTION("dbaccess");
2672 return sName;
2675 void SAL_CALL OApplicationController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
2677 m_pSelectionNotifier->addListener( Listener );
2680 void SAL_CALL OApplicationController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
2682 m_pSelectionNotifier->removeListener( Listener );
2685 sal_Bool SAL_CALL OApplicationController::select( const Any& _aSelection )
2687 SolarMutexGuard aSolarGuard;
2688 ::osl::MutexGuard aGuard( getMutex() );
2689 Sequence< OUString> aSelection;
2690 if ( !_aSelection.hasValue() || !getView() )
2692 getContainer()->selectElements(aSelection);
2693 return true;
2696 // BEGIN compatibility
2697 Sequence< NamedValue > aCurrentSelection;
2698 if ( (_aSelection >>= aCurrentSelection) && aCurrentSelection.hasElements() )
2700 ElementType eType = E_NONE;
2701 const NamedValue* pIter = aCurrentSelection.getConstArray();
2702 const NamedValue* pEnd = pIter + aCurrentSelection.getLength();
2703 for(;pIter != pEnd;++pIter)
2705 if ( pIter->Name == "Type" )
2707 sal_Int32 nType = 0;
2708 pIter->Value >>= nType;
2709 if ( nType < DatabaseObject::TABLE || nType > DatabaseObject::REPORT )
2710 throw IllegalArgumentException();
2711 eType = static_cast< ElementType >( nType );
2713 else if ( pIter->Name == "Selection" )
2714 pIter->Value >>= aSelection;
2717 m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running
2718 getContainer()->selectContainer(eType);
2719 getContainer()->selectElements(aSelection);
2720 return true;
2722 // END compatibility
2724 Sequence< NamedDatabaseObject > aSelectedObjects;
2725 if ( !( _aSelection >>= aSelectedObjects ) )
2727 aSelectedObjects.realloc( 1 );
2728 if ( !( _aSelection >>= aSelectedObjects.getArray()[0] ) )
2729 throw IllegalArgumentException();
2732 SelectionByElementType aSelectedElements;
2733 ElementType eSelectedCategory = E_NONE;
2734 for ( const NamedDatabaseObject* pObject = aSelectedObjects.getConstArray();
2735 pObject != aSelectedObjects.getConstArray() + aSelectedObjects.getLength();
2736 ++pObject
2739 switch ( pObject->Type )
2741 case DatabaseObject::TABLE:
2742 case DatabaseObjectContainer::SCHEMA:
2743 case DatabaseObjectContainer::CATALOG:
2744 aSelectedElements[ E_TABLE ].push_back( pObject->Name );
2745 break;
2746 case DatabaseObject::QUERY:
2747 aSelectedElements[ E_QUERY ].push_back( pObject->Name );
2748 break;
2749 case DatabaseObject::FORM:
2750 case DatabaseObjectContainer::FORMS_FOLDER:
2751 aSelectedElements[ E_FORM ].push_back( pObject->Name );
2752 break;
2753 case DatabaseObject::REPORT:
2754 case DatabaseObjectContainer::REPORTS_FOLDER:
2755 aSelectedElements[ E_REPORT ].push_back( pObject->Name );
2756 break;
2757 case DatabaseObjectContainer::TABLES:
2758 case DatabaseObjectContainer::QUERIES:
2759 case DatabaseObjectContainer::FORMS:
2760 case DatabaseObjectContainer::REPORTS:
2761 if ( eSelectedCategory != E_NONE )
2762 throw IllegalArgumentException(
2763 DBA_RES(RID_STR_NO_DIFF_CAT),
2764 *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ) );
2765 eSelectedCategory =
2766 ( pObject->Type == DatabaseObjectContainer::TABLES ) ? E_TABLE
2767 : ( pObject->Type == DatabaseObjectContainer::QUERIES ) ? E_QUERY
2768 : ( pObject->Type == DatabaseObjectContainer::FORMS ) ? E_FORM
2769 : ( pObject->Type == DatabaseObjectContainer::REPORTS ) ? E_REPORT
2770 : E_NONE;
2771 break;
2773 default:
2774 case DatabaseObjectContainer::DATA_SOURCE:
2776 OUString sMessage(
2777 DBA_RES(RID_STR_UNSUPPORTED_OBJECT_TYPE).
2778 replaceFirst("$type$", OUString::number(pObject->Type)));
2779 throw IllegalArgumentException(sMessage, *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ));
2783 for (auto const& selectedElement : aSelectedElements)
2785 if ( selectedElement.first == m_eCurrentType )
2787 getContainer()->selectElements( comphelper::containerToSequence(selectedElement.second) );
2789 else
2791 m_aPendingSelection[ selectedElement.first ] = selectedElement.second;
2795 m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running
2796 getContainer()->selectContainer( eSelectedCategory );
2798 return true;
2801 Any SAL_CALL OApplicationController::getSelection( )
2803 SolarMutexGuard aSolarGuard;
2804 ::osl::MutexGuard aGuard( getMutex() );
2806 Sequence< NamedDatabaseObject > aCurrentSelection;
2807 const ElementType eType( getContainer()->getElementType() );
2808 if ( eType != E_NONE )
2810 getContainer()->describeCurrentSelectionForType( eType, aCurrentSelection );
2811 if ( !aCurrentSelection.hasElements() )
2812 { // if no objects are selected, add an entry to the sequence which describes the overall category
2813 // which is selected currently
2814 aCurrentSelection.realloc(1);
2815 auto pCurrentSelection = aCurrentSelection.getArray();
2816 pCurrentSelection[0].Name = getDatabaseName();
2817 switch ( eType )
2819 case E_TABLE: pCurrentSelection[0].Type = DatabaseObjectContainer::TABLES; break;
2820 case E_QUERY: pCurrentSelection[0].Type = DatabaseObjectContainer::QUERIES; break;
2821 case E_FORM: pCurrentSelection[0].Type = DatabaseObjectContainer::FORMS; break;
2822 case E_REPORT: pCurrentSelection[0].Type = DatabaseObjectContainer::REPORTS; break;
2823 default:
2824 OSL_FAIL( "OApplicationController::getSelection: unexpected current element type!" );
2825 break;
2829 return Any( aCurrentSelection );
2832 } // namespace dbaui
2834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */