1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include "AddField.hxx"
20 #include "UITools.hxx"
21 #include <boost/noncopyable.hpp>
22 #include <svx/dbaexchange.hxx>
23 #include <svx/svdpagv.hxx>
24 #include <com/sun/star/sdb/CommandType.hpp>
25 #include <com/sun/star/util/URL.hpp>
26 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
27 #include <com/sun/star/i18n/XCollator.hpp>
29 #include <vcl/waitobj.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/settings.hxx>
33 #include <tools/diagnose_ex.h>
34 #include "rptui_slotid.hrc"
36 #include <connectivity/dbtools.hxx>
37 #include "helpids.hrc"
38 #include "RptResId.hrc"
39 #include "CondFormat.hrc"
40 #include "ModuleHelper.hxx"
41 #include "uistrings.hrc"
42 #include "ColumnInfo.hxx"
44 #include <comphelper/property.hxx>
45 #include <svtools/imgdef.hxx>
46 #include <svtools/treelistentry.hxx>
50 const long STD_WIN_SIZE_X
= 180;
51 const long STD_WIN_SIZE_Y
= 320;
53 using namespace ::com::sun::star
;
57 using namespace datatransfer
;
58 using namespace beans
;
60 using namespace container
;
61 using namespace ::svx
;
63 class OAddFieldWindowListBox
: public SvTreeListBox
65 VclPtr
<OAddFieldWindow
> m_pTabWin
;
68 OAddFieldWindowListBox( OAddFieldWindow
* _pParent
);
69 virtual ~OAddFieldWindowListBox();
70 virtual void dispose() SAL_OVERRIDE
;
72 sal_Int8
AcceptDrop( const AcceptDropEvent
& rEvt
) SAL_OVERRIDE
;
73 sal_Int8
ExecuteDrop( const ExecuteDropEvent
& rEvt
) SAL_OVERRIDE
;
75 uno::Sequence
< beans::PropertyValue
> getSelectedFieldDescriptors();
79 virtual void StartDrag( sal_Int8 nAction
, const Point
& rPosPixel
) SAL_OVERRIDE
;
82 using SvTreeListBox::ExecuteDrop
;
85 uno::Sequence
< beans::PropertyValue
> OAddFieldWindowListBox::getSelectedFieldDescriptors()
87 uno::Sequence
< beans::PropertyValue
> aArgs(GetSelectionCount());
89 SvTreeListEntry
* pSelected
= FirstSelected();
92 // build a descriptor for the currently selected field
93 svx::ODataAccessDescriptor aDescriptor
;
94 m_pTabWin
->fillDescriptor(pSelected
,aDescriptor
);
95 aArgs
[i
++].Value
<<= aDescriptor
.createPropertyValueSequence();
96 pSelected
= NextSelected(pSelected
);
101 // class OAddFieldWindowListBox
104 OAddFieldWindowListBox::OAddFieldWindowListBox( OAddFieldWindow
* _pParent
)
105 :SvTreeListBox( _pParent
, WB_TABSTOP
|WB_BORDER
|WB_SORT
)
106 ,m_pTabWin( _pParent
)
108 SetHelpId( HID_RPT_FIELD_SEL
);
109 SetSelectionMode(MULTIPLE_SELECTION
);
110 SetDragDropMode( DragDropMode::ALL
);
111 SetHighlightRange( );
115 OAddFieldWindowListBox::~OAddFieldWindowListBox()
120 void OAddFieldWindowListBox::dispose()
123 SvTreeListBox::dispose();
126 sal_Int8
OAddFieldWindowListBox::AcceptDrop( const AcceptDropEvent
& /*rEvt*/ )
128 return DND_ACTION_NONE
;
132 sal_Int8
OAddFieldWindowListBox::ExecuteDrop( const ExecuteDropEvent
& /*rEvt*/ )
134 return DND_ACTION_NONE
;
138 void OAddFieldWindowListBox::StartDrag( sal_Int8
/*_nAction*/, const Point
& /*_rPosPixel*/ )
140 if ( GetSelectionCount() < 1 )
141 // no drag without a field
144 OMultiColumnTransferable
* pDataContainer
= new OMultiColumnTransferable(getSelectedFieldDescriptors());
145 Reference
< XTransferable
> xEnsureDelete
= pDataContainer
;
148 pDataContainer
->StartDrag( this, DND_ACTION_COPYMOVE
| DND_ACTION_LINK
);
151 // class OAddFieldWindow
154 OAddFieldWindow::OAddFieldWindow(vcl::Window
* pParent
155 ,const uno::Reference
< beans::XPropertySet
>& _xRowSet
157 :FloatingWindow(pParent
, WinBits(WB_STDMODELESS
|WB_SIZEABLE
))
158 ,::comphelper::OPropertyChangeListener(m_aMutex
)
159 ,::comphelper::OContainerListener(m_aMutex
)
161 ,m_aActions(VclPtr
<ToolBox
>::Create(this,ModuleRes(RID_TB_SORTING
)))
162 ,m_pListBox(VclPtr
<OAddFieldWindowListBox
>::Create( this ))
163 ,m_aFixedLine(VclPtr
<FixedLine
>::Create(this, ModuleRes(ADDFIELD_FL_HELP_SEPARATOR
) ))
164 ,m_aHelpText(VclPtr
<FixedText
>::Create(this, ModuleRes(ADDFIELD_HELP_FIELD
) ))
165 ,m_aInsertButton(VclPtr
<PushButton
>::Create(this, WB_TABSTOP
|WB_CENTER
))
167 ,m_bEscapeProcessing(false)
168 ,m_pChangeListener(NULL
)
169 ,m_pContainerListener(NULL
)
171 SetHelpId( HID_RPT_FIELD_SEL_WIN
);
172 SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
173 SetMinOutputSizePixel(Size(STD_WIN_SIZE_X
,STD_WIN_SIZE_Y
));
175 m_aActions
->SetStyle(m_aActions
->GetStyle()|WB_LINESPACING
);
176 m_aActions
->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
178 m_aActions
->SetSelectHdl(LINK(this, OAddFieldWindow
, OnSortAction
));
179 setToolBox(m_aActions
.get());
180 m_aActions
->CheckItem(SID_FM_SORTUP
);
181 m_aActions
->EnableItem(SID_ADD_CONTROL_PAIR
, false);
183 m_pListBox
->SetDoubleClickHdl(LINK( this, OAddFieldWindow
, OnDoubleClickHdl
) );
184 m_pListBox
->SetSelectHdl(LINK( this, OAddFieldWindow
, OnSelectHdl
) );
185 m_pListBox
->SetDeselectHdl(LINK( this, OAddFieldWindow
, OnSelectHdl
) );
186 m_pListBox
->SetDoubleClickHdl(LINK( this, OAddFieldWindow
, OnDoubleClickHdl
) );
188 const OUString
sTitle(ModuleRes(RID_STR_INSERT
));
189 m_aInsertButton
->SetText(sTitle
);
190 m_aInsertButton
->SetClickHdl(LINK( this, OAddFieldWindow
, OnDoubleClickHdl
) );
191 m_aInsertButton
->Show();
193 m_aFixedLine
->SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
194 m_aHelpText
->SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
196 SetSizePixel(Size(STD_WIN_SIZE_X
,STD_WIN_SIZE_Y
));
198 if ( m_xRowSet
.is() )
202 // be notified when the settings of report definition change
203 m_pChangeListener
= new ::comphelper::OPropertyChangeMultiplexer( this, m_xRowSet
);
204 m_pChangeListener
->addProperty( PROPERTY_COMMAND
);
205 m_pChangeListener
->addProperty( PROPERTY_COMMANDTYPE
);
206 m_pChangeListener
->addProperty( PROPERTY_ESCAPEPROCESSING
);
207 m_pChangeListener
->addProperty( PROPERTY_FILTER
);
209 catch( const Exception
& )
211 DBG_UNHANDLED_EXCEPTION();
217 OAddFieldWindow::~OAddFieldWindow()
222 void OAddFieldWindow::dispose()
224 if ( m_pListBox
.get() )
226 SvTreeList
* pModel
= m_pListBox
->GetModel();
227 sal_uLong nCount
= pModel
->GetEntryCount();
228 for(sal_uLong i
= 0; i
< nCount
;++i
)
230 delete static_cast<ColumnInfo
*>(pModel
->GetEntry(i
)->GetUserData());
233 if (m_pChangeListener
.is())
234 m_pChangeListener
->dispose();
235 if ( m_pContainerListener
.is() )
236 m_pContainerListener
->dispose();
238 m_aActions
.disposeAndClear();
239 m_aFixedLine
.disposeAndClear();
240 m_aHelpText
.disposeAndClear();
241 m_aInsertButton
.disposeAndClear();
242 m_pListBox
.disposeAndClear();
243 FloatingWindow::dispose();
247 void OAddFieldWindow::GetFocus()
249 if ( m_pListBox
.get() )
250 m_pListBox
->GrabFocus();
252 FloatingWindow::GetFocus();
255 uno::Sequence
< beans::PropertyValue
> OAddFieldWindow::getSelectedFieldDescriptors()
257 return m_pListBox
->getSelectedFieldDescriptors();
261 bool OAddFieldWindow::PreNotify( NotifyEvent
& _rNEvt
)
263 if ( MouseNotifyEvent::KEYINPUT
== _rNEvt
.GetType() )
265 const vcl::KeyCode
& rKeyCode
= _rNEvt
.GetKeyEvent()->GetKeyCode();
266 if ( ( 0 == rKeyCode
.GetModifier() ) && ( KEY_RETURN
== rKeyCode
.GetCode() ) )
268 if ( m_aCreateLink
.IsSet() )
270 m_aCreateLink
.Call(this);
276 return FloatingWindow::PreNotify( _rNEvt
);
279 void OAddFieldWindow::_propertyChanged( const beans::PropertyChangeEvent
& _evt
) throw( uno::RuntimeException
)
281 OSL_ENSURE( _evt
.Source
== m_xRowSet
, "OAddFieldWindow::_propertyChanged: where did this come from?" );
289 void lcl_addToList( OAddFieldWindowListBox
& _rListBox
, const uno::Sequence
< OUString
>& _rEntries
)
291 const OUString
* pEntries
= _rEntries
.getConstArray();
292 sal_Int32 nEntries
= _rEntries
.getLength();
293 for ( sal_Int32 i
= 0; i
< nEntries
; ++i
, ++pEntries
)
294 _rListBox
.InsertEntry( *pEntries
,NULL
,false,TREELIST_APPEND
,new ColumnInfo(*pEntries
) );
296 void lcl_addToList( OAddFieldWindowListBox
& _rListBox
, const uno::Reference
< container::XNameAccess
>& i_xColumns
)
298 uno::Sequence
< OUString
> aEntries
= i_xColumns
->getElementNames();
299 const OUString
* pEntries
= aEntries
.getConstArray();
300 sal_Int32 nEntries
= aEntries
.getLength();
301 for ( sal_Int32 i
= 0; i
< nEntries
; ++i
, ++pEntries
)
303 uno::Reference
< beans::XPropertySet
> xColumn(i_xColumns
->getByName(*pEntries
),UNO_QUERY_THROW
);
305 if ( xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL
) )
306 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sLabel
;
307 if ( !sLabel
.isEmpty() )
308 _rListBox
.InsertEntry( sLabel
,NULL
,false,TREELIST_APPEND
,new ColumnInfo(*pEntries
,sLabel
) );
310 _rListBox
.InsertEntry( *pEntries
,NULL
,false,TREELIST_APPEND
,new ColumnInfo(*pEntries
,sLabel
) );
316 void OAddFieldWindow::Update()
318 SolarMutexGuard aSolarGuard
;
320 if ( m_pContainerListener
.is() )
321 m_pContainerListener
->dispose();
322 m_pContainerListener
= NULL
;
329 const sal_uInt16 nItemCount
= m_aActions
->GetItemCount();
330 for (sal_uInt16 j
= 0; j
< nItemCount
; ++j
)
332 m_aActions
->EnableItem(m_aActions
->GetItemId(j
),false);
335 OUString
aTitle(ModuleRes(RID_STR_FIELDSELECTION
));
337 if ( m_xRowSet
.is() )
339 OUString
sCommand( m_aCommandName
);
340 sal_Int32
nCommandType( m_nCommandType
);
341 bool bEscapeProcessing( m_bEscapeProcessing
);
342 OUString
sFilter( m_sFilter
);
344 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_COMMAND
) >>= sCommand
);
345 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_COMMANDTYPE
) >>= nCommandType
);
346 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_ESCAPEPROCESSING
) >>= bEscapeProcessing
);
347 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
);
349 m_aCommandName
= sCommand
;
350 m_nCommandType
= nCommandType
;
351 m_bEscapeProcessing
= bEscapeProcessing
;
354 // add the columns to the list
355 uno::Reference
< sdbc::XConnection
> xCon
= getConnection();
356 if ( xCon
.is() && !m_aCommandName
.isEmpty() )
357 m_xColumns
= dbtools::getFieldsByCommandDescriptor( xCon
, GetCommandType(), GetCommand(), m_xHoldAlive
);
358 if ( m_xColumns
.is() )
360 lcl_addToList( *m_pListBox
, m_xColumns
);
361 uno::Reference
< container::XContainer
> xContainer(m_xColumns
,uno::UNO_QUERY
);
362 if ( xContainer
.is() )
363 m_pContainerListener
= new ::comphelper::OContainerListenerAdapter(this,xContainer
);
366 // add the parameter columns to the list
367 uno::Reference
< ::com::sun::star::sdbc::XRowSet
> xRowSet(m_xRowSet
,uno::UNO_QUERY
);
368 Sequence
< OUString
> aParamNames( getParameterNames( xRowSet
) );
369 lcl_addToList( *m_pListBox
, aParamNames
);
372 aTitle
+= " " + OUString( m_aCommandName
.getStr() );
374 if ( !m_aCommandName
.isEmpty() )
376 for (sal_uInt16 i
= 0; i
< nItemCount
; ++i
)
378 m_aActions
->EnableItem(m_aActions
->GetItemId(i
));
384 catch( const Exception
& )
386 DBG_UNHANDLED_EXCEPTION();
391 void OAddFieldWindow::Resize()
393 FloatingWindow::Resize();
395 const Size
aWindowSize( GetOutputSizePixel() );
398 const Size
aRelated(LogicToPixel( Size( RELATED_CONTROLS
, RELATED_CONTROLS
), MAP_APPFONT
));
399 const Size
aFixedTextSize(LogicToPixel( Size( FIXEDTEXT_WIDTH
, FIXEDTEXT_HEIGHT
), MAP_APPFONT
));
402 Size
aToolbarSize( m_aActions
->GetSizePixel() );
403 Point
aToolbarPos( aRelated
.Width(), aRelated
.Height());
404 m_aActions
->SetPosPixel(Point(aToolbarPos
.X(), aToolbarPos
.Y()));
406 Size
aLBSize( aWindowSize
);
407 aLBSize
.Width() -= ( 2 * aRelated
.Width() );
410 const Size aHelpTextSize
= m_aHelpText
->CalcMinimumSize(aLBSize
.Width());
413 Point
aLBPos( aRelated
.Width(), aRelated
.Height() + aToolbarSize
.Height() + aRelated
.Height() );
415 aLBSize
.Height() -= aToolbarSize
.Height(); // Toolbar
416 aLBSize
.Height() -= (6*aRelated
.Height()); // 6 * gap
417 aLBSize
.Height() -= aFixedTextSize
.Height(); // fixed line
418 aLBSize
.Height() -= aHelpTextSize
.Height(); // help text
419 m_pListBox
->SetPosSizePixel( aLBPos
, aLBSize
);
422 Size
aFLSize( aLBSize
.Width(),aFixedTextSize
.Height() );
423 Point
aFLPos( aRelated
.Width(), aLBPos
.Y() + aLBSize
.Height() + aRelated
.Height());
424 m_aFixedLine
->SetPosSizePixel( aFLPos
, aFLSize
);
427 Point
aFTPos( aRelated
.Width(), aFLPos
.Y() + aFLSize
.Height() + aRelated
.Height() );
428 m_aHelpText
->SetPosSizePixel( aFTPos
, aHelpTextSize
);
431 uno::Reference
< sdbc::XConnection
> OAddFieldWindow::getConnection() const
433 return uno::Reference
< sdbc::XConnection
>(m_xRowSet
->getPropertyValue( PROPERTY_ACTIVECONNECTION
),uno::UNO_QUERY
);
436 void OAddFieldWindow::fillDescriptor(SvTreeListEntry
* _pSelected
,svx::ODataAccessDescriptor
& _rDescriptor
)
438 if ( _pSelected
&& m_xColumns
.is() )
440 uno::Reference
<container::XChild
> xChild(getConnection(),uno::UNO_QUERY
);
443 uno::Reference
<sdb::XDocumentDataSource
> xDocument( xChild
->getParent(), uno::UNO_QUERY
);
444 if ( xDocument
.is() )
446 uno::Reference
<frame::XModel
> xModel(xDocument
->getDatabaseDocument(),uno::UNO_QUERY
);
448 _rDescriptor
[ daDatabaseLocation
] <<= xModel
->getURL();
452 _rDescriptor
[ svx::daCommand
] <<= GetCommand();
453 _rDescriptor
[ svx::daCommandType
] <<= GetCommandType();
454 _rDescriptor
[ svx::daEscapeProcessing
] <<= GetEscapeProcessing();
455 _rDescriptor
[ svx::daConnection
] <<= getConnection();
457 ColumnInfo
* pInfo
= static_cast<ColumnInfo
*>(_pSelected
->GetUserData());
458 _rDescriptor
[ svx::daColumnName
] <<= pInfo
->sColumnName
;
459 if ( m_xColumns
->hasByName( pInfo
->sColumnName
) )
460 _rDescriptor
[ svx::daColumnObject
] <<= m_xColumns
->getByName(pInfo
->sColumnName
);
464 void OAddFieldWindow::_elementInserted( const container::ContainerEvent
& _rEvent
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
466 if ( m_pListBox
.get() )
469 if ( (_rEvent
.Accessor
>>= sName
) && m_xColumns
->hasByName(sName
) )
471 uno::Reference
< beans::XPropertySet
> xColumn(m_xColumns
->getByName(sName
),UNO_QUERY_THROW
);
473 if ( xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL
) )
474 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sLabel
;
475 if ( !sLabel
.isEmpty() )
476 m_pListBox
->InsertEntry( sLabel
,NULL
,false,TREELIST_APPEND
,new ColumnInfo(sName
,sLabel
) );
478 m_pListBox
->InsertEntry( sName
,NULL
,false,TREELIST_APPEND
,new ColumnInfo(sName
,sLabel
) );
483 void OAddFieldWindow::_elementRemoved( const container::ContainerEvent
& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
485 if ( m_pListBox
.get() )
488 if ( m_xColumns
.is() )
489 lcl_addToList( *m_pListBox
, m_xColumns
);
493 void OAddFieldWindow::_elementReplaced( const container::ContainerEvent
& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
497 IMPL_LINK_NOARG( OAddFieldWindow
, OnSelectHdl
)
499 m_aActions
->EnableItem(SID_ADD_CONTROL_PAIR
, ( m_pListBox
.get() && m_pListBox
->GetSelectionCount() > 0 ));
504 IMPL_LINK_NOARG( OAddFieldWindow
, OnDoubleClickHdl
)
506 if ( m_aCreateLink
.IsSet() )
507 m_aCreateLink
.Call(this);
512 void OAddFieldWindow::setImageList(sal_Int16 _eBitmapSet
)
514 sal_Int16 nN
= IMG_ADDFIELD_DLG_SC
;
515 if ( _eBitmapSet
== SFX_SYMBOLS_SIZE_LARGE
)
516 nN
= IMG_ADDFIELD_DLG_LC
;
517 m_aActions
->SetImageList(ImageList(ModuleRes(nN
)));
520 void OAddFieldWindow::resizeControls(const Size
& _rDiff
)
522 // we use large images so we must change them
523 if ( _rDiff
.Width() || _rDiff
.Height() )
529 IMPL_LINK_NOARG_TYPED( OAddFieldWindow
, OnSortAction
, ToolBox
*, void )
531 const sal_uInt16 nCurItem
= m_aActions
->GetCurItemId();
532 if ( SID_ADD_CONTROL_PAIR
== nCurItem
)
533 OnDoubleClickHdl(NULL
);
536 if ( SID_FM_REMOVE_FILTER_SORT
== nCurItem
|| !m_aActions
->IsItemChecked(nCurItem
) )
538 const sal_uInt16 nItemCount
= m_aActions
->GetItemCount();
539 for (sal_uInt16 j
= 0; j
< nItemCount
; ++j
)
541 const sal_uInt16 nItemId
= m_aActions
->GetItemId(j
);
542 if ( nCurItem
!= nItemId
)
543 m_aActions
->CheckItem(nItemId
,false);
545 SvSortMode eSortMode
= SortNone
;
546 if ( SID_FM_REMOVE_FILTER_SORT
!= nCurItem
)
548 m_aActions
->CheckItem(nCurItem
,!m_aActions
->IsItemChecked(nCurItem
));
549 if ( m_aActions
->IsItemChecked(SID_FM_SORTUP
) )
550 eSortMode
= SortAscending
;
551 else if ( m_aActions
->IsItemChecked(SID_FM_SORTDOWN
) )
552 eSortMode
= SortDescending
;
555 m_pListBox
->GetModel()->SetSortMode(eSortMode
);
556 if ( SID_FM_REMOVE_FILTER_SORT
== nCurItem
)
559 m_pListBox
->GetModel()->Resort();
568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */