/* -*- 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/.
*/
// Use the directory of current source file.
INetURLObject aURL(maSrcPath);
aURL.removeSegment();
aURL.removeFinalSlash();
OUString aPath = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
if (!aPath.isEmpty())
aDlgHelper.SetDisplayFolder(aPath); if (aDlgHelper.Execute() != ERRCODE_NONE) // File picker dialog cancelled. return;
uno::Sequence<OUString> aFiles = aDlgHelper.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);
}
/** * 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);
}
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);
}
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;
}
do
{
ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *xChild);
assert(pUserData); if (pUserData->maLinkedPos.IsValid()) // Already linked. returntrue;
if (pUserData->meType == ScOrcusXMLTreeParam::ElementDefault)
{ // Check recursively. if (IsChildrenDirty(xChild.get())) returntrue;
}
} while (mxLbTree->iter_next_sibling(*xChild));
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));
}
// Convert range links. For now, an element with range link takes all its // child elements as its fields. for (constauto& rEntry: maRangeLinks)
{ const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mxLbTree, *rEntry);
// 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));
// 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();
// 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;
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);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.