Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "xmlsourcedlg.hxx"
11 : #include "xmlsourcedlg.hrc"
12 :
13 : #include "scresid.hxx"
14 : #include "document.hxx"
15 : #include "orcusfilters.hxx"
16 : #include "filter.hxx"
17 : #include "reffact.hxx"
18 : #include "tabvwsh.hxx"
19 :
20 : #include "unotools/pathoptions.hxx"
21 : #include "tools/urlobj.hxx"
22 : #include "svtools/svlbitm.hxx"
23 : #include "svtools/treelistentry.hxx"
24 : #include "svtools/viewdataentry.hxx"
25 : #include "sfx2/objsh.hxx"
26 :
27 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 : #include <com/sun/star/ui/dialogs/FilePicker.hpp>
29 : #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
30 : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
31 :
32 : using namespace com::sun::star;
33 :
34 : namespace {
35 :
36 0 : bool isAttribute(const SvTreeListEntry& rEntry)
37 : {
38 0 : const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rEntry);
39 0 : if (!pUserData)
40 0 : return false;
41 :
42 0 : return pUserData->meType == ScOrcusXMLTreeParam::Attribute;
43 : }
44 :
45 0 : OUString getXPath(
46 : const SvTreeListBox& rTree, const SvTreeListEntry& rEntry, std::vector<size_t>& rNamespaces)
47 : {
48 0 : OUStringBuffer aBuf;
49 0 : for (const SvTreeListEntry* p = &rEntry; p; p = rTree.GetParent(p))
50 : {
51 0 : const SvLBoxItem* pItem = p->GetFirstItem(SV_ITEM_ID_LBOXSTRING);
52 0 : if (!pItem)
53 0 : continue;
54 :
55 : // Collect used namespace.
56 0 : const ScOrcusXMLTreeParam::EntryData* pData = ScOrcusXMLTreeParam::getUserData(*p);
57 0 : if (pData)
58 0 : rNamespaces.push_back(pData->mnNamespaceID);
59 :
60 0 : const SvLBoxString* pStr = static_cast<const SvLBoxString*>(pItem);
61 0 : aBuf.insert(0, pStr->GetText());
62 0 : aBuf.insert(0, isAttribute(*p) ? '@' : '/');
63 : }
64 :
65 0 : return aBuf.makeStringAndClear();
66 : }
67 :
68 : }
69 :
70 0 : ScXMLSourceTree::ScXMLSourceTree(Window* pParent, const ResId& rResId) :
71 0 : SvTreeListBox(pParent, rResId) {}
72 :
73 0 : ScXMLSourceDlg::ScXMLSourceDlg(
74 : SfxBindings* pB, SfxChildWindow* pCW, Window* pParent, ScDocument* pDoc) :
75 : ScAnyRefDlg(pB, pCW, pParent, RID_SCDLG_XML_SOURCE),
76 : maFlSourceFile(this, ScResId(FL_SOURCE_FILE)),
77 : maBtnSelectSource(this, ScResId(BTN_SELECT_SOURCE_FILE)),
78 : maFtSourceFile(this, ScResId(FT_SOURCE_FILE)),
79 : maFtMapXmlDoc(this, ScResId(FL_MAP_XML_TO_DOCUMENT)),
80 : maFtMappedCellTitle(this, ScResId(FT_MAPPED_CELL_TITLE)),
81 : maLbTree(this, ScResId(LB_SOURCE_TREE)),
82 : maRefEdit(this, this, NULL, ScResId(ED_MAPPED_CELL)),
83 : maRefBtn(this, ScResId(BTN_MAPPED_CELL), &maRefEdit, this),
84 : maBtnOk(this, ScResId(BTN_OK)),
85 : maBtnCancel(this, ScResId(BTN_CANCEL)),
86 : maImgFileOpen(ScResId(IMG_FILE_OPEN)),
87 : mpCurRefEntry(NULL),
88 : mpDoc(pDoc),
89 : mpActiveEdit(&maRefEdit),
90 0 : mbDlgLostFocus(false)
91 : {
92 0 : maXMLParam.maImgElementDefault = Image(ScResId(IMG_ELEMENT_DEFAULT));
93 0 : maXMLParam.maImgElementRepeat = Image(ScResId(IMG_ELEMENT_REPEAT));
94 0 : maXMLParam.maImgAttribute = Image(ScResId(IMG_ELEMENT_ATTRIBUTE));
95 :
96 0 : maBtnSelectSource.SetModeImage(maImgFileOpen);
97 0 : FreeResource();
98 :
99 0 : Link aBtnHdl = LINK(this, ScXMLSourceDlg, BtnPressedHdl);
100 0 : maBtnSelectSource.SetClickHdl(aBtnHdl);
101 0 : maBtnOk.SetClickHdl(aBtnHdl);
102 0 : maBtnCancel.SetClickHdl(aBtnHdl);
103 :
104 0 : Link aLink = LINK(this, ScXMLSourceDlg, GetFocusHdl);
105 0 : maRefEdit.SetGetFocusHdl(aLink);
106 0 : maRefBtn.SetGetFocusHdl(aLink);
107 0 : aLink = LINK(this, ScXMLSourceDlg, LoseFocusHdl);
108 0 : maRefEdit.SetLoseFocusHdl(aLink);
109 0 : maRefBtn.SetLoseFocusHdl(aLink);
110 :
111 0 : aLink = LINK(this, ScXMLSourceDlg, TreeItemSelectHdl);
112 0 : maLbTree.SetSelectHdl(aLink);
113 :
114 0 : aLink = LINK(this, ScXMLSourceDlg, RefModifiedHdl);
115 0 : maRefEdit.SetModifyHdl(aLink);
116 :
117 0 : maBtnOk.Disable();
118 :
119 0 : SetNonLinkable();
120 0 : maBtnSelectSource.GrabFocus(); // Initial focus is on the select source button.
121 0 : }
122 :
123 0 : ScXMLSourceDlg::~ScXMLSourceDlg()
124 : {
125 0 : }
126 :
127 0 : sal_Bool ScXMLSourceDlg::IsRefInputMode() const
128 : {
129 0 : return mpActiveEdit != NULL && mpActiveEdit->IsEnabled();
130 : }
131 :
132 0 : void ScXMLSourceDlg::SetReference(const ScRange& rRange, ScDocument* pDoc)
133 : {
134 0 : if (!mpActiveEdit)
135 0 : return;
136 :
137 0 : if (rRange.aStart != rRange.aEnd)
138 0 : RefInputStart(mpActiveEdit);
139 :
140 0 : OUString aStr;
141 0 : rRange.aStart.Format(aStr, SCA_ABS_3D, pDoc, pDoc->GetAddressConvention());
142 0 : mpActiveEdit->SetRefString(aStr);
143 :
144 0 : RefEditModified();
145 : }
146 :
147 0 : void ScXMLSourceDlg::Deactivate()
148 : {
149 0 : mbDlgLostFocus = true;
150 0 : }
151 :
152 0 : void ScXMLSourceDlg::SetActive()
153 : {
154 0 : if (mbDlgLostFocus)
155 : {
156 0 : mbDlgLostFocus = false;
157 0 : if (mpActiveEdit)
158 : {
159 0 : mpActiveEdit->GrabFocus();
160 : }
161 : }
162 : else
163 : {
164 0 : GrabFocus();
165 : }
166 :
167 0 : RefInputDone();
168 0 : }
169 :
170 0 : sal_Bool ScXMLSourceDlg::Close()
171 : {
172 0 : return DoClose(ScXMLSourceDlgWrapper::GetChildWindowId());
173 : }
174 :
175 0 : void ScXMLSourceDlg::SelectSourceFile()
176 : {
177 0 : uno::Reference<ui::dialogs::XFilePicker3> xFilePicker = ui::dialogs::FilePicker::createWithMode( comphelper::getProcessComponentContext(), ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE );
178 :
179 0 : if (maSrcPath.isEmpty())
180 : // Use default path.
181 0 : xFilePicker->setDisplayDirectory(SvtPathOptions().GetWorkPath());
182 : else
183 : {
184 : // Use the directory of current source file.
185 0 : INetURLObject aURL(maSrcPath);
186 0 : aURL.removeSegment();
187 0 : aURL.removeFinalSlash();
188 0 : OUString aPath = aURL.GetMainURL(INetURLObject::NO_DECODE);
189 0 : xFilePicker->setDisplayDirectory(aPath);
190 : }
191 :
192 0 : if (xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK)
193 : // File picker dialog cancelled.
194 0 : return;
195 :
196 0 : uno::Sequence<OUString> aFiles = xFilePicker->getFiles();
197 0 : if (!aFiles.getLength())
198 0 : return;
199 :
200 : // There should only be one file returned from the file picker.
201 0 : maSrcPath = aFiles[0];
202 0 : maFtSourceFile.SetText(maSrcPath);
203 0 : maHighlightedEntries.clear();
204 0 : LoadSourceFileStructure(maSrcPath);
205 : }
206 :
207 0 : void ScXMLSourceDlg::LoadSourceFileStructure(const OUString& rPath)
208 : {
209 0 : ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
210 0 : if (!pOrcus)
211 0 : return;
212 :
213 0 : mpXMLContext.reset(pOrcus->createXMLContext(*mpDoc, rPath));
214 0 : if (!mpXMLContext)
215 0 : return;
216 :
217 0 : mpXMLContext->loadXMLStructure(maLbTree, maXMLParam);
218 : }
219 :
220 0 : void ScXMLSourceDlg::HandleGetFocus(Control* pCtrl)
221 : {
222 0 : mpActiveEdit = NULL;
223 0 : if (pCtrl == &maRefEdit || pCtrl == &maRefBtn)
224 0 : mpActiveEdit = &maRefEdit;
225 :
226 0 : if (mpActiveEdit)
227 0 : mpActiveEdit->SetSelection(Selection(0, SELECTION_MAX));
228 0 : }
229 :
230 0 : void ScXMLSourceDlg::HandleLoseFocus(Control* /*pCtrl*/)
231 : {
232 0 : }
233 :
234 : namespace {
235 :
236 : class UnhighlightEntry : std::unary_function<SvTreeListEntry*, void>
237 : {
238 : SvTreeListBox& mrTree;
239 : public:
240 0 : UnhighlightEntry(SvTreeListBox& rTree) : mrTree(rTree) {}
241 :
242 0 : void operator() (SvTreeListEntry* p)
243 : {
244 0 : SvViewDataEntry* pView = mrTree.GetViewDataEntry(p);
245 0 : if (!pView)
246 0 : return;
247 :
248 0 : pView->SetHighlighted(false);
249 0 : mrTree.PaintEntry(p);
250 : }
251 : };
252 :
253 : /**
254 : * When the current entry is a direct or indirect child of a mappable
255 : * repeat element entry, that entry becomes the reference entry.
256 : * Otherwise the reference entry equals the current entry. A reference
257 : * entry is the entry that stores mapped cell position.
258 : */
259 0 : SvTreeListEntry* getReferenceEntry(SvTreeListBox& rTree, SvTreeListEntry* pCurEntry)
260 : {
261 0 : SvTreeListEntry* pParent = rTree.GetParent(pCurEntry);
262 0 : SvTreeListEntry* pRefEntry = NULL;
263 0 : while (pParent)
264 : {
265 0 : ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*pParent);
266 : OSL_ASSERT(pUserData);
267 0 : if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
268 : {
269 : // This is a repeat element.
270 0 : if (pRefEntry)
271 : {
272 : // Second repeat element encountered. Not good.
273 0 : return pCurEntry;
274 : }
275 :
276 0 : pRefEntry = pParent;
277 : }
278 0 : pParent = rTree.GetParent(pParent);
279 : }
280 :
281 0 : return pRefEntry ? pRefEntry : pCurEntry;
282 : }
283 :
284 : }
285 :
286 0 : void ScXMLSourceDlg::TreeItemSelected()
287 : {
288 0 : SvTreeListEntry* pEntry = maLbTree.GetCurEntry();
289 0 : if (!pEntry)
290 0 : return;
291 :
292 0 : if (!maHighlightedEntries.empty())
293 : {
294 : // Remove highlights from all previously highlighted entries (if any).
295 0 : std::for_each(maHighlightedEntries.begin(), maHighlightedEntries.end(), UnhighlightEntry(maLbTree));
296 0 : maHighlightedEntries.clear();
297 : }
298 :
299 0 : mpCurRefEntry = getReferenceEntry(maLbTree, pEntry);
300 :
301 0 : ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mpCurRefEntry);
302 : OSL_ASSERT(pUserData);
303 :
304 0 : const ScAddress& rPos = pUserData->maLinkedPos;
305 0 : if (rPos.IsValid())
306 : {
307 0 : OUString aStr;
308 0 : rPos.Format(aStr, SCA_ABS_3D, mpDoc, mpDoc->GetAddressConvention());
309 0 : maRefEdit.SetRefString(aStr);
310 : }
311 : else
312 0 : maRefEdit.SetRefString(OUString());
313 :
314 0 : switch (pUserData->meType)
315 : {
316 : case ScOrcusXMLTreeParam::Attribute:
317 0 : AttributeSelected(*mpCurRefEntry);
318 0 : break;
319 : case ScOrcusXMLTreeParam::ElementDefault:
320 0 : DefaultElementSelected(*mpCurRefEntry);
321 0 : break;
322 : case ScOrcusXMLTreeParam::ElementRepeat:
323 0 : RepeatElementSelected(*mpCurRefEntry);
324 0 : break;
325 : default:
326 : ;
327 : }
328 : }
329 :
330 0 : void ScXMLSourceDlg::DefaultElementSelected(SvTreeListEntry& rEntry)
331 : {
332 :
333 0 : if (maLbTree.GetChildCount(&rEntry) > 0)
334 : {
335 : // Only an element with no child elements (leaf element) can be linked.
336 0 : bool bHasChild = false;
337 0 : ScOrcusXMLTreeParam::EntryData* pUserData = NULL;
338 0 : for (SvTreeListEntry* pChild = maLbTree.FirstChild(&rEntry); pChild; pChild = maLbTree.NextSibling(pChild))
339 : {
340 0 : pUserData = ScOrcusXMLTreeParam::getUserData(*pChild);
341 : OSL_ASSERT(pUserData);
342 0 : if (pUserData->meType != ScOrcusXMLTreeParam::Attribute)
343 : {
344 : // This child is not an attribute. Bail out.
345 0 : bHasChild = true;
346 0 : break;
347 : }
348 : }
349 :
350 0 : if (bHasChild)
351 : {
352 0 : SetNonLinkable();
353 0 : return;
354 : }
355 : }
356 :
357 : // Check all its parents and make sure non of them are range-linked nor
358 : // repeat elements.
359 0 : if (IsParentDirty(&rEntry))
360 : {
361 0 : SetNonLinkable();
362 0 : return;
363 : }
364 :
365 0 : SetSingleLinkable();
366 : }
367 :
368 0 : void ScXMLSourceDlg::RepeatElementSelected(SvTreeListEntry& rEntry)
369 : {
370 : // Check all its parents first.
371 :
372 0 : if (IsParentDirty(&rEntry))
373 : {
374 0 : SetNonLinkable();
375 0 : return;
376 : }
377 :
378 : // Check all its child elements / attributes and make sure non of them are
379 : // linked or repeat elements. In the future we will support range linking
380 : // of repeat element who has another repeat elements. But first I need to
381 : // support that scenario in orcus.
382 :
383 0 : if (IsChildrenDirty(&rEntry))
384 : {
385 0 : SetNonLinkable();
386 0 : return;
387 : }
388 :
389 0 : SvViewDataEntry* p = maLbTree.GetViewDataEntry(&rEntry);
390 0 : if (!p->IsHighlighted())
391 : {
392 : // Highlight the entry if not highlighted already. This can happen
393 : // when the current entry is a child entry of a repeat element entry.
394 0 : p->SetHighlighted(true);
395 0 : maLbTree.PaintEntry(&rEntry);
396 0 : maHighlightedEntries.push_back(&rEntry);
397 : }
398 :
399 0 : SelectAllChildEntries(rEntry);
400 0 : SetRangeLinkable();
401 : }
402 :
403 0 : void ScXMLSourceDlg::AttributeSelected(SvTreeListEntry& rEntry)
404 : {
405 : // Check all its parent elements and make sure non of them are linked nor
406 : // repeat elements. In attribute's case, it's okay to have the immediate
407 : // parent element linked (but not range-linked).
408 :
409 0 : SvTreeListEntry* pParent = maLbTree.GetParent(&rEntry);
410 : OSL_ASSERT(pParent); // attribute should have a parent element.
411 :
412 0 : ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*pParent);
413 : OSL_ASSERT(pUserData);
414 0 : if (pUserData->maLinkedPos.IsValid() && pUserData->mbRangeParent)
415 : {
416 : // Parent element is range-linked. Bail out.
417 0 : SetNonLinkable();
418 0 : return;
419 : }
420 :
421 0 : if (IsParentDirty(&rEntry))
422 : {
423 0 : SetNonLinkable();
424 0 : return;
425 : }
426 :
427 0 : SetSingleLinkable();
428 : }
429 :
430 0 : void ScXMLSourceDlg::SetNonLinkable()
431 : {
432 0 : maFtMappedCellTitle.Disable();
433 0 : maRefEdit.Disable();
434 0 : maRefBtn.Disable();
435 0 : }
436 :
437 0 : void ScXMLSourceDlg::SetSingleLinkable()
438 : {
439 0 : maFtMappedCellTitle.Enable();
440 0 : maRefEdit.Enable();
441 0 : maRefBtn.Enable();
442 0 : }
443 :
444 0 : void ScXMLSourceDlg::SetRangeLinkable()
445 : {
446 0 : maFtMappedCellTitle.Enable();
447 0 : maRefEdit.Enable();
448 0 : maRefBtn.Enable();
449 0 : }
450 :
451 0 : void ScXMLSourceDlg::SelectAllChildEntries(SvTreeListEntry& rEntry)
452 : {
453 0 : SvTreeListEntries& rChildren = rEntry.GetChildEntries();
454 0 : SvTreeListEntries::iterator it = rChildren.begin(), itEnd = rChildren.end();
455 0 : for (; it != itEnd; ++it)
456 : {
457 0 : SvTreeListEntry& r = *it;
458 0 : SelectAllChildEntries(r); // select recursively.
459 0 : SvViewDataEntry* p = maLbTree.GetViewDataEntry(&r);
460 0 : p->SetHighlighted(true);
461 0 : maLbTree.PaintEntry(&r);
462 0 : maHighlightedEntries.push_back(&r);
463 : }
464 0 : }
465 :
466 0 : bool ScXMLSourceDlg::IsParentDirty(SvTreeListEntry* pEntry) const
467 : {
468 0 : ScOrcusXMLTreeParam::EntryData* pUserData = NULL;
469 0 : SvTreeListEntry* pParent = maLbTree.GetParent(pEntry);
470 0 : while (pParent)
471 : {
472 0 : pUserData = ScOrcusXMLTreeParam::getUserData(*pParent);
473 : OSL_ASSERT(pUserData);
474 0 : if (pUserData->maLinkedPos.IsValid())
475 : {
476 : // This parent is already linked.
477 0 : return true;
478 : }
479 0 : if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
480 : {
481 : // This is a repeat element.
482 0 : return true;
483 : }
484 0 : pParent = maLbTree.GetParent(pParent);
485 : }
486 0 : return false;
487 : }
488 :
489 0 : bool ScXMLSourceDlg::IsChildrenDirty(SvTreeListEntry* pEntry) const
490 : {
491 0 : ScOrcusXMLTreeParam::EntryData* pUserData = NULL;
492 0 : for (SvTreeListEntry* pChild = maLbTree.FirstChild(pEntry); pChild; pChild = maLbTree.NextSibling(pChild))
493 : {
494 0 : pUserData = ScOrcusXMLTreeParam::getUserData(*pChild);
495 : OSL_ASSERT(pUserData);
496 0 : if (pUserData->maLinkedPos.IsValid())
497 : // Already linked.
498 0 : return true;
499 :
500 0 : if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
501 : // We don't support linking of nested repeat elements (yet).
502 0 : return true;
503 :
504 0 : if (pUserData->meType == ScOrcusXMLTreeParam::ElementDefault)
505 : {
506 : // Check recursively.
507 0 : if (IsChildrenDirty(pChild))
508 0 : return true;
509 : }
510 : }
511 :
512 0 : return false;
513 : }
514 :
515 : namespace {
516 :
517 : /**
518 : * Pick only the leaf elements.
519 : */
520 0 : void getFieldLinks(
521 : ScOrcusImportXMLParam::RangeLink& rRangeLink, std::vector<size_t>& rNamespaces,
522 : const SvTreeListBox& rTree, const SvTreeListEntry& rEntry)
523 : {
524 0 : const SvTreeListEntries& rChildren = rEntry.GetChildEntries();
525 0 : if (rChildren.empty())
526 : // No more children. We're done.
527 0 : return;
528 :
529 0 : SvTreeListEntries::const_iterator it = rChildren.begin(), itEnd = rChildren.end();
530 0 : for (; it != itEnd; ++it)
531 : {
532 0 : const SvTreeListEntry& rChild = *it;
533 0 : OUString aPath = getXPath(rTree, rChild, rNamespaces);
534 0 : const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rChild);
535 :
536 0 : if (pUserData && pUserData->mbLeafNode)
537 : {
538 0 : if (!aPath.isEmpty())
539 : // XPath should never be empty anyway, but it won't hurt to check...
540 0 : rRangeLink.maFieldPaths.push_back(OUStringToOString(aPath, RTL_TEXTENCODING_UTF8));
541 : }
542 :
543 : // Walk recursively.
544 0 : getFieldLinks(rRangeLink, rNamespaces, rTree, rChild);
545 0 : }
546 : }
547 :
548 0 : void removeDuplicates(std::vector<size_t>& rArray)
549 : {
550 0 : std::sort(rArray.begin(), rArray.end());
551 0 : std::vector<size_t>::iterator it = std::unique(rArray.begin(), rArray.end());
552 0 : rArray.erase(it, rArray.end());
553 0 : }
554 :
555 : }
556 :
557 0 : void ScXMLSourceDlg::OkPressed()
558 : {
559 0 : if (!mpXMLContext)
560 0 : return;
561 :
562 : // Begin import.
563 :
564 0 : ScOrcusImportXMLParam aParam;
565 :
566 : // Convert single cell links.
567 : {
568 0 : std::set<const SvTreeListEntry*>::const_iterator it = maCellLinks.begin(), itEnd = maCellLinks.end();
569 0 : for (; it != itEnd; ++it)
570 : {
571 0 : const SvTreeListEntry& rEntry = **it;
572 0 : OUString aPath = getXPath(maLbTree, rEntry, aParam.maNamespaces);
573 0 : const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rEntry);
574 :
575 : aParam.maCellLinks.push_back(
576 : ScOrcusImportXMLParam::CellLink(
577 0 : pUserData->maLinkedPos, OUStringToOString(aPath, RTL_TEXTENCODING_UTF8)));
578 0 : }
579 : }
580 :
581 : // Convert range links. For now, an element with range link takes all its
582 : // child elements as its fields.
583 : {
584 0 : std::set<const SvTreeListEntry*>::const_iterator it = maRangeLinks.begin(), itEnd = maRangeLinks.end();
585 0 : for (; it != itEnd; ++it)
586 : {
587 0 : const SvTreeListEntry& rEntry = **it;
588 0 : const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rEntry);
589 :
590 0 : ScOrcusImportXMLParam::RangeLink aRangeLink;
591 0 : aRangeLink.maPos = pUserData->maLinkedPos;
592 :
593 : // Go through all its child elements.
594 0 : getFieldLinks(aRangeLink, aParam.maNamespaces, maLbTree, rEntry);
595 :
596 0 : aParam.maRangeLinks.push_back(aRangeLink);
597 0 : }
598 : }
599 :
600 : // Remove duplicate namespace IDs.
601 0 : removeDuplicates(aParam.maNamespaces);
602 :
603 : // Now do the import.
604 0 : mpXMLContext->importXML(aParam);
605 :
606 : // Don't forget to broadcast the change.
607 0 : SfxObjectShell* pShell = mpDoc->GetDocumentShell();
608 0 : pShell->Broadcast(SfxSimpleHint(FID_DATACHANGED));
609 :
610 : // Repaint the grid to force repaint the cell values.
611 0 : ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
612 0 : if (pViewShell)
613 0 : pViewShell->PaintGrid();
614 :
615 0 : Close();
616 : }
617 :
618 0 : void ScXMLSourceDlg::CancelPressed()
619 : {
620 0 : Close();
621 0 : }
622 :
623 0 : void ScXMLSourceDlg::RefEditModified()
624 : {
625 0 : OUString aRefStr = maRefEdit.GetText();
626 :
627 : // Check if the address is valid.
628 0 : ScAddress aLinkedPos;
629 0 : sal_uInt16 nRes = aLinkedPos.Parse(aRefStr, mpDoc, mpDoc->GetAddressConvention());
630 0 : bool bValid = (nRes & SCA_VALID) == SCA_VALID;
631 :
632 : // TODO: For some unknown reason, setting the ref invalid will hide the text altogether.
633 : // Find out how to make this work.
634 : // maRefEdit.SetRefValid(bValid);
635 :
636 0 : if (!bValid)
637 0 : aLinkedPos.SetInvalid();
638 :
639 : // Set this address to the current reference entry.
640 0 : if (!mpCurRefEntry)
641 : // This should never happen.
642 0 : return;
643 :
644 0 : ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(*mpCurRefEntry);
645 0 : if (!pUserData)
646 : // This should never happen either.
647 0 : return;
648 :
649 0 : bool bRepeatElem = pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat;
650 0 : pUserData->maLinkedPos = aLinkedPos;
651 0 : pUserData->mbRangeParent = aLinkedPos.IsValid() && bRepeatElem;
652 :
653 0 : if (bRepeatElem)
654 : {
655 0 : if (bValid)
656 0 : maRangeLinks.insert(mpCurRefEntry);
657 : else
658 0 : maRangeLinks.erase(mpCurRefEntry);
659 : }
660 : else
661 : {
662 0 : if (bValid)
663 0 : maCellLinks.insert(mpCurRefEntry);
664 : else
665 0 : maCellLinks.erase(mpCurRefEntry);
666 : }
667 :
668 : // Enable the import button only when at least one link exists.
669 0 : bool bHasLink = !maCellLinks.empty() || !maRangeLinks.empty();
670 0 : maBtnOk.Enable(bHasLink);
671 : }
672 :
673 0 : IMPL_LINK(ScXMLSourceDlg, GetFocusHdl, Control*, pCtrl)
674 : {
675 0 : HandleGetFocus(pCtrl);
676 0 : return 0;
677 : }
678 :
679 0 : IMPL_LINK(ScXMLSourceDlg, LoseFocusHdl, Control*, pCtrl)
680 : {
681 0 : HandleLoseFocus(pCtrl);
682 0 : return 0;
683 : }
684 :
685 0 : IMPL_LINK(ScXMLSourceDlg, BtnPressedHdl, Button*, pBtn)
686 : {
687 0 : if (pBtn == &maBtnSelectSource)
688 0 : SelectSourceFile();
689 0 : else if (pBtn == &maBtnOk)
690 0 : OkPressed();
691 0 : else if (pBtn == &maBtnCancel)
692 0 : CancelPressed();
693 0 : return 0;
694 : }
695 :
696 0 : IMPL_LINK_NOARG(ScXMLSourceDlg, TreeItemSelectHdl)
697 : {
698 0 : TreeItemSelected();
699 0 : return 0;
700 : }
701 :
702 0 : IMPL_LINK_NOARG(ScXMLSourceDlg, RefModifiedHdl)
703 : {
704 0 : RefEditModified();
705 0 : return 0;
706 93 : }
707 :
708 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|