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