LibreOffice Module reportdesign (master) 1
AddField.cxx
Go to the documentation of this file.
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#include <AddField.hxx>
20#include <UITools.hxx>
21#include <com/sun/star/sdb/CommandType.hpp>
22#include <com/sun/star/sdb/XDocumentDataSource.hpp>
23
24#include <utility>
25#include <vcl/svapp.hxx>
26
28
30#include <core_resource.hxx>
31#include <helpids.h>
32#include <strings.hrc>
33#include <strings.hxx>
34
36
37namespace rptui
38{
39
40using namespace ::com::sun::star;
41using namespace sdbc;
42using namespace sdb;
43using namespace uno;
44using namespace datatransfer;
45using namespace beans;
46using namespace lang;
47using namespace container;
48using namespace ::svx;
49
50IMPL_LINK(OAddFieldWindow, DragBeginHdl, bool&, rUnsetDragIcon, bool)
51{
52 rUnsetDragIcon = false;
53 if (m_xListBox->get_selected_index() == -1)
54 {
55 // no drag without a field
56 return true;
57 }
58
59 m_xHelper->setDescriptors(getSelectedFieldDescriptors());
60 return false;
61}
62
63OAddFieldWindow::OAddFieldWindow(weld::Window* pParent, uno::Reference< beans::XPropertySet > xRowSet)
64 : GenericDialogController(pParent, "modules/dbreport/ui/floatingfield.ui", "FloatingField")
65 , ::comphelper::OPropertyChangeListener(m_aMutex)
66 , ::comphelper::OContainerListener(m_aMutex)
67 , m_xRowSet(std::move(xRowSet))
68 , m_xActions(m_xBuilder->weld_toolbar("toolbox"))
69 , m_xListBox(m_xBuilder->weld_tree_view("treeview"))
71 , m_bEscapeProcessing(false)
72{
73 m_xListBox->set_help_id(HID_RPT_FIELD_SEL);
74 m_xListBox->set_selection_mode(SelectionMode::Multiple);
75 m_xHelper.set(new svx::OMultiColumnTransferable);
77 m_xListBox->enable_drag_source(xHelper, DND_ACTION_COPYMOVE | DND_ACTION_LINK);
78 m_xListBox->connect_drag_begin(LINK(this, OAddFieldWindow, DragBeginHdl));
79
80 m_xDialog->connect_container_focus_changed(LINK(this, OAddFieldWindow, FocusChangeHdl));
81
82 m_xDialog->set_help_id(HID_RPT_FIELD_SEL_WIN);
83
84 m_xActions->connect_clicked(LINK(this, OAddFieldWindow, OnSortAction));
85 m_xActions->set_item_active("up", true);
86 m_xListBox->make_sorted();
87 m_xActions->set_item_sensitive("insert", false);
88
89 m_xListBox->connect_row_activated(LINK( this, OAddFieldWindow, OnDoubleClickHdl ) );
90 m_xListBox->connect_changed(LINK( this, OAddFieldWindow, OnSelectHdl ) );
91 m_xListBox->set_size_request(m_xListBox->get_approximate_digit_width() * 45, m_xListBox->get_height_rows(8));
92
93 if (!m_xRowSet.is())
94 return;
95
96 try
97 {
98 // be notified when the settings of report definition change
99 m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer( this, m_xRowSet );
100 m_pChangeListener->addProperty( PROPERTY_COMMAND );
101 m_pChangeListener->addProperty( PROPERTY_COMMANDTYPE );
102 m_pChangeListener->addProperty( PROPERTY_ESCAPEPROCESSING );
103 m_pChangeListener->addProperty( PROPERTY_FILTER );
104 }
105 catch( const Exception& )
106 {
107 DBG_UNHANDLED_EXCEPTION("reportdesign");
108 }
109}
110
111OAddFieldWindow::~OAddFieldWindow()
112{
113 m_aListBoxData.clear();
114 if (m_pChangeListener.is())
115 m_pChangeListener->dispose();
116 if ( m_pContainerListener.is() )
117 m_pContainerListener->dispose();
118}
119
121{
122 if (m_xDialog->has_toplevel_focus())
123 m_xListBox->grab_focus();
124}
125
126uno::Sequence< beans::PropertyValue > OAddFieldWindow::getSelectedFieldDescriptors()
127{
128 std::vector<beans::PropertyValue> aArgs;
129
130 m_xListBox->selected_foreach([this, &aArgs](weld::TreeIter& rEntry){
131 // build a descriptor for the currently selected field
132 svx::ODataAccessDescriptor aDescriptor;
133 fillDescriptor(rEntry, aDescriptor);
134 aArgs.push_back(beans::PropertyValue());
135 aArgs.back().Value <<= aDescriptor.createPropertyValueSequence();
136
137 return false;
138 });
139
141}
142
143void OAddFieldWindow::_propertyChanged( const beans::PropertyChangeEvent& _evt )
144{
145 OSL_ENSURE( _evt.Source == m_xRowSet, "OAddFieldWindow::_propertyChanged: where did this come from?" );
146 Update();
147}
148
149void OAddFieldWindow::addToList(const uno::Sequence< OUString >& rEntries)
150{
151 for (const OUString& rEntry : rEntries)
152 {
153 m_aListBoxData.emplace_back(new ColumnInfo(rEntry));
154 OUString sId(weld::toId(m_aListBoxData.back().get()));
155 m_xListBox->append(sId, rEntry);
156 }
157}
158
159void OAddFieldWindow::addToList(const uno::Reference< container::XNameAccess>& i_xColumns)
160{
161 const uno::Sequence< OUString > aEntries = i_xColumns->getElementNames();
162 for ( const OUString& rEntry : aEntries )
163 {
164 uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(rEntry),UNO_QUERY_THROW);
165 OUString sLabel;
166 if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) )
167 xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
168 m_aListBoxData.emplace_back(new ColumnInfo(rEntry, sLabel));
169 OUString sId(weld::toId(m_aListBoxData.back().get()));
170 if ( !sLabel.isEmpty() )
171 m_xListBox->append(sId, sLabel);
172 else
173 m_xListBox->append(sId, rEntry);
174 }
175}
176
177void OAddFieldWindow::Update()
178{
179 SolarMutexGuard aSolarGuard;
180
181 if ( m_pContainerListener.is() )
182 m_pContainerListener->dispose();
183 m_pContainerListener = nullptr;
184 m_xColumns.clear();
185
186 try
187 {
188 // ListBox loeschen
189 m_xListBox->clear();
190 m_aListBoxData.clear();
191 const OUString aIds[] = { "up", "down" };
192 for (size_t j = 0; j< std::size(aIds); ++j)
193 m_xActions->set_item_sensitive(aIds[j], false);
194
195 OUString aTitle(RptResId(RID_STR_FIELDSELECTION));
196 m_xDialog->set_title(aTitle);
197 if ( m_xRowSet.is() )
198 {
199 OUString sCommand( m_aCommandName );
200 sal_Int32 nCommandType( m_nCommandType );
201 bool bEscapeProcessing( m_bEscapeProcessing );
202 OUString sFilter( m_sFilter );
203
204 OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand );
205 OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nCommandType );
206 OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_ESCAPEPROCESSING ) >>= bEscapeProcessing );
207 OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_FILTER ) >>= sFilter );
208
209 m_aCommandName = sCommand;
210 m_nCommandType = nCommandType;
211 m_bEscapeProcessing = bEscapeProcessing;
212 m_sFilter = sFilter;
213
214 // add the columns to the list
215 uno::Reference< sdbc::XConnection> xCon = getConnection();
216 if ( xCon.is() && !m_aCommandName.isEmpty() )
217 m_xColumns = dbtools::getFieldsByCommandDescriptor( xCon, GetCommandType(), GetCommand(), m_xHoldAlive );
218 if ( m_xColumns.is() )
219 {
220 addToList(m_xColumns);
221 uno::Reference< container::XContainer> xContainer(m_xColumns,uno::UNO_QUERY);
222 if ( xContainer.is() )
223 m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
224 }
225
226 // add the parameter columns to the list
227 uno::Reference< css::sdbc::XRowSet > xRowSet(m_xRowSet,uno::UNO_QUERY);
228 Sequence< OUString > aParamNames( getParameterNames( xRowSet ) );
229 addToList(aParamNames);
230
231 // set title
232 aTitle += " " + m_aCommandName;
233 m_xDialog->set_title(aTitle);
234 if ( !m_aCommandName.isEmpty() )
235 {
236 for (size_t i = 0; i < std::size(aIds); ++i)
237 m_xActions->set_item_sensitive(aIds[i], true);
238 }
239 OnSelectHdl(*m_xListBox);
240 }
241 }
242 catch( const Exception& )
243 {
244 DBG_UNHANDLED_EXCEPTION("reportdesign");
245 }
246}
247
248uno::Reference< sdbc::XConnection> OAddFieldWindow::getConnection() const
249{
250 return uno::Reference< sdbc::XConnection>(m_xRowSet->getPropertyValue( PROPERTY_ACTIVECONNECTION ),uno::UNO_QUERY);
251}
252
253void OAddFieldWindow::fillDescriptor(const weld::TreeIter& rSelected, svx::ODataAccessDescriptor& rDescriptor)
254{
255 if (!m_xColumns.is())
256 return;
257
258 uno::Reference<container::XChild> xChild(getConnection(),uno::UNO_QUERY);
259 if ( xChild.is( ) )
260 {
261 uno::Reference<sdb::XDocumentDataSource> xDocument( xChild->getParent(), uno::UNO_QUERY );
262 if ( xDocument.is() )
263 {
264 uno::Reference<frame::XModel> xModel(xDocument->getDatabaseDocument(),uno::UNO_QUERY);
265 if ( xModel.is() )
266 rDescriptor[ DataAccessDescriptorProperty::DatabaseLocation ] <<= xModel->getURL();
267 }
268 }
269
270 rDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= GetCommand();
271 rDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= GetCommandType();
272 rDescriptor[ svx::DataAccessDescriptorProperty::EscapeProcessing ] <<= m_bEscapeProcessing;
274
275 ColumnInfo* pInfo = weld::fromId<ColumnInfo*>(m_xListBox->get_id(rSelected));
277 if ( m_xColumns->hasByName( pInfo->sColumnName ) )
278 rDescriptor[ svx::DataAccessDescriptorProperty::ColumnObject ] = m_xColumns->getByName(pInfo->sColumnName);
279}
280
281void OAddFieldWindow::_elementInserted( const container::ContainerEvent& _rEvent )
282{
283 OUString sName;
284 if ( !((_rEvent.Accessor >>= sName) && m_xColumns->hasByName(sName)) )
285 return;
286
287 uno::Reference< beans::XPropertySet> xColumn(m_xColumns->getByName(sName),UNO_QUERY_THROW);
288 OUString sLabel;
289 if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) )
290 xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
291 m_aListBoxData.emplace_back(new ColumnInfo(sName, sLabel));
292 OUString sId(weld::toId(m_aListBoxData.back().get()));
293 if (!sLabel.isEmpty())
294 m_xListBox->append(sId, sLabel);
295 else
296 m_xListBox->append(sId, sName);
297}
298
299void OAddFieldWindow::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ )
300{
301 m_xListBox->clear();
302 m_aListBoxData.clear();
303 if ( m_xColumns.is() )
304 addToList(m_xColumns);
305}
306
307void OAddFieldWindow::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ )
308{
309}
310
312{
313 m_xActions->set_item_sensitive("insert", m_xListBox->get_selected_index() != -1);
314}
315
317{
318 m_aCreateLink.Call(*this);
319 return true;
320}
321
322IMPL_LINK(OAddFieldWindow, OnSortAction, const OUString&, rCurItem, void)
323{
324 if (rCurItem == "insert")
325 {
326 OnDoubleClickHdl(*m_xListBox);
327 return;
328 }
329
330 const OUString aIds[] = { "up", "down" };
331
332 if (rCurItem == "delete")
333 {
334 for (size_t j = 0; j< std::size(aIds); ++j)
335 m_xActions->set_item_active(aIds[j], false);
336
337 m_xListBox->make_unsorted();
338 Update();
339 return;
340 }
341
342 for (size_t j = 0; j< std::size(aIds); ++j)
343 m_xActions->set_item_active(aIds[j], rCurItem == aIds[j]);
344
345 m_xListBox->make_sorted();
346 if (m_xActions->get_item_active("down"))
347 m_xListBox->set_sort_order(false);
348}
349
350} // namespace rptui
351
352/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XExecutableDialog > m_xDialog
OAddFieldWindow(const OAddFieldWindow &)=delete
css::uno::Sequence< css::beans::PropertyValue > const & createPropertyValueSequence()
sal_Int32 m_nCommandType
OUString RptResId(TranslateId aId)
#define DBG_UNHANDLED_EXCEPTION(...)
ScXMLEditAttributeMap::Entry const aEntries[]
Reference< XColumn > xColumn
OUString sName
#define HID_RPT_FIELD_SEL_WIN
Definition: helpids.h:34
constexpr OUStringLiteral HID_RPT_FIELD_SEL
Definition: helpids.h:33
std::mutex m_aMutex
OUString m_sFilter
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XNameAccess > getFieldsByCommandDescriptor(const Reference< XConnection > &_rxConnection, const sal_Int32 _nCommandType, const OUString &_rCommand, Reference< XComponent > &_rxKeepFieldsAlive, SQLExceptionInfo *_pErrorInfo)
Reference< XConnection > getConnection(const Reference< XRowSet > &_rxRowSet)
int i
IMPL_LINK_NOARG(OAddFieldWindow, OnDoubleClickHdl, weld::TreeView &, bool)
Definition: AddField.cxx:316
css::uno::Sequence< OUString > getParameterNames(const css::uno::Reference< css::sdbc::XRowSet > &_rxRowSet)
retrieves the names of the parameters of the command which the given RowSet is bound to
IMPL_LINK(OAddFieldWindow, OnSortAction, const OUString &, rCurItem, void)
Definition: AddField.cxx:322
IMPL_LINK(OAddFieldWindow, DragBeginHdl, bool &, rUnsetDragIcon, bool)
Definition: AddField.cxx:50
OUString toId(const void *pValue)
constexpr OUStringLiteral PROPERTY_LABEL
Definition: strings.hxx:89
constexpr OUStringLiteral PROPERTY_COMMAND
Definition: strings.hxx:59
constexpr OUStringLiteral PROPERTY_ACTIVECONNECTION
Definition: strings.hxx:187
constexpr OUStringLiteral PROPERTY_COMMANDTYPE
Definition: strings.hxx:66
constexpr OUStringLiteral PROPERTY_FILTER
Definition: strings.hxx:183
constexpr OUStringLiteral PROPERTY_ESCAPEPROCESSING
Definition: strings.hxx:184
OUString sColumnName
Definition: ColumnInfo.hxx:29
Reference< XModel > xModel
OUString sId