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 .
22 #include <fmservs.hxx>
24 #include <svx/strings.hrc>
25 #include <svx/svxids.hrc>
26 #include <com/sun/star/sdb/CommandType.hpp>
27 #include <com/sun/star/sdbc/XConnection.hpp>
28 #include <comphelper/processfactory.hxx>
29 #include <comphelper/types.hxx>
32 #include <svx/fmshell.hxx>
33 #include <fmshimp.hxx>
37 #include <svx/dialmgr.hxx>
38 #include <sfx2/bindings.hxx>
39 #include <sfx2/objitem.hxx>
40 #include <sfx2/frame.hxx>
41 #include <svx/dataaccessdescriptor.hxx>
42 #include <comphelper/diagnose_ex.hxx>
46 const tools::Long STD_WIN_SIZE_X
= 120;
47 const tools::Long STD_WIN_SIZE_Y
= 150;
49 using namespace ::com::sun::star::sdbc
;
50 using namespace ::com::sun::star::sdb
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::datatransfer
;
53 using namespace ::com::sun::star::beans
;
54 using namespace ::com::sun::star::lang
;
55 using namespace ::com::sun::star::form
;
56 using namespace ::com::sun::star::container
;
57 using namespace ::com::sun::star
;
58 using namespace ::svxform
;
59 using namespace ::svx
;
60 using namespace ::dbtools
;
65 explicit ColumnInfo(OUString i_sColumnName
)
66 : sColumnName(std::move(i_sColumnName
))
71 void FmFieldWin::addToList(const uno::Reference
< container::XNameAccess
>& i_xColumns
)
73 const uno::Sequence
< OUString
> aEntries
= i_xColumns
->getElementNames();
74 for ( const OUString
& rEntry
: aEntries
)
76 uno::Reference
< beans::XPropertySet
> xColumn(i_xColumns
->getByName(rEntry
),UNO_QUERY_THROW
);
78 if ( xColumn
->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL
) )
79 xColumn
->getPropertyValue(FM_PROP_LABEL
) >>= sLabel
;
80 m_aListBoxData
.emplace_back(new ColumnInfo(rEntry
));
81 OUString
sId(weld::toId(m_aListBoxData
.back().get()));
82 if ( !sLabel
.isEmpty() )
83 m_xListBox
->append(sId
, sLabel
);
85 m_xListBox
->append(sId
, rEntry
);
89 IMPL_LINK(FmFieldWin
, DragBeginHdl
, bool&, rUnsetDragIcon
, bool)
91 rUnsetDragIcon
= false;
93 ColumnInfo
* pSelected
= weld::fromId
<ColumnInfo
*>(m_xListBox
->get_selected_id());
96 // no drag without a field
100 svx::ODataAccessDescriptor aDescriptor
;
101 aDescriptor
[ DataAccessDescriptorProperty::DataSource
] <<= GetDatabaseName();
102 aDescriptor
[ DataAccessDescriptorProperty::Connection
] <<= GetConnection().getTyped();
103 aDescriptor
[ DataAccessDescriptorProperty::Command
] <<= GetObjectName();
104 aDescriptor
[ DataAccessDescriptorProperty::CommandType
]<<= GetObjectType();
105 aDescriptor
[ DataAccessDescriptorProperty::ColumnName
] <<= pSelected
->sColumnName
;
107 m_xHelper
->setDescriptor(aDescriptor
);
112 FmFieldWin::FmFieldWin(SfxBindings
* _pBindings
, SfxChildWindow
* _pMgr
, weld::Window
* _pParent
)
113 : SfxModelessDialogController(_pBindings
, _pMgr
, _pParent
, u
"svx/ui/formfielddialog.ui"_ustr
, u
"FormFieldDialog"_ustr
)
114 , SfxControllerItem(SID_FM_FIELDS_CONTROL
, *_pBindings
)
115 , comphelper::OPropertyChangeListener2()
116 , m_xListBox(m_xBuilder
->weld_tree_view(u
"treeview"_ustr
))
119 m_xDialog
->set_help_id(HID_FIELD_SEL_WIN
);
120 m_xListBox
->set_help_id(HID_FIELD_SEL
);
122 m_xListBox
->connect_row_activated(LINK(this, FmFieldWin
, RowActivatedHdl
));
123 m_xHelper
.set(new OColumnTransferable(
124 ColumnTransferFormatFlags::FIELD_DESCRIPTOR
| ColumnTransferFormatFlags::CONTROL_EXCHANGE
| ColumnTransferFormatFlags::COLUMN_DESCRIPTOR
126 rtl::Reference
<TransferDataContainer
> xHelper(m_xHelper
);
127 m_xListBox
->enable_drag_source(xHelper
, DND_ACTION_COPY
);
128 m_xListBox
->connect_drag_begin(LINK(this, FmFieldWin
, DragBeginHdl
));
130 UpdateContent(nullptr);
131 m_xDialog
->set_size_request(STD_WIN_SIZE_X
, STD_WIN_SIZE_Y
);
134 FmFieldWin::~FmFieldWin()
137 std::unique_lock
g(m_aMutex
);
138 if (m_xChangeListener
.is())
140 m_xChangeListener
->dispose(g
);
141 m_xChangeListener
.clear();
144 ::SfxControllerItem::dispose();
147 IMPL_LINK_NOARG(FmFieldWin
, RowActivatedHdl
, weld::TreeView
&, bool)
149 return createSelectionControls();
152 bool FmFieldWin::createSelectionControls()
154 ColumnInfo
* pSelected
= weld::fromId
<ColumnInfo
*>(m_xListBox
->get_selected_id());
157 // build a descriptor for the currently selected field
158 ODataAccessDescriptor aDescr
;
159 aDescr
.setDataSource(GetDatabaseName());
161 aDescr
[ DataAccessDescriptorProperty::Connection
] <<= GetConnection().getTyped();
163 aDescr
[ DataAccessDescriptorProperty::Command
] <<= GetObjectName();
164 aDescr
[ DataAccessDescriptorProperty::CommandType
] <<= GetObjectType();
165 aDescr
[ DataAccessDescriptorProperty::ColumnName
] <<= pSelected
->sColumnName
;
167 // transfer this to the SFX world
168 SfxUnoAnyItem
aDescriptorItem( SID_FM_DATACCESS_DESCRIPTOR
, Any( aDescr
.createPropertyValueSequence() ) );
169 const SfxPoolItem
* pArgs
[] =
171 &aDescriptorItem
, nullptr
174 // execute the create slot
175 GetBindings().Execute( SID_FM_CREATE_FIELDCONTROL
, pArgs
);
178 return nullptr != pSelected
;
181 void FmFieldWin::_propertyChanged(const css::beans::PropertyChangeEvent
& evt
)
183 css::uno::Reference
< css::form::XForm
> xForm(evt
.Source
, css::uno::UNO_QUERY
);
184 UpdateContent(xForm
);
187 void FmFieldWin::StateChangedAtToolBoxControl(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
189 if (!pState
|| SID_FM_FIELDS_CONTROL
!= nSID
)
192 if (eState
>= SfxItemState::DEFAULT
)
194 FmFormShell
* pShell
= dynamic_cast<FmFormShell
*>( static_cast<const SfxObjectItem
*>(pState
)->GetShell() );
195 UpdateContent(pShell
);
198 UpdateContent(nullptr);
201 void FmFieldWin::UpdateContent(FmFormShell
const * pShell
)
204 m_aListBoxData
.clear();
205 OUString
aTitle(SvxResId(RID_STR_FIELDSELECTION
));
206 m_xDialog
->set_title(aTitle
);
208 if (!pShell
|| !pShell
->GetImpl())
211 Reference
<XForm
> const xForm
= pShell
->GetImpl()->getCurrentForm_Lock();
213 UpdateContent( xForm
);
216 void FmFieldWin::UpdateContent(const css::uno::Reference
< css::form::XForm
> & xForm
)
222 m_aListBoxData
.clear();
223 OUString
aTitle(SvxResId(RID_STR_FIELDSELECTION
));
224 m_xDialog
->set_title(aTitle
);
229 Reference
< XPropertySet
> xSet(xForm
, UNO_QUERY
);
231 m_aObjectName
= ::comphelper::getString(xSet
->getPropertyValue(FM_PROP_COMMAND
));
232 m_aDatabaseName
= ::comphelper::getString(xSet
->getPropertyValue(FM_PROP_DATASOURCE
));
233 m_nObjectType
= ::comphelper::getINT32(xSet
->getPropertyValue(FM_PROP_COMMANDTYPE
));
235 // get the connection of the form
237 connectRowset( Reference
< XRowSet
>( xForm
, UNO_QUERY
), ::comphelper::getProcessComponentContext(), nullptr ),
238 SharedConnection::NoTakeOwnership
240 // TODO: When incompatible changes (such as extending the "virtualdbtools" interface by ensureRowSetConnection)
241 // are allowed, again, we should change this: dbtools should consistently use SharedConnection all over
242 // the place, and connectRowset should be replaced with ensureRowSetConnection
244 // get the fields of the object
246 if ( m_aConnection
.is() && !m_aObjectName
.isEmpty() )
248 Reference
< XComponent
> xKeepFieldsAlive
;
249 Reference
< XNameAccess
> xColumns
= getFieldsByCommandDescriptor( m_aConnection
, m_nObjectType
, m_aObjectName
,xKeepFieldsAlive
);
257 switch (m_nObjectType
)
259 case CommandType::TABLE
:
260 aPrefix
= SvxResId(RID_RSC_TABWIN_PREFIX
[0]);
262 case CommandType::QUERY
:
263 aPrefix
= SvxResId(RID_RSC_TABWIN_PREFIX
[1]);
266 aPrefix
= SvxResId(RID_RSC_TABWIN_PREFIX
[2]);
270 // listen for changes at ControlSource in PropertySet
271 std::unique_lock
g(m_aMutex
);
272 if (m_xChangeListener
.is())
274 m_xChangeListener
->dispose(g
);
275 m_xChangeListener
.clear();
277 m_xChangeListener
= new ::comphelper::OPropertyChangeMultiplexer2(m_aMutex
, g
, this, xSet
);
278 m_xChangeListener
->addProperty(FM_PROP_DATASOURCE
);
279 m_xChangeListener
->addProperty(FM_PROP_COMMAND
);
280 m_xChangeListener
->addProperty(FM_PROP_COMMANDTYPE
);
283 aTitle
+= " " + aPrefix
+ " " + m_aObjectName
;
284 m_xDialog
->set_title(aTitle
);
286 catch( const Exception
& )
288 TOOLS_WARN_EXCEPTION( "svx", "FmTabWin::UpdateContent" );
292 void FmFieldWin::FillInfo( SfxChildWinInfo
& rInfo
) const
294 rInfo
.bVisible
= false;
297 SFX_IMPL_MODELESSDIALOGCONTOLLER(FmFieldWinMgr
, SID_FM_ADD_FIELD
)
299 FmFieldWinMgr::FmFieldWinMgr(vcl::Window
* _pParent
, sal_uInt16 _nId
,
300 SfxBindings
* _pBindings
, SfxChildWinInfo
const * _pInfo
)
301 :SfxChildWindow(_pParent
, _nId
)
303 auto xDlg
= std::make_shared
<FmFieldWin
>(_pBindings
, this, _pParent
->GetFrameWeld());
305 SetHideNotDelete(true);
306 xDlg
->Initialize(_pInfo
);
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */