Avoid potential negative array index access to cached text.
[LibreOffice.git] / extensions / source / bibliography / framectr.cxx
blob758c8b3484c296b96f7be13d4194b21a1c7d9ebc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/types.hxx>
21 #include <comphelper/propertyvalue.hxx>
22 #include <comphelper/sequence.hxx>
23 #include "framectr.hxx"
24 #include "datman.hxx"
25 #include <toolkit/helper/vclunohelper.hxx>
26 #include "bibconfig.hxx"
27 #include <cppuhelper/implbase.hxx>
28 #include <utility>
29 #include <vcl/event.hxx>
30 #include <vcl/svapp.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <com/sun/star/awt/XTextComponent.hpp>
33 #include <com/sun/star/awt/XVclWindowPeer.hpp>
34 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
35 #include <com/sun/star/form/runtime/XFormController.hpp>
36 #include <com/sun/star/beans/PropertyValue.hpp>
37 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
38 #include <com/sun/star/sdbcx/Privilege.hpp>
39 #include <com/sun/star/sdbc/XResultSetUpdate.hpp>
40 #include <com/sun/star/sdb/FilterDialog.hpp>
41 #include <com/sun/star/sdb/RowChangeAction.hpp>
42 #include <com/sun/star/frame/CommandGroup.hpp>
43 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
44 #include <comphelper/multicontainer2.hxx>
45 #include <cppuhelper/supportsservice.hxx>
46 #include <sot/exchange.hxx>
47 #include <sot/formats.hxx>
48 #include <comphelper/diagnose_ex.hxx>
49 #include <vcl/weld.hxx>
50 #include <osl/mutex.hxx>
52 #include <unordered_map>
54 using namespace osl;
55 using namespace cppu;
56 using namespace com::sun::star::sdbc;
57 using namespace com::sun::star::frame;
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star;
61 namespace {
63 struct DispatchInfo
65 const char* pCommand;
66 sal_Int16 nGroupId;
67 bool bActiveConnection;
70 struct CacheDispatchInfo
72 sal_Int16 nGroupId;
73 bool bActiveConnection;
78 // Attention: commands must be sorted by command groups. Implementation is dependent
79 // on this!!
80 const DispatchInfo SupportedCommandsArray[] =
82 { ".uno:Undo" , frame::CommandGroup::EDIT , false },
83 { ".uno:Cut" , frame::CommandGroup::EDIT , false },
84 { ".uno:Copy" , frame::CommandGroup::EDIT , false },
85 { ".uno:Paste" , frame::CommandGroup::EDIT , false },
86 { ".uno:SelectAll" , frame::CommandGroup::EDIT , false },
87 { ".uno:CloseDoc" , frame::CommandGroup::DOCUMENT , false },
88 { ".uno:StatusBarVisible" , frame::CommandGroup::VIEW , false },
89 { ".uno:AvailableToolbars" , frame::CommandGroup::VIEW , false },
90 { ".uno:Bib/standardFilter" , frame::CommandGroup::DATA , true },
91 { ".uno:Bib/DeleteRecord" , frame::CommandGroup::DATA , true },
92 { ".uno:Bib/InsertRecord" , frame::CommandGroup::DATA , true },
93 { ".uno:Bib/query" , frame::CommandGroup::DATA , true },
94 { ".uno:Bib/autoFilter" , frame::CommandGroup::DATA , true },
95 { ".uno:Bib/source" , frame::CommandGroup::DATA , true },
96 { ".uno:Bib/removeFilter" , frame::CommandGroup::DATA , true },
97 { ".uno:Bib/sdbsource" , frame::CommandGroup::DATA , true },
98 { ".uno:Bib/Mapping" , frame::CommandGroup::DATA , true },
101 typedef std::unordered_map< OUString, CacheDispatchInfo > CmdToInfoCache;
103 static const CmdToInfoCache& GetCommandToInfoCache()
105 static CmdToInfoCache aCmdToInfoCache = []() {
106 CmdToInfoCache aCache;
107 for (const auto& command : SupportedCommandsArray)
109 OUString aCommand(OUString::createFromAscii(command.pCommand));
111 CacheDispatchInfo aDispatchInfo;
112 aDispatchInfo.nGroupId = command.nGroupId;
113 aDispatchInfo.bActiveConnection = command.bActiveConnection;
114 aCache.emplace(aCommand, aDispatchInfo);
116 return aCache;
117 }();
119 return aCmdToInfoCache;
123 class BibFrameCtrl_Impl : public cppu::WeakImplHelper < XFrameActionListener >
125 public:
126 Mutex aMutex;
127 comphelper::OMultiTypeInterfaceContainerHelper2 aLC;
129 BibFrameController_Impl* pController;
131 BibFrameCtrl_Impl()
132 : aLC( aMutex )
133 , pController(nullptr)
136 virtual void SAL_CALL frameAction(const FrameActionEvent& aEvent) override;
137 virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
140 void BibFrameCtrl_Impl::frameAction(const FrameActionEvent& )
144 void BibFrameCtrl_Impl::disposing( const lang::EventObject& /*Source*/ )
146 ::SolarMutexGuard aGuard;
147 if ( pController )
148 pController->getFrame()->removeFrameActionListener( this );
151 BibFrameController_Impl::BibFrameController_Impl( uno::Reference< awt::XWindow > xComponent,
152 BibDataManager* pDataManager)
153 :m_xWindow(std::move( xComponent ))
154 ,m_xDatMan( pDataManager )
156 m_bDisposing = false;
157 m_xImpl = new BibFrameCtrl_Impl;
158 m_xImpl->pController = this;
161 BibFrameController_Impl::~BibFrameController_Impl()
163 m_xImpl->pController = nullptr;
164 m_xDatMan.clear();
167 OUString SAL_CALL BibFrameController_Impl::getImplementationName()
169 return "com.sun.star.comp.extensions.Bibliography";
172 sal_Bool SAL_CALL BibFrameController_Impl::supportsService( const OUString& sServiceName )
174 return cppu::supportsService( this, sServiceName );
177 css::uno::Sequence< OUString > SAL_CALL BibFrameController_Impl::getSupportedServiceNames()
179 // return only top level services ...
180 // base services are included there and should be asked by uno-rtti.
181 return { "com.sun.star.frame.Bibliography" };
184 void BibFrameController_Impl::attachFrame( const uno::Reference< XFrame > & xArg )
186 m_xFrame = xArg;
187 m_xFrame->addFrameActionListener( m_xImpl );
190 sal_Bool BibFrameController_Impl::attachModel( const uno::Reference< XModel > & /*xModel*/ )
192 return false;
195 sal_Bool BibFrameController_Impl::suspend( sal_Bool bSuspend )
197 if ( bSuspend )
198 getFrame()->removeFrameActionListener( m_xImpl );
199 else
200 getFrame()->addFrameActionListener( m_xImpl );
201 return true;
204 uno::Any BibFrameController_Impl::getViewData()
206 return uno::Any();
209 void BibFrameController_Impl::restoreViewData( const uno::Any& /*Value*/ )
213 uno::Reference< XFrame > BibFrameController_Impl::getFrame()
215 return m_xFrame;
218 uno::Reference< XModel > BibFrameController_Impl::getModel()
220 return uno::Reference< XModel > ();
223 void BibFrameController_Impl::dispose()
225 m_bDisposing = true;
226 lang::EventObject aObject;
227 uno::Reference< XFrame > xFrame = getFrame();
229 if (xFrame.is())
230 xFrame->removeFrameActionListener( m_xImpl );
231 m_xFrame.clear();
233 aObject.Source = static_cast<XController*>(this);
234 m_xImpl->aLC.disposeAndClear(aObject);
235 m_xDatMan.clear();
236 m_aStatusListeners.clear();
237 m_xLastQueriedFocusWin.clear();
238 m_xWindow.clear();
239 m_xImpl.clear();
242 void BibFrameController_Impl::addEventListener( const uno::Reference< lang::XEventListener > & aListener )
244 m_xImpl->aLC.addInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
247 void BibFrameController_Impl::removeEventListener( const uno::Reference< lang::XEventListener > & aListener )
249 m_xImpl->aLC.removeInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
252 uno::Reference< frame::XDispatch > BibFrameController_Impl::queryDispatch( const util::URL& aURL, const OUString& /*aTarget*/, sal_Int32 /*nSearchFlags*/ )
254 if ( !m_bDisposing )
256 const CmdToInfoCache& rCmdCache = GetCommandToInfoCache();
257 CmdToInfoCache::const_iterator pIter = rCmdCache.find( aURL.Complete );
258 if ( pIter != rCmdCache.end() )
260 if (( m_xDatMan->HasActiveConnection() ) ||
261 ( !pIter->second.bActiveConnection ))
262 return static_cast<frame::XDispatch*>(this);
266 return uno::Reference< frame::XDispatch > ();
269 uno::Sequence<uno::Reference< XDispatch > > BibFrameController_Impl::queryDispatches( const uno::Sequence<DispatchDescriptor>& aDescripts )
271 uno::Sequence< uno::Reference< XDispatch > > aDispatches( aDescripts.getLength() );
272 auto aDispatchesRange = asNonConstRange(aDispatches);
273 for ( sal_Int32 i=0; i<aDescripts.getLength(); ++i )
274 aDispatchesRange[i] = queryDispatch( aDescripts[i].FeatureURL, aDescripts[i].FrameName, aDescripts[i].SearchFlags );
275 return aDispatches;
278 uno::Sequence< ::sal_Int16 > SAL_CALL BibFrameController_Impl::getSupportedCommandGroups()
280 uno::Sequence< ::sal_Int16 > aDispatchInfo{ frame::CommandGroup::EDIT,
281 frame::CommandGroup::DOCUMENT,
282 frame::CommandGroup::DATA,
283 frame::CommandGroup::VIEW };
285 return aDispatchInfo;
288 uno::Sequence< frame::DispatchInformation > SAL_CALL BibFrameController_Impl::getConfigurableDispatchInformation( ::sal_Int16 nCommandGroup )
290 const CmdToInfoCache& rCmdCache = GetCommandToInfoCache();
292 frame::DispatchInformation aDispatchInfo;
293 std::vector< frame::DispatchInformation > aDispatchInfoVector;
295 if (( nCommandGroup == frame::CommandGroup::EDIT ) ||
296 ( nCommandGroup == frame::CommandGroup::DOCUMENT ) ||
297 ( nCommandGroup == frame::CommandGroup::DATA ) ||
298 ( nCommandGroup == frame::CommandGroup::VIEW ))
300 bool bGroupFound = false;
301 for (auto const& item : rCmdCache)
303 if ( item.second.nGroupId == nCommandGroup )
305 bGroupFound = true;
306 aDispatchInfo.Command = item.first;
307 aDispatchInfo.GroupId = item.second.nGroupId;
308 aDispatchInfoVector.push_back( aDispatchInfo );
310 else if ( bGroupFound )
311 break;
315 return comphelper::containerToSequence( aDispatchInfoVector );
318 static bool canInsertRecords(const Reference< beans::XPropertySet>& _rxCursorSet)
320 sal_Int32 nPriv = 0;
321 _rxCursorSet->getPropertyValue("Privileges") >>= nPriv;
322 return _rxCursorSet.is() && (nPriv & sdbcx::Privilege::INSERT) != 0;
325 bool BibFrameController_Impl::SaveModified(const Reference< form::runtime::XFormController>& xController)
327 if (!xController.is())
328 return false;
330 Reference< XResultSetUpdate> _xCursor(xController->getModel(), UNO_QUERY);
332 if (!_xCursor.is())
333 return false;
335 Reference< beans::XPropertySet> _xSet(_xCursor, UNO_QUERY);
336 if (!_xSet.is())
337 return false;
339 // need to save?
340 bool bIsNew = ::comphelper::getBOOL(_xSet->getPropertyValue("IsNew"));
341 bool bIsModified = ::comphelper::getBOOL(_xSet->getPropertyValue("IsModified"));
342 bool bResult = !bIsModified;
343 if (bIsModified)
347 if (bIsNew)
348 _xCursor->insertRow();
349 else
350 _xCursor->updateRow();
351 bResult = true;
353 catch(const Exception&)
355 TOOLS_WARN_EXCEPTION("extensions.biblio", "");
358 return bResult;
361 static vcl::Window* lcl_GetFocusChild( vcl::Window const * pParent )
363 sal_uInt16 nChildren = pParent->GetChildCount();
364 for( sal_uInt16 nChild = 0; nChild < nChildren; ++nChild)
366 vcl::Window* pChild = pParent->GetChild( nChild );
367 if(pChild->HasFocus())
368 return pChild;
369 vcl::Window* pSubChild = lcl_GetFocusChild( pChild );
370 if(pSubChild)
371 return pSubChild;
373 return nullptr;
376 //class XDispatch
377 void BibFrameController_Impl::dispatch(const util::URL& _rURL, const uno::Sequence< beans::PropertyValue >& aArgs)
379 if ( m_bDisposing )
380 return;
382 ::SolarMutexGuard aGuard;
383 weld::Window* pParent = Application::GetFrameWeld(m_xWindow);
384 weld::WaitObject aWaitObject(pParent);
386 OUString aCommand( _rURL.Path);
387 if(aCommand == "Bib/Mapping")
389 m_xDatMan->CreateMappingDialog(pParent);
391 else if(aCommand == "Bib/source")
393 ChangeDataSource(aArgs);
395 else if(aCommand == "Bib/sdbsource")
397 OUString aURL = m_xDatMan->CreateDBChangeDialog(pParent);
398 if(!aURL.isEmpty())
402 uno::Sequence< beans::PropertyValue > aNewDataSource
404 comphelper::makePropertyValue( {}, OUString() ),
405 comphelper::makePropertyValue( {}, aURL )
407 ChangeDataSource(aNewDataSource);
409 catch(const Exception&)
411 TOOLS_WARN_EXCEPTION("extensions.biblio",
412 "Exception caught while changing the data source");
416 else if(aCommand == "Bib/autoFilter")
418 sal_uInt16 nCount = m_aStatusListeners.size();
419 for ( sal_uInt16 n=0; n<nCount; n++ )
421 BibStatusDispatch *pObj = m_aStatusListeners[n].get();
422 if ( pObj->aURL.Path == "Bib/removeFilter" )
424 FeatureStateEvent aEvent;
425 aEvent.FeatureURL = pObj->aURL;
426 aEvent.IsEnabled = true;
427 aEvent.Requery = false;
428 aEvent.Source = static_cast<XDispatch *>(this);
429 pObj->xListener->statusChanged( aEvent );
430 //break; because there are more than one
434 const beans::PropertyValue* pPropertyValue = aArgs.getConstArray();
435 uno::Any aValue=pPropertyValue[0].Value;
436 OUString aQuery;
437 aValue >>= aQuery;
439 aValue=pPropertyValue[1].Value;
440 OUString aQueryField;
441 aValue >>= aQueryField;
442 BibConfig* pConfig = BibModul::GetConfig();
443 pConfig->setQueryField(aQueryField);
444 m_xDatMan->startQueryWith(aQuery);
446 else if(aCommand == "Bib/standardFilter")
450 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
452 // create the dialog object
453 uno::Reference< ui::dialogs::XExecutableDialog > xDialog = sdb::FilterDialog::createWithQuery(xContext, m_xDatMan->getParser(),
454 Reference<sdbc::XRowSet>(m_xDatMan->getForm(), uno::UNO_QUERY_THROW), m_xWindow);
455 // execute it
456 if ( xDialog->execute( ) )
458 // the dialog has been executed successfully, and the filter on the query composer
459 // has been changed
460 OUString sNewFilter = m_xDatMan->getParser()->getFilter();
461 m_xDatMan->setFilter( sNewFilter );
464 catch( const uno::Exception& )
466 TOOLS_WARN_EXCEPTION( "extensions.biblio", "BibFrameController_Impl::dispatch" );
469 sal_uInt16 nCount = m_aStatusListeners.size();
470 for ( sal_uInt16 n=0; n<nCount; n++ )
472 BibStatusDispatch *pObj = m_aStatusListeners[n].get();
473 if ( pObj->aURL.Path == "Bib/removeFilter" && m_xDatMan->getParser().is())
475 FeatureStateEvent aEvent;
476 aEvent.FeatureURL = pObj->aURL;
477 aEvent.IsEnabled = !m_xDatMan->getParser()->getFilter().isEmpty();
478 aEvent.Requery = false;
479 aEvent.Source = static_cast<XDispatch *>(this);
480 pObj->xListener->statusChanged( aEvent );
484 else if(aCommand == "Bib/removeFilter")
486 RemoveFilter();
488 else if( _rURL.Complete == ".uno:CloseDoc" || aCommand == "CloseDoc" )
490 Application::PostUserEvent( LINK( this, BibFrameController_Impl,
491 DisposeHdl ) );
494 else if(aCommand == "Bib/InsertRecord")
496 Reference<form::runtime::XFormController > xFormCtrl = m_xDatMan->GetFormController();
497 if(SaveModified(xFormCtrl))
501 Reference< sdbc::XResultSet > xCursor( m_xDatMan->getForm(), UNO_QUERY );
502 xCursor->last();
504 Reference< XResultSetUpdate > xUpdateCursor( m_xDatMan->getForm(), UNO_QUERY );
505 xUpdateCursor->moveToInsertRow();
507 catch(const Exception&)
509 TOOLS_WARN_EXCEPTION("extensions.biblio",
510 "Exception in last() or moveToInsertRow()");
514 else if(aCommand == "Bib/DeleteRecord")
516 Reference< css::sdbc::XResultSet > xCursor(m_xDatMan->getForm(), UNO_QUERY);
517 Reference< XResultSetUpdate > xUpdateCursor(xCursor, UNO_QUERY);
518 Reference< beans::XPropertySet > xSet(m_xDatMan->getForm(), UNO_QUERY);
519 bool bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue("IsNew"));
520 if(!bIsNew)
522 sal_uInt32 nCount = 0;
523 xSet->getPropertyValue("RowCount") >>= nCount;
524 // determine next position
525 bool bSuccess = false;
526 bool bLeft = false;
527 bool bRight = false;
530 bLeft = xCursor->isLast() && nCount > 1;
531 bRight= !xCursor->isLast();
532 // ask for confirmation
533 Reference< form::XConfirmDeleteListener > xConfirm(m_xDatMan->GetFormController(),UNO_QUERY);
534 if (xConfirm.is())
536 sdb::RowChangeEvent aEvent;
537 aEvent.Source.set(xCursor, UNO_QUERY);
538 aEvent.Action = sdb::RowChangeAction::DELETE;
539 aEvent.Rows = 1;
540 bSuccess = xConfirm->confirmDelete(aEvent);
543 // delete it
544 if (bSuccess)
545 xUpdateCursor->deleteRow();
547 catch(const Exception&)
549 bSuccess = false;
551 if (bSuccess)
553 if (bLeft || bRight)
554 xCursor->relative(bRight ? 1 : -1);
555 else
557 bool bCanInsert = canInsertRecords(xSet);
558 // can another entry be inserted?
561 if (bCanInsert)
562 xUpdateCursor->moveToInsertRow();
563 else
564 // move data entry to reset state
565 xCursor->first();
567 catch(const Exception&)
569 TOOLS_WARN_EXCEPTION("extensions.biblio",
570 "DeleteRecord: exception caught!");
576 else if(aCommand == "Cut")
578 vcl::Window* pChild = m_xLastQueriedFocusWin.get();
579 if(pChild)
581 KeyEvent aEvent( 0, KeyFuncType::CUT );
582 pChild->KeyInput( aEvent );
585 else if(aCommand == "Copy")
587 vcl::Window* pChild = m_xLastQueriedFocusWin.get();
588 if(pChild)
590 KeyEvent aEvent( 0, KeyFuncType::COPY );
591 pChild->KeyInput( aEvent );
594 else if(aCommand == "Paste")
596 vcl::Window* pChild = m_xLastQueriedFocusWin.get();
597 if(pChild)
599 KeyEvent aEvent( 0, KeyFuncType::PASTE );
600 pChild->KeyInput( aEvent );
604 IMPL_LINK_NOARG( BibFrameController_Impl, DisposeHdl, void*, void )
606 if (m_xFrame.is())
607 m_xFrame->dispose();
610 void BibFrameController_Impl::addStatusListener(
611 const uno::Reference< frame::XStatusListener > & aListener,
612 const util::URL& aURL)
614 BibConfig* pConfig = BibModul::GetConfig();
615 // create a new Reference and insert into listener array
616 m_aStatusListeners.push_back( std::make_unique<BibStatusDispatch>( aURL, aListener ) );
618 // send first status synchronously
619 FeatureStateEvent aEvent;
620 aEvent.FeatureURL = aURL;
621 aEvent.Requery = false;
622 aEvent.Source = static_cast<XDispatch *>(this);
623 if ( aURL.Path == "StatusBarVisible" )
625 aEvent.IsEnabled = false;
626 aEvent.State <<= false;
628 else if ( aURL.Path == "Bib/hierarchical" )
630 aEvent.IsEnabled = true;
631 aEvent.State <<= OUString();
633 else if(aURL.Path == "Bib/MenuFilter")
635 aEvent.IsEnabled = true;
636 aEvent.FeatureDescriptor=m_xDatMan->getQueryField();
638 aEvent.State <<= m_xDatMan->getQueryFields();
641 else if ( aURL.Path == "Bib/source")
643 aEvent.IsEnabled = true;
644 aEvent.FeatureDescriptor=m_xDatMan->getActiveDataTable();
646 aEvent.State <<= m_xDatMan->getDataSources();
648 else if( aURL.Path == "Bib/sdbsource" ||
649 aURL.Path == "Bib/Mapping" ||
650 aURL.Path == "Bib/autoFilter" ||
651 aURL.Path == "Bib/standardFilter" )
653 aEvent.IsEnabled = true;
655 else if(aURL.Path == "Bib/query")
657 aEvent.IsEnabled = true;
658 aEvent.State <<= pConfig->getQueryText();
660 else if (aURL.Path == "Bib/removeFilter" )
662 OUString aFilterStr=m_xDatMan->getFilter();
663 aEvent.IsEnabled = !aFilterStr.isEmpty();
665 else if(aURL.Path == "Cut")
667 m_xLastQueriedFocusWin = lcl_GetFocusChild( VCLUnoHelper::GetWindow( m_xWindow ) );
668 if (m_xLastQueriedFocusWin)
670 Reference<css::awt::XTextComponent> xEdit(m_xLastQueriedFocusWin->GetComponentInterface(), css::uno::UNO_QUERY);
671 aEvent.IsEnabled = xEdit && xEdit->isEditable() && !xEdit->getSelectedText().isEmpty();
674 if(aURL.Path == "Copy")
676 m_xLastQueriedFocusWin = lcl_GetFocusChild( VCLUnoHelper::GetWindow( m_xWindow ) );
677 if (m_xLastQueriedFocusWin)
679 Reference<css::awt::XTextComponent> xEdit(m_xLastQueriedFocusWin->GetComponentInterface(), css::uno::UNO_QUERY);
680 aEvent.IsEnabled = xEdit && !xEdit->getSelectedText().isEmpty();
683 else if(aURL.Path == "Paste" )
685 aEvent.IsEnabled = false;
686 m_xLastQueriedFocusWin = lcl_GetFocusChild( VCLUnoHelper::GetWindow( m_xWindow ) );
687 if (m_xLastQueriedFocusWin)
689 Reference<css::awt::XTextComponent> xEdit(m_xLastQueriedFocusWin->GetComponentInterface(), css::uno::UNO_QUERY);
690 if (xEdit && !xEdit->isEditable())
692 uno::Reference< datatransfer::clipboard::XClipboard > xClip = m_xLastQueriedFocusWin->GetClipboard();
693 if(xClip.is())
695 uno::Reference< datatransfer::XTransferable > xDataObj;
699 SolarMutexReleaser aReleaser;
700 xDataObj = xClip->getContents();
702 catch( const uno::Exception& )
706 if ( xDataObj.is() )
708 datatransfer::DataFlavor aFlavor;
709 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
712 uno::Any aData = xDataObj->getTransferData( aFlavor );
713 OUString aText;
714 aData >>= aText;
715 aEvent.IsEnabled = !aText.isEmpty();
717 catch( const uno::Exception& )
725 else if(aURL.Path == "Bib/DeleteRecord")
727 Reference< beans::XPropertySet > xSet(m_xDatMan->getForm(), UNO_QUERY);
728 bool bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue("IsNew"));
729 if(!bIsNew)
731 sal_uInt32 nCount = 0;
732 xSet->getPropertyValue("RowCount") >>= nCount;
733 aEvent.IsEnabled = nCount > 0;
736 else if (aURL.Path == "Bib/InsertRecord")
738 Reference< beans::XPropertySet > xSet(m_xDatMan->getForm(), UNO_QUERY);
739 aEvent.IsEnabled = canInsertRecords(xSet);
741 aListener->statusChanged( aEvent );
744 void BibFrameController_Impl::removeStatusListener(
745 const uno::Reference< frame::XStatusListener > & aObject, const util::URL& aURL)
747 // search listener array for given listener
748 // for checking equality always "cast" to XInterface
749 if ( m_bDisposing )
750 return;
752 sal_uInt16 nCount = m_aStatusListeners.size();
753 for ( sal_uInt16 n=0; n<nCount; n++ )
755 BibStatusDispatch *pObj = m_aStatusListeners[n].get();
756 bool bFlag=pObj->xListener.is();
757 if (!bFlag || (pObj->xListener == aObject &&
758 ( aURL.Complete.isEmpty() || pObj->aURL.Path == aURL.Path )))
760 m_aStatusListeners.erase( m_aStatusListeners.begin() + n );
761 break;
766 void BibFrameController_Impl::RemoveFilter()
768 OUString aQuery;
769 m_xDatMan->startQueryWith(aQuery);
771 sal_uInt16 nCount = m_aStatusListeners.size();
773 bool bRemoveFilter=false;
774 bool bQueryText=false;
776 for ( sal_uInt16 n=0; n<nCount; n++ )
778 BibStatusDispatch *pObj = m_aStatusListeners[n].get();
779 if ( pObj->aURL.Path == "Bib/removeFilter" )
781 FeatureStateEvent aEvent;
782 aEvent.FeatureURL = pObj->aURL;
783 aEvent.IsEnabled = false;
784 aEvent.Requery = false;
785 aEvent.Source = static_cast<XDispatch *>(this);
786 pObj->xListener->statusChanged( aEvent );
787 bRemoveFilter=true;
789 else if(pObj->aURL.Path == "Bib/query")
791 FeatureStateEvent aEvent;
792 aEvent.FeatureURL = pObj->aURL;
793 aEvent.IsEnabled = true;
794 aEvent.Requery = false;
795 aEvent.Source = static_cast<XDispatch *>(this);
796 aEvent.State <<= aQuery;
797 pObj->xListener->statusChanged( aEvent );
798 bQueryText=true;
801 if(bRemoveFilter && bQueryText)
802 break;
807 void BibFrameController_Impl::ChangeDataSource(const uno::Sequence< beans::PropertyValue >& aArgs)
809 const beans::PropertyValue* pPropertyValue = aArgs.getConstArray();
810 uno::Any aValue=pPropertyValue[0].Value;
811 OUString aDBTableName;
812 aValue >>= aDBTableName;
815 if(aArgs.getLength() > 1)
817 uno::Any aDB = pPropertyValue[1].Value;
818 OUString aURL;
819 aDB >>= aURL;
820 m_xDatMan->setActiveDataSource(aURL);
821 aDBTableName = m_xDatMan->getActiveDataTable();
823 else
825 Reference<css::form::XLoadable> xLoadable(m_xDatMan);
826 xLoadable->unload();
827 m_xDatMan->setActiveDataTable(aDBTableName);
828 m_xDatMan->updateGridModel();
829 xLoadable->load();
833 sal_uInt16 nCount = m_aStatusListeners.size();
835 bool bMenuFilter=false;
836 bool bQueryText=false;
837 for ( sal_uInt16 n=0; n<nCount; n++ )
839 BibStatusDispatch *pObj = m_aStatusListeners[n].get();
840 if (pObj->aURL.Path == "Bib/MenuFilter")
842 FeatureStateEvent aEvent;
843 aEvent.FeatureURL = pObj->aURL;
844 aEvent.IsEnabled = true;
845 aEvent.Requery = false;
846 aEvent.Source = static_cast<XDispatch *>(this);
847 aEvent.FeatureDescriptor=m_xDatMan->getQueryField();
849 uno::Sequence<OUString> aStringSeq=m_xDatMan->getQueryFields();
850 aEvent.State <<= aStringSeq;
852 pObj->xListener->statusChanged( aEvent );
853 bMenuFilter=true;
855 else if (pObj->aURL.Path == "Bib/query")
857 FeatureStateEvent aEvent;
858 aEvent.FeatureURL = pObj->aURL;
859 aEvent.IsEnabled = true;
860 aEvent.Requery = false;
861 aEvent.Source = static_cast<XDispatch *>(this);
862 BibConfig* pConfig = BibModul::GetConfig();
863 aEvent.State <<= pConfig->getQueryText();
864 pObj->xListener->statusChanged( aEvent );
865 bQueryText=true;
868 if (bMenuFilter && bQueryText)
869 break;
874 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */