LibreOffice Module sc (master)  1
PivotLayoutTreeListData.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  */
11 
12 #include <memory>
13 #include <string_view>
14 
16 #include <PivotLayoutDialog.hxx>
17 
18 #include <vcl/event.hxx>
19 #include <pivot.hxx>
20 #include <globstr.hrc>
21 #include <scresid.hxx>
22 
23 namespace
24 {
25 
26 OUString lclGetFunctionMaskName(const PivotFunc nFunctionMask)
27 {
28  TranslateId pStrId;
29  switch (nFunctionMask)
30  {
31  case PivotFunc::Sum: pStrId = STR_FUN_TEXT_SUM; break;
32  case PivotFunc::Count: pStrId = STR_FUN_TEXT_COUNT; break;
33  case PivotFunc::Average: pStrId = STR_FUN_TEXT_AVG; break;
34  case PivotFunc::Median: pStrId = STR_FUN_TEXT_MEDIAN; break;
35  case PivotFunc::Max: pStrId = STR_FUN_TEXT_MAX; break;
36  case PivotFunc::Min: pStrId = STR_FUN_TEXT_MIN; break;
37  case PivotFunc::Product: pStrId = STR_FUN_TEXT_PRODUCT; break;
38  case PivotFunc::CountNum: pStrId = STR_FUN_TEXT_COUNT; break;
39  case PivotFunc::StdDev: pStrId = STR_FUN_TEXT_STDDEV; break;
40  case PivotFunc::StdDevP: pStrId = STR_FUN_TEXT_STDDEV; break;
41  case PivotFunc::StdVar: pStrId = STR_FUN_TEXT_VAR; break;
42  case PivotFunc::StdVarP: pStrId = STR_FUN_TEXT_VAR; break;
43  default:
44  assert(false);
45  break;
46  }
47  if (pStrId)
48  return ScResId(pStrId);
49  else
50  return OUString();
51 }
52 
53 OUString lclCreateDataItemName(const PivotFunc nFunctionMask, std::u16string_view rName, const sal_uInt8 nDuplicationCount)
54 {
55  OUString aBuffer = lclGetFunctionMaskName(nFunctionMask) + " - " + rName;
56  if(nDuplicationCount > 0)
57  {
58  aBuffer += " " + OUString::number(nDuplicationCount);
59  }
60  return aBuffer;
61 }
62 
63 } // anonymous namespace
64 
65 ScPivotLayoutTreeListData::ScPivotLayoutTreeListData(std::unique_ptr<weld::TreeView> xControl)
66  : ScPivotLayoutTreeListBase(std::move(xControl))
67 {
68  mxControl->connect_key_press(LINK(this, ScPivotLayoutTreeListData, KeyInputHdl));
69  mxControl->connect_row_activated(LINK(this, ScPivotLayoutTreeListData, DoubleClickHdl));
70 }
71 
73 {
74  if (mpFunctionDlg)
75  {
78  }
79 }
80 
82 {
83  int nEntry = mxControl->get_cursor_index();
84  if (nEntry == -1)
85  return true;
86 
87  ScItemValue* pCurrentItemValue = reinterpret_cast<ScItemValue*>(mxControl->get_id(nEntry).toInt64());
88  ScPivotFuncData& rCurrentFunctionData = pCurrentItemValue->maFunctionData;
89 
90  SCCOL nCurrentColumn = rCurrentFunctionData.mnCol;
91  ScDPLabelData& rCurrentLabelData = mpParent->GetLabelData(nCurrentColumn);
92 
94 
95  mpFunctionDlg = pFactory->CreateScDPFunctionDlg(mxControl.get(), mpParent->GetLabelDataVector(), rCurrentLabelData, rCurrentFunctionData);
96 
97  mpFunctionDlg->StartExecuteAsync([this, pCurrentItemValue,
98  rCurrentLabelData, nEntry](int nResult) mutable {
99  if (nResult == RET_OK)
100  {
101  ScPivotFuncData& rFunctionData = pCurrentItemValue->maFunctionData;
102  rFunctionData.mnFuncMask = mpFunctionDlg->GetFuncMask();
103  rCurrentLabelData.mnFuncMask = mpFunctionDlg->GetFuncMask();
104 
105  rFunctionData.maFieldRef = mpFunctionDlg->GetFieldRef();
106 
107  ScDPLabelData& rDFData = mpParent->GetLabelData(rFunctionData.mnCol);
108 
109  AdjustDuplicateCount(pCurrentItemValue);
110 
111  OUString sDataItemName = lclCreateDataItemName(
112  rFunctionData.mnFuncMask,
113  rDFData.maName,
114  rFunctionData.mnDupCount);
115 
116  mxControl->set_text(nEntry, sDataItemName);
117  }
118 
119  mpFunctionDlg->disposeOnce();
120  });
121 
122  return true;
123 }
124 
126 {
127  mxControl->clear();
128  maDataItemValues.clear();
129 
130  for (const ScPivotField& rField : rDataFields)
131  {
132  if (rField.nCol == PIVOT_DATA_FIELD)
133  continue;
134 
135  SCCOL nColumn;
136  if (rField.mnOriginalDim >= 0)
137  nColumn = rField.mnOriginalDim;
138  else
139  nColumn = rField.nCol;
140 
141  ScItemValue* pOriginalItemValue = mpParent->GetItem(nColumn);
142  ScItemValue* pItemValue = new ScItemValue(pOriginalItemValue->maName, nColumn, rField.nFuncMask);
143 
144  pItemValue->mpOriginalItemValue = pOriginalItemValue;
145  pItemValue->maFunctionData.mnOriginalDim = rField.mnOriginalDim;
146  pItemValue->maFunctionData.maFieldRef = rField.maFieldRef;
147 
148  AdjustDuplicateCount(pItemValue);
149  OUString sDataItemName = lclCreateDataItemName(pItemValue->maFunctionData.mnFuncMask,
150  pItemValue->maName,
151  pItemValue->maFunctionData.mnDupCount);
152 
153  maDataItemValues.push_back(std::unique_ptr<ScItemValue>(pItemValue));
154  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pItemValue)));
155  mxControl->append(sId, sDataItemName);
156  }
157 }
158 
159 void ScPivotLayoutTreeListData::PushDataFieldNames(std::vector<ScDPName>& rDataFieldNames)
160 {
161  std::unique_ptr<weld::TreeIter> xLoopEntry(mxControl->make_iterator());
162  if (!mxControl->get_iter_first(*xLoopEntry))
163  return;
164 
165  do
166  {
167  ScItemValue* pEachItemValue = reinterpret_cast<ScItemValue*>(mxControl->get_id(*xLoopEntry).toInt64());
168  SCCOL nColumn = pEachItemValue->maFunctionData.mnCol;
169 
170  ScDPLabelData& rLabelData = mpParent->GetLabelData(nColumn);
171 
172  if (rLabelData.maName.isEmpty())
173  continue;
174 
175  OUString sLayoutName = rLabelData.maLayoutName;
176  if (sLayoutName.isEmpty())
177  {
178  sLayoutName = lclCreateDataItemName(
179  pEachItemValue->maFunctionData.mnFuncMask,
180  pEachItemValue->maName,
181  pEachItemValue->maFunctionData.mnDupCount);
182  }
183 
184  rDataFieldNames.emplace_back(rLabelData.maName, sLayoutName, rLabelData.mnDupCount);
185  } while (mxControl->iter_next(*xLoopEntry));
186 }
187 
189 {
190  if (rSource.count_selected_rows() <=0)
191  return;
192 
193  ScItemValue* pItemValue = reinterpret_cast<ScItemValue*>(rSource.get_selected_id().toInt64());
194 
195  if (mpParent->IsDataElement(pItemValue->maFunctionData.mnCol))
196  return;
197 
198  if (&rSource == mxControl.get())
199  {
200  OUString sText = mxControl->get_selected_text();
201  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pItemValue)));
202  mxControl->remove_id(sId);
203  mxControl->insert(nullptr, nTarget, &sText, &sId, nullptr, nullptr, false, nullptr);
204  }
205  else
206  {
207  InsertEntryForItem(pItemValue->mpOriginalItemValue, nTarget);
208  }
209 }
210 
212 {
213  ScItemValue* pDataItemValue = new ScItemValue(pItemValue);
214  pDataItemValue->mpOriginalItemValue = pItemValue;
215  maDataItemValues.push_back(std::unique_ptr<ScItemValue>(pDataItemValue));
216 
217  ScPivotFuncData& rFunctionData = pDataItemValue->maFunctionData;
218 
219  if (rFunctionData.mnFuncMask == PivotFunc::NONE ||
220  rFunctionData.mnFuncMask == PivotFunc::Auto)
221  {
222  rFunctionData.mnFuncMask = PivotFunc::Sum;
223  }
224 
225  AdjustDuplicateCount(pDataItemValue);
226 
227  OUString sDataName = lclCreateDataItemName(
228  rFunctionData.mnFuncMask,
229  pDataItemValue->maName,
230  rFunctionData.mnDupCount);
231 
232  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pDataItemValue)));
233  mxControl->insert(nullptr, nPosition, &sDataName, &sId, nullptr, nullptr, false, nullptr);
234 }
235 
237 {
238  ScPivotFuncData& rInputFunctionData = pInputItemValue->maFunctionData;
239 
240  bool bFoundDuplicate = false;
241 
242  rInputFunctionData.mnDupCount = 0;
243  sal_uInt8 nMaxDuplicateCount = 0;
244 
245  std::unique_ptr<weld::TreeIter> xEachEntry(mxControl->make_iterator());
246  if (!mxControl->get_iter_first(*xEachEntry))
247  return;
248  do
249  {
250  ScItemValue* pItemValue = reinterpret_cast<ScItemValue*>(mxControl->get_id(*xEachEntry).toInt64());
251  if (pItemValue == pInputItemValue)
252  continue;
253 
254  ScPivotFuncData& rFunctionData = pItemValue->maFunctionData;
255 
256  if (rFunctionData.mnCol == rInputFunctionData.mnCol &&
257  rFunctionData.mnFuncMask == rInputFunctionData.mnFuncMask)
258  {
259  bFoundDuplicate = true;
260  if(rFunctionData.mnDupCount > nMaxDuplicateCount)
261  nMaxDuplicateCount = rFunctionData.mnDupCount;
262  }
263  } while (mxControl->iter_next(*xEachEntry));
264 
265  if(bFoundDuplicate)
266  {
267  rInputFunctionData.mnDupCount = nMaxDuplicateCount + 1;
268  }
269 }
270 
271 IMPL_LINK(ScPivotLayoutTreeListData, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
272 {
273  vcl::KeyCode aCode = rKeyEvent.GetKeyCode();
274  sal_uInt16 nCode = aCode.GetCode();
275 
276  if (nCode == KEY_DELETE)
277  {
278  int nEntry = mxControl->get_cursor_index();
279  if (nEntry != -1)
280  mxControl->remove(nEntry);
281  return true;
282  }
283 
284  return false;
285 }
286 
287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual int count_selected_rows() const =0
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
sal_uInt8 mnDupCount
Definition: pivot.hxx:76
ScDPLabelData & GetLabelData(SCCOL nColumn)
void AdjustDuplicateCount(ScItemValue *pInputItemValue)
bool IsDataElement(SCCOL nColumn)
std::vector< std::unique_ptr< ScItemValue > > maDataItemValues
sal_uInt16 GetCode() const
RET_CANCEL
PivotFunc mnFuncMask
Definition: pivot.hxx:161
#define PIVOT_DATA_FIELD
Definition: pivot.hxx:54
css::sheet::DataPilotFieldReference maFieldRef
Definition: pivot.hxx:158
virtual void Response(int nResponse)=0
PivotFunc mnFuncMask
Page/Column/Row subtotal function.
Definition: pivot.hxx:73
PivotFunc
Definition: dpglobal.hxx:24
sal_uInt16 nCode
OUString maName
Original name of the dimension.
Definition: pivot.hxx:68
void InsertEntryForItem(ScItemValue *pItemValue, int nPosition)
ScItemValue * mpOriginalItemValue
void PushDataFieldNames(std::vector< ScDPName > &rDataFieldNames)
void clear()
IMPL_LINK_NOARG(ScPivotLayoutTreeListData, DoubleClickHdl, weld::TreeView &, bool)
std::vector< ScPivotField > ScPivotFieldVector
Definition: pivot.hxx:129
sal_Int16 SCCOL
Definition: types.hxx:21
virtual VclPtr< AbstractScDPFunctionDlg > CreateScDPFunctionDlg(weld::Widget *pParent, const ScDPLabelDataVector &rLabelVec, const ScDPLabelData &rLabelData, const ScPivotFuncData &rFuncData)=0
void FillDataField(ScPivotFieldVector &rDataFields)
IMPL_LINK(ScPivotLayoutTreeListData, KeyInputHdl, const KeyEvent &, rKeyEvent, bool)
ScPivotFuncData maFunctionData
ScPivotLayoutTreeListData(std::unique_ptr< weld::TreeView > xControl)
bool StartExecuteAsync(const std::function< void(sal_Int32)> &rEndDialogFn)
virtual void InsertEntryForSourceTarget(weld::TreeView &rSource, int nTarget) override
VclPtr< AbstractScDPFunctionDlg > mpFunctionDlg
virtual OUString get_selected_id() const =0
RegionData_Impl * mpParent
virtual ~ScPivotLayoutTreeListData() override
OUString maLayoutName
Layout name (display name)
Definition: pivot.hxx:69
ScItemValue * GetItem(SCCOL nColumn)
std::unique_ptr< char[]> aBuffer
tools::Long mnOriginalDim
Definition: pivot.hxx:160
unsigned char sal_uInt8
static SC_DLLPUBLIC ScAbstractDialogFactory * Create()
Definition: scabstdlg.cxx:37
RET_OK
std::unique_ptr< weld::TreeView > mxControl
sal_uInt8 mnDupCount
Definition: pivot.hxx:163
constexpr sal_uInt16 KEY_DELETE
OUString sId