Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / dbaccess / source / ui / app / AppController.cxx
blob741dc7afeeb8bde55539285ce78e61d83d3c3c7a
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 { u"com.sun.star.sdb.application.DefaultViewController"_ustr };
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 // Should correspond to ODatabaseSource::createArrayHelper in dbaccess/source/core/dataaccess/datasource.cxx
331 m_xDataSource->removePropertyChangeListener(OUString(), this);
332 m_xDataSource->removePropertyChangeListener(PROPERTY_INFO, this);
333 m_xDataSource->removePropertyChangeListener(PROPERTY_ISPASSWORDREQUIRED, this);
334 m_xDataSource->removePropertyChangeListener(PROPERTY_ISREADONLY, this);
335 m_xDataSource->removePropertyChangeListener(PROPERTY_LAYOUTINFORMATION, this);
336 m_xDataSource->removePropertyChangeListener(PROPERTY_NAME, this);
337 m_xDataSource->removePropertyChangeListener(PROPERTY_NUMBERFORMATSSUPPLIER, this);
338 m_xDataSource->removePropertyChangeListener(PROPERTY_PASSWORD, this);
339 m_xDataSource->removePropertyChangeListener(PROPERTY_SETTINGS, this);
340 m_xDataSource->removePropertyChangeListener(PROPERTY_SUPPRESSVERSIONCL, this);
341 m_xDataSource->removePropertyChangeListener(PROPERTY_TABLEFILTER, this);
342 m_xDataSource->removePropertyChangeListener(PROPERTY_TABLETYPEFILTER, this);
343 m_xDataSource->removePropertyChangeListener(PROPERTY_URL, this);
344 m_xDataSource->removePropertyChangeListener(PROPERTY_USER, this);
345 m_xDataSource = nullptr;
348 Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
349 if ( xBroadcaster.is() )
350 xBroadcaster->removeModifyListener(static_cast<XModifyListener*>(this));
352 if ( m_xModel.is() )
354 OUString sUrl = m_xModel->getURL();
355 if ( !sUrl.isEmpty() )
357 if ( ::comphelper::NamedValueCollection::getOrDefault( m_xModel->getArgs(), u"PickListEntry", true ) )
359 OUString aFilter;
360 INetURLObject aURL( m_xModel->getURL() );
361 std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
362 if ( pFilter )
363 aFilter = pFilter->GetFilterName();
365 OUString sDatabaseName;
366 // add to svtool history options
367 SvtHistoryOptions::AppendItem( EHistoryType::PickList,
368 aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
369 aFilter,
370 ::dbaui::getStrippedDatabaseName(m_xDataSource, sDatabaseName),
371 std::nullopt, std::nullopt);
373 // add to recent document list
374 if ( aURL.GetProtocol() == INetProtocol::File )
375 Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::DecodeMechanism::NONE ),
376 pFilter ? pFilter->GetMimeType() : OUString(),
377 pFilter ? pFilter->GetServiceName() : OUString() );
381 m_xModel->disconnectController( this );
383 m_xModel.clear();
386 catch(const Exception&)
388 DBG_UNHANDLED_EXCEPTION("dbaccess");
391 clearView();
392 OGenericUnoController::disposing(); // here the m_refCount must be equal 5
395 bool OApplicationController::Construct(vcl::Window* _pParent)
397 setView( VclPtr<OApplicationView>::Create( _pParent, getORB(), *this, m_ePreviewMode ) );
399 // late construction
400 bool bSuccess = false;
403 getContainer()->Construct();
404 bSuccess = true;
406 catch(const SQLException&)
409 catch(const Exception&)
411 OSL_FAIL("OApplicationController::Construct : the construction of UnoDataBrowserView failed !");
414 if ( !bSuccess )
416 clearView();
417 return false;
420 // now that we have a view we can create the clipboard listener
421 m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() );
422 m_aSystemClipboard.StartClipboardListening( );
424 m_pClipboardNotifier = new TransferableClipboardListener( LINK( this, OApplicationController, OnClipboardChanged ) );
425 m_pClipboardNotifier->AddListener( getView() );
427 OGenericUnoController::Construct( _pParent );
428 getView()->Show();
430 return true;
433 void SAL_CALL OApplicationController::disposing(const EventObject& _rSource)
435 ::osl::MutexGuard aGuard( getMutex() );
436 Reference<XConnection> xCon(_rSource.Source, UNO_QUERY);
437 if ( xCon.is() )
439 OSL_ENSURE( m_xDataSourceConnection == xCon,
440 "OApplicationController::disposing: which connection does this come from?" );
442 if ( getContainer() && getContainer()->getElementType() == E_TABLE )
443 getContainer()->clearPages();
444 if ( m_xDataSourceConnection == xCon )
446 m_xMetaData.clear();
447 m_xDataSourceConnection.clear();
450 else if ( _rSource.Source == m_xModel )
452 m_xModel.clear();
454 else if ( _rSource.Source == m_xDataSource )
456 m_xDataSource = nullptr;
458 else
460 Reference<XContainer> xContainer( _rSource.Source, UNO_QUERY );
461 if ( xContainer.is() )
463 TContainerVector::iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer);
464 if ( aFind != m_aCurrentContainers.end() )
465 m_aCurrentContainers.erase(aFind);
467 OGenericUnoController::disposing( _rSource );
471 sal_Bool SAL_CALL OApplicationController::suspend(sal_Bool bSuspend)
473 // notify the OnPrepareViewClosing event (before locking any mutex)
474 Reference< XDocumentEventBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
475 if ( xBroadcaster.is() )
477 xBroadcaster->notifyDocumentEvent(
478 u"OnPrepareViewClosing"_ustr,
479 this,
480 Any()
484 SolarMutexGuard aSolarGuard;
485 ::osl::MutexGuard aGuard( getMutex() );
487 if ( getView() && getView()->IsInModalMode() )
488 return false;
490 bool bCanSuspend = true;
492 if ( m_bSuspended != bool(bSuspend) )
494 if ( bSuspend && !closeSubComponents() )
495 return false;
497 Reference<XModifiable> xModi(m_xModel,UNO_QUERY);
498 Reference<XStorable> xStor(getModel(),UNO_QUERY);
500 if ( bSuspend
501 && xStor.is()
502 && !xStor->isReadonly()
503 && ( xModi.is()
504 && xModi->isModified()
508 OUString sDatabaseName;
509 switch (ExecuteQuerySaveDocument(getFrameWeld(), ::dbaui::getStrippedDatabaseName(m_xDataSource, sDatabaseName)))
511 case RET_YES:
512 Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
513 bCanSuspend = !xModi->isModified();
514 // when we save the document this must be false else some press cancel
515 break;
516 case RET_CANCEL:
517 bCanSuspend = false;
518 break;
519 default:
520 break;
525 if ( bCanSuspend )
526 m_bSuspended = bSuspend;
528 return bCanSuspend;
531 FeatureState OApplicationController::GetState(sal_uInt16 _nId) const
533 FeatureState aReturn;
534 aReturn.bEnabled = false;
535 // check this first
536 if ( !getContainer() || m_bReadOnly )
537 return aReturn;
541 switch (_nId)
543 case SID_NEWDOCDIRECT:
544 aReturn.bEnabled = true;
545 aReturn.sTitle = "private:factory/sdatabase";
546 break;
547 case SID_OPENURL:
548 aReturn.bEnabled = true;
549 if ( m_xModel.is() )
550 aReturn.sTitle = m_xModel->getURL();
551 break;
552 case ID_BROWSER_COPY:
554 sal_Int32 nCount = getContainer()->getSelectionCount();
555 aReturn.bEnabled = nCount >= 1;
556 if ( aReturn.bEnabled && nCount == 1 && getContainer()->getElementType() == E_TABLE )
557 aReturn.bEnabled = getContainer()->isALeafSelected();
559 break;
560 case ID_BROWSER_CUT:
561 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() >= 1;
562 aReturn.bEnabled = aReturn.bEnabled && (getContainer()->getElementType() != E_TABLE || getContainer()->isCutAllowed());
563 break;
564 case ID_BROWSER_PASTE:
565 switch( getContainer()->getElementType() )
567 case E_TABLE:
568 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
569 break;
570 case E_QUERY:
571 aReturn.bEnabled = !isDataSourceReadOnly() && getViewClipboard().HasFormat(SotClipboardFormatId::DBACCESS_QUERY);
572 break;
573 default:
574 aReturn.bEnabled = !isDataSourceReadOnly() && OComponentTransferable::canExtractComponentDescriptor(getViewClipboard().GetDataFlavorExVector(),getContainer()->getElementType() == E_FORM);
576 break;
577 case SID_DB_APP_PASTE_SPECIAL:
578 aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && !isDataSourceReadOnly() && !isConnectionReadOnly() && isTableFormat();
579 break;
580 case SID_OPENDOC:
581 aReturn.bEnabled = true;
582 break;
583 case ID_BROWSER_SAVEDOC:
584 aReturn.bEnabled = !isDataSourceReadOnly();
585 break;
586 case ID_BROWSER_SAVEASDOC:
587 aReturn.bEnabled = true;
588 break;
589 case ID_BROWSER_SORTUP:
590 aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
591 aReturn.bChecked = aReturn.bEnabled && getContainer()->isSortUp();
592 break;
593 case ID_BROWSER_SORTDOWN:
594 aReturn.bEnabled = getContainer()->isFilled() && getContainer()->getElementCount();
595 aReturn.bChecked = aReturn.bEnabled && !getContainer()->isSortUp();
596 break;
598 case SID_NEWDOC:
599 case SID_APP_NEW_FORM:
600 case ID_DOCUMENT_CREATE_REPWIZ:
601 aReturn.bEnabled = !isDataSourceReadOnly() && SvtModuleOptions().IsWriterInstalled();
602 break;
603 case SID_APP_NEW_REPORT:
604 aReturn.bEnabled = !isDataSourceReadOnly() && SvtModuleOptions().IsWriterInstalled();
605 if ( aReturn.bEnabled )
607 Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
608 aReturn.bEnabled = xEnumAccess.is();
609 if ( aReturn.bEnabled )
611 const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext);
612 aReturn.bEnabled = !sReportEngineServiceName.isEmpty();
613 if ( aReturn.bEnabled )
615 const Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
616 aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
620 break;
621 case SID_DB_APP_VIEW_TABLES:
622 aReturn.bEnabled = true;
623 aReturn.bChecked = getContainer()->getElementType() == E_TABLE;
624 break;
625 case SID_DB_APP_VIEW_QUERIES:
626 aReturn.bEnabled = true;
627 aReturn.bChecked = getContainer()->getElementType() == E_QUERY;
628 break;
629 case SID_DB_APP_VIEW_FORMS:
630 aReturn.bEnabled = true;
631 aReturn.bChecked = getContainer()->getElementType() == E_FORM;
632 break;
633 case SID_DB_APP_VIEW_REPORTS:
634 aReturn.bEnabled = true;
635 aReturn.bChecked = getContainer()->getElementType() == E_REPORT;
636 break;
637 case ID_NEW_QUERY_DESIGN:
638 case ID_NEW_QUERY_SQL:
639 case ID_APP_NEW_QUERY_AUTO_PILOT:
640 case SID_DB_FORM_NEW_PILOT:
641 aReturn.bEnabled = !isDataSourceReadOnly();
642 break;
643 case ID_NEW_VIEW_DESIGN:
644 case SID_DB_NEW_VIEW_SQL:
645 case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
646 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
647 if ( aReturn.bEnabled )
649 Reference<XViewsSupplier> xViewsSup( getConnection(), UNO_QUERY );
650 aReturn.bEnabled = xViewsSup.is();
652 break;
653 case ID_NEW_TABLE_DESIGN:
654 case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
655 aReturn.bEnabled = !isDataSourceReadOnly() && !isConnectionReadOnly();
656 break;
657 case ID_DIRECT_SQL:
658 aReturn.bEnabled = true;
659 break;
660 case SID_APP_NEW_FOLDER:
661 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() <= 1;
662 if ( aReturn.bEnabled )
664 const ElementType eType = getContainer()->getElementType();
665 aReturn.bEnabled = eType == E_REPORT || eType == E_FORM;
667 break;
668 case SID_FORM_CREATE_REPWIZ_PRE_SEL:
669 case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
670 case SID_APP_NEW_REPORT_PRE_SEL:
671 aReturn.bEnabled = !isDataSourceReadOnly()
672 && SvtModuleOptions().IsWriterInstalled()
673 && getContainer()->isALeafSelected();
674 if ( aReturn.bEnabled )
676 ElementType eType = getContainer()->getElementType();
677 aReturn.bEnabled = eType == E_QUERY || eType == E_TABLE;
678 if ( aReturn.bEnabled && SID_APP_NEW_REPORT_PRE_SEL == _nId )
680 Reference< XContentEnumerationAccess > xEnumAccess(m_xContext->getServiceManager(), UNO_QUERY);
681 aReturn.bEnabled = xEnumAccess.is();
682 if ( aReturn.bEnabled )
684 static constexpr OUStringLiteral s_sReportDesign = u"org.libreoffice.report.pentaho.SOReportJobFactory";
685 Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(s_sReportDesign);
686 aReturn.bEnabled = xEnumDrivers.is() && xEnumDrivers->hasMoreElements();
690 break;
691 case SID_DB_APP_DELETE:
692 case SID_DB_APP_RENAME:
693 aReturn.bEnabled = isRenameDeleteAllowed(getContainer()->getElementType(), _nId == SID_DB_APP_DELETE);
694 break;
695 case SID_DB_APP_TABLE_DELETE:
696 case SID_DB_APP_TABLE_RENAME:
697 aReturn.bEnabled = isRenameDeleteAllowed(E_TABLE, _nId == SID_DB_APP_TABLE_DELETE);
698 break;
699 case SID_DB_APP_QUERY_DELETE:
700 case SID_DB_APP_QUERY_RENAME:
701 aReturn.bEnabled = isRenameDeleteAllowed(E_QUERY, _nId == SID_DB_APP_QUERY_DELETE);
702 break;
703 case SID_DB_APP_FORM_DELETE:
704 case SID_DB_APP_FORM_RENAME:
705 aReturn.bEnabled = isRenameDeleteAllowed(E_FORM, _nId == SID_DB_APP_FORM_DELETE);
706 break;
707 case SID_DB_APP_REPORT_DELETE:
708 case SID_DB_APP_REPORT_RENAME:
709 aReturn.bEnabled = isRenameDeleteAllowed(E_REPORT, _nId == SID_DB_APP_REPORT_DELETE);
710 break;
712 case SID_SELECTALL:
713 aReturn.bEnabled = getContainer()->getElementCount() > 0 && getContainer()->getSelectionCount() != getContainer()->getElementCount();
714 break;
715 case SID_DB_APP_EDIT:
716 case SID_DB_APP_TABLE_EDIT:
717 case SID_DB_APP_QUERY_EDIT:
718 case SID_DB_APP_FORM_EDIT:
719 case SID_DB_APP_REPORT_EDIT:
720 aReturn.bEnabled = !isDataSourceReadOnly() && getContainer()->getSelectionCount() > 0
721 && getContainer()->isALeafSelected();
722 break;
723 case SID_DB_APP_EDIT_SQL_VIEW:
724 if ( isDataSourceReadOnly() )
725 aReturn.bEnabled = false;
726 else
728 switch ( getContainer()->getElementType() )
730 case E_QUERY:
731 aReturn.bEnabled = ( getContainer()->getSelectionCount() > 0 )
732 && ( getContainer()->isALeafSelected() );
733 break;
734 case E_TABLE:
735 aReturn.bEnabled = false;
736 // there's one exception: views which support altering their underlying
737 // command can be edited in SQL view, too
738 if ( ( getContainer()->getSelectionCount() > 0 )
739 && ( getContainer()->isALeafSelected() )
742 std::vector< OUString > aSelected;
743 getSelectionElementNames( aSelected );
744 bool bAlterableViews = true;
745 for (auto const& selectedName : aSelected)
747 bAlterableViews &= impl_isAlterableView_nothrow(selectedName);
748 if (!bAlterableViews)
749 break;
751 aReturn.bEnabled = bAlterableViews;
753 break;
754 default:
755 break;
758 break;
759 case SID_DB_APP_OPEN:
760 case SID_DB_APP_TABLE_OPEN:
761 case SID_DB_APP_QUERY_OPEN:
762 case SID_DB_APP_FORM_OPEN:
763 case SID_DB_APP_REPORT_OPEN:
764 aReturn.bEnabled = getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
765 break;
766 case SID_DB_APP_DSUSERADMIN:
767 aReturn.bEnabled = !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
768 break;
769 case SID_DB_APP_DSRELDESIGN:
770 aReturn.bEnabled = true;
771 break;
772 case SID_DB_APP_TABLEFILTER:
773 aReturn.bEnabled = !isDataSourceReadOnly();
774 break;
775 case SID_DB_APP_REFRESH_TABLES:
776 aReturn.bEnabled = getContainer()->getElementType() == E_TABLE && isConnected();
777 break;
778 case SID_DB_APP_DSPROPS:
779 aReturn.bEnabled = m_xDataSource.is() && dbaccess::ODsnTypeCollection::isShowPropertiesEnabled(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
780 break;
781 case SID_DB_APP_DSCONNECTION_TYPE:
782 aReturn.bEnabled = !isDataSourceReadOnly() && m_xDataSource.is() && !dbaccess::ODsnTypeCollection::isEmbeddedDatabase(::comphelper::getString(m_xDataSource->getPropertyValue(PROPERTY_URL)));
783 break;
784 case SID_DB_APP_DSADVANCED_SETTINGS:
785 aReturn.bEnabled = m_xDataSource.is() && AdvancedSettingsDialog::doesHaveAnyAdvancedSettings( m_aTypeCollection.getType(::comphelper::getString( m_xDataSource->getPropertyValue( PROPERTY_URL ) )) );
786 break;
787 case SID_DB_APP_CONVERTTOVIEW:
788 aReturn.bEnabled = !isDataSourceReadOnly();
789 if ( aReturn.bEnabled )
791 ElementType eType = getContainer()->getElementType();
792 aReturn.bEnabled = eType == E_QUERY && getContainer()->getSelectionCount() > 0;
793 if ( aReturn.bEnabled )
795 Reference<XViewsSupplier> xViewSup( getConnection(), UNO_QUERY );
796 aReturn.bEnabled = xViewSup.is() && Reference<XAppend>(xViewSup->getViews(),UNO_QUERY).is();
799 break;
800 case SID_DB_APP_DISABLE_PREVIEW:
801 aReturn.bEnabled = true;
802 aReturn.bChecked = getContainer()->getPreviewMode() == PreviewMode::NONE;
803 break;
804 case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
806 ElementType eType = getContainer()->getElementType();
807 aReturn.bEnabled = (E_REPORT == eType || E_FORM == eType);
808 aReturn.bChecked = getContainer()->getPreviewMode() == PreviewMode::DocumentInfo;
810 break;
811 case SID_DB_APP_VIEW_DOC_PREVIEW:
812 aReturn.bEnabled = true;
813 aReturn.bChecked = getContainer()->getPreviewMode() == PreviewMode::Document;
814 break;
815 case ID_BROWSER_UNDO:
816 case SID_DB_APP_SENDREPORTTOWRITER:
817 case SID_DB_APP_DBADMIN:
818 aReturn.bEnabled = false;
819 break;
820 case SID_MAIL_SENDDOC:
821 aReturn.bEnabled = true;
822 break;
823 case SID_DB_APP_SENDREPORTASMAIL:
825 ElementType eType = getContainer()->getElementType();
826 aReturn.bEnabled = E_REPORT == eType && getContainer()->getSelectionCount() > 0 && getContainer()->isALeafSelected();
828 break;
829 case SID_DB_APP_STATUS_TYPE:
830 aReturn.bEnabled = m_xDataSource.is();
831 if ( aReturn.bEnabled )
833 OUString sURL;
834 m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
835 OUString sDSTypeName;
836 if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase( sURL ) )
838 sDSTypeName = DBA_RES(RID_STR_EMBEDDED_DATABASE);
840 else
842 sDSTypeName = m_aTypeCollection.getTypeDisplayName(sURL);
844 aReturn.sTitle = sDSTypeName;
846 break;
847 case SID_DB_APP_STATUS_DBNAME:
848 aReturn.bEnabled = m_xDataSource.is();
849 if ( aReturn.bEnabled )
851 OUString sURL;
852 m_xDataSource->getPropertyValue(PROPERTY_URL) >>= sURL;
853 OUString sDatabaseName;
854 OUString sHostName;
855 sal_Int32 nPortNumber( -1 );
857 m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
859 if ( sDatabaseName.isEmpty() )
860 sDatabaseName = m_aTypeCollection.cutPrefix( sURL );
861 if ( m_aTypeCollection.isFileSystemBased(sURL) )
863 sDatabaseName = SvtPathOptions().SubstituteVariable( sDatabaseName );
864 if ( !sDatabaseName.isEmpty() )
866 ::svt::OFileNotation aFileNotation(sDatabaseName);
867 // set this decoded URL as text
868 sDatabaseName = aFileNotation.get(::svt::OFileNotation::N_SYSTEM);
872 if ( sDatabaseName.isEmpty() )
873 sDatabaseName = m_aTypeCollection.getTypeDisplayName( sURL );
875 aReturn.sTitle = sDatabaseName;
877 break;
878 case SID_DB_APP_STATUS_USERNAME:
879 aReturn.bEnabled = m_xDataSource.is();
880 if ( aReturn.bEnabled )
881 m_xDataSource->getPropertyValue( PROPERTY_USER ) >>= aReturn.sTitle;
882 break;
883 case SID_DB_APP_STATUS_HOSTNAME:
884 aReturn.bEnabled = m_xDataSource.is();
885 if ( aReturn.bEnabled )
887 OUString sURL;
888 m_xDataSource->getPropertyValue( PROPERTY_URL ) >>= sURL;
890 OUString sHostName, sDatabaseName;
891 sal_Int32 nPortNumber = -1;
892 m_aTypeCollection.extractHostNamePort( sURL, sDatabaseName, sHostName, nPortNumber );
893 aReturn.sTitle = sHostName;
895 break;
896 default:
897 aReturn = OGenericUnoController::GetState(_nId);
900 catch(const Exception& )
902 DBG_UNHANDLED_EXCEPTION("dbaccess");
904 return aReturn;
907 namespace
909 bool lcl_handleException_nothrow( const Reference< XModel >& _rxDocument, const Any& _rException )
911 bool bHandled = false;
913 // try handling the error with an interaction handler
914 Reference< XInteractionHandler > xHandler = ::comphelper::NamedValueCollection::getOrDefault( _rxDocument->getArgs(), u"InteractionHandler", Reference< XInteractionHandler >() );
915 if ( xHandler.is() )
917 rtl::Reference pRequest( new ::comphelper::OInteractionRequest( _rException ) );
918 rtl::Reference pApprove( new ::comphelper::OInteractionApprove );
919 pRequest->addContinuation( pApprove );
923 xHandler->handle( pRequest );
925 catch( const Exception& )
927 DBG_UNHANDLED_EXCEPTION("dbaccess");
930 bHandled = pApprove->wasSelected();
932 return bHandled;
936 void OApplicationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
938 SolarMutexGuard aSolarGuard;
939 ::osl::MutexGuard aGuard( getMutex() );
941 if ( isUserDefinedFeature( _nId ) )
943 OGenericUnoController::Execute( _nId, aArgs );
944 return;
947 if ( !getContainer() || m_bReadOnly )
948 return; // return without execution
952 switch(_nId)
954 case ID_BROWSER_CUT:
955 getContainer()->cut();
956 break;
957 case ID_BROWSER_COPY:
959 rtl::Reference<TransferableHelper> pTransfer = copyObject();
960 if ( pTransfer )
961 pTransfer->CopyToClipboard(getView());
963 break;
964 case ID_BROWSER_PASTE:
966 const TransferableDataHelper& rTransferData( getViewClipboard() );
967 ElementType eType = getContainer()->getElementType();
969 switch( eType )
971 case E_TABLE:
973 // get the selected tablename
974 std::vector< OUString > aList;
975 getSelectionElementNames( aList );
976 if ( !aList.empty() )
977 m_aTableCopyHelper.SetTableNameForAppend( *aList.begin() );
978 else
979 m_aTableCopyHelper.ResetTableNameForAppend();
981 m_aTableCopyHelper.pasteTable( rTransferData , getDatabaseName(), ensureConnection() );
983 break;
985 case E_QUERY:
986 if ( rTransferData.HasFormat(SotClipboardFormatId::DBACCESS_QUERY) )
987 paste( E_QUERY, ODataAccessObjectTransferable::extractObjectDescriptor( rTransferData ) );
988 break;
989 default:
991 std::vector< OUString> aList;
992 getSelectionElementNames(aList);
993 OUString sFolderNameToInsertInto;
994 if ( !aList.empty() )
996 Reference< XHierarchicalNameAccess > xContainer(getElements(eType),UNO_QUERY);
997 if ( xContainer.is()
998 && xContainer->hasByHierarchicalName(*aList.begin())
999 && (xContainer->getByHierarchicalName(*aList.begin()) >>= xContainer)
1000 && xContainer.is()
1002 sFolderNameToInsertInto = *aList.begin();
1004 paste( eType, OComponentTransferable::extractComponentDescriptor( rTransferData ),
1005 sFolderNameToInsertInto );
1007 break;
1010 break;
1011 case SID_DB_APP_PASTE_SPECIAL:
1013 if ( !aArgs.hasElements() )
1015 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1016 ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(getFrameWeld()));
1017 std::vector<SotClipboardFormatId> aFormatIds;
1018 getSupportedFormats(getContainer()->getElementType(),aFormatIds);
1019 for (auto const& formatId : aFormatIds)
1020 pDlg->Insert(formatId,u""_ustr);
1022 const TransferableDataHelper& rClipboard = getViewClipboard();
1023 pasteFormat(pDlg->GetFormat(rClipboard.GetTransferable()));
1025 else
1027 for (auto& arg : aArgs)
1029 if (arg.Name == "FormatStringId")
1031 sal_uInt32 nTmp;
1032 if (arg.Value >>= nTmp)
1033 pasteFormat(static_cast<SotClipboardFormatId>(nTmp));
1034 break;
1039 break;
1040 case SID_NEWDOCDIRECT:
1041 case SID_OPENDOC:
1043 Reference < XDispatchProvider > xProv( getFrame(), UNO_QUERY );
1044 if ( xProv.is() )
1046 URL aURL;
1047 OUString aTarget;
1048 if ( _nId == SID_NEWDOCDIRECT )
1050 aURL.Complete = "private:factory/sdatabase?Interactive";
1051 aTarget = "_default";
1053 else
1054 aURL.Complete = ".uno:Open";
1056 if ( m_xUrlTransformer.is() )
1057 m_xUrlTransformer->parseStrict( aURL );
1058 Reference < XDispatch > xDisp = xProv->queryDispatch( aURL, aTarget, 0 );
1059 if ( xDisp.is() )
1060 xDisp->dispatch( aURL, Sequence < PropertyValue >() );
1063 break;
1064 case ID_BROWSER_SAVEDOC:
1066 Reference< XStorable > xStore( m_xModel, UNO_QUERY_THROW );
1069 xStore->store();
1071 catch( const Exception& )
1073 lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
1076 break;
1078 case ID_BROWSER_SAVEASDOC:
1080 OUString sUrl;
1081 if ( m_xModel.is() )
1082 sUrl = m_xModel->getURL();
1084 ::sfx2::FileDialogHelper aFileDlg(
1085 ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
1086 FileDialogFlags::NONE, getFrameWeld());
1087 aFileDlg.SetContext(sfx2::FileDialogHelper::BaseSaveAs);
1088 if (!sUrl.isEmpty())
1089 aFileDlg.SetDisplayDirectory( sUrl );
1091 std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
1092 if ( pFilter )
1094 aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension());
1095 aFileDlg.SetCurrentFilter(pFilter->GetUIName());
1098 if ( aFileDlg.Execute() != ERRCODE_NONE )
1099 break;
1101 Reference<XStorable> xStore( m_xModel, UNO_QUERY_THROW );
1102 INetURLObject aURL( aFileDlg.GetPath() );
1105 xStore->storeAsURL( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Sequence< PropertyValue >() );
1107 catch( const Exception& )
1109 lcl_handleException_nothrow( m_xModel, ::cppu::getCaughtException() );
1112 /*updateTitle();*/
1113 m_bCurrentlyModified = false;
1114 InvalidateFeature(ID_BROWSER_SAVEDOC);
1115 if ( getContainer()->getElementType() == E_NONE )
1117 getContainer()->selectContainer(E_NONE);
1118 getContainer()->selectContainer(E_TABLE);
1119 // #i95524#
1120 getContainer()->Invalidate();
1121 refreshTables();
1125 break;
1126 case ID_BROWSER_SORTUP:
1127 getContainer()->sortUp();
1128 InvalidateFeature(ID_BROWSER_SORTDOWN);
1129 break;
1130 case ID_BROWSER_SORTDOWN:
1131 getContainer()->sortDown();
1132 InvalidateFeature(ID_BROWSER_SORTUP);
1133 break;
1135 case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
1136 case ID_NEW_VIEW_DESIGN_AUTO_PILOT:
1137 case ID_APP_NEW_QUERY_AUTO_PILOT:
1138 case SID_DB_FORM_NEW_PILOT:
1139 case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
1140 case SID_APP_NEW_REPORT_PRE_SEL:
1141 case SID_FORM_CREATE_REPWIZ_PRE_SEL:
1142 case ID_DOCUMENT_CREATE_REPWIZ:
1143 case SID_APP_NEW_FORM:
1144 case SID_APP_NEW_REPORT:
1145 case ID_NEW_QUERY_SQL:
1146 case ID_NEW_QUERY_DESIGN:
1147 case ID_NEW_TABLE_DESIGN:
1149 ElementType eType = E_TABLE;
1150 bool bAutoPilot = false;
1151 ::comphelper::NamedValueCollection aCreationArgs;
1153 switch( _nId )
1155 case SID_DB_FORM_NEW_PILOT:
1156 case SID_FORM_CREATE_REPWIZ_PRE_SEL:
1157 bAutoPilot = true;
1158 [[fallthrough]];
1159 case SID_APP_NEW_FORM:
1160 eType = E_FORM;
1161 break;
1162 case ID_DOCUMENT_CREATE_REPWIZ:
1163 case SID_REPORT_CREATE_REPWIZ_PRE_SEL:
1164 bAutoPilot = true;
1165 [[fallthrough]];
1166 case SID_APP_NEW_REPORT:
1167 case SID_APP_NEW_REPORT_PRE_SEL:
1168 eType = E_REPORT;
1169 break;
1170 case ID_APP_NEW_QUERY_AUTO_PILOT:
1171 bAutoPilot = true;
1172 eType = E_QUERY;
1173 break;
1174 case ID_NEW_QUERY_DESIGN:
1175 aCreationArgs.put( PROPERTY_GRAPHICAL_DESIGN, true );
1176 [[fallthrough]];
1177 case ID_NEW_QUERY_SQL:
1178 eType = E_QUERY;
1179 break;
1180 case ID_NEW_TABLE_DESIGN_AUTO_PILOT:
1181 bAutoPilot = true;
1182 [[fallthrough]];
1183 case ID_NEW_TABLE_DESIGN:
1184 break;
1185 default:
1186 OSL_FAIL("illegal switch call!");
1188 if ( bAutoPilot )
1189 getContainer()->PostUserEvent( LINK( this, OApplicationController, OnCreateWithPilot ), reinterpret_cast< void* >( eType ) );
1190 else
1192 Reference< XComponent > xDocDefinition;
1193 newElement( eType, aCreationArgs, xDocDefinition );
1196 break;
1197 case SID_APP_NEW_FOLDER:
1199 ElementType eType = getContainer()->getElementType();
1200 OUString sName = getContainer()->getQualifiedName( nullptr );
1201 insertHierarchyElement(eType,sName);
1203 break;
1204 case ID_NEW_VIEW_DESIGN:
1205 case SID_DB_NEW_VIEW_SQL:
1207 SharedConnection xConnection( ensureConnection() );
1208 if ( xConnection.is() )
1210 QueryDesigner aDesigner( getORB(), this, getFrame(), true );
1212 ::comphelper::NamedValueCollection aCreationArgs;
1213 aCreationArgs.put( PROPERTY_GRAPHICAL_DESIGN, ID_NEW_VIEW_DESIGN == _nId );
1215 const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1216 const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource, aCreationArgs );
1217 onDocumentOpened( OUString(), E_QUERY, ElementOpenMode::Design, xComponent, nullptr );
1220 break;
1221 case SID_DB_APP_DELETE:
1222 case SID_DB_APP_TABLE_DELETE:
1223 case SID_DB_APP_QUERY_DELETE:
1224 case SID_DB_APP_FORM_DELETE:
1225 case SID_DB_APP_REPORT_DELETE:
1226 deleteEntries();
1227 break;
1228 case SID_DB_APP_RENAME:
1229 case SID_DB_APP_TABLE_RENAME:
1230 case SID_DB_APP_QUERY_RENAME:
1231 case SID_DB_APP_FORM_RENAME:
1232 case SID_DB_APP_REPORT_RENAME:
1233 renameEntry();
1234 break;
1235 case SID_DB_APP_EDIT:
1236 case SID_DB_APP_EDIT_SQL_VIEW:
1237 case SID_DB_APP_TABLE_EDIT:
1238 case SID_DB_APP_QUERY_EDIT:
1239 case SID_DB_APP_FORM_EDIT:
1240 case SID_DB_APP_REPORT_EDIT:
1241 doAction( _nId, ElementOpenMode::Design );
1242 break;
1243 case SID_DB_APP_OPEN:
1244 case SID_DB_APP_TABLE_OPEN:
1245 case SID_DB_APP_QUERY_OPEN:
1246 case SID_DB_APP_FORM_OPEN:
1247 case SID_DB_APP_REPORT_OPEN:
1248 case SID_DB_APP_CONVERTTOVIEW:
1249 doAction( _nId, ElementOpenMode::Normal );
1250 break;
1251 case SID_SELECTALL:
1252 getContainer()->selectAll();
1253 InvalidateAll();
1254 break;
1255 case SID_DB_APP_DSRELDESIGN:
1257 Reference< XComponent > xRelationDesigner;
1258 if ( !m_pSubComponentManager->activateSubFrame( OUString(), SID_DB_APP_DSRELDESIGN, ElementOpenMode::Design, xRelationDesigner ) )
1260 SharedConnection xConnection( ensureConnection() );
1261 if ( xConnection.is() )
1263 RelationDesigner aDesigner( getORB(), this, m_aCurrentFrame.getFrame() );
1265 const Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1266 const Reference< XComponent > xComponent = aDesigner.createNew( xDataSource );
1267 onDocumentOpened( OUString(), SID_DB_APP_DSRELDESIGN, ElementOpenMode::Design, xComponent, nullptr );
1271 break;
1272 case SID_DB_APP_DSUSERADMIN:
1274 SharedConnection xConnection( ensureConnection() );
1275 if ( xConnection.is() )
1276 openDialog(u"com.sun.star.sdb.UserAdministrationDialog"_ustr);
1278 break;
1279 case SID_DB_APP_TABLEFILTER:
1280 // opens the table filter dialog for the selected data source
1281 openDialog( u"com.sun.star.sdb.TableFilterDialog"_ustr );
1282 askToReconnect();
1283 break;
1284 case SID_DB_APP_REFRESH_TABLES:
1285 refreshTables();
1286 break;
1287 case SID_DB_APP_DSPROPS:
1288 // opens the administration dialog for the selected data source
1289 openDialog( u"com.sun.star.sdb.DatasourceAdministrationDialog"_ustr );
1290 askToReconnect();
1291 break;
1292 case SID_DB_APP_DSADVANCED_SETTINGS:
1293 openDialog(u"com.sun.star.sdb.AdvancedDatabaseSettingsDialog"_ustr);
1294 askToReconnect();
1295 break;
1296 case SID_DB_APP_DSCONNECTION_TYPE:
1297 openDialog(u"com.sun.star.sdb.DataSourceTypeChangeDialog"_ustr);
1298 askToReconnect();
1299 break;
1300 case ID_DIRECT_SQL:
1302 SharedConnection xConnection( ensureConnection() );
1303 if ( xConnection.is() )
1304 // opens the DirectSQLDialog to execute hand made sql statements.
1305 openDialog( SERVICE_SDB_DIRECTSQLDIALOG );
1307 break;
1308 case SID_DB_APP_VIEW_TABLES:
1309 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_TABLE ) );
1310 break;
1311 case SID_DB_APP_VIEW_QUERIES:
1312 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_QUERY ) );
1313 break;
1314 case SID_DB_APP_VIEW_FORMS:
1315 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_FORM ) );
1316 break;
1317 case SID_DB_APP_VIEW_REPORTS:
1318 m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_REPORT ) );
1319 break;
1320 case SID_DB_APP_DISABLE_PREVIEW:
1321 m_ePreviewMode = PreviewMode::NONE;
1322 getContainer()->switchPreview(m_ePreviewMode);
1323 break;
1324 case SID_DB_APP_VIEW_DOCINFO_PREVIEW:
1325 m_ePreviewMode = PreviewMode::DocumentInfo;
1326 getContainer()->switchPreview(m_ePreviewMode);
1327 break;
1328 case SID_DB_APP_VIEW_DOC_PREVIEW:
1329 m_ePreviewMode = PreviewMode::Document;
1330 getContainer()->switchPreview(m_ePreviewMode);
1331 break;
1332 case SID_MAIL_SENDDOC:
1334 SfxMailModel aSendMail;
1335 if ( aSendMail.AttachDocument(getModel(), OUString()) == SfxMailModel::SEND_MAIL_OK )
1336 aSendMail.Send( getFrame() );
1338 break;
1339 case SID_DB_APP_SENDREPORTASMAIL:
1340 doAction( _nId, ElementOpenMode::Mail );
1341 break;
1344 catch( const Exception& )
1346 DBG_UNHANDLED_EXCEPTION("dbaccess");
1348 InvalidateFeature(_nId);
1351 void OApplicationController::describeSupportedFeatures()
1353 OGenericUnoController::describeSupportedFeatures();
1355 implDescribeSupportedFeature( u".uno:AddDirect"_ustr, SID_NEWDOCDIRECT, CommandGroup::APPLICATION );
1356 implDescribeSupportedFeature( u".uno:Save"_ustr, ID_BROWSER_SAVEDOC, CommandGroup::DOCUMENT );
1357 implDescribeSupportedFeature( u".uno:SaveAs"_ustr, ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
1358 implDescribeSupportedFeature( u".uno:SendMail"_ustr, SID_MAIL_SENDDOC, CommandGroup::DOCUMENT );
1359 implDescribeSupportedFeature( u".uno:DBSendReportAsMail"_ustr,SID_DB_APP_SENDREPORTASMAIL,
1360 CommandGroup::DOCUMENT );
1361 implDescribeSupportedFeature( u".uno:DBSendReportToWriter"_ustr,SID_DB_APP_SENDREPORTTOWRITER,
1362 CommandGroup::DOCUMENT );
1363 implDescribeSupportedFeature( u".uno:DBNewForm"_ustr, SID_APP_NEW_FORM, CommandGroup::INSERT );
1364 implDescribeSupportedFeature( u".uno:DBNewFolder"_ustr, SID_APP_NEW_FOLDER, CommandGroup::INSERT );
1365 implDescribeSupportedFeature( u".uno:DBNewFormAutoPilot"_ustr, SID_DB_FORM_NEW_PILOT, CommandGroup::INSERT );
1366 implDescribeSupportedFeature( u".uno:DBNewFormAutoPilotWithPreSelection"_ustr,
1367 SID_FORM_CREATE_REPWIZ_PRE_SEL,
1368 CommandGroup::APPLICATION );
1370 implDescribeSupportedFeature( u".uno:DBNewReport"_ustr, SID_APP_NEW_REPORT, CommandGroup::INSERT );
1371 implDescribeSupportedFeature( u".uno:DBNewReportAutoPilot"_ustr,
1372 ID_DOCUMENT_CREATE_REPWIZ, CommandGroup::INSERT );
1373 implDescribeSupportedFeature( u".uno:DBNewReportAutoPilotWithPreSelection"_ustr,
1374 SID_REPORT_CREATE_REPWIZ_PRE_SEL,
1375 CommandGroup::APPLICATION );
1376 implDescribeSupportedFeature( u".uno:DBNewQuery"_ustr, ID_NEW_QUERY_DESIGN, CommandGroup::INSERT );
1377 implDescribeSupportedFeature( u".uno:DBNewQuerySql"_ustr, ID_NEW_QUERY_SQL, CommandGroup::INSERT );
1378 implDescribeSupportedFeature( u".uno:DBNewQueryAutoPilot"_ustr,ID_APP_NEW_QUERY_AUTO_PILOT,
1379 CommandGroup::INSERT );
1380 implDescribeSupportedFeature( u".uno:DBNewTable"_ustr, ID_NEW_TABLE_DESIGN, CommandGroup::INSERT );
1381 implDescribeSupportedFeature( u".uno:DBNewTableAutoPilot"_ustr,ID_NEW_TABLE_DESIGN_AUTO_PILOT,
1382 CommandGroup::INSERT );
1383 implDescribeSupportedFeature( u".uno:DBNewView"_ustr, ID_NEW_VIEW_DESIGN, CommandGroup::INSERT );
1384 implDescribeSupportedFeature( u".uno:DBNewViewSQL"_ustr, SID_DB_NEW_VIEW_SQL, CommandGroup::INSERT );
1386 implDescribeSupportedFeature( u".uno:DBDelete"_ustr, SID_DB_APP_DELETE, CommandGroup::EDIT );
1387 implDescribeSupportedFeature( u".uno:Delete"_ustr, SID_DB_APP_DELETE, CommandGroup::EDIT );
1388 implDescribeSupportedFeature( u".uno:DBRename"_ustr, SID_DB_APP_RENAME, CommandGroup::EDIT );
1389 implDescribeSupportedFeature( u".uno:DBEdit"_ustr, SID_DB_APP_EDIT, CommandGroup::EDIT );
1390 implDescribeSupportedFeature( u".uno:DBEditSqlView"_ustr, SID_DB_APP_EDIT_SQL_VIEW, CommandGroup::EDIT );
1391 implDescribeSupportedFeature( u".uno:DBOpen"_ustr, SID_DB_APP_OPEN, CommandGroup::EDIT );
1393 implDescribeSupportedFeature( u".uno:DBTableDelete"_ustr, SID_DB_APP_TABLE_DELETE, CommandGroup::EDIT );
1394 implDescribeSupportedFeature( u".uno:DBTableRename"_ustr, SID_DB_APP_TABLE_RENAME, CommandGroup::EDIT );
1395 implDescribeSupportedFeature( u".uno:DBTableEdit"_ustr, SID_DB_APP_TABLE_EDIT, CommandGroup::EDIT );
1396 implDescribeSupportedFeature( u".uno:DBTableOpen"_ustr, SID_DB_APP_TABLE_OPEN, CommandGroup::EDIT );
1398 implDescribeSupportedFeature( u".uno:DBQueryDelete"_ustr, SID_DB_APP_QUERY_DELETE, CommandGroup::EDIT );
1399 implDescribeSupportedFeature( u".uno:DBQueryRename"_ustr, SID_DB_APP_QUERY_RENAME, CommandGroup::EDIT );
1400 implDescribeSupportedFeature( u".uno:DBQueryEdit"_ustr, SID_DB_APP_QUERY_EDIT, CommandGroup::EDIT );
1401 implDescribeSupportedFeature( u".uno:DBQueryOpen"_ustr, SID_DB_APP_QUERY_OPEN, CommandGroup::EDIT );
1403 implDescribeSupportedFeature( u".uno:DBFormDelete"_ustr, SID_DB_APP_FORM_DELETE, CommandGroup::EDIT );
1404 implDescribeSupportedFeature( u".uno:DBFormRename"_ustr, SID_DB_APP_FORM_RENAME, CommandGroup::EDIT );
1405 implDescribeSupportedFeature( u".uno:DBFormEdit"_ustr, SID_DB_APP_FORM_EDIT, CommandGroup::EDIT );
1406 implDescribeSupportedFeature( u".uno:DBFormOpen"_ustr, SID_DB_APP_FORM_OPEN, CommandGroup::EDIT );
1408 implDescribeSupportedFeature( u".uno:DBReportDelete"_ustr, SID_DB_APP_REPORT_DELETE, CommandGroup::EDIT );
1409 implDescribeSupportedFeature( u".uno:DBReportRename"_ustr, SID_DB_APP_REPORT_RENAME, CommandGroup::EDIT );
1410 implDescribeSupportedFeature( u".uno:DBReportEdit"_ustr, SID_DB_APP_REPORT_EDIT, CommandGroup::EDIT );
1411 implDescribeSupportedFeature( u".uno:DBReportOpen"_ustr, SID_DB_APP_REPORT_OPEN, CommandGroup::EDIT );
1413 implDescribeSupportedFeature( u".uno:SelectAll"_ustr, SID_SELECTALL, CommandGroup::EDIT );
1414 implDescribeSupportedFeature( u".uno:Undo"_ustr, ID_BROWSER_UNDO, CommandGroup::EDIT );
1416 implDescribeSupportedFeature( u".uno:Sortup"_ustr, ID_BROWSER_SORTUP, CommandGroup::VIEW );
1417 implDescribeSupportedFeature( u".uno:SortDown"_ustr, ID_BROWSER_SORTDOWN, CommandGroup::VIEW );
1418 implDescribeSupportedFeature( u".uno:DBRelationDesign"_ustr, SID_DB_APP_DSRELDESIGN, CommandGroup::APPLICATION );
1419 implDescribeSupportedFeature( u".uno:DBUserAdmin"_ustr, SID_DB_APP_DSUSERADMIN, CommandGroup::APPLICATION );
1420 implDescribeSupportedFeature( u".uno:DBTableFilter"_ustr, SID_DB_APP_TABLEFILTER, CommandGroup::APPLICATION );
1421 implDescribeSupportedFeature( u".uno:DBDSProperties"_ustr, SID_DB_APP_DSPROPS, CommandGroup::EDIT );
1422 implDescribeSupportedFeature( u".uno:DBDSConnectionType"_ustr, SID_DB_APP_DSCONNECTION_TYPE,
1423 CommandGroup::EDIT );
1424 implDescribeSupportedFeature( u".uno:DBDSAdvancedSettings"_ustr,
1425 SID_DB_APP_DSADVANCED_SETTINGS,
1426 CommandGroup::EDIT );
1427 implDescribeSupportedFeature( u".uno:PasteSpecial"_ustr, SID_DB_APP_PASTE_SPECIAL, CommandGroup::EDIT );
1428 implDescribeSupportedFeature( u".uno:DBConvertToView"_ustr, SID_DB_APP_CONVERTTOVIEW, CommandGroup::EDIT );
1429 implDescribeSupportedFeature( u".uno:DBRefreshTables"_ustr, SID_DB_APP_REFRESH_TABLES, CommandGroup::APPLICATION );
1430 implDescribeSupportedFeature( u".uno:DBDirectSQL"_ustr, ID_DIRECT_SQL, CommandGroup::APPLICATION );
1431 implDescribeSupportedFeature( u".uno:DBViewTables"_ustr, SID_DB_APP_VIEW_TABLES, CommandGroup::VIEW );
1432 implDescribeSupportedFeature( u".uno:DBViewQueries"_ustr, SID_DB_APP_VIEW_QUERIES, CommandGroup::VIEW );
1433 implDescribeSupportedFeature( u".uno:DBViewForms"_ustr, SID_DB_APP_VIEW_FORMS, CommandGroup::VIEW );
1434 implDescribeSupportedFeature( u".uno:DBViewReports"_ustr, SID_DB_APP_VIEW_REPORTS, CommandGroup::VIEW );
1435 implDescribeSupportedFeature( u".uno:DBDisablePreview"_ustr, SID_DB_APP_DISABLE_PREVIEW,CommandGroup::VIEW );
1436 implDescribeSupportedFeature( u".uno:DBShowDocInfoPreview"_ustr,
1437 SID_DB_APP_VIEW_DOCINFO_PREVIEW,
1438 CommandGroup::VIEW );
1439 implDescribeSupportedFeature( u".uno:DBShowDocPreview"_ustr, SID_DB_APP_VIEW_DOC_PREVIEW,
1440 CommandGroup::VIEW );
1442 implDescribeSupportedFeature( u".uno:OpenUrl"_ustr, SID_OPENURL, CommandGroup::APPLICATION );
1444 // this one should not appear under Tools->Customize->Keyboard
1445 implDescribeSupportedFeature( u".uno:DBNewReportWithPreSelection"_ustr,
1446 SID_APP_NEW_REPORT_PRE_SEL );
1447 implDescribeSupportedFeature( u".uno:DBDSImport"_ustr, SID_DB_APP_DSIMPORT);
1448 implDescribeSupportedFeature( u".uno:DBDSExport"_ustr, SID_DB_APP_DSEXPORT);
1449 implDescribeSupportedFeature( u".uno:DBDBAdmin"_ustr, SID_DB_APP_DBADMIN);
1451 // status info
1452 implDescribeSupportedFeature( u".uno:DBStatusType"_ustr, SID_DB_APP_STATUS_TYPE);
1453 implDescribeSupportedFeature( u".uno:DBStatusDBName"_ustr, SID_DB_APP_STATUS_DBNAME);
1454 implDescribeSupportedFeature( u".uno:DBStatusUserName"_ustr, SID_DB_APP_STATUS_USERNAME);
1455 implDescribeSupportedFeature( u".uno:DBStatusHostName"_ustr, SID_DB_APP_STATUS_HOSTNAME);
1458 OApplicationView* OApplicationController::getContainer() const
1460 return static_cast< OApplicationView* >( getView() );
1463 // css::container::XContainerListener
1464 void SAL_CALL OApplicationController::elementInserted( const ContainerEvent& _rEvent )
1466 SolarMutexGuard aSolarGuard;
1467 ::osl::MutexGuard aGuard( getMutex() );
1469 Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1470 if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
1471 return;
1473 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1474 if ( !getContainer() )
1475 return;
1477 OUString sName;
1478 _rEvent.Accessor >>= sName;
1479 ElementType eType = getElementType(xContainer);
1481 switch( eType )
1483 case E_TABLE:
1484 ensureConnection();
1485 break;
1486 case E_FORM:
1487 case E_REPORT:
1489 Reference< XContainer > xSubContainer(_rEvent.Element,UNO_QUERY);
1490 if ( xSubContainer.is() )
1491 containerFound(xSubContainer);
1493 break;
1494 default:
1495 break;
1497 getContainer()->elementAdded(eType,sName,_rEvent.Element);
1500 void SAL_CALL OApplicationController::elementRemoved( const ContainerEvent& _rEvent )
1502 SolarMutexGuard aSolarGuard;
1503 ::osl::MutexGuard aGuard( getMutex() );
1505 Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1506 if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
1507 return;
1509 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1510 OUString sName;
1511 _rEvent.Accessor >>= sName;
1512 ElementType eType = getElementType(xContainer);
1513 switch( eType )
1515 case E_TABLE:
1516 ensureConnection();
1517 break;
1518 case E_FORM:
1519 case E_REPORT:
1521 Reference<XContent> xContent(xContainer,UNO_QUERY);
1522 if ( xContent.is() )
1524 sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
1527 break;
1528 default:
1529 break;
1531 getContainer()->elementRemoved(eType,sName);
1534 void SAL_CALL OApplicationController::elementReplaced( const ContainerEvent& _rEvent )
1536 SolarMutexGuard aSolarGuard;
1537 ::osl::MutexGuard aGuard( getMutex() );
1539 Reference< XContainer > xContainer(_rEvent.Source, UNO_QUERY);
1540 if ( std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xContainer) == m_aCurrentContainers.end() )
1541 return;
1543 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1544 OUString sName;
1547 _rEvent.Accessor >>= sName;
1548 Reference<XPropertySet> xProp(_rEvent.Element,UNO_QUERY);
1550 ElementType eType = getElementType(xContainer);
1551 switch( eType )
1553 case E_TABLE:
1555 ensureConnection();
1556 if ( xProp.is() && m_xMetaData.is() )
1557 //TODO: tdf#133497 "OApplicationController::elementReplaced effectively does
1558 // nothing":
1559 (void) ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
1561 break;
1562 case E_FORM:
1563 case E_REPORT:
1565 Reference<XContent> xContent(xContainer,UNO_QUERY);
1566 if ( xContent.is() )
1568 sName = xContent->getIdentifier()->getContentIdentifier() + "/" + sName;
1571 break;
1572 default:
1573 break;
1575 // getContainer()->elementReplaced(getContainer()->getElementType(),sName,sNewName);
1577 catch( Exception& )
1579 DBG_UNHANDLED_EXCEPTION("dbaccess");
1583 namespace
1585 OUString lcl_getToolBarResource(ElementType _eType)
1587 OUString sToolbar;
1588 switch(_eType)
1590 case E_TABLE:
1591 sToolbar = "private:resource/toolbar/tableobjectbar";
1592 break;
1593 case E_QUERY:
1594 sToolbar = "private:resource/toolbar/queryobjectbar";
1595 break;
1596 case E_FORM:
1597 sToolbar = "private:resource/toolbar/formobjectbar";
1598 break;
1599 case E_REPORT:
1600 sToolbar = "private:resource/toolbar/reportobjectbar";
1601 break;
1602 case E_NONE:
1603 break;
1604 default:
1605 OSL_FAIL("Invalid ElementType!");
1606 break;
1608 return sToolbar;
1612 bool OApplicationController::onContainerSelect(ElementType _eType)
1614 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1616 if ( m_eCurrentType != _eType && _eType != E_NONE )
1618 SelectionGuard aSelGuard( *m_pSelectionNotifier );
1620 if ( _eType == E_TABLE )
1624 SharedConnection xConnection( ensureConnection() );
1625 if ( xConnection.is() && getContainer()->getDetailView() )
1627 getContainer()->getDetailView()->createTablesPage(xConnection);
1628 Reference<XTablesSupplier> xTabSup(xConnection,UNO_QUERY);
1629 if ( xTabSup.is() )
1630 addContainerListener(xTabSup->getTables());
1632 else
1634 return false;
1637 catch( const Exception& )
1639 return false;
1642 else if ( _eType == E_QUERY )
1644 // tdf#126578: retrieve connection to be able to call "Create as View"
1645 ensureConnection();
1647 Reference< XLayoutManager > xLayoutManager = getLayoutManager( getFrame() );
1648 if ( xLayoutManager.is() )
1650 OUString sToolbar = lcl_getToolBarResource(_eType);
1651 OUString sDestroyToolbar = lcl_getToolBarResource(m_eCurrentType);
1653 xLayoutManager->lock();
1654 xLayoutManager->destroyElement( sDestroyToolbar );
1655 if ( !sToolbar.isEmpty() )
1657 xLayoutManager->createElement( sToolbar );
1658 xLayoutManager->requestElement( sToolbar );
1660 xLayoutManager->unlock();
1661 xLayoutManager->doLayout();
1664 if ( _eType != E_TABLE && getContainer()->getDetailView() )
1666 Reference< XNameAccess > xContainer = getElements(_eType);
1667 addContainerListener(xContainer);
1668 getContainer()->getDetailView()->createPage(_eType,xContainer);
1671 SelectionByElementType::const_iterator pendingSelection = m_aPendingSelection.find( _eType );
1672 if ( pendingSelection != m_aPendingSelection.end() )
1674 getContainer()->selectElements( comphelper::containerToSequence(pendingSelection->second) );
1676 m_aPendingSelection.erase( pendingSelection );
1679 InvalidateAll();
1681 m_eCurrentType = _eType;
1683 return true;
1686 bool OApplicationController::onEntryDoubleClick(const weld::TreeView& rTreeView)
1688 OApplicationView* pContainer = getContainer();
1689 if (!pContainer)
1690 return false; // not handled
1692 std::unique_ptr<weld::TreeIter> xHdlEntry = rTreeView.make_iterator();
1693 if (!rTreeView.get_cursor(xHdlEntry.get()))
1694 return false;
1696 if (!pContainer->isLeaf(rTreeView, *xHdlEntry))
1697 return false; // not handled
1701 // opens a new frame with either the table or the query or report or form or view
1702 openElementWithArguments(
1703 getContainer()->getQualifiedName(xHdlEntry.get()),
1704 getContainer()->getElementType(),
1705 ElementOpenMode::Normal,
1707 ::comphelper::NamedValueCollection() );
1708 return true; // handled
1710 catch(const Exception&)
1712 DBG_UNHANDLED_EXCEPTION("dbaccess");
1715 return false; // not handled
1718 bool OApplicationController::impl_isAlterableView_nothrow( const OUString& _rTableOrViewName ) const
1720 OSL_PRECOND( m_xDataSourceConnection.is(), "OApplicationController::impl_isAlterableView_nothrow: no connection!" );
1722 bool bIsAlterableView( false );
1725 Reference< XViewsSupplier > xViewsSupp( m_xDataSourceConnection, UNO_QUERY );
1726 Reference< XNameAccess > xViews;
1727 if ( xViewsSupp.is() )
1728 xViews = xViewsSupp->getViews();
1730 Reference< XAlterView > xAsAlterableView;
1731 if ( xViews.is() && xViews->hasByName( _rTableOrViewName ) )
1732 xAsAlterableView.set( xViews->getByName( _rTableOrViewName ), UNO_QUERY );
1734 bIsAlterableView = xAsAlterableView.is();
1736 catch( const Exception& )
1738 DBG_UNHANDLED_EXCEPTION("dbaccess");
1740 return bIsAlterableView;
1743 Reference< XComponent > OApplicationController::openElementWithArguments( const OUString& _sName, ElementType _eType,
1744 ElementOpenMode _eOpenMode, sal_uInt16 _nInstigatorCommand, const ::comphelper::NamedValueCollection& _rAdditionalArguments )
1746 OSL_PRECOND( getContainer(), "OApplicationController::openElementWithArguments: no view!" );
1747 if ( !getContainer() )
1748 return nullptr;
1750 Reference< XComponent > xRet;
1751 if ( _eOpenMode == ElementOpenMode::Design )
1753 // https://bz.apache.org/ooo/show_bug.cgi?id=30382
1754 getContainer()->showPreview(nullptr);
1757 bool isStandaloneDocument = false;
1758 switch ( _eType )
1760 case E_REPORT:
1761 if ( _eOpenMode != ElementOpenMode::Design )
1763 // reports which are opened in a mode other than design are no sub components of our application
1764 // component, but standalone documents.
1765 isStandaloneDocument = true;
1767 [[fallthrough]];
1768 case E_FORM:
1770 if ( isStandaloneDocument || !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
1772 std::unique_ptr< OLinkedDocumentsAccess > aHelper = getDocumentsAccess( _eType );
1773 if ( !aHelper->isConnected() )
1774 break;
1776 Reference< XComponent > xDefinition;
1777 xRet = aHelper->open( _sName, xDefinition, _eOpenMode, _rAdditionalArguments );
1779 if ( !isStandaloneDocument )
1780 onDocumentOpened( _sName, _eType, _eOpenMode, xRet, xDefinition );
1783 break;
1785 case E_QUERY:
1786 case E_TABLE:
1788 if ( !m_pSubComponentManager->activateSubFrame( _sName, _eType, _eOpenMode, xRet ) )
1790 SharedConnection xConnection( ensureConnection() );
1791 if ( !xConnection.is() )
1792 break;
1794 std::unique_ptr< DatabaseObjectView > pDesigner;
1795 ::comphelper::NamedValueCollection aArguments( _rAdditionalArguments );
1797 Any aDataSource;
1798 if ( _eOpenMode == ElementOpenMode::Design )
1800 bool bAddViewTypeArg = false;
1802 if ( _eType == E_TABLE )
1804 if ( impl_isAlterableView_nothrow( _sName ) )
1806 pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), true ) );
1807 bAddViewTypeArg = true;
1809 else
1811 pDesigner.reset( new TableDesigner( getORB(), this, m_aCurrentFrame.getFrame() ) );
1814 else if ( _eType == E_QUERY )
1816 pDesigner.reset( new QueryDesigner( getORB(), this, m_aCurrentFrame.getFrame(), false ) );
1817 bAddViewTypeArg = true;
1819 aDataSource <<= m_xDataSource;
1821 if ( bAddViewTypeArg )
1823 const bool bQueryGraphicalMode =( _nInstigatorCommand != SID_DB_APP_EDIT_SQL_VIEW );
1824 aArguments.put( PROPERTY_GRAPHICAL_DESIGN, bQueryGraphicalMode );
1828 else
1830 pDesigner.reset( new ResultSetBrowser( getORB(), this, m_aCurrentFrame.getFrame(), _eType == E_TABLE ) );
1832 if ( !aArguments.has( PROPERTY_SHOWMENU ) )
1833 aArguments.put( PROPERTY_SHOWMENU, Any( true ) );
1835 aDataSource <<= getDatabaseName();
1838 xRet.set( pDesigner->openExisting( aDataSource, _sName, aArguments ) );
1839 onDocumentOpened( _sName, _eType, _eOpenMode, xRet, nullptr );
1842 break;
1844 default:
1845 OSL_FAIL( "OApplicationController::openElement: illegal object type!" );
1846 break;
1848 return xRet;
1851 IMPL_LINK( OApplicationController, OnSelectContainer, void*, _pType, void )
1853 ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
1854 if (getContainer())
1855 getContainer()->selectContainer(eType);
1858 IMPL_LINK( OApplicationController, OnCreateWithPilot, void*, _pType, void )
1860 ElementType eType = static_cast<ElementType>(reinterpret_cast< sal_IntPtr >( _pType ));
1861 newElementWithPilot( eType );
1864 void OApplicationController::newElementWithPilot( ElementType _eType )
1866 utl::CloseVeto aKeepDoc( getFrame() );
1867 // prevent the document being closed while the wizard is open
1869 OSL_ENSURE( getContainer(), "OApplicationController::newElementWithPilot: without a view?" );
1871 switch ( _eType )
1873 case E_REPORT:
1874 case E_FORM:
1876 std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
1877 if ( aHelper->isConnected() )
1879 sal_Int32 nCommandType = -1;
1880 const OUString sCurrentSelected( getCurrentlySelectedName( nCommandType ) );
1881 if ( E_REPORT == _eType )
1882 aHelper->newReportWithPilot( nCommandType, sCurrentSelected );
1883 else
1884 aHelper->newFormWithPilot( nCommandType, sCurrentSelected );
1887 break;
1888 case E_QUERY:
1889 case E_TABLE:
1891 std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess(_eType);
1892 if ( aHelper->isConnected() )
1894 if ( E_QUERY == _eType )
1895 aHelper->newQueryWithPilot();
1896 else
1897 aHelper->newTableWithPilot();
1900 break;
1901 case E_NONE:
1902 break;
1905 // no need for onDocumentOpened, the table wizard opens the created table by using
1906 // XDatabaseDocumentUI::loadComponent method.
1909 Reference< XComponent > OApplicationController::newElement( ElementType _eType, const ::comphelper::NamedValueCollection& i_rAdditionalArguments,
1910 Reference< XComponent >& o_rDocumentDefinition )
1912 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1914 Reference< XComponent > xComponent;
1915 o_rDocumentDefinition.clear();
1917 switch ( _eType )
1919 case E_FORM:
1920 case E_REPORT:
1922 std::unique_ptr<OLinkedDocumentsAccess> aHelper = getDocumentsAccess( _eType );
1923 if ( !aHelper->isConnected() )
1924 break;
1926 xComponent = aHelper->newDocument( _eType == E_FORM ? ID_FORM_NEW_TEXT : ID_REPORT_NEW_TEXT, i_rAdditionalArguments, o_rDocumentDefinition );
1928 break;
1930 case E_QUERY:
1931 case E_TABLE:
1933 std::unique_ptr< DatabaseObjectView > pDesigner;
1934 SharedConnection xConnection( ensureConnection() );
1935 if ( !xConnection.is() )
1936 break;
1938 if ( _eType == E_TABLE )
1940 pDesigner.reset( new TableDesigner( getORB(), this, getFrame() ) );
1942 else if ( _eType == E_QUERY )
1944 pDesigner.reset( new QueryDesigner( getORB(), this, getFrame(), false ) );
1947 Reference< XDataSource > xDataSource( m_xDataSource, UNO_QUERY );
1948 xComponent = pDesigner->createNew( xDataSource, i_rAdditionalArguments );
1950 break;
1952 default:
1953 OSL_FAIL( "OApplicationController::newElement: illegal type!" );
1954 break;
1957 if ( xComponent.is() )
1958 onDocumentOpened( OUString(), _eType, ElementOpenMode::Design, xComponent, o_rDocumentDefinition );
1960 return xComponent;
1963 void OApplicationController::addContainerListener(const Reference<XNameAccess>& _xCollection)
1967 Reference< XContainer > xCont(_xCollection, UNO_QUERY);
1968 if ( xCont.is() )
1970 // add as listener to get notified if elements are inserted or removed
1971 TContainerVector::const_iterator aFind = std::find(m_aCurrentContainers.begin(),m_aCurrentContainers.end(),xCont);
1972 if ( aFind == m_aCurrentContainers.end() )
1974 xCont->addContainerListener(this);
1975 m_aCurrentContainers.push_back(xCont);
1979 catch( const Exception& )
1981 DBG_UNHANDLED_EXCEPTION("dbaccess");
1985 void OApplicationController::renameEntry()
1987 SolarMutexGuard aSolarGuard;
1988 ::osl::MutexGuard aGuard( getMutex() );
1990 OSL_ENSURE(getContainer(),"View is NULL! -> GPF");
1991 std::vector< OUString> aList;
1992 getSelectionElementNames(aList);
1994 Reference< XNameAccess > xContainer = getElements(getContainer()->getElementType());
1995 OSL_ENSURE(aList.size() == 1,"Invalid rename call here. More than one element!");
1996 if ( aList.empty() )
1997 return;
2001 if ( xContainer.is() )
2003 std::unique_ptr< IObjectNameCheck > pNameChecker;
2004 std::unique_ptr<OSaveAsDlg> xDialog;
2006 Reference<XRename> xRename;
2007 const ElementType eType = getContainer()->getElementType();
2008 switch( eType )
2010 case E_FORM:
2011 case E_REPORT:
2013 Reference<XHierarchicalNameContainer> xHNames(xContainer, UNO_QUERY);
2014 if ( xHNames.is() )
2016 OUString sLabel;
2017 if ( eType == E_FORM )
2018 sLabel = DBA_RES(STR_FRM_LABEL);
2019 else
2020 sLabel = DBA_RES(STR_RPT_LABEL);
2022 OUString sName = *aList.begin();
2023 if ( xHNames->hasByHierarchicalName(sName) )
2025 xRename.set(xHNames->getByHierarchicalName(sName),UNO_QUERY);
2026 Reference<XChild> xChild(xRename,UNO_QUERY);
2027 if ( xChild.is() )
2029 Reference<XHierarchicalNameContainer> xParent(xChild->getParent(),UNO_QUERY);
2030 if ( xParent.is() )
2032 xHNames = std::move(xParent);
2033 Reference<XPropertySet>(xRename,UNO_QUERY_THROW)->getPropertyValue(PROPERTY_NAME) >>= sName;
2036 pNameChecker.reset( new HierarchicalNameCheck( xHNames, OUString() ) );
2037 xDialog.reset(new OSaveAsDlg(
2038 getFrameWeld(), getORB(), sName, sLabel, *pNameChecker, SADFlags::TitleRename));
2042 break;
2043 case E_TABLE:
2044 ensureConnection();
2045 if ( !getConnection().is() )
2046 break;
2047 [[fallthrough]];
2048 case E_QUERY:
2049 if ( xContainer->hasByName(*aList.begin()) )
2051 xRename.set(xContainer->getByName(*aList.begin()),UNO_QUERY);
2052 sal_Int32 nCommandType = eType == E_QUERY ? CommandType::QUERY : CommandType::TABLE;
2054 ensureConnection();
2055 pNameChecker.reset( new DynamicTableOrQueryNameCheck( getConnection(), nCommandType ) );
2056 xDialog.reset(new OSaveAsDlg(getFrameWeld(), nCommandType, getORB(), getConnection(),
2057 *aList.begin(), *pNameChecker, SADFlags::TitleRename));
2059 break;
2060 default:
2061 break;
2064 if (xRename.is() && xDialog)
2067 bool bTryAgain = true;
2068 while( bTryAgain )
2070 if (xDialog->run() == RET_OK)
2074 OUString sNewName;
2075 if ( eType == E_TABLE )
2077 OUString sName = xDialog->getName();
2078 OUString sCatalog = xDialog->getCatalog();
2079 OUString sSchema = xDialog->getSchema();
2081 sNewName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sName, false, ::dbtools::EComposeRule::InDataManipulation );
2083 else
2084 sNewName = xDialog->getName();
2086 OUString sOldName = *aList.begin();
2087 if ( eType == E_FORM || eType == E_REPORT )
2089 Reference<XContent> xContent(xRename,UNO_QUERY);
2090 if ( xContent.is() )
2092 sOldName = xContent->getIdentifier()->getContentIdentifier();
2096 xRename->rename(sNewName);
2098 if ( eType == E_TABLE )
2100 Reference<XPropertySet> xProp(xRename,UNO_QUERY);
2101 sNewName = ::dbaui::composeTableName( m_xMetaData, xProp, ::dbtools::EComposeRule::InDataManipulation, false );
2103 getContainer()->elementReplaced( eType , sOldName, sNewName );
2105 bTryAgain = false;
2107 catch(const SQLException& )
2109 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
2112 catch(const ElementExistException& e)
2114 OUString sMsg(DBA_RES(STR_NAME_ALREADY_EXISTS));
2115 showError(SQLExceptionInfo(SQLException(sMsg.replaceAll("#", e.Message), e.Context, u"S1000"_ustr, 0, Any())));
2117 catch(const Exception& )
2119 DBG_UNHANDLED_EXCEPTION("dbaccess");
2122 else
2123 bTryAgain = false;
2128 catch(const Exception& )
2130 DBG_UNHANDLED_EXCEPTION("dbaccess");
2134 void OApplicationController::onSelectionChanged()
2136 InvalidateAll();
2138 SelectionGuard aSelGuard( *m_pSelectionNotifier );
2140 OApplicationView* pView = getContainer();
2141 if ( !pView )
2142 return;
2144 if ( pView->getSelectionCount() == 1 )
2146 const ElementType eType = pView->getElementType();
2147 if ( pView->isALeafSelected() )
2149 const OUString sName = pView->getQualifiedName( nullptr /* means 'first selected' */ );
2150 showPreviewFor( eType, sName );
2155 void OApplicationController::showPreviewFor(const ElementType _eType,const OUString& _sName)
2157 if ( m_ePreviewMode == PreviewMode::NONE )
2158 return;
2160 OApplicationView* pView = getContainer();
2161 if ( !pView )
2162 return;
2166 switch( _eType )
2168 case E_FORM:
2169 case E_REPORT:
2171 Reference< XHierarchicalNameAccess > xContainer( getElements( _eType ), UNO_QUERY_THROW );
2172 Reference< XContent> xContent( xContainer->getByHierarchicalName( _sName ), UNO_QUERY_THROW );
2173 pView->showPreview( xContent );
2175 break;
2177 case E_TABLE:
2178 case E_QUERY:
2180 SharedConnection xConnection( ensureConnection() );
2181 if ( xConnection.is() )
2182 pView->showPreview( getDatabaseName(), xConnection, _sName, _eType == E_TABLE );
2184 return;
2186 default:
2187 OSL_FAIL( "OApplicationController::showPreviewFor: unexpected element type!" );
2188 break;
2191 catch( const SQLException& )
2193 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
2195 catch(const Exception& )
2197 DBG_UNHANDLED_EXCEPTION("dbaccess");
2201 IMPL_LINK_NOARG(OApplicationController, OnClipboardChanged, TransferableDataHelper*, void)
2203 OnInvalidateClipboard();
2206 void OApplicationController::OnInvalidateClipboard()
2208 InvalidateFeature(ID_BROWSER_CUT);
2209 InvalidateFeature(ID_BROWSER_COPY);
2210 InvalidateFeature(ID_BROWSER_PASTE);
2211 InvalidateFeature(SID_DB_APP_PASTE_SPECIAL);
2214 void OApplicationController::onCopyEntry()
2216 Execute(ID_BROWSER_COPY,Sequence<PropertyValue>());
2219 void OApplicationController::onPasteEntry()
2221 Execute(ID_BROWSER_PASTE,Sequence<PropertyValue>());
2224 void OApplicationController::onDeleteEntry()
2226 ElementType eType = getContainer()->getElementType();
2227 sal_uInt16 nId = 0;
2228 switch(eType)
2230 case E_TABLE:
2231 nId = SID_DB_APP_TABLE_DELETE;
2232 break;
2233 case E_QUERY:
2234 nId = SID_DB_APP_QUERY_DELETE;
2235 break;
2236 case E_FORM:
2237 nId = SID_DB_APP_FORM_DELETE;
2238 break;
2239 case E_REPORT:
2240 nId = SID_DB_APP_REPORT_DELETE;
2241 break;
2242 default:
2243 OSL_FAIL("Invalid ElementType!");
2244 break;
2246 executeChecked(nId,Sequence<PropertyValue>());
2249 OUString OApplicationController::getContextMenuResourceName() const
2251 return u"edit"_ustr;
2254 IController& OApplicationController::getCommandController()
2256 return *this;
2259 ::comphelper::OInterfaceContainerHelper2* OApplicationController::getContextMenuInterceptors()
2261 return &m_aContextMenuInterceptors;
2264 Any OApplicationController::getCurrentSelection(weld::TreeView& rControl) const
2266 Sequence< NamedDatabaseObject > aSelection;
2267 getContainer()->describeCurrentSelectionForControl(rControl, aSelection);
2268 return Any( aSelection );
2271 vcl::Window* OApplicationController::getMenuParent() const
2273 return getContainer()->getMenuParent();
2276 void OApplicationController::adjustMenuPosition(const weld::TreeView& rControl, ::Point& rPos) const
2278 getContainer()->adjustMenuPosition(rControl, rPos);
2281 bool OApplicationController::requestQuickHelp(const void* /*pUserData*/, OUString& /*rText*/) const
2283 return false;
2286 bool OApplicationController::requestDrag(const weld::TreeIter& /*rEntry*/)
2288 bool bSuccess = false;
2290 OApplicationView* pContainer = getContainer();
2291 if (pContainer && pContainer->getSelectionCount())
2295 if (getContainer()->getDetailView())
2297 TreeListBox* pTreeListBox = getContainer()->getDetailView()->getTreeWindow();
2299 ElementType eType = getContainer()->getElementType();
2300 if (eType == E_TABLE || eType == E_QUERY)
2302 ODataClipboard& rExchange = static_cast<ODataClipboard&>(pTreeListBox->GetDataTransfer());
2303 bSuccess = copySQLObject(rExchange);
2305 else
2307 svx::OComponentTransferable& rExchange = static_cast<svx::OComponentTransferable&>(pTreeListBox->GetDataTransfer());
2308 bSuccess = copyDocObject(rExchange);
2312 catch(const Exception& )
2314 DBG_UNHANDLED_EXCEPTION("dbaccess");
2318 return bSuccess;
2321 sal_Int8 OApplicationController::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
2323 sal_Int8 nActionAskedFor = _rEvt.mnAction;
2324 // check if we're a table or query container
2325 OApplicationView* pView = getContainer();
2326 if ( !pView || isDataSourceReadOnly() )
2327 return DND_ACTION_NONE;
2329 ElementType eType = pView->getElementType();
2330 if ( eType == E_NONE || (eType == E_TABLE && isConnectionReadOnly()) )
2331 return DND_ACTION_NONE;
2333 // check for the concrete type
2334 if(std::any_of(_rFlavors.begin(),_rFlavors.end(),TAppSupportedSotFunctor(eType)))
2335 return DND_ACTION_COPY;
2337 if ( eType != E_FORM && eType != E_REPORT )
2338 return DND_ACTION_NONE;
2340 sal_Int8 nAction = OComponentTransferable::canExtractComponentDescriptor(_rFlavors,eType == E_FORM) ? DND_ACTION_COPY : DND_ACTION_NONE;
2341 if ( nAction == DND_ACTION_NONE )
2342 return DND_ACTION_NONE;
2344 auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
2345 if (xHitEntry)
2347 OUString sName = pView->getQualifiedName(xHitEntry.get());
2348 if ( !sName.isEmpty() )
2350 Reference< XHierarchicalNameAccess > xContainer(getElements(pView->getElementType()),UNO_QUERY);
2351 if ( xContainer.is() && xContainer->hasByHierarchicalName(sName) )
2353 Reference< XHierarchicalNameAccess > xHitObject(xContainer->getByHierarchicalName(sName),UNO_QUERY);
2354 if ( xHitObject.is() )
2355 nAction = nActionAskedFor & DND_ACTION_COPYMOVE;
2357 else
2358 nAction = DND_ACTION_NONE;
2361 return nAction;
2364 sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt )
2366 OApplicationView* pView = getContainer();
2367 if ( !pView || pView->getElementType() == E_NONE )
2369 OSL_FAIL("OApplicationController::executeDrop: what the hell did queryDrop do?");
2370 // queryDrop should not have allowed us to reach this situation...
2371 return DND_ACTION_NONE;
2374 // a TransferableDataHelper for accessing the dropped data
2375 TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
2377 // reset the data of the previous async drop (if any)
2378 if ( m_nAsyncDrop )
2379 Application::RemoveUserEvent(m_nAsyncDrop);
2381 m_nAsyncDrop = nullptr;
2382 m_aAsyncDrop.aDroppedData.clear();
2383 m_aAsyncDrop.nType = pView->getElementType();
2384 m_aAsyncDrop.nAction = _rEvt.mnAction;
2385 m_aAsyncDrop.bError = false;
2386 m_aAsyncDrop.bHtml = false;
2387 m_aAsyncDrop.aUrl.clear();
2389 // loop through the available formats and see what we can do...
2390 // first we have to check if it is our own format, if not we have to copy the stream :-(
2391 if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(aDroppedData.GetDataFlavorExVector()) )
2393 m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData);
2395 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2396 m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2397 return DND_ACTION_COPY;
2399 else if ( OComponentTransferable::canExtractComponentDescriptor(aDroppedData.GetDataFlavorExVector(),m_aAsyncDrop.nType == E_FORM) )
2401 m_aAsyncDrop.aDroppedData = OComponentTransferable::extractComponentDescriptor(aDroppedData);
2402 auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
2403 if ( xHitEntry )
2404 m_aAsyncDrop.aUrl = pView->getQualifiedName(xHitEntry.get());
2406 sal_Int8 nAction = _rEvt.mnAction;
2407 Reference<XContent> xContent;
2408 m_aAsyncDrop.aDroppedData[DataAccessDescriptorProperty::Component] >>= xContent;
2409 if ( xContent.is() )
2411 OUString sName = xContent->getIdentifier()->getContentIdentifier();
2412 sName = sName.copy(sName.indexOf('/') + 1);
2413 if ( m_aAsyncDrop.aUrl.getLength() >= sName.getLength() && m_aAsyncDrop.aUrl.startsWith(sName) )
2415 m_aAsyncDrop.aDroppedData.clear();
2416 return DND_ACTION_NONE;
2419 // check if move is allowed, if another object with the same name exists only copy is allowed
2420 Reference< XHierarchicalNameAccess > xContainer(getElements(m_aAsyncDrop.nType),UNO_QUERY);
2421 Reference<XNameAccess> xNameAccess(xContainer,UNO_QUERY);
2423 if ( !m_aAsyncDrop.aUrl.isEmpty() && xContainer.is() && xContainer->hasByHierarchicalName(m_aAsyncDrop.aUrl) )
2424 xNameAccess.set(xContainer->getByHierarchicalName(m_aAsyncDrop.aUrl),UNO_QUERY);
2426 if ( xNameAccess.is() )
2428 Reference<XPropertySet> xProp(xContent,UNO_QUERY);
2429 if ( xProp.is() )
2431 xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
2432 if ( xNameAccess.is() && xNameAccess->hasByName(sName) )
2433 nAction &= ~DND_ACTION_MOVE;
2435 else
2436 nAction &= ~DND_ACTION_MOVE;
2439 if ( nAction != DND_ACTION_NONE )
2441 m_aAsyncDrop.nAction = nAction;
2442 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2443 m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2445 else
2446 m_aAsyncDrop.aDroppedData.clear();
2447 return nAction;
2449 else
2451 SharedConnection xConnection( ensureConnection() );
2452 if ( xConnection.is() && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xConnection ) )
2454 // asynchron because we some dialogs and we aren't allowed to show them while in D&D
2455 m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop));
2456 return DND_ACTION_COPY;
2460 return DND_ACTION_NONE;
2463 Reference< XModel > SAL_CALL OApplicationController::getModel()
2465 return m_xModel;
2468 void OApplicationController::onAttachedFrame()
2470 sal_Int32 nConnectedControllers( 0 );
2473 Reference< XModel2 > xModel( m_xModel, UNO_QUERY_THROW );
2474 Reference< XEnumeration > xEnumControllers( xModel->getControllers(), UNO_SET_THROW );
2475 while ( xEnumControllers->hasMoreElements() )
2477 Reference< XController > xController( xEnumControllers->nextElement(), UNO_QUERY_THROW );
2478 ++nConnectedControllers;
2481 catch( const Exception& )
2483 DBG_UNHANDLED_EXCEPTION("dbaccess");
2486 if ( nConnectedControllers > 1 )
2487 { // we are not the first connected controller, there were already others
2488 return;
2491 OnFirstControllerConnected();
2494 void OApplicationController::OnFirstControllerConnected()
2496 if ( !m_xModel.is() )
2498 OSL_FAIL( "OApplicationController::OnFirstControllerConnected: too late!" );
2501 // if we have forms or reports which contain macros/scripts, then show a warning
2502 // which suggests the user to migrate them to the database document
2503 Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
2504 if ( xDocumentScripts.is() )
2506 // no need to show this warning, obviously the document supports embedding scripts
2507 // into itself, so there are no "old-style" forms/reports which have macros/scripts
2508 // themselves
2509 return;
2514 // If the migration just happened, but was not successful, the document is reloaded.
2515 // In this case, we should not show the warning, again.
2516 if ( ::comphelper::NamedValueCollection::getOrDefault( m_xModel->getArgs(), u"SuppressMigrationWarning", false ) )
2517 return;
2519 // also, if the document is read-only, then no migration is possible, and the
2520 // respective menu entry is hidden. So, don't show the warning in this case, too.
2521 if ( Reference< XStorable >( m_xModel, UNO_QUERY_THROW )->isReadonly() )
2522 return;
2524 SQLException aDetail(DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS_DETAIL), {}, {}, 0, {});
2525 SQLWarning aWarning(DBA_RES(STR_SUB_DOCS_WITH_SCRIPTS), {}, {}, 0, css::uno::Any(aDetail));
2527 Reference< XExecutableDialog > xDialog = ErrorMessageDialog::create( getORB(), u""_ustr, nullptr, Any( aWarning ) );
2528 xDialog->execute();
2530 catch( const Exception& )
2532 DBG_UNHANDLED_EXCEPTION("dbaccess");
2536 void SAL_CALL OApplicationController::attachFrame( const Reference< XFrame > & i_rxFrame )
2538 SolarMutexGuard aSolarGuard; // avoid deadlock in XModel calls
2539 ::osl::MutexGuard aGuard( getMutex() );
2541 OGenericUnoController::attachFrame( i_rxFrame );
2542 if ( getFrame().is() )
2543 onAttachedFrame();
2546 sal_Bool SAL_CALL OApplicationController::attachModel(const Reference< XModel > & _rxModel)
2548 ::osl::MutexGuard aGuard( getMutex() );
2549 const Reference< XOfficeDatabaseDocument > xOfficeDoc( _rxModel, UNO_QUERY );
2550 const Reference< XModifiable > xDocModify( _rxModel, UNO_QUERY );
2551 if ( ( !xOfficeDoc.is() || !xDocModify.is() ) && _rxModel.is() )
2553 OSL_FAIL( "OApplicationController::attachModel: invalid model!" );
2554 return false;
2557 if ( m_xModel.is() && ( m_xModel != _rxModel ) && ( _rxModel.is() ) )
2559 OSL_ENSURE( false, "OApplicationController::attachModel: missing implementation: setting a new model while we have another one!" );
2560 // we'd need to completely update our view here, close sub components, and the like
2561 return false;
2564 const OUString aPropertyNames[] =
2566 PROPERTY_URL, PROPERTY_USER
2569 // disconnect from old model
2572 if ( m_xDataSource.is() )
2574 for (const auto & aPropertyName : aPropertyNames)
2576 m_xDataSource->removePropertyChangeListener( aPropertyName, this );
2580 Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY );
2581 if ( xBroadcaster.is() )
2582 xBroadcaster->removeModifyListener( this );
2584 catch( const Exception& )
2586 DBG_UNHANDLED_EXCEPTION("dbaccess");
2589 m_xModel = _rxModel;
2590 m_xDataSource.set( xOfficeDoc.is() ? xOfficeDoc->getDataSource() : Reference< XDataSource >(), UNO_QUERY );
2592 // connect to new model
2595 if ( m_xDataSource.is() )
2597 for (const auto & aPropertyName : aPropertyNames)
2599 m_xDataSource->addPropertyChangeListener( aPropertyName, this );
2603 Reference< XModifyBroadcaster > xBroadcaster( m_xModel, UNO_QUERY_THROW );
2604 xBroadcaster->addModifyListener( this );
2607 catch( const Exception& )
2609 DBG_UNHANDLED_EXCEPTION("dbaccess");
2612 // initial preview mode
2613 if ( !m_xDataSource )
2614 return true;
2618 // to get the 'modified' for the data source
2619 ::comphelper::NamedValueCollection aLayoutInfo( m_xDataSource->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) );
2620 if ( aLayoutInfo.has( INFO_PREVIEW ) )
2622 const sal_Int32 nPreviewMode( aLayoutInfo.getOrDefault( INFO_PREVIEW, sal_Int32(0) ) );
2623 m_ePreviewMode = static_cast< PreviewMode >( nPreviewMode );
2624 if ( getView() )
2625 getContainer()->switchPreview( m_ePreviewMode );
2628 catch( const Exception& )
2630 DBG_UNHANDLED_EXCEPTION("dbaccess");
2633 return true;
2636 void OApplicationController::containerFound( const Reference< XContainer >& _xContainer)
2640 if ( _xContainer.is() )
2642 m_aCurrentContainers.push_back(_xContainer);
2643 _xContainer->addContainerListener(this);
2646 catch(const Exception&)
2648 DBG_UNHANDLED_EXCEPTION("dbaccess");
2652 OUString OApplicationController::getCurrentlySelectedName(sal_Int32& _rnCommandType) const
2654 _rnCommandType = ( (getContainer()->getElementType() == E_QUERY)
2655 ? CommandType::QUERY : ( (getContainer()->getElementType() == E_TABLE) ? CommandType::TABLE : -1 ));
2657 OUString sName;
2658 if ( _rnCommandType != -1 )
2662 sName = getContainer()->getQualifiedName( nullptr );
2663 OSL_ENSURE( !sName.isEmpty(), "OApplicationController::getCurrentlySelectedName: no name given!" );
2665 catch( const Exception& )
2667 DBG_UNHANDLED_EXCEPTION("dbaccess");
2670 return sName;
2673 void SAL_CALL OApplicationController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
2675 m_pSelectionNotifier->addListener( Listener );
2678 void SAL_CALL OApplicationController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener )
2680 m_pSelectionNotifier->removeListener( Listener );
2683 sal_Bool SAL_CALL OApplicationController::select( const Any& _aSelection )
2685 SolarMutexGuard aSolarGuard;
2686 ::osl::MutexGuard aGuard( getMutex() );
2687 Sequence< OUString> aSelection;
2688 if ( !_aSelection.hasValue() || !getView() )
2690 getContainer()->selectElements(aSelection);
2691 return true;
2694 // BEGIN compatibility
2695 Sequence< NamedValue > aCurrentSelection;
2696 if ( (_aSelection >>= aCurrentSelection) && aCurrentSelection.hasElements() )
2698 ElementType eType = E_NONE;
2699 for (auto& item : aCurrentSelection)
2701 if (item.Name == "Type")
2703 sal_Int32 nType = 0;
2704 item.Value >>= nType;
2705 if ( nType < DatabaseObject::TABLE || nType > DatabaseObject::REPORT )
2706 throw IllegalArgumentException();
2707 eType = static_cast< ElementType >( nType );
2709 else if (item.Name == "Selection")
2710 item.Value >>= aSelection;
2713 m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running
2714 getContainer()->selectContainer(eType);
2715 getContainer()->selectElements(aSelection);
2716 return true;
2718 // END compatibility
2720 Sequence< NamedDatabaseObject > aSelectedObjects;
2721 if ( !( _aSelection >>= aSelectedObjects ) )
2723 aSelectedObjects.realloc( 1 );
2724 if ( !( _aSelection >>= aSelectedObjects.getArray()[0] ) )
2725 throw IllegalArgumentException();
2728 SelectionByElementType aSelectedElements;
2729 ElementType eSelectedCategory = E_NONE;
2730 for (sal_Int32 i = 0; i < aSelectedObjects.getLength(); ++i)
2732 switch (aSelectedObjects[i].Type)
2734 case DatabaseObject::TABLE:
2735 case DatabaseObjectContainer::SCHEMA:
2736 case DatabaseObjectContainer::CATALOG:
2737 aSelectedElements[E_TABLE].push_back(aSelectedObjects[i].Name);
2738 break;
2739 case DatabaseObject::QUERY:
2740 aSelectedElements[E_QUERY].push_back(aSelectedObjects[i].Name);
2741 break;
2742 case DatabaseObject::FORM:
2743 case DatabaseObjectContainer::FORMS_FOLDER:
2744 aSelectedElements[E_FORM].push_back(aSelectedObjects[i].Name);
2745 break;
2746 case DatabaseObject::REPORT:
2747 case DatabaseObjectContainer::REPORTS_FOLDER:
2748 aSelectedElements[E_REPORT].push_back(aSelectedObjects[i].Name);
2749 break;
2750 case DatabaseObjectContainer::TABLES:
2751 case DatabaseObjectContainer::QUERIES:
2752 case DatabaseObjectContainer::FORMS:
2753 case DatabaseObjectContainer::REPORTS:
2754 if ( eSelectedCategory != E_NONE )
2755 throw IllegalArgumentException(DBA_RES(RID_STR_NO_DIFF_CAT), *this, i);
2756 eSelectedCategory =
2757 ( aSelectedObjects[i].Type == DatabaseObjectContainer::TABLES ) ? E_TABLE
2758 : ( aSelectedObjects[i].Type == DatabaseObjectContainer::QUERIES ) ? E_QUERY
2759 : ( aSelectedObjects[i].Type == DatabaseObjectContainer::FORMS ) ? E_FORM
2760 : ( aSelectedObjects[i].Type == DatabaseObjectContainer::REPORTS ) ? E_REPORT
2761 : E_NONE;
2762 break;
2764 default:
2765 case DatabaseObjectContainer::DATA_SOURCE:
2767 OUString sMessage(
2768 DBA_RES(RID_STR_UNSUPPORTED_OBJECT_TYPE).
2769 replaceFirst("$type$", OUString::number(aSelectedObjects[i].Type)));
2770 throw IllegalArgumentException(sMessage, *this, i);
2774 for (auto const& selectedElement : aSelectedElements)
2776 if ( selectedElement.first == m_eCurrentType )
2778 getContainer()->selectElements( comphelper::containerToSequence(selectedElement.second) );
2780 else
2782 m_aPendingSelection[ selectedElement.first ] = selectedElement.second;
2786 m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running
2787 getContainer()->selectContainer( eSelectedCategory );
2789 return true;
2792 Any SAL_CALL OApplicationController::getSelection( )
2794 SolarMutexGuard aSolarGuard;
2795 ::osl::MutexGuard aGuard( getMutex() );
2797 Sequence< NamedDatabaseObject > aCurrentSelection;
2798 const ElementType eType( getContainer()->getElementType() );
2799 if ( eType != E_NONE )
2801 getContainer()->describeCurrentSelectionForType( eType, aCurrentSelection );
2802 if ( !aCurrentSelection.hasElements() )
2803 { // if no objects are selected, add an entry to the sequence which describes the overall category
2804 // which is selected currently
2805 aCurrentSelection.realloc(1);
2806 auto pCurrentSelection = aCurrentSelection.getArray();
2807 pCurrentSelection[0].Name = getDatabaseName();
2808 switch ( eType )
2810 case E_TABLE: pCurrentSelection[0].Type = DatabaseObjectContainer::TABLES; break;
2811 case E_QUERY: pCurrentSelection[0].Type = DatabaseObjectContainer::QUERIES; break;
2812 case E_FORM: pCurrentSelection[0].Type = DatabaseObjectContainer::FORMS; break;
2813 case E_REPORT: pCurrentSelection[0].Type = DatabaseObjectContainer::REPORTS; break;
2814 default:
2815 OSL_FAIL( "OApplicationController::getSelection: unexpected current element type!" );
2816 break;
2820 return Any( aCurrentSelection );
2823 } // namespace dbaui
2825 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */