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