1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #undef SC_DLLIMPLEMENTATION
22 #include <pvfundlg.hxx>
24 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
25 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
26 #include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
27 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
28 #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
30 #include <osl/diagnose.h>
32 #include <scresid.hxx>
33 #include <dpobject.hxx>
35 #include <pvfundlg.hrc>
36 #include <globstr.hrc>
41 using namespace ::com::sun::star::sheet
;
43 using ::com::sun::star::uno::Sequence
;
48 /** Appends all strings from the Sequence to the list box.
50 Empty strings are replaced by a localized "(empty)" entry and inserted at
51 the specified position.
53 @return true = The passed string list contains an empty string entry.
56 bool lclFillListBox(weld::ComboBox
& rLBox
, const Sequence
< OUString
>& rStrings
)
59 for (const OUString
& str
: rStrings
)
62 rLBox
.append_text(str
);
65 rLBox
.append_text(ScResId(STR_EMPTYDATA
));
72 bool lclFillListBox(weld::ComboBox
& rLBox
, const vector
<ScDPLabelData::Member
>& rMembers
, int nEmptyPos
)
75 vector
<ScDPLabelData::Member
>::const_iterator itr
= rMembers
.begin(), itrEnd
= rMembers
.end();
76 for (; itr
!= itrEnd
; ++itr
)
78 OUString aName
= itr
->getDisplayName();
80 rLBox
.append_text(aName
);
83 rLBox
.insert_text(nEmptyPos
, ScResId(STR_EMPTYDATA
));
90 bool lclFillListBox(weld::TreeView
& rLBox
, const vector
<ScDPLabelData::Member
>& rMembers
)
93 for (const auto& rMember
: rMembers
)
96 int pos
= rLBox
.n_children() - 1;
97 rLBox
.set_toggle(pos
, TRISTATE_FALSE
);
98 OUString aName
= rMember
.getDisplayName();
100 rLBox
.set_text(pos
, aName
, 0);
103 rLBox
.set_text(pos
, ScResId(STR_EMPTYDATA
), 0);
110 /** This table represents the order of the strings in the resource string array. */
111 const PivotFunc spnFunctions
[] =
127 const sal_uInt16 SC_BASEITEM_PREV_POS
= 0;
128 const sal_uInt16 SC_BASEITEM_NEXT_POS
= 1;
129 const sal_uInt16 SC_BASEITEM_USER_POS
= 2;
131 const sal_uInt16 SC_SORTNAME_POS
= 0;
132 const sal_uInt16 SC_SORTDATA_POS
= 1;
134 const tools::Long SC_SHOW_DEFAULT
= 10;
138 ScDPFunctionListBox::ScDPFunctionListBox(std::unique_ptr
<weld::TreeView
> xControl
)
139 : m_xControl(std::move(xControl
))
144 void ScDPFunctionListBox::SetSelection( PivotFunc nFuncMask
)
146 if( (nFuncMask
== PivotFunc::NONE
) || (nFuncMask
== PivotFunc::Auto
) )
147 m_xControl
->unselect_all();
150 for( sal_Int32 nEntry
= 0, nCount
= m_xControl
->n_children(); nEntry
< nCount
; ++nEntry
)
152 if (bool(nFuncMask
& spnFunctions
[ nEntry
]))
153 m_xControl
->select(nEntry
);
155 m_xControl
->unselect(nEntry
);
160 PivotFunc
ScDPFunctionListBox::GetSelection() const
162 PivotFunc nFuncMask
= PivotFunc::NONE
;
163 std::vector
<int> aRows
= m_xControl
->get_selected_rows();
164 for (int nSel
: aRows
)
165 nFuncMask
|= spnFunctions
[nSel
];
169 void ScDPFunctionListBox::FillFunctionNames()
171 OSL_ENSURE( !m_xControl
->n_children(), "ScDPMultiFuncListBox::FillFunctionNames - do not add texts to resource" );
173 m_xControl
->freeze();
174 for (size_t nIndex
= 0; nIndex
< SAL_N_ELEMENTS(SCSTR_DPFUNCLISTBOX
); ++nIndex
)
175 m_xControl
->append_text(ScResId(SCSTR_DPFUNCLISTBOX
[nIndex
]));
177 assert(m_xControl
->n_children() == SAL_N_ELEMENTS(spnFunctions
));
182 int FromDataPilotFieldReferenceType(int eMode
)
186 case DataPilotFieldReferenceType::NONE
:
188 case DataPilotFieldReferenceType::ITEM_DIFFERENCE
:
190 case DataPilotFieldReferenceType::ITEM_PERCENTAGE
:
192 case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE
:
194 case DataPilotFieldReferenceType::RUNNING_TOTAL
:
196 case DataPilotFieldReferenceType::ROW_PERCENTAGE
:
198 case DataPilotFieldReferenceType::COLUMN_PERCENTAGE
:
200 case DataPilotFieldReferenceType::TOTAL_PERCENTAGE
:
202 case DataPilotFieldReferenceType::INDEX
:
208 int ToDataPilotFieldReferenceType(int nPos
)
213 return DataPilotFieldReferenceType::NONE
;
215 return DataPilotFieldReferenceType::ITEM_DIFFERENCE
;
217 return DataPilotFieldReferenceType::ITEM_PERCENTAGE
;
219 return DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE
;
221 return DataPilotFieldReferenceType::RUNNING_TOTAL
;
223 return DataPilotFieldReferenceType::ROW_PERCENTAGE
;
225 return DataPilotFieldReferenceType::COLUMN_PERCENTAGE
;
227 return DataPilotFieldReferenceType::TOTAL_PERCENTAGE
;
229 return DataPilotFieldReferenceType::INDEX
;
231 return DataPilotFieldReferenceType::NONE
;
236 ScDPFunctionDlg::ScDPFunctionDlg(
237 weld::Widget
* pParent
, const ScDPLabelDataVector
& rLabelVec
,
238 const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
)
239 : GenericDialogController(pParent
, "modules/scalc/ui/datafielddialog.ui", "DataFieldDialog")
240 , mxLbFunc(new ScDPFunctionListBox(m_xBuilder
->weld_tree_view("functions")))
241 , mxFtName(m_xBuilder
->weld_label("name"))
242 , mxLbType(m_xBuilder
->weld_combo_box("type"))
243 , mxFtBaseField(m_xBuilder
->weld_label("basefieldft"))
244 , mxLbBaseField(m_xBuilder
->weld_combo_box("basefield"))
245 , mxFtBaseItem(m_xBuilder
->weld_label("baseitemft"))
246 , mxLbBaseItem(m_xBuilder
->weld_combo_box("baseitem"))
247 , mxBtnOk(m_xBuilder
->weld_button("ok"))
248 , mxBtnCancel(m_xBuilder
->weld_button("cancel"))
249 , mrLabelVec(rLabelVec
)
252 mxLbFunc
->set_size_request(-1, mxLbFunc
->get_height_rows(8));
254 Init(rLabelData
, rFuncData
);
257 ScDPFunctionDlg::~ScDPFunctionDlg()
261 PivotFunc
ScDPFunctionDlg::GetFuncMask() const
263 return mxLbFunc
->GetSelection();
266 DataPilotFieldReference
ScDPFunctionDlg::GetFieldRef() const
268 DataPilotFieldReference aRef
;
270 aRef
.ReferenceType
= ToDataPilotFieldReferenceType(mxLbType
->get_active());
271 aRef
.ReferenceField
= GetBaseFieldName(mxLbBaseField
->get_active_text());
273 sal_Int32 nBaseItemPos
= mxLbBaseItem
->get_active();
274 switch( nBaseItemPos
)
276 case SC_BASEITEM_PREV_POS
:
277 aRef
.ReferenceItemType
= DataPilotFieldReferenceItemType::PREVIOUS
;
279 case SC_BASEITEM_NEXT_POS
:
280 aRef
.ReferenceItemType
= DataPilotFieldReferenceItemType::NEXT
;
284 aRef
.ReferenceItemType
= DataPilotFieldReferenceItemType::NAMED
;
285 if( !mbEmptyItem
|| (nBaseItemPos
> SC_BASEITEM_USER_POS
) )
286 aRef
.ReferenceItemName
= GetBaseItemName(mxLbBaseItem
->get_active_text());
293 void ScDPFunctionDlg::Init( const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
)
295 mxBtnOk
->connect_clicked( LINK( this, ScDPFunctionDlg
, ButtonClicked
) );
296 mxBtnCancel
->connect_clicked( LINK( this, ScDPFunctionDlg
, ButtonClicked
) );
299 PivotFunc nFuncMask
= (rFuncData
.mnFuncMask
== PivotFunc::NONE
) ? PivotFunc::Sum
: rFuncData
.mnFuncMask
;
300 mxLbFunc
->SetSelection( nFuncMask
);
303 mxFtName
->set_label(rLabelData
.getDisplayName());
306 mxLbFunc
->connect_row_activated( LINK( this, ScDPFunctionDlg
, DblClickHdl
) );
307 mxLbType
->connect_changed( LINK( this, ScDPFunctionDlg
, SelectHdl
) );
308 mxLbBaseField
->connect_changed( LINK( this, ScDPFunctionDlg
, SelectHdl
) );
310 // base field list box
311 OUString aSelectedEntry
;
312 for( const auto& rxLabel
: mrLabelVec
)
314 mxLbBaseField
->append_text(rxLabel
->getDisplayName());
315 maBaseFieldNameMap
.emplace(rxLabel
->getDisplayName(), rxLabel
->maName
);
316 if (rxLabel
->maName
== rFuncData
.maFieldRef
.ReferenceField
)
317 aSelectedEntry
= rxLabel
->getDisplayName();
320 // select field reference type
321 mxLbType
->set_active(FromDataPilotFieldReferenceType(rFuncData
.maFieldRef
.ReferenceType
));
322 SelectHdl( *mxLbType
); // enables base field/item list boxes
325 mxLbBaseField
->set_active_text(aSelectedEntry
);
326 if (mxLbBaseField
->get_active() == -1)
327 mxLbBaseField
->set_active(0);
328 SelectHdl( *mxLbBaseField
); // fills base item list, selects base item
331 switch( rFuncData
.maFieldRef
.ReferenceItemType
)
333 case DataPilotFieldReferenceItemType::PREVIOUS
:
334 mxLbBaseItem
->set_active( SC_BASEITEM_PREV_POS
);
336 case DataPilotFieldReferenceItemType::NEXT
:
337 mxLbBaseItem
->set_active( SC_BASEITEM_NEXT_POS
);
341 if( mbEmptyItem
&& rFuncData
.maFieldRef
.ReferenceItemName
.isEmpty() )
343 // select special "(empty)" entry added before other items
344 mxLbBaseItem
->set_active( SC_BASEITEM_USER_POS
);
348 sal_Int32 nStartPos
= mbEmptyItem
? (SC_BASEITEM_USER_POS
+ 1) : SC_BASEITEM_USER_POS
;
349 sal_Int32 nPos
= FindBaseItemPos( rFuncData
.maFieldRef
.ReferenceItemName
, nStartPos
);
351 nPos
= (mxLbBaseItem
->get_count() > SC_BASEITEM_USER_POS
) ? SC_BASEITEM_USER_POS
: SC_BASEITEM_PREV_POS
;
352 mxLbBaseItem
->set_active( nPos
);
358 const OUString
& ScDPFunctionDlg::GetBaseFieldName(const OUString
& rLayoutName
) const
360 NameMapType::const_iterator itr
= maBaseFieldNameMap
.find(rLayoutName
);
361 return itr
== maBaseFieldNameMap
.end() ? rLayoutName
: itr
->second
;
364 const OUString
& ScDPFunctionDlg::GetBaseItemName(const OUString
& rLayoutName
) const
366 NameMapType::const_iterator itr
= maBaseItemNameMap
.find(rLayoutName
);
367 return itr
== maBaseItemNameMap
.end() ? rLayoutName
: itr
->second
;
370 sal_Int32
ScDPFunctionDlg::FindBaseItemPos( std::u16string_view rEntry
, sal_Int32 nStartPos
) const
372 sal_Int32 nPos
= nStartPos
;
374 while (nPos
< mxLbBaseItem
->get_count())
376 // translate the displayed field name back to its original field name.
377 const OUString
& rInName
= mxLbBaseItem
->get_text(nPos
);
378 const OUString
& rName
= GetBaseItemName(rInName
);
386 return bFound
? nPos
: -1;
389 IMPL_LINK( ScDPFunctionDlg
, SelectHdl
, weld::ComboBox
&, rLBox
, void )
391 if (&rLBox
== mxLbType
.get())
393 bool bEnableField
, bEnableItem
;
394 switch (ToDataPilotFieldReferenceType(mxLbType
->get_active()))
396 case DataPilotFieldReferenceType::ITEM_DIFFERENCE
:
397 case DataPilotFieldReferenceType::ITEM_PERCENTAGE
:
398 case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE
:
399 bEnableField
= bEnableItem
= true;
402 case DataPilotFieldReferenceType::RUNNING_TOTAL
:
408 bEnableField
= bEnableItem
= false;
411 bEnableField
&= (mxLbBaseField
->get_count() > 0);
412 mxFtBaseField
->set_sensitive( bEnableField
);
413 mxLbBaseField
->set_sensitive( bEnableField
);
415 bEnableItem
&= bEnableField
;
416 mxFtBaseItem
->set_sensitive( bEnableItem
);
417 mxLbBaseItem
->set_sensitive( bEnableItem
);
419 else if (&rLBox
== mxLbBaseField
.get())
421 // keep "previous" and "next" entries
422 while (mxLbBaseItem
->get_count() > SC_BASEITEM_USER_POS
)
423 mxLbBaseItem
->remove(SC_BASEITEM_USER_POS
);
425 // update item list for current base field
427 size_t nBasePos
= mxLbBaseField
->get_active();
428 if (nBasePos
< mrLabelVec
.size())
430 const vector
<ScDPLabelData::Member
>& rMembers
= mrLabelVec
[nBasePos
]->maMembers
;
431 mbEmptyItem
= lclFillListBox(*mxLbBaseItem
, rMembers
, SC_BASEITEM_USER_POS
);
432 // build cache for base names.
434 for (const auto& rMember
: rMembers
)
435 aMap
.emplace(rMember
.getDisplayName(), rMember
.maName
);
436 maBaseItemNameMap
.swap(aMap
);
440 sal_uInt16 nItemPos
= (mxLbBaseItem
->get_count() > SC_BASEITEM_USER_POS
) ? SC_BASEITEM_USER_POS
: SC_BASEITEM_PREV_POS
;
441 mxLbBaseItem
->set_active( nItemPos
);
445 IMPL_LINK(ScDPFunctionDlg
, ButtonClicked
, weld::Button
&, rButton
, void)
447 if (&rButton
== mxBtnOk
.get())
450 response(RET_CANCEL
);
453 IMPL_LINK_NOARG(ScDPFunctionDlg
, DblClickHdl
, weld::TreeView
&, bool)
455 m_xDialog
->response(RET_OK
);
459 ScDPSubtotalDlg::ScDPSubtotalDlg(weld::Widget
* pParent
, ScDPObject
& rDPObj
,
460 const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
,
461 const ScDPNameVec
& rDataFields
, bool bEnableLayout
)
462 : GenericDialogController(pParent
, "modules/scalc/ui/pivotfielddialog.ui", "PivotFieldDialog")
464 , mrDataFields(rDataFields
)
465 , maLabelData(rLabelData
)
466 , mbEnableLayout(bEnableLayout
)
467 , mxRbNone(m_xBuilder
->weld_radio_button("none"))
468 , mxRbAuto(m_xBuilder
->weld_radio_button("auto"))
469 , mxRbUser(m_xBuilder
->weld_radio_button("user"))
470 , mxLbFunc(new ScDPFunctionListBox(m_xBuilder
->weld_tree_view("functions")))
471 , mxFtName(m_xBuilder
->weld_label("name"))
472 , mxCbShowAll(m_xBuilder
->weld_check_button("showall"))
473 , mxBtnOk(m_xBuilder
->weld_button("ok"))
474 , mxBtnCancel(m_xBuilder
->weld_button("cancel"))
475 , mxBtnOptions(m_xBuilder
->weld_button("options"))
477 mxLbFunc
->set_selection_mode(SelectionMode::Multiple
);
478 mxLbFunc
->set_size_request(-1, mxLbFunc
->get_height_rows(8));
479 Init(rLabelData
, rFuncData
);
482 ScDPSubtotalDlg::~ScDPSubtotalDlg()
487 void ScDPSubtotalDlg::CloseSubdialog()
489 if (mxOptionsDlg
&& mxOptionsDlg
->getDialog())
491 mxOptionsDlg
->getDialog()->response(RET_CANCEL
);
492 mxOptionsDlg
= nullptr;
496 PivotFunc
ScDPSubtotalDlg::GetFuncMask() const
498 PivotFunc nFuncMask
= PivotFunc::NONE
;
500 if (mxRbAuto
->get_active())
501 nFuncMask
= PivotFunc::Auto
;
502 else if (mxRbUser
->get_active())
503 nFuncMask
= mxLbFunc
->GetSelection();
508 void ScDPSubtotalDlg::FillLabelData( ScDPLabelData
& rLabelData
) const
510 rLabelData
.mnFuncMask
= GetFuncMask();
511 rLabelData
.mnUsedHier
= maLabelData
.mnUsedHier
;
512 rLabelData
.mbShowAll
= mxCbShowAll
->get_active();
513 rLabelData
.maMembers
= maLabelData
.maMembers
;
514 rLabelData
.maSortInfo
= maLabelData
.maSortInfo
;
515 rLabelData
.maLayoutInfo
= maLabelData
.maLayoutInfo
;
516 rLabelData
.maShowInfo
= maLabelData
.maShowInfo
;
517 rLabelData
.mbRepeatItemLabels
= maLabelData
.mbRepeatItemLabels
;
520 void ScDPSubtotalDlg::Init( const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
)
522 mxBtnOk
->connect_clicked( LINK( this, ScDPSubtotalDlg
, ButtonClicked
) );
523 mxBtnCancel
->connect_clicked( LINK( this, ScDPSubtotalDlg
, ButtonClicked
) );
526 mxFtName
->set_label(rLabelData
.getDisplayName());
529 mxRbNone
->connect_toggled( LINK( this, ScDPSubtotalDlg
, RadioClickHdl
) );
530 mxRbAuto
->connect_toggled( LINK( this, ScDPSubtotalDlg
, RadioClickHdl
) );
531 mxRbUser
->connect_toggled( LINK( this, ScDPSubtotalDlg
, RadioClickHdl
) );
533 weld::RadioButton
* pRBtn
= nullptr;
534 switch( rFuncData
.mnFuncMask
)
536 case PivotFunc::NONE
: pRBtn
= mxRbNone
.get(); break;
537 case PivotFunc::Auto
: pRBtn
= mxRbAuto
.get(); break;
538 default: pRBtn
= mxRbUser
.get();
540 pRBtn
->set_active(true);
541 RadioClickHdl(*pRBtn
);
544 mxLbFunc
->SetSelection( rFuncData
.mnFuncMask
);
545 mxLbFunc
->connect_row_activated( LINK( this, ScDPSubtotalDlg
, DblClickHdl
) );
548 mxCbShowAll
->set_active( rLabelData
.mbShowAll
);
551 mxBtnOptions
->connect_clicked( LINK( this, ScDPSubtotalDlg
, ClickHdl
) );
554 IMPL_LINK(ScDPSubtotalDlg
, ButtonClicked
, weld::Button
&, rButton
, void)
558 if (&rButton
== mxBtnOk
.get())
561 response(RET_CANCEL
);
564 IMPL_LINK(ScDPSubtotalDlg
, RadioClickHdl
, weld::Toggleable
&, rBtn
, void)
566 if (!rBtn
.get_active())
568 mxLbFunc
->set_sensitive(mxRbUser
->get_active());
571 IMPL_LINK_NOARG(ScDPSubtotalDlg
, DblClickHdl
, weld::TreeView
&, bool)
573 m_xDialog
->response(RET_OK
);
577 IMPL_LINK(ScDPSubtotalDlg
, ClickHdl
, weld::Button
&, rBtn
, void)
579 if (&rBtn
== mxBtnOptions
.get())
581 mxOptionsDlg
= std::make_shared
<ScDPSubtotalOptDlg
>(m_xDialog
.get(), mrDPObj
, maLabelData
, mrDataFields
, mbEnableLayout
);
583 weld::DialogController::runAsync(mxOptionsDlg
, [this](int nResult
) {
584 if (nResult
== RET_OK
)
585 mxOptionsDlg
->FillLabelData(maLabelData
);
586 mxOptionsDlg
= nullptr;
593 int FromDataPilotFieldLayoutMode(int eMode
)
597 case DataPilotFieldLayoutMode::TABULAR_LAYOUT
:
599 case DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP
:
601 case DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM
:
603 case DataPilotFieldLayoutMode::COMPACT_LAYOUT
:
609 int ToDataPilotFieldLayoutMode(int nPos
)
614 return DataPilotFieldLayoutMode::TABULAR_LAYOUT
;
616 return DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP
;
618 return DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM
;
620 return DataPilotFieldLayoutMode::COMPACT_LAYOUT
;
622 return DataPilotFieldLayoutMode::TABULAR_LAYOUT
;
625 int FromDataPilotFieldShowItemsMode(int eMode
)
629 case DataPilotFieldShowItemsMode::FROM_TOP
:
631 case DataPilotFieldShowItemsMode::FROM_BOTTOM
:
637 int ToDataPilotFieldShowItemsMode(int nPos
)
642 return DataPilotFieldShowItemsMode::FROM_TOP
;
644 return DataPilotFieldShowItemsMode::FROM_BOTTOM
;
646 return DataPilotFieldShowItemsMode::FROM_TOP
;
650 ScDPSubtotalOptDlg::ScDPSubtotalOptDlg(weld::Window
* pParent
, ScDPObject
& rDPObj
,
651 const ScDPLabelData
& rLabelData
, const ScDPNameVec
& rDataFields
,
653 : GenericDialogController(pParent
, "modules/scalc/ui/datafieldoptionsdialog.ui",
654 "DataFieldOptionsDialog")
655 , m_xLbSortBy(m_xBuilder
->weld_combo_box("sortby"))
656 , m_xRbSortAsc(m_xBuilder
->weld_radio_button("ascending"))
657 , m_xRbSortDesc(m_xBuilder
->weld_radio_button("descending"))
658 , m_xRbSortMan(m_xBuilder
->weld_radio_button("manual"))
659 , m_xLayoutFrame(m_xBuilder
->weld_widget("layoutframe"))
660 , m_xLbLayout(m_xBuilder
->weld_combo_box("layout"))
661 , m_xCbLayoutEmpty(m_xBuilder
->weld_check_button("emptyline"))
662 , m_xCbRepeatItemLabels(m_xBuilder
->weld_check_button("repeatitemlabels"))
663 , m_xCbShow(m_xBuilder
->weld_check_button("show"))
664 , m_xNfShow(m_xBuilder
->weld_spin_button("items"))
665 , m_xFtShow(m_xBuilder
->weld_label("showft"))
666 , m_xFtShowFrom(m_xBuilder
->weld_label("showfromft"))
667 , m_xLbShowFrom(m_xBuilder
->weld_combo_box("from"))
668 , m_xFtShowUsing(m_xBuilder
->weld_label("usingft"))
669 , m_xLbShowUsing(m_xBuilder
->weld_combo_box("using"))
670 , m_xHideFrame(m_xBuilder
->weld_widget("hideframe"))
671 , m_xLbHide(m_xBuilder
->weld_tree_view("hideitems"))
672 , m_xFtHierarchy(m_xBuilder
->weld_label("hierarchyft"))
673 , m_xLbHierarchy(m_xBuilder
->weld_combo_box("hierarchy"))
674 , m_xBtnOk(m_xBuilder
->weld_button("ok"))
675 , m_xBtnCancel(m_xBuilder
->weld_button("cancel"))
677 , maLabelData(rLabelData
)
679 m_xLbHide
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
681 m_xLbSortBy
->set_size_request(m_xLbSortBy
->get_approximate_digit_width() * 18, -1);
682 m_xLbHide
->set_size_request(-1, m_xLbHide
->get_height_rows(5));
683 Init(rDataFields
, bEnableLayout
);
686 ScDPSubtotalOptDlg::~ScDPSubtotalOptDlg()
690 void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData
& rLabelData
) const
694 if (m_xRbSortMan
->get_active())
695 rLabelData
.maSortInfo
.Mode
= DataPilotFieldSortMode::MANUAL
;
696 else if (m_xLbSortBy
->get_active() == SC_SORTNAME_POS
)
697 rLabelData
.maSortInfo
.Mode
= DataPilotFieldSortMode::NAME
;
699 rLabelData
.maSortInfo
.Mode
= DataPilotFieldSortMode::DATA
;
701 ScDPName aFieldName
= GetFieldName(m_xLbSortBy
->get_active_text());
702 if (!aFieldName
.maName
.isEmpty())
704 rLabelData
.maSortInfo
.Field
=
705 ScDPUtil::createDuplicateDimensionName(aFieldName
.maName
, aFieldName
.mnDupCount
);
708 if (rLabelData
.maSortInfo
.Mode
!= DataPilotFieldSortMode::MANUAL
)
709 rLabelData
.maSortInfo
.IsAscending
= m_xRbSortAsc
->get_active();
711 // *** LAYOUT MODE ***
713 rLabelData
.maLayoutInfo
.LayoutMode
= ToDataPilotFieldLayoutMode(m_xLbLayout
->get_active());
714 rLabelData
.maLayoutInfo
.AddEmptyLines
= m_xCbLayoutEmpty
->get_active();
715 rLabelData
.mbRepeatItemLabels
= m_xCbRepeatItemLabels
->get_active();
719 aFieldName
= GetFieldName(m_xLbShowUsing
->get_active_text());
720 if (!aFieldName
.maName
.isEmpty())
722 rLabelData
.maShowInfo
.IsEnabled
= m_xCbShow
->get_active();
723 rLabelData
.maShowInfo
.ShowItemsMode
= ToDataPilotFieldShowItemsMode(m_xLbShowFrom
->get_active());
724 rLabelData
.maShowInfo
.ItemCount
= sal::static_int_cast
<sal_Int32
>( m_xNfShow
->get_value() );
725 rLabelData
.maShowInfo
.DataField
=
726 ScDPUtil::createDuplicateDimensionName(aFieldName
.maName
, aFieldName
.mnDupCount
);
729 // *** HIDDEN ITEMS ***
731 rLabelData
.maMembers
= maLabelData
.maMembers
;
732 int nVisCount
= m_xLbHide
->n_children();
733 for (int nPos
= 0; nPos
< nVisCount
; ++nPos
)
734 rLabelData
.maMembers
[nPos
].mbVisible
= m_xLbHide
->get_toggle(nPos
) == TRISTATE_FALSE
;
738 rLabelData
.mnUsedHier
= m_xLbHierarchy
->get_active() != -1 ? m_xLbHierarchy
->get_active() : 0;
741 void ScDPSubtotalOptDlg::Init( const ScDPNameVec
& rDataFields
, bool bEnableLayout
)
743 m_xBtnOk
->connect_clicked(LINK(this, ScDPSubtotalOptDlg
, ButtonClicked
));
744 m_xBtnCancel
->connect_clicked(LINK(this, ScDPSubtotalOptDlg
, ButtonClicked
));
748 sal_Int32 nSortMode
= maLabelData
.maSortInfo
.Mode
;
750 // sort fields list box
751 m_xLbSortBy
->append_text(maLabelData
.getDisplayName());
753 for( const auto& rDataField
: rDataFields
)
755 // Cache names for later lookup.
756 maDataFieldNameMap
.emplace(rDataField
.maLayoutName
, rDataField
);
758 m_xLbSortBy
->append_text(rDataField
.maLayoutName
);
759 m_xLbShowUsing
->append_text(rDataField
.maLayoutName
); // for AutoShow
762 sal_Int32 nSortPos
= SC_SORTNAME_POS
;
763 if( nSortMode
== DataPilotFieldSortMode::DATA
)
765 nSortPos
= FindListBoxEntry( *m_xLbSortBy
, maLabelData
.maSortInfo
.Field
, SC_SORTDATA_POS
);
768 nSortPos
= SC_SORTNAME_POS
;
769 nSortMode
= DataPilotFieldSortMode::MANUAL
;
772 m_xLbSortBy
->set_active(nSortPos
);
774 weld::RadioButton
* pRBtn
= nullptr;
777 case DataPilotFieldSortMode::NONE
:
778 case DataPilotFieldSortMode::MANUAL
:
779 pRBtn
= m_xRbSortMan
.get();
782 pRBtn
= maLabelData
.maSortInfo
.IsAscending
? m_xRbSortAsc
.get() : m_xRbSortDesc
.get();
784 pRBtn
->set_active(true);
786 // *** LAYOUT MODE ***
788 m_xLayoutFrame
->set_sensitive(bEnableLayout
);
790 m_xLbLayout
->set_active(FromDataPilotFieldLayoutMode(maLabelData
.maLayoutInfo
.LayoutMode
));
791 m_xCbLayoutEmpty
->set_active( maLabelData
.maLayoutInfo
.AddEmptyLines
);
792 m_xCbRepeatItemLabels
->set_active( maLabelData
.mbRepeatItemLabels
);
796 m_xCbShow
->set_active( maLabelData
.maShowInfo
.IsEnabled
);
797 m_xCbShow
->connect_toggled( LINK( this, ScDPSubtotalOptDlg
, CheckHdl
) );
799 m_xLbShowFrom
->set_active(FromDataPilotFieldShowItemsMode(maLabelData
.maShowInfo
.ShowItemsMode
));
800 tools::Long nCount
= static_cast< tools::Long
>( maLabelData
.maShowInfo
.ItemCount
);
802 nCount
= SC_SHOW_DEFAULT
;
803 m_xNfShow
->set_value( nCount
);
805 // m_xLbShowUsing already filled above
806 m_xLbShowUsing
->set_active_text(maLabelData
.maShowInfo
.DataField
);
807 if (m_xLbShowUsing
->get_active() == -1)
808 m_xLbShowUsing
->set_active(0);
810 CheckHdl(*m_xCbShow
); // enable/disable dependent controls
812 // *** HIDDEN ITEMS ***
818 if( maLabelData
.maHiers
.getLength() > 1 )
820 lclFillListBox(*m_xLbHierarchy
, maLabelData
.maHiers
);
821 sal_Int32 nHier
= maLabelData
.mnUsedHier
;
822 if( (nHier
< 0) || (nHier
>= maLabelData
.maHiers
.getLength()) ) nHier
= 0;
823 m_xLbHierarchy
->set_active( nHier
);
824 m_xLbHierarchy
->connect_changed( LINK( this, ScDPSubtotalOptDlg
, SelectHdl
) );
828 m_xFtHierarchy
->set_sensitive(false);
829 m_xLbHierarchy
->set_sensitive(false);
833 void ScDPSubtotalOptDlg::InitHideListBox()
836 lclFillListBox(*m_xLbHide
, maLabelData
.maMembers
);
837 size_t n
= maLabelData
.maMembers
.size();
838 for (size_t i
= 0; i
< n
; ++i
)
839 m_xLbHide
->set_toggle(i
, maLabelData
.maMembers
[i
].mbVisible
? TRISTATE_FALSE
: TRISTATE_TRUE
);
840 bool bEnable
= m_xLbHide
->n_children() > 0;
841 m_xHideFrame
->set_sensitive(bEnable
);
844 ScDPName
ScDPSubtotalOptDlg::GetFieldName(const OUString
& rLayoutName
) const
846 NameMapType::const_iterator itr
= maDataFieldNameMap
.find(rLayoutName
);
847 return itr
== maDataFieldNameMap
.end() ? ScDPName() : itr
->second
;
850 sal_Int32
ScDPSubtotalOptDlg::FindListBoxEntry(
851 const weld::ComboBox
& rLBox
, std::u16string_view rEntry
, sal_Int32 nStartPos
) const
853 sal_Int32 nPos
= nStartPos
;
855 while (nPos
< rLBox
.get_count())
857 // translate the displayed field name back to its original field name.
858 ScDPName aName
= GetFieldName(rLBox
.get_text(nPos
));
859 OUString aUnoName
= ScDPUtil::createDuplicateDimensionName(aName
.maName
, aName
.mnDupCount
);
860 if (aUnoName
== rEntry
)
867 return bFound
? nPos
: -1;
870 IMPL_LINK(ScDPSubtotalOptDlg
, ButtonClicked
, weld::Button
&, rButton
, void)
872 if (&rButton
== m_xBtnOk
.get())
875 response(RET_CANCEL
);
878 IMPL_LINK(ScDPSubtotalOptDlg
, CheckHdl
, weld::Toggleable
&, rCBox
, void)
880 if (&rCBox
== m_xCbShow
.get())
882 bool bEnable
= m_xCbShow
->get_active();
883 m_xNfShow
->set_sensitive( bEnable
);
884 m_xFtShow
->set_sensitive( bEnable
);
885 m_xFtShowFrom
->set_sensitive( bEnable
);
886 m_xLbShowFrom
->set_sensitive( bEnable
);
888 bool bEnableUsing
= bEnable
&& (m_xLbShowUsing
->get_count() > 0);
889 m_xFtShowUsing
->set_sensitive(bEnableUsing
);
890 m_xLbShowUsing
->set_sensitive(bEnableUsing
);
894 IMPL_LINK_NOARG(ScDPSubtotalOptDlg
, SelectHdl
, weld::ComboBox
&, void)
896 mrDPObj
.GetMembers(maLabelData
.mnCol
, m_xLbHierarchy
->get_active(), maLabelData
.maMembers
);
900 ScDPShowDetailDlg::ScDPShowDetailDlg(weld::Window
* pParent
, ScDPObject
& rDPObj
, css::sheet::DataPilotFieldOrientation nOrient
)
901 : GenericDialogController(pParent
, "modules/scalc/ui/showdetaildialog.ui", "ShowDetail")
903 , mxLbDims(m_xBuilder
->weld_tree_view("dimsTreeview"))
905 ScDPSaveData
* pSaveData
= rDPObj
.GetSaveData();
906 tools::Long nDimCount
= rDPObj
.GetDimCount();
907 for (tools::Long nDim
=0; nDim
<nDimCount
; nDim
++)
910 sal_Int32 nDimFlags
= 0;
911 OUString aName
= rDPObj
.GetDimName( nDim
, bIsDataLayout
, &nDimFlags
);
912 if ( !bIsDataLayout
&& !rDPObj
.IsDuplicated( nDim
) && ScDPObject::IsOrientationAllowed( nOrient
, nDimFlags
) )
914 const ScDPSaveDimension
* pDimension
= pSaveData
? pSaveData
->GetExistingDimensionByName(aName
) : nullptr;
915 if ( !pDimension
|| (pDimension
->GetOrientation() != nOrient
) )
919 const std::optional
<OUString
> & pLayoutName
= pDimension
->GetLayoutName();
921 aName
= *pLayoutName
;
923 mxLbDims
->append_text(aName
);
924 maNameIndexMap
.emplace(aName
, nDim
);
928 if (mxLbDims
->n_children())
931 mxLbDims
->connect_row_activated(LINK(this, ScDPShowDetailDlg
, DblClickHdl
));
934 ScDPShowDetailDlg::~ScDPShowDetailDlg()
938 short ScDPShowDetailDlg::run()
940 return mxLbDims
->n_children() ? GenericDialogController::run() : static_cast<short>(RET_CANCEL
);
943 OUString
ScDPShowDetailDlg::GetDimensionName() const
945 // Look up the internal dimension name which may be different from the
946 // displayed field name.
947 OUString aSelectedName
= mxLbDims
->get_selected_text();
948 DimNameIndexMap::const_iterator itr
= maNameIndexMap
.find(aSelectedName
);
949 if (itr
== maNameIndexMap
.end())
950 // This should never happen!
951 return aSelectedName
;
953 tools::Long nDim
= itr
->second
;
954 bool bIsDataLayout
= false;
955 return mrDPObj
.GetDimName(nDim
, bIsDataLayout
);
958 IMPL_LINK_NOARG(ScDPShowDetailDlg
, DblClickHdl
, weld::TreeView
&, bool)
960 m_xDialog
->response(RET_OK
);
964 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */