624 lines
18 KiB
C++
624 lines
18 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/.
|
|
*/
|
|
|
|
#include <xmlsourcedlg.hxx>
|
|
#include <bitmaps.hlst>
|
|
#include <document.hxx>
|
|
#include <orcusfilters.hxx>
|
|
#include <filter.hxx>
|
|
#include <reffact.hxx>
|
|
#include <tabvwsh.hxx>
|
|
|
|
#include <tools/urlobj.hxx>
|
|
#include <sfx2/filedlghelper.hxx>
|
|
|
|
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
|
|
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
|
|
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
|
|
|
|
using namespace com::sun::star;
|
|
|
|
namespace {
|
|
|
|
bool isAttribute(const weld::TreeView& rControl, const weld::TreeIter& rEntry)
|
|
{
|
|
const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rControl, rEntry);
|
|
if (!pUserData)
|
|
return false;
|
|
|
|
return pUserData->meType == ScOrcusXMLTreeParam::Attribute;
|
|
}
|
|
|
|
OUString getXPath(
|
|
const weld::TreeView& rTree, const weld::TreeIter& rEntry, std::vector<size_t>& rNamespaces)
|
|
{
|
|
OUStringBuffer aBuf;
|
|
std::unique_ptr<weld::TreeIter> xEntry(rTree.make_iterator(&rEntry));
|
|
do
|
|
{
|
|
// Collect used namespace.
|
|
const ScOrcusXMLTreeParam::EntryData* pData = ScOrcusXMLTreeParam::getUserData(rTree, *xEntry);
|
|
if (pData)
|
|
rNamespaces.push_back(pData->mnNamespaceID);
|
|
|
|
// element separator is '/' whereas attribute separator is '/@' in xpath.
|
|
std::u16string_view sSeparator;
|
|
if (isAttribute(rTree, *xEntry))
|
|
sSeparator = u"/@";
|
|
else
|
|
sSeparator = u"/";
|
|
aBuf.insert(0, sSeparator + rTree.get_text(*xEntry, 0));
|
|
}
|
|
while (rTree.iter_parent(*xEntry));
|
|
|
|
return aBuf.makeStringAndClear();
|
|
}
|
|
|
|
}
|
|
|
|
ScXMLSourceDlg::ScXMLSourceDlg(
|
|
SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, ScDocument* pDoc)
|
|
: ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/xmlsourcedialog.ui"_ustr, u"XMLSourceDialog"_ustr)
|
|
, mpDoc(pDoc)
|
|
, mbDlgLostFocus(false)
|
|
, mxBtnSelectSource(m_xBuilder->weld_button(u"selectsource"_ustr))
|
|
, mxFtSourceFile(m_xBuilder->weld_label(u"sourcefile"_ustr))
|
|
, mxMapGrid(m_xBuilder->weld_container(u"mapgrid"_ustr))
|
|
, mxLbTree(m_xBuilder->weld_tree_view(u"tree"_ustr))
|
|
, mxRefEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"edit"_ustr)))
|
|
, mxRefBtn(new formula::RefButton(m_xBuilder->weld_button(u"ref"_ustr)))
|
|
, mxBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
|
|
, mxBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
|
|
, maCustomCompare(*mxLbTree)
|
|
, maCellLinks(maCustomCompare)
|
|
, maRangeLinks(maCustomCompare)
|
|
{
|
|
mxLbTree->set_size_request(mxLbTree->get_approximate_digit_width() * 40,
|
|
mxLbTree->get_height_rows(15));
|
|
mxLbTree->set_selection_mode(SelectionMode::Multiple);
|
|
mxRefEdit->SetReferences(this, nullptr);
|
|
mxRefBtn->SetReferences(this, mxRefEdit.get());
|
|
|
|
mpActiveEdit = mxRefEdit.get();
|
|
|
|
maXMLParam.maImgElementDefault = RID_BMP_ELEMENT_DEFAULT;
|
|
maXMLParam.maImgElementRepeat = RID_BMP_ELEMENT_REPEAT;
|
|
maXMLParam.maImgAttribute = RID_BMP_ELEMENT_ATTRIBUTE;
|
|
|
|
Link<weld::Button&,void> aBtnHdl = LINK(this, ScXMLSourceDlg, BtnPressedHdl);
|
|
mxBtnSelectSource->connect_clicked(aBtnHdl);
|
|
mxBtnOk->connect_clicked(aBtnHdl);
|
|
mxBtnCancel->connect_clicked(aBtnHdl);
|
|
|
|
mxLbTree->connect_changed(LINK(this, ScXMLSourceDlg, TreeItemSelectHdl));
|
|
|
|
Link<formula::RefEdit&,void> aLink = LINK(this, ScXMLSourceDlg, RefModifiedHdl);
|
|
mxRefEdit->SetModifyHdl(aLink);
|
|
|
|
mxBtnOk->set_sensitive(false);
|
|
|
|
SetNonLinkable();
|
|
mxBtnSelectSource->grab_focus(); // Initial focus is on the select source button.
|
|
}
|
|
|
|
ScXMLSourceDlg::~ScXMLSourceDlg()
|
|
{
|
|
}
|
|
|
|
bool ScXMLSourceDlg::IsRefInputMode() const
|
|
{
|
|
return mpActiveEdit != nullptr && mpActiveEdit->GetWidget()->get_sensitive();
|
|
}
|
|
|
|
void ScXMLSourceDlg::SetReference(const ScRange& rRange, ScDocument& rDoc)
|
|
{
|
|
if (!mpActiveEdit)
|
|
return;
|
|
|
|
if (rRange.aStart != rRange.aEnd)
|
|
RefInputStart(mpActiveEdit);
|
|
|
|
OUString aStr(rRange.aStart.Format(ScRefFlags::ADDR_ABS_3D, &rDoc, rDoc.GetAddressConvention()));
|
|
mpActiveEdit->SetRefString(aStr);
|
|
|
|
RefEditModified();
|
|
}
|
|
|
|
void ScXMLSourceDlg::Deactivate()
|
|
{
|
|
mbDlgLostFocus = true;
|
|
}
|
|
|
|
void ScXMLSourceDlg::SetActive()
|
|
{
|
|
if (mbDlgLostFocus)
|
|
{
|
|
mbDlgLostFocus = false;
|
|
if (mpActiveEdit)
|
|
{
|
|
mpActiveEdit->GrabFocus();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_xDialog->grab_focus();
|
|
}
|
|
|
|
RefInputDone();
|
|
}
|
|
|
|
void ScXMLSourceDlg::Close()
|
|
{
|
|
DoClose(ScXMLSourceDlgWrapper::GetChildWindowId());
|
|
}
|
|
|
|
void ScXMLSourceDlg::SelectSourceFile()
|
|
{
|
|
sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
|
|
FileDialogFlags::NONE, m_xDialog.get());
|
|
aDlgHelper.SetContext(sfx2::FileDialogHelper::CalcXMLSource);
|
|
|
|
uno::Reference<ui::dialogs::XFilePicker3> xFilePicker = aDlgHelper.GetFilePicker();
|
|
|
|
// Use the directory of current source file.
|
|
INetURLObject aURL(maSrcPath);
|
|
aURL.removeSegment();
|
|
aURL.removeFinalSlash();
|
|
OUString aPath = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
|
|
xFilePicker->setDisplayDirectory(aPath);
|
|
|
|
if (xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK)
|
|
// File picker dialog cancelled.
|
|
return;
|
|
|
|
uno::Sequence<OUString> aFiles = xFilePicker->getSelectedFiles();
|
|
if (!aFiles.hasElements())
|
|
return;
|
|
|
|
// There should only be one file returned from the file picker.
|
|
maSrcPath = aFiles[0];
|
|
mxFtSourceFile->set_label(maSrcPath);
|
|
LoadSourceFileStructure(maSrcPath);
|
|
}
|
|
|
|
void ScXMLSourceDlg::LoadSourceFileStructure(const OUString& rPath)
|
|
{
|
|
ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
|
|
if (!pOrcus)
|
|
return;
|
|
|
|
mpXMLContext = pOrcus->createXMLContext(*mpDoc, rPath);
|
|
if (!mpXMLContext)
|
|
return;
|
|
|
|
mpXMLContext->loadXMLStructure(*mxLbTree, maXMLParam);
|
|
}
|
|
|
|
namespace {
|
|
|
|
/**
|
|
* The current entry is the reference entry for a cell link. For a range
|
|
* link, the reference entry is the shallowest repeat element entry up from
|
|
* the current entry position. The mapped cell position for a range link is
|
|
* stored with the reference entry.
|
|
*/
|
|
std::unique_ptr<weld::TreeIter> getReferenceEntry(const weld::TreeView& rTree, const weld::TreeIter& rCurEntry)
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xParent(rTree.make_iterator(&rCurEntry));
|
|
bool bParent = rTree.iter_parent(*xParent);
|
|
std::unique_ptr<weld::TreeIter> xRefEntry;
|
|
while (bParent)
|
|
{
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rTree, *xParent);
|
|
assert(pUserData);
|
|
if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
|
|
{
|
|
// This is a repeat element - a potential reference entry.
|
|
xRefEntry = rTree.make_iterator(xParent.get());
|
|
}
|
|
bParent = rTree.iter_parent(*xParent);
|
|
}
|
|
|
|
if (xRefEntry)
|
|
return xRefEntry;
|
|
|
|
std::unique_ptr<weld::TreeIter> xCurEntry(rTree.make_iterator(&rCurEntry));
|
|
return xCurEntry;
|
|
}
|
|
|
|
}
|
|
|
|
void ScXMLSourceDlg::TreeItemSelected()
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xEntry(mxLbTree->make_iterator());
|
|
if (!mxLbTree->get_cursor(xEntry.get()))
|
|
return;
|
|
|
|
mxLbTree->unselect_all();
|
|
mxLbTree->select(*xEntry);
|
|
|
|
mxCurRefEntry = getReferenceEntry(*mxLbTree, *xEntry);
|
|
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *mxCurRefEntry);
|
|
assert(pUserData);
|
|
|
|
const ScAddress& rPos = pUserData->maLinkedPos;
|
|
if (rPos.IsValid())
|
|
{
|
|
OUString aStr(rPos.Format(ScRefFlags::ADDR_ABS_3D, mpDoc, mpDoc->GetAddressConvention()));
|
|
mxRefEdit->SetRefString(aStr);
|
|
}
|
|
else
|
|
mxRefEdit->SetRefString(OUString());
|
|
|
|
switch (pUserData->meType)
|
|
{
|
|
case ScOrcusXMLTreeParam::Attribute:
|
|
AttributeSelected(*mxCurRefEntry);
|
|
break;
|
|
case ScOrcusXMLTreeParam::ElementDefault:
|
|
DefaultElementSelected(*mxCurRefEntry);
|
|
break;
|
|
case ScOrcusXMLTreeParam::ElementRepeat:
|
|
RepeatElementSelected(*mxCurRefEntry);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
|
|
void ScXMLSourceDlg::DefaultElementSelected(const weld::TreeIter& rEntry)
|
|
{
|
|
if (mxLbTree->iter_has_child(rEntry))
|
|
{
|
|
// Only an element with no child elements (leaf element) can be linked.
|
|
bool bHasChild = false;
|
|
std::unique_ptr<weld::TreeIter> xChild(mxLbTree->make_iterator(&rEntry));
|
|
(void)mxLbTree->iter_children(*xChild);
|
|
do
|
|
{
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *xChild);
|
|
assert(pUserData);
|
|
if (pUserData->meType != ScOrcusXMLTreeParam::Attribute)
|
|
{
|
|
// This child is not an attribute. Bail out.
|
|
bHasChild = true;
|
|
break;
|
|
}
|
|
}
|
|
while (mxLbTree->iter_next_sibling(*xChild));
|
|
|
|
if (bHasChild)
|
|
{
|
|
SetNonLinkable();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check all its parents and make sure non of them are range-linked nor
|
|
// repeat elements.
|
|
if (IsParentDirty(&rEntry))
|
|
{
|
|
SetNonLinkable();
|
|
return;
|
|
}
|
|
|
|
SetSingleLinkable();
|
|
}
|
|
|
|
void ScXMLSourceDlg::RepeatElementSelected(const weld::TreeIter& rEntry)
|
|
{
|
|
// Check all its parents first.
|
|
|
|
if (IsParentDirty(&rEntry))
|
|
{
|
|
SetNonLinkable();
|
|
return;
|
|
}
|
|
|
|
// Check all its child elements / attributes and make sure non of them are
|
|
// linked.
|
|
|
|
if (IsChildrenDirty(&rEntry))
|
|
{
|
|
SetNonLinkable();
|
|
return;
|
|
}
|
|
|
|
if (!mxLbTree->is_selected(rEntry))
|
|
{
|
|
// Highlight the entry if not highlighted already. This can happen
|
|
// when the current entry is a child entry of a repeat element entry.
|
|
mxLbTree->select(rEntry);
|
|
}
|
|
|
|
SelectAllChildEntries(rEntry);
|
|
SetRangeLinkable();
|
|
}
|
|
|
|
void ScXMLSourceDlg::AttributeSelected(const weld::TreeIter& rEntry)
|
|
{
|
|
// Check all its parent elements and make sure non of them are linked nor
|
|
// repeat elements. In attribute's case, it's okay to have the immediate
|
|
// parent element linked (but not range-linked).
|
|
std::unique_ptr<weld::TreeIter> xParent(mxLbTree->make_iterator(&rEntry));
|
|
mxLbTree->iter_parent(*xParent);
|
|
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *xParent);
|
|
assert(pUserData);
|
|
if (pUserData->maLinkedPos.IsValid() && pUserData->mbRangeParent)
|
|
{
|
|
// Parent element is range-linked. Bail out.
|
|
SetNonLinkable();
|
|
return;
|
|
}
|
|
|
|
if (IsParentDirty(&rEntry))
|
|
{
|
|
SetNonLinkable();
|
|
return;
|
|
}
|
|
|
|
SetSingleLinkable();
|
|
}
|
|
|
|
void ScXMLSourceDlg::SetNonLinkable()
|
|
{
|
|
mxMapGrid->set_sensitive(false);
|
|
}
|
|
|
|
void ScXMLSourceDlg::SetSingleLinkable()
|
|
{
|
|
mxMapGrid->set_sensitive(true);
|
|
}
|
|
|
|
void ScXMLSourceDlg::SetRangeLinkable()
|
|
{
|
|
mxMapGrid->set_sensitive(true);
|
|
}
|
|
|
|
void ScXMLSourceDlg::SelectAllChildEntries(const weld::TreeIter& rEntry)
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xChild(mxLbTree->make_iterator(&rEntry));
|
|
if (!mxLbTree->iter_children(*xChild))
|
|
return;
|
|
do
|
|
{
|
|
SelectAllChildEntries(*xChild); // select recursively.
|
|
mxLbTree->select(*xChild);
|
|
} while (mxLbTree->iter_next_sibling(*xChild));
|
|
}
|
|
|
|
bool ScXMLSourceDlg::IsParentDirty(const weld::TreeIter* pEntry) const
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xParent(mxLbTree->make_iterator(pEntry));
|
|
if (!mxLbTree->iter_parent(*xParent))
|
|
return false;
|
|
do
|
|
{
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *xParent);
|
|
assert(pUserData);
|
|
if (pUserData->maLinkedPos.IsValid())
|
|
{
|
|
// This parent is already linked.
|
|
return true;
|
|
}
|
|
}
|
|
while (mxLbTree->iter_parent(*xParent));
|
|
return false;
|
|
}
|
|
|
|
bool ScXMLSourceDlg::IsChildrenDirty(const weld::TreeIter* pEntry) const
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xChild(mxLbTree->make_iterator(pEntry));
|
|
if (!mxLbTree->iter_children(*xChild))
|
|
return false;
|
|
|
|
do
|
|
{
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *xChild);
|
|
assert(pUserData);
|
|
if (pUserData->maLinkedPos.IsValid())
|
|
// Already linked.
|
|
return true;
|
|
|
|
if (pUserData->meType == ScOrcusXMLTreeParam::ElementDefault)
|
|
{
|
|
// Check recursively.
|
|
if (IsChildrenDirty(xChild.get()))
|
|
return true;
|
|
}
|
|
} while (mxLbTree->iter_next_sibling(*xChild));
|
|
|
|
return false;
|
|
}
|
|
|
|
namespace {
|
|
|
|
/**
|
|
* Pick only the leaf elements.
|
|
*/
|
|
void getFieldLinks(
|
|
ScOrcusImportXMLParam::RangeLink& rRangeLink, std::vector<size_t>& rNamespaces,
|
|
const weld::TreeView& rTree, const weld::TreeIter& rEntry)
|
|
{
|
|
OUString aPath = getXPath(rTree, rEntry, rNamespaces);
|
|
const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rTree, rEntry);
|
|
|
|
if (pUserData)
|
|
{
|
|
if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
|
|
// nested repeat element automatically becomes a row-group node.
|
|
rRangeLink.maRowGroups.push_back(
|
|
OUStringToOString(aPath, RTL_TEXTENCODING_UTF8));
|
|
|
|
if (pUserData->mbLeafNode && !aPath.isEmpty())
|
|
// XPath should never be empty anyway, but it won't hurt to check...
|
|
rRangeLink.maFieldPaths.push_back(OUStringToOString(aPath, RTL_TEXTENCODING_UTF8));
|
|
}
|
|
|
|
std::unique_ptr<weld::TreeIter> xChild(rTree.make_iterator(&rEntry));
|
|
|
|
if (!rTree.iter_children(*xChild))
|
|
// No more children. We're done.
|
|
return;
|
|
|
|
do
|
|
{
|
|
// Walk recursively.
|
|
getFieldLinks(rRangeLink, rNamespaces, rTree, *xChild);
|
|
}
|
|
while (rTree.iter_next_sibling(*xChild));
|
|
}
|
|
|
|
void removeDuplicates(std::vector<size_t>& rArray)
|
|
{
|
|
std::sort(rArray.begin(), rArray.end());
|
|
std::vector<size_t>::iterator it = std::unique(rArray.begin(), rArray.end());
|
|
rArray.erase(it, rArray.end());
|
|
}
|
|
|
|
}
|
|
|
|
void ScXMLSourceDlg::OkPressed()
|
|
{
|
|
if (!mpXMLContext)
|
|
return;
|
|
|
|
// Begin import.
|
|
|
|
ScOrcusImportXMLParam aParam;
|
|
|
|
// Convert single cell links.
|
|
for (const auto& rEntry : maCellLinks)
|
|
{
|
|
OUString aPath = getXPath(*mxLbTree, *rEntry, aParam.maNamespaces);
|
|
const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *rEntry);
|
|
|
|
aParam.maCellLinks.emplace_back(
|
|
pUserData->maLinkedPos, OUStringToOString(aPath, RTL_TEXTENCODING_UTF8));
|
|
}
|
|
|
|
// Convert range links. For now, an element with range link takes all its
|
|
// child elements as its fields.
|
|
for (const auto& rEntry: maRangeLinks)
|
|
{
|
|
const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *rEntry);
|
|
|
|
ScOrcusImportXMLParam::RangeLink aRangeLink;
|
|
aRangeLink.maPos = pUserData->maLinkedPos;
|
|
|
|
// Go through all its child elements.
|
|
getFieldLinks(aRangeLink, aParam.maNamespaces, *mxLbTree, *rEntry);
|
|
|
|
// Add the reference entry as a row-group node, which will be used
|
|
// as a row position increment point.
|
|
OUString aThisEntry = getXPath(*mxLbTree, *rEntry, aParam.maNamespaces);
|
|
aRangeLink.maRowGroups.push_back(
|
|
OUStringToOString(aThisEntry, RTL_TEXTENCODING_UTF8));
|
|
|
|
aParam.maRangeLinks.push_back(aRangeLink);
|
|
}
|
|
|
|
// Remove duplicate namespace IDs.
|
|
removeDuplicates(aParam.maNamespaces);
|
|
|
|
// Now do the import.
|
|
mpXMLContext->importXML(aParam);
|
|
|
|
// Don't forget to broadcast the change.
|
|
ScDocShell* pShell = mpDoc->GetDocumentShell();
|
|
pShell->Broadcast(SfxHint(SfxHintId::ScDataChanged));
|
|
|
|
// Repaint the grid to force repaint the cell values.
|
|
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
|
|
if (pViewShell)
|
|
pViewShell->PaintGrid();
|
|
|
|
m_xDialog->response(RET_OK);
|
|
}
|
|
|
|
void ScXMLSourceDlg::CancelPressed()
|
|
{
|
|
m_xDialog->response(RET_CANCEL);
|
|
}
|
|
|
|
void ScXMLSourceDlg::RefEditModified()
|
|
{
|
|
OUString aRefStr = mxRefEdit->GetText();
|
|
|
|
// Check if the address is valid.
|
|
// Preset current sheet in case only address was entered.
|
|
ScAddress aLinkedPos;
|
|
aLinkedPos.SetTab( ScDocShell::GetCurTab());
|
|
ScRefFlags nRes = aLinkedPos.Parse(aRefStr, *mpDoc, mpDoc->GetAddressConvention());
|
|
bool bValid = ( (nRes & ScRefFlags::VALID) == ScRefFlags::VALID );
|
|
|
|
// TODO: For some unknown reason, setting the ref invalid will hide the text altogether.
|
|
// Find out how to make this work.
|
|
// mxRefEdit->SetRefValid(bValid);
|
|
|
|
if (!bValid)
|
|
aLinkedPos.SetInvalid();
|
|
|
|
// Set this address to the current reference entry.
|
|
if (!mxCurRefEntry)
|
|
// This should never happen.
|
|
return;
|
|
|
|
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *mxCurRefEntry);
|
|
if (!pUserData)
|
|
// This should never happen either.
|
|
return;
|
|
|
|
bool bRepeatElem = pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat;
|
|
pUserData->maLinkedPos = aLinkedPos;
|
|
pUserData->mbRangeParent = aLinkedPos.IsValid() && bRepeatElem;
|
|
|
|
if (bRepeatElem)
|
|
{
|
|
if (bValid)
|
|
maRangeLinks.insert(mxLbTree->make_iterator(mxCurRefEntry.get()));
|
|
else
|
|
maRangeLinks.erase(mxCurRefEntry);
|
|
}
|
|
else
|
|
{
|
|
if (bValid)
|
|
maCellLinks.insert(mxLbTree->make_iterator(mxCurRefEntry.get()));
|
|
else
|
|
maCellLinks.erase(mxCurRefEntry);
|
|
}
|
|
|
|
// Enable the import button only when at least one link exists.
|
|
bool bHasLink = !maCellLinks.empty() || !maRangeLinks.empty();
|
|
mxBtnOk->set_sensitive(bHasLink);
|
|
}
|
|
|
|
IMPL_LINK(ScXMLSourceDlg, BtnPressedHdl, weld::Button&, rBtn, void)
|
|
{
|
|
if (&rBtn == mxBtnSelectSource.get())
|
|
SelectSourceFile();
|
|
else if (&rBtn == mxBtnOk.get())
|
|
OkPressed();
|
|
else if (&rBtn == mxBtnCancel.get())
|
|
CancelPressed();
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ScXMLSourceDlg, TreeItemSelectHdl, weld::TreeView&, void)
|
|
{
|
|
TreeItemSelected();
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ScXMLSourceDlg, RefModifiedHdl, formula::RefEdit&, void)
|
|
{
|
|
RefEditModified();
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|