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