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 const 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
, u
"modules/scalc/ui/datafielddialog.ui"_ustr
, u
"DataFieldDialog"_ustr
)
240 , mxLbFunc(new ScDPFunctionListBox(m_xBuilder
->weld_tree_view(u
"functions"_ustr
)))
241 , mxFtName(m_xBuilder
->weld_label(u
"name"_ustr
))
242 , mxLbType(m_xBuilder
->weld_combo_box(u
"type"_ustr
))
243 , mxFtBaseField(m_xBuilder
->weld_label(u
"basefieldft"_ustr
))
244 , mxLbBaseField(m_xBuilder
->weld_combo_box(u
"basefield"_ustr
))
245 , mxFtBaseItem(m_xBuilder
->weld_label(u
"baseitemft"_ustr
))
246 , mxLbBaseItem(m_xBuilder
->weld_combo_box(u
"baseitem"_ustr
))
247 , mxBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
248 , mxBtnCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
249 , mxExpander(m_xBuilder
->weld_expander(u
"expander"_ustr
))
250 , mrLabelVec(rLabelVec
)
253 mxLbFunc
->set_size_request(-1, mxLbFunc
->get_height_rows(8));
255 Init(rLabelData
, rFuncData
);
258 ScDPFunctionDlg::~ScDPFunctionDlg()
262 PivotFunc
ScDPFunctionDlg::GetFuncMask() const
264 return mxLbFunc
->GetSelection();
267 DataPilotFieldReference
ScDPFunctionDlg::GetFieldRef() const
269 DataPilotFieldReference aRef
;
271 aRef
.ReferenceType
= ToDataPilotFieldReferenceType(mxLbType
->get_active());
272 aRef
.ReferenceField
= GetBaseFieldName(mxLbBaseField
->get_active_text());
274 sal_Int32 nBaseItemPos
= mxLbBaseItem
->get_active();
275 switch( nBaseItemPos
)
277 case SC_BASEITEM_PREV_POS
:
278 aRef
.ReferenceItemType
= DataPilotFieldReferenceItemType::PREVIOUS
;
280 case SC_BASEITEM_NEXT_POS
:
281 aRef
.ReferenceItemType
= DataPilotFieldReferenceItemType::NEXT
;
285 aRef
.ReferenceItemType
= DataPilotFieldReferenceItemType::NAMED
;
286 if( !mbEmptyItem
|| (nBaseItemPos
> SC_BASEITEM_USER_POS
) )
287 aRef
.ReferenceItemName
= GetBaseItemName(mxLbBaseItem
->get_active_text());
294 void ScDPFunctionDlg::Init( const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
)
296 mxBtnOk
->connect_clicked( LINK( this, ScDPFunctionDlg
, ButtonClicked
) );
297 mxBtnCancel
->connect_clicked( LINK( this, ScDPFunctionDlg
, ButtonClicked
) );
300 PivotFunc nFuncMask
= (rFuncData
.mnFuncMask
== PivotFunc::NONE
) ? PivotFunc::Sum
: rFuncData
.mnFuncMask
;
301 mxLbFunc
->SetSelection( nFuncMask
);
304 mxFtName
->set_label(rLabelData
.getDisplayName());
307 mxLbFunc
->connect_row_activated( LINK( this, ScDPFunctionDlg
, DblClickHdl
) );
308 mxLbType
->connect_changed( LINK( this, ScDPFunctionDlg
, SelectHdl
) );
309 mxLbBaseField
->connect_changed( LINK( this, ScDPFunctionDlg
, SelectHdl
) );
311 // base field list box
312 OUString aSelectedEntry
;
313 for( const auto& rxLabel
: mrLabelVec
)
315 mxLbBaseField
->append_text(rxLabel
->getDisplayName());
316 maBaseFieldNameMap
.emplace(rxLabel
->getDisplayName(), rxLabel
->maName
);
317 if (rxLabel
->maName
== rFuncData
.maFieldRef
.ReferenceField
)
318 aSelectedEntry
= rxLabel
->getDisplayName();
321 // select field reference type
322 mxLbType
->set_active(FromDataPilotFieldReferenceType(rFuncData
.maFieldRef
.ReferenceType
));
323 SelectHdl( *mxLbType
); // enables base field/item list boxes
326 mxLbBaseField
->set_active_text(aSelectedEntry
);
327 if (mxLbBaseField
->get_active() == -1)
328 mxLbBaseField
->set_active(0);
329 SelectHdl( *mxLbBaseField
); // fills base item list, selects base item
332 switch( rFuncData
.maFieldRef
.ReferenceItemType
)
334 case DataPilotFieldReferenceItemType::PREVIOUS
:
335 mxLbBaseItem
->set_active( SC_BASEITEM_PREV_POS
);
337 case DataPilotFieldReferenceItemType::NEXT
:
338 mxLbBaseItem
->set_active( SC_BASEITEM_NEXT_POS
);
342 if( mbEmptyItem
&& rFuncData
.maFieldRef
.ReferenceItemName
.isEmpty() )
344 // select special "(empty)" entry added before other items
345 mxLbBaseItem
->set_active( SC_BASEITEM_USER_POS
);
349 sal_Int32 nStartPos
= mbEmptyItem
? (SC_BASEITEM_USER_POS
+ 1) : SC_BASEITEM_USER_POS
;
350 sal_Int32 nPos
= FindBaseItemPos( rFuncData
.maFieldRef
.ReferenceItemName
, nStartPos
);
352 nPos
= (mxLbBaseItem
->get_count() > SC_BASEITEM_USER_POS
) ? SC_BASEITEM_USER_POS
: SC_BASEITEM_PREV_POS
;
353 mxLbBaseItem
->set_active( nPos
);
359 const OUString
& ScDPFunctionDlg::GetBaseFieldName(const OUString
& rLayoutName
) const
361 NameMapType::const_iterator itr
= maBaseFieldNameMap
.find(rLayoutName
);
362 return itr
== maBaseFieldNameMap
.end() ? rLayoutName
: itr
->second
;
365 const OUString
& ScDPFunctionDlg::GetBaseItemName(const OUString
& rLayoutName
) const
367 NameMapType::const_iterator itr
= maBaseItemNameMap
.find(rLayoutName
);
368 return itr
== maBaseItemNameMap
.end() ? rLayoutName
: itr
->second
;
371 sal_Int32
ScDPFunctionDlg::FindBaseItemPos( std::u16string_view rEntry
, sal_Int32 nStartPos
) const
373 sal_Int32 nPos
= nStartPos
;
375 while (nPos
< mxLbBaseItem
->get_count())
377 // translate the displayed field name back to its original field name.
378 const OUString aInName
= mxLbBaseItem
->get_text(nPos
);
379 const OUString
& rName
= GetBaseItemName(aInName
);
387 return bFound
? nPos
: -1;
390 IMPL_LINK( ScDPFunctionDlg
, SelectHdl
, weld::ComboBox
&, rLBox
, void )
392 if (&rLBox
== mxLbType
.get())
394 bool bEnableField
, bEnableItem
;
395 switch (ToDataPilotFieldReferenceType(mxLbType
->get_active()))
397 case DataPilotFieldReferenceType::ITEM_DIFFERENCE
:
398 case DataPilotFieldReferenceType::ITEM_PERCENTAGE
:
399 case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE
:
400 bEnableField
= bEnableItem
= true;
403 case DataPilotFieldReferenceType::RUNNING_TOTAL
:
409 bEnableField
= bEnableItem
= false;
412 bEnableField
&= (mxLbBaseField
->get_count() > 0);
413 mxFtBaseField
->set_sensitive( bEnableField
);
414 mxLbBaseField
->set_sensitive( bEnableField
);
416 bEnableItem
&= bEnableField
;
417 mxFtBaseItem
->set_sensitive( bEnableItem
);
418 mxLbBaseItem
->set_sensitive( bEnableItem
);
420 else if (&rLBox
== mxLbBaseField
.get())
422 // keep "previous" and "next" entries
423 while (mxLbBaseItem
->get_count() > SC_BASEITEM_USER_POS
)
424 mxLbBaseItem
->remove(SC_BASEITEM_USER_POS
);
426 // update item list for current base field
428 size_t nBasePos
= mxLbBaseField
->get_active();
429 if (nBasePos
< mrLabelVec
.size())
431 const vector
<ScDPLabelData::Member
>& rMembers
= mrLabelVec
[nBasePos
]->maMembers
;
432 mbEmptyItem
= lclFillListBox(*mxLbBaseItem
, rMembers
, SC_BASEITEM_USER_POS
);
433 // build cache for base names.
435 for (const auto& rMember
: rMembers
)
436 aMap
.emplace(rMember
.getDisplayName(), rMember
.maName
);
437 maBaseItemNameMap
.swap(aMap
);
441 sal_uInt16 nItemPos
= (mxLbBaseItem
->get_count() > SC_BASEITEM_USER_POS
) ? SC_BASEITEM_USER_POS
: SC_BASEITEM_PREV_POS
;
442 mxLbBaseItem
->set_active( nItemPos
);
446 IMPL_LINK(ScDPFunctionDlg
, ButtonClicked
, weld::Button
&, rButton
, void)
448 if (&rButton
== mxBtnOk
.get())
451 response(RET_CANCEL
);
454 IMPL_LINK_NOARG(ScDPFunctionDlg
, DblClickHdl
, weld::TreeView
&, bool)
456 m_xDialog
->response(RET_OK
);
460 ScDPSubtotalDlg::ScDPSubtotalDlg(weld::Widget
* pParent
, ScDPObject
& rDPObj
,
461 const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
,
462 const ScDPNameVec
& rDataFields
, bool bEnableLayout
)
463 : GenericDialogController(pParent
, u
"modules/scalc/ui/pivotfielddialog.ui"_ustr
, u
"PivotFieldDialog"_ustr
)
465 , mrDataFields(rDataFields
)
466 , maLabelData(rLabelData
)
467 , mbEnableLayout(bEnableLayout
)
468 , mxRbNone(m_xBuilder
->weld_radio_button(u
"none"_ustr
))
469 , mxRbAuto(m_xBuilder
->weld_radio_button(u
"auto"_ustr
))
470 , mxRbUser(m_xBuilder
->weld_radio_button(u
"user"_ustr
))
471 , mxLbFunc(new ScDPFunctionListBox(m_xBuilder
->weld_tree_view(u
"functions"_ustr
)))
472 , mxFtName(m_xBuilder
->weld_label(u
"name"_ustr
))
473 , mxCbShowAll(m_xBuilder
->weld_check_button(u
"showall"_ustr
))
474 , mxBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
475 , mxBtnCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
476 , mxBtnOptions(m_xBuilder
->weld_button(u
"options"_ustr
))
478 mxLbFunc
->set_selection_mode(SelectionMode::Multiple
);
479 mxLbFunc
->set_size_request(-1, mxLbFunc
->get_height_rows(8));
480 Init(rLabelData
, rFuncData
);
483 ScDPSubtotalDlg::~ScDPSubtotalDlg()
488 void ScDPSubtotalDlg::CloseSubdialog()
490 if (mxOptionsDlg
&& mxOptionsDlg
->getDialog())
492 mxOptionsDlg
->getDialog()->response(RET_CANCEL
);
493 mxOptionsDlg
= nullptr;
497 PivotFunc
ScDPSubtotalDlg::GetFuncMask() const
499 PivotFunc nFuncMask
= PivotFunc::NONE
;
501 if (mxRbAuto
->get_active())
502 nFuncMask
= PivotFunc::Auto
;
503 else if (mxRbUser
->get_active())
504 nFuncMask
= mxLbFunc
->GetSelection();
509 void ScDPSubtotalDlg::FillLabelData( ScDPLabelData
& rLabelData
) const
511 rLabelData
.mnFuncMask
= GetFuncMask();
512 rLabelData
.mnUsedHier
= maLabelData
.mnUsedHier
;
513 rLabelData
.mbShowAll
= mxCbShowAll
->get_active();
514 rLabelData
.maMembers
= maLabelData
.maMembers
;
515 rLabelData
.maSortInfo
= maLabelData
.maSortInfo
;
516 rLabelData
.maLayoutInfo
= maLabelData
.maLayoutInfo
;
517 rLabelData
.maShowInfo
= maLabelData
.maShowInfo
;
518 rLabelData
.mbRepeatItemLabels
= maLabelData
.mbRepeatItemLabels
;
521 void ScDPSubtotalDlg::Init( const ScDPLabelData
& rLabelData
, const ScPivotFuncData
& rFuncData
)
523 mxBtnOk
->connect_clicked( LINK( this, ScDPSubtotalDlg
, ButtonClicked
) );
524 mxBtnCancel
->connect_clicked( LINK( this, ScDPSubtotalDlg
, ButtonClicked
) );
527 mxFtName
->set_label(rLabelData
.getDisplayName());
530 mxRbNone
->connect_toggled( LINK( this, ScDPSubtotalDlg
, RadioClickHdl
) );
531 mxRbAuto
->connect_toggled( LINK( this, ScDPSubtotalDlg
, RadioClickHdl
) );
532 mxRbUser
->connect_toggled( LINK( this, ScDPSubtotalDlg
, RadioClickHdl
) );
534 weld::RadioButton
* pRBtn
= nullptr;
535 switch( rFuncData
.mnFuncMask
)
537 case PivotFunc::NONE
: pRBtn
= mxRbNone
.get(); break;
538 case PivotFunc::Auto
: pRBtn
= mxRbAuto
.get(); break;
539 default: pRBtn
= mxRbUser
.get();
541 pRBtn
->set_active(true);
542 RadioClickHdl(*pRBtn
);
545 mxLbFunc
->SetSelection( rFuncData
.mnFuncMask
);
546 mxLbFunc
->connect_row_activated( LINK( this, ScDPSubtotalDlg
, DblClickHdl
) );
549 mxCbShowAll
->set_active( rLabelData
.mbShowAll
);
552 mxBtnOptions
->connect_clicked( LINK( this, ScDPSubtotalDlg
, ClickHdl
) );
555 IMPL_LINK(ScDPSubtotalDlg
, ButtonClicked
, weld::Button
&, rButton
, void)
559 if (&rButton
== mxBtnOk
.get())
562 response(RET_CANCEL
);
565 IMPL_LINK(ScDPSubtotalDlg
, RadioClickHdl
, weld::Toggleable
&, rBtn
, void)
567 if (!rBtn
.get_active())
569 mxLbFunc
->set_sensitive(mxRbUser
->get_active());
572 IMPL_LINK_NOARG(ScDPSubtotalDlg
, DblClickHdl
, weld::TreeView
&, bool)
574 m_xDialog
->response(RET_OK
);
578 IMPL_LINK(ScDPSubtotalDlg
, ClickHdl
, weld::Button
&, rBtn
, void)
580 if (&rBtn
== mxBtnOptions
.get())
582 mxOptionsDlg
= std::make_shared
<ScDPSubtotalOptDlg
>(m_xDialog
.get(), mrDPObj
, maLabelData
, mrDataFields
, mbEnableLayout
);
584 weld::DialogController::runAsync(mxOptionsDlg
, [this](int nResult
) {
585 if (nResult
== RET_OK
)
586 mxOptionsDlg
->FillLabelData(maLabelData
);
587 mxOptionsDlg
= nullptr;
594 int FromDataPilotFieldLayoutMode(int eMode
)
598 case DataPilotFieldLayoutMode::TABULAR_LAYOUT
:
600 case DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP
:
602 case DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM
:
604 case DataPilotFieldLayoutMode::COMPACT_LAYOUT
:
610 int ToDataPilotFieldLayoutMode(int nPos
)
615 return DataPilotFieldLayoutMode::TABULAR_LAYOUT
;
617 return DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP
;
619 return DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM
;
621 return DataPilotFieldLayoutMode::COMPACT_LAYOUT
;
623 return DataPilotFieldLayoutMode::TABULAR_LAYOUT
;
626 int FromDataPilotFieldShowItemsMode(int eMode
)
630 case DataPilotFieldShowItemsMode::FROM_TOP
:
632 case DataPilotFieldShowItemsMode::FROM_BOTTOM
:
638 int ToDataPilotFieldShowItemsMode(int nPos
)
643 return DataPilotFieldShowItemsMode::FROM_TOP
;
645 return DataPilotFieldShowItemsMode::FROM_BOTTOM
;
647 return DataPilotFieldShowItemsMode::FROM_TOP
;
651 ScDPSubtotalOptDlg::ScDPSubtotalOptDlg(weld::Window
* pParent
, ScDPObject
& rDPObj
,
652 const ScDPLabelData
& rLabelData
, const ScDPNameVec
& rDataFields
,
654 : GenericDialogController(pParent
, u
"modules/scalc/ui/datafieldoptionsdialog.ui"_ustr
,
655 u
"DataFieldOptionsDialog"_ustr
)
656 , m_xLbSortBy(m_xBuilder
->weld_combo_box(u
"sortby"_ustr
))
657 , m_xRbSortAsc(m_xBuilder
->weld_radio_button(u
"ascending"_ustr
))
658 , m_xRbSortDesc(m_xBuilder
->weld_radio_button(u
"descending"_ustr
))
659 , m_xRbSortMan(m_xBuilder
->weld_radio_button(u
"manual"_ustr
))
660 , m_xLayoutFrame(m_xBuilder
->weld_widget(u
"layoutframe"_ustr
))
661 , m_xLbLayout(m_xBuilder
->weld_combo_box(u
"layout"_ustr
))
662 , m_xCbLayoutEmpty(m_xBuilder
->weld_check_button(u
"emptyline"_ustr
))
663 , m_xCbRepeatItemLabels(m_xBuilder
->weld_check_button(u
"repeatitemlabels"_ustr
))
664 , m_xCbShow(m_xBuilder
->weld_check_button(u
"show"_ustr
))
665 , m_xNfShow(m_xBuilder
->weld_spin_button(u
"items"_ustr
))
666 , m_xFtShow(m_xBuilder
->weld_label(u
"showft"_ustr
))
667 , m_xFtShowFrom(m_xBuilder
->weld_label(u
"showfromft"_ustr
))
668 , m_xLbShowFrom(m_xBuilder
->weld_combo_box(u
"from"_ustr
))
669 , m_xFtShowUsing(m_xBuilder
->weld_label(u
"usingft"_ustr
))
670 , m_xLbShowUsing(m_xBuilder
->weld_combo_box(u
"using"_ustr
))
671 , m_xHideFrame(m_xBuilder
->weld_widget(u
"hideframe"_ustr
))
672 , m_xLbHide(m_xBuilder
->weld_tree_view(u
"hideitems"_ustr
))
673 , m_xFtHierarchy(m_xBuilder
->weld_label(u
"hierarchyft"_ustr
))
674 , m_xLbHierarchy(m_xBuilder
->weld_combo_box(u
"hierarchy"_ustr
))
675 , m_xBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
676 , m_xBtnCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
678 , maLabelData(rLabelData
)
680 m_xLbHide
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
682 m_xLbSortBy
->set_size_request(m_xLbSortBy
->get_approximate_digit_width() * 18, -1);
683 m_xLbHide
->set_size_request(-1, m_xLbHide
->get_height_rows(5));
684 Init(rDataFields
, bEnableLayout
);
687 ScDPSubtotalOptDlg::~ScDPSubtotalOptDlg()
691 void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData
& rLabelData
) const
695 if (m_xRbSortMan
->get_active())
696 rLabelData
.maSortInfo
.Mode
= DataPilotFieldSortMode::MANUAL
;
697 else if (m_xLbSortBy
->get_active() == SC_SORTNAME_POS
)
698 rLabelData
.maSortInfo
.Mode
= DataPilotFieldSortMode::NAME
;
700 rLabelData
.maSortInfo
.Mode
= DataPilotFieldSortMode::DATA
;
702 ScDPName aFieldName
= GetFieldName(m_xLbSortBy
->get_active_text());
703 if (!aFieldName
.maName
.isEmpty())
705 rLabelData
.maSortInfo
.Field
=
706 ScDPUtil::createDuplicateDimensionName(aFieldName
.maName
, aFieldName
.mnDupCount
);
709 if (rLabelData
.maSortInfo
.Mode
!= DataPilotFieldSortMode::MANUAL
)
710 rLabelData
.maSortInfo
.IsAscending
= m_xRbSortAsc
->get_active();
712 // *** LAYOUT MODE ***
714 rLabelData
.maLayoutInfo
.LayoutMode
= ToDataPilotFieldLayoutMode(m_xLbLayout
->get_active());
715 rLabelData
.maLayoutInfo
.AddEmptyLines
= m_xCbLayoutEmpty
->get_active();
716 rLabelData
.mbRepeatItemLabels
= m_xCbRepeatItemLabels
->get_active();
720 aFieldName
= GetFieldName(m_xLbShowUsing
->get_active_text());
721 if (!aFieldName
.maName
.isEmpty())
723 rLabelData
.maShowInfo
.IsEnabled
= m_xCbShow
->get_active();
724 rLabelData
.maShowInfo
.ShowItemsMode
= ToDataPilotFieldShowItemsMode(m_xLbShowFrom
->get_active());
725 rLabelData
.maShowInfo
.ItemCount
= sal::static_int_cast
<sal_Int32
>( m_xNfShow
->get_value() );
726 rLabelData
.maShowInfo
.DataField
=
727 ScDPUtil::createDuplicateDimensionName(aFieldName
.maName
, aFieldName
.mnDupCount
);
730 // *** HIDDEN ITEMS ***
732 rLabelData
.maMembers
= maLabelData
.maMembers
;
733 int nVisCount
= m_xLbHide
->n_children();
734 for (int nPos
= 0; nPos
< nVisCount
; ++nPos
)
735 rLabelData
.maMembers
[nPos
].mbVisible
= m_xLbHide
->get_toggle(nPos
) == TRISTATE_FALSE
;
739 rLabelData
.mnUsedHier
= m_xLbHierarchy
->get_active() != -1 ? m_xLbHierarchy
->get_active() : 0;
742 void ScDPSubtotalOptDlg::Init( const ScDPNameVec
& rDataFields
, bool bEnableLayout
)
744 m_xBtnOk
->connect_clicked(LINK(this, ScDPSubtotalOptDlg
, ButtonClicked
));
745 m_xBtnCancel
->connect_clicked(LINK(this, ScDPSubtotalOptDlg
, ButtonClicked
));
749 sal_Int32 nSortMode
= maLabelData
.maSortInfo
.Mode
;
751 // sort fields list box
752 m_xLbSortBy
->append_text(maLabelData
.getDisplayName());
754 for( const auto& rDataField
: rDataFields
)
756 // Cache names for later lookup.
757 maDataFieldNameMap
.emplace(rDataField
.maLayoutName
, rDataField
);
759 m_xLbSortBy
->append_text(rDataField
.maLayoutName
);
760 m_xLbShowUsing
->append_text(rDataField
.maLayoutName
); // for AutoShow
763 sal_Int32 nSortPos
= SC_SORTNAME_POS
;
764 if( nSortMode
== DataPilotFieldSortMode::DATA
)
766 nSortPos
= FindListBoxEntry( *m_xLbSortBy
, maLabelData
.maSortInfo
.Field
, SC_SORTDATA_POS
);
769 nSortPos
= SC_SORTNAME_POS
;
770 nSortMode
= DataPilotFieldSortMode::MANUAL
;
773 m_xLbSortBy
->set_active(nSortPos
);
775 weld::RadioButton
* pRBtn
= nullptr;
778 case DataPilotFieldSortMode::NONE
:
779 case DataPilotFieldSortMode::MANUAL
:
780 pRBtn
= m_xRbSortMan
.get();
783 pRBtn
= maLabelData
.maSortInfo
.IsAscending
? m_xRbSortAsc
.get() : m_xRbSortDesc
.get();
785 pRBtn
->set_active(true);
787 // *** LAYOUT MODE ***
789 m_xLayoutFrame
->set_sensitive(bEnableLayout
);
791 m_xLbLayout
->set_active(FromDataPilotFieldLayoutMode(maLabelData
.maLayoutInfo
.LayoutMode
));
792 m_xCbLayoutEmpty
->set_active( maLabelData
.maLayoutInfo
.AddEmptyLines
);
793 m_xCbRepeatItemLabels
->set_active( maLabelData
.mbRepeatItemLabels
);
797 m_xCbShow
->set_active( maLabelData
.maShowInfo
.IsEnabled
);
798 m_xCbShow
->connect_toggled( LINK( this, ScDPSubtotalOptDlg
, CheckHdl
) );
800 m_xLbShowFrom
->set_active(FromDataPilotFieldShowItemsMode(maLabelData
.maShowInfo
.ShowItemsMode
));
801 tools::Long nCount
= static_cast< tools::Long
>( maLabelData
.maShowInfo
.ItemCount
);
803 nCount
= SC_SHOW_DEFAULT
;
804 m_xNfShow
->set_value( nCount
);
806 // m_xLbShowUsing already filled above
807 m_xLbShowUsing
->set_active_text(maLabelData
.maShowInfo
.DataField
);
808 if (m_xLbShowUsing
->get_active() == -1)
809 m_xLbShowUsing
->set_active(0);
811 CheckHdl(*m_xCbShow
); // enable/disable dependent controls
813 // *** HIDDEN ITEMS ***
819 if( maLabelData
.maHiers
.getLength() > 1 )
821 lclFillListBox(*m_xLbHierarchy
, maLabelData
.maHiers
);
822 sal_Int32 nHier
= maLabelData
.mnUsedHier
;
823 if( (nHier
< 0) || (nHier
>= maLabelData
.maHiers
.getLength()) ) nHier
= 0;
824 m_xLbHierarchy
->set_active( nHier
);
825 m_xLbHierarchy
->connect_changed( LINK( this, ScDPSubtotalOptDlg
, SelectHdl
) );
829 m_xFtHierarchy
->set_sensitive(false);
830 m_xLbHierarchy
->set_sensitive(false);
834 void ScDPSubtotalOptDlg::InitHideListBox()
837 lclFillListBox(*m_xLbHide
, maLabelData
.maMembers
);
838 size_t n
= maLabelData
.maMembers
.size();
839 for (size_t i
= 0; i
< n
; ++i
)
840 m_xLbHide
->set_toggle(i
, maLabelData
.maMembers
[i
].mbVisible
? TRISTATE_FALSE
: TRISTATE_TRUE
);
841 bool bEnable
= m_xLbHide
->n_children() > 0;
842 m_xHideFrame
->set_sensitive(bEnable
);
845 ScDPName
ScDPSubtotalOptDlg::GetFieldName(const OUString
& rLayoutName
) const
847 NameMapType::const_iterator itr
= maDataFieldNameMap
.find(rLayoutName
);
848 return itr
== maDataFieldNameMap
.end() ? ScDPName() : itr
->second
;
851 sal_Int32
ScDPSubtotalOptDlg::FindListBoxEntry(
852 const weld::ComboBox
& rLBox
, std::u16string_view rEntry
, sal_Int32 nStartPos
) const
854 sal_Int32 nPos
= nStartPos
;
856 while (nPos
< rLBox
.get_count())
858 // translate the displayed field name back to its original field name.
859 ScDPName aName
= GetFieldName(rLBox
.get_text(nPos
));
860 OUString aUnoName
= ScDPUtil::createDuplicateDimensionName(aName
.maName
, aName
.mnDupCount
);
861 if (aUnoName
== rEntry
)
868 return bFound
? nPos
: -1;
871 IMPL_LINK(ScDPSubtotalOptDlg
, ButtonClicked
, weld::Button
&, rButton
, void)
873 if (&rButton
== m_xBtnOk
.get())
876 response(RET_CANCEL
);
879 IMPL_LINK(ScDPSubtotalOptDlg
, CheckHdl
, weld::Toggleable
&, rCBox
, void)
881 if (&rCBox
== m_xCbShow
.get())
883 bool bEnable
= m_xCbShow
->get_active();
884 m_xNfShow
->set_sensitive( bEnable
);
885 m_xFtShow
->set_sensitive( bEnable
);
886 m_xFtShowFrom
->set_sensitive( bEnable
);
887 m_xLbShowFrom
->set_sensitive( bEnable
);
889 bool bEnableUsing
= bEnable
&& (m_xLbShowUsing
->get_count() > 0);
890 m_xFtShowUsing
->set_sensitive(bEnableUsing
);
891 m_xLbShowUsing
->set_sensitive(bEnableUsing
);
895 IMPL_LINK_NOARG(ScDPSubtotalOptDlg
, SelectHdl
, weld::ComboBox
&, void)
897 mrDPObj
.GetMembers(maLabelData
.mnCol
, m_xLbHierarchy
->get_active(), maLabelData
.maMembers
);
901 ScDPShowDetailDlg::ScDPShowDetailDlg(weld::Window
* pParent
, ScDPObject
& rDPObj
, css::sheet::DataPilotFieldOrientation nOrient
)
902 : GenericDialogController(pParent
, u
"modules/scalc/ui/showdetaildialog.ui"_ustr
, u
"ShowDetail"_ustr
)
904 , mxLbDims(m_xBuilder
->weld_tree_view(u
"dimsTreeview"_ustr
))
906 ScDPSaveData
* pSaveData
= rDPObj
.GetSaveData();
907 tools::Long nDimCount
= rDPObj
.GetDimCount();
908 for (tools::Long nDim
=0; nDim
<nDimCount
; nDim
++)
911 sal_Int32 nDimFlags
= 0;
912 OUString aName
= rDPObj
.GetDimName( nDim
, bIsDataLayout
, &nDimFlags
);
913 if ( !bIsDataLayout
&& !rDPObj
.IsDuplicated( nDim
) && ScDPObject::IsOrientationAllowed( nOrient
, nDimFlags
) )
915 const ScDPSaveDimension
* pDimension
= pSaveData
? pSaveData
->GetExistingDimensionByName(aName
) : nullptr;
916 if ( !pDimension
|| (pDimension
->GetOrientation() != nOrient
) )
920 const std::optional
<OUString
> & pLayoutName
= pDimension
->GetLayoutName();
922 aName
= *pLayoutName
;
924 mxLbDims
->append_text(aName
);
925 maNameIndexMap
.emplace(aName
, nDim
);
929 if (mxLbDims
->n_children())
932 mxLbDims
->connect_row_activated(LINK(this, ScDPShowDetailDlg
, DblClickHdl
));
935 ScDPShowDetailDlg::~ScDPShowDetailDlg()
939 short ScDPShowDetailDlg::run()
941 return mxLbDims
->n_children() ? GenericDialogController::run() : static_cast<short>(RET_CANCEL
);
944 OUString
ScDPShowDetailDlg::GetDimensionName() const
946 // Look up the internal dimension name which may be different from the
947 // displayed field name.
948 OUString aSelectedName
= mxLbDims
->get_selected_text();
949 DimNameIndexMap::const_iterator itr
= maNameIndexMap
.find(aSelectedName
);
950 if (itr
== maNameIndexMap
.end())
951 // This should never happen!
952 return aSelectedName
;
954 tools::Long nDim
= itr
->second
;
955 bool bIsDataLayout
= false;
956 return mrDPObj
.GetDimName(nDim
, bIsDataLayout
);
959 IMPL_LINK_NOARG(ScDPShowDetailDlg
, DblClickHdl
, weld::TreeView
&, bool)
961 m_xDialog
->response(RET_OK
);
965 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */