813 lines
33 KiB
C++
813 lines
33 KiB
C++
/* -*- 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 ::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_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(), u"modules/dbreport/ui/navigatormenu.ui"_ustr));
|
|
std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu(u"menu"_ustr));
|
|
|
|
const OUString aIds[] = { u"sorting"_ustr, u"page"_ustr, u"report"_ustr, u"function"_ustr, u"properties"_ustr, u"delete"_ustr };
|
|
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 : 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()
|
|
, 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, u"modules/dbreport/ui/floatingnavigator.ui"_ustr, u"FloatingNavigator"_ustr)
|
|
, m_xReport(rController.getReportDefinition())
|
|
, m_xNavigatorTree(std::make_unique<NavigatorTree>(m_xBuilder->weld_tree_view(u"treeview"_ustr), 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: */
|