diff options
Diffstat (limited to 'sc/source/ui/dbgui/consdlg.cxx')
-rw-r--r-- | sc/source/ui/dbgui/consdlg.cxx | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/sc/source/ui/dbgui/consdlg.cxx b/sc/source/ui/dbgui/consdlg.cxx new file mode 100644 index 000000000..1dde53c18 --- /dev/null +++ b/sc/source/ui/dbgui/consdlg.cxx @@ -0,0 +1,535 @@ +/* -*- 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 . + */ + +#include <sfx2/dispatch.hxx> + +#include <tabvwsh.hxx> +#include <uiitems.hxx> +#include <dbdata.hxx> +#include <rangenam.hxx> +#include <rangeutl.hxx> +#include <reffact.hxx> +#include <document.hxx> +#include <scresid.hxx> + +#include <globstr.hrc> +#include <strings.hrc> + +#include <consdlg.hxx> +#include <o3tl/safeint.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +namespace +{ + void INFOBOX(weld::Window* pWindow, TranslateId id) + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWindow, + VclMessageType::Info, VclButtonsType::Ok, + ScResId(id))); + xInfoBox->run(); + } +} + +class ScAreaData +{ +public: + ScAreaData() + { + } + + void Set( const OUString& rName, const OUString& rArea ) + { + aStrName = rName; + aStrArea = rArea; + } + + OUString aStrName; + OUString aStrArea; +}; + +ScConsolidateDlg::ScConsolidateDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, + const SfxItemSet& rArgSet) + + : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/consolidatedialog.ui", "ConsolidateDialog") + , aStrUndefined ( ScResId( SCSTR_UNDEFINED ) ) + , theConsData ( static_cast<const ScConsolidateItem&>( + rArgSet.Get( rArgSet.GetPool()-> + GetWhich( SID_CONSOLIDATE ) ) + ).GetData() ) + , rViewData ( static_cast<ScTabViewShell*>(SfxViewShell::Current())-> + GetViewData() ) + , rDoc ( static_cast<ScTabViewShell*>(SfxViewShell::Current())-> + GetViewData().GetDocument() ) + , nAreaDataCount ( 0 ) + , nWhichCons ( rArgSet.GetPool()->GetWhich( SID_CONSOLIDATE ) ) + , bDlgLostFocus ( false ) + , m_xLbFunc(m_xBuilder->weld_combo_box("func")) + , m_xLbConsAreas(m_xBuilder->weld_tree_view("consareas")) + , m_xLbDataArea(m_xBuilder->weld_combo_box("lbdataarea")) + , m_xEdDataArea(new formula::RefEdit(m_xBuilder->weld_entry("eddataarea"))) + , m_xRbDataArea(new formula::RefButton(m_xBuilder->weld_button("rbdataarea"))) + , m_xLbDestArea(m_xBuilder->weld_combo_box("lbdestarea")) + , m_xEdDestArea(new formula::RefEdit(m_xBuilder->weld_entry("eddestarea"))) + , m_xRbDestArea(new formula::RefButton(m_xBuilder->weld_button("rbdestarea"))) + , m_xExpander(m_xBuilder->weld_expander("more")) + , m_xBtnByRow(m_xBuilder->weld_check_button("byrow")) + , m_xBtnByCol(m_xBuilder->weld_check_button("bycol")) + , m_xBtnRefs(m_xBuilder->weld_check_button("refs")) + , m_xBtnOk(m_xBuilder->weld_button("ok")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnRemove(m_xBuilder->weld_button("delete")) + , m_xDataFT(m_xBuilder->weld_label("ftdataarea")) + , m_xDestFT(m_xBuilder->weld_label("ftdestarea")) +{ + m_pRefInputEdit = m_xEdDataArea.get(); + Init(); +} + +ScConsolidateDlg::~ScConsolidateDlg() +{ +} + +void ScConsolidateDlg::Init() +{ + OUString aStr; + sal_uInt16 i=0; + + m_xRbDataArea->SetReferences(this, m_xEdDataArea.get()); + m_xEdDataArea->SetReferences(this, m_xDataFT.get()); + m_xRbDestArea->SetReferences(this, m_xEdDestArea.get()); + m_xEdDestArea->SetReferences(this, m_xDestFT.get()); + + m_xEdDataArea->SetGetFocusHdl( LINK( this, ScConsolidateDlg, GetEditFocusHdl ) ); + m_xEdDestArea->SetGetFocusHdl( LINK( this, ScConsolidateDlg, GetEditFocusHdl ) ); + m_xLbDataArea->connect_focus_in( LINK( this, ScConsolidateDlg, GetFocusHdl ) ); + m_xLbDestArea->connect_focus_in( LINK( this, ScConsolidateDlg, GetFocusHdl ) ); + m_xEdDataArea->SetModifyHdl( LINK( this, ScConsolidateDlg, ModifyHdl ) ); + m_xEdDestArea->SetModifyHdl( LINK( this, ScConsolidateDlg, ModifyHdl ) ); + m_xLbConsAreas->connect_changed( LINK( this, ScConsolidateDlg, SelectTVHdl ) ); + m_xLbDataArea->connect_changed( LINK( this, ScConsolidateDlg, SelectCBHdl ) ); + m_xLbDestArea->connect_changed( LINK( this, ScConsolidateDlg, SelectCBHdl ) ); + m_xBtnOk->connect_clicked( LINK( this, ScConsolidateDlg, OkHdl ) ); + m_xBtnCancel->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) ); + m_xBtnAdd->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) ); + m_xBtnRemove->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) ); + + m_xBtnAdd->set_sensitive(false); + m_xBtnRemove->set_sensitive(false); + + m_xBtnByRow->set_active( theConsData.bByRow ); + m_xBtnByCol->set_active( theConsData.bByCol ); + m_xBtnRefs->set_active( theConsData.bReferenceData ); + + m_xLbFunc->set_active( FuncToLbPos( theConsData.eFunction ) ); + + m_xLbConsAreas->set_selection_mode(SelectionMode::Multiple); + m_xLbConsAreas->set_size_request(m_xLbConsAreas->get_approximate_digit_width() * 16, + m_xLbConsAreas->get_height_rows(5)); + + // read consolidation areas + m_xLbConsAreas->clear(); + const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); + for ( i=0; i<theConsData.nDataAreaCount; i++ ) + { + const ScArea& rArea = theConsData.pDataAreas[i]; + if ( rArea.nTab < rDoc.GetTableCount() ) + { + aStr = ScRange( rArea.nColStart, rArea.nRowStart, rArea.nTab, + rArea.nColEnd, rArea.nRowEnd, rArea.nTab ).Format( rDoc, + ScRefFlags::RANGE_ABS_3D, eConv ); + m_xLbConsAreas->append_text(aStr); + } + } + + if ( theConsData.nTab < rDoc.GetTableCount() ) + { + aStr = ScAddress( theConsData.nCol, theConsData.nRow, theConsData.nTab + ).Format( ScRefFlags::ADDR_ABS_3D, &rDoc, eConv ); + m_xEdDestArea->SetText( aStr ); + } + else + m_xEdDestArea->SetText(OUString()); + + // Use the ScAreaData helper class to save those range names from the + // RangeNames and database ranges that appear in the ListBoxes. + + ScRangeName* pRangeNames = rDoc.GetRangeName(); + ScDBCollection* pDbNames = rDoc.GetDBCollection(); + size_t nRangeCount = pRangeNames ? pRangeNames->size() : 0; + size_t nDbCount = pDbNames ? pDbNames->getNamedDBs().size() : 0; + + nAreaDataCount = nRangeCount+nDbCount; + pAreaData = nullptr; + + if ( nAreaDataCount > 0 ) + { + pAreaData.reset( new ScAreaData[nAreaDataCount] ); + + OUString aStrName; + sal_uInt16 nAt = 0; + ScRange aRange; + ScAreaNameIterator aIter( rDoc ); + while ( aIter.Next( aStrName, aRange ) ) + { + OUString aStrArea(aRange.Format(rDoc, ScRefFlags::ADDR_ABS_3D, eConv)); + pAreaData[nAt++].Set( aStrName, aStrArea ); + } + } + + FillAreaLists(); + ModifyHdl( *m_xEdDestArea ); + m_xLbDataArea->set_active( 0 ); + m_xEdDataArea->SetText(OUString()); + m_xEdDataArea->GrabFocus(); + + //aFlSep.SetStyle( aFlSep.GetStyle() | WB_VERT ); + + //@BugID 54702 enable/disable only in base class + //SFX_APPWINDOW->set_sensitive(true); +} + +void ScConsolidateDlg::FillAreaLists() +{ + m_xLbDataArea->clear(); + m_xLbDestArea->clear(); + m_xLbDataArea->append_text( aStrUndefined ); + m_xLbDestArea->append_text( aStrUndefined ); + + if ( pAreaData && (nAreaDataCount > 0) ) + { + for ( size_t i=0; + (i<nAreaDataCount) && (!pAreaData[i].aStrName.isEmpty()); + i++ ) + { + m_xLbDataArea->append_text(pAreaData[i].aStrName); + m_xLbDestArea->append_text(pAreaData[i].aStrName); + } + } +} + +// Handover of a range within a table that has been selected by the mouse. +// This range is then shown in the reference window as new selection. + +void ScConsolidateDlg::SetReference( const ScRange& rRef, ScDocument& rDocP ) +{ + if ( !m_pRefInputEdit ) + return; + + if ( rRef.aStart != rRef.aEnd ) + RefInputStart( m_pRefInputEdit ); + + OUString aStr; + ScRefFlags nFmt = ScRefFlags::RANGE_ABS_3D; //!!! nCurTab is still missing + const formula::FormulaGrammar::AddressConvention eConv = rDocP.GetAddressConvention(); + + if ( rRef.aStart.Tab() != rRef.aEnd.Tab() ) + nFmt |= ScRefFlags::TAB2_3D; + + if ( m_pRefInputEdit == m_xEdDataArea.get()) + aStr = rRef.Format(rDocP, nFmt, eConv); + else if ( m_pRefInputEdit == m_xEdDestArea.get() ) + aStr = rRef.aStart.Format(nFmt, &rDocP, eConv); + + m_pRefInputEdit->SetRefString( aStr ); + ModifyHdl( *m_pRefInputEdit ); +} + +void ScConsolidateDlg::Close() +{ + DoClose( ScConsolidateDlgWrapper::GetChildWindowId() ); +} + +void ScConsolidateDlg::SetActive() +{ + if ( bDlgLostFocus ) + { + bDlgLostFocus = false; + + if ( m_pRefInputEdit ) + { + m_pRefInputEdit->GrabFocus(); + ModifyHdl( *m_pRefInputEdit ); + } + } + else + m_xDialog->grab_focus(); + + RefInputDone(); +} + +void ScConsolidateDlg::Deactivate() +{ + bDlgLostFocus = true; +} + +bool ScConsolidateDlg::VerifyEdit( formula::RefEdit* pEd ) +{ + if (pEd != m_xEdDataArea.get() && pEd != m_xEdDestArea.get()) + return false; + + SCTAB nTab = rViewData.GetTabNo(); + bool bEditOk = false; + OUString theCompleteStr; + const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); + + if ( pEd == m_xEdDataArea.get() ) + { + bEditOk = ScRangeUtil::IsAbsArea( pEd->GetText(), rDoc, + nTab, &theCompleteStr, nullptr, nullptr, eConv ); + } + else if ( pEd == m_xEdDestArea.get() ) + { + OUString aPosStr; + + ScRangeUtil::CutPosString( pEd->GetText(), aPosStr ); + bEditOk = ScRangeUtil::IsAbsPos( aPosStr, rDoc, + nTab, &theCompleteStr, nullptr, eConv ); + } + + if ( bEditOk ) + pEd->SetText( theCompleteStr ); + + return bEditOk; +} + +// Handler: + +IMPL_LINK( ScConsolidateDlg, GetEditFocusHdl, formula::RefEdit&, rControl, void ) +{ + m_pRefInputEdit = &rControl; +} + +IMPL_LINK( ScConsolidateDlg, GetFocusHdl, weld::Widget&, rControl, void ) +{ + if (&rControl == m_xLbDataArea.get()) + m_pRefInputEdit = m_xEdDataArea.get(); + else if (&rControl == m_xLbDestArea.get()) + m_pRefInputEdit = m_xEdDestArea.get(); +} + +IMPL_LINK_NOARG(ScConsolidateDlg, OkHdl, weld::Button&, void) +{ + const sal_Int32 nDataAreaCount = m_xLbConsAreas->n_children(); + + if ( nDataAreaCount > 0 ) + { + ScRefAddress aDestAddress; + SCTAB nTab = rViewData.GetTabNo(); + OUString aDestPosStr( m_xEdDestArea->GetText() ); + const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); + + if ( ScRangeUtil::IsAbsPos( aDestPosStr, rDoc, nTab, nullptr, &aDestAddress, eConv ) ) + { + ScConsolidateParam theOutParam( theConsData ); + std::unique_ptr<ScArea[]> pDataAreas(new ScArea[nDataAreaCount]); + + for ( sal_Int32 i=0; i<nDataAreaCount; ++i ) + { + ScRangeUtil::MakeArea(m_xLbConsAreas->get_text(i), + pDataAreas[i], rDoc, nTab, eConv); + } + + theOutParam.nCol = aDestAddress.Col(); + theOutParam.nRow = aDestAddress.Row(); + theOutParam.nTab = aDestAddress.Tab(); + theOutParam.eFunction = LbPosToFunc( m_xLbFunc->get_active() ); + theOutParam.bByCol = m_xBtnByCol->get_active(); + theOutParam.bByRow = m_xBtnByRow->get_active(); + theOutParam.bReferenceData = m_xBtnRefs->get_active(); + theOutParam.SetAreas( std::move(pDataAreas), nDataAreaCount ); + + ScConsolidateItem aOutItem( nWhichCons, &theOutParam ); + + SetDispatcherLock( false ); + SwitchToDocument(); + GetBindings().GetDispatcher()->ExecuteList(SID_CONSOLIDATE, + SfxCallMode::SLOT | SfxCallMode::RECORD, + { &aOutItem }); + response(RET_OK); + } + else + { + INFOBOX(m_xDialog.get(), STR_INVALID_TABREF); + m_xEdDestArea->GrabFocus(); + } + } + else + response(RET_CANCEL); // no area defined -> Cancel +} + +IMPL_LINK( ScConsolidateDlg, ClickHdl, weld::Button&, rBtn, void ) +{ + if ( &rBtn == m_xBtnCancel.get() ) + response(RET_CANCEL); + else if ( &rBtn == m_xBtnAdd.get() ) + { + if ( !m_xEdDataArea->GetText().isEmpty() ) + { + OUString aNewEntry( m_xEdDataArea->GetText() ); + std::unique_ptr<ScArea[]> ppAreas; + sal_uInt16 nAreaCount = 0; + const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); + + if ( ScRangeUtil::IsAbsTabArea( aNewEntry, &rDoc, &ppAreas, &nAreaCount, true, eConv ) ) + { + // IsAbsTabArea() creates an array of ScArea pointers, + // which have been created dynamically as well. + // These objects need to be deleted here. + + for ( sal_uInt16 i=0; i<nAreaCount; i++ ) + { + const ScArea& rArea = ppAreas[i]; + OUString aNewArea = ScRange( rArea.nColStart, rArea.nRowStart, rArea.nTab, + rArea.nColEnd, rArea.nRowEnd, rArea.nTab + ).Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv); + + if (m_xLbConsAreas->find_text(aNewArea) == -1) + { + m_xLbConsAreas->append_text( aNewArea ); + } + } + } + else if ( VerifyEdit( m_xEdDataArea.get() ) ) + { + OUString aNewArea( m_xEdDataArea->GetText() ); + + if (m_xLbConsAreas->find_text(aNewArea) == -1) + m_xLbConsAreas->append_text(aNewArea); + else + INFOBOX(m_xDialog.get(), STR_AREA_ALREADY_INSERTED); + } + else + { + INFOBOX(m_xDialog.get(), STR_INVALID_TABREF); + m_xEdDataArea->GrabFocus(); + } + } + } + else if ( &rBtn == m_xBtnRemove.get() ) + { + std::vector<int> aSelectedRows(m_xLbConsAreas->get_selected_rows()); + std::sort(aSelectedRows.begin(), aSelectedRows.end()); + for (auto it = aSelectedRows.rbegin(); it != aSelectedRows.rend(); ++it) + m_xLbConsAreas->remove(*it); + m_xBtnRemove->set_sensitive(false); + } +} + +IMPL_LINK( ScConsolidateDlg, SelectTVHdl, weld::TreeView&, rLb, void ) +{ + if (rLb.get_selected_index() != -1) + m_xBtnRemove->set_sensitive(true); + else + m_xBtnRemove->set_sensitive(false); +} + +IMPL_LINK( ScConsolidateDlg, SelectCBHdl, weld::ComboBox&, rLb, void ) +{ + formula::RefEdit* pEd = (&rLb == m_xLbDataArea.get()) ? m_xEdDataArea.get() : m_xEdDestArea.get(); + const sal_Int32 nSelPos = rLb.get_active(); + + if ( (nSelPos > 0) + && (nAreaDataCount > 0) + && (pAreaData != nullptr) ) + { + if ( o3tl::make_unsigned(nSelPos) <= nAreaDataCount ) + { + OUString aString( pAreaData[nSelPos-1].aStrArea ); + + if ( &rLb == m_xLbDestArea.get() ) + ScRangeUtil::CutPosString( aString, aString ); + + pEd->SetText( aString ); + + if ( pEd == m_xEdDataArea.get() ) + m_xBtnAdd->set_sensitive(true); + } + } + else + { + pEd->SetText( OUString() ); + if ( pEd == m_xEdDataArea.get() ) + m_xBtnAdd->set_sensitive(true); + } +} + +IMPL_LINK( ScConsolidateDlg, ModifyHdl, formula::RefEdit&, rEd, void ) +{ + if ( &rEd == m_xEdDataArea.get() ) + { + OUString aAreaStr( rEd.GetText() ); + if ( !aAreaStr.isEmpty() ) + m_xBtnAdd->set_sensitive(true); + else + m_xBtnAdd->set_sensitive(false); + } + else if ( &rEd == m_xEdDestArea.get() ) + { + m_xLbDestArea->set_active(0); + } +} + +// TODO: generalize! +// Resource of the ListBox and these two conversion methods are also in +// tpsubt and everywhere, where StarCalc functions are selectable. + +ScSubTotalFunc ScConsolidateDlg::LbPosToFunc( sal_Int32 nPos ) +{ + switch ( nPos ) + { + case 2: return SUBTOTAL_FUNC_AVE; + case 6: return SUBTOTAL_FUNC_CNT; + case 1: return SUBTOTAL_FUNC_CNT2; + case 3: return SUBTOTAL_FUNC_MAX; + case 4: return SUBTOTAL_FUNC_MIN; + case 5: return SUBTOTAL_FUNC_PROD; + case 7: return SUBTOTAL_FUNC_STD; + case 8: return SUBTOTAL_FUNC_STDP; + case 9: return SUBTOTAL_FUNC_VAR; + case 10: return SUBTOTAL_FUNC_VARP; + case 0: + default: + return SUBTOTAL_FUNC_SUM; + } +} + +sal_Int32 ScConsolidateDlg::FuncToLbPos( ScSubTotalFunc eFunc ) +{ + switch ( eFunc ) + { + case SUBTOTAL_FUNC_AVE: return 2; + case SUBTOTAL_FUNC_CNT: return 6; + case SUBTOTAL_FUNC_CNT2: return 1; + case SUBTOTAL_FUNC_MAX: return 3; + case SUBTOTAL_FUNC_MIN: return 4; + case SUBTOTAL_FUNC_PROD: return 5; + case SUBTOTAL_FUNC_STD: return 7; + case SUBTOTAL_FUNC_STDP: return 8; + case SUBTOTAL_FUNC_VAR: return 9; + case SUBTOTAL_FUNC_VARP: return 10; + case SUBTOTAL_FUNC_NONE: + case SUBTOTAL_FUNC_SUM: + default: + return 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |