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