LibreOffice Module extensions (master) 1
selectlabeldialog.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
20#include <sal/config.h>
21
22#include "selectlabeldialog.hxx"
23#include <strings.hrc>
24#include <bitmaps.hlst>
25#include "formbrowsertools.hxx"
26#include "formstrings.hxx"
27#include "modulepcr.hxx"
28#include <com/sun/star/form/FormComponentType.hpp>
29#include <com/sun/star/container/XChild.hpp>
30#include <com/sun/star/container/XIndexAccess.hpp>
31#include <com/sun/star/sdbc/XResultSet.hpp>
32#include <com/sun/star/beans/XPropertySet.hpp>
33#include <com/sun/star/lang/XServiceInfo.hpp>
35#include <comphelper/types.hxx>
36#include <sal/log.hxx>
37#include <tools/debug.hxx>
38
39
40namespace pcr
41{
42
43
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::container;
46 using namespace ::com::sun::star::beans;
47 using namespace ::com::sun::star::form;
48 using namespace ::com::sun::star::sdbc;
49 using namespace ::com::sun::star::lang;
50
51
52 // OSelectLabelDialog
53 OSelectLabelDialog::OSelectLabelDialog(weld::Window* pParent, Reference< XPropertySet > const & _xControlModel)
54 : GenericDialogController(pParent, "modules/spropctrlr/ui/labelselectiondialog.ui", "LabelSelectionDialog")
55 , m_xControlModel(_xControlModel)
56 , m_bLastSelected(false)
57 , m_bHaveAssignableControl(false)
58 , m_xMainDesc(m_xBuilder->weld_label("label"))
59 , m_xControlTree(m_xBuilder->weld_tree_view("control"))
60 , m_xScratchIter(m_xControlTree->make_iterator())
61 , m_xNoAssignment(m_xBuilder->weld_check_button("noassignment"))
62 {
63 m_xControlTree->connect_changed(LINK(this, OSelectLabelDialog, OnEntrySelected));
64 m_xControlTree->set_size_request(-1, m_xControlTree->get_height_rows(8));
65
66 // fill the description
67 OUString sDescription = m_xMainDesc->get_label();
68 sal_Int16 nClassID = FormComponentType::CONTROL;
69 if (::comphelper::hasProperty(PROPERTY_CLASSID, m_xControlModel))
70 nClassID = ::comphelper::getINT16(m_xControlModel->getPropertyValue(PROPERTY_CLASSID));
71
72 sDescription = sDescription.replaceAll("$controlclass$",
74 OUString sName = ::comphelper::getString(m_xControlModel->getPropertyValue(PROPERTY_NAME));
75 sDescription = sDescription.replaceAll("$controlname$", sName);
76 m_xMainDesc->set_label(sDescription);
77
78 // search for the root of the form hierarchy
79 Reference< XChild > xCont(m_xControlModel, UNO_QUERY);
80 Reference< XInterface > xSearch( xCont.is() ? xCont->getParent() : Reference< XInterface > ());
81 Reference< XResultSet > xParentAsResultSet(xSearch, UNO_QUERY);
82 while (xParentAsResultSet.is())
83 {
84 xCont.set(xSearch, UNO_QUERY);
85 xSearch = xCont.is() ? xCont->getParent() : Reference< XInterface > ();
86 xParentAsResultSet.set(xSearch, UNO_QUERY);
87 }
88
89 // and insert all entries below this root into the listbox
90 if (xSearch.is())
91 {
92 // check which service the allowed components must support
93 sal_Int16 nClassId = 0;
94 try { nClassId = ::comphelper::getINT16(m_xControlModel->getPropertyValue(PROPERTY_CLASSID)); } catch(...) { }
95 m_sRequiredService = (FormComponentType::RADIOBUTTON == nClassId) ? OUString(SERVICE_COMPONENT_GROUPBOX) : OUString(SERVICE_COMPONENT_FIXEDTEXT);
96 m_aRequiredControlImage = (FormComponentType::RADIOBUTTON == nClassId) ? OUString(RID_EXTBMP_GROUPBOX) : OUString(RID_EXTBMP_FIXEDTEXT);
97
98 // calc the currently set label control (so InsertEntries can calc m_xInitialSelection)
99 Any aCurrentLabelControl( m_xControlModel->getPropertyValue(PROPERTY_CONTROLLABEL) );
100 DBG_ASSERT((aCurrentLabelControl.getValueTypeClass() == TypeClass_INTERFACE) || !aCurrentLabelControl.hasValue(),
101
102 "OSelectLabelDialog::OSelectLabelDialog : invalid ControlLabel property !");
103 if (aCurrentLabelControl.hasValue())
104 aCurrentLabelControl >>= m_xInitialLabelControl;
105
106 // insert the root
107 OUString sRootName(PcrRes(RID_STR_FORMS));
108 m_xControlTree->insert(nullptr, -1, &sRootName, nullptr,
109 nullptr, nullptr, false, m_xScratchIter.get());
110 m_xControlTree->set_image(*m_xScratchIter, RID_EXTBMP_FORMS);
111
112 // build the tree
113 m_xInitialSelection.reset();
115 std::unique_ptr<weld::TreeIter> xRoot = m_xControlTree->make_iterator();
116 m_xControlTree->get_iter_first(*xRoot);
117 InsertEntries(xSearch, *xRoot);
118 m_xControlTree->expand_row(*xRoot);
119 }
120
122 {
123 m_xControlTree->scroll_to_row(*m_xInitialSelection);
125 }
126 else
127 {
128 m_xControlTree->scroll_to_row(0);
129 m_xControlTree->unselect_all();
130 m_xNoAssignment->set_active(true);
131 }
132
134 { // no controls which can be assigned
135 m_xNoAssignment->set_active(true);
136 m_xNoAssignment->set_sensitive(false);
137 }
138
139 m_xLastSelected = m_xControlTree->make_iterator(nullptr);
140
141 m_xNoAssignment->connect_toggled(LINK(this, OSelectLabelDialog, OnNoAssignmentClicked));
142 OnNoAssignmentClicked(*m_xNoAssignment);
143 }
144
146 {
147 }
148
149 sal_Int32 OSelectLabelDialog::InsertEntries(const Reference< XInterface > & _xContainer, const weld::TreeIter& rContainerEntry)
150 {
151 Reference< XIndexAccess > xContainer(_xContainer, UNO_QUERY);
152 if (!xContainer.is())
153 return 0;
154
155 sal_Int32 nChildren = 0;
156 OUString sName;
157 Reference< XPropertySet > xAsSet;
158 for (sal_Int32 i=0; i<xContainer->getCount(); ++i)
159 {
160 xContainer->getByIndex(i) >>= xAsSet;
161 if (!xAsSet.is())
162 {
163 SAL_INFO("extensions.propctrlr", "OSelectLabelDialog::InsertEntries : strange : a form component which isn't a property set !");
164 continue;
165 }
166
167 if (!::comphelper::hasProperty(PROPERTY_NAME, xAsSet))
168 // we need at least a name for displaying ...
169 continue;
170 sName = ::comphelper::getString(xAsSet->getPropertyValue(PROPERTY_NAME));
171
172 // we need to check if the control model supports the required service
173 Reference< XServiceInfo > xInfo(xAsSet, UNO_QUERY);
174 if (!xInfo.is())
175 continue;
176
177 if (!xInfo->supportsService(m_sRequiredService))
178 { // perhaps it is a container
179 Reference< XIndexAccess > xCont(xAsSet, UNO_QUERY);
180 if (xCont.is() && xCont->getCount())
181 { // yes -> step down
182 m_xControlTree->insert(&rContainerEntry, -1, &sName, nullptr,
183 nullptr, nullptr, false, m_xScratchIter.get());
184 m_xControlTree->set_image(*m_xScratchIter, RID_EXTBMP_FORM);
185 auto xIter = m_xControlTree->make_iterator(&rContainerEntry);
186 m_xControlTree->iter_nth_child(*xIter, nChildren);
187 sal_Int32 nContChildren = InsertEntries(xCont, *xIter);
188 if (nContChildren)
189 {
190 m_xControlTree->expand_row(*xIter);
191 ++nChildren;
192 }
193 else
194 { // oops, no valid children -> remove the entry
195 m_xControlTree->remove(*xIter);
196 }
197 }
198 continue;
199 }
200
201 // get the label
202 if (!::comphelper::hasProperty(PROPERTY_LABEL, xAsSet))
203 continue;
204
205 OUString sDisplayName =
206 ::comphelper::getString(xAsSet->getPropertyValue(PROPERTY_LABEL)) +
207 " (" + sName + ")";
208
209 // all requirements met -> insert
210 m_xUserData.emplace_back(new Reference<XPropertySet>(xAsSet));
211 OUString sId(weld::toId(m_xUserData.back().get()));
212 m_xControlTree->insert(&rContainerEntry, -1, &sDisplayName, &sId, nullptr, nullptr, false, m_xScratchIter.get());
214
215 if (m_xInitialLabelControl == xAsSet)
216 {
217 m_xInitialSelection = m_xControlTree->make_iterator(&rContainerEntry);
218 m_xControlTree->iter_nth_child(*m_xInitialSelection, nChildren);
219 }
220
221 ++nChildren;
223 }
224
225 return nChildren;
226 }
227
228 IMPL_LINK(OSelectLabelDialog, OnEntrySelected, weld::TreeView&, rLB, void)
229 {
230 DBG_ASSERT(&rLB == m_xControlTree.get(), "OSelectLabelDialog::OnEntrySelected : where did this come from ?");
231 std::unique_ptr<weld::TreeIter> xIter = m_xControlTree->make_iterator();
232 bool bSelected = m_xControlTree->get_selected(xIter.get());
233 OUString sData = bSelected ? m_xControlTree->get_id(*xIter) : OUString();
234 if (!sData.isEmpty())
235 m_xSelectedControl.set(*weld::fromId<Reference<XPropertySet>*>(sData));
236 m_xNoAssignment->set_active(sData.isEmpty());
237 }
238
239 IMPL_LINK(OSelectLabelDialog, OnNoAssignmentClicked, weld::Toggleable&, rButton, void)
240 {
241 DBG_ASSERT(&rButton == m_xNoAssignment.get(), "OSelectLabelDialog::OnNoAssignmentClicked : where did this come from ?");
242
243 if (m_xNoAssignment->get_active())
244 {
245 m_bLastSelected = m_xControlTree->get_selected(m_xLastSelected.get());
246 }
247 else
248 {
249 DBG_ASSERT(m_bHaveAssignableControl, "OSelectLabelDialog::OnNoAssignmentClicked");
250 // search the first assignable entry
251 auto xSearch = m_xControlTree->make_iterator(nullptr);
252 bool bSearch = m_xControlTree->get_iter_first(*xSearch);
253 while (bSearch)
254 {
255 if (m_xControlTree->get_id(*xSearch).toInt64())
256 break;
257 bSearch = m_xControlTree->iter_next(*xSearch);
258 }
259 // and select it
260 if (bSearch)
261 {
262 m_xControlTree->copy_iterator(*xSearch, *m_xLastSelected);
263 m_xControlTree->select(*m_xLastSelected);
264 m_bLastSelected = true;
265 }
266 }
267
268 if (m_bLastSelected)
269 {
270 if (!m_xNoAssignment->get_active())
271 m_xControlTree->select(*m_xLastSelected);
272 else
273 m_xControlTree->unselect(*m_xLastSelected);
274 }
275 }
276} // namespace pcr
277
278
279/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::CheckButton > m_xNoAssignment
std::unique_ptr< weld::TreeView > m_xControlTree
virtual ~OSelectLabelDialog() override
std::vector< std::unique_ptr< css::uno::Reference< css::beans::XPropertySet > > > m_xUserData
css::uno::Reference< css::beans::XPropertySet > m_xInitialLabelControl
std::unique_ptr< weld::TreeIter > m_xInitialSelection
std::unique_ptr< weld::Label > m_xMainDesc
std::unique_ptr< weld::TreeIter > m_xLastSelected
std::unique_ptr< weld::TreeIter > m_xScratchIter
OSelectLabelDialog(weld::Window *pParent, css::uno::Reference< css::beans::XPropertySet > const &_xControlModel)
css::uno::Reference< css::beans::XPropertySet > m_xControlModel
sal_Int32 InsertEntries(const css::uno::Reference< css::uno::XInterface > &_xContainer, const weld::TreeIter &rContainerEntry)
#define DBG_ASSERT(sCon, aError)
OUString sName
constexpr OUStringLiteral PROPERTY_LABEL
Definition: formstrings.hxx:32
constexpr OUStringLiteral PROPERTY_NAME
Definition: formstrings.hxx:36
constexpr OUStringLiteral SERVICE_COMPONENT_GROUPBOX
constexpr OUStringLiteral PROPERTY_CONTROLLABEL
Definition: formstrings.hxx:31
constexpr OUStringLiteral PROPERTY_CLASSID
Definition: formstrings.hxx:30
constexpr OUStringLiteral SERVICE_COMPONENT_FIXEDTEXT
OUString sDisplayName
#define SAL_INFO(area, stream)
int i
a property handler for any virtual string properties
Definition: browserline.cxx:39
OUString PcrRes(TranslateId aId)
Definition: modulepcr.cxx:26
IMPL_LINK(OBrowserLine, OnButtonClicked, weld::Button &, rButton, void)
OUString GetUIHeadlineName(sal_Int16 nClassId, const Any &aUnoObj)
T fromId(const OUString &rValue)
OUString toId(const void *pValue)
OUString sId