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 <PivotLayoutTreeListData.hxx>
14 #include <PivotLayoutDialog.hxx>
15
16 #include <vcl/event.hxx>
17 #include <pivot.hxx>
18 #include <scabstdlg.hxx>
19 #include <globstr.hrc>
20 #include <scresid.hxx>
21
22 namespace
23 {
24
lclGetFunctionMaskName(const PivotFunc nFunctionMask)25 OUString lclGetFunctionMaskName(const PivotFunc nFunctionMask)
26 {
27 const char* pStrId = nullptr;
28 switch (nFunctionMask)
29 {
30 case PivotFunc::Sum: pStrId = STR_FUN_TEXT_SUM; break;
31 case PivotFunc::Count: pStrId = STR_FUN_TEXT_COUNT; break;
32 case PivotFunc::Average: pStrId = STR_FUN_TEXT_AVG; break;
33 case PivotFunc::Median: pStrId = STR_FUN_TEXT_MEDIAN; break;
34 case PivotFunc::Max: pStrId = STR_FUN_TEXT_MAX; break;
35 case PivotFunc::Min: pStrId = STR_FUN_TEXT_MIN; break;
36 case PivotFunc::Product: pStrId = STR_FUN_TEXT_PRODUCT; break;
37 case PivotFunc::CountNum: pStrId = STR_FUN_TEXT_COUNT; break;
38 case PivotFunc::StdDev: pStrId = STR_FUN_TEXT_STDDEV; break;
39 case PivotFunc::StdDevP: pStrId = STR_FUN_TEXT_STDDEV; break;
40 case PivotFunc::StdVar: pStrId = STR_FUN_TEXT_VAR; break;
41 case PivotFunc::StdVarP: pStrId = STR_FUN_TEXT_VAR; break;
42 default:
43 assert(false);
44 break;
45 }
46 if (pStrId)
47 return ScResId(pStrId);
48 else
49 return OUString();
50 }
51
lclCreateDataItemName(const PivotFunc nFunctionMask,const OUString & rName,const sal_uInt8 nDuplicationCount)52 OUString lclCreateDataItemName(const PivotFunc nFunctionMask, const OUString& rName, const sal_uInt8 nDuplicationCount)
53 {
54 OUString aBuffer = lclGetFunctionMaskName(nFunctionMask) + " - " + rName;
55 if(nDuplicationCount > 0)
56 {
57 aBuffer += " " + OUString::number(nDuplicationCount);
58 }
59 return aBuffer;
60 }
61
62 } // anonymous namespace
63
ScPivotLayoutTreeListData(std::unique_ptr<weld::TreeView> xControl)64 ScPivotLayoutTreeListData::ScPivotLayoutTreeListData(std::unique_ptr<weld::TreeView> xControl)
65 : ScPivotLayoutTreeListBase(std::move(xControl))
66 {
67 mxControl->connect_key_press(LINK(this, ScPivotLayoutTreeListData, KeyInputHdl));
68 mxControl->connect_row_activated(LINK(this, ScPivotLayoutTreeListData, DoubleClickHdl));
69 }
70
~ScPivotLayoutTreeListData()71 ScPivotLayoutTreeListData::~ScPivotLayoutTreeListData()
72 {}
73
IMPL_LINK_NOARG(ScPivotLayoutTreeListData,DoubleClickHdl,weld::TreeView &,bool)74 IMPL_LINK_NOARG(ScPivotLayoutTreeListData, DoubleClickHdl, weld::TreeView&, bool)
75 {
76 int nEntry = mxControl->get_cursor_index();
77 if (nEntry == -1)
78 return true;
79
80 ScItemValue* pCurrentItemValue = reinterpret_cast<ScItemValue*>(mxControl->get_id(nEntry).toInt64());
81 ScPivotFuncData& rCurrentFunctionData = pCurrentItemValue->maFunctionData;
82
83 SCCOL nCurrentColumn = rCurrentFunctionData.mnCol;
84 ScDPLabelData& rCurrentLabelData = mpParent->GetLabelData(nCurrentColumn);
85
86 ScAbstractDialogFactory* pFactory = ScAbstractDialogFactory::Create();
87
88 ScopedVclPtr<AbstractScDPFunctionDlg> pDialog(
89 pFactory->CreateScDPFunctionDlg(mxControl.get(), mpParent->GetLabelDataVector(), rCurrentLabelData, rCurrentFunctionData));
90
91 if (pDialog->Execute() == RET_OK)
92 {
93 rCurrentFunctionData.mnFuncMask = pDialog->GetFuncMask();
94 rCurrentLabelData.mnFuncMask = pDialog->GetFuncMask();
95
96 rCurrentFunctionData.maFieldRef = pDialog->GetFieldRef();
97
98 ScDPLabelData& rDFData = mpParent->GetLabelData(rCurrentFunctionData.mnCol);
99
100 AdjustDuplicateCount(pCurrentItemValue);
101
102 OUString sDataItemName = lclCreateDataItemName(
103 rCurrentFunctionData.mnFuncMask,
104 rDFData.maName,
105 rCurrentFunctionData.mnDupCount);
106
107 mxControl->set_text(nEntry, sDataItemName);
108 }
109
110 return true;
111 }
112
FillDataField(ScPivotFieldVector & rDataFields)113 void ScPivotLayoutTreeListData::FillDataField(ScPivotFieldVector& rDataFields)
114 {
115 mxControl->clear();
116 maDataItemValues.clear();
117
118 for (const ScPivotField& rField : rDataFields)
119 {
120 if (rField.nCol == PIVOT_DATA_FIELD)
121 continue;
122
123 SCCOL nColumn;
124 if (rField.mnOriginalDim >= 0)
125 nColumn = rField.mnOriginalDim;
126 else
127 nColumn = rField.nCol;
128
129 ScItemValue* pOriginalItemValue = mpParent->GetItem(nColumn);
130 ScItemValue* pItemValue = new ScItemValue(pOriginalItemValue->maName, nColumn, rField.nFuncMask);
131
132 pItemValue->mpOriginalItemValue = pOriginalItemValue;
133 pItemValue->maFunctionData.mnOriginalDim = rField.mnOriginalDim;
134 pItemValue->maFunctionData.maFieldRef = rField.maFieldRef;
135
136 AdjustDuplicateCount(pItemValue);
137 OUString sDataItemName = lclCreateDataItemName(pItemValue->maFunctionData.mnFuncMask,
138 pItemValue->maName,
139 pItemValue->maFunctionData.mnDupCount);
140
141 maDataItemValues.push_back(std::unique_ptr<ScItemValue>(pItemValue));
142 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pItemValue)));
143 mxControl->append(sId, sDataItemName);
144 }
145 }
146
PushDataFieldNames(std::vector<ScDPName> & rDataFieldNames)147 void ScPivotLayoutTreeListData::PushDataFieldNames(std::vector<ScDPName>& rDataFieldNames)
148 {
149 std::unique_ptr<weld::TreeIter> xLoopEntry(mxControl->make_iterator());
150 if (!mxControl->get_iter_first(*xLoopEntry))
151 return;
152
153 do
154 {
155 ScItemValue* pEachItemValue = reinterpret_cast<ScItemValue*>(mxControl->get_id(*xLoopEntry).toInt64());
156 SCCOL nColumn = pEachItemValue->maFunctionData.mnCol;
157
158 ScDPLabelData& rLabelData = mpParent->GetLabelData(nColumn);
159
160 if (rLabelData.maName.isEmpty())
161 continue;
162
163 OUString sLayoutName = rLabelData.maLayoutName;
164 if (sLayoutName.isEmpty())
165 {
166 sLayoutName = lclCreateDataItemName(
167 pEachItemValue->maFunctionData.mnFuncMask,
168 pEachItemValue->maName,
169 pEachItemValue->maFunctionData.mnDupCount);
170 }
171
172 rDataFieldNames.emplace_back(rLabelData.maName, sLayoutName, rLabelData.mnDupCount);
173 } while (mxControl->iter_next(*xLoopEntry));
174 }
175
InsertEntryForSourceTarget(weld::TreeView & rSource,int nTarget)176 void ScPivotLayoutTreeListData::InsertEntryForSourceTarget(weld::TreeView& rSource, int nTarget)
177 {
178 ScItemValue* pItemValue = reinterpret_cast<ScItemValue*>(rSource.get_selected_id().toInt64());
179
180 if (mpParent->IsDataElement(pItemValue->maFunctionData.mnCol))
181 return;
182
183 if (&rSource == mxControl.get())
184 {
185 OUString sText = mxControl->get_selected_text();
186 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pItemValue)));
187 mxControl->remove_id(sId);
188 mxControl->insert(nullptr, nTarget, &sText, &sId, nullptr, nullptr, nullptr, false, nullptr);
189 }
190 else
191 {
192 InsertEntryForItem(pItemValue->mpOriginalItemValue, nTarget);
193 }
194 }
195
InsertEntryForItem(ScItemValue * pItemValue,int nPosition)196 void ScPivotLayoutTreeListData::InsertEntryForItem(ScItemValue* pItemValue, int nPosition)
197 {
198 ScItemValue* pDataItemValue = new ScItemValue(pItemValue);
199 pDataItemValue->mpOriginalItemValue = pItemValue;
200 maDataItemValues.push_back(std::unique_ptr<ScItemValue>(pDataItemValue));
201
202 ScPivotFuncData& rFunctionData = pDataItemValue->maFunctionData;
203
204 if (rFunctionData.mnFuncMask == PivotFunc::NONE ||
205 rFunctionData.mnFuncMask == PivotFunc::Auto)
206 {
207 rFunctionData.mnFuncMask = PivotFunc::Sum;
208 }
209
210 AdjustDuplicateCount(pDataItemValue);
211
212 OUString sDataName = lclCreateDataItemName(
213 rFunctionData.mnFuncMask,
214 pDataItemValue->maName,
215 rFunctionData.mnDupCount);
216
217 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pDataItemValue)));
218 mxControl->insert(nullptr, nPosition, &sDataName, &sId, nullptr, nullptr, nullptr, false, nullptr);
219 }
220
AdjustDuplicateCount(ScItemValue * pInputItemValue)221 void ScPivotLayoutTreeListData::AdjustDuplicateCount(ScItemValue* pInputItemValue)
222 {
223 ScPivotFuncData& rInputFunctionData = pInputItemValue->maFunctionData;
224
225 bool bFoundDuplicate = false;
226
227 rInputFunctionData.mnDupCount = 0;
228 sal_uInt8 nMaxDuplicateCount = 0;
229
230 std::unique_ptr<weld::TreeIter> xEachEntry(mxControl->make_iterator());
231 if (!mxControl->get_iter_first(*xEachEntry))
232 return;
233 do
234 {
235 ScItemValue* pItemValue = reinterpret_cast<ScItemValue*>(mxControl->get_id(*xEachEntry).toInt64());
236 if (pItemValue == pInputItemValue)
237 continue;
238
239 ScPivotFuncData& rFunctionData = pItemValue->maFunctionData;
240
241 if (rFunctionData.mnCol == rInputFunctionData.mnCol &&
242 rFunctionData.mnFuncMask == rInputFunctionData.mnFuncMask)
243 {
244 bFoundDuplicate = true;
245 if(rFunctionData.mnDupCount > nMaxDuplicateCount)
246 nMaxDuplicateCount = rFunctionData.mnDupCount;
247 }
248 } while (mxControl->iter_next(*xEachEntry));
249
250 if(bFoundDuplicate)
251 {
252 rInputFunctionData.mnDupCount = nMaxDuplicateCount + 1;
253 }
254 }
255
IMPL_LINK(ScPivotLayoutTreeListData,KeyInputHdl,const KeyEvent &,rKeyEvent,bool)256 IMPL_LINK(ScPivotLayoutTreeListData, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
257 {
258 vcl::KeyCode aCode = rKeyEvent.GetKeyCode();
259 sal_uInt16 nCode = aCode.GetCode();
260
261 if (nCode == KEY_DELETE)
262 {
263 int nEntry = mxControl->get_cursor_index();
264 if (nEntry != -1)
265 mxControl->remove(nEntry);
266 return true;
267 }
268
269 return false;
270 }
271
272 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
273