/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #undef SC_DLLIMPLEMENTATION #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star::sheet; using ::com::sun::star::uno::Sequence; using ::std::vector; namespace { /** Appends all strings from the Sequence to the list box. Empty strings are replaced by a localized "(empty)" entry and inserted at the specified position. @return true = The passed string list contains an empty string entry. */ bool lclFillListBox(weld::ComboBox& rLBox, const Sequence< OUString >& rStrings) { bool bEmpty = false; for (const OUString& str : rStrings) { if (!str.isEmpty()) rLBox.append_text(str); else { rLBox.append_text(ScResId(STR_EMPTYDATA)); bEmpty = true; } } return bEmpty; } bool lclFillListBox(weld::ComboBox& rLBox, const vector& rMembers, int nEmptyPos) { bool bEmpty = false; vector::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end(); for (; itr != itrEnd; ++itr) { OUString aName = itr->getDisplayName(); if (!aName.isEmpty()) rLBox.append_text(aName); else { rLBox.insert_text(nEmptyPos, ScResId(STR_EMPTYDATA)); bEmpty = true; } } return bEmpty; } bool lclFillListBox(weld::TreeView& rLBox, const vector& rMembers) { bool bEmpty = false; for (const auto& rMember : rMembers) { rLBox.append(); int pos = rLBox.n_children() - 1; rLBox.set_toggle(pos, TRISTATE_FALSE); OUString aName = rMember.getDisplayName(); if (!aName.isEmpty()) rLBox.set_text(pos, aName, 0); else { rLBox.set_text(pos, ScResId(STR_EMPTYDATA), 0); bEmpty = true; } } return bEmpty; } /** This table represents the order of the strings in the resource string array. */ const PivotFunc spnFunctions[] = { PivotFunc::Sum, PivotFunc::Count, PivotFunc::Average, PivotFunc::Median, PivotFunc::Max, PivotFunc::Min, PivotFunc::Product, PivotFunc::CountNum, PivotFunc::StdDev, PivotFunc::StdDevP, PivotFunc::StdVar, PivotFunc::StdVarP }; const sal_uInt16 SC_BASEITEM_PREV_POS = 0; const sal_uInt16 SC_BASEITEM_NEXT_POS = 1; const sal_uInt16 SC_BASEITEM_USER_POS = 2; const sal_uInt16 SC_SORTNAME_POS = 0; const sal_uInt16 SC_SORTDATA_POS = 1; const tools::Long SC_SHOW_DEFAULT = 10; } // namespace ScDPFunctionListBox::ScDPFunctionListBox(std::unique_ptr xControl) : m_xControl(std::move(xControl)) { FillFunctionNames(); } void ScDPFunctionListBox::SetSelection( PivotFunc nFuncMask ) { if( (nFuncMask == PivotFunc::NONE) || (nFuncMask == PivotFunc::Auto) ) m_xControl->unselect_all(); else { for( sal_Int32 nEntry = 0, nCount = m_xControl->n_children(); nEntry < nCount; ++nEntry ) { if (bool(nFuncMask & spnFunctions[ nEntry ])) m_xControl->select(nEntry); else m_xControl->unselect(nEntry); } } } PivotFunc ScDPFunctionListBox::GetSelection() const { PivotFunc nFuncMask = PivotFunc::NONE; std::vector aRows = m_xControl->get_selected_rows(); for (int nSel : aRows) nFuncMask |= spnFunctions[nSel]; return nFuncMask; } void ScDPFunctionListBox::FillFunctionNames() { OSL_ENSURE( !m_xControl->n_children(), "ScDPMultiFuncListBox::FillFunctionNames - do not add texts to resource" ); m_xControl->clear(); m_xControl->freeze(); for (size_t nIndex = 0; nIndex < SAL_N_ELEMENTS(SCSTR_DPFUNCLISTBOX); ++nIndex) m_xControl->append_text(ScResId(SCSTR_DPFUNCLISTBOX[nIndex])); m_xControl->thaw(); assert(m_xControl->n_children() == SAL_N_ELEMENTS(spnFunctions)); } namespace { int FromDataPilotFieldReferenceType(int eMode) { switch (eMode) { case DataPilotFieldReferenceType::NONE: return 0; case DataPilotFieldReferenceType::ITEM_DIFFERENCE: return 1; case DataPilotFieldReferenceType::ITEM_PERCENTAGE: return 2; case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: return 3; case DataPilotFieldReferenceType::RUNNING_TOTAL: return 4; case DataPilotFieldReferenceType::ROW_PERCENTAGE: return 5; case DataPilotFieldReferenceType::COLUMN_PERCENTAGE: return 6; case DataPilotFieldReferenceType::TOTAL_PERCENTAGE: return 7; case DataPilotFieldReferenceType::INDEX: return 8; } return -1; } int ToDataPilotFieldReferenceType(int nPos) { switch (nPos) { case 0: return DataPilotFieldReferenceType::NONE; case 1: return DataPilotFieldReferenceType::ITEM_DIFFERENCE; case 2: return DataPilotFieldReferenceType::ITEM_PERCENTAGE; case 3: return DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE; case 4: return DataPilotFieldReferenceType::RUNNING_TOTAL; case 5: return DataPilotFieldReferenceType::ROW_PERCENTAGE; case 6: return DataPilotFieldReferenceType::COLUMN_PERCENTAGE; case 7: return DataPilotFieldReferenceType::TOTAL_PERCENTAGE; case 8: return DataPilotFieldReferenceType::INDEX; } return DataPilotFieldReferenceType::NONE; } } ScDPFunctionDlg::ScDPFunctionDlg( weld::Widget* pParent, const ScDPLabelDataVector& rLabelVec, const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData) : GenericDialogController(pParent, u"modules/scalc/ui/datafielddialog.ui"_ustr, u"DataFieldDialog"_ustr) , mxLbFunc(new ScDPFunctionListBox(m_xBuilder->weld_tree_view(u"functions"_ustr))) , mxFtName(m_xBuilder->weld_label(u"name"_ustr)) , mxLbType(m_xBuilder->weld_combo_box(u"type"_ustr)) , mxFtBaseField(m_xBuilder->weld_label(u"basefieldft"_ustr)) , mxLbBaseField(m_xBuilder->weld_combo_box(u"basefield"_ustr)) , mxFtBaseItem(m_xBuilder->weld_label(u"baseitemft"_ustr)) , mxLbBaseItem(m_xBuilder->weld_combo_box(u"baseitem"_ustr)) , mxBtnOk(m_xBuilder->weld_button(u"ok"_ustr)) , mxBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr)) , mxExpander(m_xBuilder->weld_expander(u"expander"_ustr)) , mrLabelVec(rLabelVec) , mbEmptyItem(false) { mxLbFunc->set_size_request(-1, mxLbFunc->get_height_rows(8)); Init(rLabelData, rFuncData); } ScDPFunctionDlg::~ScDPFunctionDlg() { } PivotFunc ScDPFunctionDlg::GetFuncMask() const { return mxLbFunc->GetSelection(); } DataPilotFieldReference ScDPFunctionDlg::GetFieldRef() const { DataPilotFieldReference aRef; aRef.ReferenceType = ToDataPilotFieldReferenceType(mxLbType->get_active()); aRef.ReferenceField = GetBaseFieldName(mxLbBaseField->get_active_text()); sal_Int32 nBaseItemPos = mxLbBaseItem->get_active(); switch( nBaseItemPos ) { case SC_BASEITEM_PREV_POS: aRef.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS; break; case SC_BASEITEM_NEXT_POS: aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT; break; default: { aRef.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED; if( !mbEmptyItem || (nBaseItemPos > SC_BASEITEM_USER_POS) ) aRef.ReferenceItemName = GetBaseItemName(mxLbBaseItem->get_active_text()); } } return aRef; } void ScDPFunctionDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData ) { mxBtnOk->connect_clicked( LINK( this, ScDPFunctionDlg, ButtonClicked ) ); mxBtnCancel->connect_clicked( LINK( this, ScDPFunctionDlg, ButtonClicked ) ); // list box PivotFunc nFuncMask = (rFuncData.mnFuncMask == PivotFunc::NONE) ? PivotFunc::Sum : rFuncData.mnFuncMask; mxLbFunc->SetSelection( nFuncMask ); // field name mxFtName->set_label(rLabelData.getDisplayName()); // handlers mxLbFunc->connect_row_activated( LINK( this, ScDPFunctionDlg, DblClickHdl ) ); mxLbType->connect_changed( LINK( this, ScDPFunctionDlg, SelectHdl ) ); mxLbBaseField->connect_changed( LINK( this, ScDPFunctionDlg, SelectHdl ) ); // base field list box OUString aSelectedEntry; for( const auto& rxLabel : mrLabelVec ) { mxLbBaseField->append_text(rxLabel->getDisplayName()); maBaseFieldNameMap.emplace(rxLabel->getDisplayName(), rxLabel->maName); if (rxLabel->maName == rFuncData.maFieldRef.ReferenceField) aSelectedEntry = rxLabel->getDisplayName(); } // select field reference type mxLbType->set_active(FromDataPilotFieldReferenceType(rFuncData.maFieldRef.ReferenceType)); SelectHdl( *mxLbType ); // enables base field/item list boxes // select base field mxLbBaseField->set_active_text(aSelectedEntry); if (mxLbBaseField->get_active() == -1) mxLbBaseField->set_active(0); SelectHdl( *mxLbBaseField ); // fills base item list, selects base item // select base item switch( rFuncData.maFieldRef.ReferenceItemType ) { case DataPilotFieldReferenceItemType::PREVIOUS: mxLbBaseItem->set_active( SC_BASEITEM_PREV_POS ); break; case DataPilotFieldReferenceItemType::NEXT: mxLbBaseItem->set_active( SC_BASEITEM_NEXT_POS ); break; default: { if( mbEmptyItem && rFuncData.maFieldRef.ReferenceItemName.isEmpty() ) { // select special "(empty)" entry added before other items mxLbBaseItem->set_active( SC_BASEITEM_USER_POS ); } else { sal_Int32 nStartPos = mbEmptyItem ? (SC_BASEITEM_USER_POS + 1) : SC_BASEITEM_USER_POS; sal_Int32 nPos = FindBaseItemPos( rFuncData.maFieldRef.ReferenceItemName, nStartPos ); if( nPos == -1) nPos = (mxLbBaseItem->get_count() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS; mxLbBaseItem->set_active( nPos ); } } } } const OUString& ScDPFunctionDlg::GetBaseFieldName(const OUString& rLayoutName) const { NameMapType::const_iterator itr = maBaseFieldNameMap.find(rLayoutName); return itr == maBaseFieldNameMap.end() ? rLayoutName : itr->second; } const OUString& ScDPFunctionDlg::GetBaseItemName(const OUString& rLayoutName) const { NameMapType::const_iterator itr = maBaseItemNameMap.find(rLayoutName); return itr == maBaseItemNameMap.end() ? rLayoutName : itr->second; } sal_Int32 ScDPFunctionDlg::FindBaseItemPos( std::u16string_view rEntry, sal_Int32 nStartPos ) const { sal_Int32 nPos = nStartPos; bool bFound = false; while (nPos < mxLbBaseItem->get_count()) { // translate the displayed field name back to its original field name. const OUString& rInName = mxLbBaseItem->get_text(nPos); const OUString& rName = GetBaseItemName(rInName); if (rName == rEntry) { bFound = true; break; } ++nPos; } return bFound ? nPos : -1; } IMPL_LINK( ScDPFunctionDlg, SelectHdl, weld::ComboBox&, rLBox, void ) { if (&rLBox == mxLbType.get()) { bool bEnableField, bEnableItem; switch (ToDataPilotFieldReferenceType(mxLbType->get_active())) { case DataPilotFieldReferenceType::ITEM_DIFFERENCE: case DataPilotFieldReferenceType::ITEM_PERCENTAGE: case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: bEnableField = bEnableItem = true; break; case DataPilotFieldReferenceType::RUNNING_TOTAL: bEnableField = true; bEnableItem = false; break; default: bEnableField = bEnableItem = false; } bEnableField &= (mxLbBaseField->get_count() > 0); mxFtBaseField->set_sensitive( bEnableField ); mxLbBaseField->set_sensitive( bEnableField ); bEnableItem &= bEnableField; mxFtBaseItem->set_sensitive( bEnableItem ); mxLbBaseItem->set_sensitive( bEnableItem ); } else if (&rLBox == mxLbBaseField.get()) { // keep "previous" and "next" entries while (mxLbBaseItem->get_count() > SC_BASEITEM_USER_POS) mxLbBaseItem->remove(SC_BASEITEM_USER_POS); // update item list for current base field mbEmptyItem = false; size_t nBasePos = mxLbBaseField->get_active(); if (nBasePos < mrLabelVec.size()) { const vector& rMembers = mrLabelVec[nBasePos]->maMembers; mbEmptyItem = lclFillListBox(*mxLbBaseItem, rMembers, SC_BASEITEM_USER_POS); // build cache for base names. NameMapType aMap; for (const auto& rMember : rMembers) aMap.emplace(rMember.getDisplayName(), rMember.maName); maBaseItemNameMap.swap(aMap); } // select base item sal_uInt16 nItemPos = (mxLbBaseItem->get_count() > SC_BASEITEM_USER_POS) ? SC_BASEITEM_USER_POS : SC_BASEITEM_PREV_POS; mxLbBaseItem->set_active( nItemPos ); } } IMPL_LINK(ScDPFunctionDlg, ButtonClicked, weld::Button&, rButton, void) { if (&rButton == mxBtnOk.get()) response(RET_OK); else response(RET_CANCEL); } IMPL_LINK_NOARG(ScDPFunctionDlg, DblClickHdl, weld::TreeView&, bool) { m_xDialog->response(RET_OK); return true; } ScDPSubtotalDlg::ScDPSubtotalDlg(weld::Widget* pParent, ScDPObject& rDPObj, const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData, const ScDPNameVec& rDataFields, bool bEnableLayout) : GenericDialogController(pParent, u"modules/scalc/ui/pivotfielddialog.ui"_ustr, u"PivotFieldDialog"_ustr) , mrDPObj(rDPObj) , mrDataFields(rDataFields) , maLabelData(rLabelData) , mbEnableLayout(bEnableLayout) , mxRbNone(m_xBuilder->weld_radio_button(u"none"_ustr)) , mxRbAuto(m_xBuilder->weld_radio_button(u"auto"_ustr)) , mxRbUser(m_xBuilder->weld_radio_button(u"user"_ustr)) , mxLbFunc(new ScDPFunctionListBox(m_xBuilder->weld_tree_view(u"functions"_ustr))) , mxFtName(m_xBuilder->weld_label(u"name"_ustr)) , mxCbShowAll(m_xBuilder->weld_check_button(u"showall"_ustr)) , mxBtnOk(m_xBuilder->weld_button(u"ok"_ustr)) , mxBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr)) , mxBtnOptions(m_xBuilder->weld_button(u"options"_ustr)) { mxLbFunc->set_selection_mode(SelectionMode::Multiple); mxLbFunc->set_size_request(-1, mxLbFunc->get_height_rows(8)); Init(rLabelData, rFuncData); } ScDPSubtotalDlg::~ScDPSubtotalDlg() { CloseSubdialog(); } void ScDPSubtotalDlg::CloseSubdialog() { if (mxOptionsDlg && mxOptionsDlg->getDialog()) { mxOptionsDlg->getDialog()->response(RET_CANCEL); mxOptionsDlg = nullptr; } } PivotFunc ScDPSubtotalDlg::GetFuncMask() const { PivotFunc nFuncMask = PivotFunc::NONE; if (mxRbAuto->get_active()) nFuncMask = PivotFunc::Auto; else if (mxRbUser->get_active()) nFuncMask = mxLbFunc->GetSelection(); return nFuncMask; } void ScDPSubtotalDlg::FillLabelData( ScDPLabelData& rLabelData ) const { rLabelData.mnFuncMask = GetFuncMask(); rLabelData.mnUsedHier = maLabelData.mnUsedHier; rLabelData.mbShowAll = mxCbShowAll->get_active(); rLabelData.maMembers = maLabelData.maMembers; rLabelData.maSortInfo = maLabelData.maSortInfo; rLabelData.maLayoutInfo = maLabelData.maLayoutInfo; rLabelData.maShowInfo = maLabelData.maShowInfo; rLabelData.mbRepeatItemLabels = maLabelData.mbRepeatItemLabels; } void ScDPSubtotalDlg::Init( const ScDPLabelData& rLabelData, const ScPivotFuncData& rFuncData ) { mxBtnOk->connect_clicked( LINK( this, ScDPSubtotalDlg, ButtonClicked ) ); mxBtnCancel->connect_clicked( LINK( this, ScDPSubtotalDlg, ButtonClicked ) ); // field name mxFtName->set_label(rLabelData.getDisplayName()); // radio buttons mxRbNone->connect_toggled( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) ); mxRbAuto->connect_toggled( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) ); mxRbUser->connect_toggled( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) ); weld::RadioButton* pRBtn = nullptr; switch( rFuncData.mnFuncMask ) { case PivotFunc::NONE: pRBtn = mxRbNone.get(); break; case PivotFunc::Auto: pRBtn = mxRbAuto.get(); break; default: pRBtn = mxRbUser.get(); } pRBtn->set_active(true); RadioClickHdl(*pRBtn); // list box mxLbFunc->SetSelection( rFuncData.mnFuncMask ); mxLbFunc->connect_row_activated( LINK( this, ScDPSubtotalDlg, DblClickHdl ) ); // show all mxCbShowAll->set_active( rLabelData.mbShowAll ); // options mxBtnOptions->connect_clicked( LINK( this, ScDPSubtotalDlg, ClickHdl ) ); } IMPL_LINK(ScDPSubtotalDlg, ButtonClicked, weld::Button&, rButton, void) { CloseSubdialog(); if (&rButton == mxBtnOk.get()) response(RET_OK); else response(RET_CANCEL); } IMPL_LINK(ScDPSubtotalDlg, RadioClickHdl, weld::Toggleable&, rBtn, void) { if (!rBtn.get_active()) return; mxLbFunc->set_sensitive(mxRbUser->get_active()); } IMPL_LINK_NOARG(ScDPSubtotalDlg, DblClickHdl, weld::TreeView&, bool) { m_xDialog->response(RET_OK); return true; } IMPL_LINK(ScDPSubtotalDlg, ClickHdl, weld::Button&, rBtn, void) { if (&rBtn == mxBtnOptions.get()) { mxOptionsDlg = std::make_shared(m_xDialog.get(), mrDPObj, maLabelData, mrDataFields, mbEnableLayout); weld::DialogController::runAsync(mxOptionsDlg, [this](int nResult) { if (nResult == RET_OK) mxOptionsDlg->FillLabelData(maLabelData); mxOptionsDlg = nullptr; }); } } namespace { int FromDataPilotFieldLayoutMode(int eMode) { switch (eMode) { case DataPilotFieldLayoutMode::TABULAR_LAYOUT: return 0; case DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP: return 1; case DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM: return 2; case DataPilotFieldLayoutMode::COMPACT_LAYOUT: return 3; } return -1; } int ToDataPilotFieldLayoutMode(int nPos) { switch (nPos) { case 0: return DataPilotFieldLayoutMode::TABULAR_LAYOUT; case 1: return DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP; case 2: return DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM; case 3: return DataPilotFieldLayoutMode::COMPACT_LAYOUT; } return DataPilotFieldLayoutMode::TABULAR_LAYOUT; } int FromDataPilotFieldShowItemsMode(int eMode) { switch (eMode) { case DataPilotFieldShowItemsMode::FROM_TOP: return 0; case DataPilotFieldShowItemsMode::FROM_BOTTOM: return 1; } return -1; } int ToDataPilotFieldShowItemsMode(int nPos) { switch (nPos) { case 0: return DataPilotFieldShowItemsMode::FROM_TOP; case 1: return DataPilotFieldShowItemsMode::FROM_BOTTOM; } return DataPilotFieldShowItemsMode::FROM_TOP; } } ScDPSubtotalOptDlg::ScDPSubtotalOptDlg(weld::Window* pParent, ScDPObject& rDPObj, const ScDPLabelData& rLabelData, const ScDPNameVec& rDataFields, bool bEnableLayout ) : GenericDialogController(pParent, u"modules/scalc/ui/datafieldoptionsdialog.ui"_ustr, u"DataFieldOptionsDialog"_ustr) , m_xLbSortBy(m_xBuilder->weld_combo_box(u"sortby"_ustr)) , m_xRbSortAsc(m_xBuilder->weld_radio_button(u"ascending"_ustr)) , m_xRbSortDesc(m_xBuilder->weld_radio_button(u"descending"_ustr)) , m_xRbSortMan(m_xBuilder->weld_radio_button(u"manual"_ustr)) , m_xLayoutFrame(m_xBuilder->weld_widget(u"layoutframe"_ustr)) , m_xLbLayout(m_xBuilder->weld_combo_box(u"layout"_ustr)) , m_xCbLayoutEmpty(m_xBuilder->weld_check_button(u"emptyline"_ustr)) , m_xCbRepeatItemLabels(m_xBuilder->weld_check_button(u"repeatitemlabels"_ustr)) , m_xCbShow(m_xBuilder->weld_check_button(u"show"_ustr)) , m_xNfShow(m_xBuilder->weld_spin_button(u"items"_ustr)) , m_xFtShow(m_xBuilder->weld_label(u"showft"_ustr)) , m_xFtShowFrom(m_xBuilder->weld_label(u"showfromft"_ustr)) , m_xLbShowFrom(m_xBuilder->weld_combo_box(u"from"_ustr)) , m_xFtShowUsing(m_xBuilder->weld_label(u"usingft"_ustr)) , m_xLbShowUsing(m_xBuilder->weld_combo_box(u"using"_ustr)) , m_xHideFrame(m_xBuilder->weld_widget(u"hideframe"_ustr)) , m_xLbHide(m_xBuilder->weld_tree_view(u"hideitems"_ustr)) , m_xFtHierarchy(m_xBuilder->weld_label(u"hierarchyft"_ustr)) , m_xLbHierarchy(m_xBuilder->weld_combo_box(u"hierarchy"_ustr)) , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr)) , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr)) , mrDPObj(rDPObj) , maLabelData(rLabelData) { m_xLbHide->enable_toggle_buttons(weld::ColumnToggleType::Check); m_xLbSortBy->set_size_request(m_xLbSortBy->get_approximate_digit_width() * 18, -1); m_xLbHide->set_size_request(-1, m_xLbHide->get_height_rows(5)); Init(rDataFields, bEnableLayout); } ScDPSubtotalOptDlg::~ScDPSubtotalOptDlg() { } void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const { // *** SORTING *** if (m_xRbSortMan->get_active()) rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::MANUAL; else if (m_xLbSortBy->get_active() == SC_SORTNAME_POS) rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::NAME; else rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::DATA; ScDPName aFieldName = GetFieldName(m_xLbSortBy->get_active_text()); if (!aFieldName.maName.isEmpty()) { rLabelData.maSortInfo.Field = ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount); } if (rLabelData.maSortInfo.Mode != DataPilotFieldSortMode::MANUAL) rLabelData.maSortInfo.IsAscending = m_xRbSortAsc->get_active(); // *** LAYOUT MODE *** rLabelData.maLayoutInfo.LayoutMode = ToDataPilotFieldLayoutMode(m_xLbLayout->get_active()); rLabelData.maLayoutInfo.AddEmptyLines = m_xCbLayoutEmpty->get_active(); rLabelData.mbRepeatItemLabels = m_xCbRepeatItemLabels->get_active(); // *** AUTO SHOW *** aFieldName = GetFieldName(m_xLbShowUsing->get_active_text()); if (!aFieldName.maName.isEmpty()) { rLabelData.maShowInfo.IsEnabled = m_xCbShow->get_active(); rLabelData.maShowInfo.ShowItemsMode = ToDataPilotFieldShowItemsMode(m_xLbShowFrom->get_active()); rLabelData.maShowInfo.ItemCount = sal::static_int_cast( m_xNfShow->get_value() ); rLabelData.maShowInfo.DataField = ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount); } // *** HIDDEN ITEMS *** rLabelData.maMembers = maLabelData.maMembers; int nVisCount = m_xLbHide->n_children(); for (int nPos = 0; nPos < nVisCount; ++nPos) rLabelData.maMembers[nPos].mbVisible = m_xLbHide->get_toggle(nPos) == TRISTATE_FALSE; // *** HIERARCHY *** rLabelData.mnUsedHier = m_xLbHierarchy->get_active() != -1 ? m_xLbHierarchy->get_active() : 0; } void ScDPSubtotalOptDlg::Init( const ScDPNameVec& rDataFields, bool bEnableLayout ) { m_xBtnOk->connect_clicked(LINK(this, ScDPSubtotalOptDlg, ButtonClicked)); m_xBtnCancel->connect_clicked(LINK(this, ScDPSubtotalOptDlg, ButtonClicked)); // *** SORTING *** sal_Int32 nSortMode = maLabelData.maSortInfo.Mode; // sort fields list box m_xLbSortBy->append_text(maLabelData.getDisplayName()); for( const auto& rDataField : rDataFields ) { // Cache names for later lookup. maDataFieldNameMap.emplace(rDataField.maLayoutName, rDataField); m_xLbSortBy->append_text(rDataField.maLayoutName); m_xLbShowUsing->append_text(rDataField.maLayoutName); // for AutoShow } sal_Int32 nSortPos = SC_SORTNAME_POS; if( nSortMode == DataPilotFieldSortMode::DATA ) { nSortPos = FindListBoxEntry( *m_xLbSortBy, maLabelData.maSortInfo.Field, SC_SORTDATA_POS ); if( nSortPos == -1 ) { nSortPos = SC_SORTNAME_POS; nSortMode = DataPilotFieldSortMode::MANUAL; } } m_xLbSortBy->set_active(nSortPos); weld::RadioButton* pRBtn = nullptr; switch( nSortMode ) { case DataPilotFieldSortMode::NONE: case DataPilotFieldSortMode::MANUAL: pRBtn = m_xRbSortMan.get(); break; default: pRBtn = maLabelData.maSortInfo.IsAscending ? m_xRbSortAsc.get() : m_xRbSortDesc.get(); } pRBtn->set_active(true); // *** LAYOUT MODE *** m_xLayoutFrame->set_sensitive(bEnableLayout); m_xLbLayout->set_active(FromDataPilotFieldLayoutMode(maLabelData.maLayoutInfo.LayoutMode)); m_xCbLayoutEmpty->set_active( maLabelData.maLayoutInfo.AddEmptyLines ); m_xCbRepeatItemLabels->set_active( maLabelData.mbRepeatItemLabels ); // *** AUTO SHOW *** m_xCbShow->set_active( maLabelData.maShowInfo.IsEnabled ); m_xCbShow->connect_toggled( LINK( this, ScDPSubtotalOptDlg, CheckHdl ) ); m_xLbShowFrom->set_active(FromDataPilotFieldShowItemsMode(maLabelData.maShowInfo.ShowItemsMode)); tools::Long nCount = static_cast< tools::Long >( maLabelData.maShowInfo.ItemCount ); if( nCount < 1 ) nCount = SC_SHOW_DEFAULT; m_xNfShow->set_value( nCount ); // m_xLbShowUsing already filled above m_xLbShowUsing->set_active_text(maLabelData.maShowInfo.DataField); if (m_xLbShowUsing->get_active() == -1) m_xLbShowUsing->set_active(0); CheckHdl(*m_xCbShow); // enable/disable dependent controls // *** HIDDEN ITEMS *** InitHideListBox(); // *** HIERARCHY *** if( maLabelData.maHiers.getLength() > 1 ) { lclFillListBox(*m_xLbHierarchy, maLabelData.maHiers); sal_Int32 nHier = maLabelData.mnUsedHier; if( (nHier < 0) || (nHier >= maLabelData.maHiers.getLength()) ) nHier = 0; m_xLbHierarchy->set_active( nHier ); m_xLbHierarchy->connect_changed( LINK( this, ScDPSubtotalOptDlg, SelectHdl ) ); } else { m_xFtHierarchy->set_sensitive(false); m_xLbHierarchy->set_sensitive(false); } } void ScDPSubtotalOptDlg::InitHideListBox() { m_xLbHide->clear(); lclFillListBox(*m_xLbHide, maLabelData.maMembers); size_t n = maLabelData.maMembers.size(); for (size_t i = 0; i < n; ++i) m_xLbHide->set_toggle(i, maLabelData.maMembers[i].mbVisible ? TRISTATE_FALSE : TRISTATE_TRUE); bool bEnable = m_xLbHide->n_children() > 0; m_xHideFrame->set_sensitive(bEnable); } ScDPName ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const { NameMapType::const_iterator itr = maDataFieldNameMap.find(rLayoutName); return itr == maDataFieldNameMap.end() ? ScDPName() : itr->second; } sal_Int32 ScDPSubtotalOptDlg::FindListBoxEntry( const weld::ComboBox& rLBox, std::u16string_view rEntry, sal_Int32 nStartPos ) const { sal_Int32 nPos = nStartPos; bool bFound = false; while (nPos < rLBox.get_count()) { // translate the displayed field name back to its original field name. ScDPName aName = GetFieldName(rLBox.get_text(nPos)); OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aName.maName, aName.mnDupCount); if (aUnoName == rEntry) { bFound = true; break; } ++nPos; } return bFound ? nPos : -1; } IMPL_LINK(ScDPSubtotalOptDlg, ButtonClicked, weld::Button&, rButton, void) { if (&rButton == m_xBtnOk.get()) response(RET_OK); else response(RET_CANCEL); } IMPL_LINK(ScDPSubtotalOptDlg, CheckHdl, weld::Toggleable&, rCBox, void) { if (&rCBox == m_xCbShow.get()) { bool bEnable = m_xCbShow->get_active(); m_xNfShow->set_sensitive( bEnable ); m_xFtShow->set_sensitive( bEnable ); m_xFtShowFrom->set_sensitive( bEnable ); m_xLbShowFrom->set_sensitive( bEnable ); bool bEnableUsing = bEnable && (m_xLbShowUsing->get_count() > 0); m_xFtShowUsing->set_sensitive(bEnableUsing); m_xLbShowUsing->set_sensitive(bEnableUsing); } } IMPL_LINK_NOARG(ScDPSubtotalOptDlg, SelectHdl, weld::ComboBox&, void) { mrDPObj.GetMembers(maLabelData.mnCol, m_xLbHierarchy->get_active(), maLabelData.maMembers); InitHideListBox(); } ScDPShowDetailDlg::ScDPShowDetailDlg(weld::Window* pParent, ScDPObject& rDPObj, css::sheet::DataPilotFieldOrientation nOrient) : GenericDialogController(pParent, u"modules/scalc/ui/showdetaildialog.ui"_ustr, u"ShowDetail"_ustr) , mrDPObj(rDPObj) , mxLbDims(m_xBuilder->weld_tree_view(u"dimsTreeview"_ustr)) { ScDPSaveData* pSaveData = rDPObj.GetSaveData(); tools::Long nDimCount = rDPObj.GetDimCount(); for (tools::Long nDim=0; nDimGetExistingDimensionByName(aName) : nullptr; if ( !pDimension || (pDimension->GetOrientation() != nOrient) ) { if (pDimension) { const std::optional & pLayoutName = pDimension->GetLayoutName(); if (pLayoutName) aName = *pLayoutName; } mxLbDims->append_text(aName); maNameIndexMap.emplace(aName, nDim); } } } if (mxLbDims->n_children()) mxLbDims->select(0); mxLbDims->connect_row_activated(LINK(this, ScDPShowDetailDlg, DblClickHdl)); } ScDPShowDetailDlg::~ScDPShowDetailDlg() { } short ScDPShowDetailDlg::run() { return mxLbDims->n_children() ? GenericDialogController::run() : static_cast(RET_CANCEL); } OUString ScDPShowDetailDlg::GetDimensionName() const { // Look up the internal dimension name which may be different from the // displayed field name. OUString aSelectedName = mxLbDims->get_selected_text(); DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName); if (itr == maNameIndexMap.end()) // This should never happen! return aSelectedName; tools::Long nDim = itr->second; bool bIsDataLayout = false; return mrDPObj.GetDimName(nDim, bIsDataLayout); } IMPL_LINK_NOARG(ScDPShowDetailDlg, DblClickHdl, weld::TreeView&, bool) { m_xDialog->response(RET_OK); return true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */