Line data Source code
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 "exsrcbrw.hxx"
21 : #include "uiservices.hxx"
22 : #include <com/sun/star/form/FormComponentType.hpp>
23 : #include <com/sun/star/util/XURLTransformer.hpp>
24 : #include <com/sun/star/form/XGridColumnFactory.hpp>
25 : #include <com/sun/star/form/XLoadable.hpp>
26 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
27 : #include "formadapter.hxx"
28 : #include <comphelper/processfactory.hxx>
29 : #include "dbustrings.hrc"
30 : #include "dbu_reghelper.hxx"
31 : #include <tools/diagnose_ex.h>
32 : #include <rtl/strbuf.hxx>
33 :
34 : using namespace ::com::sun::star::uno;
35 : using namespace ::com::sun::star::sdb;
36 : using namespace ::com::sun::star::sdbc;
37 : using namespace ::com::sun::star::sdbcx;
38 : using namespace ::com::sun::star::beans;
39 : using namespace ::com::sun::star::container;
40 : using namespace ::com::sun::star::lang;
41 : using namespace ::com::sun::star::form;
42 : using namespace ::com::sun::star::frame;
43 : using namespace dbaui;
44 :
45 : // SbaExternalSourceBrowser
46 12 : extern "C" void SAL_CALL createRegistryInfo_OFormGridView()
47 : {
48 12 : static OMultiInstanceAutoRegistration< SbaExternalSourceBrowser > aAutoRegistration;
49 12 : }
50 :
51 0 : Any SAL_CALL SbaExternalSourceBrowser::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
52 : {
53 0 : Any aRet = SbaXDataBrowserController::queryInterface(_rType);
54 0 : if(!aRet.hasValue())
55 0 : aRet = ::cppu::queryInterface(_rType,
56 : static_cast<com::sun::star::util::XModifyBroadcaster*>(this),
57 0 : static_cast<com::sun::star::form::XLoadListener*>(this));
58 :
59 0 : return aRet;
60 : }
61 :
62 0 : SbaExternalSourceBrowser::SbaExternalSourceBrowser(const Reference< ::com::sun::star::uno::XComponentContext >& _rM)
63 : :SbaXDataBrowserController(_rM)
64 0 : ,m_aModifyListeners(getMutex())
65 : ,m_pDataSourceImpl(NULL)
66 0 : ,m_bInQueryDispatch( false )
67 : {
68 :
69 0 : }
70 :
71 0 : SbaExternalSourceBrowser::~SbaExternalSourceBrowser()
72 : {
73 :
74 0 : }
75 :
76 0 : ::comphelper::StringSequence SAL_CALL SbaExternalSourceBrowser::getSupportedServiceNames() throw(RuntimeException, std::exception)
77 : {
78 0 : return getSupportedServiceNames_Static();
79 : }
80 :
81 24 : OUString SbaExternalSourceBrowser::getImplementationName_Static() throw(RuntimeException)
82 : {
83 24 : return OUString("org.openoffice.comp.dbu.OFormGridView");
84 : }
85 :
86 12 : ::comphelper::StringSequence SbaExternalSourceBrowser::getSupportedServiceNames_Static() throw(RuntimeException)
87 : {
88 12 : ::comphelper::StringSequence aSupported(1);
89 12 : aSupported[0] = "com.sun.star.sdb.FormGridView";
90 12 : return aSupported;
91 : }
92 :
93 0 : Reference< XInterface > SAL_CALL SbaExternalSourceBrowser::Create(const Reference<XMultiServiceFactory >& _rxFactory)
94 : {
95 0 : return *(new SbaExternalSourceBrowser( comphelper::getComponentContext(_rxFactory)));
96 : }
97 :
98 0 : OUString SAL_CALL SbaExternalSourceBrowser::getImplementationName() throw(RuntimeException, std::exception)
99 : {
100 0 : return getImplementationName_Static();
101 : }
102 :
103 0 : Reference< XRowSet > SbaExternalSourceBrowser::CreateForm()
104 : {
105 0 : m_pDataSourceImpl = new SbaXFormAdapter();
106 0 : return m_pDataSourceImpl;
107 : }
108 :
109 0 : bool SbaExternalSourceBrowser::InitializeForm(const Reference< XPropertySet > & /*i_formProperties*/)
110 : {
111 0 : return true;
112 : }
113 :
114 0 : bool SbaExternalSourceBrowser::LoadForm()
115 : {
116 : // as we don't have a main form (yet), we have nothing to do
117 : // we don't call FormLoaded, because this expects a working data source
118 0 : return true;
119 : }
120 :
121 0 : void SbaExternalSourceBrowser::modified(const ::com::sun::star::lang::EventObject& aEvent) throw( RuntimeException, std::exception )
122 : {
123 0 : SbaXDataBrowserController::modified(aEvent);
124 :
125 : // multiplex this event to all my listeners
126 0 : ::com::sun::star::lang::EventObject aEvt(*this);
127 0 : ::cppu::OInterfaceIteratorHelper aIt(m_aModifyListeners);
128 0 : while (aIt.hasMoreElements())
129 0 : static_cast< ::com::sun::star::util::XModifyListener*>(aIt.next())->modified(aEvt);
130 0 : }
131 :
132 0 : 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, std::exception)
133 : {
134 0 : const ::com::sun::star::beans::PropertyValue* pArguments = aArgs.getConstArray();
135 0 : if ( aURL.Complete == ".uno:FormSlots/AddGridColumn" )
136 : {
137 : // search the argument describing the column to create
138 0 : OUString sControlType;
139 0 : sal_Int32 nControlPos = -1;
140 0 : Sequence< ::com::sun::star::beans::PropertyValue> aControlProps;
141 : sal_uInt16 i;
142 0 : for ( i = 0; i < aArgs.getLength(); ++i, ++pArguments )
143 : {
144 0 : if ( pArguments->Name == "ColumnType" )
145 : {
146 0 : bool bCorrectType = pArguments->Value.getValueType().equals(::cppu::UnoType<OUString>::get());
147 : OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnType\" !");
148 0 : if (bCorrectType)
149 0 : sControlType = ::comphelper::getString(pArguments->Value);
150 : }
151 0 : else if ( pArguments->Name == "ColumnPosition" )
152 : {
153 0 : bool bCorrectType = pArguments->Value.getValueType().equals(::cppu::UnoType<sal_Int16>::get());
154 : OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnPosition\" !");
155 0 : if (bCorrectType)
156 0 : nControlPos = ::comphelper::getINT16(pArguments->Value);
157 : }
158 0 : else if ( pArguments->Name == "ColumnProperties" )
159 : {
160 0 : bool bCorrectType = pArguments->Value.getValueType().equals(cppu::UnoType<Sequence< ::com::sun::star::beans::PropertyValue>>::get());
161 : OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnProperties\" !");
162 0 : if (bCorrectType)
163 0 : aControlProps = *static_cast<Sequence< ::com::sun::star::beans::PropertyValue> const *>(pArguments->Value.getValue());
164 : }
165 : else
166 : SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch(AddGridColumn) : unknown argument (" << pArguments->Name << ") !");
167 : }
168 0 : if (sControlType.isEmpty())
169 : {
170 : SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnType) !");
171 0 : sControlType = "TextField";
172 : }
173 : OSL_ENSURE(aControlProps.getLength(), "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnProperties) !");
174 :
175 : // create the col
176 0 : Reference< ::com::sun::star::form::XGridColumnFactory > xColFactory(getControlModel(), UNO_QUERY);
177 0 : Reference< ::com::sun::star::beans::XPropertySet > xNewCol = xColFactory->createColumn(sControlType);
178 0 : Reference< XPropertySetInfo > xNewColProperties;
179 0 : if (xNewCol.is())
180 0 : xNewColProperties = xNewCol->getPropertySetInfo();
181 : // set its properties
182 0 : if (xNewColProperties.is())
183 : {
184 0 : const ::com::sun::star::beans::PropertyValue* pControlProps = aControlProps.getConstArray();
185 0 : for (i=0; i<aControlProps.getLength(); ++i, ++pControlProps)
186 : {
187 : try
188 : {
189 0 : if (xNewColProperties->hasPropertyByName(pControlProps->Name))
190 0 : xNewCol->setPropertyValue(pControlProps->Name, pControlProps->Value);
191 : }
192 0 : catch (const Exception&)
193 : {
194 : SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch : could not set a column property (" << pControlProps->Name << ")!");
195 : }
196 : }
197 : }
198 :
199 : // correct the position
200 0 : Reference< ::com::sun::star::container::XIndexContainer > xColContainer(getControlModel(), UNO_QUERY);
201 :
202 0 : if (nControlPos > xColContainer->getCount())
203 0 : nControlPos = xColContainer->getCount();
204 0 : if (nControlPos < 0)
205 0 : nControlPos = 0;
206 :
207 : // append the column
208 0 : xColContainer->insertByIndex(nControlPos, makeAny(xNewCol));
209 : }
210 0 : else if ( aURL.Complete == ".uno:FormSlots/ClearView" )
211 : {
212 0 : ClearView();
213 : }
214 0 : else if ( aURL.Complete == ".uno:FormSlots/AttachToForm" )
215 : {
216 0 : if (!m_pDataSourceImpl)
217 0 : return;
218 :
219 0 : Reference< XRowSet > xMasterForm;
220 : // search the arguments for the master form
221 0 : for (sal_Int32 i=0; i<aArgs.getLength(); ++i, ++pArguments)
222 : {
223 0 : if ( (pArguments->Name == "MasterForm") && (pArguments->Value.getValueTypeClass() == TypeClass_INTERFACE) )
224 : {
225 0 : xMasterForm = Reference< XRowSet > (*static_cast<Reference< XInterface > const *>(pArguments->Value.getValue()), UNO_QUERY);
226 0 : break;
227 : }
228 : }
229 0 : if (!xMasterForm.is())
230 : {
231 : SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::dispatch(FormSlots/AttachToForm) : please specify a form to attach to as argument !");
232 0 : return;
233 : }
234 :
235 0 : Attach(xMasterForm);
236 : }
237 : else
238 0 : SbaXDataBrowserController::dispatch(aURL, aArgs);
239 : }
240 :
241 0 : Reference< ::com::sun::star::frame::XDispatch > SAL_CALL SbaExternalSourceBrowser::queryDispatch(const ::com::sun::star::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException, std::exception )
242 : {
243 0 : Reference< ::com::sun::star::frame::XDispatch > xReturn;
244 0 : if (m_bInQueryDispatch)
245 0 : return xReturn;
246 :
247 0 : m_bInQueryDispatch = true;
248 :
249 0 : if ( ( aURL.Complete == ".uno:FormSlots/AttachToForm" )
250 : // attach a new external form
251 0 : || ( aURL.Complete == ".uno:FormSlots/AddGridColumn" )
252 : // add a column to the grid
253 0 : || ( aURL.Complete == ".uno:FormSlots/ClearView" )
254 : // clear the grid
255 : )
256 0 : xReturn = static_cast<com::sun::star::frame::XDispatch*>(this);
257 :
258 0 : if ( !xReturn.is()
259 0 : && ( (aURL.Complete == ".uno:FormSlots/moveToFirst" ) || (aURL.Complete == ".uno:FormSlots/moveToPrev" )
260 0 : || (aURL.Complete == ".uno:FormSlots/moveToNext" ) || (aURL.Complete == ".uno:FormSlots/moveToLast" )
261 0 : || (aURL.Complete == ".uno:FormSlots/moveToNew" ) || (aURL.Complete == ".uno:FormSlots/undoRecord" )
262 : )
263 : )
264 : {
265 : OSL_ENSURE(aURL.Mark.isEmpty(), "SbaExternalSourceBrowser::queryDispatch : the ::com::sun::star::util::URL shouldn't have a mark !");
266 0 : ::com::sun::star::util::URL aNewUrl = aURL;
267 :
268 : // split the ::com::sun::star::util::URL
269 : OSL_ENSURE( m_xUrlTransformer.is(), "SbaExternalSourceBrowser::queryDispatch : could not create an URLTransformer !" );
270 0 : if ( m_xUrlTransformer.is() )
271 0 : m_xUrlTransformer->parseStrict( aNewUrl );
272 :
273 : // set a new mark
274 0 : aNewUrl.Mark = "DB/FormGridView";
275 : // this controller is instantiated when somebody dispatches the ".component:DB/FormGridView" in any
276 : // frame, so we use "FormGridView" as mark that a dispatch request came from this view
277 :
278 0 : if (m_xUrlTransformer.is())
279 0 : m_xUrlTransformer->assemble(aNewUrl);
280 :
281 0 : Reference< XDispatchProvider > xFrameDispatcher( getFrame(), UNO_QUERY );
282 0 : if (xFrameDispatcher.is())
283 0 : xReturn = xFrameDispatcher->queryDispatch(aNewUrl, aTargetFrameName, FrameSearchFlag::PARENT);
284 :
285 : }
286 :
287 0 : if (!xReturn.is())
288 0 : xReturn = SbaXDataBrowserController::queryDispatch(aURL, aTargetFrameName, nSearchFlags);
289 :
290 0 : m_bInQueryDispatch = false;
291 0 : return xReturn;
292 : }
293 :
294 0 : void SAL_CALL SbaExternalSourceBrowser::disposing()
295 : {
296 : // say our modify listeners goodbye
297 0 : ::com::sun::star::lang::EventObject aEvt;
298 0 : aEvt.Source = static_cast<XWeak*>(this);
299 0 : m_aModifyListeners.disposeAndClear(aEvt);
300 :
301 0 : stopListening();
302 :
303 0 : SbaXDataBrowserController::disposing();
304 0 : }
305 :
306 0 : void SAL_CALL SbaExternalSourceBrowser::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener > & aListener) throw( RuntimeException, std::exception )
307 : {
308 0 : m_aModifyListeners.addInterface(aListener);
309 0 : }
310 :
311 0 : void SAL_CALL SbaExternalSourceBrowser::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener > & aListener) throw( RuntimeException, std::exception )
312 : {
313 0 : m_aModifyListeners.removeInterface(aListener);
314 0 : }
315 :
316 0 : void SAL_CALL SbaExternalSourceBrowser::unloading(const ::com::sun::star::lang::EventObject& aEvent) throw( RuntimeException, std::exception )
317 : {
318 0 : if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == aEvent.Source))
319 : {
320 0 : ClearView();
321 : }
322 :
323 0 : SbaXDataBrowserController::unloading(aEvent);
324 0 : }
325 :
326 0 : void SbaExternalSourceBrowser::Attach(const Reference< XRowSet > & xMaster)
327 : {
328 0 : Any aOldPos;
329 0 : bool bWasInsertRow = false;
330 0 : bool bBeforeFirst = true;
331 0 : bool bAfterLast = true;
332 0 : Reference< XRowLocate > xCursor(xMaster, UNO_QUERY);
333 0 : Reference< XPropertySet > xMasterProps(xMaster, UNO_QUERY);
334 :
335 : try
336 : {
337 : // switch the control to design mode
338 0 : if (getBrowserView() && getBrowserView()->getGridControl().is())
339 0 : getBrowserView()->getGridControl()->setDesignMode(sal_True);
340 :
341 : // the grid will move the form's cursor to the first record, but we want the form to remain unchanged
342 : // restore the old position
343 0 : if (xCursor.is() && xMaster.is())
344 : {
345 0 : bBeforeFirst = xMaster->isBeforeFirst();
346 0 : bAfterLast = xMaster->isAfterLast();
347 0 : if(!bBeforeFirst && !bAfterLast)
348 0 : aOldPos = xCursor->getBookmark();
349 : }
350 :
351 0 : if (xMasterProps.is())
352 0 : xMasterProps->getPropertyValue(PROPERTY_ISNEW) >>= bWasInsertRow;
353 : }
354 0 : catch( const Exception& )
355 : {
356 : DBG_UNHANDLED_EXCEPTION();
357 : }
358 :
359 0 : onStartLoading( Reference< XLoadable >( xMaster, UNO_QUERY ) );
360 :
361 0 : stopListening();
362 0 : m_pDataSourceImpl->AttachForm(xMaster);
363 0 : startListening();
364 :
365 0 : if (xMaster.is())
366 : {
367 : // at this point we have to reset the formatter for the new form
368 0 : initFormatter();
369 : // assume that the master form is already loaded
370 : #if OSL_DEBUG_LEVEL > 0
371 : {
372 : Reference< XLoadable > xLoadable( xMaster, UNO_QUERY );
373 : OSL_ENSURE( xLoadable.is() && xLoadable->isLoaded(), "SbaExternalSourceBrowser::Attach: master is not loaded!" );
374 : }
375 : #endif
376 :
377 0 : LoadFinished(true);
378 :
379 0 : Reference< XResultSetUpdate > xUpdate(xMaster, UNO_QUERY);
380 : try
381 : {
382 0 : if (bWasInsertRow && xUpdate.is())
383 0 : xUpdate->moveToInsertRow();
384 0 : else if (xCursor.is() && aOldPos.hasValue())
385 0 : xCursor->moveToBookmark(aOldPos);
386 0 : else if(bBeforeFirst && xMaster.is())
387 0 : xMaster->beforeFirst();
388 0 : else if(bAfterLast && xMaster.is())
389 0 : xMaster->afterLast();
390 : }
391 0 : catch(Exception&)
392 : {
393 : SAL_WARN("dbaccess.ui", "SbaExternalSourceBrowser::Attach : couldn't restore the cursor position !");
394 0 : }
395 :
396 0 : }
397 0 : }
398 :
399 0 : void SbaExternalSourceBrowser::ClearView()
400 : {
401 : // set a new (empty) datasource
402 0 : Attach(Reference< XRowSet > ());
403 :
404 : // clear all cols in the grid
405 0 : Reference< ::com::sun::star::container::XIndexContainer > xColContainer(getControlModel(), UNO_QUERY);
406 0 : while (xColContainer->getCount() > 0)
407 0 : xColContainer->removeByIndex(0);
408 0 : }
409 :
410 0 : void SAL_CALL SbaExternalSourceBrowser::disposing(const ::com::sun::star::lang::EventObject& Source) throw( RuntimeException, std::exception )
411 : {
412 0 : if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == Source.Source))
413 : {
414 0 : ClearView();
415 : }
416 :
417 0 : SbaXDataBrowserController::disposing(Source);
418 0 : }
419 :
420 0 : void SbaExternalSourceBrowser::startListening()
421 : {
422 0 : if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is())
423 : {
424 0 : Reference< ::com::sun::star::form::XLoadable > xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY);
425 0 : xLoadable->addLoadListener(static_cast<com::sun::star::form::XLoadListener*>(this));
426 : }
427 0 : }
428 :
429 0 : void SbaExternalSourceBrowser::stopListening()
430 : {
431 0 : if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is())
432 : {
433 0 : Reference< ::com::sun::star::form::XLoadable > xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY);
434 0 : xLoadable->removeLoadListener(static_cast<com::sun::star::form::XLoadListener*>(this));
435 : }
436 36 : }
437 :
438 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|