LibreOffice Module reportdesign (master)  1
Navigator.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 <Navigator.hxx>
21 
22 #include <strings.hxx>
23 #include <bitmaps.hlst>
24 #include <ReportController.hxx>
25 #include <UITools.hxx>
26 #include <reportformula.hxx>
27 #include <com/sun/star/report/XReportDefinition.hpp>
28 #include <com/sun/star/report/XFixedText.hpp>
29 #include <com/sun/star/report/XFixedLine.hpp>
30 #include <com/sun/star/report/XFormattedField.hpp>
31 #include <com/sun/star/report/XImageControl.hpp>
32 #include <com/sun/star/report/XShape.hpp>
33 #include <helpids.h>
34 #include <strings.hrc>
35 #include <rptui_slotid.hrc>
39 #include <cppuhelper/basemutex.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/weld.hxx>
43 #include <vcl/commandevent.hxx>
44 #include <ReportVisitor.hxx>
45 #include <core_resource.hxx>
46 #include <rtl/ref.hxx>
47 #include <svx/svxids.hrc>
48 
49 #include <memory>
50 #include <string_view>
51 
52 namespace rptui
53 {
54 using namespace ::com::sun::star;
55 using namespace utl;
56 using namespace ::comphelper;
57 
58 static OUString lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement)
59 {
60  OUString sId;
61  uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY);
62  if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() )
63  sId = RID_SVXBMP_FM_FIXEDTEXT;
64  else if ( xFixedLine.is() )
65  sId = xFixedLine->getOrientation() ? OUString(RID_SVXBMP_INSERT_VFIXEDLINE) : OUString(RID_SVXBMP_INSERT_HFIXEDLINE);
66  else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() )
67  sId = RID_SVXBMP_FM_EDIT;
68  else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() )
69  sId = RID_SVXBMP_FM_IMAGECONTROL;
70  else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() )
71  sId = RID_SVXBMP_DRAWTBX_CS_BASIC;
72  return sId;
73 }
74 
75 static OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement)
76 {
77  OSL_ENSURE(_xElement.is(),"Found report element which is NULL!");
78  OUString sTempName;
79  _xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName;
80  OUStringBuffer sName(sTempName);
81  uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY);
82  uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY);
83  if ( xFixedText.is() )
84  {
85  sName.append(" : ");
86  sName.append(xFixedText->getLabel());
87  }
88  else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) )
89  {
90  ReportFormula aFormula( xReportModel->getDataField() );
91  if ( aFormula.isValid() )
92  {
93  sName.append(" : ");
94  sName.append( aFormula.getUndecoratedContent() );
95  }
96  }
97  return sName.makeStringAndClear();
98 }
99 
100 namespace {
101 
102 class NavigatorTree : public ::cppu::BaseMutex
106 {
107  class UserData;
108  friend class UserData;
109  class UserData : public ::cppu::BaseMutex
112  {
113  uno::Reference< uno::XInterface > m_xContent;
116  NavigatorTree* m_pTree;
117  public:
118  UserData(NavigatorTree* pTree, const uno::Reference<uno::XInterface>& xContent);
119  virtual ~UserData() override;
120 
121  const uno::Reference< uno::XInterface >& getContent() const { return m_xContent; }
122  void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; }
123 
124  protected:
125  // OPropertyChangeListener
126  virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override;
127 
128  // OContainerListener
129  virtual void _elementInserted( const container::ContainerEvent& _rEvent ) override;
130  virtual void _elementRemoved( const container::ContainerEvent& Event ) override;
131  virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) override;
132  virtual void _disposing(const lang::EventObject& _rSource) override;
133  };
134 
135  std::unique_ptr<weld::TreeView> m_xTreeView;
136  OReportController& m_rController;
137  std::unique_ptr<weld::TreeIter> m_xMasterReport;
140 
141  void insertEntry(const OUString& rName, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition, const UserData* pData, weld::TreeIter& rRet);
142 
143  void traverseSection(const uno::Reference<report::XSection>& xSection, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition = -1);
144  void traverseFunctions(const uno::Reference< report::XFunctions>& xFunctions, const weld::TreeIter* pParent);
145 
146 protected:
147  // OSelectionChangeListener
148  virtual void _disposing(const lang::EventObject& _rSource) override;
149 
150  // OPropertyChangeListener
151  virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override;
152 
153  // OContainerListener Helper
154  void _elementInserted( const container::ContainerEvent& _rEvent );
155  void _elementRemoved( const container::ContainerEvent& Event );
156  void _elementReplaced( const container::ContainerEvent& _rEvent );
157 
158 public:
159  NavigatorTree(std::unique_ptr<weld::TreeView>, OReportController& rController);
160  virtual ~NavigatorTree() override;
161 
162  DECL_LINK(OnEntrySelDesel, weld::TreeView&, void);
163  DECL_LINK(CommandHdl, const CommandEvent&, bool);
164 
165  virtual void _selectionChanged( const lang::EventObject& aEvent ) override;
166 
167  // ITraverseReport
168  virtual void traverseReport(const uno::Reference< report::XReportDefinition>& xReport) override;
169  virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& xFunctions) override;
170  virtual void traverseReportHeader(const uno::Reference< report::XSection>& xSection) override;
171  virtual void traverseReportFooter(const uno::Reference< report::XSection>& xSection) override;
172  virtual void traversePageHeader(const uno::Reference< report::XSection>& xSection) override;
173  virtual void traversePageFooter(const uno::Reference< report::XSection>& xSection) override;
174 
175  virtual void traverseGroups(const uno::Reference< report::XGroups>& xGroups) override;
176  virtual void traverseGroup(const uno::Reference< report::XGroup>& xGroup) override;
177  virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& xFunctions) override;
178  virtual void traverseGroupHeader(const uno::Reference< report::XSection>& xSection) override;
179  virtual void traverseGroupFooter(const uno::Reference< report::XSection>& xSection) override;
180 
181  virtual void traverseDetail(const uno::Reference< report::XSection>& xSection) override;
182 
183  bool find(const uno::Reference<uno::XInterface>& xContent, weld::TreeIter& rIter);
184  void removeEntry(const weld::TreeIter& rEntry, bool bRemove = true);
185 
186  void grab_focus() { m_xTreeView->grab_focus(); }
187 
188  void set_text(const weld::TreeIter& rIter, const OUString& rStr)
189  {
190  m_xTreeView->set_text(rIter, rStr);
191  }
192 
193  void expand_row(const weld::TreeIter& rIter)
194  {
195  m_xTreeView->expand_row(rIter);
196  }
197 
198  std::unique_ptr<weld::TreeIter> make_iterator() const
199  {
200  return m_xTreeView->make_iterator();
201  }
202 
203  int iter_n_children(const weld::TreeIter& rIter) const
204  {
205  return m_xTreeView->iter_n_children(rIter);
206  }
207 };
208 
209 }
210 
211 NavigatorTree::NavigatorTree(std::unique_ptr<weld::TreeView> xTreeView, OReportController& rController)
212  : OPropertyChangeListener(m_aMutex)
213  , m_xTreeView(std::move(xTreeView))
214  , m_rController(rController)
215 {
216  m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 25, m_xTreeView->get_height_rows(18));
217 
218  m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition());
219  m_pReportListener->addProperty(PROPERTY_PAGEHEADERON);
220  m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON);
221  m_pReportListener->addProperty(PROPERTY_REPORTHEADERON);
222  m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON);
223 
224  m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController);
225 
226  m_xTreeView->set_help_id(HID_REPORT_NAVIGATOR_TREE);
227 
228  m_xTreeView->set_selection_mode(SelectionMode::Multiple);
229 
230  m_xTreeView->connect_changed(LINK(this, NavigatorTree, OnEntrySelDesel));
231  m_xTreeView->connect_popup_menu(LINK(this, NavigatorTree, CommandHdl));
232 }
233 
234 NavigatorTree::~NavigatorTree()
235 {
236  m_xTreeView->all_foreach([this](weld::TreeIter& rIter) {
237  UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_id(rIter));
238  delete pData;
239  return false;
240  });
241  m_pReportListener->dispose();
242 }
243 
244 namespace
245 {
246  sal_uInt16 mapIdent(std::string_view rIdent)
247  {
248  if (rIdent == "sorting")
249  return SID_SORTINGANDGROUPING;
250  else if (rIdent == "page")
251  return SID_PAGEHEADERFOOTER;
252  else if (rIdent == "report")
253  return SID_REPORTHEADERFOOTER;
254  else if (rIdent == "function")
255  return SID_RPT_NEW_FUNCTION;
256  else if (rIdent == "properties")
257  return SID_SHOW_PROPERTYBROWSER;
258  else if (rIdent == "delete")
259  return SID_DELETE;
260  return 0;
261  }
262 }
263 
264 IMPL_LINK(NavigatorTree, CommandHdl, const CommandEvent&, rEvt, bool)
265 {
266  bool bHandled = false;
267  switch( rEvt.GetCommand())
268  {
269  case CommandEventId::ContextMenu:
270  {
271  UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_selected_id());
272  if (!pData)
273  break;
274 
275  uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY);
276  uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY);
277  uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY);
278  bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() ||
279  uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is());
280 
281  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/dbreport/ui/navigatormenu.ui"));
282  std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
283 
284  const OString aIds[] = { "sorting", "page", "report", "function", "properties", "delete" };
285  for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
286  {
287  sal_uInt16 nSId = mapIdent(aIds[i]);
288 
289  if (aIds[i] == "page" || aIds[i] == "report" || aIds[i] == "properties")
290  xContextMenu->set_active(aIds[i], m_rController.isCommandChecked(nSId));
291  bool bEnabled = m_rController.isCommandEnabled(nSId);
292  if (nSId == SID_RPT_NEW_FUNCTION)
293  xContextMenu->set_sensitive(aIds[i], m_rController.isEditable() && (xSupplier.is() || xFunctions.is()));
294  // special condition, check for function and group
295  else if (nSId == SID_DELETE)
296  xContextMenu->set_sensitive(aIds[i], bDeleteAllowed);
297  else
298  xContextMenu->set_sensitive(aIds[i], bEnabled);
299  }
300 
301  // the point that was clicked on
302  ::Point aWhere(rEvt.GetMousePosPixel());
303  OString sCurItemIdent = xContextMenu->popup_at_rect(m_xTreeView.get(), tools::Rectangle(aWhere, Size(1,1)));
304  if (!sCurItemIdent.isEmpty())
305  {
306  sal_uInt16 nId = mapIdent(sCurItemIdent);
307  uno::Sequence< beans::PropertyValue> aArgs;
308  if ( nId == SID_RPT_NEW_FUNCTION )
309  {
310  aArgs.realloc(1);
311  aArgs.getArray()[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions());
312  }
313  else if ( nId == SID_DELETE )
314  {
315  if ( xGroup.is() )
316  nId = SID_GROUP_REMOVE;
317  aArgs = { comphelper::makePropertyValue(PROPERTY_GROUP, pData->getContent()) };
318  }
319  m_rController.executeUnChecked(nId,aArgs);
320  }
321 
322  bHandled = true;
323  }
324  break;
325  default: break;
326  }
327 
328  return bHandled;
329 }
330 
331 IMPL_LINK_NOARG(NavigatorTree, OnEntrySelDesel, weld::TreeView&, void)
332 {
333  if ( !m_pSelectionListener->locked() )
334  {
335  m_pSelectionListener->lock();
336  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
337  bool bEntry = m_xTreeView->get_cursor(xEntry.get());
338  uno::Any aSelection;
339  if (bEntry && m_xTreeView->is_selected(*xEntry))
340  aSelection <<= weld::fromId<UserData*>(m_xTreeView->get_id(*xEntry))->getContent();
341  m_rController.select(aSelection);
342  m_pSelectionListener->unlock();
343  }
344 }
345 
346 void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent )
347 {
348  m_pSelectionListener->lock();
349  uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY);
350  uno::Any aSec = xSelectionSupplier->getSelection();
351  uno::Sequence< uno::Reference< report::XReportComponent > > aSelection;
352  aSec >>= aSelection;
353  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
354  if ( !aSelection.hasElements() )
355  {
356  uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY);
357  bool bEntry = find(xSelection, *xEntry);
358  if (bEntry && !m_xTreeView->is_selected(*xEntry))
359  {
360  m_xTreeView->select(*xEntry);
361  m_xTreeView->set_cursor(*xEntry);
362  }
363  else if (!bEntry)
364  m_xTreeView->unselect_all();
365  }
366  else
367  {
368  for (const uno::Reference<report::XReportComponent>& rElem : std::as_const(aSelection))
369  {
370  bool bEntry = find(rElem, *xEntry);
371  if (bEntry && !m_xTreeView->is_selected(*xEntry))
372  {
373  m_xTreeView->select(*xEntry);
374  m_xTreeView->set_cursor(*xEntry);
375  }
376  }
377  }
378  m_pSelectionListener->unlock();
379 }
380 
381 void NavigatorTree::insertEntry(const OUString& rName, const weld::TreeIter* pParent, const OUString& rImageId,
382  int nPosition, const UserData* pData, weld::TreeIter& rRet)
383 {
384  OUString sId = pData ? weld::toId(pData) : OUString();
385  m_xTreeView->insert(pParent, nPosition, &rName, &sId, nullptr, nullptr, false, &rRet);
386  if (!rImageId.isEmpty())
387  m_xTreeView->set_image(rRet, rImageId);
388 }
389 
390 void NavigatorTree::traverseSection(const uno::Reference<report::XSection>& xSection, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition)
391 {
392  std::unique_ptr<weld::TreeIter> xSectionIter = m_xTreeView->make_iterator();
393  std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
394  insertEntry(xSection->getName(), pParent, rImageId, nPosition, new UserData(this, xSection), *xSectionIter);
395  const sal_Int32 nCount = xSection->getCount();
396  for (sal_Int32 i = 0; i < nCount; ++i)
397  {
398  uno::Reference< report::XReportComponent> xElement(xSection->getByIndex(i), uno::UNO_QUERY_THROW);
399  insertEntry(lcl_getName(xElement), xSectionIter.get(), lcl_getImageId(xElement), -1, new UserData(this, xElement), *xScratch);
400  uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY);
401  if ( xSubReport.is() )
402  {
403  bool bMasterReport = find(xSection->getReportDefinition(), *xScratch);
404  if (!bMasterReport)
405  m_xMasterReport.reset();
406  else
407  m_xMasterReport = m_xTreeView->make_iterator(xScratch.get());
408  reportdesign::OReportVisitor aSubVisitor(this);
409  aSubVisitor.start(xSubReport);
410  }
411  }
412 }
413 
414 void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& xFunctions, const weld::TreeIter* pParent)
415 {
416  std::unique_ptr<weld::TreeIter> xFunctionIter = m_xTreeView->make_iterator();
417  std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
418  insertEntry(RptResId(RID_STR_FUNCTIONS), pParent, RID_SVXBMP_RPT_NEW_FUNCTION, -1, new UserData(this, xFunctions), *xFunctionIter);
419  const sal_Int32 nCount = xFunctions->getCount();
420  for (sal_Int32 i = 0; i< nCount; ++i)
421  {
422  uno::Reference< report::XFunction> xElement(xFunctions->getByIndex(i),uno::UNO_QUERY);
423  insertEntry(xElement->getName(), xFunctionIter.get(), RID_SVXBMP_RPT_NEW_FUNCTION, -1, new UserData(this,xElement), *xScratch);
424  }
425 }
426 
427 bool NavigatorTree::find(const uno::Reference<uno::XInterface>& xContent, weld::TreeIter& rRet)
428 {
429  bool bRet = false;
430  if (xContent.is())
431  {
432  m_xTreeView->all_foreach([this, &xContent, &bRet, &rRet](weld::TreeIter& rIter) {
433  UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_id(rIter));
434  if (pData->getContent() == xContent)
435  {
436  m_xTreeView->copy_iterator(rIter, rRet);
437  bRet = true;
438  return true;
439  }
440  return false;
441  });
442  }
443  return bRet;
444 }
445 
446 // ITraverseReport
447 
448 void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& xReport)
449 {
450  std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
451  insertEntry(xReport->getName(), m_xMasterReport.get(), RID_SVXBMP_SELECT_REPORT,-1, new UserData(this, xReport), *xScratch);
452 }
453 
454 void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& xFunctions)
455 {
456  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
457  bool bReport = find(xFunctions->getParent(), *xReport);
458  if (!bReport)
459  xReport.reset();
460  traverseFunctions(xFunctions, xReport.get());
461 }
462 
463 void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& xSection)
464 {
465  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
466  bool bReport = find(xSection->getReportDefinition(), *xReport);
467  if (!bReport)
468  xReport.reset();
469  traverseSection(xSection, xReport.get(), RID_SVXBMP_REPORTHEADERFOOTER);
470 }
471 
472 void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& xSection)
473 {
474  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
475  bool bReport = find(xSection->getReportDefinition(), *xReport);
476  if (!bReport)
477  xReport.reset();
478  traverseSection(xSection, xReport.get(), RID_SVXBMP_REPORTHEADERFOOTER);
479 }
480 
481 void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& xSection)
482 {
483  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
484  bool bReport = find(xSection->getReportDefinition(), *xReport);
485  if (!bReport)
486  xReport.reset();
487  traverseSection(xSection, xReport.get(), RID_SVXBMP_PAGEHEADERFOOTER);
488 }
489 
490 void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& xSection)
491 {
492  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
493  bool bReport = find(xSection->getReportDefinition(), *xReport);
494  if (!bReport)
495  xReport.reset();
496  traverseSection(xSection, xReport.get(), RID_SVXBMP_PAGEHEADERFOOTER);
497 }
498 
499 void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& xGroups)
500 {
501  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
502  bool bReport = find(xGroups->getReportDefinition(), *xReport);
503  if (!bReport)
504  xReport.reset();
505  std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
506  insertEntry(RptResId(RID_STR_GROUPS), xReport.get(), RID_SVXBMP_SORTINGANDGROUPING, -1, new UserData(this, xGroups), *xScratch);
507 }
508 
509 void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& xGroup)
510 {
511  uno::Reference< report::XGroups> xGroups(xGroup->getParent(),uno::UNO_QUERY);
512  std::unique_ptr<weld::TreeIter> xGroupsIter = m_xTreeView->make_iterator();
513  bool bGroups = find(xGroups, *xGroupsIter);
514  OSL_ENSURE(bGroups, "No Groups inserted so far. Why!");
515  if (!bGroups)
516  xGroupsIter.reset();
517  std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
518  insertEntry(xGroup->getExpression(), xGroupsIter.get(), RID_SVXBMP_GROUP, rptui::getPositionInIndexAccess(xGroups,xGroup), new UserData(this,xGroup), *xScratch);
519 }
520 
521 void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& xFunctions)
522 {
523  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
524  bool bReport = find(xFunctions->getParent(), *xReport);
525  if (!bReport)
526  xReport.reset();
527  traverseFunctions(xFunctions, xReport.get());
528 }
529 
530 void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& xSection)
531 {
532  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
533  bool bReport = find(xSection->getGroup(), *xReport);
534  OSL_ENSURE(bReport, "No group found");
535  if (!bReport)
536  xReport.reset();
537  traverseSection(xSection, xReport.get(), RID_SVXBMP_GROUPHEADER, 1);
538 }
539 
540 void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& xSection)
541 {
542  std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
543  bool bReport = find(xSection->getGroup(), *xReport);
544  OSL_ENSURE(bReport, "No group found");
545  if (!bReport)
546  xReport.reset();
547  traverseSection(xSection, xReport.get(), RID_SVXBMP_GROUPFOOTER);
548 }
549 
550 void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& xSection)
551 {
552  uno::Reference< report::XReportDefinition> xReport = xSection->getReportDefinition();
553  std::unique_ptr<weld::TreeIter> xParent = m_xTreeView->make_iterator();
554  bool bParent = find(xReport, *xParent);
555  if (!bParent)
556  xParent.reset();
557  traverseSection(xSection, xParent.get(), RID_SVXBMP_ICON_DETAIL);
558 }
559 
560 void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
561 {
562  uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY);
563  if ( !xReport.is() )
564  return;
565 
566  bool bEnabled = false;
567  _rEvent.NewValue >>= bEnabled;
568  if ( !bEnabled )
569  return;
570 
571  std::unique_ptr<weld::TreeIter> xParent = m_xTreeView->make_iterator();
572  bool bParent = find(xReport, *xParent);
573  if (!bParent)
574  xParent.reset();
575  if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON )
576  {
577  sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1;
578  traverseSection(xReport->getReportHeader(),xParent.get(),RID_SVXBMP_REPORTHEADERFOOTER,nPos);
579  }
580  else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON )
581  {
582  traverseSection(xReport->getPageHeader(),xParent.get(), RID_SVXBMP_PAGEHEADERFOOTER,1);
583  }
584  else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON )
585  traverseSection(xReport->getPageFooter(),xParent.get(), RID_SVXBMP_PAGEHEADERFOOTER);
586  else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON )
587  {
588  int nPos = -1;
589  if (xReport->getPageFooterOn() && xParent)
590  nPos = m_xTreeView->iter_n_children(*xParent) - 1;
591  traverseSection(xReport->getReportFooter(),xParent.get(),RID_SVXBMP_REPORTHEADERFOOTER,nPos);
592  }
593 }
594 
595 void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent )
596 {
597  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
598  bool bEntry = find(_rEvent.Source, *xEntry);
599  if (!bEntry)
600  xEntry.reset();
601  uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW);
602  OUString sName;
603  uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
604  if ( xInfo.is() )
605  {
606  if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
607  xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
608  else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
609  xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName;
610  }
611  uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY);
612  if ( xGroup.is() )
613  {
614  reportdesign::OReportVisitor aSubVisitor(this);
615  aSubVisitor.start(xGroup);
616  }
617  else
618  {
619  uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY);
620  if ( xProp.is() )
621  sName = lcl_getName(xProp);
622  std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
623  insertEntry(sName, xEntry.get(), (!xElement.is() ? OUString(RID_SVXBMP_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)),
624  -1, new UserData(this,xProp), *xScratch);
625  }
626  if (bEntry && !m_xTreeView->get_row_expanded(*xEntry))
627  m_xTreeView->expand_row(*xEntry);
628 }
629 
630 void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent )
631 {
632  uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY);
633  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
634  bool bEntry = find(xProp, *xEntry);
635  OSL_ENSURE(bEntry,"NavigatorTree::_elementRemoved: No Entry found!");
636 
637  if (bEntry)
638  {
639  removeEntry(*xEntry);
640  }
641 }
642 
643 void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent )
644 {
645  uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY);
646  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
647  bool bEntry = find(xProp, *xEntry);
648  if (bEntry)
649  {
650  UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_id(*xEntry));
651  xProp.set(_rEvent.Element,uno::UNO_QUERY);
652  pData->setContent(xProp);
653  OUString sName;
654  xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
655  m_xTreeView->set_text(*xEntry, sName);
656  }
657 }
658 
659 void NavigatorTree::_disposing(const lang::EventObject& _rSource)
660 {
661  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
662  if (find(_rSource.Source, *xEntry))
663  removeEntry(*xEntry);
664 }
665 
666 void NavigatorTree::removeEntry(const weld::TreeIter& rEntry, bool bRemove)
667 {
668  std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator(&rEntry);
669  bool bChild = m_xTreeView->iter_children(*xChild);
670  while (bChild)
671  {
672  removeEntry(*xChild, false);
673  bChild = m_xTreeView->iter_next_sibling(*xChild);
674  }
675  delete weld::fromId<UserData*>(m_xTreeView->get_id(rEntry));
676  if (bRemove)
677  m_xTreeView->remove(rEntry);
678 }
679 
680 NavigatorTree::UserData::UserData(NavigatorTree* pTree,const uno::Reference<uno::XInterface>& xContent)
681  : OPropertyChangeListener(m_aMutex)
682  , OContainerListener(m_aMutex)
683  , m_xContent(xContent)
684  , m_pTree(pTree)
685 {
686  uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY);
687  if ( xProp.is() )
688  {
689  uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
690  if ( xInfo.is() )
691  {
692  m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp);
693  if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
694  m_pListener->addProperty(PROPERTY_NAME);
695  else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
696  m_pListener->addProperty(PROPERTY_EXPRESSION);
697  if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) )
698  m_pListener->addProperty(PROPERTY_DATAFIELD);
699  if ( xInfo->hasPropertyByName(PROPERTY_LABEL) )
700  m_pListener->addProperty(PROPERTY_LABEL);
701  if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) )
702  m_pListener->addProperty(PROPERTY_HEADERON);
703  if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) )
704  m_pListener->addProperty(PROPERTY_FOOTERON);
705  }
706  }
707  uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY);
708  if ( xContainer.is() )
709  {
710  m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
711  }
712 }
713 
714 NavigatorTree::UserData::~UserData()
715 {
716  if ( m_pContainerListener.is() )
717  m_pContainerListener->dispose();
718  if ( m_pListener.is() )
719  m_pListener->dispose();
720 }
721 
722 // OPropertyChangeListener
723 void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
724 {
725  std::unique_ptr<weld::TreeIter> xEntry = m_pTree->make_iterator();
726  bool bEntry = m_pTree->find(_rEvent.Source, *xEntry);
727  OSL_ENSURE(bEntry,"No entry could be found! Why not!");
728  if (!bEntry)
729  return;
730  const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName);
731  try
732  {
733  if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName )
734  {
735  sal_Int32 nPos = 1;
736  uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY);
737  ::std::function<bool(OGroupHelper *)> pIsOn = ::std::mem_fn(&OGroupHelper::getHeaderOn);
738  ::std::function<uno::Reference<report::XSection>(OGroupHelper *)> pMemFunSection = ::std::mem_fn(&OGroupHelper::getHeader);
739  if ( bFooterOn )
740  {
741  pIsOn = ::std::mem_fn(&OGroupHelper::getFooterOn);
742  pMemFunSection = ::std::mem_fn(&OGroupHelper::getFooter);
743  nPos = m_pTree->iter_n_children(*xEntry) - 1;
744  }
745 
746  OGroupHelper aGroupHelper(xGroup);
747  if ( pIsOn(&aGroupHelper) )
748  {
749  if ( bFooterOn )
750  ++nPos;
751  m_pTree->traverseSection(pMemFunSection(&aGroupHelper),xEntry.get(),bFooterOn ? OUString(RID_SVXBMP_GROUPFOOTER) : OUString(RID_SVXBMP_GROUPHEADER),nPos);
752  }
753  }
754  else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName)
755  {
756  OUString sNewName;
757  _rEvent.NewValue >>= sNewName;
758  m_pTree->set_text(*xEntry, sNewName);
759  }
760  else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName )
761  {
762  uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY);
763  m_pTree->set_text(*xEntry, lcl_getName(xProp));
764  }
765  }
766  catch(const uno::Exception &)
767  {}
768 }
769 
770 void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent )
771 {
772  m_pTree->_elementInserted( _rEvent );
773 }
774 
775 void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent )
776 {
777  m_pTree->_elementRemoved( _rEvent );
778 }
779 
780 void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent )
781 {
782  m_pTree->_elementReplaced( _rEvent );
783 }
784 
785 void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource)
786 {
787  m_pTree->_disposing( _rSource );
788 }
789 
791 {
792 public:
793  ONavigatorImpl(OReportController& rController, weld::Builder& rBuilder);
794  ONavigatorImpl(const ONavigatorImpl&) = delete;
795  ONavigatorImpl& operator=(const ONavigatorImpl&) = delete;
796 
797  uno::Reference< report::XReportDefinition> m_xReport;
798  std::unique_ptr<NavigatorTree> m_xNavigatorTree;
799 };
800 
801 ONavigatorImpl::ONavigatorImpl(OReportController& rController, weld::Builder& rBuilder)
802  : m_xReport(rController.getReportDefinition())
803  , m_xNavigatorTree(std::make_unique<NavigatorTree>(rBuilder.weld_tree_view("treeview"), rController))
804 {
806  aVisitor.start(m_xReport);
807  std::unique_ptr<weld::TreeIter> xScratch = m_xNavigatorTree->make_iterator();
808  if (m_xNavigatorTree->find(m_xReport, *xScratch))
809  m_xNavigatorTree->expand_row(*xScratch);
810  lang::EventObject aEvent(rController);
811  m_xNavigatorTree->_selectionChanged(aEvent);
812 }
813 
815  : GenericDialogController(pParent, "modules/dbreport/ui/floatingnavigator.ui", "FloatingNavigator")
816 {
817  m_pImpl.reset(new ONavigatorImpl(rController, *m_xBuilder));
818  m_pImpl->m_xNavigatorTree->grab_focus();
819 
820  m_xDialog->connect_container_focus_changed(LINK(this, ONavigator, FocusChangeHdl));
821 }
822 
824 {
825 }
826 
828 {
829  if (m_xDialog->has_toplevel_focus())
830  m_pImpl->m_xNavigatorTree->grab_focus();
831 }
832 
833 } // rptui
834 
835 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::shared_ptr< weld::Dialog > m_xDialog
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
#define PROPERTY_LABEL
Definition: strings.hxx:89
rEdit set_text(aStr)
#define PROPERTY_HEADERON
Definition: strings.hxx:71
std::unique_ptr< weld::Builder > m_xBuilder
#define PROPERTY_GROUP
Definition: strings.hxx:48
std::unique_ptr< sal_Int32[]> pData
IMPL_LINK_NOARG(ONavigator, FocusChangeHdl, weld::Container &, void)
Definition: Navigator.cxx:827
sal_uIntPtr sal_uLong
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
sal_Int16 nId
uno::Reference< report::XReportDefinition > m_xReport
Definition: Navigator.cxx:797
#define PROPERTY_FOOTERON
Definition: strings.hxx:72
IMPL_LINK(NavigatorTree, CommandHdl, const CommandEvent &, rEvt, bool)
Definition: Navigator.cxx:264
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
#define PROPERTY_DATAFIELD
Definition: strings.hxx:78
#define PROPERTY_PAGEHEADERON
Definition: strings.hxx:69
int nCount
std::mutex m_aMutex
::std::unique_ptr< ONavigatorImpl > m_pImpl
Definition: Navigator.hxx:30
const char * sName
#define SAL_N_ELEMENTS(arr)
#define PROPERTY_REPORTFOOTERON
Definition: strings.hxx:68
#define PROPERTY_NAME
Definition: strings.hxx:36
OUString RptResId(TranslateId aId)
int i
IMPL_LINK_NOARG(OAddFieldWindow, FocusChangeHdl, weld::Container &, void)
Definition: AddField.cxx:120
std::unique_ptr< NavigatorTree > m_xNavigatorTree
Definition: Navigator.cxx:798
ONavigator(const ONavigator &)=delete
static OUString lcl_getImageId(const uno::Reference< report::XReportComponent > &_xElement)
Definition: Navigator.cxx:58
#define PROPERTY_EXPRESSION
Definition: strings.hxx:52
OUString toId(const void *pValue)
sal_Int32 getPositionInIndexAccess(const css::uno::Reference< css::container::XIndexAccess > &_xCollection, const css::uno::Reference< T > &_xSearch)
returns the position of the object inside the index container
Definition: UITools.hxx:52
#define PROPERTY_REPORTHEADERON
Definition: strings.hxx:67
constexpr OStringLiteral HID_REPORT_NAVIGATOR_TREE
Definition: helpids.h:77
void start(const css::uno::Reference< css::report::XReportDefinition > &_xReportDefinition)
Reference< XExecutableDialog > m_xDialog
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
#define PROPERTY_PAGEFOOTERON
Definition: strings.hxx:70
sal_uInt16 nPos
static std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false, sal_uInt64 nLOKWindowId=0)
static OUString lcl_getName(const uno::Reference< beans::XPropertySet > &_xElement)
Definition: Navigator.cxx:75
OUString sId