/* -*- 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 <sal/config.h>
#include <memory>
#include <sal/log.hxx>
#include <datanavi.hxx>
#include <fmservs.hxx>
#include <bitmaps.hlst>
#include <fpicker/strings.hrc>
#include <o3tl/safeint.hxx>
#include <o3tl/string_view.hxx>
#include <svx/svxids.hrc>
#include <comphelper/diagnose_ex.hxx>
#include <unotools/resmgr.hxx>
#include <svx/xmlexchg.hxx>
#include <unotools/viewoptions.hxx>
#include <sfx2/filedlghelper.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <utility>
#include <vcl/commandevent.hxx>
#include <vcl/event.hxx>
#include <vcl/weld.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/container/XSet.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/xforms/XFormsSupplier.hpp>
#include <com/sun/star/xml/dom/XDocument.hpp>
#include <comphelper/string.hxx>
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::datatransfer;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::dom::events;
using namespace ::svx;
constexpr OUString CFGNAME_DATANAVIGATOR = u
"DataNavigator" _ustr;
constexpr OUString CFGNAME_SHOWDETAILS = u
"ShowDetails" _ustr;
constexpr OUString MSG_VARIABLE = u
"%1" _ustr;
constexpr OUStringLiteral MODELNAME = u
"$MODELNAME" ;
constexpr OUStringLiteral INSTANCENAME = u
"$INSTANCENAME" ;
constexpr OUStringLiteral ELEMENTNAME = u
"$ELEMENTNAME" ;
constexpr OUStringLiteral ATTRIBUTENAME = u
"$ATTRIBUTENAME" ;
constexpr OUStringLiteral SUBMISSIONNAME = u
"$SUBMISSIONNAME" ;
constexpr OUStringLiteral BINDINGNAME = u
"$BINDINGNAME" ;
namespace svxform
{
// properties of instance
constexpr OUStringLiteral PN_INSTANCE_MODEL = u
"Instance" ;
constexpr OUString PN_INSTANCE_ID = u
"ID" _ustr;
constexpr OUStringLiteral PN_INSTANCE_URL = u
"URL" ;
// properties of binding
constexpr OUString PN_BINDING_ID = u
"BindingID" _ustr;
constexpr OUString PN_BINDING_EXPR = u
"BindingExpression" _ustr;
constexpr OUStringLiteral PN_BINDING_MODEL = u
"Model" ;
constexpr OUString PN_BINDING_NAMESPACES = u
"ModelNamespaces" _ustr;
constexpr OUString PN_READONLY_EXPR = u
"ReadonlyExpression" _ustr;
constexpr OUString PN_RELEVANT_EXPR = u
"RelevantExpression" _ustr;
constexpr OUString PN_REQUIRED_EXPR = u
"RequiredExpression" _ustr;
constexpr OUString PN_CONSTRAINT_EXPR = u
"ConstraintExpression" _ustr;
constexpr OUString PN_CALCULATE_EXPR = u
"CalculateExpression" _ustr;
constexpr OUString PN_BINDING_TYPE = u
"Type" _ustr;
// properties of submission
constexpr OUString PN_SUBMISSION_ID = u
"ID" _ustr;
constexpr OUString PN_SUBMISSION_BIND = u
"Bind" _ustr;
constexpr OUString PN_SUBMISSION_REF = u
"Ref" _ustr;
constexpr OUString PN_SUBMISSION_ACTION = u
"Action" _ustr;
constexpr OUString PN_SUBMISSION_METHOD = u
"Method" _ustr;
constexpr OUString PN_SUBMISSION_REPLACE = u
"Replace" _ustr;
// other const strings
constexpr OUString TRUE_VALUE = u
"true()" _ustr;
constexpr OUStringLiteral NEW_ELEMENT = u
"newElement" ;
constexpr OUStringLiteral NEW_ATTRIBUTE = u
"newAttribute" ;
constexpr OUString EVENTTYPE_CHARDATA = u
"DOMCharacterDataModified" _ustr;
constexpr OUString EVENTTYPE_ATTR = u
"DOMAttrModified" _ustr;
#define MIN_PAGE_COUNT 3
// at least one instance, one submission and one binding page
struct ItemNode
{
Reference< css::xml::dom::XNode > m_xNode;
Reference< XPropertySet > m_xPropSet;
explicit ItemNode(
const Reference< css::xml::dom::XNode >& _rxNode ) :
m_xNode( _rxNode ) {}
explicit ItemNode(
const Reference< XPropertySet >& _rxSet ) :
m_xPropSet( _rxSet ) {}
};
DataTreeDropTarget::DataTreeDropTarget(weld::TreeView& rWidget)
: DropTargetHelper(rWidget.get_drop_target())
{
}
sal_Int8 DataTreeDropTarget::AcceptDrop(
const AcceptDropEvent&
/*rEvt*/ )
{
return DND_ACTION_NONE;
}
sal_Int8 DataTreeDropTarget::ExecuteDrop(
const ExecuteDropEvent&
/*rEvt*/ )
{
return DND_ACTION_NONE;
}
IMPL_LINK(XFormsPage, PopupMenuHdl,
const CommandEvent&, rCEvt,
bool )
{
if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
return false ;
Point aPos(rCEvt.GetMousePosPixel());
if (m_xItemList->get_dest_row_at_pos(aPos, m_xScratchIter.get(),
false ) && !m_xItemList->
is_selected(*m_xScratchIter))
{
m_xItemList->select(*m_xScratchIter);
ItemSelectHdl(*m_xItemList);
}
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xItemList.get(), u"svx/ui/formdatamenu.ui" _ustr));
m_xMenu = xBuilder->weld_menu(u"menu" _ustr);
m_aRemovedMenuEntries.clear();
if (DGTInstance == m_eGroup)
m_aRemovedMenuEntries.insert(u"additem" _ustr);
else
{
m_aRemovedMenuEntries.insert(u"addelement" _ustr);
m_aRemovedMenuEntries.insert(u"addattribute" _ustr);
if (DGTSubmission == m_eGroup)
{
m_xMenu->set_label(u"additem" _ustr, SvxResId(RID_STR_DATANAV_ADD_SUBMISSION));
m_xMenu->set_label(u"edit" _ustr, SvxResId(RID_STR_DATANAV_EDIT_SUBMISSION));
m_xMenu->set_label(u"delete" _ustr, SvxResId(RID_STR_DATANAV_REMOVE_SUBMISSION));
}
else
{
m_xMenu->set_label(u"additem" _ustr, SvxResId(RID_STR_DATANAV_ADD_BINDING));
m_xMenu->set_label(u"edit" _ustr, SvxResId(RID_STR_DATANAV_EDIT_BINDING));
m_xMenu->set_label(u"delete" _ustr, SvxResId(RID_STR_DATANAV_REMOVE_BINDING));
}
}
for (const auto & rRemove : m_aRemovedMenuEntries)
m_xMenu->remove(rRemove);
EnableMenuItems();
OUString sCommand = m_xMenu->popup_at_rect(m_xItemList.get(), tools::Rectangle(aPos, Size(1,1)));
if (!sCommand.isEmpty())
DoMenuAction(sCommand);
m_xMenu.reset();
return true ;
}
void XFormsPage::DeleteAndClearTree()
{
m_xItemList->all_foreach([this ](weld::TreeIter& rEntry) {
delete weld::fromId<ItemNode*>(m_xItemList->get_id(rEntry));
return false ;
});
m_xItemList->clear();
}
void XFormsPage::SelectFirstEntry()
{
if (m_xItemList->get_iter_first(*m_xScratchIter))
{
m_xItemList->select(*m_xScratchIter);
ItemSelectHdl(*m_xItemList);
}
}
XFormsPage::XFormsPage(weld::Container* pPage, DataNavigatorWindow* _pNaviWin, DataGroupType _eGroup)
: BuilderPage(pPage, nullptr, u"svx/ui/xformspage.ui" _ustr, u"XFormsPage" _ustr)
, m_pParent(pPage)
, m_xToolBox(m_xBuilder->weld_toolbar(u"toolbar" _ustr))
, m_xItemList(m_xBuilder->weld_tree_view(u"items" _ustr))
, m_xScratchIter(m_xItemList->make_iterator())
, m_aDropHelper(*m_xItemList)
, m_pNaviWin(_pNaviWin)
, m_bHasModel(false )
, m_eGroup(_eGroup)
, m_bLinkOnce(false )
{
m_xItemList->set_show_expanders(DGTInstance == m_eGroup || DGTSubmission == m_eGroup);
if ( DGTInstance == m_eGroup )
m_xToolBox->set_item_visible(u"additem" _ustr, false );
else
{
m_xToolBox->set_item_visible(u"addelement" _ustr, false );
m_xToolBox->set_item_visible(u"addattribute" _ustr, false );
if ( DGTSubmission == m_eGroup )
{
m_xToolBox->set_item_label(u"additem" _ustr, SvxResId(RID_STR_DATANAV_ADD_SUBMISSION));
m_xToolBox->set_item_label(u"edit" _ustr, SvxResId(RID_STR_DATANAV_EDIT_SUBMISSION));
m_xToolBox->set_item_label(u"delete" _ustr, SvxResId(RID_STR_DATANAV_REMOVE_SUBMISSION));
}
else
{
m_xToolBox->set_item_label(u"additem" _ustr, SvxResId(RID_STR_DATANAV_ADD_BINDING));
m_xToolBox->set_item_label(u"edit" _ustr, SvxResId(RID_STR_DATANAV_EDIT_BINDING));
m_xToolBox->set_item_label(u"delete" _ustr, SvxResId(RID_STR_DATANAV_REMOVE_BINDING));
}
}
m_xToolBox->connect_clicked(LINK(this , XFormsPage, TbxSelectHdl));
m_xItemList->connect_selection_changed(LINK(this , XFormsPage, ItemSelectHdl));
m_xItemList->connect_key_press(LINK(this , XFormsPage, KeyInputHdl));
m_xItemList->connect_popup_menu(LINK(this , XFormsPage, PopupMenuHdl));
ItemSelectHdl(*m_xItemList);
}
XFormsPage::~XFormsPage()
{
DeleteAndClearTree();
m_pNaviWin = nullptr;
m_pParent->move(m_xContainer.get(), nullptr);
}
IMPL_LINK(XFormsPage, TbxSelectHdl, const OUString&, rIdent, void )
{
DoToolBoxAction(rIdent);
}
IMPL_LINK_NOARG(XFormsPage, ItemSelectHdl, weld::TreeView&, void )
{
EnableMenuItems();
PrepDnD();
}
void XFormsPage::PrepDnD()
{
rtl::Reference<TransferDataContainer> xTransferable(new TransferDataContainer);
m_xItemList->enable_drag_source(xTransferable, DND_ACTION_NONE);
if (!m_xItemList->get_selected(m_xScratchIter.get()))
{
// no drag without an entry
return ;
}
if ( m_eGroup == DGTBinding )
{
// for the moment, bindings cannot be dragged.
// #i59395# / 2005-12-15 / frank.schoenheit@sun.com
return ;
}
// GetServiceNameForNode() requires a datatype repository which
// will be automatically build if requested???
Reference< css::xforms::XModel > xModel( GetXFormsHelper(), UNO_QUERY );
Reference< css::xforms::XDataTypeRepository > xDataTypes =
xModel->getDataTypeRepository();
if (!xDataTypes.is())
return ;
ItemNode *pItemNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*m_xScratchIter));
if (!pItemNode)
{
// the only known (and allowed?) case where this happens are sub-entries of a submission
// entry
DBG_ASSERT( DGTSubmission == m_eGroup, "DataTreeListBox::StartDrag: how this?" );
bool bSelected = m_xItemList->iter_parent(*m_xScratchIter);
DBG_ASSERT(bSelected && !m_xItemList->get_iter_depth(*m_xScratchIter), "DataTreeListBox::StartDrag: what kind of entry *is* this?" );
// on the submission page, we have only top-level entries (the submission themself)
// plus direct children of those (facets of a submission)
pItemNode = bSelected ? weld::fromId<ItemNode*>(m_xItemList->get_id(*m_xScratchIter)) : nullptr;
if (!pItemNode)
return ;
}
OUString szName = m_xItemList->get_text(*m_xScratchIter);
Reference<css::xml::dom::XNode> xNode(pItemNode->m_xNode);
Reference<XPropertySet> xPropSet(pItemNode->m_xPropSet);
// tdf#154535 create the OXFormsDescriptor on-demand so we don't cause an unwanted
// Binding to be created unless we are forced to.
auto fnCreateFormsDescriptor = [this , szName=std::move(szName), xNode=std::move(xNode), xPropSet=std::move(xPropSet)](){
OXFormsDescriptor desc;
desc.szName = szName;
if (xNode) {
// a valid node interface tells us that we need to create a control from a binding
desc.szServiceName = GetServiceNameForNode(xNode);
desc.xPropSet = GetBindingForNode(xNode);
DBG_ASSERT( desc.xPropSet.is(), "DataTreeListBox::StartDrag(): invalid node binding" );
}
else {
desc.szServiceName = FM_COMPONENT_COMMANDBUTTON;
desc.xPropSet = xPropSet;
}
return desc;
};
xTransferable = rtl::Reference<TransferDataContainer>(new OXFormsTransferable(fnCreateFormsDescriptor));
m_xItemList->enable_drag_source(xTransferable, DND_ACTION_COPY);
}
void XFormsPage::AddChildren(const weld::TreeIter* _pParent,
const Reference< css::xml::dom::XNode >& _xNode)
{
DBG_ASSERT( m_xUIHelper.is(), "XFormsPage::AddChildren(): invalid UIHelper" );
try
{
Reference< css::xml::dom::XNodeList > xNodeList = _xNode->getChildNodes();
if ( xNodeList.is() )
{
bool bShowDetails = m_pNaviWin->IsShowDetails();
sal_Int32 i, nNodeCount = xNodeList->getLength();
for ( i = 0; i < nNodeCount; ++i )
{
Reference< css::xml::dom::XNode > xChild = xNodeList->item(i);
css::xml::dom::NodeType eChildType = xChild->getNodeType();
OUString aExpImg;
switch ( eChildType )
{
case css::xml::dom::NodeType_ATTRIBUTE_NODE:
aExpImg = RID_SVXBMP_ATTRIBUTE;
break ;
case css::xml::dom::NodeType_ELEMENT_NODE:
aExpImg = RID_SVXBMP_ELEMENT;
break ;
case css::xml::dom::NodeType_TEXT_NODE:
aExpImg = RID_SVXBMP_TEXT;
break ;
default :
aExpImg = RID_SVXBMP_OTHER;
}
OUString sName = m_xUIHelper->getNodeDisplayName( xChild, bShowDetails );
if ( !sName.isEmpty() )
{
ItemNode* pNode = new ItemNode( xChild );
OUString sId(weld::toId(pNode));
std::unique_ptr<weld::TreeIter> xEntry = m_xItemList->make_iterator();
m_xItemList->insert(_pParent, -1, &sName, &sId, nullptr, nullptr, false , xEntry.get());
m_xItemList->set_image(*xEntry, aExpImg);
if ( xChild->hasAttributes() )
{
Reference< css::xml::dom::XNamedNodeMap > xMap = xChild->getAttributes();
if ( xMap.is() )
{
aExpImg = RID_SVXBMP_ATTRIBUTE;
sal_Int32 j, nMapLen = xMap->getLength();
for ( j = 0; j < nMapLen; ++j )
{
Reference< css::xml::dom::XNode > xAttr = xMap->item(j);
pNode = new ItemNode( xAttr );
OUString sSubId(weld::toId(pNode));
OUString sAttrName = m_xUIHelper->getNodeDisplayName( xAttr, bShowDetails );
m_xItemList->insert(xEntry.get(), -1, &sAttrName, &sSubId, nullptr, nullptr, false , m_xScratchIter.get());
m_xItemList->set_image(*m_xScratchIter, aExpImg);
}
}
}
if ( xChild->hasChildNodes() )
AddChildren(xEntry.get(), xChild);
}
}
}
}
catch ( Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx" );
}
}
bool XFormsPage::DoToolBoxAction(std::u16string_view rToolBoxID)
{
bool bHandled = false ;
bool bIsDocModified = false ;
m_pNaviWin->DisableNotify( true );
if (rToolBoxID == u"additem" || rToolBoxID == u"addelement" || rToolBoxID == u"addattribute" )
{
bHandled = true ;
Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
DBG_ASSERT( xModel.is(), "XFormsPage::DoToolBoxAction(): Action without model" );
if ( DGTSubmission == m_eGroup )
{
AddSubmissionDialog aDlg(m_pNaviWin->GetFrameWeld(), nullptr, m_xUIHelper);
if ( aDlg.run() == RET_OK && aDlg.GetNewSubmission().is() )
{
try
{
const Reference< css::xforms::XSubmission >& xNewSubmission = aDlg.GetNewSubmission();
Reference< XSet > xSubmissions = xModel->getSubmissions();
xSubmissions->insert( Any( xNewSubmission ) );
AddEntry(xNewSubmission, m_xScratchIter.get());
m_xItemList->select(*m_xScratchIter);
bIsDocModified = true ;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolBoxAction()" );
}
}
}
else
{
DataItemType eType = DITElement;
std::unique_ptr<weld::TreeIter> xEntry(m_xItemList->make_iterator());
bool bEntry = m_xItemList->get_selected(xEntry.get());
std::unique_ptr<ItemNode> pNode;
Reference< css::xml::dom::XNode > xParentNode;
Reference< XPropertySet > xNewBinding;
TranslateId pResId;
bool bIsElement = true ;
if ( DGTInstance == m_eGroup )
{
if ( !m_sInstanceURL.isEmpty() )
{
LinkedInstanceWarningBox aMsgBox(m_pNaviWin->GetFrameWeld());
if (aMsgBox.run() != RET_OK)
return bHandled;
}
DBG_ASSERT( bEntry, "XFormsPage::DoToolBoxAction(): no entry" );
ItemNode* pParentNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*xEntry));
assert(pParentNode && "XFormsPage::DoToolBoxAction(): no parent node" );
xParentNode = pParentNode->m_xNode;
Reference< css::xml::dom::XNode > xNewNode;
if (rToolBoxID == u"addelement" )
{
try
{
pResId = RID_STR_DATANAV_ADD_ELEMENT;
xNewNode = m_xUIHelper->createElement( xParentNode, NEW_ELEMENT );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolBoxAction(): exception while create element" );
}
}
else
{
pResId = RID_STR_DATANAV_ADD_ATTRIBUTE;
bIsElement = false ;
eType = DITAttribute;
try
{
xNewNode = m_xUIHelper->createAttribute( xParentNode, NEW_ATTRIBUTE );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolBoxAction(): exception while create attribute" );
}
}
try
{
xNewNode = xParentNode->appendChild( xNewNode );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolBoxAction(): exception while append child" );
}
try
{
Reference< css::xml::dom::XNode > xPNode;
if ( xNewNode.is() )
xPNode = xNewNode->getParentNode();
// attributes don't have parents in the DOM model
DBG_ASSERT( rToolBoxID == u"addattribute"
|| xPNode.is(), "XFormsPage::DoToolboxAction(): node not added" );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolboxAction()" );
}
try
{
m_xUIHelper->getBindingForNode( xNewNode, true );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolBoxAction(): exception while get binding for node" );
}
pNode.reset(new ItemNode( xNewNode ));
}
else
{
try
{
pResId = RID_STR_DATANAV_ADD_BINDING;
xNewBinding = xModel->createBinding();
Reference< XSet > xBindings = xModel->getBindings();
xBindings->insert( Any( xNewBinding ) );
pNode.reset(new ItemNode( xNewBinding ));
eType = DITBinding;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolBoxAction(): exception while adding binding" );
}
}
AddDataItemDialog aDlg(m_pNaviWin->GetFrameWeld(), pNode.get(), m_xUIHelper);
aDlg.set_title(SvxResId(pResId));
aDlg.InitText( eType );
short nReturn = aDlg.run();
if ( DGTInstance == m_eGroup )
{
if ( RET_OK == nReturn )
{
AddEntry( std::move(pNode), bIsElement, m_xScratchIter.get());
m_xItemList->scroll_to_row(*m_xScratchIter);
m_xItemList->select(*m_xScratchIter);
bIsDocModified = true ;
}
else
{
try
{
Reference< css::xml::dom::XNode > xPNode;
Reference< css::xml::dom::XNode > xNode =
xParentNode->removeChild( pNode->m_xNode );
if ( xNode.is() )
xPNode = xNode->getParentNode();
DBG_ASSERT( !xPNode.is(), "XFormsPage::RemoveEntry(): node not removed" );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolboxAction()" );
}
}
}
else
{
if ( RET_OK == nReturn )
{
AddEntry(xNewBinding, m_xScratchIter.get());
m_xItemList->select(*m_xScratchIter);
bIsDocModified = true ;
}
else
{
try
{
Reference< XSet > xBindings = xModel->getBindings();
xBindings->remove( Any( xNewBinding ) );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolboxAction()" );
}
}
}
}
}
else if (rToolBoxID == u"edit" )
{
bHandled = true ;
std::unique_ptr<weld::TreeIter> xEntry(m_xItemList->make_iterator());
bool bEntry = m_xItemList->get_selected(xEntry.get());
if ( bEntry )
{
if ( DGTSubmission == m_eGroup && m_xItemList->get_iter_depth(*xEntry) )
{
m_xItemList->iter_parent(*xEntry);
}
ItemNode* pNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*xEntry));
if ( DGTInstance == m_eGroup || DGTBinding == m_eGroup )
{
if ( DGTInstance == m_eGroup && !m_sInstanceURL.isEmpty() )
{
LinkedInstanceWarningBox aMsgBox(m_pNaviWin->GetFrameWeld());
if (aMsgBox.run() != RET_OK)
return bHandled;
}
AddDataItemDialog aDlg(m_pNaviWin->GetFrameWeld(), pNode, m_xUIHelper);
DataItemType eType = DITElement;
TranslateId pResId = RID_STR_DATANAV_EDIT_ELEMENT;
if ( pNode && pNode->m_xNode.is() )
{
try
{
css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
if ( eChildType == css::xml::dom::NodeType_ATTRIBUTE_NODE )
{
pResId = RID_STR_DATANAV_EDIT_ATTRIBUTE;
eType = DITAttribute;
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolboxAction()" );
}
}
else if ( DGTBinding == m_eGroup )
{
pResId = RID_STR_DATANAV_EDIT_BINDING;
eType = DITBinding;
}
aDlg.set_title(SvxResId(pResId));
aDlg.InitText( eType );
if (aDlg.run() == RET_OK)
{
// Set the new name
OUString sNewName;
if (pNode)
{
if ( DGTInstance == m_eGroup )
{
try
{
sNewName = m_xUIHelper->getNodeDisplayName(
pNode->m_xNode, m_pNaviWin->IsShowDetails() );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolboxAction()" );
}
}
else
{
try
{
OUString sTemp;
pNode->m_xPropSet->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
sNewName += sTemp + ": " ;
pNode->m_xPropSet->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
sNewName += sTemp;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::DoToolboxAction()" );
}
}
}
m_xItemList->set_text(*xEntry, sNewName);
bIsDocModified = true ;
}
}
else
{
AddSubmissionDialog aDlg(m_pNaviWin->GetFrameWeld(), pNode, m_xUIHelper);
aDlg.set_title(SvxResId(RID_STR_DATANAV_EDIT_SUBMISSION));
if (aDlg.run() == RET_OK)
{
EditEntry( pNode->m_xPropSet );
bIsDocModified = true ;
}
}
}
}
else if (rToolBoxID == u"delete" )
{
bHandled = true ;
if ( DGTInstance == m_eGroup && !m_sInstanceURL.isEmpty() )
{
LinkedInstanceWarningBox aMsgBox(m_pNaviWin->GetFrameWeld());
if (aMsgBox.run() != RET_OK)
return bHandled;
}
bIsDocModified = RemoveEntry();
}
else
{
OSL_FAIL( "XFormsPage::DoToolboxAction: unknown ID!" );
}
m_pNaviWin->DisableNotify( false );
EnableMenuItems();
if ( bIsDocModified )
svxform::DataNavigatorWindow::SetDocModified();
return bHandled;
}
void XFormsPage::AddEntry(std::unique_ptr<ItemNode> _pNewNode, bool _bIsElement, weld::TreeIter* pRet)
{
if (!pRet)
pRet = m_xScratchIter.get();
std::unique_ptr<weld::TreeIter> xParent(m_xItemList->make_iterator());
if (!m_xItemList->get_selected(xParent.get()))
xParent.reset();
OUString aImage(_bIsElement ? RID_SVXBMP_ELEMENT : RID_SVXBMP_ATTRIBUTE);
OUString sName;
try
{
sName = m_xUIHelper->getNodeDisplayName(
_pNewNode->m_xNode, m_pNaviWin->IsShowDetails() );
}
catch ( Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx" );
}
OUString sId(weld::toId(_pNewNode.release()));
m_xItemList->insert(xParent.get(), -1, &sName, &sId, nullptr, nullptr, false , pRet);
m_xItemList->set_image(*pRet, aImage);
if (xParent && !m_xItemList->get_row_expanded(*xParent) && m_xItemList->iter_has_child(*xParent))
m_xItemList->expand_row(*xParent);
}
void XFormsPage::AddEntry(const Reference< XPropertySet >& _rEntry, weld::TreeIter* pRet)
{
if (!pRet)
pRet = m_xScratchIter.get();
OUString aImage(RID_SVXBMP_ELEMENT);
ItemNode* pNode = new ItemNode( _rEntry );
OUString sTemp;
if ( DGTSubmission == m_eGroup )
{
try
{
// ID
_rEntry->getPropertyValue( PN_SUBMISSION_ID ) >>= sTemp;
OUString sId(weld::toId(pNode));
m_xItemList->insert(nullptr, -1, &sTemp, &sId, nullptr, nullptr, false , pRet);
m_xItemList->set_image(*pRet, aImage);
std::unique_ptr<weld::TreeIter> xRes(m_xItemList->make_iterator());
// Action
_rEntry->getPropertyValue( PN_SUBMISSION_ACTION ) >>= sTemp;
OUString sEntry = SvxResId( RID_STR_DATANAV_SUBM_ACTION ) + sTemp;
m_xItemList->insert(pRet, -1, &sEntry, nullptr, nullptr, nullptr, false , xRes.get());
m_xItemList->set_image(*xRes, aImage);
// Method
_rEntry->getPropertyValue( PN_SUBMISSION_METHOD ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_METHOD ) +
m_aMethodString.toUI( sTemp );
m_xItemList->insert(pRet, -1, &sEntry, nullptr, nullptr, nullptr, false , xRes.get());
m_xItemList->set_image(*xRes, aImage);
// Ref
_rEntry->getPropertyValue( PN_SUBMISSION_REF ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_REF ) + sTemp;
m_xItemList->insert(pRet, -1, &sEntry, nullptr, nullptr, nullptr, false , xRes.get());
m_xItemList->set_image(*xRes, aImage);
// Bind
_rEntry->getPropertyValue( PN_SUBMISSION_BIND ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_BIND ) + sTemp;
m_xItemList->insert(pRet, -1, &sEntry, nullptr, nullptr, nullptr, false , xRes.get());
m_xItemList->set_image(*xRes, aImage);
// Replace
_rEntry->getPropertyValue( PN_SUBMISSION_REPLACE ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_REPLACE ) +
m_aReplaceString.toUI( sTemp );
m_xItemList->insert(pRet, -1, &sEntry, nullptr, nullptr, nullptr, false , xRes.get());
m_xItemList->set_image(*xRes, aImage);
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::AddEntry(Ref)" );
}
}
else // then Binding Page
{
try
{
OUString sName;
_rEntry->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
sName += sTemp + ": " ;
_rEntry->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
sName += sTemp;
OUString sId(weld::toId(pNode));
m_xItemList->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, false , pRet);
m_xItemList->set_image(*pRet, aImage);
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::AddEntry(Ref)" );
}
}
}
void XFormsPage::EditEntry( const Reference< XPropertySet >& _rEntry )
{
if ( DGTSubmission != m_eGroup )
return ;
try
{
std::unique_ptr<weld::TreeIter> xEntry(m_xItemList->make_iterator());
if (!m_xItemList->get_selected(xEntry.get()))
{
SAL_WARN( "svx.form" , "corrupt tree" );
return ;
}
// #i36262# may be called for submission entry *or* for
// submission children. If we don't have any children, we
// assume the latter case and use the parent
if (!m_xItemList->iter_has_child(*xEntry))
m_xItemList->iter_parent(*xEntry);
OUString sTemp;
_rEntry->getPropertyValue( PN_SUBMISSION_ID ) >>= sTemp;
m_xItemList->set_text(*xEntry, sTemp);
_rEntry->getPropertyValue( PN_SUBMISSION_BIND ) >>= sTemp;
OUString sEntry = SvxResId( RID_STR_DATANAV_SUBM_BIND ) + sTemp;
if (!m_xItemList->iter_children(*xEntry))
{
SAL_WARN( "svx.form" , "corrupt tree" );
return ;
}
m_xItemList->set_text(*xEntry, sEntry);
_rEntry->getPropertyValue( PN_SUBMISSION_REF ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_REF ) + sTemp;
if (!m_xItemList->iter_next_sibling(*xEntry))
{
SAL_WARN( "svx.form" , "corrupt tree" );
return ;
}
m_xItemList->set_text(*xEntry, sEntry);
_rEntry->getPropertyValue( PN_SUBMISSION_ACTION ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_ACTION ) + sTemp;
if (!m_xItemList->iter_next_sibling(*xEntry))
{
SAL_WARN( "svx.form" , "corrupt tree" );
return ;
}
_rEntry->getPropertyValue( PN_SUBMISSION_METHOD ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_METHOD ) +
m_aMethodString.toUI( sTemp );
if (!m_xItemList->iter_next_sibling(*xEntry))
{
SAL_WARN( "svx.form" , "corrupt tree" );
return ;
}
m_xItemList->set_text(*xEntry, sEntry);
_rEntry->getPropertyValue( PN_SUBMISSION_REPLACE ) >>= sTemp;
sEntry = SvxResId( RID_STR_DATANAV_SUBM_REPLACE ) +
m_aReplaceString.toUI( sTemp );
if (!m_xItemList->iter_next_sibling(*xEntry))
{
SAL_WARN( "svx.form" , "corrupt tree" );
return ;
}
m_xItemList->set_text(*xEntry, sEntry);
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::EditEntry()" );
}
}
bool XFormsPage::RemoveEntry()
{
bool bRet = false ;
std::unique_ptr<weld::TreeIter> xEntry(m_xItemList->make_iterator());
bool bEntry = m_xItemList->get_selected(xEntry.get());
if ( bEntry &&
( DGTInstance != m_eGroup || m_xItemList->get_iter_depth(*xEntry) ) )
{
Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
DBG_ASSERT( xModel.is(), "XFormsPage::RemoveEntry(): no model" );
ItemNode* pNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*xEntry));
assert(pNode && "XFormsPage::RemoveEntry(): no node" );
if ( DGTInstance == m_eGroup )
{
try
{
DBG_ASSERT( pNode->m_xNode.is(), "XFormsPage::RemoveEntry(): no XNode" );
css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
bool bIsElement = ( eChildType == css::xml::dom::NodeType_ELEMENT_NODE );
TranslateId pResId = bIsElement ? RID_STR_QRY_REMOVE_ELEMENT : RID_STR_QRY_REMOVE_ATTRIBUTE;
OUString sVar = bIsElement ? OUString(ELEMENTNAME) : OUString(ATTRIBUTENAME);
std::unique_ptr<weld::MessageDialog> xQBox(Application::CreateMessageDialog(m_pNaviWin->GetFrameWeld(),
VclMessageType::Question, VclButtonsType::YesNo,
SvxResId(pResId)));
OUString sMessText = xQBox->get_primary_text();
sMessText = sMessText.replaceFirst(
sVar, m_xUIHelper->getNodeDisplayName( pNode->m_xNode, false ) );
xQBox->set_primary_text(sMessText);
if (xQBox->run() == RET_YES)
{
std::unique_ptr<weld::TreeIter> xParent(m_xItemList->make_iterator(xEntry.get()));
bool bParent = m_xItemList->iter_parent(*xParent); (void )bParent;
assert(bParent && "XFormsPage::RemoveEntry(): no parent entry" );
ItemNode* pParentNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*xParent));
assert(pParentNode && pParentNode->m_xNode.is() && "XFormsPage::RemoveEntry(): no parent XNode" );
Reference< css::xml::dom::XNode > xPNode;
Reference< css::xml::dom::XNode > xNode =
pParentNode->m_xNode->removeChild( pNode->m_xNode );
if ( xNode.is() )
xPNode = xNode->getParentNode();
DBG_ASSERT( !xPNode.is(), "XFormsPage::RemoveEntry(): node not removed" );
bRet = true ;
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::RemoveEntry()" );
}
}
else
{
DBG_ASSERT( pNode->m_xPropSet.is(), "XFormsPage::RemoveEntry(): no propset" );
bool bSubmission = ( DGTSubmission == m_eGroup );
TranslateId pResId = bSubmission ? RID_STR_QRY_REMOVE_SUBMISSION : RID_STR_QRY_REMOVE_BINDING;
OUString sProperty = bSubmission ? PN_SUBMISSION_ID : PN_BINDING_ID;
OUString sSearch = bSubmission ? OUString(SUBMISSIONNAME) : OUString(BINDINGNAME);
OUString sName;
try
{
pNode->m_xPropSet->getPropertyValue( sProperty ) >>= sName;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::RemoveEntry()" );
}
std::unique_ptr<weld::MessageDialog> xQBox(Application::CreateMessageDialog(m_pNaviWin->GetFrameWeld(),
VclMessageType::Question, VclButtonsType::YesNo,
SvxResId(pResId)));
OUString sMessText = xQBox->get_primary_text();
sMessText = sMessText.replaceFirst( sSearch, sName);
xQBox->set_primary_text(sMessText);
if (xQBox->run() == RET_YES)
{
try
{
if ( bSubmission )
xModel->getSubmissions()->remove( Any( pNode->m_xPropSet ) );
else // then Binding Page
xModel->getBindings()->remove( Any( pNode->m_xPropSet ) );
bRet = true ;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::RemoveEntry()" );
}
}
}
if (bRet)
{
m_xItemList->remove(*xEntry);
delete pNode;
}
}
return bRet;
}
IMPL_LINK(XFormsPage, KeyInputHdl, const KeyEvent&, rKEvt, bool )
{
bool bHandled = false ;
sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
if (nCode == KEY_DELETE)
bHandled = DoMenuAction(u"delete" );
return bHandled;
}
OUString XFormsPage::SetModel( const Reference< css::xforms::XModel >& _xModel, int _nPagePos )
{
DBG_ASSERT( _xModel.is(), "XFormsPage::SetModel(): invalid model" );
m_xUIHelper.set( _xModel, UNO_QUERY );
OUString sRet;
m_bHasModel = true ;
switch ( m_eGroup )
{
case DGTInstance :
{
DBG_ASSERT( _nPagePos != -1, "XFormsPage::SetModel(): invalid page position" );
try
{
Reference< XContainer > xContainer( _xModel->getInstances(), UNO_QUERY );
if ( xContainer.is() )
m_pNaviWin->AddContainerBroadcaster( xContainer );
Reference< XEnumerationAccess > xNumAccess = _xModel->getInstances();
if ( xNumAccess.is() )
{
Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
if ( xNum.is() && xNum->hasMoreElements() )
{
int nIter = 0;
while ( xNum->hasMoreElements() )
{
if ( nIter == _nPagePos )
{
Sequence< PropertyValue > xPropSeq;
Any aAny = xNum->nextElement();
if ( aAny >>= xPropSeq )
sRet = LoadInstance(xPropSeq);
else
{
SAL_WARN( "svx.form" , "XFormsPage::SetModel(): invalid instance" );
}
break ;
}
else
{
xNum->nextElement();
++nIter;
}
}
}
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::SetModel()" );
}
break ;
}
case DGTSubmission :
{
DBG_ASSERT( _nPagePos == -1, "XFormsPage::SetModel(): invalid page position" );
try
{
Reference< XContainer > xContainer( _xModel->getSubmissions(), UNO_QUERY );
if ( xContainer.is() )
m_pNaviWin->AddContainerBroadcaster( xContainer );
Reference< XEnumerationAccess > xNumAccess = _xModel->getSubmissions();
if ( xNumAccess.is() )
{
Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
if ( xNum.is() && xNum->hasMoreElements() )
{
while ( xNum->hasMoreElements() )
{
Reference< XPropertySet > xPropSet;
Any aAny = xNum->nextElement();
if ( aAny >>= xPropSet )
AddEntry( xPropSet );
}
}
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::SetModel()" );
}
break ;
}
case DGTBinding :
{
DBG_ASSERT( _nPagePos == -1, "XFormsPage::SetModel(): invalid page position" );
try
{
Reference< XContainer > xContainer( _xModel->getBindings(), UNO_QUERY );
if ( xContainer.is() )
m_pNaviWin->AddContainerBroadcaster( xContainer );
Reference< XEnumerationAccess > xNumAccess = _xModel->getBindings();
if ( xNumAccess.is() )
{
Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
if ( xNum.is() && xNum->hasMoreElements() )
{
OUString aImage(RID_SVXBMP_ELEMENT);
std::unique_ptr<weld::TreeIter> xRes(m_xItemList->make_iterator());
while ( xNum->hasMoreElements() )
{
Reference< XPropertySet > xPropSet;
Any aAny = xNum->nextElement();
if ( aAny >>= xPropSet )
{
OUString sEntry;
OUString sTemp;
xPropSet->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
sEntry += sTemp + ": " ;
xPropSet->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
sEntry += sTemp;
ItemNode* pNode = new ItemNode( xPropSet );
OUString sId(weld::toId(pNode));
m_xItemList->insert(nullptr, -1, &sEntry, &sId, nullptr, nullptr, false , xRes.get());
m_xItemList->set_image(*xRes, aImage);
}
}
}
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::SetModel()" );
}
break ;
}
default :
OSL_FAIL( "XFormsPage::SetModel: unknown group!" );
break ;
}
EnableMenuItems();
return sRet;
}
void XFormsPage::ClearModel()
{
m_bHasModel = false ;
DeleteAndClearTree();
}
OUString XFormsPage::LoadInstance(const Sequence< PropertyValue >& _xPropSeq)
{
OUString sRet;
OUString sTemp;
OUString sInstModel = PN_INSTANCE_MODEL;
OUString sInstName = PN_INSTANCE_ID;
OUString sInstURL = PN_INSTANCE_URL;
for ( const PropertyValue& rProp : _xPropSeq )
{
if ( sInstModel == rProp.Name )
{
Reference< css::xml::dom::XNode > xRoot;
if ( rProp.Value >>= xRoot )
{
try
{
Reference< XEventTarget > xTarget( xRoot, UNO_QUERY );
if ( xTarget.is() )
m_pNaviWin->AddEventBroadcaster( xTarget );
OUString sNodeName =
m_xUIHelper->getNodeDisplayName( xRoot, m_pNaviWin->IsShowDetails() );
if ( sNodeName.isEmpty() )
sNodeName = xRoot->getNodeName();
if ( xRoot->hasChildNodes() )
AddChildren(nullptr, xRoot);
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::LoadInstance()" );
}
}
}
else if ( sInstName == rProp.Name && ( rProp.Value >>= sTemp ) )
m_sInstanceName = sRet = sTemp;
else if ( sInstURL == rProp.Name && ( rProp.Value >>= sTemp ) )
m_sInstanceURL = sTemp;
}
return sRet;
}
bool XFormsPage::DoMenuAction(std::u16string_view rMenuID)
{
return DoToolBoxAction(rMenuID);
}
void XFormsPage::SetMenuEntrySensitive(const OUString& rIdent, bool bSensitive)
{
if (m_aRemovedMenuEntries.find(rIdent) != m_aRemovedMenuEntries.end())
return ;
m_xMenu->set_sensitive(rIdent, bSensitive);
}
void XFormsPage::EnableMenuItems()
{
bool bEnableAdd = false ;
bool bEnableEdit = false ;
bool bEnableRemove = false ;
std::unique_ptr<weld::TreeIter> xEntry(m_xItemList->make_iterator());
bool bEntry = m_xItemList->get_selected(xEntry.get());
if (bEntry)
{
bEnableAdd = true ;
bool bSubmitChild = false ;
if (DGTSubmission == m_eGroup && m_xItemList->get_iter_depth(*xEntry))
{
m_xItemList->iter_parent(*xEntry);
bSubmitChild = true ;
}
ItemNode* pNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*xEntry));
if ( pNode && ( pNode->m_xNode.is() || pNode->m_xPropSet.is() ) )
{
bEnableEdit = true ;
bEnableRemove = !bSubmitChild;
if ( DGTInstance == m_eGroup && !m_xItemList->get_iter_depth(*xEntry) )
bEnableRemove = false ;
if ( pNode->m_xNode.is() )
{
try
{
css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
if ( eChildType != css::xml::dom::NodeType_ELEMENT_NODE
&& eChildType != css::xml::dom::NodeType_DOCUMENT_NODE )
{
bEnableAdd = false ;
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::EnableMenuItems()" );
}
}
}
}
else if ( m_eGroup != DGTInstance )
bEnableAdd = true ;
m_xToolBox->set_item_sensitive(u"additem" _ustr, bEnableAdd);
m_xToolBox->set_item_sensitive(u"addelement" _ustr, bEnableAdd);
m_xToolBox->set_item_sensitive(u"addattribute" _ustr, bEnableAdd);
m_xToolBox->set_item_sensitive(u"edit" _ustr, bEnableEdit);
m_xToolBox->set_item_sensitive(u"delete" _ustr, bEnableRemove);
if (m_xMenu)
{
SetMenuEntrySensitive(u"additem" _ustr, bEnableAdd);
SetMenuEntrySensitive(u"addelement" _ustr, bEnableAdd);
SetMenuEntrySensitive(u"addattribute" _ustr, bEnableAdd);
SetMenuEntrySensitive(u"edit" _ustr, bEnableEdit);
SetMenuEntrySensitive(u"delete" _ustr, bEnableRemove);
}
if ( DGTInstance != m_eGroup )
return ;
TranslateId pResId1 = RID_STR_DATANAV_EDIT_ELEMENT;
TranslateId pResId2 = RID_STR_DATANAV_REMOVE_ELEMENT;
if (bEntry)
{
ItemNode* pNode = weld::fromId<ItemNode*>(m_xItemList->get_id(*xEntry));
if ( pNode && pNode->m_xNode.is() )
{
try
{
css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
if ( eChildType == css::xml::dom::NodeType_ATTRIBUTE_NODE )
{
pResId1 = RID_STR_DATANAV_EDIT_ATTRIBUTE;
pResId2 = RID_STR_DATANAV_REMOVE_ATTRIBUTE;
}
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "XFormsPage::EnableMenuItems()" );
}
}
}
m_xToolBox->set_item_label(u"edit" _ustr, SvxResId(pResId1));
m_xToolBox->set_item_label(u"delete" _ustr, SvxResId(pResId2));
if (m_xMenu)
{
m_xMenu->set_label(u"edit" _ustr, SvxResId( pResId1 ) );
m_xMenu->set_label(u"delete" _ustr, SvxResId( pResId2 ) );
}
}
DataNavigatorWindow::DataNavigatorWindow(vcl::Window* pParent, weld::Builder& rBuilder, SfxBindings const * pBindings)
: m_xParent(pParent)
, m_xModelsBox(rBuilder.weld_combo_box(u"modelslist" _ustr))
, m_xModelBtn(rBuilder.weld_menu_button(u"modelsbutton" _ustr))
, m_xTabCtrl(rBuilder.weld_notebook(u"tabcontrol" _ustr))
, m_xInstanceBtn(rBuilder.weld_menu_button(u"instances" _ustr))
, m_nLastSelectedPos(-1)
, m_bShowDetails(false )
, m_bIsNotifyDisabled(false )
, m_aUpdateTimer("svx DataNavigatorWindow m_aUpdateTimer" )
, m_xDataListener(new DataListener(this ))
{
// handler
m_xModelsBox->connect_changed( LINK( this , DataNavigatorWindow, ModelSelectListBoxHdl ) );
Link<const OUString&, void > aLink1 = LINK( this , DataNavigatorWindow, MenuSelectHdl );
m_xModelBtn->connect_selected(aLink1);
m_xInstanceBtn->connect_selected(aLink1);
Link<weld::Toggleable&,void > aLink2 = LINK( this , DataNavigatorWindow, MenuActivateHdl );
m_xModelBtn->connect_toggled( aLink2 );
m_xInstanceBtn->connect_toggled( aLink2 );
m_xTabCtrl->connect_enter_page( LINK( this , DataNavigatorWindow, ActivatePageHdl ) );
m_aUpdateTimer.SetTimeout( 2000 );
m_aUpdateTimer.SetInvokeHandler( LINK( this , DataNavigatorWindow, UpdateHdl ) );
// init tabcontrol
OUString sPageId(u"instance" _ustr);
SvtViewOptions aViewOpt( EViewType::TabDialog, CFGNAME_DATANAVIGATOR );
if ( aViewOpt.Exists() )
{
OUString sNewPageId = aViewOpt.GetPageID();
if (m_xTabCtrl->get_page_index(sNewPageId) != -1)
sPageId = sNewPageId;
aViewOpt.GetUserItem(CFGNAME_SHOWDETAILS) >>= m_bShowDetails;
}
m_xInstanceBtn->set_item_active(u"instancesdetails" _ustr, m_bShowDetails);
// get our frame
assert(pBindings != nullptr &&
"DataNavigatorWindow::LoadModels(): no SfxBindings; can't get frame" );
m_xFrame = pBindings->GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface();
DBG_ASSERT( m_xFrame.is(), "DataNavigatorWindow::LoadModels(): no frame" );
// add frameaction listener
m_xFrame->addFrameActionListener( Reference< XFrameActionListener >(m_xDataListener) );
// load xforms models of the current document
LoadModels();
// tdf#154683 Select the current page after loading the Models, the default
// Instance page needs to be selected at LoadModel time in order to get its
// tab text updated automatically.
m_xTabCtrl->set_current_page(sPageId);
ActivatePageHdl(sPageId);
// tdf#154322 select the first entry of the current page by default
if (XFormsPage* pPage = GetPage(sPageId))
pPage->SelectFirstEntry();
}
DataNavigatorWindow::~DataNavigatorWindow()
{
m_xFrame->removeFrameActionListener( Reference< XFrameActionListener >(m_xDataListener) );
SvtViewOptions aViewOpt( EViewType::TabDialog, CFGNAME_DATANAVIGATOR );
aViewOpt.SetPageID(m_xTabCtrl->get_current_page_ident());
aViewOpt.SetUserItem(CFGNAME_SHOWDETAILS, Any(m_bShowDetails));
m_xInstPage.reset();
m_xSubmissionPage.reset();
m_xBindingPage.reset();
sal_Int32 i, nCount = m_aPageList.size();
for ( i = 0; i < nCount; ++i )
m_aPageList[i].reset();
m_aPageList.clear();
RemoveBroadcaster();
m_xDataListener.clear();
}
IMPL_LINK( DataNavigatorWindow, ModelSelectListBoxHdl, weld::ComboBox&, rBox, void )
{
ModelSelectHdl(&rBox);
}
void DataNavigatorWindow::ModelSelectHdl(const weld::ComboBox* pBox)
{
sal_Int32 nPos = m_xModelsBox->get_active();
// pBox == NULL, if you want to force a new fill.
if ( nPos != m_nLastSelectedPos || !pBox )
{
m_nLastSelectedPos = nPos;
ClearAllPageModels( pBox != nullptr );
InitPages();
SetPageModel(GetCurrentPage());
}
}
IMPL_LINK(DataNavigatorWindow, MenuSelectHdl, const OUString&, rIdent, void )
{
bool bIsDocModified = false ;
Reference< css::xforms::XFormsUIHelper1 > xUIHelper;
sal_Int32 nSelectedPos = m_xModelsBox->get_active();
OUString sSelectedModel(m_xModelsBox->get_text(nSelectedPos));
Reference< css::xforms::XModel > xModel;
try
{
Any aAny = m_xDataContainer->getByName( sSelectedModel );
if ( aAny >>= xModel )
xUIHelper.set( xModel, UNO_QUERY );
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "DataNavigatorWindow::MenuSelectHdl()" );
}
DBG_ASSERT( xUIHelper.is(), "DataNavigatorWindow::MenuSelectHdl(): no UIHelper" );
m_bIsNotifyDisabled = true ;
if (rIdent == "modelsadd" )
{
AddModelDialog aDlg(GetFrameWeld(), false );
bool bShowDialog = true ;
while ( bShowDialog )
{
bShowDialog = false ;
if (aDlg.run() == RET_OK)
{
OUString sNewName = aDlg.GetName();
bool bDocumentData = aDlg.GetModifyDoc();
if (m_xModelsBox->find_text(sNewName) != -1)
{
// error: model name already exists
std::unique_ptr<weld::MessageDialog> xErrBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Warning, VclButtonsType::Ok,
SvxResId(RID_STR_DOUBLE_MODELNAME)));
xErrBox->set_primary_text(xErrBox->get_primary_text().replaceFirst(MSG_VARIABLE, sNewName));
xErrBox->run();
bShowDialog = true ;
}
else
{
try
{
// add new model to frame model
Reference< css::xforms::XModel > xNewModel(
xUIHelper->newModel( m_xFrameModel, sNewName ), UNO_SET_THROW );
Reference< XPropertySet > xModelProps( xNewModel, UNO_QUERY_THROW );
xModelProps->setPropertyValue(u"ExternalData" _ustr, Any( !bDocumentData ) );
m_xModelsBox->append_text(sNewName);
m_xModelsBox->set_active(m_xModelsBox->get_count() - 1);
ModelSelectHdl(m_xModelsBox.get());
bIsDocModified = true ;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "DataNavigatorWindow::MenuSelectHdl()" );
}
}
}
}
}
else if (rIdent == "modelsedit" )
{
AddModelDialog aDlg(GetFrameWeld(), true );
aDlg.SetName( sSelectedModel );
bool bDocumentData( false );
try
{
Reference< css::xforms::XFormsSupplier > xFormsSupp( m_xFrameModel, UNO_QUERY_THROW );
Reference< XNameContainer > xXForms( xFormsSupp->getXForms(), UNO_SET_THROW );
Reference< XPropertySet > xModelProps( xXForms->getByName( sSelectedModel ), UNO_QUERY_THROW );
bool bExternalData = false ;
OSL_VERIFY( xModelProps->getPropertyValue( u"ExternalData" _ustr ) >>= bExternalData );
bDocumentData = !bExternalData;
}
catch ( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx" );
}
aDlg.SetModifyDoc( bDocumentData );
if (aDlg.run() == RET_OK)
{
if ( aDlg.GetModifyDoc() != bDocumentData )
{
bDocumentData = aDlg.GetModifyDoc();
try
{
Reference< css::xforms::XFormsSupplier > xFormsSupp( m_xFrameModel, UNO_QUERY_THROW );
Reference< XNameContainer > xXForms( xFormsSupp->getXForms(), UNO_SET_THROW );
Reference< XPropertySet > xModelProps( xXForms->getByName( sSelectedModel ), UNO_QUERY_THROW );
xModelProps->setPropertyValue( u"ExternalData" _ustr, Any( !bDocumentData ) );
bIsDocModified = true ;
}
catch ( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx" );
}
}
OUString sNewName = aDlg.GetName();
if ( !sNewName.isEmpty() && ( sNewName != sSelectedModel ) )
{
try
{
xUIHelper->renameModel( m_xFrameModel, sSelectedModel, sNewName );
m_xModelsBox->remove(nSelectedPos);
m_xModelsBox->append_text(sNewName);
m_xModelsBox->set_active(m_xModelsBox->get_count() - 1);
bIsDocModified = true ;
}
catch ( Exception const & )
{
TOOLS_WARN_EXCEPTION( "svx.form" , "DataNavigatorWindow::MenuSelectHdl()" );
}
}
}
}
else if (rIdent == "modelsremove" )
{
std::unique_ptr<weld::MessageDialog> xQBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Question, VclButtonsType::YesNo,
SvxResId( RID_STR_QRY_REMOVE_MODEL)));
OUString sText = xQBox->get_primary_text();
sText = sText.replaceFirst( MODELNAME, sSelectedModel );
xQBox->set_primary_text(sText);
if (xQBox->run() == RET_YES)
{
try
{
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=99 H=99 G=98
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland