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