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  * This file incorporates work covered by the following license notice:
10  */
11 
12 #include <PivotLayoutTreeList.hxx>
13 #include <PivotLayoutDialog.hxx>
14 #include <reffact.hxx>
15 
16 #include <rangeutl.hxx>
17 #include <uiitems.hxx>
18 #include <dputil.hxx>
19 #include <dbdocfun.hxx>
20 #include <dpsave.hxx>
21 #include <dpshttab.hxx>
22 #include <scmod.hxx>
23 
24 #include <memory>
25 #include <vector>
26 
27 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
28 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
29 
30 using namespace css::uno;
31 using namespace css::sheet;
32 
ScItemValue(OUString const & aName,SCCOL nColumn,PivotFunc nFunctionMask)33 ScItemValue::ScItemValue(OUString const & aName, SCCOL nColumn, PivotFunc nFunctionMask) :
34     maName(aName),
35     maFunctionData(nColumn, nFunctionMask),
36     mpOriginalItemValue(this)
37 {}
38 
ScItemValue(const ScItemValue * pInputItemValue)39 ScItemValue::ScItemValue(const ScItemValue* pInputItemValue) :
40     maName(pInputItemValue->maName),
41     maFunctionData(pInputItemValue->maFunctionData),
42     mpOriginalItemValue(this)
43 {}
44 
~ScItemValue()45 ScItemValue::~ScItemValue()
46 {}
47 
48 namespace
49 {
50 
lclGetRangeForNamedRange(OUString const & aName,const ScDocument & rDocument)51 ScRange lclGetRangeForNamedRange(OUString const & aName, const ScDocument& rDocument)
52 {
53     ScRange aInvalidRange(ScAddress::INITIALIZE_INVALID);
54     ScRangeName* pRangeName = rDocument.GetRangeName();
55     if (pRangeName == nullptr)
56         return aInvalidRange;
57 
58     const ScRangeData* pData = pRangeName->findByUpperName(aName.toAsciiUpperCase());
59     if (pData == nullptr)
60         return aInvalidRange;
61 
62     ScRange aRange;
63     if (pData->IsReference(aRange))
64         return aRange;
65 
66     return aInvalidRange;
67 }
68 
69 }
70 
ScPivotLayoutDialog(SfxBindings * pSfxBindings,SfxChildWindow * pChildWindow,weld::Window * pParent,ScViewData * pViewData,const ScDPObject * pPivotTableObject,bool bNewPivotTable)71 ScPivotLayoutDialog::ScPivotLayoutDialog(
72                             SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, weld::Window* pParent,
73                             ScViewData* pViewData, const ScDPObject* pPivotTableObject, bool bNewPivotTable)
74     : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, "modules/scalc/ui/pivottablelayoutdialog.ui", "PivotTableLayout")
75     , maPivotTableObject(*pPivotTableObject)
76     , mpPreviouslyFocusedListBox(nullptr)
77     , mpViewData(pViewData)
78     , mrDocument(pViewData->GetDocument())
79     , mbNewPivotTable(bNewPivotTable)
80     , maAddressDetails(mrDocument.GetAddressConvention(), 0, 0)
81     , mbDialogLostFocus(false)
82     , mpActiveEdit(nullptr)
83     , mxListBoxField(new ScPivotLayoutTreeListLabel(m_xBuilder->weld_tree_view("listbox-fields")))
84     , mxListBoxPage(new ScPivotLayoutTreeList(m_xBuilder->weld_tree_view("listbox-page")))
85     , mxListBoxColumn(new ScPivotLayoutTreeList(m_xBuilder->weld_tree_view("listbox-column")))
86     , mxListBoxRow(new ScPivotLayoutTreeList(m_xBuilder->weld_tree_view("listbox-row")))
87     , mxListBoxData(new ScPivotLayoutTreeListData(m_xBuilder->weld_tree_view("listbox-data")))
88     , mxCheckIgnoreEmptyRows(m_xBuilder->weld_check_button("check-ignore-empty-rows"))
89     , mxCheckTotalColumns(m_xBuilder->weld_check_button("check-total-columns"))
90     , mxCheckAddFilter(m_xBuilder->weld_check_button("check-add-filter"))
91     , mxCheckIdentifyCategories(m_xBuilder->weld_check_button("check-identify-categories"))
92     , mxCheckTotalRows(m_xBuilder->weld_check_button("check-total-rows"))
93     , mxCheckDrillToDetail(m_xBuilder->weld_check_button("check-drill-to-details"))
94     , mxSourceRadioNamedRange(m_xBuilder->weld_radio_button("source-radio-named-range"))
95     , mxSourceRadioSelection(m_xBuilder->weld_radio_button("source-radio-selection"))
96     , mxSourceListBox(m_xBuilder->weld_combo_box("source-list"))
97     , mxSourceEdit(new formula::RefEdit(m_xBuilder->weld_entry("source-edit")))
98     , mxSourceButton(new formula::RefButton(m_xBuilder->weld_button("source-button")))
99     , mxDestinationRadioNewSheet(m_xBuilder->weld_radio_button("destination-radio-new-sheet"))
100     , mxDestinationRadioNamedRange(m_xBuilder->weld_radio_button("destination-radio-named-range"))
101     , mxDestinationRadioSelection(m_xBuilder->weld_radio_button("destination-radio-selection"))
102     , mxDestinationListBox(m_xBuilder->weld_combo_box("destination-list"))
103     , mxDestinationEdit(new formula::RefEdit(m_xBuilder->weld_entry("destination-edit")))
104     , mxDestinationButton(new formula::RefButton(m_xBuilder->weld_button("destination-button")))
105     , mxBtnOK(m_xBuilder->weld_button("ok"))
106     , mxBtnCancel(m_xBuilder->weld_button("cancel"))
107     , mxSourceFrame(m_xBuilder->weld_frame("frame2"))
108     , mxSourceLabel(mxSourceFrame->weld_label_widget())
109     , mxDestFrame(m_xBuilder->weld_frame("frame1"))
110     , mxDestLabel(mxDestFrame->weld_label_widget())
111     , mxOptions(m_xBuilder->weld_expander("options"))
112     , mxMore(m_xBuilder->weld_expander("more"))
113 {
114     // Source UI
115     Link<weld::Toggleable&,void> aLink2 = LINK(this, ScPivotLayoutDialog, ToggleSource);
116     mxSourceRadioNamedRange->connect_toggled(aLink2);
117     mxSourceRadioSelection->connect_toggled(aLink2);
118 
119     mxSourceEdit->SetReferences(this, mxSourceLabel.get());
120     mxSourceButton->SetReferences(this, mxSourceEdit.get());
121 
122     Link<formula::RefEdit&,void> aEditLink = LINK(this, ScPivotLayoutDialog, GetEditFocusHandler);
123     mxDestinationEdit->SetGetFocusHdl(aEditLink);
124     mxSourceEdit->SetGetFocusHdl(aEditLink);
125 
126     aEditLink = LINK(this, ScPivotLayoutDialog, LoseEditFocusHandler);
127     mxDestinationEdit->SetLoseFocusHdl(aEditLink);
128     mxSourceEdit->SetLoseFocusHdl(aEditLink);
129 
130     mxSourceEdit->SetModifyHdl(LINK(this, ScPivotLayoutDialog, SourceEditModified));
131     mxSourceListBox->connect_changed(LINK(this, ScPivotLayoutDialog, SourceListSelected));
132 
133     // Destination UI
134     aLink2 = LINK(this, ScPivotLayoutDialog, ToggleDestination);
135     mxDestinationRadioNewSheet->connect_toggled(aLink2);
136     mxDestinationRadioNamedRange->connect_toggled(aLink2);
137     mxDestinationRadioSelection->connect_toggled(aLink2);
138 
139     mxDestinationEdit->SetReferences(this, mxDestLabel.get());
140     mxDestinationButton->SetReferences(this, mxDestinationEdit.get());
141 
142     Link<formula::RefButton&,void> aButtonLink = LINK(this, ScPivotLayoutDialog, GetButtonFocusHandler);
143     mxSourceButton->SetGetFocusHdl(aButtonLink);
144     mxDestinationButton->SetGetFocusHdl(aButtonLink);
145 
146     aButtonLink = LINK(this, ScPivotLayoutDialog, LoseButtonFocusHandler);
147     mxSourceButton->SetLoseFocusHdl(aButtonLink);
148     mxDestinationButton->SetLoseFocusHdl(aButtonLink);
149 
150     // Buttons
151     mxBtnCancel->connect_clicked(LINK(this, ScPivotLayoutDialog, CancelClicked));
152     mxBtnOK->connect_clicked(LINK(this, ScPivotLayoutDialog, OKClicked));
153 
154     // Initialize Data
155     maPivotTableObject.FillOldParam(maPivotParameters);
156     maPivotTableObject.FillLabelData(maPivotParameters);
157 
158     mxListBoxField->Setup (this);
159     mxListBoxPage->Setup  (this, ScPivotLayoutTreeList::PAGE_LIST);
160     mxListBoxColumn->Setup(this, ScPivotLayoutTreeList::COLUMN_LIST);
161     mxListBoxRow->Setup   (this, ScPivotLayoutTreeList::ROW_LIST);
162     mxListBoxData->Setup  (this);
163 
164     FillValuesToListBoxes();
165 
166     // Initialize Options
167     const ScDPSaveData* pSaveData = maPivotTableObject.GetSaveData();
168     if (pSaveData == nullptr)
169     {
170         mxCheckAddFilter->set_active(false);
171         mxCheckDrillToDetail->set_active(false);
172     }
173     else
174     {
175         mxCheckAddFilter->set_active(pSaveData->GetFilterButton());
176         mxCheckDrillToDetail->set_active(pSaveData->GetDrillDown());
177     }
178 
179     mxCheckIgnoreEmptyRows->set_active(maPivotParameters.bIgnoreEmptyRows);
180     mxCheckIdentifyCategories->set_active(maPivotParameters.bDetectCategories);
181     mxCheckTotalColumns->set_active(maPivotParameters.bMakeTotalCol);
182     mxCheckTotalRows->set_active(maPivotParameters.bMakeTotalRow);
183 
184     SetupSource();
185     SetupDestination();
186 }
187 
~ScPivotLayoutDialog()188 ScPivotLayoutDialog::~ScPivotLayoutDialog()
189 {
190 }
191 
SetupSource()192 void ScPivotLayoutDialog::SetupSource()
193 {
194     mxSourceListBox->clear();
195 
196     ScRange aSourceRange;
197     OUString sSourceNamedRangeName;
198 
199     if (maPivotTableObject.GetSheetDesc())
200     {
201         const ScSheetSourceDesc* pSheetSourceDesc = maPivotTableObject.GetSheetDesc();
202         aSourceRange = pSheetSourceDesc->GetSourceRange();
203 
204         if(!aSourceRange.IsValid())
205         {
206             // Source is probably a DB Range
207             mxSourceRadioNamedRange->set_sensitive(false);
208             mxSourceRadioSelection->set_sensitive(false);
209             ToggleSource();
210             return;
211         }
212         else
213         {
214             OUString aSourceRangeName = aSourceRange.Format(mrDocument, ScRefFlags::RANGE_ABS_3D, maAddressDetails);
215             mxSourceEdit->SetText(aSourceRangeName);
216         }
217     }
218     else
219     {
220         mxSourceRadioNamedRange->set_sensitive(false);
221         mxSourceRadioSelection->set_sensitive(false);
222         ToggleSource();
223         return;
224     }
225 
226     // Setup Named Ranges
227     bool bIsNamedRange = false;
228 
229     ScAreaNameIterator aIterator(mrDocument);
230     OUString aEachName;
231     ScRange aEachRange;
232 
233     while (aIterator.Next(aEachName, aEachRange))
234     {
235         if (!aIterator.WasDBName())
236         {
237             mxSourceListBox->append_text(aEachName);
238             if (aEachRange == aSourceRange)
239             {
240                 sSourceNamedRangeName = aEachName;
241                 bIsNamedRange = true;
242             }
243         }
244     }
245 
246     bool bSourceBoxHasEntries = mxSourceListBox->get_count() > 0;
247 
248     if (bIsNamedRange)
249     {
250         mxSourceListBox->set_active_text(sSourceNamedRangeName);
251         mxSourceRadioNamedRange->set_active(true);
252     }
253     else
254     {
255         // If entries - select first entry
256         mxSourceListBox->set_active(bSourceBoxHasEntries ? 0 : -1);
257         mxSourceRadioSelection->set_active(true);
258     }
259 
260     // If no entries disable the radio button.
261     if (!bSourceBoxHasEntries)
262         mxSourceRadioNamedRange->set_sensitive(false);
263 
264     ToggleSource();
265 }
266 
SetupDestination()267 void ScPivotLayoutDialog::SetupDestination()
268 {
269     mxDestinationListBox->clear();
270 
271     // Fill up named ranges
272     ScAreaNameIterator aIterator(mrDocument);
273     OUString aName;
274     ScRange aRange;
275 
276     while (aIterator.Next(aName, aRange))
277     {
278         if (!aIterator.WasDBName())
279         {
280             mxDestinationListBox->append_text(aName);
281         }
282     }
283 
284     // If entries - select first entry, otherwise disable the radio button.
285     if (mxDestinationListBox->get_count() > 0)
286         mxDestinationListBox->set_active(0);
287     else
288         mxDestinationRadioNamedRange->set_sensitive(false);
289 
290     //
291     if (mbNewPivotTable)
292     {
293         mxDestinationRadioNewSheet->set_active(true);
294     }
295     else
296     {
297         if (maPivotParameters.nTab != MAXTAB + 1)
298         {
299             ScAddress aAddress(maPivotParameters.nCol, maPivotParameters.nRow, maPivotParameters.nTab);
300             OUString aAddressString = aAddress.Format(ScRefFlags::ADDR_ABS_3D, &mrDocument, maAddressDetails);
301             mxDestinationEdit->SetText(aAddressString);
302             mxDestinationRadioSelection->set_active(true);
303         }
304     }
305 
306     ToggleDestination();
307 }
308 
FillValuesToListBoxes()309 void ScPivotLayoutDialog::FillValuesToListBoxes()
310 {
311     mxListBoxField->FillLabelFields(maPivotParameters.maLabelArray);
312     mxListBoxData->FillDataField(maPivotParameters.maDataFields);
313     mxListBoxColumn->FillFields(maPivotParameters.maColFields);
314     mxListBoxRow->FillFields(maPivotParameters.maRowFields);
315     mxListBoxPage->FillFields(maPivotParameters.maPageFields);
316 }
317 
SetActive()318 void ScPivotLayoutDialog::SetActive()
319 {
320     if (mbDialogLostFocus)
321     {
322         mbDialogLostFocus = false;
323         if(mpActiveEdit != nullptr)
324         {
325             mpActiveEdit->GrabFocus();
326             if (mpActiveEdit == mxSourceEdit.get())
327                 UpdateSourceRange();
328         }
329     }
330     else
331     {
332         m_xDialog->grab_focus();
333     }
334 
335     RefInputDone();
336 }
337 
SetReference(const ScRange & rReferenceRange,ScDocument & rDocument)338 void ScPivotLayoutDialog::SetReference(const ScRange& rReferenceRange, ScDocument& rDocument)
339 {
340     if (!mbDialogLostFocus)
341         return;
342 
343     if (mpActiveEdit == nullptr)
344         return;
345 
346     if (rReferenceRange.aStart != rReferenceRange.aEnd)
347         RefInputStart(mpActiveEdit);
348 
349     OUString aReferenceString = rReferenceRange.Format(rDocument, ScRefFlags::RANGE_ABS_3D, maAddressDetails);
350 
351     if (mpActiveEdit == mxSourceEdit.get())
352     {
353         mxSourceEdit->SetRefString(aReferenceString);
354     }
355     else if (mpActiveEdit == mxDestinationEdit.get())
356     {
357         mxDestinationEdit->SetRefString(aReferenceString);
358     }
359 }
360 
IsRefInputMode() const361 bool ScPivotLayoutDialog::IsRefInputMode() const
362 {
363     return mbDialogLostFocus;
364 }
365 
ItemInserted(const ScItemValue * pItemValue,ScPivotLayoutTreeList::SvPivotTreeListType eType)366 void ScPivotLayoutDialog::ItemInserted(const ScItemValue* pItemValue, ScPivotLayoutTreeList::SvPivotTreeListType eType)
367 {
368     if (pItemValue == nullptr)
369         return;
370 
371     switch (eType)
372     {
373         case ScPivotLayoutTreeList::ROW_LIST:
374         case ScPivotLayoutTreeList::COLUMN_LIST:
375         case ScPivotLayoutTreeList::PAGE_LIST:
376         {
377             mxListBoxRow->RemoveEntryForItem(pItemValue);
378             mxListBoxColumn->RemoveEntryForItem(pItemValue);
379             mxListBoxPage->RemoveEntryForItem(pItemValue);
380         }
381         break;
382         case ScPivotLayoutTreeList::LABEL_LIST:
383         {
384             mxListBoxRow->RemoveEntryForItem(pItemValue);
385             mxListBoxColumn->RemoveEntryForItem(pItemValue);
386             mxListBoxPage->RemoveEntryForItem(pItemValue);
387             mxListBoxData->RemoveEntryForItem(pItemValue);
388         }
389         break;
390         default:
391             break;
392     }
393 }
394 
UpdateSourceRange()395 void ScPivotLayoutDialog::UpdateSourceRange()
396 {
397     if (!maPivotTableObject.GetSheetDesc())
398        return;
399 
400     ScSheetSourceDesc aSourceSheet = *maPivotTableObject.GetSheetDesc();
401 
402     if (mxSourceRadioNamedRange->get_active())
403     {
404         OUString aEntryString = mxSourceListBox->get_active_text();
405         ScRange aSourceRange = lclGetRangeForNamedRange(aEntryString, mrDocument);
406         if (!aSourceRange.IsValid() || aSourceSheet.GetSourceRange() == aSourceRange)
407             return;
408         aSourceSheet.SetRangeName(aEntryString);
409     }
410     else if (mxSourceRadioSelection->get_active())
411     {
412         OUString aSourceString = mxSourceEdit->GetText();
413         ScRange aSourceRange;
414         ScRefFlags nResult = aSourceRange.Parse(aSourceString, mrDocument, maAddressDetails);
415 
416         bool bIsValid = (nResult & ScRefFlags::VALID) == ScRefFlags::VALID; // aSourceString is valid
417 
418         mxSourceEdit->SetRefValid(true);
419 
420         if (bIsValid)
421         {
422             ScRefAddress aStart;
423             ScRefAddress aEnd;
424 
425             ConvertDoubleRef(mrDocument, aSourceString, 1, aStart, aEnd, maAddressDetails);
426             aSourceRange.aStart = aStart.GetAddress();
427             aSourceRange.aEnd = aEnd.GetAddress();
428         }
429         else
430         {
431             aSourceRange = lclGetRangeForNamedRange(aSourceString, mrDocument);
432         }
433 
434         if (!aSourceRange.IsValid())
435         {
436             mxSourceEdit->SetRefValid(false);
437             return;
438         }
439 
440         if (aSourceSheet.GetSourceRange() == aSourceRange)
441                 return;
442 
443         aSourceSheet.SetSourceRange(aSourceRange);
444         if (aSourceSheet.CheckSourceRange() != nullptr)
445         {
446             mxSourceEdit->SetRefValid(false);
447             return;
448         }
449     }
450     else
451     {
452         return;
453     }
454 
455     maPivotTableObject.SetSheetDesc(aSourceSheet);
456     maPivotTableObject.FillOldParam(maPivotParameters);
457     maPivotTableObject.FillLabelData(maPivotParameters);
458 
459     FillValuesToListBoxes();
460 }
461 
ApplyChanges()462 void ScPivotLayoutDialog::ApplyChanges()
463 {
464     ScDPSaveData aSaveData;
465     ApplySaveData(aSaveData);
466     ApplyLabelData(aSaveData);
467 
468     ScDPObject *pOldDPObj = mrDocument.GetDPAtCursor( maPivotParameters.nCol, maPivotParameters.nRow, maPivotParameters.nTab);
469     ScRange aDestinationRange;
470     bool bToNewSheet = false;
471 
472     if (!GetDestination(aDestinationRange, bToNewSheet))
473         return;
474 
475     SetDispatcherLock(false);
476     SwitchToDocument();
477 
478     sal_uInt16 nWhichPivot = SC_MOD()->GetPool().GetWhich(SID_PIVOT_TABLE);
479     ScPivotItem aPivotItem(nWhichPivot, &aSaveData, &aDestinationRange, bToNewSheet);
480     mpViewData->GetViewShell()->SetDialogDPObject(std::make_unique<ScDPObject>(maPivotTableObject));
481 
482 
483     SfxDispatcher* pDispatcher = GetBindings().GetDispatcher();
484     SfxCallMode const nCallMode = SfxCallMode::SLOT | SfxCallMode::RECORD;
485     const SfxPoolItem* pResult = pDispatcher->ExecuteList(SID_PIVOT_TABLE,
486             nCallMode, { &aPivotItem });
487 
488     if (pResult != nullptr)
489     {
490         // existing pivot table might have moved to a new range or a new sheet
491         if ( pOldDPObj != nullptr  )
492         {
493             const ScRange& rOldRange = pOldDPObj->GetOutRange();
494 
495             ScDPObject *pDPObj = nullptr;
496             // FIXME: if the new range overlaps with the old one, the table actually doesn't move
497             // and shouldn't therefore be deleted
498             if ( ( ( rOldRange != aDestinationRange ) && !rOldRange.In( aDestinationRange ) )
499                  || bToNewSheet )
500             {
501                 pDPObj = mrDocument.GetDPAtCursor( maPivotParameters.nCol, maPivotParameters.nRow, maPivotParameters.nTab);
502             }
503             if (pDPObj)
504             {
505                 ScDBDocFunc aFunc( *(mpViewData->GetDocShell() ));
506                 aFunc.RemovePivotTable( *pDPObj, true, false);
507                 mpViewData->GetView()->CursorPosChanged();
508             }
509         }
510         return;
511     }
512 
513     SetDispatcherLock(true);
514 }
515 
ApplySaveData(ScDPSaveData & rSaveData)516 void ScPivotLayoutDialog::ApplySaveData(ScDPSaveData& rSaveData)
517 {
518     rSaveData.SetIgnoreEmptyRows(mxCheckIgnoreEmptyRows->get_active());
519     rSaveData.SetRepeatIfEmpty(mxCheckIdentifyCategories->get_active());
520     rSaveData.SetColumnGrand(mxCheckTotalColumns->get_active());
521     rSaveData.SetRowGrand(mxCheckTotalRows->get_active());
522     rSaveData.SetFilterButton(mxCheckAddFilter->get_active());
523     rSaveData.SetDrillDown(mxCheckDrillToDetail->get_active());
524 
525     Reference<XDimensionsSupplier> xSource = maPivotTableObject.GetSource();
526 
527     ScPivotFieldVector aPageFieldVector;
528     mxListBoxPage->PushEntriesToPivotFieldVector(aPageFieldVector);
529     ScDPObject::ConvertOrientation(rSaveData, aPageFieldVector, DataPilotFieldOrientation_PAGE,
530                                    xSource, maPivotParameters.maLabelArray);
531 
532     ScPivotFieldVector aColFieldVector;
533     mxListBoxColumn->PushEntriesToPivotFieldVector(aColFieldVector);
534     ScDPObject::ConvertOrientation(rSaveData, aColFieldVector, DataPilotFieldOrientation_COLUMN,
535                                    xSource, maPivotParameters.maLabelArray);
536 
537     ScPivotFieldVector aRowFieldVector;
538     mxListBoxRow->PushEntriesToPivotFieldVector(aRowFieldVector);
539     ScDPObject::ConvertOrientation(rSaveData, aRowFieldVector, DataPilotFieldOrientation_ROW,
540                                    xSource, maPivotParameters.maLabelArray);
541 
542     ScPivotFieldVector aDataFieldVector;
543     mxListBoxData->PushEntriesToPivotFieldVector(aDataFieldVector);
544     ScDPObject::ConvertOrientation(rSaveData, aDataFieldVector, DataPilotFieldOrientation_DATA,
545                                    xSource, maPivotParameters.maLabelArray,
546                                    &aColFieldVector, &aRowFieldVector, &aPageFieldVector);
547 }
548 
ApplyLabelData(const ScDPSaveData & rSaveData)549 void ScPivotLayoutDialog::ApplyLabelData(const ScDPSaveData& rSaveData)
550 {
551     ScDPLabelDataVector& rLabelDataVector = GetLabelDataVector();
552 
553     for (std::unique_ptr<ScDPLabelData> const & pLabelData : rLabelDataVector)
554     {
555         OUString aUnoName = ScDPUtil::createDuplicateDimensionName(pLabelData->maName, pLabelData->mnDupCount);
556         ScDPSaveDimension* pSaveDimensions = rSaveData.GetExistingDimensionByName(aUnoName);
557 
558         if (pSaveDimensions == nullptr)
559             continue;
560 
561         pSaveDimensions->SetUsedHierarchy(pLabelData->mnUsedHier);
562         pSaveDimensions->SetShowEmpty(pLabelData->mbShowAll);
563         pSaveDimensions->SetRepeatItemLabels(pLabelData->mbRepeatItemLabels);
564         pSaveDimensions->SetSortInfo(&pLabelData->maSortInfo);
565         pSaveDimensions->SetLayoutInfo(&pLabelData->maLayoutInfo);
566         pSaveDimensions->SetAutoShowInfo(&pLabelData->maShowInfo);
567 
568         bool bManualSort = (pLabelData->maSortInfo.Mode == DataPilotFieldSortMode::MANUAL);
569 
570         for (ScDPLabelData::Member const & rLabelMember : pLabelData->maMembers)
571         {
572             ScDPSaveMember* pMember = pSaveDimensions->GetMemberByName(rLabelMember.maName);
573 
574             if (bManualSort || !rLabelMember.mbVisible || !rLabelMember.mbShowDetails)
575             {
576                 pMember->SetIsVisible(rLabelMember.mbVisible);
577                 pMember->SetShowDetails(rLabelMember.mbShowDetails);
578             }
579         }
580     }
581 }
582 
GetDestination(ScRange & aDestinationRange,bool & bToNewSheet)583 bool ScPivotLayoutDialog::GetDestination(ScRange& aDestinationRange, bool& bToNewSheet)
584 {
585     bToNewSheet = false;
586 
587     if (mxDestinationRadioNamedRange->get_active())
588     {
589         OUString aName = mxDestinationListBox->get_active_text();
590         aDestinationRange = lclGetRangeForNamedRange(aName, mrDocument);
591         if (!aDestinationRange.IsValid())
592             return false;
593     }
594     else if (mxDestinationRadioSelection->get_active())
595     {
596         ScAddress aAddress;
597         aAddress.Parse(mxDestinationEdit->GetText(), mrDocument, maAddressDetails);
598         aDestinationRange = ScRange(aAddress);
599     }
600     else
601     {
602         bToNewSheet = true;
603         aDestinationRange = ScRange(maPivotParameters.nCol, maPivotParameters.nRow, maPivotParameters.nTab);
604     }
605     return true;
606 }
607 
GetItem(SCCOL nColumn)608 ScItemValue* ScPivotLayoutDialog::GetItem(SCCOL nColumn)
609 {
610     return mxListBoxField->GetItem(nColumn);
611 }
612 
IsDataElement(SCCOL nColumn)613 bool ScPivotLayoutDialog::IsDataElement(SCCOL nColumn)
614 {
615     return mxListBoxField->IsDataElement(nColumn);
616 }
617 
GetLabelData(SCCOL nColumn)618 ScDPLabelData& ScPivotLayoutDialog::GetLabelData(SCCOL nColumn)
619 {
620     return *maPivotParameters.maLabelArray[nColumn];
621 }
622 
PushDataFieldNames(std::vector<ScDPName> & rDataFieldNames)623 void ScPivotLayoutDialog::PushDataFieldNames(std::vector<ScDPName>& rDataFieldNames)
624 {
625     mxListBoxData->PushDataFieldNames(rDataFieldNames);
626 }
627 
Close()628 void ScPivotLayoutDialog::Close()
629 {
630     DoClose(ScPivotLayoutWrapper::GetChildWindowId());
631     SfxDialogController::Close();
632 }
633 
IMPL_LINK_NOARG(ScPivotLayoutDialog,OKClicked,weld::Button &,void)634 IMPL_LINK_NOARG( ScPivotLayoutDialog, OKClicked, weld::Button&, void )
635 {
636     /* tdf#137726 hide so it's not a candidate to be parent of any error
637        messages that may appear because this dialog is going to disappear on
638        response(RET_OK) and the error dialog is not run in its own event loop
639        but instead async */
640     m_xDialog->hide();
641 
642     ApplyChanges();
643     m_xDialog->response(RET_OK);
644 }
645 
IMPL_LINK_NOARG(ScPivotLayoutDialog,CancelClicked,weld::Button &,void)646 IMPL_LINK_NOARG( ScPivotLayoutDialog, CancelClicked, weld::Button&, void )
647 {
648     m_xDialog->response(RET_CANCEL);
649 }
650 
IMPL_LINK(ScPivotLayoutDialog,GetEditFocusHandler,formula::RefEdit &,rCtrl,void)651 IMPL_LINK(ScPivotLayoutDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void)
652 {
653     mpActiveEdit = &rCtrl;
654     mpActiveEdit->SelectAll();
655 }
656 
IMPL_LINK(ScPivotLayoutDialog,GetButtonFocusHandler,formula::RefButton &,rCtrl,void)657 IMPL_LINK(ScPivotLayoutDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void)
658 {
659     mpActiveEdit = nullptr;
660 
661     if (&rCtrl == mxSourceButton.get())
662         mpActiveEdit = mxSourceEdit.get();
663     else if (&rCtrl == mxDestinationButton.get())
664         mpActiveEdit = mxDestinationEdit.get();
665 
666     if (mpActiveEdit)
667         mpActiveEdit->SelectAll();
668 }
669 
IMPL_LINK_NOARG(ScPivotLayoutDialog,LoseEditFocusHandler,formula::RefEdit &,void)670 IMPL_LINK_NOARG(ScPivotLayoutDialog, LoseEditFocusHandler, formula::RefEdit&, void)
671 {
672     mbDialogLostFocus = !m_xDialog->has_toplevel_focus();
673 }
674 
IMPL_LINK_NOARG(ScPivotLayoutDialog,LoseButtonFocusHandler,formula::RefButton &,void)675 IMPL_LINK_NOARG(ScPivotLayoutDialog, LoseButtonFocusHandler, formula::RefButton&, void)
676 {
677     mbDialogLostFocus = !m_xDialog->has_toplevel_focus();
678 }
679 
IMPL_LINK_NOARG(ScPivotLayoutDialog,SourceListSelected,weld::ComboBox &,void)680 IMPL_LINK_NOARG(ScPivotLayoutDialog, SourceListSelected, weld::ComboBox&, void)
681 {
682     UpdateSourceRange();
683 }
684 
IMPL_LINK_NOARG(ScPivotLayoutDialog,SourceEditModified,formula::RefEdit &,void)685 IMPL_LINK_NOARG(ScPivotLayoutDialog, SourceEditModified, formula::RefEdit&, void)
686 {
687     UpdateSourceRange();
688 }
689 
IMPL_LINK_NOARG(ScPivotLayoutDialog,ToggleSource,weld::Toggleable &,void)690 IMPL_LINK_NOARG(ScPivotLayoutDialog, ToggleSource, weld::Toggleable&, void)
691 {
692     ToggleSource();
693 }
694 
ToggleSource()695 void ScPivotLayoutDialog::ToggleSource()
696 {
697     bool bNamedRange = mxSourceRadioNamedRange->get_active();
698     bool bSelection = mxSourceRadioSelection->get_active();
699     mxSourceListBox->set_sensitive(bNamedRange);
700     mxSourceButton->GetWidget()->set_sensitive(bSelection);
701     mxSourceEdit->GetWidget()->set_sensitive(bSelection);
702     UpdateSourceRange();
703 }
704 
IMPL_LINK_NOARG(ScPivotLayoutDialog,ToggleDestination,weld::Toggleable &,void)705 IMPL_LINK_NOARG(ScPivotLayoutDialog, ToggleDestination, weld::Toggleable&, void)
706 {
707     ToggleDestination();
708 }
709 
ToggleDestination()710 void ScPivotLayoutDialog::ToggleDestination()
711 {
712     bool bNamedRange = mxDestinationRadioNamedRange->get_active();
713     bool bSelection = mxDestinationRadioSelection->get_active();
714     mxDestinationListBox->set_sensitive(bNamedRange);
715     mxDestinationButton->GetWidget()->set_sensitive(bSelection);
716     mxDestinationEdit->GetWidget()->set_sensitive(bSelection);
717 }
718 
719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
720