xref: /trunk/main/dbaccess/source/ui/browser/exsrcbrw.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #ifndef _SBA_EXTCTRLR_HXX
32 #include "exsrcbrw.hxx"
33 #endif
34 #ifndef _COM_SUN_STAR_FORM_FORMCOMPONENTTYPE_HPP_
35 #include <com/sun/star/form/FormComponentType.hpp>
36 #endif
37 #ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
38 #include <com/sun/star/util/XURLTransformer.hpp>
39 #endif
40 #ifndef _COM_SUN_STAR_FORM_XGRIDCOLUMNFACTORY_HPP_
41 #include <com/sun/star/form/XGridColumnFactory.hpp>
42 #endif
43 #ifndef _COM_SUN_STAR_FORM_XLOADABLE_HPP_
44 #include <com/sun/star/form/XLoadable.hpp>
45 #endif
46 #ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
47 #include <com/sun/star/frame/FrameSearchFlag.hpp>
48 #endif
49 #ifndef _SBA_FORMADAPTER_HXX
50 #include "formadapter.hxx"
51 #endif
52 #ifndef _COMPHELPER_PROCESSFACTORY_HXX_
53 #include <comphelper/processfactory.hxx>
54 #endif
55 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
56 #include "dbustrings.hrc"
57 #endif
58 #ifndef _DBU_REGHELPER_HXX_
59 #include "dbu_reghelper.hxx"
60 #endif
61 #ifndef TOOLS_DIAGNOSE_EX_H
62 #include <tools/diagnose_ex.h>
63 #endif
64 
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::sdb;
67 using namespace ::com::sun::star::sdbc;
68 using namespace ::com::sun::star::sdbcx;
69 using namespace ::com::sun::star::beans;
70 using namespace ::com::sun::star::container;
71 using namespace ::com::sun::star::lang;
72 using namespace ::com::sun::star::form;
73 using namespace ::com::sun::star::frame;
74 using namespace dbaui;
75 
76 //==============================================================================
77 //= SbaExternalSourceBrowser
78 //==============================================================================
79 extern "C" void SAL_CALL createRegistryInfo_OFormGridView()
80 {
81     static OMultiInstanceAutoRegistration< SbaExternalSourceBrowser > aAutoRegistration;
82 }
83 //------------------------------------------------------------------------------
84 Any SAL_CALL SbaExternalSourceBrowser::queryInterface(const Type& _rType) throw (RuntimeException)
85 {
86     Any aRet = SbaXDataBrowserController::queryInterface(_rType);
87     if(!aRet.hasValue())
88         aRet = ::cppu::queryInterface(_rType,
89                                 (::com::sun::star::util::XModifyBroadcaster*)this,
90                                 (::com::sun::star::form::XLoadListener*)this);
91 
92     return aRet;
93 }
94 DBG_NAME(SbaExternalSourceBrowser)
95 //------------------------------------------------------------------------------
96 SbaExternalSourceBrowser::SbaExternalSourceBrowser(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rM)
97     :SbaXDataBrowserController(_rM)
98     ,m_aModifyListeners(getMutex())
99     ,m_pDataSourceImpl(NULL)
100     ,m_bInQueryDispatch( sal_False )
101 {
102     DBG_CTOR(SbaExternalSourceBrowser,NULL);
103 
104 }
105 
106 //------------------------------------------------------------------------------
107 SbaExternalSourceBrowser::~SbaExternalSourceBrowser()
108 {
109 
110     DBG_DTOR(SbaExternalSourceBrowser,NULL);
111 }
112 
113 //-------------------------------------------------------------------------
114 ::comphelper::StringSequence SAL_CALL SbaExternalSourceBrowser::getSupportedServiceNames() throw(RuntimeException)
115 {
116     return getSupportedServiceNames_Static();
117 }
118 // -------------------------------------------------------------------------
119 ::rtl::OUString SbaExternalSourceBrowser::getImplementationName_Static() throw(RuntimeException)
120 {
121     return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.OFormGridView"));
122 }
123 //-------------------------------------------------------------------------
124 ::comphelper::StringSequence SbaExternalSourceBrowser::getSupportedServiceNames_Static() throw(RuntimeException)
125 {
126     ::comphelper::StringSequence aSupported(1);
127     aSupported.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.FormGridView"));
128     return aSupported;
129 }
130 //-------------------------------------------------------------------------
131 Reference< XInterface > SAL_CALL SbaExternalSourceBrowser::Create(const Reference<XMultiServiceFactory >& _rxFactory)
132 {
133     return *(new SbaExternalSourceBrowser(_rxFactory));
134 }
135 //-------------------------------------------------------------------------
136 ::rtl::OUString SAL_CALL SbaExternalSourceBrowser::getImplementationName() throw(RuntimeException)
137 {
138     return getImplementationName_Static();
139 }
140 //------------------------------------------------------------------------------
141 Reference< XRowSet >  SbaExternalSourceBrowser::CreateForm()
142 {
143     m_pDataSourceImpl = new SbaXFormAdapter();
144     return m_pDataSourceImpl;
145 }
146 
147 //------------------------------------------------------------------------------
148 sal_Bool SbaExternalSourceBrowser::InitializeForm(const Reference< XPropertySet > & /*i_formProperties*/)
149 {
150     return sal_True;
151 }
152 
153 //------------------------------------------------------------------
154 sal_Bool SbaExternalSourceBrowser::LoadForm()
155 {
156     // as we don't have a main form (yet), we have nothing to do
157     // we don't call FormLoaded, because this expects a working data source
158     return sal_True;
159 }
160 
161 
162 //------------------------------------------------------------------
163 void SbaExternalSourceBrowser::modified(const ::com::sun::star::lang::EventObject& aEvent) throw( RuntimeException )
164 {
165     SbaXDataBrowserController::modified(aEvent);
166 
167     // multiplex this event to all my listeners
168     ::com::sun::star::lang::EventObject aEvt(*this);
169     ::cppu::OInterfaceIteratorHelper aIt(m_aModifyListeners);
170     while (aIt.hasMoreElements())
171         ((::com::sun::star::util::XModifyListener*)aIt.next())->modified(aEvt);
172 }
173 
174 //------------------------------------------------------------------
175 void SAL_CALL SbaExternalSourceBrowser::dispatch(const ::com::sun::star::util::URL& aURL, const Sequence< ::com::sun::star::beans::PropertyValue>& aArgs) throw(::com::sun::star::uno::RuntimeException)
176 {
177     const ::com::sun::star::beans::PropertyValue* pArguments = aArgs.getConstArray();
178     if (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AddGridColumn")))
179     {
180         // search the argument describing the column to create
181         ::rtl::OUString sControlType;
182         sal_Int32 nControlPos = -1;
183         Sequence< ::com::sun::star::beans::PropertyValue> aControlProps;
184         sal_uInt16 i;
185         for ( i = 0; i < aArgs.getLength(); ++i, ++pArguments )
186         {
187             if (pArguments->Name.equals(::rtl::OUString::createFromAscii("ColumnType")))
188             {
189                 sal_Bool bCorrectType = pArguments->Value.getValueType().equals(::getCppuType((const ::rtl::OUString*)0));
190                 OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnType\" !");
191                 if (bCorrectType)
192                     sControlType = ::comphelper::getString(pArguments->Value);
193             }
194             else if (pArguments->Name.equals(::rtl::OUString::createFromAscii("ColumnPosition")))
195             {
196                 sal_Bool bCorrectType = pArguments->Value.getValueType().equals(::getCppuType((const sal_Int16*)0));
197                 OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnPosition\" !");
198                 if (bCorrectType)
199                     nControlPos = ::comphelper::getINT16(pArguments->Value);
200             }
201             else if (pArguments->Name.equals(::rtl::OUString::createFromAscii("ColumnProperties")))
202             {
203                 sal_Bool bCorrectType = pArguments->Value.getValueType().equals(::getCppuType((const Sequence< ::com::sun::star::beans::PropertyValue>*)0));
204                 OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnProperties\" !");
205                 if (bCorrectType)
206                     aControlProps = *(Sequence< ::com::sun::star::beans::PropertyValue>*)pArguments->Value.getValue();
207             }
208             else
209                 OSL_ENSURE(sal_False, ((ByteString("SbaExternalSourceBrowser::dispatch(AddGridColumn) : unknown argument (") += ByteString((const sal_Unicode*)pArguments->Name, gsl_getSystemTextEncoding()).GetBuffer()) += ") !").GetBuffer());
210         }
211         if (!sControlType.getLength())
212         {
213             OSL_ENSURE(sal_False, "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnType) !");
214             sControlType = ::rtl::OUString::createFromAscii("TextField");
215         }
216         OSL_ENSURE(aControlProps.getLength(), "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnProperties) !");
217 
218         // create the col
219         Reference< ::com::sun::star::form::XGridColumnFactory >  xColFactory(getControlModel(), UNO_QUERY);
220         Reference< ::com::sun::star::beans::XPropertySet >  xNewCol = xColFactory->createColumn(sControlType);
221         Reference< XPropertySetInfo > xNewColProperties;
222         if (xNewCol.is())
223             xNewColProperties = xNewCol->getPropertySetInfo();
224         // set it's properties
225         if (xNewColProperties.is())
226         {
227             const ::com::sun::star::beans::PropertyValue* pControlProps = aControlProps.getConstArray();
228             for (i=0; i<aControlProps.getLength(); ++i, ++pControlProps)
229             {
230                 try
231                 {
232                     if (xNewColProperties->hasPropertyByName(pControlProps->Name))
233                         xNewCol->setPropertyValue(pControlProps->Name, pControlProps->Value);
234                 }
235                 catch(Exception&)
236                 {
237                     OSL_ENSURE(sal_False,
238                         (   ByteString("SbaExternalSourceBrowser::dispatch : could not set a column property (")
239                         +=  ByteString(pControlProps->Name.getStr(), (sal_uInt16)pControlProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US)
240                         +=  ByteString(")!")).GetBuffer());
241                 }
242             }
243         }
244 
245         // correct the position
246         Reference< ::com::sun::star::container::XIndexContainer >  xColContainer(getControlModel(), UNO_QUERY);
247 
248         if (nControlPos > xColContainer->getCount())
249             nControlPos = xColContainer->getCount();
250         if (nControlPos < 0)
251             nControlPos = 0;
252 
253         // append the column
254         xColContainer->insertByIndex(nControlPos, makeAny(xNewCol));
255     }
256     else if (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/ClearView")))
257     {
258         ClearView();
259     }
260     else if (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AttachToForm")))
261     {
262         if (!m_pDataSourceImpl)
263             return;
264 
265         Reference< XRowSet >  xMasterForm;
266         // search the arguments for he master form
267         for (sal_uInt16 i=0; i<aArgs.getLength(); ++i, ++pArguments)
268         {
269             if ((pArguments->Name.equals(::rtl::OUString::createFromAscii("MasterForm"))) && (pArguments->Value.getValueTypeClass() == TypeClass_INTERFACE))
270             {
271                 xMasterForm = Reference< XRowSet > (*(Reference< XInterface > *)pArguments->Value.getValue(), UNO_QUERY);
272                 break;
273             }
274         }
275         if (!xMasterForm.is())
276         {
277             OSL_ENSURE(sal_False, "SbaExternalSourceBrowser::dispatch(FormSlots/AttachToForm) : please specify a form to attach to as argument !");
278             return;
279         }
280 
281         Attach(xMasterForm);
282     }
283     else
284         SbaXDataBrowserController::dispatch(aURL, aArgs);
285 }
286 
287 //------------------------------------------------------------------
288 Reference< ::com::sun::star::frame::XDispatch >  SAL_CALL SbaExternalSourceBrowser::queryDispatch(const ::com::sun::star::util::URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException )
289 {
290     Reference< ::com::sun::star::frame::XDispatch >  xReturn;
291     if (m_bInQueryDispatch)
292         return xReturn;
293 
294     m_bInQueryDispatch = sal_True;
295 
296     if  (   (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AttachToForm")))
297             // attach a new external form
298         ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AddGridColumn")))
299             // add a column to the grid
300         ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/ClearView")))
301             // clear the grid
302         )
303         xReturn = (::com::sun::star::frame::XDispatch*)this;
304 
305     if  (   !xReturn.is()
306         &&  (   (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToFirst")))
307             ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToPrev")))
308             ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToNext")))
309             ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToLast")))
310             ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToNew")))
311             ||  (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/undoRecord")))
312             )
313         )
314     {
315         OSL_ENSURE(aURL.Mark.getLength() == 0, "SbaExternalSourceBrowser::queryDispatch : the ::com::sun::star::util::URL shouldn't have a mark !");
316         ::com::sun::star::util::URL aNewUrl = aURL;
317 
318         // split the ::com::sun::star::util::URL
319         OSL_ENSURE( m_xUrlTransformer.is(), "SbaExternalSourceBrowser::queryDispatch : could not create an URLTransformer !" );
320         if ( m_xUrlTransformer.is() )
321             m_xUrlTransformer->parseStrict( aNewUrl );
322 
323         // set a new mark
324         aNewUrl.Mark = ::rtl::OUString::createFromAscii("DB/FormGridView");
325             // this controller is instantiated when somebody dispatches the ".component:DB/FormGridView" in any
326             // frame, so we use "FormGridView" as mark that a dispatch request came from this view
327 
328         if (m_xUrlTransformer.is())
329             m_xUrlTransformer->assemble(aNewUrl);
330 
331         Reference< XDispatchProvider >  xFrameDispatcher( getFrame(), UNO_QUERY );
332         if (xFrameDispatcher.is())
333             xReturn = xFrameDispatcher->queryDispatch(aNewUrl, aTargetFrameName, FrameSearchFlag::PARENT);
334 
335     }
336 
337     if (!xReturn.is())
338         xReturn = SbaXDataBrowserController::queryDispatch(aURL, aTargetFrameName, nSearchFlags);
339 
340     m_bInQueryDispatch = sal_False;
341     return xReturn;
342 }
343 
344 //------------------------------------------------------------------
345 void SAL_CALL SbaExternalSourceBrowser::disposing()
346 {
347     // say our modify listeners goodbye
348     ::com::sun::star::lang::EventObject aEvt;
349     aEvt.Source = (XWeak*) this;
350     m_aModifyListeners.disposeAndClear(aEvt);
351 
352     stopListening();
353 
354     SbaXDataBrowserController::disposing();
355 }
356 
357 //------------------------------------------------------------------
358 void SAL_CALL SbaExternalSourceBrowser::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener > & aListener) throw( RuntimeException )
359 {
360     m_aModifyListeners.addInterface(aListener);
361 }
362 
363 //------------------------------------------------------------------
364 void SAL_CALL SbaExternalSourceBrowser::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener > & aListener) throw( RuntimeException )
365 {
366     m_aModifyListeners.removeInterface(aListener);
367 }
368 
369 //------------------------------------------------------------------
370 void SAL_CALL SbaExternalSourceBrowser::unloading(const ::com::sun::star::lang::EventObject& aEvent) throw( RuntimeException )
371 {
372     if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == aEvent.Source))
373     {
374         ClearView();
375     }
376 
377     SbaXDataBrowserController::unloading(aEvent);
378 }
379 
380 //------------------------------------------------------------------
381 void SbaExternalSourceBrowser::Attach(const Reference< XRowSet > & xMaster)
382 {
383     Any aOldPos;
384     sal_Bool bWasInsertRow = sal_False;
385     sal_Bool bBeforeFirst   = sal_True;
386     sal_Bool bAfterLast     = sal_True;
387     Reference< XResultSet > xResultSet(xMaster, UNO_QUERY);
388     Reference< XRowLocate > xCursor(xMaster, UNO_QUERY);
389     Reference< XPropertySet > xMasterProps(xMaster, UNO_QUERY);
390 
391     try
392     {
393         // switch the control to design mode
394         if (getBrowserView() && getBrowserView()->getGridControl().is())
395             getBrowserView()->getGridControl()->setDesignMode(sal_True);
396 
397         // the grid will move the form's cursor to the first record, but we want the form to remain unchanged
398         // restore the old position
399         if (xCursor.is() && xResultSet.is())
400         {
401             bBeforeFirst = xResultSet->isBeforeFirst();
402             bAfterLast   = xResultSet->isAfterLast();
403             if(!bBeforeFirst && !bAfterLast)
404                 aOldPos = xCursor->getBookmark();
405         }
406 
407         if (xMasterProps.is())
408             xMasterProps->getPropertyValue(PROPERTY_ISNEW) >>= bWasInsertRow;
409     }
410     catch( const Exception& )
411     {
412         DBG_UNHANDLED_EXCEPTION();
413     }
414 
415     onStartLoading( Reference< XLoadable >( xMaster, UNO_QUERY ) );
416 
417     stopListening();
418     m_pDataSourceImpl->AttachForm(xMaster);
419     startListening();
420 
421     if (xMaster.is())
422     {
423         // at this point we have to reset the formatter for the new form
424         initFormatter();
425         // assume that the master form is already loaded
426 #if OSL_DEBUG_LEVEL > 0
427         {
428             Reference< XLoadable > xLoadable( xMaster, UNO_QUERY );
429             OSL_ENSURE( xLoadable.is() && xLoadable->isLoaded(), "SbaExternalSourceBrowser::Attach: master is not loaded!" );
430         }
431 #endif
432 
433         LoadFinished(sal_True);
434 
435         Reference< XResultSetUpdate >  xUpdate(xMaster, UNO_QUERY);
436         try
437         {
438             if (bWasInsertRow && xUpdate.is())
439                 xUpdate->moveToInsertRow();
440             else if (xCursor.is() && aOldPos.hasValue())
441                 xCursor->moveToBookmark(aOldPos);
442             else if(bBeforeFirst && xResultSet.is())
443                 xResultSet->beforeFirst();
444             else if(bAfterLast && xResultSet.is())
445                 xResultSet->afterLast();
446         }
447         catch(Exception&)
448         {
449             OSL_ENSURE(sal_False, "SbaExternalSourceBrowser::Attach : couldn't restore the cursor position !");
450         }
451 
452     }
453 }
454 
455 //------------------------------------------------------------------
456 void SbaExternalSourceBrowser::ClearView()
457 {
458     // set a new (empty) datasource
459     Attach(Reference< XRowSet > ());
460 
461 
462     // clear all cols in the grid
463     Reference< ::com::sun::star::container::XIndexContainer >  xColContainer(getControlModel(), UNO_QUERY);
464     while (xColContainer->getCount() > 0)
465         xColContainer->removeByIndex(0);
466 }
467 
468 //------------------------------------------------------------------
469 void SAL_CALL SbaExternalSourceBrowser::disposing(const ::com::sun::star::lang::EventObject& Source) throw( RuntimeException )
470 {
471     if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == Source.Source))
472     {
473         ClearView();
474     }
475 
476     SbaXDataBrowserController::disposing(Source);
477 }
478 
479 //------------------------------------------------------------------
480 void SbaExternalSourceBrowser::startListening()
481 {
482     if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is())
483     {
484         Reference< ::com::sun::star::form::XLoadable >  xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY);
485         xLoadable->addLoadListener((::com::sun::star::form::XLoadListener*)this);
486     }
487 }
488 
489 //------------------------------------------------------------------
490 void SbaExternalSourceBrowser::stopListening()
491 {
492     if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is())
493     {
494         Reference< ::com::sun::star::form::XLoadable >  xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY);
495         xLoadable->removeLoadListener((::com::sun::star::form::XLoadListener*)this);
496     }
497 }
498 
499 //==================================================================
500 //==================================================================
501