Coverage Report

Created: 2026-06-30 11:14

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