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
15 #include <PivotLayoutTreeListData.hxx>
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
lclGetFunctionMaskName(const PivotFunc nFunctionMask)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
lclCreateDataItemName(const PivotFunc nFunctionMask,std::u16string_view rName,const sal_uInt8 nDuplicationCount)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
ScPivotLayoutTreeListData(std::unique_ptr<weld::TreeView> xControl)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
~ScPivotLayoutTreeListData()72 ScPivotLayoutTreeListData::~ScPivotLayoutTreeListData()
73 {
74 if (mpFunctionDlg)
75 {
76 mpFunctionDlg->Response(RET_CANCEL);
77 mpFunctionDlg.clear();
78 }
79 }
80
IMPL_LINK_NOARG(ScPivotLayoutTreeListData,DoubleClickHdl,weld::TreeView &,bool)81 IMPL_LINK_NOARG(ScPivotLayoutTreeListData, DoubleClickHdl, weld::TreeView&, bool)
82 {
83 int nEntry = mxControl->get_cursor_index();
84 if (nEntry == -1)
85 return true;
86
87 ScItemValue* pCurrentItemValue = weld::fromId<ScItemValue*>(mxControl->get_id(nEntry));
88 ScPivotFuncData& rCurrentFunctionData = pCurrentItemValue->maFunctionData;
89
90 SCCOL nCurrentColumn = rCurrentFunctionData.mnCol;
91 ScDPLabelData& rCurrentLabelData = mpParent->GetLabelData(nCurrentColumn);
92
93 ScAbstractDialogFactory* pFactory = ScAbstractDialogFactory::Create();
94
95 mpFunctionDlg = pFactory->CreateScDPFunctionDlg(mxControl.get(), mpParent->GetLabelDataVector(), rCurrentLabelData, rCurrentFunctionData);
96
97 mpFunctionDlg->StartExecuteAsync([this, pCurrentItemValue, nEntry](int nResult) mutable {
98 if (nResult == RET_OK)
99 {
100 ScPivotFuncData& rFunctionData = pCurrentItemValue->maFunctionData;
101 rFunctionData.mnFuncMask = mpFunctionDlg->GetFuncMask();
102 ScDPLabelData& rLabelData = mpParent->GetLabelData(rFunctionData.mnCol);
103 rLabelData.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
FillDataField(ScPivotFieldVector & rDataFields)125 void ScPivotLayoutTreeListData::FillDataField(ScPivotFieldVector& rDataFields)
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(weld::toId(pItemValue));
155 mxControl->append(sId, sDataItemName);
156 }
157 }
158
PushDataFieldNames(std::vector<ScDPName> & rDataFieldNames)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 = weld::fromId<ScItemValue*>(mxControl->get_id(*xLoopEntry));
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
InsertEntryForSourceTarget(weld::TreeView & rSource,int nTarget)188 void ScPivotLayoutTreeListData::InsertEntryForSourceTarget(weld::TreeView& rSource, int nTarget)
189 {
190 if (rSource.count_selected_rows() <=0)
191 return;
192
193 ScItemValue* pItemValue = weld::fromId<ScItemValue*>(rSource.get_selected_id());
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(weld::toId(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
InsertEntryForItem(ScItemValue * pItemValue,int nPosition)211 void ScPivotLayoutTreeListData::InsertEntryForItem(ScItemValue* pItemValue, int nPosition)
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(weld::toId(pDataItemValue));
233 mxControl->insert(nullptr, nPosition, &sDataName, &sId, nullptr, nullptr, false, nullptr);
234 }
235
AdjustDuplicateCount(ScItemValue * pInputItemValue)236 void ScPivotLayoutTreeListData::AdjustDuplicateCount(ScItemValue* pInputItemValue)
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 = weld::fromId<ScItemValue*>(mxControl->get_id(*xEachEntry));
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
IMPL_LINK(ScPivotLayoutTreeListData,KeyInputHdl,const KeyEvent &,rKeyEvent,bool)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: */
288