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