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 "sbagrid.hrc"
21 : #include "uiservices.hxx"
22 :
23 : #include <svx/svxids.hrc>
24 :
25 : #include <svx/numinf.hxx>
26 : #include <svx/dbaexchange.hxx>
27 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
28 :
29 : #include "sbagrid.hxx"
30 : #include "dlgattr.hxx"
31 : #include "dlgsize.hxx"
32 : #include <com/sun/star/form/XLoadable.hpp>
33 : #include <com/sun/star/form/ControlFontDialog.hpp>
34 : #include <com/sun/star/sdb/CommandType.hpp>
35 : #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
36 : #include <com/sun/star/sdb/XResultSetAccess.hpp>
37 : #include <com/sun/star/form/XForm.hpp>
38 : #include <com/sun/star/container/XIndexContainer.hpp>
39 : #include <com/sun/star/util/NumberFormat.hpp>
40 :
41 : #include <com/sun/star/view/XSelectionSupplier.hpp>
42 : #include <com/sun/star/form/DataSelectionType.hpp>
43 : #include <com/sun/star/awt/TextAlign.hpp>
44 : #include <com/sun/star/awt/XTextComponent.hpp>
45 : #include <com/sun/star/util/Date.hpp>
46 : #include <com/sun/star/util/Time.hpp>
47 : #include <com/sun/star/util/DateTime.hpp>
48 : #include <com/sun/star/sdbc/XResultSetUpdate.hpp>
49 : #include <tools/diagnose_ex.h>
50 :
51 : #include <svl/intitem.hxx>
52 : #include <svx/algitem.hxx>
53 : #include <tools/multisel.hxx>
54 : #include <svl/numuno.hxx>
55 : #include <svl/itempool.hxx>
56 : #include <svl/itemset.hxx>
57 : #include <svl/rngitem.hxx>
58 :
59 : #include <vcl/waitobj.hxx>
60 : #include <toolkit/helper/vclunohelper.hxx>
61 :
62 : #include <svl/zforlist.hxx>
63 : #include <cppuhelper/queryinterface.hxx>
64 : #include <connectivity/dbtools.hxx>
65 : #include <connectivity/dbconversion.hxx>
66 : #include <cppuhelper/typeprovider.hxx>
67 : #include <comphelper/servicehelper.hxx>
68 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
69 : #include <com/sun/star/sdbc/DataType.hpp>
70 : #include <vcl/msgbox.hxx>
71 : #include "dbu_brw.hrc"
72 : #include "browserids.hxx"
73 : #include "dbustrings.hrc"
74 : #include "dbu_reghelper.hxx"
75 : #include "dbexchange.hxx"
76 : #include "TableRowExchange.hxx"
77 : #include "TableRow.hxx"
78 : #include "FieldDescriptions.hxx"
79 : #include <svtools/stringtransfer.hxx>
80 : #include <vcl/stdtext.hxx>
81 : #include "UITools.hxx"
82 : #include "TokenWriter.hxx"
83 : #include <osl/diagnose.h>
84 :
85 : using namespace ::com::sun::star::ui::dialogs;
86 : using namespace ::com::sun::star::uno;
87 : using namespace ::com::sun::star::sdb;
88 : using namespace ::com::sun::star::sdbc;
89 : using namespace ::com::sun::star::sdbcx;
90 : using namespace ::com::sun::star::beans;
91 : using namespace ::com::sun::star::container;
92 : using namespace ::com::sun::star::datatransfer;
93 : using namespace ::com::sun::star::lang;
94 : using namespace ::com::sun::star::view;
95 : using namespace ::com::sun::star::form;
96 : using namespace ::com::sun::star::frame;
97 : using namespace ::com::sun::star::util;
98 : using namespace ::dbaui;
99 : using namespace ::dbtools;
100 : using namespace ::svx;
101 : using namespace ::svt;
102 :
103 24 : extern "C" void SAL_CALL createRegistryInfo_SbaXGridControl()
104 : {
105 24 : static OMultiInstanceAutoRegistration< SbaXGridControl > aAutoRegistration;
106 24 : }
107 :
108 0 : ::comphelper::StringSequence SAL_CALL SbaXGridControl::getSupportedServiceNames() throw(std::exception)
109 : {
110 0 : return getSupportedServiceNames_Static();
111 : }
112 :
113 20 : Reference< XInterface > SAL_CALL SbaXGridControl::Create(const Reference<XMultiServiceFactory >& _rxFactory)
114 : {
115 20 : return *(new SbaXGridControl( comphelper::getComponentContext(_rxFactory) ));
116 : }
117 :
118 : // SbaXGridControl
119 :
120 0 : OUString SAL_CALL SbaXGridControl::getImplementationName() throw(std::exception)
121 : {
122 0 : return getImplementationName_Static();
123 : }
124 :
125 48 : OUString SbaXGridControl::getImplementationName_Static() throw( RuntimeException )
126 : {
127 48 : return OUString("com.sun.star.comp.dbu.SbaXGridControl");
128 : }
129 :
130 24 : Sequence< OUString> SbaXGridControl::getSupportedServiceNames_Static(void) throw( RuntimeException )
131 : {
132 24 : Sequence< OUString> aSupported(3);
133 24 : aSupported[0] = "com.sun.star.form.control.InteractionGridControl";
134 24 : aSupported[1] = "com.sun.star.form.control.GridControl";
135 24 : aSupported[2] = "com.sun.star.awt.UnoControl";
136 24 : return aSupported;
137 : }
138 :
139 22 : SbaXGridControl::SbaXGridControl(const Reference< XComponentContext >& _rM)
140 22 : : FmXGridControl(_rM)
141 : {
142 22 : }
143 :
144 44 : SbaXGridControl::~SbaXGridControl()
145 : {
146 44 : }
147 :
148 41 : FmXGridPeer* SbaXGridControl::imp_CreatePeer(vcl::Window* pParent)
149 : {
150 41 : FmXGridPeer* pReturn = new SbaXGridPeer(m_xContext);
151 :
152 : // translate properties into WinBits
153 41 : WinBits nStyle = WB_TABSTOP;
154 41 : Reference< XPropertySet > xModelSet(getModel(), UNO_QUERY);
155 41 : if (xModelSet.is())
156 : {
157 : try
158 : {
159 41 : if (::comphelper::getINT16(xModelSet->getPropertyValue(PROPERTY_BORDER)))
160 41 : nStyle |= WB_BORDER;
161 : }
162 0 : catch(Exception&)
163 : {
164 : }
165 :
166 : }
167 :
168 41 : pReturn->Create(pParent, nStyle);
169 41 : return pReturn;
170 : }
171 :
172 814 : Any SAL_CALL SbaXGridControl::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
173 : {
174 814 : Any aRet = FmXGridControl::queryInterface(_rType);
175 814 : return aRet.hasValue() ? aRet : ::cppu::queryInterface(_rType,(::com::sun::star::frame::XDispatch*)this);
176 : }
177 :
178 0 : Sequence< Type > SAL_CALL SbaXGridControl::getTypes( ) throw (RuntimeException, std::exception)
179 : {
180 0 : Sequence< Type > aTypes = FmXGridControl::getTypes();
181 :
182 0 : sal_Int32 nTypes = aTypes.getLength();
183 0 : aTypes.realloc(nTypes + 1);
184 0 : aTypes[nTypes] = cppu::UnoType<com::sun::star::frame::XDispatch>::get();
185 :
186 0 : return aTypes;
187 : }
188 :
189 0 : Sequence< sal_Int8 > SAL_CALL SbaXGridControl::getImplementationId( ) throw (RuntimeException, std::exception)
190 : {
191 0 : return css::uno::Sequence<sal_Int8>();
192 : }
193 :
194 41 : void SAL_CALL SbaXGridControl::createPeer(const Reference< ::com::sun::star::awt::XToolkit > & rToolkit, const Reference< ::com::sun::star::awt::XWindowPeer > & rParentPeer) throw( RuntimeException, std::exception )
195 : {
196 41 : FmXGridControl::createPeer(rToolkit, rParentPeer);
197 :
198 : OSL_ENSURE(!mbCreatingPeer, "FmXGridControl::createPeer : recursion!");
199 : // see the base class' createPeer for a comment on this
200 :
201 : // TODO: why the hell this whole class does not use any mutex?
202 :
203 41 : Reference< ::com::sun::star::frame::XDispatch > xDisp(getPeer(), UNO_QUERY);
204 123 : for ( StatusMultiplexerArray::iterator aIter = m_aStatusMultiplexer.begin();
205 82 : aIter != m_aStatusMultiplexer.end();
206 : ++aIter)
207 : {
208 0 : if ((*aIter).second && (*aIter).second->getLength())
209 0 : xDisp->addStatusListener((*aIter).second, (*aIter).first);
210 41 : }
211 41 : }
212 :
213 0 : void SAL_CALL SbaXGridControl::dispatch(const ::com::sun::star::util::URL& aURL, const Sequence< PropertyValue >& aArgs) throw( RuntimeException, std::exception )
214 : {
215 0 : Reference< ::com::sun::star::frame::XDispatch > xDisp(getPeer(), UNO_QUERY);
216 0 : if (xDisp.is())
217 0 : xDisp->dispatch(aURL, aArgs);
218 0 : }
219 :
220 0 : void SAL_CALL SbaXGridControl::addStatusListener( const Reference< XStatusListener > & _rxListener, const URL& _rURL ) throw( RuntimeException, std::exception )
221 : {
222 0 : ::osl::MutexGuard aGuard( GetMutex() );
223 0 : if ( _rxListener.is() )
224 : {
225 0 : SbaXStatusMultiplexer*& pMultiplexer = m_aStatusMultiplexer[ _rURL ];
226 0 : if ( !pMultiplexer )
227 : {
228 0 : pMultiplexer = new SbaXStatusMultiplexer( *this, GetMutex() );
229 0 : pMultiplexer->acquire();
230 : }
231 :
232 0 : pMultiplexer->addInterface( _rxListener );
233 0 : if ( getPeer().is() )
234 : {
235 0 : if ( 1 == pMultiplexer->getLength() )
236 : { // the first external listener for this URL
237 0 : Reference< XDispatch > xDisp( getPeer(), UNO_QUERY );
238 0 : xDisp->addStatusListener( pMultiplexer, _rURL );
239 : }
240 : else
241 : { // already have other listeners for this URL
242 0 : _rxListener->statusChanged( pMultiplexer->getLastEvent() );
243 : }
244 : }
245 0 : }
246 0 : }
247 :
248 0 : void SAL_CALL SbaXGridControl::removeStatusListener(const Reference< ::com::sun::star::frame::XStatusListener > & _rxListener, const ::com::sun::star::util::URL& _rURL) throw( RuntimeException, std::exception )
249 : {
250 0 : ::osl::MutexGuard aGuard( GetMutex() );
251 :
252 0 : SbaXStatusMultiplexer*& pMultiplexer = m_aStatusMultiplexer[_rURL];
253 0 : if (!pMultiplexer)
254 : {
255 0 : pMultiplexer = new SbaXStatusMultiplexer(*this,GetMutex());
256 0 : pMultiplexer->acquire();
257 : }
258 :
259 0 : if (getPeer().is() && pMultiplexer->getLength() == 1)
260 : {
261 0 : Reference< ::com::sun::star::frame::XDispatch > xDisp(getPeer(), UNO_QUERY);
262 0 : xDisp->removeStatusListener(pMultiplexer, _rURL);
263 : }
264 0 : pMultiplexer->removeInterface( _rxListener );
265 0 : }
266 :
267 24 : void SAL_CALL SbaXGridControl::dispose(void) throw( RuntimeException, std::exception )
268 : {
269 24 : SolarMutexGuard aGuard;
270 :
271 48 : EventObject aEvt;
272 24 : aEvt.Source = *this;
273 :
274 72 : for ( StatusMultiplexerArray::iterator aIter = m_aStatusMultiplexer.begin();
275 48 : aIter != m_aStatusMultiplexer.end();
276 : ++aIter)
277 : {
278 0 : if ((*aIter).second)
279 : {
280 0 : (*aIter).second->disposeAndClear(aEvt);
281 0 : (*aIter).second->release();
282 0 : (*aIter).second = NULL;
283 : }
284 : }
285 24 : StatusMultiplexerArray().swap(m_aStatusMultiplexer);
286 :
287 48 : FmXGridControl::dispose();
288 24 : }
289 :
290 : // SbaXGridPeer
291 41 : SbaXGridPeer::SbaXGridPeer(const Reference< XComponentContext >& _rM)
292 : : FmXGridPeer(_rM)
293 41 : ,m_aStatusListeners(m_aMutex)
294 : {
295 41 : }
296 :
297 82 : SbaXGridPeer::~SbaXGridPeer()
298 : {
299 82 : }
300 :
301 82 : void SAL_CALL SbaXGridPeer::dispose(void) throw( RuntimeException, std::exception )
302 : {
303 82 : EventObject aEvt(*this);
304 :
305 82 : m_aStatusListeners.disposeAndClear(aEvt);
306 :
307 82 : FmXGridPeer::dispose();
308 82 : }
309 :
310 0 : void SbaXGridPeer::NotifyStatusChanged(const ::com::sun::star::util::URL& _rUrl, const Reference< ::com::sun::star::frame::XStatusListener > & xControl)
311 : {
312 0 : SbaGridControl* pGrid = static_cast<SbaGridControl*>(GetWindow());
313 0 : if (!pGrid)
314 0 : return;
315 :
316 0 : ::com::sun::star::frame::FeatureStateEvent aEvt;
317 0 : aEvt.Source = *this;
318 0 : aEvt.IsEnabled = !pGrid->IsReadOnlyDB();
319 0 : aEvt.FeatureURL = _rUrl;
320 :
321 0 : MapDispatchToBool::const_iterator aURLStatePos = m_aDispatchStates.find( classifyDispatchURL( _rUrl ) );
322 0 : if ( m_aDispatchStates.end() != aURLStatePos )
323 0 : aEvt.State <<= aURLStatePos->second;
324 : else
325 0 : aEvt.State <<= sal_False;
326 :
327 0 : if (xControl.is())
328 0 : xControl->statusChanged(aEvt);
329 : else
330 : {
331 0 : ::cppu::OInterfaceContainerHelper * pIter = m_aStatusListeners.getContainer(_rUrl);
332 :
333 0 : if (pIter)
334 : {
335 0 : ::cppu::OInterfaceIteratorHelper aListIter(*pIter);
336 0 : while (aListIter.hasMoreElements())
337 0 : static_cast< ::com::sun::star::frame::XStatusListener*>(aListIter.next())->statusChanged(aEvt);
338 : }
339 0 : }
340 : }
341 :
342 2104 : Any SAL_CALL SbaXGridPeer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
343 : {
344 2104 : Any aRet = ::cppu::queryInterface(_rType,(::com::sun::star::frame::XDispatch*)this);
345 2104 : if(aRet.hasValue())
346 41 : return aRet;
347 2063 : return FmXGridPeer::queryInterface(_rType);
348 : }
349 :
350 42 : Reference< ::com::sun::star::frame::XDispatch > SAL_CALL SbaXGridPeer::queryDispatch(const ::com::sun::star::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException, std::exception )
351 : {
352 126 : if ( ( aURL.Complete == ".uno:GridSlots/BrowserAttribs" ) || ( aURL.Complete == ".uno:GridSlots/RowHeight" )
353 84 : || ( aURL.Complete == ".uno:GridSlots/ColumnAttribs" ) || ( aURL.Complete == ".uno:GridSlots/ColumnWidth" )
354 : )
355 : {
356 0 : return (::com::sun::star::frame::XDispatch*)this;
357 : }
358 :
359 42 : return FmXGridPeer::queryDispatch(aURL, aTargetFrameName, nSearchFlags);
360 : }
361 :
362 0 : IMPL_LINK( SbaXGridPeer, OnDispatchEvent, void*, /*NOTINTERESTEDIN*/ )
363 : {
364 0 : SbaGridControl* pGrid = static_cast< SbaGridControl* >( GetWindow() );
365 0 : if ( pGrid ) // if this fails, we were disposing before arriving here
366 : {
367 0 : if ( Application::GetMainThreadIdentifier() != ::osl::Thread::getCurrentIdentifier() )
368 : {
369 : // still not in the main thread (see SbaXGridPeer::dispatch). post an event, again
370 : // without moving the special even to the back of the queue
371 0 : pGrid->PostUserEvent( LINK( this, SbaXGridPeer, OnDispatchEvent ) );
372 : }
373 : else
374 : {
375 0 : DispatchArgs aArgs = m_aDispatchArgs.front();
376 0 : m_aDispatchArgs.pop();
377 :
378 0 : SbaXGridPeer::dispatch( aArgs.aURL, aArgs.aArgs );
379 : }
380 : }
381 :
382 0 : return 0;
383 : }
384 :
385 0 : SbaXGridPeer::DispatchType SbaXGridPeer::classifyDispatchURL( const URL& _rURL )
386 : {
387 0 : DispatchType eURLType = dtUnknown;
388 0 : if ( _rURL.Complete == ".uno:GridSlots/BrowserAttribs" )
389 0 : eURLType = dtBrowserAttribs;
390 0 : else if ( _rURL.Complete == ".uno:GridSlots/RowHeight" )
391 0 : eURLType = dtRowHeight;
392 0 : else if ( _rURL.Complete == ".uno:GridSlots/ColumnAttribs" )
393 0 : eURLType = dtColumnAttribs;
394 0 : else if ( _rURL.Complete == ".uno:GridSlots/ColumnWidth" )
395 0 : eURLType = dtColumnWidth;
396 0 : return eURLType;
397 : }
398 :
399 0 : void SAL_CALL SbaXGridPeer::dispatch(const URL& aURL, const Sequence< PropertyValue >& aArgs) throw( RuntimeException, std::exception )
400 : {
401 0 : SbaGridControl* pGrid = static_cast<SbaGridControl*>(GetWindow());
402 0 : if (!pGrid)
403 0 : return;
404 :
405 0 : if ( Application::GetMainThreadIdentifier() != ::osl::Thread::getCurrentIdentifier() )
406 : {
407 : // we're not in the main thread. This is bad, as we want to raise windows here,
408 : // and VCL does not like windows to be opened in non-main threads (at least on Win32).
409 : // Okay, do this async. No problem with this, as XDispatch::dispatch is defined to be
410 : // a one-way method.
411 :
412 : // save the args
413 0 : DispatchArgs aDispatchArgs;
414 0 : aDispatchArgs.aURL = aURL;
415 0 : aDispatchArgs.aArgs = aArgs;
416 0 : m_aDispatchArgs.push( aDispatchArgs );
417 :
418 : // post an event
419 : // we use the Window::PostUserEvent here, instead of the application::PostUserEvent
420 : // this saves us from keeping track of these events - as soon as the window dies,
421 : // the events are deleted automatically. For the application way, we would need to
422 : // do this ourself.
423 : // As we use our grid as window, and the grid dies before we dy, this should be no problem.
424 0 : pGrid->PostUserEvent( LINK( this, SbaXGridPeer, OnDispatchEvent ) );
425 0 : return;
426 : }
427 :
428 0 : SolarMutexGuard aGuard;
429 0 : sal_Int16 nColId = -1;
430 0 : const PropertyValue* pArgs = aArgs.getConstArray();
431 0 : for (sal_uInt16 i=0; i<aArgs.getLength(); ++i, ++pArgs)
432 : {
433 0 : if (pArgs->Name == "ColumnViewPos")
434 : {
435 0 : nColId = pGrid->GetColumnIdFromViewPos(::comphelper::getINT16(pArgs->Value));
436 0 : break;
437 : }
438 0 : if (pArgs->Name == "ColumnModelPos")
439 : {
440 0 : nColId = pGrid->GetColumnIdFromModelPos(::comphelper::getINT16(pArgs->Value));
441 0 : break;
442 : }
443 0 : if (pArgs->Name == "ColumnId")
444 : {
445 0 : nColId = ::comphelper::getINT16(pArgs->Value);
446 0 : break;
447 : }
448 : }
449 :
450 0 : DispatchType eURLType = classifyDispatchURL( aURL );
451 :
452 0 : if ( dtUnknown != eURLType )
453 : {
454 : // notify any status listeners that the dialog is now active (well, about to be active)
455 0 : MapDispatchToBool::iterator aThisURLState = m_aDispatchStates.insert( MapDispatchToBool::value_type( eURLType, sal_True ) ).first;
456 0 : NotifyStatusChanged( aURL, NULL );
457 :
458 : // execute the dialog
459 0 : switch ( eURLType )
460 : {
461 : case dtBrowserAttribs:
462 0 : pGrid->SetBrowserAttrs();
463 0 : break;
464 :
465 : case dtRowHeight:
466 0 : pGrid->SetRowHeight();
467 0 : break;
468 :
469 : case dtColumnAttribs:
470 : {
471 : OSL_ENSURE(nColId != -1, "SbaXGridPeer::dispatch : invalid parameter !");
472 0 : if (nColId != -1)
473 0 : break;
474 0 : pGrid->SetColAttrs(nColId);
475 : }
476 0 : break;
477 :
478 : case dtColumnWidth:
479 : {
480 : OSL_ENSURE(nColId != -1, "SbaXGridPeer::dispatch : invalid parameter !");
481 0 : if (nColId != -1)
482 0 : break;
483 0 : pGrid->SetColWidth(nColId);
484 : }
485 0 : break;
486 :
487 : case dtUnknown:
488 0 : break;
489 : }
490 :
491 : // notify any status listeners that the dialog vanished
492 0 : m_aDispatchStates.erase( aThisURLState );
493 0 : NotifyStatusChanged( aURL, NULL );
494 0 : }
495 : }
496 :
497 0 : void SAL_CALL SbaXGridPeer::addStatusListener(const Reference< ::com::sun::star::frame::XStatusListener > & xControl, const ::com::sun::star::util::URL& aURL) throw( RuntimeException, std::exception )
498 : {
499 0 : ::cppu::OInterfaceContainerHelper* pCont = m_aStatusListeners.getContainer(aURL);
500 0 : if (!pCont)
501 0 : m_aStatusListeners.addInterface(aURL,xControl);
502 : else
503 0 : pCont->addInterface(xControl);
504 0 : NotifyStatusChanged(aURL, xControl);
505 0 : }
506 :
507 0 : void SAL_CALL SbaXGridPeer::removeStatusListener(const Reference< ::com::sun::star::frame::XStatusListener > & xControl, const ::com::sun::star::util::URL& aURL) throw( RuntimeException, std::exception )
508 : {
509 0 : ::cppu::OInterfaceContainerHelper* pCont = m_aStatusListeners.getContainer(aURL);
510 0 : if ( pCont )
511 0 : pCont->removeInterface(xControl);
512 0 : }
513 :
514 : namespace
515 : {
516 : class theSbaXGridPeerUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSbaXGridPeerUnoTunnelId > {};
517 : }
518 :
519 473 : const Sequence< sal_Int8 > & SbaXGridPeer::getUnoTunnelId()
520 : {
521 473 : return theSbaXGridPeerUnoTunnelId::get().getSeq();
522 : }
523 :
524 0 : Sequence< Type > SAL_CALL SbaXGridPeer::getTypes() throw (RuntimeException, std::exception)
525 : {
526 0 : Sequence< Type > aTypes = FmXGridPeer::getTypes();
527 0 : sal_Int32 nOldLen = aTypes.getLength();
528 0 : aTypes.realloc(nOldLen + 1);
529 0 : aTypes.getArray()[nOldLen] = cppu::UnoType<com::sun::star::frame::XDispatch>::get();
530 :
531 0 : return aTypes;
532 : }
533 :
534 : // return implementation specific data
535 471 : sal_Int64 SAL_CALL SbaXGridPeer::getSomething( const Sequence< sal_Int8 > & rId ) throw(::com::sun::star::uno::RuntimeException, std::exception)
536 : {
537 471 : if( rId.getLength() == 16 && 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) )
538 2 : return reinterpret_cast< sal_Int64 >( this );
539 :
540 469 : return FmXGridPeer::getSomething(rId);
541 : }
542 :
543 2 : SbaXGridPeer* SbaXGridPeer::getImplementation(const Reference< XInterface >& _rxIFace)
544 : {
545 : Reference< XUnoTunnel > xTunnel(
546 2 : _rxIFace, UNO_QUERY);
547 2 : if (xTunnel.is())
548 2 : return reinterpret_cast<SbaXGridPeer*>(xTunnel->getSomething(getUnoTunnelId()));
549 0 : return NULL;
550 : }
551 :
552 41 : FmGridControl* SbaXGridPeer::imp_CreateControl(vcl::Window* pParent, WinBits nStyle)
553 : {
554 41 : return new SbaGridControl( m_xContext, pParent, this, nStyle);
555 : }
556 :
557 : // SbaGridHeader
558 :
559 41 : SbaGridHeader::SbaGridHeader(BrowseBox* pParent, WinBits nWinBits)
560 : :FmGridHeader(pParent, nWinBits)
561 41 : ,DragSourceHelper(this)
562 : {
563 41 : }
564 :
565 0 : void SbaGridHeader::StartDrag( sal_Int8 _nAction, const Point& _rPosPixel )
566 : {
567 0 : SolarMutexGuard aGuard;
568 : // in the new DnD API, the solar mutex is not locked when StartDrag get's called
569 :
570 0 : ImplStartColumnDrag( _nAction, _rPosPixel );
571 0 : }
572 :
573 0 : void SbaGridHeader::MouseButtonDown( const MouseEvent& _rMEvt )
574 : {
575 0 : if (_rMEvt.IsLeft())
576 0 : if (_rMEvt.GetClicks() != 2)
577 : {
578 : // the base class will start a column move here, which we don't want to allow
579 : // (at the moment. If we store relative positions with the columns, we can allow column moves ....)
580 :
581 : }
582 :
583 0 : FmGridHeader::MouseButtonDown(_rMEvt);
584 0 : }
585 :
586 0 : bool SbaGridHeader::ImplStartColumnDrag(sal_Int8 _nAction, const Point& _rMousePos)
587 : {
588 0 : sal_uInt16 nId = GetItemId(_rMousePos);
589 0 : bool bResizingCol = false;
590 0 : if (HEADERBAR_ITEM_NOTFOUND != nId)
591 : {
592 0 : Rectangle aColRect = GetItemRect(nId);
593 0 : aColRect.Left() += nId ? 3 : 0; // the handle col (nId == 0) does not have a left margin for resizing
594 0 : aColRect.Right() -= 3;
595 0 : bResizingCol = !aColRect.IsInside(_rMousePos);
596 : }
597 0 : if (!bResizingCol)
598 : {
599 : // force the base class to end it's drag mode
600 0 : EndTracking(ENDTRACK_CANCEL | ENDTRACK_END);
601 :
602 : // because we have 3d-buttons the select handler is called from MouseButtonUp, but StartDrag
603 : // occurs earlier (while the mouse button is down)
604 : // so for optical reasons we select the column before really starting the drag operation.
605 0 : notifyColumnSelect(nId);
606 :
607 0 : static_cast<SbaGridControl*>(GetParent())->StartDrag(_nAction,
608 : Point(
609 0 : _rMousePos.X() + GetPosPixel().X(), // we aren't left-justified with our parent, in contrast to the data window
610 0 : _rMousePos.Y() - GetSizePixel().Height()
611 : )
612 0 : );
613 0 : return true;
614 : }
615 :
616 0 : return false;
617 : }
618 :
619 0 : void SbaGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu)
620 : {
621 0 : FmGridHeader::PreExecuteColumnContextMenu(nColId, rMenu);
622 :
623 : // some items are valid only if the db isn't readonly
624 0 : bool bDBIsReadOnly = static_cast<SbaGridControl*>(GetParent())->IsReadOnlyDB();
625 :
626 0 : if (bDBIsReadOnly)
627 : {
628 0 : rMenu.EnableItem(SID_FM_HIDECOL, false);
629 0 : PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(SID_FM_SHOWCOLS);
630 0 : if (pShowColsMenu)
631 : {
632 : // at most 16 items which mean "show column <name>"
633 0 : for (sal_uInt16 i=1; i<16; ++i)
634 0 : pShowColsMenu->EnableItem(i, false);
635 : // "show cols/more..." and "show cols/all"
636 0 : pShowColsMenu->EnableItem(SID_FM_SHOWCOLS_MORE, false);
637 0 : pShowColsMenu->EnableItem(SID_FM_SHOWALLCOLS, false);
638 : }
639 : }
640 :
641 : // prepend some new items
642 0 : bool bColAttrs = (nColId != (sal_uInt16)-1) && (nColId != 0);
643 0 : if ( bColAttrs && !bDBIsReadOnly)
644 : {
645 0 : PopupMenu aNewItems(ModuleRes(RID_SBA_GRID_COLCTXMENU));
646 0 : sal_uInt16 nPos = 0;
647 0 : sal_uInt16 nModelPos = static_cast<SbaGridControl*>(GetParent())->GetModelColumnPos(nColId);
648 0 : Reference< XPropertySet > xField = static_cast<SbaGridControl*>(GetParent())->getField(nModelPos);
649 :
650 0 : if ( xField.is() )
651 : {
652 0 : switch( ::comphelper::getINT32(xField->getPropertyValue(PROPERTY_TYPE)) )
653 : {
654 : case DataType::BINARY:
655 : case DataType::VARBINARY:
656 : case DataType::LONGVARBINARY:
657 : case DataType::SQLNULL:
658 : case DataType::OBJECT:
659 : case DataType::BLOB:
660 : case DataType::CLOB:
661 : case DataType::REF:
662 0 : break;
663 : default:
664 0 : rMenu.InsertItem(ID_BROWSER_COLATTRSET, aNewItems.GetItemText(ID_BROWSER_COLATTRSET), MenuItemBits::NONE, OString(), nPos++);
665 0 : rMenu.SetHelpId(ID_BROWSER_COLATTRSET, aNewItems.GetHelpId(ID_BROWSER_COLATTRSET));
666 0 : rMenu.InsertSeparator(OString(), nPos++);
667 : }
668 : }
669 :
670 0 : rMenu.InsertItem(ID_BROWSER_COLWIDTH, aNewItems.GetItemText(ID_BROWSER_COLWIDTH), MenuItemBits::NONE, OString(), nPos++);
671 0 : rMenu.SetHelpId(ID_BROWSER_COLWIDTH, aNewItems.GetHelpId(ID_BROWSER_COLWIDTH));
672 0 : rMenu.InsertSeparator(OString(), nPos++);
673 : }
674 0 : }
675 :
676 0 : void SbaGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
677 : {
678 0 : switch (nExecutionResult)
679 : {
680 : case ID_BROWSER_COLWIDTH:
681 0 : static_cast<SbaGridControl*>(GetParent())->SetColWidth(nColId);
682 0 : break;
683 :
684 : case ID_BROWSER_COLATTRSET:
685 0 : static_cast<SbaGridControl*>(GetParent())->SetColAttrs(nColId);
686 0 : break;
687 : case ID_BROWSER_COLUMNINFO:
688 : {
689 0 : sal_uInt16 nModelPos = static_cast<SbaGridControl*>(GetParent())->GetModelColumnPos(nColId);
690 0 : Reference< XPropertySet > xField = static_cast<SbaGridControl*>(GetParent())->getField(nModelPos);
691 :
692 0 : if(!xField.is())
693 0 : break;
694 0 : ::std::vector< ::boost::shared_ptr<OTableRow> > vClipboardList;
695 : // send it to the clipboard
696 0 : vClipboardList.push_back(::boost::shared_ptr<OTableRow>(new OTableRow(xField)));
697 0 : OTableRowExchange* pData = new OTableRowExchange(vClipboardList);
698 0 : Reference< ::com::sun::star::datatransfer::XTransferable> xRef = pData;
699 0 : pData->CopyToClipboard(GetParent());
700 : }
701 0 : break;
702 :
703 0 : default: FmGridHeader::PostExecuteColumnContextMenu(nColId, rMenu, nExecutionResult);
704 : }
705 0 : }
706 :
707 : // SbaGridControl
708 41 : SbaGridControl::SbaGridControl(Reference< XComponentContext > _rM,
709 : vcl::Window* pParent, FmXGridPeer* _pPeer, WinBits nBits)
710 : :FmGridControl(_rM,pParent, _pPeer, nBits)
711 : ,m_pMasterListener(NULL)
712 : ,m_nAsyncDropEvent(0)
713 : ,m_nCurrentActionColId((sal_uInt16)-1)
714 41 : ,m_bActivatingForDrop(false)
715 : {
716 41 : }
717 :
718 123 : SbaGridControl::~SbaGridControl()
719 : {
720 41 : if (m_nAsyncDropEvent)
721 0 : Application::RemoveUserEvent(m_nAsyncDropEvent);
722 82 : }
723 :
724 41 : BrowserHeader* SbaGridControl::imp_CreateHeaderBar(BrowseBox* pParent)
725 : {
726 41 : return new SbaGridHeader(pParent);
727 : }
728 :
729 2 : CellController* SbaGridControl::GetController(long nRow, sal_uInt16 nCol)
730 : {
731 2 : if ( m_bActivatingForDrop )
732 0 : return NULL;
733 :
734 2 : return FmGridControl::GetController(nRow, nCol);
735 : }
736 :
737 0 : void SbaGridControl::PreExecuteRowContextMenu(sal_uInt16 nRow, PopupMenu& rMenu)
738 : {
739 0 : FmGridControl::PreExecuteRowContextMenu(nRow, rMenu);
740 :
741 0 : PopupMenu aNewItems(ModuleRes(RID_SBA_GRID_ROWCTXMENU));
742 0 : sal_uInt16 nPos = 0;
743 :
744 0 : if (!IsReadOnlyDB())
745 : {
746 0 : rMenu.InsertItem(ID_BROWSER_TABLEATTR, aNewItems.GetItemText(ID_BROWSER_TABLEATTR), MenuItemBits::NONE, OString(), nPos++);
747 0 : rMenu.SetHelpId(ID_BROWSER_TABLEATTR, aNewItems.GetHelpId(ID_BROWSER_TABLEATTR));
748 :
749 0 : rMenu.InsertItem(ID_BROWSER_ROWHEIGHT, aNewItems.GetItemText(ID_BROWSER_ROWHEIGHT), MenuItemBits::NONE, OString(), nPos++);
750 0 : rMenu.SetHelpId(ID_BROWSER_ROWHEIGHT, aNewItems.GetHelpId(ID_BROWSER_ROWHEIGHT));
751 0 : rMenu.InsertSeparator(OString(), nPos++);
752 : }
753 :
754 0 : if ( GetSelectRowCount() > 0 )
755 : {
756 0 : rMenu.InsertItem(ID_BROWSER_COPY, aNewItems.GetItemText(SID_COPY), MenuItemBits::NONE, OString(), nPos++);
757 0 : rMenu.SetHelpId(ID_BROWSER_COPY, aNewItems.GetHelpId(SID_COPY));
758 :
759 0 : rMenu.InsertSeparator(OString(), nPos++);
760 0 : }
761 0 : }
762 :
763 0 : SvNumberFormatter* SbaGridControl::GetDatasourceFormatter()
764 : {
765 0 : Reference< ::com::sun::star::util::XNumberFormatsSupplier > xSupplier = ::dbtools::getNumberFormats(::dbtools::getConnection(Reference< XRowSet > (getDataSource(),UNO_QUERY)), true, getContext());
766 :
767 0 : SvNumberFormatsSupplierObj* pSupplierImpl = SvNumberFormatsSupplierObj::getImplementation( xSupplier );
768 0 : if ( !pSupplierImpl )
769 0 : return NULL;
770 :
771 0 : SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter();
772 0 : return pFormatter;
773 : }
774 :
775 0 : void SbaGridControl::SetColWidth(sal_uInt16 nColId)
776 : {
777 : // get the (UNO) column model
778 0 : sal_uInt16 nModelPos = GetModelColumnPos(nColId);
779 0 : Reference< XIndexAccess > xCols(GetPeer()->getColumns(), UNO_QUERY);
780 0 : Reference< XPropertySet > xAffectedCol;
781 0 : if (xCols.is() && (nModelPos != (sal_uInt16)-1))
782 0 : xAffectedCol.set(xCols->getByIndex(nModelPos), css::uno::UNO_QUERY);
783 :
784 0 : if (xAffectedCol.is())
785 : {
786 0 : Any aWidth = xAffectedCol->getPropertyValue(PROPERTY_WIDTH);
787 0 : sal_Int32 nCurWidth = aWidth.hasValue() ? ::comphelper::getINT32(aWidth) : -1;
788 :
789 0 : DlgSize aDlgColWidth(this, nCurWidth, false);
790 0 : if (aDlgColWidth.Execute())
791 : {
792 0 : sal_Int32 nValue = aDlgColWidth.GetValue();
793 0 : Any aNewWidth;
794 0 : if (-1 == nValue)
795 : { // set to default
796 0 : Reference< XPropertyState > xPropState(xAffectedCol, UNO_QUERY);
797 0 : if (xPropState.is())
798 : {
799 0 : try { aNewWidth = xPropState->getPropertyDefault(PROPERTY_WIDTH); } catch(Exception&) { } ;
800 0 : }
801 : }
802 : else
803 0 : aNewWidth <<= nValue;
804 0 : try { xAffectedCol->setPropertyValue(PROPERTY_WIDTH, aNewWidth); } catch(Exception&) { } ;
805 0 : }
806 0 : }
807 0 : }
808 :
809 0 : void SbaGridControl::SetRowHeight()
810 : {
811 0 : Reference< XPropertySet > xCols(GetPeer()->getColumns(), UNO_QUERY);
812 0 : if (!xCols.is())
813 0 : return;
814 :
815 0 : Any aHeight = xCols->getPropertyValue(PROPERTY_ROW_HEIGHT);
816 0 : sal_Int32 nCurHeight = aHeight.hasValue() ? ::comphelper::getINT32(aHeight) : -1;
817 :
818 0 : DlgSize aDlgRowHeight(this, nCurHeight, true);
819 0 : if (aDlgRowHeight.Execute())
820 : {
821 0 : sal_Int32 nValue = aDlgRowHeight.GetValue();
822 0 : Any aNewHeight;
823 0 : if ((sal_Int16)-1 == nValue)
824 : { // set to default
825 0 : Reference< XPropertyState > xPropState(xCols, UNO_QUERY);
826 0 : if (xPropState.is())
827 : {
828 : try
829 : {
830 0 : aNewHeight = xPropState->getPropertyDefault(PROPERTY_ROW_HEIGHT);
831 : }
832 0 : catch(Exception&)
833 : { }
834 0 : }
835 : }
836 : else
837 0 : aNewHeight <<= nValue;
838 : try
839 : {
840 0 : xCols->setPropertyValue(PROPERTY_ROW_HEIGHT, aNewHeight);
841 : }
842 0 : catch(Exception&)
843 : {
844 : OSL_FAIL("setPropertyValue: PROPERTY_ROW_HEIGHT throws a exception");
845 0 : }
846 0 : }
847 : }
848 :
849 0 : void SbaGridControl::SetColAttrs(sal_uInt16 nColId)
850 : {
851 0 : SvNumberFormatter* pFormatter = GetDatasourceFormatter();
852 0 : if (!pFormatter)
853 0 : return;
854 :
855 0 : sal_uInt16 nModelPos = GetModelColumnPos(nColId);
856 :
857 : // get the (UNO) column model
858 0 : Reference< XIndexAccess > xCols(GetPeer()->getColumns(), UNO_QUERY);
859 0 : Reference< XPropertySet > xAffectedCol;
860 0 : if (xCols.is() && (nModelPos != (sal_uInt16)-1))
861 0 : xAffectedCol.set(xCols->getByIndex(nModelPos), css::uno::UNO_QUERY);
862 :
863 : // get the field the column is bound to
864 0 : Reference< XPropertySet > xField = getField(nModelPos);
865 0 : ::dbaui::callColumnFormatDialog(xAffectedCol,xField,pFormatter,this);//(Window::GetSettings().GetLanguage());
866 : }
867 :
868 0 : void SbaGridControl::SetBrowserAttrs()
869 : {
870 0 : Reference< XPropertySet > xGridModel(GetPeer()->getColumns(), UNO_QUERY);
871 0 : if (!xGridModel.is())
872 0 : return;
873 :
874 : try
875 : {
876 0 : Reference< XComponentContext > xContext = getContext();
877 0 : Reference< XExecutableDialog > xExecute = ControlFontDialog::createWithGridModel( xContext, xGridModel);
878 0 : xExecute->execute();
879 : }
880 0 : catch( const Exception& )
881 : {
882 : DBG_UNHANDLED_EXCEPTION();
883 0 : }
884 : }
885 :
886 0 : void SbaGridControl::PostExecuteRowContextMenu(sal_uInt16 nRow, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
887 : {
888 0 : switch (nExecutionResult)
889 : {
890 : case ID_BROWSER_TABLEATTR:
891 0 : SetBrowserAttrs();
892 0 : break;
893 : case ID_BROWSER_ROWHEIGHT:
894 0 : SetRowHeight();
895 0 : break;
896 : case ID_BROWSER_COPY:
897 0 : CopySelectedRowsToClipboard();
898 0 : break;
899 :
900 : default:
901 0 : FmGridControl::PostExecuteRowContextMenu(nRow, rMenu, nExecutionResult);
902 0 : break;
903 : }
904 0 : }
905 :
906 0 : void SbaGridControl::Select()
907 : {
908 : // Some selection has changed ...
909 0 : FmGridControl::Select();
910 :
911 0 : if (m_pMasterListener)
912 0 : m_pMasterListener->SelectionChanged();
913 0 : }
914 :
915 73 : void SbaGridControl::CursorMoved()
916 : {
917 73 : FmGridControl::CursorMoved();
918 73 : }
919 :
920 73 : void SbaGridControl::ActivateCell(long nRow, sal_uInt16 nCol, bool bSetCellFocus /*= sal_True*/ )
921 : {
922 73 : FmGridControl::ActivateCell(nRow, nCol, bSetCellFocus);
923 73 : if (m_pMasterListener)
924 12 : m_pMasterListener->CellActivated();
925 73 : }
926 :
927 33 : void SbaGridControl::DeactivateCell(bool bUpdate /*= sal_True*/)
928 : {
929 33 : FmGridControl::DeactivateCell(bUpdate);
930 33 : if (m_pMasterListener)
931 10 : m_pMasterListener->CellDeactivated();
932 33 : }
933 :
934 4 : void SbaGridControl::onRowChange()
935 : {
936 4 : if ( m_pMasterListener )
937 4 : m_pMasterListener->RowChanged();
938 4 : }
939 :
940 6 : void SbaGridControl::onColumnChange()
941 : {
942 6 : if ( m_pMasterListener )
943 6 : m_pMasterListener->ColumnChanged();
944 6 : }
945 :
946 0 : void SbaGridControl::BeforeDrop()
947 : {
948 0 : if (m_pMasterListener)
949 0 : m_pMasterListener->BeforeDrop();
950 0 : }
951 :
952 0 : void SbaGridControl::AfterDrop()
953 : {
954 0 : if (m_pMasterListener)
955 0 : m_pMasterListener->AfterDrop();
956 0 : }
957 :
958 0 : Reference< XPropertySet > SbaGridControl::getField(sal_uInt16 nModelPos)
959 : {
960 0 : Reference< XPropertySet > xEmptyReturn;
961 : try
962 : {
963 : // first get the name of the column
964 0 : Reference< XIndexAccess > xCols(GetPeer()->getColumns(), UNO_QUERY);
965 0 : if ( xCols.is() && xCols->getCount() > nModelPos )
966 : {
967 0 : Reference< XPropertySet > xCol(xCols->getByIndex(nModelPos),UNO_QUERY);
968 0 : if ( xCol.is() )
969 0 : xEmptyReturn.set(xCol->getPropertyValue(PROPERTY_BOUNDFIELD),UNO_QUERY);
970 : }
971 : else
972 0 : OSL_FAIL("SbaGridControl::getField getColumns returns NULL or ModelPos is > than count!");
973 : }
974 0 : catch (const Exception&)
975 : {
976 : OSL_FAIL("SbaGridControl::getField Exception occurred!");
977 : }
978 :
979 0 : return xEmptyReturn;
980 : }
981 :
982 0 : bool SbaGridControl::IsReadOnlyDB() const
983 : {
984 : // assume yes if anything fails
985 0 : bool bDBIsReadOnly = true;
986 :
987 : // the db is the implemented by the parent of the grid control's model ...
988 0 : Reference< XChild > xColumns(GetPeer()->getColumns(), UNO_QUERY);
989 0 : if (xColumns.is())
990 : {
991 0 : Reference< XRowSet > xDataSource(xColumns->getParent(), UNO_QUERY);
992 0 : Reference< XChild > xConn(::dbtools::getConnection(xDataSource),UNO_QUERY);
993 0 : if (xConn.is())
994 : {
995 : // ... and the RO-flag simply is implemented by a property
996 0 : Reference< XPropertySet > xDbProps(xConn->getParent(), UNO_QUERY);
997 0 : if (xDbProps.is())
998 : {
999 0 : Reference< XPropertySetInfo > xInfo = xDbProps->getPropertySetInfo();
1000 0 : if (xInfo->hasPropertyByName(PROPERTY_ISREADONLY))
1001 0 : bDBIsReadOnly = ::comphelper::getBOOL(xDbProps->getPropertyValue(PROPERTY_ISREADONLY));
1002 0 : }
1003 0 : }
1004 : }
1005 0 : return bDBIsReadOnly;
1006 : }
1007 :
1008 0 : void SbaGridControl::MouseButtonDown( const BrowserMouseEvent& rMEvt)
1009 : {
1010 0 : long nRow = GetRowAtYPosPixel(rMEvt.GetPosPixel().Y());
1011 0 : sal_uInt16 nColPos = GetColumnAtXPosPixel(rMEvt.GetPosPixel().X());
1012 0 : sal_uInt16 nViewPos = (nColPos == BROWSER_INVALIDID) ? (sal_uInt16)-1 : nColPos-1;
1013 : // 'the handle column' and 'no valid column' will both result in a view position of -1 !
1014 :
1015 0 : bool bHitEmptySpace = (nRow > GetRowCount()) || (nViewPos == (sal_uInt16)-1);
1016 :
1017 0 : if (bHitEmptySpace && (rMEvt.GetClicks() == 2) && rMEvt.IsMod1())
1018 0 : Control::MouseButtonDown(rMEvt);
1019 : else
1020 0 : FmGridControl::MouseButtonDown(rMEvt);
1021 0 : }
1022 :
1023 0 : void SbaGridControl::StartDrag( sal_Int8 _nAction, const Point& _rPosPixel )
1024 : {
1025 0 : SolarMutexGuard aGuard;
1026 : // in the new DnD API, the solar mutex is not locked when StartDrag get's called
1027 :
1028 0 : bool bHandled = false;
1029 :
1030 : do
1031 : {
1032 : // determine if dragging is allowed
1033 : // (Yes, this is controller (not view) functionality. But collecting and evaluating all the
1034 : // information necessary via UNO would be quite difficult (if not impossible) so
1035 : // my laziness says 'do it here' ...)
1036 0 : long nRow = GetRowAtYPosPixel(_rPosPixel.Y());
1037 0 : sal_uInt16 nColPos = GetColumnAtXPosPixel(_rPosPixel.X());
1038 0 : sal_uInt16 nViewPos = (nColPos == BROWSER_INVALIDID) ? (sal_uInt16)-1 : nColPos-1;
1039 : // 'the handle column' and 'no valid column' will both result in a view position of -1 !
1040 :
1041 0 : bool bCurrentRowVirtual = IsCurrentAppending() && IsModified();
1042 : // the current row doesn't really exist : the user's appendign a new one and already has entered some data,
1043 : // so the row contains data which has no counter part within the data source
1044 :
1045 0 : long nCorrectRowCount = GetRowCount();
1046 0 : if (GetOptions() & OPT_INSERT)
1047 0 : --nCorrectRowCount; // there is a empty row for inserting records
1048 0 : if (bCurrentRowVirtual)
1049 0 : --nCorrectRowCount;
1050 :
1051 0 : if ((nColPos == BROWSER_INVALIDID) || (nRow >= nCorrectRowCount))
1052 : break;
1053 :
1054 0 : bool bHitHandle = (nColPos == 0);
1055 :
1056 : // check which kind of dragging has to be initiated
1057 0 : if ( bHitHandle // the handle column
1058 : // AND
1059 0 : && ( GetSelectRowCount() // at least one row is selected
1060 : // OR
1061 0 : || ( (nRow >= 0) // a row below the header
1062 0 : && !bCurrentRowVirtual // we aren't appending a new record
1063 0 : && (nRow != GetCurrentPos()) // a row which is not the current one
1064 : ) // OR
1065 0 : || ( (0 == GetSelectRowCount()) // no rows selected
1066 0 : && (-1 == nRow) // hit the header
1067 : )
1068 : )
1069 : )
1070 : { // => start dragging the row
1071 0 : if (GetDataWindow().IsMouseCaptured())
1072 0 : GetDataWindow().ReleaseMouse();
1073 :
1074 0 : if (0 == GetSelectRowCount())
1075 : // no rows selected, but here in this branch
1076 : // -> the user started dragging the upper left corner, which symbolizes the whole table
1077 0 : SelectAll();
1078 :
1079 0 : getMouseEvent().Clear();
1080 0 : DoRowDrag((sal_Int16)nRow);
1081 :
1082 0 : bHandled = true;
1083 : }
1084 0 : else if ( (nRow < 0) // the header
1085 0 : && (!bHitHandle) // non-handle column
1086 0 : && (nViewPos < GetViewColCount()) // valid (existing) column
1087 : )
1088 : { // => start dragging the column
1089 0 : if (GetDataWindow().IsMouseCaptured())
1090 0 : GetDataWindow().ReleaseMouse();
1091 :
1092 0 : getMouseEvent().Clear();
1093 0 : DoColumnDrag(nViewPos);
1094 :
1095 0 : bHandled = true;
1096 : }
1097 0 : else if ( !bHitHandle // non-handle column
1098 0 : && (nRow >= 0) // non-header row
1099 : )
1100 : { // => start dragging the field content
1101 0 : if (GetDataWindow().IsMouseCaptured())
1102 0 : GetDataWindow().ReleaseMouse();
1103 :
1104 0 : getMouseEvent().Clear();
1105 0 : DoFieldDrag(nViewPos, (sal_Int16)nRow);
1106 :
1107 0 : bHandled = true;
1108 : }
1109 : }
1110 : while (false);
1111 :
1112 0 : if (!bHandled)
1113 0 : FmGridControl::StartDrag(_nAction, _rPosPixel);
1114 0 : }
1115 :
1116 0 : void SbaGridControl::Command(const CommandEvent& rEvt)
1117 : {
1118 0 : FmGridControl::Command(rEvt);
1119 0 : }
1120 :
1121 0 : void SbaGridControl::DoColumnDrag(sal_uInt16 nColumnPos)
1122 : {
1123 0 : Reference< XPropertySet > xDataSource(getDataSource(), UNO_QUERY);
1124 : OSL_ENSURE(xDataSource.is(), "SbaGridControl::DoColumnDrag : invalid data source !");
1125 :
1126 0 : Reference< XPropertySet > xAffectedCol;
1127 0 : Reference< XPropertySet > xAffectedField;
1128 0 : Reference< XConnection > xActiveConnection;
1129 :
1130 : // determine the field to drag
1131 0 : OUString sField;
1132 : try
1133 : {
1134 0 : xActiveConnection = ::dbtools::getConnection(Reference< XRowSet >(getDataSource(),UNO_QUERY));
1135 :
1136 0 : sal_uInt16 nModelPos = GetModelColumnPos(GetColumnIdFromViewPos(nColumnPos));
1137 0 : Reference< XIndexContainer > xCols(GetPeer()->getColumns(), UNO_QUERY);
1138 0 : xAffectedCol.set(xCols->getByIndex(nModelPos),UNO_QUERY);
1139 0 : if (xAffectedCol.is())
1140 : {
1141 0 : xAffectedCol->getPropertyValue(PROPERTY_CONTROLSOURCE) >>= sField;
1142 0 : xAffectedField.set(xAffectedCol->getPropertyValue(PROPERTY_BOUNDFIELD),UNO_QUERY);
1143 0 : }
1144 : }
1145 0 : catch(Exception&)
1146 : {
1147 : OSL_FAIL("SbaGridControl::DoColumnDrag : something went wrong while getting the column");
1148 : }
1149 0 : if (sField.isEmpty())
1150 0 : return;
1151 :
1152 0 : OColumnTransferable* pDataTransfer = new OColumnTransferable(xDataSource, sField, xAffectedField, xActiveConnection, CTF_FIELD_DESCRIPTOR | CTF_COLUMN_DESCRIPTOR);
1153 0 : Reference< XTransferable > xEnsureDelete = pDataTransfer;
1154 0 : pDataTransfer->StartDrag(this, DND_ACTION_COPY | DND_ACTION_LINK);
1155 : }
1156 :
1157 0 : void SbaGridControl::CopySelectedRowsToClipboard()
1158 : {
1159 : OSL_ENSURE( GetSelectRowCount() > 0, "SbaGridControl::CopySelectedRowsToClipboard: invalid call!" );
1160 0 : implTransferSelectedRows( (sal_Int16)FirstSelectedRow(), true );
1161 0 : }
1162 :
1163 0 : void SbaGridControl::DoRowDrag( sal_Int16 nRowPos )
1164 : {
1165 0 : implTransferSelectedRows( nRowPos, false );
1166 0 : }
1167 :
1168 0 : void SbaGridControl::implTransferSelectedRows( sal_Int16 nRowPos, bool _bTrueIfClipboardFalseIfDrag )
1169 : {
1170 0 : Reference< XPropertySet > xForm( getDataSource(), UNO_QUERY );
1171 : OSL_ENSURE( xForm.is(), "SbaGridControl::implTransferSelectedRows: invalid form!" );
1172 :
1173 : // build the sequence of numbers of selected rows
1174 0 : Sequence< Any > aSelectedRows;
1175 0 : bool bSelectionBookmarks = true;
1176 :
1177 : // collect the affected rows
1178 0 : if ((GetSelectRowCount() == 0) && (nRowPos >= 0))
1179 : {
1180 0 : aSelectedRows.realloc( 1 );
1181 0 : aSelectedRows[0] <<= (sal_Int32)(nRowPos + 1);
1182 0 : bSelectionBookmarks = false;
1183 : }
1184 0 : else if ( !IsAllSelected() && GetSelectRowCount() )
1185 : {
1186 0 : aSelectedRows = getSelectionBookmarks();
1187 0 : bSelectionBookmarks = true;
1188 : }
1189 :
1190 0 : Reference< XResultSet> xRowSetClone;
1191 : try
1192 : {
1193 0 : ODataClipboard* pTransfer = new ODataClipboard( xForm, aSelectedRows, bSelectionBookmarks, getContext() );
1194 :
1195 0 : Reference< XTransferable > xEnsureDelete = pTransfer;
1196 0 : if ( _bTrueIfClipboardFalseIfDrag )
1197 0 : pTransfer->CopyToClipboard( this );
1198 : else
1199 0 : pTransfer->StartDrag(this, DND_ACTION_COPY | DND_ACTION_LINK);
1200 : }
1201 0 : catch(Exception&)
1202 : {
1203 0 : }
1204 0 : }
1205 :
1206 0 : void SbaGridControl::DoFieldDrag(sal_uInt16 nColumnPos, sal_Int16 nRowPos)
1207 : {
1208 : // the only thing to do here is dragging the pure cell text
1209 : // the old implementation copied a SBA_FIELDDATAEXCHANGE_FORMAT, too, (which was rather expensive to obtain),
1210 : // but we have no client for this DnD format anymore (the mail part of SO 5.2 was the only client)
1211 :
1212 0 : OUString sCellText;
1213 : try
1214 : {
1215 0 : Reference< XGridFieldDataSupplier > xFieldData(static_cast< XGridPeer* >(GetPeer()), UNO_QUERY);
1216 0 : Sequence<sal_Bool> aSupportingText = xFieldData->queryFieldDataType(::getCppuType(&sCellText));
1217 0 : if (aSupportingText.getConstArray()[nColumnPos])
1218 : {
1219 0 : Sequence< Any> aCellContents = xFieldData->queryFieldData(nRowPos, ::getCppuType(&sCellText));
1220 0 : sCellText = ::comphelper::getString(aCellContents.getConstArray()[nColumnPos]);
1221 0 : ::svt::OStringTransfer::StartStringDrag(sCellText, this, DND_ACTION_COPY);
1222 0 : }
1223 : }
1224 0 : catch(Exception&)
1225 : {
1226 : OSL_FAIL("SbaGridControl::DoFieldDrag : could not retrieve the cell's contents !");
1227 0 : return;
1228 0 : }
1229 :
1230 : }
1231 :
1232 : /// unary_function Functor object for class ZZ returntype is void
1233 : struct SbaGridControlPrec : ::std::unary_function<DataFlavorExVector::value_type,bool>
1234 : {
1235 : bool bQueryDrop;
1236 0 : SbaGridControlPrec(bool _bQueryDrop)
1237 0 : : bQueryDrop(_bQueryDrop)
1238 : {
1239 0 : }
1240 :
1241 0 : inline bool operator()(const DataFlavorExVector::value_type& _aType)
1242 : {
1243 0 : switch (_aType.mnSotId)
1244 : {
1245 : case SOT_FORMATSTR_ID_DBACCESS_TABLE: // table descriptor
1246 : case SOT_FORMATSTR_ID_DBACCESS_QUERY: // query descriptor
1247 : case SOT_FORMATSTR_ID_DBACCESS_COMMAND: // SQL command
1248 0 : return true;
1249 : }
1250 0 : return false;
1251 : }
1252 : };
1253 0 : sal_Int8 SbaGridControl::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
1254 : {
1255 0 : sal_Int8 nAction = DND_ACTION_NONE;
1256 :
1257 : // we need a valid connection
1258 0 : if (!::dbtools::getConnection(Reference< XRowSet > (getDataSource(),UNO_QUERY)).is())
1259 0 : return nAction;
1260 :
1261 0 : if ( IsDropFormatSupported( FORMAT_STRING ) ) do
1262 : { // odd construction, but spares us a lot of (explicit ;) goto's
1263 :
1264 0 : if (!GetEmptyRow().Is())
1265 : // without an empty row we're not in update mode
1266 0 : break;
1267 :
1268 0 : long nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
1269 0 : sal_uInt16 nCol = GetColumnAtXPosPixel(rEvt.maPosPixel.X(), false);
1270 :
1271 0 : long nCorrectRowCount = GetRowCount();
1272 0 : if (GetOptions() & OPT_INSERT)
1273 0 : --nCorrectRowCount; // there is a empty row for inserting records
1274 0 : if (IsCurrentAppending())
1275 0 : --nCorrectRowCount; // the current data record doesn't really exist, we are appending a new one
1276 :
1277 0 : if ((nCol == BROWSER_INVALIDID) || (nRow >= nCorrectRowCount) || GetColumnId(nCol) == 0 || GetColumnId(nCol) == BROWSER_INVALIDID )
1278 : // no valid cell under the mouse cursor
1279 0 : break;
1280 :
1281 0 : Rectangle aRect = GetCellRect(nRow, nCol, false);
1282 0 : if (!aRect.IsInside(rEvt.maPosPixel))
1283 : // not dropped within a cell (a cell isn't as wide as the column - the are small spaces)
1284 0 : break;
1285 :
1286 0 : if ((IsModified() || (GetCurrentRow().Is() && GetCurrentRow()->IsModified())) && (GetCurrentPos() != nRow))
1287 : // there is a current and modified row or cell and he text is to be dropped into another one
1288 0 : break;
1289 :
1290 0 : CellControllerRef xCurrentController = Controller();
1291 0 : if (xCurrentController.Is() && xCurrentController->IsModified() && ((nRow != GetCurRow()) || (nCol != GetCurColumnId())))
1292 : // the current controller is modified and the user wants to drop in another cell -> no chance
1293 : // (when leaving the modified cell a error may occur - this is deadly while dragging)
1294 0 : break;
1295 :
1296 0 : Reference< XPropertySet > xField = getField(GetModelColumnPos(nCol));
1297 0 : if (!xField.is())
1298 : // the column is not valid bound (for instance a binary field)
1299 0 : break;
1300 :
1301 : try
1302 : {
1303 0 : if (::comphelper::getBOOL(xField->getPropertyValue(PROPERTY_ISREADONLY)))
1304 0 : break;
1305 : }
1306 0 : catch (const Exception& e )
1307 : {
1308 : (void)e; // make compiler happy
1309 : // assume RO
1310 0 : break;
1311 : }
1312 :
1313 : try
1314 : {
1315 : // assume that text can be dropped into a field if the column has a ::com::sun::star::awt::XTextComponent interface
1316 0 : Reference< XIndexAccess > xColumnControls((::com::sun::star::form::XGridPeer*)GetPeer(), UNO_QUERY);
1317 0 : if (xColumnControls.is())
1318 : {
1319 : Reference< ::com::sun::star::awt::XTextComponent > xColControl(
1320 0 : xColumnControls->getByIndex(GetViewColumnPos(nCol)),
1321 0 : css::uno::UNO_QUERY);
1322 0 : if (xColControl.is())
1323 : {
1324 0 : m_bActivatingForDrop = true;
1325 0 : GoToRowColumnId(nRow, nCol);
1326 0 : m_bActivatingForDrop = false;
1327 :
1328 0 : nAction = DND_ACTION_COPY;
1329 0 : }
1330 0 : }
1331 : }
1332 0 : catch( const Exception& )
1333 : {
1334 : DBG_UNHANDLED_EXCEPTION();
1335 0 : }
1336 :
1337 : } while (false);
1338 :
1339 0 : if(nAction != DND_ACTION_COPY && GetEmptyRow().Is())
1340 : {
1341 0 : const DataFlavorExVector& _rFlavors = GetDataFlavors();
1342 0 : if(::std::find_if(_rFlavors.begin(),_rFlavors.end(),SbaGridControlPrec(true)) != _rFlavors.end())
1343 0 : nAction = DND_ACTION_COPY;
1344 : }
1345 :
1346 0 : return (DND_ACTION_NONE != nAction) ? nAction : FmGridControl::AcceptDrop(rEvt);
1347 : }
1348 :
1349 0 : sal_Int8 SbaGridControl::ExecuteDrop( const BrowserExecuteDropEvent& rEvt )
1350 : {
1351 : // we need some properties of our data source
1352 0 : Reference< XPropertySet > xDataSource = getDataSource();
1353 0 : if (!xDataSource.is())
1354 0 : return DND_ACTION_NONE;
1355 :
1356 : // we need a valid connection
1357 0 : if (!::dbtools::getConnection(Reference< XRowSet > (xDataSource,UNO_QUERY)).is())
1358 0 : return DND_ACTION_NONE;
1359 :
1360 0 : if ( IsDropFormatSupported( FORMAT_STRING ) )
1361 : {
1362 0 : long nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
1363 0 : sal_uInt16 nCol = GetColumnAtXPosPixel(rEvt.maPosPixel.X(), false);
1364 :
1365 0 : long nCorrectRowCount = GetRowCount();
1366 0 : if (GetOptions() & OPT_INSERT)
1367 0 : --nCorrectRowCount; // there is a empty row for inserting records
1368 0 : if (IsCurrentAppending())
1369 0 : --nCorrectRowCount; // the current data record doesn't really exist, we are appending a new one
1370 :
1371 : OSL_ENSURE((nCol != BROWSER_INVALIDID) && (nRow < nCorrectRowCount), "SbaGridControl::Drop : dropped on an invalid position !");
1372 : // AcceptDrop should have caught this
1373 :
1374 : // from now we work with ids instead of positions
1375 0 : nCol = GetColumnId(nCol);
1376 :
1377 0 : GoToRowColumnId(nRow, nCol);
1378 0 : if (!IsEditing())
1379 0 : ActivateCell();
1380 :
1381 0 : CellControllerRef xCurrentController = Controller();
1382 0 : if (!xCurrentController.Is() || !xCurrentController->ISA(EditCellController))
1383 0 : return DND_ACTION_NONE;
1384 0 : Edit& rEdit = static_cast<Edit&>(xCurrentController->GetWindow());
1385 :
1386 : // get the dropped string
1387 0 : TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
1388 0 : OUString sDropped;
1389 0 : if ( !aDropped.GetString( FORMAT_STRING, sDropped ) )
1390 0 : return DND_ACTION_NONE;
1391 :
1392 0 : rEdit.SetText( sDropped );
1393 0 : xCurrentController->SetModified();
1394 0 : rEdit.Modify();
1395 : // SetText itself doesn't call a Modify as it isn't a user interaction
1396 :
1397 0 : return DND_ACTION_COPY;
1398 : }
1399 :
1400 0 : if(GetEmptyRow().Is())
1401 : {
1402 0 : const DataFlavorExVector& _rFlavors = GetDataFlavors();
1403 0 : DataFlavorExVector::const_iterator aFind = ::std::find_if(_rFlavors.begin(),_rFlavors.end(),SbaGridControlPrec(true));
1404 0 : if( aFind != _rFlavors.end())
1405 : {
1406 0 : TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
1407 0 : m_aDataDescriptor = ODataAccessObjectTransferable::extractObjectDescriptor(aDropped);
1408 0 : if (m_nAsyncDropEvent)
1409 0 : Application::RemoveUserEvent(m_nAsyncDropEvent);
1410 0 : m_nAsyncDropEvent = Application::PostUserEvent(LINK(this, SbaGridControl, AsynchDropEvent));
1411 0 : return DND_ACTION_COPY;
1412 : }
1413 : }
1414 :
1415 0 : return DND_ACTION_NONE;
1416 : }
1417 :
1418 0 : Reference< XPropertySet > SbaGridControl::getDataSource() const
1419 : {
1420 0 : Reference< XPropertySet > xReturn;
1421 :
1422 0 : Reference< XChild > xColumns(GetPeer()->getColumns(), UNO_QUERY);
1423 0 : Reference< XPropertySet > xDataSource;
1424 0 : if (xColumns.is())
1425 0 : xReturn = Reference< XPropertySet > (xColumns->getParent(), UNO_QUERY);
1426 :
1427 0 : return xReturn;
1428 : }
1429 :
1430 0 : IMPL_LINK(SbaGridControl, AsynchDropEvent, void*, /*EMPTY_ARG*/)
1431 : {
1432 0 : m_nAsyncDropEvent = 0;
1433 :
1434 0 : Reference< XPropertySet > xDataSource = getDataSource();
1435 0 : if ( xDataSource.is() )
1436 : {
1437 0 : bool bCountFinal = false;
1438 0 : xDataSource->getPropertyValue(PROPERTY_ISROWCOUNTFINAL) >>= bCountFinal;
1439 0 : if ( !bCountFinal )
1440 0 : setDataSource(NULL); // deattach from grid control
1441 0 : Reference< XResultSetUpdate > xResultSetUpdate(xDataSource,UNO_QUERY);
1442 0 : ODatabaseImportExport* pImExport = new ORowSetImportExport(this,xResultSetUpdate,m_aDataDescriptor, getContext());
1443 0 : Reference<XEventListener> xHolder = pImExport;
1444 0 : Hide();
1445 : try
1446 : {
1447 0 : pImExport->initialize(m_aDataDescriptor);
1448 0 : BeforeDrop();
1449 0 : if(!pImExport->Read())
1450 : {
1451 0 : OUString sError = OUString(ModuleRes(STR_NO_COLUMNNAME_MATCHING));
1452 0 : throwGenericSQLException(sError,NULL);
1453 : }
1454 0 : AfterDrop();
1455 0 : Show();
1456 : }
1457 0 : catch(const SQLException& e)
1458 : {
1459 0 : AfterDrop();
1460 0 : Show();
1461 0 : ::dbaui::showError( ::dbtools::SQLExceptionInfo(e), this, getContext() );
1462 : }
1463 0 : catch(const Exception& )
1464 : {
1465 0 : AfterDrop();
1466 0 : Show();
1467 : DBG_UNHANDLED_EXCEPTION();
1468 : }
1469 0 : if ( !bCountFinal )
1470 0 : setDataSource(Reference< XRowSet >(xDataSource,UNO_QUERY));
1471 : }
1472 0 : m_aDataDescriptor.clear();
1473 :
1474 0 : return 0L;
1475 : }
1476 :
1477 0 : OUString SbaGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType eObjType,sal_Int32 _nPosition) const
1478 : {
1479 0 : OUString sRet;
1480 0 : if ( ::svt::BBTYPE_BROWSEBOX == eObjType )
1481 : {
1482 0 : SolarMutexGuard aGuard;
1483 0 : sRet = OUString(ModuleRes(STR_DATASOURCE_GRIDCONTROL_DESC));
1484 : }
1485 : else
1486 0 : sRet = FmGridControl::GetAccessibleObjectDescription( eObjType,_nPosition);
1487 0 : return sRet;
1488 : }
1489 :
1490 0 : void SbaGridControl::DeleteSelectedRows()
1491 : {
1492 0 : FmGridControl::DeleteSelectedRows();
1493 72 : }
1494 :
1495 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|