/* -*- 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 <scitems.hxx>
#include <uiitems.hxx>
#include <global.hxx>
#include <userlist.hxx>
#include <viewdata.hxx>
#include <document.hxx>
#include <scresid.hxx>
#include <sc.hrc>
#include <strings.hrc>
#include <subtdlg.hxx>
#include <tpsubt.hxx>
#include <memory>
// Subtotals group tabpage:
ScTpSubTotalGroup::ScTpSubTotalGroup( vcl::Window* pParent,
const SfxItemSet& rArgSet )
: SfxTabPage ( pParent,
"SubTotalGrpPage", "modules/scalc/ui/subtotalgrppage.ui",
&rArgSet ),
aStrNone ( ScResId( SCSTR_NONE ) ),
aStrColumn ( ScResId( SCSTR_COLUMN ) ),
pViewData ( nullptr ),
pDoc ( nullptr ),
nWhichSubTotals ( rArgSet.GetPool()->GetWhich( SID_SUBTOTALS ) ),
rSubTotalData ( static_cast<const ScSubTotalItem&>(
rArgSet.Get( nWhichSubTotals )).
GetSubTotalData() ),
nFieldCount ( 0 )
{
get(mpLbGroup, "group_by");
get(mpLbColumns, "columns");
get(mpLbFunctions, "functions");
long nHeight = mpLbColumns->GetTextHeight() * 14;
mpLbColumns->set_height_request(nHeight);
mpLbFunctions->set_height_request(nHeight);
// Font is correctly initialized by SvTreeListBox ctor
mpLbColumns->SetSelectionMode( SelectionMode::Single );
mpLbColumns->SetDragDropMode( DragDropMode::NONE );
mpLbColumns->SetSpaceBetweenEntries( 0 );
Init ();
}
ScTpSubTotalGroup::~ScTpSubTotalGroup()
{
disposeOnce();
}
void ScTpSubTotalGroup::dispose()
{
sal_uLong nCount = mpLbColumns->GetEntryCount();
if ( nCount > 0 )
{
for ( sal_uLong i=0; i<nCount; i++ )
{
sal_uInt16* pData = static_cast<sal_uInt16*>(mpLbColumns->GetEntryData( i ));
OSL_ENSURE( pData, "EntryData not found" );
delete pData;
}
}
mpLbGroup.clear();
mpLbColumns.clear();
mpLbFunctions.clear();
SfxTabPage::dispose();
}
void ScTpSubTotalGroup::Init()
{
const ScSubTotalItem& rSubTotalItem = static_cast<const ScSubTotalItem&>(
GetItemSet().Get( nWhichSubTotals ));
pViewData = rSubTotalItem.GetViewData();
pDoc = ( pViewData ) ? pViewData->GetDocument() : nullptr;
OSL_ENSURE( pViewData && pDoc, "ViewData or Document not found :-(" );
mpLbGroup->SetSelectHdl ( LINK( this, ScTpSubTotalGroup, SelectListBoxHdl ) );
mpLbColumns->SetSelectHdl ( LINK( this, ScTpSubTotalGroup, SelectTreeListBoxHdl ) );
mpLbColumns->SetCheckButtonHdl( LINK( this, ScTpSubTotalGroup, CheckHdl ) );
mpLbFunctions->SetSelectHdl ( LINK( this, ScTpSubTotalGroup, SelectListBoxHdl ) );
nFieldArr[0] = 0;
FillListBoxes();
}
bool ScTpSubTotalGroup::DoReset( sal_uInt16 nGroupNo,
const SfxItemSet& rArgSet )
{
sal_uInt16 nGroupIdx = 0;
OSL_ENSURE( (nGroupNo<=3) && (nGroupNo>0), "Invalid group" );
if ( (nGroupNo > 3) || (nGroupNo == 0) )
return false;
else
nGroupIdx = nGroupNo-1;
// first we have to clear the listboxes...
for ( sal_uLong nLbEntry = 0; nLbEntry < mpLbColumns->GetEntryCount(); ++nLbEntry )
{
mpLbColumns->CheckEntryPos( nLbEntry, false );
*static_cast<sal_uInt16*>(mpLbColumns->GetEntryData( nLbEntry )) = 0;
}
mpLbFunctions->SelectEntryPos( 0 );
ScSubTotalParam theSubTotalData( static_cast<const ScSubTotalItem&>(
rArgSet.Get( nWhichSubTotals )).
GetSubTotalData() );
if ( theSubTotalData.bGroupActive[nGroupIdx] )
{
SCCOL nField = theSubTotalData.nField[nGroupIdx];
SCCOL nSubTotals = theSubTotalData.nSubTotals[nGroupIdx];
SCCOL* pSubTotals = theSubTotalData.pSubTotals[nGroupIdx];
ScSubTotalFunc* pFunctions = theSubTotalData.pFunctions[nGroupIdx];
mpLbGroup->SelectEntryPos( GetFieldSelPos( nField )+1 );
sal_uInt16 nFirstChecked = 0;
for ( sal_uInt16 i=0; i<nSubTotals; i++ )
{
sal_uInt16 nCheckPos = GetFieldSelPos( pSubTotals[i] );
sal_uInt16* pFunction = static_cast<sal_uInt16*>(mpLbColumns->GetEntryData( nCheckPos ));
mpLbColumns->CheckEntryPos( nCheckPos );
*pFunction = FuncToLbPos( pFunctions[i] );
if (i == 0 || (i > 0 && nCheckPos < nFirstChecked))
nFirstChecked = nCheckPos;
}
// Select the first checked field from the top.
mpLbColumns->SelectEntryPos(nFirstChecked);
}
else
{
mpLbGroup->SelectEntryPos( (nGroupNo == 1) ? 1 : 0 );
mpLbColumns->SelectEntryPos( 0 );
mpLbFunctions->SelectEntryPos( 0 );
}
return true;
}
bool ScTpSubTotalGroup::DoFillItemSet( sal_uInt16 nGroupNo,
SfxItemSet& rArgSet )
{
sal_uInt16 nGroupIdx = 0;
OSL_ENSURE( (nGroupNo<=3) && (nGroupNo>0), "Invalid group" );
OSL_ENSURE( (mpLbGroup->GetEntryCount() > 0)
&& (mpLbColumns->GetEntryCount() > 0)
&& (mpLbFunctions->GetEntryCount() > 0),
"Non-initialized Lists" );
if ( (nGroupNo > 3) || (nGroupNo == 0)
|| (mpLbGroup->GetEntryCount() == 0)
|| (mpLbColumns->GetEntryCount() == 0)
|| (mpLbFunctions->GetEntryCount() == 0)
)
return false;
else
nGroupIdx = nGroupNo-1;
ScSubTotalParam theSubTotalData; // read out, if already partly filled
SfxTabDialog* pDlg = GetTabDialog();
if ( pDlg )
{
const SfxItemSet* pExample = pDlg->GetExampleSet();
const SfxPoolItem* pItem;
if ( pExample && pExample->GetItemState( nWhichSubTotals, true, &pItem ) == SfxItemState::SET )
theSubTotalData = static_cast<const ScSubTotalItem*>(pItem)->GetSubTotalData();
}
std::unique_ptr<ScSubTotalFunc[]> pFunctions;
std::unique_ptr<SCCOL[]> pSubTotals;
const sal_Int32 nGroup = mpLbGroup->GetSelectedEntryPos();
const sal_Int32 nEntryCount = mpLbColumns->GetEntryCount();
const sal_Int32 nCheckCount = mpLbColumns->GetCheckedEntryCount();
theSubTotalData.nCol1 = rSubTotalData.nCol1;
theSubTotalData.nRow1 = rSubTotalData.nRow1;
theSubTotalData.nCol2 = rSubTotalData.nCol2;
theSubTotalData.nRow2 = rSubTotalData.nRow2;
theSubTotalData.bGroupActive[nGroupIdx] = (nGroup != 0);
theSubTotalData.nField[nGroupIdx] = (nGroup != 0)
? nFieldArr[nGroup-1]
: static_cast<SCCOL>(0);
if ( nEntryCount>0 && nCheckCount>0 && nGroup!=0 )
{
sal_uInt16 nFunction = 0;
pSubTotals.reset(new SCCOL [nCheckCount]);
pFunctions.reset(new ScSubTotalFunc [nCheckCount]);
for ( sal_Int32 i=0, nCheck=0; i<nEntryCount; i++ )
{
if ( mpLbColumns->IsChecked( i ) )
{
OSL_ENSURE( nCheck <= nCheckCount,
"Range error :-(" );
nFunction = *static_cast<sal_uInt16*>(mpLbColumns->GetEntryData( i ));
pSubTotals[nCheck] = nFieldArr[i];
pFunctions[nCheck] = LbPosToFunc( nFunction );
nCheck++;
}
}
theSubTotalData.SetSubTotals( nGroupNo, // group number
pSubTotals.get(),
pFunctions.get(),
nCheckCount ); // number of array elements
}
rArgSet.Put( ScSubTotalItem( SCITEM_SUBTDATA, &theSubTotalData ) );
return true;
}
void ScTpSubTotalGroup::FillListBoxes()
{
OSL_ENSURE( pViewData && pDoc, "ViewData or Document not found :-/" );
if ( pViewData && pDoc )
{
SCCOL nFirstCol = rSubTotalData.nCol1;
SCROW nFirstRow = rSubTotalData.nRow1;
SCTAB nTab = pViewData->GetTabNo();
SCCOL nMaxCol = rSubTotalData.nCol2;
SCCOL col;
OUString aFieldName;
mpLbGroup->Clear();
mpLbColumns->Clear();
mpLbGroup->InsertEntry( aStrNone, 0 );
sal_uInt16 i=0;
for ( col=nFirstCol; col<=nMaxCol && i<SC_MAXFIELDS; col++ )
{
aFieldName = pDoc->GetString(col, nFirstRow, nTab);
if ( aFieldName.isEmpty() )
{
aFieldName = ScGlobal::ReplaceOrAppend( aStrColumn, "%1", ScColToAlpha( col ));
}
nFieldArr[i] = col;
mpLbGroup->InsertEntry( aFieldName, i+1 );
mpLbColumns->InsertEntry( aFieldName, i );
mpLbColumns->SetEntryData( i, new sal_uInt16(0) );
i++;
}
// subsequent initialization of the constant:
const_cast<sal_uInt16&>(nFieldCount) = i;
}
}
sal_uInt16 ScTpSubTotalGroup::GetFieldSelPos( SCCOL nField )
{
sal_uInt16 nFieldPos = 0;
bool bFound = false;
for ( sal_uInt16 n=0; n<nFieldCount && !bFound; n++ )
{
if ( nFieldArr[n] == nField )
{
nFieldPos = n;
bFound = true;
}
}
return nFieldPos;
}
ScSubTotalFunc ScTpSubTotalGroup::LbPosToFunc( sal_uInt16 nPos )
{
switch ( nPos )
{
// case 0: return SUBTOTAL_FUNC_NONE;
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 0: return SUBTOTAL_FUNC_SUM;
case 9: return SUBTOTAL_FUNC_VAR;
case 10: return SUBTOTAL_FUNC_VARP;
default:
OSL_FAIL( "ScTpSubTotalGroup::LbPosToFunc" );
return SUBTOTAL_FUNC_NONE;
}
}
sal_uInt16 ScTpSubTotalGroup::FuncToLbPos( ScSubTotalFunc eFunc )
{
switch ( eFunc )
{
// case SUBTOTAL_FUNC_NONE: return 0;
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_SUM: return 0;
case SUBTOTAL_FUNC_VAR: return 9;
case SUBTOTAL_FUNC_VARP: return 10;
default:
OSL_FAIL( "ScTpSubTotalGroup::FuncToLbPos" );
return 0;
}
}
// Handler:
IMPL_LINK( ScTpSubTotalGroup, SelectTreeListBoxHdl, SvTreeListBox*, pLb, void )
{
SelectHdl(pLb);
}
IMPL_LINK( ScTpSubTotalGroup, SelectListBoxHdl, ListBox&, rLb, void )
{
SelectHdl(&rLb);
}
void ScTpSubTotalGroup::SelectHdl(const void *pLb)
{
if ( (mpLbColumns->GetEntryCount() > 0)
&& (mpLbColumns->GetSelectionCount() > 0) )
{
const sal_Int32 nFunction = mpLbFunctions->GetSelectedEntryPos();
const sal_Int32 nColumn = mpLbColumns->GetSelectedEntryPos();
sal_uInt16* pFunction = static_cast<sal_uInt16*>(mpLbColumns->GetEntryData( nColumn ));
OSL_ENSURE( pFunction, "EntryData not found!" );
if ( !pFunction )
return;
if ( pLb == mpLbColumns )
{
mpLbFunctions->SelectEntryPos( *pFunction );
}
else if ( pLb == mpLbFunctions )
{
*pFunction = static_cast<sal_uInt16>(nFunction);
mpLbColumns->CheckEntryPos( nColumn );
}
}
}
IMPL_LINK( ScTpSubTotalGroup, CheckHdl, SvTreeListBox*, pLb, void )
{
if ( pLb == mpLbColumns )
{
SvTreeListEntry* pEntry = mpLbColumns->GetHdlEntry();
if ( pEntry )
{
mpLbColumns->SelectEntryPos( static_cast<sal_uInt16>(mpLbColumns->GetModel()->GetAbsPos( pEntry )) );
SelectHdl( pLb );
}
}
}
// Derived Group TabPages:
VclPtr<SfxTabPage> ScTpSubTotalGroup1::Create( TabPageParent pParent,
const SfxItemSet* rArgSet )
{
return VclPtr<ScTpSubTotalGroup1>::Create( pParent.pParent, *rArgSet );
}
VclPtr<SfxTabPage> ScTpSubTotalGroup2::Create( TabPageParent pParent,
const SfxItemSet* rArgSet )
{
return VclPtr<ScTpSubTotalGroup2>::Create( pParent.pParent, *rArgSet );
}
VclPtr<SfxTabPage> ScTpSubTotalGroup3::Create( TabPageParent pParent,
const SfxItemSet* rArgSet )
{
return VclPtr<ScTpSubTotalGroup3>::Create( pParent.pParent, *rArgSet );
}
ScTpSubTotalGroup1::ScTpSubTotalGroup1( vcl::Window* pParent, const SfxItemSet& rArgSet ) :
ScTpSubTotalGroup( pParent, rArgSet )
{}
ScTpSubTotalGroup2::ScTpSubTotalGroup2( vcl::Window* pParent, const SfxItemSet& rArgSet ) :
ScTpSubTotalGroup( pParent, rArgSet )
{}
ScTpSubTotalGroup3::ScTpSubTotalGroup3( vcl::Window* pParent, const SfxItemSet& rArgSet ) :
ScTpSubTotalGroup( pParent, rArgSet )
{}
#define RESET(i) (ScTpSubTotalGroup::DoReset( (i), *rArgSet ))
void ScTpSubTotalGroup1::Reset( const SfxItemSet* rArgSet ) { RESET(1); }
void ScTpSubTotalGroup2::Reset( const SfxItemSet* rArgSet ) { RESET(2); }
void ScTpSubTotalGroup3::Reset( const SfxItemSet* rArgSet ) { RESET(3); }
#undef RESET
#define FILLSET(i) (ScTpSubTotalGroup::DoFillItemSet( (i), *rArgSet ))
bool ScTpSubTotalGroup1::FillItemSet( SfxItemSet* rArgSet ) { return FILLSET(1); }
bool ScTpSubTotalGroup2::FillItemSet( SfxItemSet* rArgSet ) { return FILLSET(2); }
bool ScTpSubTotalGroup3::FillItemSet( SfxItemSet* rArgSet ) { return FILLSET(3); }
#undef FILL
// options tab page:
ScTpSubTotalOptions::ScTpSubTotalOptions( vcl::Window* pParent,
const SfxItemSet& rArgSet )
: SfxTabPage ( pParent,
"SubTotalOptionsPage", "modules/scalc/ui/subtotaloptionspage.ui" ,
&rArgSet ),
pViewData ( nullptr ),
pDoc ( nullptr ),
nWhichSubTotals ( rArgSet.GetPool()->GetWhich( SID_SUBTOTALS ) ),
rSubTotalData ( static_cast<const ScSubTotalItem&>(
rArgSet.Get( nWhichSubTotals )).
GetSubTotalData() )
{
get(pBtnPagebreak,"pagebreak");
get(pBtnCase,"case");
get(pBtnSort,"sort");
get(pFlSort,"label2");
get(pBtnAscending,"ascending");
get(pBtnDescending,"descending");
get(pBtnFormats,"formats");
get(pBtnUserDef,"btnuserdef");
get(pLbUserDef,"lbuserdef");
Init();
}
ScTpSubTotalOptions::~ScTpSubTotalOptions()
{
disposeOnce();
}
void ScTpSubTotalOptions::dispose()
{
pBtnPagebreak.clear();
pBtnCase.clear();
pBtnSort.clear();
pFlSort.clear();
pBtnAscending.clear();
pBtnDescending.clear();
pBtnFormats.clear();
pBtnUserDef.clear();
pLbUserDef.clear();
SfxTabPage::dispose();
}
void ScTpSubTotalOptions::Init()
{
const ScSubTotalItem& rSubTotalItem = static_cast<const ScSubTotalItem&>(
GetItemSet().Get( nWhichSubTotals ));
pViewData = rSubTotalItem.GetViewData();
pDoc = ( pViewData ) ? pViewData->GetDocument() : nullptr;
OSL_ENSURE( pViewData && pDoc, "ViewData or Document not found!" );
pBtnSort->SetClickHdl ( LINK( this, ScTpSubTotalOptions, CheckHdl ) );
pBtnUserDef->SetClickHdl ( LINK( this, ScTpSubTotalOptions, CheckHdl ) );
FillUserSortListBox();
}
VclPtr<SfxTabPage> ScTpSubTotalOptions::Create( TabPageParent pParent,
const SfxItemSet* rArgSet )
{
return VclPtr<ScTpSubTotalOptions>::Create( pParent.pParent, *rArgSet );
}
void ScTpSubTotalOptions::Reset( const SfxItemSet* /* rArgSet */ )
{
pBtnPagebreak->Check ( rSubTotalData.bPagebreak );
pBtnCase->Check ( rSubTotalData.bCaseSens );
pBtnFormats->Check ( rSubTotalData.bIncludePattern );
pBtnSort->Check ( rSubTotalData.bDoSort );
pBtnAscending->Check ( rSubTotalData.bAscending );
pBtnDescending->Check( !rSubTotalData.bAscending );
if ( rSubTotalData.bUserDef )
{
pBtnUserDef->Check();
pLbUserDef->Enable();
pLbUserDef->SelectEntryPos( rSubTotalData.nUserIndex );
}
else
{
pBtnUserDef->Check( false );
pLbUserDef->Disable();
pLbUserDef->SelectEntryPos( 0 );
}
CheckHdl( pBtnSort );
}
bool ScTpSubTotalOptions::FillItemSet( SfxItemSet* rArgSet )
{
ScSubTotalParam theSubTotalData; // read out, if already partly filled
SfxTabDialog* pDlg = GetTabDialog();
if ( pDlg )
{
const SfxItemSet* pExample = pDlg->GetExampleSet();
const SfxPoolItem* pItem;
if ( pExample && pExample->GetItemState( nWhichSubTotals, true, &pItem ) == SfxItemState::SET )
theSubTotalData = static_cast<const ScSubTotalItem*>(pItem)->GetSubTotalData();
}
theSubTotalData.bPagebreak = pBtnPagebreak->IsChecked();
theSubTotalData.bReplace = true;
theSubTotalData.bCaseSens = pBtnCase->IsChecked();
theSubTotalData.bIncludePattern = pBtnFormats->IsChecked();
theSubTotalData.bDoSort = pBtnSort->IsChecked();
theSubTotalData.bAscending = pBtnAscending->IsChecked();
theSubTotalData.bUserDef = pBtnUserDef->IsChecked();
theSubTotalData.nUserIndex = (pBtnUserDef->IsChecked())
? pLbUserDef->GetSelectedEntryPos()
: 0;
rArgSet->Put( ScSubTotalItem( nWhichSubTotals, &theSubTotalData ) );
return true;
}
void ScTpSubTotalOptions::FillUserSortListBox()
{
ScUserList* pUserLists = ScGlobal::GetUserList();
pLbUserDef->Clear();
if ( pUserLists )
{
size_t nCount = pUserLists->size();
for ( size_t i=0; i<nCount; ++i )
pLbUserDef->InsertEntry( (*pUserLists)[i].GetString() );
}
}
// Handler:
IMPL_LINK( ScTpSubTotalOptions, CheckHdl, Button*, pBox, void )
{
if ( pBox == pBtnSort )
{
if ( pBtnSort->IsChecked() )
{
pFlSort->Enable();
pBtnFormats->Enable();
pBtnUserDef->Enable();
pBtnAscending->Enable();
pBtnDescending->Enable();
if ( pBtnUserDef->IsChecked() )
pLbUserDef->Enable();
}
else
{
pFlSort->Disable();
pBtnFormats->Disable();
pBtnUserDef->Disable();
pBtnAscending->Disable();
pBtnDescending->Disable();
pLbUserDef->Disable();
}
}
else if ( pBox == pBtnUserDef )
{
if ( pBtnUserDef->IsChecked() )
{
pLbUserDef->Enable();
pLbUserDef->GrabFocus();
}
else
pLbUserDef->Disable();
}
}
ScTpSubTotalGroup1::~ScTpSubTotalGroup1()
{
}
ScTpSubTotalGroup2::~ScTpSubTotalGroup2()
{
}
ScTpSubTotalGroup3::~ScTpSubTotalGroup3()
{
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V560 A part of conditional expression is always true: i > 0.