summaryrefslogtreecommitdiffstats
path: root/reportdesign/source/ui/dlg/Navigator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'reportdesign/source/ui/dlg/Navigator.cxx')
-rw-r--r--reportdesign/source/ui/dlg/Navigator.cxx814
1 files changed, 814 insertions, 0 deletions
diff --git a/reportdesign/source/ui/dlg/Navigator.cxx b/reportdesign/source/ui/dlg/Navigator.cxx
new file mode 100644
index 0000000000..690d90ca1b
--- /dev/null
+++ b/reportdesign/source/ui/dlg/Navigator.cxx
@@ -0,0 +1,814 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Navigator.hxx>
+
+#include <strings.hxx>
+#include <bitmaps.hlst>
+#include <ReportController.hxx>
+#include <UITools.hxx>
+#include <reportformula.hxx>
+#include <com/sun/star/report/XFixedText.hpp>
+#include <com/sun/star/report/XFixedLine.hpp>
+#include <com/sun/star/report/XFormattedField.hpp>
+#include <com/sun/star/report/XImageControl.hpp>
+#include <com/sun/star/report/XShape.hpp>
+#include <helpids.h>
+#include <strings.hrc>
+#include <rptui_slotid.hrc>
+#include <comphelper/propmultiplex.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/containermultiplexer.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <comphelper/SelectionMultiplex.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/commandevent.hxx>
+#include <ReportVisitor.hxx>
+#include <core_resource.hxx>
+#include <rtl/ref.hxx>
+#include <svx/svxids.hrc>
+
+#include <memory>
+#include <string_view>
+
+namespace rptui
+{
+using namespace ::com::sun::star;
+using namespace utl;
+using namespace ::comphelper;
+
+static OUString lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement)
+{
+ OUString sId;
+ uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY);
+ if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() )
+ sId = RID_SVXBMP_FM_FIXEDTEXT;
+ else if ( xFixedLine.is() )
+ sId = xFixedLine->getOrientation() ? RID_SVXBMP_INSERT_VFIXEDLINE : RID_SVXBMP_INSERT_HFIXEDLINE;
+ else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() )
+ sId = RID_SVXBMP_FM_EDIT;
+ else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() )
+ sId = RID_SVXBMP_FM_IMAGECONTROL;
+ else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() )
+ sId = RID_SVXBMP_DRAWTBX_CS_BASIC;
+ return sId;
+}
+
+static OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement)
+{
+ OSL_ENSURE(_xElement.is(),"Found report element which is NULL!");
+ OUString sTempName;
+ _xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName;
+ OUStringBuffer sName(sTempName);
+ uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY);
+ uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY);
+ if ( xFixedText.is() )
+ {
+ sName.append(" : " + xFixedText->getLabel());
+ }
+ else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) )
+ {
+ ReportFormula aFormula( xReportModel->getDataField() );
+ if ( aFormula.isValid() )
+ {
+ sName.append(" : " + aFormula.getUndecoratedContent() );
+ }
+ }
+ return sName.makeStringAndClear();
+}
+
+class NavigatorTree : public ::cppu::BaseMutex
+ , public reportdesign::ITraverseReport
+ , public comphelper::OSelectionChangeListener
+ , public ::comphelper::OPropertyChangeListener
+{
+ class UserData;
+ friend class UserData;
+ class UserData : public ::cppu::BaseMutex
+ ,public ::comphelper::OPropertyChangeListener
+ ,public ::comphelper::OContainerListener
+ {
+ uno::Reference< uno::XInterface > m_xContent;
+ ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pListener;
+ ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener;
+ NavigatorTree* m_pTree;
+ public:
+ UserData(NavigatorTree* pTree, uno::Reference<uno::XInterface> xContent);
+ virtual ~UserData() override;
+
+ const uno::Reference< uno::XInterface >& getContent() const { return m_xContent; }
+ void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; }
+
+ protected:
+ // OPropertyChangeListener
+ virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override;
+
+ // OContainerListener
+ virtual void _elementInserted( const container::ContainerEvent& _rEvent ) override;
+ virtual void _elementRemoved( const container::ContainerEvent& Event ) override;
+ virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) override;
+ virtual void _disposing(const lang::EventObject& _rSource) override;
+ };
+
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ OReportController& m_rController;
+ std::unique_ptr<weld::TreeIter> m_xMasterReport;
+ ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener;
+ ::rtl::Reference< comphelper::OSelectionChangeMultiplexer> m_pSelectionListener;
+
+ void insertEntry(const OUString& rName, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition, const UserData* pData, weld::TreeIter& rRet);
+
+ void traverseSection(const uno::Reference<report::XSection>& xSection, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition = -1);
+ void traverseFunctions(const uno::Reference< report::XFunctions>& xFunctions, const weld::TreeIter* pParent);
+
+protected:
+ // OSelectionChangeListener
+ virtual void _disposing(const lang::EventObject& _rSource) override;
+
+ // OPropertyChangeListener
+ virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override;
+
+ // OContainerListener Helper
+ void _elementInserted( const container::ContainerEvent& _rEvent );
+ void _elementRemoved( const container::ContainerEvent& Event );
+ void _elementReplaced( const container::ContainerEvent& _rEvent );
+
+public:
+ NavigatorTree(std::unique_ptr<weld::TreeView>, OReportController& rController);
+ virtual ~NavigatorTree() override;
+
+ DECL_LINK(OnEntrySelDesel, weld::TreeView&, void);
+ DECL_LINK(CommandHdl, const CommandEvent&, bool);
+
+ virtual void _selectionChanged( const lang::EventObject& aEvent ) override;
+
+ // ITraverseReport
+ virtual void traverseReport(const uno::Reference< report::XReportDefinition>& xReport) override;
+ virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& xFunctions) override;
+ virtual void traverseReportHeader(const uno::Reference< report::XSection>& xSection) override;
+ virtual void traverseReportFooter(const uno::Reference< report::XSection>& xSection) override;
+ virtual void traversePageHeader(const uno::Reference< report::XSection>& xSection) override;
+ virtual void traversePageFooter(const uno::Reference< report::XSection>& xSection) override;
+
+ virtual void traverseGroups(const uno::Reference< report::XGroups>& xGroups) override;
+ virtual void traverseGroup(const uno::Reference< report::XGroup>& xGroup) override;
+ virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& xFunctions) override;
+ virtual void traverseGroupHeader(const uno::Reference< report::XSection>& xSection) override;
+ virtual void traverseGroupFooter(const uno::Reference< report::XSection>& xSection) override;
+
+ virtual void traverseDetail(const uno::Reference< report::XSection>& xSection) override;
+
+ bool find(const uno::Reference<uno::XInterface>& xContent, weld::TreeIter& rIter);
+ void removeEntry(const weld::TreeIter& rEntry, bool bRemove = true);
+
+ void grab_focus() { m_xTreeView->grab_focus(); }
+
+ void set_text(const weld::TreeIter& rIter, const OUString& rStr)
+ {
+ m_xTreeView->set_text(rIter, rStr);
+ }
+
+ void expand_row(const weld::TreeIter& rIter)
+ {
+ m_xTreeView->expand_row(rIter);
+ }
+
+ std::unique_ptr<weld::TreeIter> make_iterator() const
+ {
+ return m_xTreeView->make_iterator();
+ }
+
+ int iter_n_children(const weld::TreeIter& rIter) const
+ {
+ return m_xTreeView->iter_n_children(rIter);
+ }
+};
+
+NavigatorTree::NavigatorTree(std::unique_ptr<weld::TreeView> xTreeView, OReportController& rController)
+ : OPropertyChangeListener(m_aMutex)
+ , m_xTreeView(std::move(xTreeView))
+ , m_rController(rController)
+{
+ m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 25, m_xTreeView->get_height_rows(18));
+
+ m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition());
+ m_pReportListener->addProperty(PROPERTY_PAGEHEADERON);
+ m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON);
+ m_pReportListener->addProperty(PROPERTY_REPORTHEADERON);
+ m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON);
+
+ m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController);
+
+ m_xTreeView->set_help_id(HID_REPORT_NAVIGATOR_TREE);
+
+ m_xTreeView->set_selection_mode(SelectionMode::Multiple);
+
+ m_xTreeView->connect_changed(LINK(this, NavigatorTree, OnEntrySelDesel));
+ m_xTreeView->connect_popup_menu(LINK(this, NavigatorTree, CommandHdl));
+}
+
+NavigatorTree::~NavigatorTree()
+{
+ m_xTreeView->all_foreach([this](weld::TreeIter& rIter) {
+ UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_id(rIter));
+ delete pData;
+ return false;
+ });
+ m_pSelectionListener->dispose();
+ m_pReportListener->dispose();
+}
+
+namespace
+{
+ sal_uInt16 mapIdent(std::u16string_view rIdent)
+ {
+ if (rIdent == u"sorting")
+ return SID_SORTINGANDGROUPING;
+ else if (rIdent == u"page")
+ return SID_PAGEHEADERFOOTER;
+ else if (rIdent == u"report")
+ return SID_REPORTHEADERFOOTER;
+ else if (rIdent == u"function")
+ return SID_RPT_NEW_FUNCTION;
+ else if (rIdent == u"properties")
+ return SID_SHOW_PROPERTYBROWSER;
+ else if (rIdent == u"delete")
+ return SID_DELETE;
+ return 0;
+ }
+}
+
+IMPL_LINK(NavigatorTree, CommandHdl, const CommandEvent&, rEvt, bool)
+{
+ bool bHandled = false;
+ switch( rEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_selected_id());
+ if (!pData)
+ break;
+
+ uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY);
+ uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY);
+ uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY);
+ bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() ||
+ uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is());
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/dbreport/ui/navigatormenu.ui"));
+ std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
+
+ const OUString aIds[] = { "sorting", "page", "report", "function", "properties", "delete" };
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
+ {
+ sal_uInt16 nSId = mapIdent(aIds[i]);
+
+ if (aIds[i] == "page" || aIds[i] == "report" || aIds[i] == "properties")
+ xContextMenu->set_active(aIds[i], m_rController.isCommandChecked(nSId));
+ bool bEnabled = m_rController.isCommandEnabled(nSId);
+ if (nSId == SID_RPT_NEW_FUNCTION)
+ xContextMenu->set_sensitive(aIds[i], m_rController.isEditable() && (xSupplier.is() || xFunctions.is()));
+ // special condition, check for function and group
+ else if (nSId == SID_DELETE)
+ xContextMenu->set_sensitive(aIds[i], bDeleteAllowed);
+ else
+ xContextMenu->set_sensitive(aIds[i], bEnabled);
+ }
+
+ // the point that was clicked on
+ ::Point aWhere(rEvt.GetMousePosPixel());
+ OUString sCurItemIdent = xContextMenu->popup_at_rect(m_xTreeView.get(), tools::Rectangle(aWhere, Size(1,1)));
+ if (!sCurItemIdent.isEmpty())
+ {
+ sal_uInt16 nId = mapIdent(sCurItemIdent);
+ uno::Sequence< beans::PropertyValue> aArgs;
+ if ( nId == SID_RPT_NEW_FUNCTION )
+ {
+ aArgs.realloc(1);
+ aArgs.getArray()[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions());
+ }
+ else if ( nId == SID_DELETE )
+ {
+ if ( xGroup.is() )
+ nId = SID_GROUP_REMOVE;
+ aArgs = { comphelper::makePropertyValue(PROPERTY_GROUP, pData->getContent()) };
+ }
+ m_rController.executeUnChecked(nId,aArgs);
+ }
+
+ bHandled = true;
+ }
+ break;
+ default: break;
+ }
+
+ return bHandled;
+}
+
+IMPL_LINK_NOARG(NavigatorTree, OnEntrySelDesel, weld::TreeView&, void)
+{
+ if ( !m_pSelectionListener->locked() )
+ {
+ m_pSelectionListener->lock();
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ bool bEntry = m_xTreeView->get_cursor(xEntry.get());
+ uno::Any aSelection;
+ if (bEntry && m_xTreeView->is_selected(*xEntry))
+ aSelection <<= weld::fromId<UserData*>(m_xTreeView->get_id(*xEntry))->getContent();
+ m_rController.select(aSelection);
+ m_pSelectionListener->unlock();
+ }
+}
+
+void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent )
+{
+ m_pSelectionListener->lock();
+ uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY);
+ uno::Any aSec = xSelectionSupplier->getSelection();
+ uno::Sequence< uno::Reference< report::XReportComponent > > aSelection;
+ aSec >>= aSelection;
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ if ( !aSelection.hasElements() )
+ {
+ uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY);
+ bool bEntry = find(xSelection, *xEntry);
+ if (bEntry && !m_xTreeView->is_selected(*xEntry))
+ {
+ m_xTreeView->select(*xEntry);
+ m_xTreeView->set_cursor(*xEntry);
+ }
+ else if (!bEntry)
+ m_xTreeView->unselect_all();
+ }
+ else
+ {
+ for (const uno::Reference<report::XReportComponent>& rElem : std::as_const(aSelection))
+ {
+ bool bEntry = find(rElem, *xEntry);
+ if (bEntry && !m_xTreeView->is_selected(*xEntry))
+ {
+ m_xTreeView->select(*xEntry);
+ m_xTreeView->set_cursor(*xEntry);
+ }
+ }
+ }
+ m_pSelectionListener->unlock();
+}
+
+void NavigatorTree::insertEntry(const OUString& rName, const weld::TreeIter* pParent, const OUString& rImageId,
+ int nPosition, const UserData* pData, weld::TreeIter& rRet)
+{
+ OUString sId = pData ? weld::toId(pData) : OUString();
+ m_xTreeView->insert(pParent, nPosition, &rName, &sId, nullptr, nullptr, false, &rRet);
+ if (!rImageId.isEmpty())
+ m_xTreeView->set_image(rRet, rImageId);
+}
+
+void NavigatorTree::traverseSection(const uno::Reference<report::XSection>& xSection, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition)
+{
+ std::unique_ptr<weld::TreeIter> xSectionIter = m_xTreeView->make_iterator();
+ std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
+ insertEntry(xSection->getName(), pParent, rImageId, nPosition, new UserData(this, xSection), *xSectionIter);
+ const sal_Int32 nCount = xSection->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference< report::XReportComponent> xElement(xSection->getByIndex(i), uno::UNO_QUERY_THROW);
+ insertEntry(lcl_getName(xElement), xSectionIter.get(), lcl_getImageId(xElement), -1, new UserData(this, xElement), *xScratch);
+ uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY);
+ if ( xSubReport.is() )
+ {
+ bool bMasterReport = find(xSection->getReportDefinition(), *xScratch);
+ if (!bMasterReport)
+ m_xMasterReport.reset();
+ else
+ m_xMasterReport = m_xTreeView->make_iterator(xScratch.get());
+ reportdesign::OReportVisitor aSubVisitor(this);
+ aSubVisitor.start(xSubReport);
+ }
+ }
+}
+
+void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& xFunctions, const weld::TreeIter* pParent)
+{
+ std::unique_ptr<weld::TreeIter> xFunctionIter = m_xTreeView->make_iterator();
+ std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
+ insertEntry(RptResId(RID_STR_FUNCTIONS), pParent, RID_SVXBMP_RPT_NEW_FUNCTION, -1, new UserData(this, xFunctions), *xFunctionIter);
+ const sal_Int32 nCount = xFunctions->getCount();
+ for (sal_Int32 i = 0; i< nCount; ++i)
+ {
+ uno::Reference< report::XFunction> xElement(xFunctions->getByIndex(i),uno::UNO_QUERY);
+ insertEntry(xElement->getName(), xFunctionIter.get(), RID_SVXBMP_RPT_NEW_FUNCTION, -1, new UserData(this,xElement), *xScratch);
+ }
+}
+
+bool NavigatorTree::find(const uno::Reference<uno::XInterface>& xContent, weld::TreeIter& rRet)
+{
+ bool bRet = false;
+ if (xContent.is())
+ {
+ m_xTreeView->all_foreach([this, &xContent, &bRet, &rRet](weld::TreeIter& rIter) {
+ UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_id(rIter));
+ if (pData->getContent() == xContent)
+ {
+ m_xTreeView->copy_iterator(rIter, rRet);
+ bRet = true;
+ return true;
+ }
+ return false;
+ });
+ }
+ return bRet;
+}
+
+// ITraverseReport
+
+void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& xReport)
+{
+ std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
+ insertEntry(xReport->getName(), m_xMasterReport.get(), RID_SVXBMP_SELECT_REPORT,-1, new UserData(this, xReport), *xScratch);
+}
+
+void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& xFunctions)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xFunctions->getParent(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ traverseFunctions(xFunctions, xReport.get());
+}
+
+void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& xSection)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xSection->getReportDefinition(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ traverseSection(xSection, xReport.get(), RID_SVXBMP_REPORTHEADERFOOTER);
+}
+
+void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& xSection)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xSection->getReportDefinition(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ traverseSection(xSection, xReport.get(), RID_SVXBMP_REPORTHEADERFOOTER);
+}
+
+void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& xSection)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xSection->getReportDefinition(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ traverseSection(xSection, xReport.get(), RID_SVXBMP_PAGEHEADERFOOTER);
+}
+
+void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& xSection)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xSection->getReportDefinition(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ traverseSection(xSection, xReport.get(), RID_SVXBMP_PAGEHEADERFOOTER);
+}
+
+void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& xGroups)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xGroups->getReportDefinition(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
+ insertEntry(RptResId(RID_STR_GROUPS), xReport.get(), RID_SVXBMP_SORTINGANDGROUPING, -1, new UserData(this, xGroups), *xScratch);
+}
+
+void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& xGroup)
+{
+ uno::Reference< report::XGroups> xGroups(xGroup->getParent(),uno::UNO_QUERY);
+ std::unique_ptr<weld::TreeIter> xGroupsIter = m_xTreeView->make_iterator();
+ bool bGroups = find(xGroups, *xGroupsIter);
+ OSL_ENSURE(bGroups, "No Groups inserted so far. Why!");
+ if (!bGroups)
+ xGroupsIter.reset();
+ std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
+ insertEntry(xGroup->getExpression(), xGroupsIter.get(), RID_SVXBMP_GROUP, rptui::getPositionInIndexAccess(xGroups,xGroup), new UserData(this,xGroup), *xScratch);
+}
+
+void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& xFunctions)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xFunctions->getParent(), *xReport);
+ if (!bReport)
+ xReport.reset();
+ traverseFunctions(xFunctions, xReport.get());
+}
+
+void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& xSection)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xSection->getGroup(), *xReport);
+ OSL_ENSURE(bReport, "No group found");
+ if (!bReport)
+ xReport.reset();
+ traverseSection(xSection, xReport.get(), RID_SVXBMP_GROUPHEADER, 1);
+}
+
+void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& xSection)
+{
+ std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator();
+ bool bReport = find(xSection->getGroup(), *xReport);
+ OSL_ENSURE(bReport, "No group found");
+ if (!bReport)
+ xReport.reset();
+ traverseSection(xSection, xReport.get(), RID_SVXBMP_GROUPFOOTER);
+}
+
+void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& xSection)
+{
+ uno::Reference< report::XReportDefinition> xReport = xSection->getReportDefinition();
+ std::unique_ptr<weld::TreeIter> xParent = m_xTreeView->make_iterator();
+ bool bParent = find(xReport, *xParent);
+ if (!bParent)
+ xParent.reset();
+ traverseSection(xSection, xParent.get(), RID_SVXBMP_ICON_DETAIL);
+}
+
+void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
+{
+ uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY);
+ if ( !xReport.is() )
+ return;
+
+ bool bEnabled = false;
+ _rEvent.NewValue >>= bEnabled;
+ if ( !bEnabled )
+ return;
+
+ std::unique_ptr<weld::TreeIter> xParent = m_xTreeView->make_iterator();
+ bool bParent = find(xReport, *xParent);
+ if (!bParent)
+ xParent.reset();
+ if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON )
+ {
+ int nPos = xReport->getReportHeaderOn() ? 2 : 1;
+ traverseSection(xReport->getReportHeader(),xParent.get(),RID_SVXBMP_REPORTHEADERFOOTER,nPos);
+ }
+ else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON )
+ {
+ traverseSection(xReport->getPageHeader(),xParent.get(), RID_SVXBMP_PAGEHEADERFOOTER,1);
+ }
+ else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON )
+ traverseSection(xReport->getPageFooter(),xParent.get(), RID_SVXBMP_PAGEHEADERFOOTER);
+ else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON )
+ {
+ int nPos = -1;
+ if (xReport->getPageFooterOn() && xParent)
+ nPos = m_xTreeView->iter_n_children(*xParent) - 1;
+ traverseSection(xReport->getReportFooter(),xParent.get(),RID_SVXBMP_REPORTHEADERFOOTER,nPos);
+ }
+}
+
+void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent )
+{
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ bool bEntry = find(_rEvent.Source, *xEntry);
+ if (!bEntry)
+ xEntry.reset();
+ uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW);
+ OUString sName;
+ uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
+ if ( xInfo.is() )
+ {
+ if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
+ else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
+ xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName;
+ }
+ uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY);
+ if ( xGroup.is() )
+ {
+ reportdesign::OReportVisitor aSubVisitor(this);
+ aSubVisitor.start(xGroup);
+ }
+ else
+ {
+ uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY);
+ if ( xProp.is() )
+ sName = lcl_getName(xProp);
+ std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator();
+ insertEntry(sName, xEntry.get(), (!xElement.is() ? RID_SVXBMP_RPT_NEW_FUNCTION : lcl_getImageId(xElement)),
+ -1, new UserData(this,xProp), *xScratch);
+ }
+ if (bEntry && !m_xTreeView->get_row_expanded(*xEntry))
+ m_xTreeView->expand_row(*xEntry);
+}
+
+void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent )
+{
+ uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY);
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ bool bEntry = find(xProp, *xEntry);
+ OSL_ENSURE(bEntry,"NavigatorTree::_elementRemoved: No Entry found!");
+
+ if (bEntry)
+ {
+ removeEntry(*xEntry);
+ }
+}
+
+void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent )
+{
+ uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY);
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ bool bEntry = find(xProp, *xEntry);
+ if (bEntry)
+ {
+ UserData* pData = weld::fromId<UserData*>(m_xTreeView->get_id(*xEntry));
+ xProp.set(_rEvent.Element,uno::UNO_QUERY);
+ pData->setContent(xProp);
+ OUString sName;
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
+ m_xTreeView->set_text(*xEntry, sName);
+ }
+}
+
+void NavigatorTree::_disposing(const lang::EventObject& _rSource)
+{
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ if (find(_rSource.Source, *xEntry))
+ removeEntry(*xEntry);
+}
+
+void NavigatorTree::removeEntry(const weld::TreeIter& rEntry, bool bRemove)
+{
+ std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator(&rEntry);
+ bool bChild = m_xTreeView->iter_children(*xChild);
+ while (bChild)
+ {
+ removeEntry(*xChild, false);
+ bChild = m_xTreeView->iter_next_sibling(*xChild);
+ }
+ delete weld::fromId<UserData*>(m_xTreeView->get_id(rEntry));
+ if (bRemove)
+ m_xTreeView->remove(rEntry);
+}
+
+NavigatorTree::UserData::UserData(NavigatorTree* pTree,uno::Reference<uno::XInterface> xContent)
+ : OPropertyChangeListener(m_aMutex)
+ , OContainerListener(m_aMutex)
+ , m_xContent(std::move(xContent))
+ , m_pTree(pTree)
+{
+ uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY);
+ if ( xProp.is() )
+ {
+ uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
+ if ( xInfo.is() )
+ {
+ m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp);
+ if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
+ m_pListener->addProperty(PROPERTY_NAME);
+ else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
+ m_pListener->addProperty(PROPERTY_EXPRESSION);
+ if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) )
+ m_pListener->addProperty(PROPERTY_DATAFIELD);
+ if ( xInfo->hasPropertyByName(PROPERTY_LABEL) )
+ m_pListener->addProperty(PROPERTY_LABEL);
+ if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) )
+ m_pListener->addProperty(PROPERTY_HEADERON);
+ if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) )
+ m_pListener->addProperty(PROPERTY_FOOTERON);
+ }
+ }
+ uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY);
+ if ( xContainer.is() )
+ {
+ m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
+ }
+}
+
+NavigatorTree::UserData::~UserData()
+{
+ if ( m_pContainerListener.is() )
+ m_pContainerListener->dispose();
+ if ( m_pListener.is() )
+ m_pListener->dispose();
+}
+
+// OPropertyChangeListener
+void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
+{
+ std::unique_ptr<weld::TreeIter> xEntry = m_pTree->make_iterator();
+ bool bEntry = m_pTree->find(_rEvent.Source, *xEntry);
+ OSL_ENSURE(bEntry,"No entry could be found! Why not!");
+ if (!bEntry)
+ return;
+ const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName);
+ try
+ {
+ if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName )
+ {
+ sal_Int32 nPos = 1;
+ uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY);
+ ::std::function<bool(OGroupHelper *)> pIsOn = ::std::mem_fn(&OGroupHelper::getHeaderOn);
+ ::std::function<uno::Reference<report::XSection>(OGroupHelper *)> pMemFunSection = ::std::mem_fn(&OGroupHelper::getHeader);
+ if ( bFooterOn )
+ {
+ pIsOn = ::std::mem_fn(&OGroupHelper::getFooterOn);
+ pMemFunSection = ::std::mem_fn(&OGroupHelper::getFooter);
+ nPos = m_pTree->iter_n_children(*xEntry) - 1;
+ }
+
+ OGroupHelper aGroupHelper(xGroup);
+ if ( pIsOn(&aGroupHelper) )
+ {
+ if ( bFooterOn )
+ ++nPos;
+ m_pTree->traverseSection(pMemFunSection(&aGroupHelper),xEntry.get(),bFooterOn ? RID_SVXBMP_GROUPFOOTER : RID_SVXBMP_GROUPHEADER,nPos);
+ }
+ }
+ else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName)
+ {
+ OUString sNewName;
+ _rEvent.NewValue >>= sNewName;
+ m_pTree->set_text(*xEntry, sNewName);
+ }
+ else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName )
+ {
+ uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY);
+ m_pTree->set_text(*xEntry, lcl_getName(xProp));
+ }
+ }
+ catch(const uno::Exception &)
+ {}
+}
+
+void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent )
+{
+ m_pTree->_elementInserted( _rEvent );
+}
+
+void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent )
+{
+ m_pTree->_elementRemoved( _rEvent );
+}
+
+void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent )
+{
+ m_pTree->_elementReplaced( _rEvent );
+}
+
+void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource)
+{
+ m_pTree->_disposing( _rSource );
+}
+
+ONavigator::ONavigator(weld::Window* pParent, OReportController& rController)
+ : GenericDialogController(pParent, "modules/dbreport/ui/floatingnavigator.ui", "FloatingNavigator")
+ , m_xReport(rController.getReportDefinition())
+ , m_xNavigatorTree(std::make_unique<NavigatorTree>(m_xBuilder->weld_tree_view("treeview"), rController))
+{
+ reportdesign::OReportVisitor aVisitor(m_xNavigatorTree.get());
+ aVisitor.start(m_xReport);
+ std::unique_ptr<weld::TreeIter> xScratch = m_xNavigatorTree->make_iterator();
+ if (m_xNavigatorTree->find(m_xReport, *xScratch))
+ m_xNavigatorTree->expand_row(*xScratch);
+ lang::EventObject aEvent(rController);
+ m_xNavigatorTree->_selectionChanged(aEvent);
+ m_xNavigatorTree->grab_focus();
+
+ m_xDialog->connect_container_focus_changed(LINK(this, ONavigator, FocusChangeHdl));
+}
+
+ONavigator::~ONavigator()
+{
+}
+
+IMPL_LINK_NOARG(ONavigator, FocusChangeHdl, weld::Container&, void)
+{
+ if (m_xDialog->has_toplevel_focus())
+ m_xNavigatorTree->grab_focus();
+}
+
+} // rptui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */