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