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 <svx/dbaexchange.hxx>
22 #include <svx/svdpagv.hxx>
23 #include <com/sun/star/sdb/CommandType.hpp>
24 #include <com/sun/star/util/URL.hpp>
25 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
26 #include <com/sun/star/i18n/XCollator.hpp>
27 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
29 #include <vcl/event.hxx>
30 #include <vcl/waitobj.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/settings.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <rptui_slotid.hrc>
37 #include <connectivity/dbtools.hxx>
38 #include <core_resource.hxx>
40 #include <strings.hrc>
41 #include <strings.hxx>
42 #include <ColumnInfo.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <comphelper/property.hxx>
46 #include <svtools/imgdef.hxx>
47 #include <vcl/treelistentry.hxx>
51 const long STD_WIN_SIZE_X
= 180;
52 const long STD_WIN_SIZE_Y
= 320;
54 using namespace ::com::sun::star
;
58 using namespace datatransfer
;
59 using namespace beans
;
61 using namespace container
;
62 using namespace ::svx
;
64 class OAddFieldWindowListBox
: public SvTreeListBox
66 VclPtr
<OAddFieldWindow
> m_pTabWin
;
69 explicit OAddFieldWindowListBox(Window
* pParent
, OAddFieldWindow
* pFieldWindow
);
70 virtual ~OAddFieldWindowListBox() override
;
71 virtual void dispose() override
;
73 sal_Int8
AcceptDrop( const AcceptDropEvent
& rEvt
) override
;
74 sal_Int8
ExecuteDrop( const ExecuteDropEvent
& rEvt
) override
;
76 uno::Sequence
< beans::PropertyValue
> getSelectedFieldDescriptors();
80 virtual void StartDrag( sal_Int8 nAction
, const Point
& rPosPixel
) override
;
83 using SvTreeListBox::ExecuteDrop
;
86 uno::Sequence
< beans::PropertyValue
> OAddFieldWindowListBox::getSelectedFieldDescriptors()
88 uno::Sequence
< beans::PropertyValue
> aArgs(GetSelectionCount());
90 SvTreeListEntry
* pSelected
= FirstSelected();
93 // build a descriptor for the currently selected field
94 svx::ODataAccessDescriptor aDescriptor
;
95 m_pTabWin
->fillDescriptor(pSelected
,aDescriptor
);
96 aArgs
[i
++].Value
<<= aDescriptor
.createPropertyValueSequence();
97 pSelected
= NextSelected(pSelected
);
102 // class OAddFieldWindowListBox
105 OAddFieldWindowListBox::OAddFieldWindowListBox(Window
*pParent
, OAddFieldWindow
* pFieldWindow
)
106 : SvTreeListBox(pParent
, WB_TABSTOP
|WB_BORDER
|WB_SORT
)
107 , m_pTabWin(pFieldWindow
)
109 SetHelpId( HID_RPT_FIELD_SEL
);
110 SetSelectionMode(SelectionMode::Multiple
);
111 SetDragDropMode( DragDropMode::ALL
);
112 SetHighlightRange( );
116 OAddFieldWindowListBox::~OAddFieldWindowListBox()
121 void OAddFieldWindowListBox::dispose()
124 SvTreeListBox::dispose();
127 sal_Int8
OAddFieldWindowListBox::AcceptDrop( const AcceptDropEvent
& /*rEvt*/ )
129 return DND_ACTION_NONE
;
133 sal_Int8
OAddFieldWindowListBox::ExecuteDrop( const ExecuteDropEvent
& /*rEvt*/ )
135 return DND_ACTION_NONE
;
139 void OAddFieldWindowListBox::StartDrag( sal_Int8
/*_nAction*/, const Point
& /*_rPosPixel*/ )
141 if ( GetSelectionCount() < 1 )
142 // no drag without a field
145 rtl::Reference
<OMultiColumnTransferable
> pDataContainer
= new OMultiColumnTransferable(getSelectedFieldDescriptors());
148 pDataContainer
->StartDrag( this, DND_ACTION_COPYMOVE
| DND_ACTION_LINK
);
151 OAddFieldWindow::OAddFieldWindow(vcl::Window
* pParent
,const uno::Reference
< beans::XPropertySet
>& _xRowSet
)
152 : FloatingWindow(pParent
, "FloatingField", "modules/dbreport/ui/floatingfield.ui")
153 , ::comphelper::OPropertyChangeListener(m_aMutex
)
154 , ::comphelper::OContainerListener(m_aMutex
)
155 , m_xRowSet(_xRowSet
)
156 , m_pListBox(VclPtr
<OAddFieldWindowListBox
>::Create(get
<vcl::Window
>("box"), this))
158 , m_bEscapeProcessing(false)
160 get(m_aActions
, "toolbox");
161 m_nSortUpId
= m_aActions
->GetItemId(0);
162 m_nSortDownId
= m_aActions
->GetItemId(1);
163 m_nRemoveSortId
= m_aActions
->GetItemId(2);
164 m_nInsertId
= m_aActions
->GetItemId(4);
165 get(m_aHelpText
, "helptext");
167 SetHelpId( HID_RPT_FIELD_SEL_WIN
);
168 SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
169 SetMinOutputSizePixel(Size(STD_WIN_SIZE_X
,STD_WIN_SIZE_Y
));
171 m_aActions
->SetLineSpacing(true);
172 m_aActions
->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
174 m_aActions
->SetSelectHdl(LINK(this, OAddFieldWindow
, OnSortAction
));
175 setToolBox(m_aActions
.get());
176 m_aActions
->CheckItem(m_nSortUpId
);
177 m_aActions
->EnableItem(m_nInsertId
, false);
179 m_pListBox
->SetDoubleClickHdl(LINK( this, OAddFieldWindow
, OnDoubleClickHdl
) );
180 m_pListBox
->SetSelectHdl(LINK( this, OAddFieldWindow
, OnSelectHdl
) );
181 m_pListBox
->SetDeselectHdl(LINK( this, OAddFieldWindow
, OnSelectHdl
) );
182 m_pListBox
->SetDoubleClickHdl(LINK( this, OAddFieldWindow
, OnDoubleClickHdl
) );
183 m_pListBox
->set_expand(true);
184 m_pListBox
->set_height_request(m_pListBox
->GetTextHeight() * 8);
185 m_pListBox
->set_width_request(m_pListBox
->approximate_char_width() * 40);
188 m_aHelpText
->SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
190 SetSizePixel(Size(STD_WIN_SIZE_X
,STD_WIN_SIZE_Y
));
192 if ( m_xRowSet
.is() )
196 // be notified when the settings of report definition change
197 m_pChangeListener
= new ::comphelper::OPropertyChangeMultiplexer( this, m_xRowSet
);
198 m_pChangeListener
->addProperty( PROPERTY_COMMAND
);
199 m_pChangeListener
->addProperty( PROPERTY_COMMANDTYPE
);
200 m_pChangeListener
->addProperty( PROPERTY_ESCAPEPROCESSING
);
201 m_pChangeListener
->addProperty( PROPERTY_FILTER
);
203 catch( const Exception
& )
205 DBG_UNHANDLED_EXCEPTION("reportdesign");
210 OAddFieldWindow::~OAddFieldWindow()
215 void OAddFieldWindow::dispose()
217 if ( m_pListBox
.get() )
219 SvTreeList
* pModel
= m_pListBox
->GetModel();
220 sal_uLong nCount
= pModel
->GetEntryCount();
221 for(sal_uLong i
= 0; i
< nCount
;++i
)
223 delete static_cast<ColumnInfo
*>(pModel
->GetEntry(i
)->GetUserData());
226 if (m_pChangeListener
.is())
227 m_pChangeListener
->dispose();
228 if ( m_pContainerListener
.is() )
229 m_pContainerListener
->dispose();
233 m_pListBox
.disposeAndClear();
234 FloatingWindow::dispose();
237 void OAddFieldWindow::GetFocus()
239 if ( m_pListBox
.get() )
240 m_pListBox
->GrabFocus();
242 FloatingWindow::GetFocus();
245 uno::Sequence
< beans::PropertyValue
> OAddFieldWindow::getSelectedFieldDescriptors()
247 return m_pListBox
->getSelectedFieldDescriptors();
251 bool OAddFieldWindow::PreNotify( NotifyEvent
& _rNEvt
)
253 if ( MouseNotifyEvent::KEYINPUT
== _rNEvt
.GetType() )
255 const vcl::KeyCode
& rKeyCode
= _rNEvt
.GetKeyEvent()->GetKeyCode();
256 if ( ( 0 == rKeyCode
.GetModifier() ) && ( KEY_RETURN
== rKeyCode
.GetCode() ) )
258 if ( m_aCreateLink
.IsSet() )
260 m_aCreateLink
.Call(*this);
266 return FloatingWindow::PreNotify( _rNEvt
);
269 void OAddFieldWindow::_propertyChanged( const beans::PropertyChangeEvent
& _evt
)
271 OSL_ENSURE( _evt
.Source
== m_xRowSet
, "OAddFieldWindow::_propertyChanged: where did this come from?" );
278 void lcl_addToList( OAddFieldWindowListBox
& _rListBox
, const uno::Sequence
< OUString
>& _rEntries
)
280 const OUString
* pEntries
= _rEntries
.getConstArray();
281 sal_Int32 nEntries
= _rEntries
.getLength();
282 for ( sal_Int32 i
= 0; i
< nEntries
; ++i
, ++pEntries
)
283 _rListBox
.InsertEntry( *pEntries
,nullptr,false,TREELIST_APPEND
,new ColumnInfo(*pEntries
) );
285 void lcl_addToList( OAddFieldWindowListBox
& _rListBox
, const uno::Reference
< container::XNameAccess
>& i_xColumns
)
287 uno::Sequence
< OUString
> aEntries
= i_xColumns
->getElementNames();
288 const OUString
* pEntries
= aEntries
.getConstArray();
289 sal_Int32 nEntries
= aEntries
.getLength();
290 for ( sal_Int32 i
= 0; i
< nEntries
; ++i
, ++pEntries
)
292 uno::Reference
< beans::XPropertySet
> xColumn(i_xColumns
->getByName(*pEntries
),UNO_QUERY_THROW
);
294 if ( xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL
) )
295 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sLabel
;
296 if ( !sLabel
.isEmpty() )
297 _rListBox
.InsertEntry( sLabel
,nullptr,false,TREELIST_APPEND
,new ColumnInfo(*pEntries
,sLabel
) );
299 _rListBox
.InsertEntry( *pEntries
,nullptr,false,TREELIST_APPEND
,new ColumnInfo(*pEntries
,sLabel
) );
305 void OAddFieldWindow::Update()
307 SolarMutexGuard aSolarGuard
;
309 if ( m_pContainerListener
.is() )
310 m_pContainerListener
->dispose();
311 m_pContainerListener
= nullptr;
318 const ToolBox::ImplToolItems::size_type nItemCount
= m_aActions
->GetItemCount();
319 for (ToolBox::ImplToolItems::size_type j
= 0; j
< nItemCount
; ++j
)
321 m_aActions
->EnableItem(m_aActions
->GetItemId(j
),false);
324 OUString
aTitle(RptResId(RID_STR_FIELDSELECTION
));
326 if ( m_xRowSet
.is() )
328 OUString
sCommand( m_aCommandName
);
329 sal_Int32
nCommandType( m_nCommandType
);
330 bool bEscapeProcessing( m_bEscapeProcessing
);
331 OUString
sFilter( m_sFilter
);
333 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_COMMAND
) >>= sCommand
);
334 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_COMMANDTYPE
) >>= nCommandType
);
335 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_ESCAPEPROCESSING
) >>= bEscapeProcessing
);
336 OSL_VERIFY( m_xRowSet
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
);
338 m_aCommandName
= sCommand
;
339 m_nCommandType
= nCommandType
;
340 m_bEscapeProcessing
= bEscapeProcessing
;
343 // add the columns to the list
344 uno::Reference
< sdbc::XConnection
> xCon
= getConnection();
345 if ( xCon
.is() && !m_aCommandName
.isEmpty() )
346 m_xColumns
= dbtools::getFieldsByCommandDescriptor( xCon
, GetCommandType(), GetCommand(), m_xHoldAlive
);
347 if ( m_xColumns
.is() )
349 lcl_addToList( *m_pListBox
, m_xColumns
);
350 uno::Reference
< container::XContainer
> xContainer(m_xColumns
,uno::UNO_QUERY
);
351 if ( xContainer
.is() )
352 m_pContainerListener
= new ::comphelper::OContainerListenerAdapter(this,xContainer
);
355 // add the parameter columns to the list
356 uno::Reference
< css::sdbc::XRowSet
> xRowSet(m_xRowSet
,uno::UNO_QUERY
);
357 Sequence
< OUString
> aParamNames( getParameterNames( xRowSet
) );
358 lcl_addToList( *m_pListBox
, aParamNames
);
361 aTitle
+= " " + m_aCommandName
;
363 if ( !m_aCommandName
.isEmpty() )
365 for (ToolBox::ImplToolItems::size_type i
= 0; i
< nItemCount
; ++i
)
367 m_aActions
->EnableItem(m_aActions
->GetItemId(i
));
370 OnSelectHdl(nullptr);
373 catch( const Exception
& )
375 DBG_UNHANDLED_EXCEPTION("reportdesign");
379 uno::Reference
< sdbc::XConnection
> OAddFieldWindow::getConnection() const
381 return uno::Reference
< sdbc::XConnection
>(m_xRowSet
->getPropertyValue( PROPERTY_ACTIVECONNECTION
),uno::UNO_QUERY
);
384 void OAddFieldWindow::fillDescriptor(SvTreeListEntry
const * _pSelected
,svx::ODataAccessDescriptor
& _rDescriptor
)
386 if ( _pSelected
&& m_xColumns
.is() )
388 uno::Reference
<container::XChild
> xChild(getConnection(),uno::UNO_QUERY
);
391 uno::Reference
<sdb::XDocumentDataSource
> xDocument( xChild
->getParent(), uno::UNO_QUERY
);
392 if ( xDocument
.is() )
394 uno::Reference
<frame::XModel
> xModel(xDocument
->getDatabaseDocument(),uno::UNO_QUERY
);
396 _rDescriptor
[ DataAccessDescriptorProperty::DatabaseLocation
] <<= xModel
->getURL();
400 _rDescriptor
[ svx::DataAccessDescriptorProperty::Command
] <<= GetCommand();
401 _rDescriptor
[ svx::DataAccessDescriptorProperty::CommandType
] <<= GetCommandType();
402 _rDescriptor
[ svx::DataAccessDescriptorProperty::EscapeProcessing
] <<= GetEscapeProcessing();
403 _rDescriptor
[ svx::DataAccessDescriptorProperty::Connection
] <<= getConnection();
405 ColumnInfo
* pInfo
= static_cast<ColumnInfo
*>(_pSelected
->GetUserData());
406 _rDescriptor
[ svx::DataAccessDescriptorProperty::ColumnName
] <<= pInfo
->sColumnName
;
407 if ( m_xColumns
->hasByName( pInfo
->sColumnName
) )
408 _rDescriptor
[ svx::DataAccessDescriptorProperty::ColumnObject
] = m_xColumns
->getByName(pInfo
->sColumnName
);
412 void OAddFieldWindow::_elementInserted( const container::ContainerEvent
& _rEvent
)
414 if ( m_pListBox
.get() )
417 if ( (_rEvent
.Accessor
>>= sName
) && m_xColumns
->hasByName(sName
) )
419 uno::Reference
< beans::XPropertySet
> xColumn(m_xColumns
->getByName(sName
),UNO_QUERY_THROW
);
421 if ( xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL
) )
422 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sLabel
;
423 if ( !sLabel
.isEmpty() )
424 m_pListBox
->InsertEntry( sLabel
,nullptr,false,TREELIST_APPEND
,new ColumnInfo(sName
,sLabel
) );
426 m_pListBox
->InsertEntry( sName
,nullptr,false,TREELIST_APPEND
,new ColumnInfo(sName
,sLabel
) );
431 void OAddFieldWindow::_elementRemoved( const container::ContainerEvent
& /*_rEvent*/ )
433 if ( m_pListBox
.get() )
436 if ( m_xColumns
.is() )
437 lcl_addToList( *m_pListBox
, m_xColumns
);
441 void OAddFieldWindow::_elementReplaced( const container::ContainerEvent
& /*_rEvent*/ )
445 IMPL_LINK_NOARG( OAddFieldWindow
, OnSelectHdl
, SvTreeListBox
*, void )
447 m_aActions
->EnableItem(m_nInsertId
, ( m_pListBox
.get() && m_pListBox
->GetSelectionCount() > 0 ));
450 IMPL_LINK_NOARG( OAddFieldWindow
, OnDoubleClickHdl
, SvTreeListBox
*, bool )
452 m_aCreateLink
.Call(*this);
457 void OAddFieldWindow::resizeControls(const Size
& _rDiff
)
459 // we use large images so we must change them
460 if ( _rDiff
.Width() || _rDiff
.Height() )
466 IMPL_LINK_NOARG( OAddFieldWindow
, OnSortAction
, ToolBox
*, void )
468 const sal_uInt16 nCurItem
= m_aActions
->GetCurItemId();
469 if (nCurItem
== m_nInsertId
)
470 OnDoubleClickHdl(nullptr);
473 if (nCurItem
== m_nRemoveSortId
|| !m_aActions
->IsItemChecked(nCurItem
))
475 const ToolBox::ImplToolItems::size_type nItemCount
= m_aActions
->GetItemCount();
476 for (ToolBox::ImplToolItems::size_type j
= 0; j
< nItemCount
; ++j
)
478 const sal_uInt16 nItemId
= m_aActions
->GetItemId(j
);
479 if ( nCurItem
!= nItemId
)
480 m_aActions
->CheckItem(nItemId
,false);
482 SvSortMode eSortMode
= SortNone
;
483 if (nCurItem
!= m_nRemoveSortId
)
485 m_aActions
->CheckItem(nCurItem
,!m_aActions
->IsItemChecked(nCurItem
));
486 if (m_aActions
->IsItemChecked(m_nSortUpId
))
487 eSortMode
= SortAscending
;
488 else if (m_aActions
->IsItemChecked(m_nSortDownId
))
489 eSortMode
= SortDescending
;
492 m_pListBox
->GetModel()->SetSortMode(eSortMode
);
493 if (nCurItem
== m_nRemoveSortId
)
496 m_pListBox
->GetModel()->Resort();
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */