/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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() ? OUString(RID_SVXBMP_INSERT_VFIXEDLINE) : OUString(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(" : "); sName.append(xFixedText->getLabel()); } else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) { ReportFormula aFormula( xReportModel->getDataField() ); if ( aFormula.isValid() ) { sName.append(" : "); sName.append( aFormula.getUndecoratedContent() ); } } return sName.makeStringAndClear(); } namespace { 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, const uno::Reference& 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 m_xTreeView; OReportController& m_rController; std::unique_ptr 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& 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, 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& 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 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 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(m_xTreeView->get_id(rIter)); delete pData; return false; }); m_pSelectionListener->dispose(); m_pReportListener->dispose(); } namespace { sal_uInt16 mapIdent(std::string_view rIdent) { if (rIdent == "sorting") return SID_SORTINGANDGROUPING; else if (rIdent == "page") return SID_PAGEHEADERFOOTER; else if (rIdent == "report") return SID_REPORTHEADERFOOTER; else if (rIdent == "function") return SID_RPT_NEW_FUNCTION; else if (rIdent == "properties") return SID_SHOW_PROPERTYBROWSER; else if (rIdent == "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(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 xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/dbreport/ui/navigatormenu.ui")); std::unique_ptr xContextMenu(xBuilder->weld_menu("menu")); const OString 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()); OString 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 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(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 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& 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& xSection, const weld::TreeIter* pParent, const OUString& rImageId, int nPosition) { std::unique_ptr xSectionIter = m_xTreeView->make_iterator(); std::unique_ptr 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 xFunctionIter = m_xTreeView->make_iterator(); std::unique_ptr 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& 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(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 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 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 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 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 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 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 xReport = m_xTreeView->make_iterator(); bool bReport = find(xGroups->getReportDefinition(), *xReport); if (!bReport) xReport.reset(); std::unique_ptr 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 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 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 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 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 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 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 xParent = m_xTreeView->make_iterator(); bool bParent = find(xReport, *xParent); if (!bParent) xParent.reset(); if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON ) { sal_uLong 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 xEntry = m_xTreeView->make_iterator(); bool bEntry = find(_rEvent.Source, *xEntry); if (!bEntry) xEntry.reset(); uno::Reference 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 xScratch = m_xTreeView->make_iterator(); insertEntry(sName, xEntry.get(), (!xElement.is() ? OUString(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 xProp(_rEvent.Element,uno::UNO_QUERY); std::unique_ptr 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 xProp(_rEvent.ReplacedElement,uno::UNO_QUERY); std::unique_ptr xEntry = m_xTreeView->make_iterator(); bool bEntry = find(xProp, *xEntry); if (bEntry) { UserData* pData = weld::fromId(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 xEntry = m_xTreeView->make_iterator(); if (find(_rSource.Source, *xEntry)) removeEntry(*xEntry); } void NavigatorTree::removeEntry(const weld::TreeIter& rEntry, bool bRemove) { std::unique_ptr 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(m_xTreeView->get_id(rEntry)); if (bRemove) m_xTreeView->remove(rEntry); } NavigatorTree::UserData::UserData(NavigatorTree* pTree,const uno::Reference& xContent) : OPropertyChangeListener(m_aMutex) , OContainerListener(m_aMutex) , m_xContent(xContent) , m_pTree(pTree) { uno::Reference 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 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 pIsOn = ::std::mem_fn(&OGroupHelper::getHeaderOn); ::std::function(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 ? OUString(RID_SVXBMP_GROUPFOOTER) : OUString(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 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 ); } class ONavigatorImpl { public: ONavigatorImpl(OReportController& rController, weld::Builder& rBuilder); ONavigatorImpl(const ONavigatorImpl&) = delete; ONavigatorImpl& operator=(const ONavigatorImpl&) = delete; uno::Reference< report::XReportDefinition> m_xReport; std::unique_ptr m_xNavigatorTree; }; ONavigatorImpl::ONavigatorImpl(OReportController& rController, weld::Builder& rBuilder) : m_xReport(rController.getReportDefinition()) , m_xNavigatorTree(std::make_unique(rBuilder.weld_tree_view("treeview"), rController)) { reportdesign::OReportVisitor aVisitor(m_xNavigatorTree.get()); aVisitor.start(m_xReport); std::unique_ptr 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); } ONavigator::ONavigator(weld::Window* pParent, OReportController& rController) : GenericDialogController(pParent, "modules/dbreport/ui/floatingnavigator.ui", "FloatingNavigator") { m_pImpl.reset(new ONavigatorImpl(rController, *m_xBuilder)); m_pImpl->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_pImpl->m_xNavigatorTree->grab_focus(); } } // rptui /* vim:set shiftwidth=4 softtabstop=4 expandtab: */