LibreOffice Module sc (master)  1
dataproviderdlg.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 
10 #include <dataproviderdlg.hxx>
11 
12 #include <document.hxx>
13 #include <dataprovider.hxx>
14 #include <datatransformation.hxx>
15 #include <datamapper.hxx>
16 #include <dbdata.hxx>
17 
18 #include <comphelper/string.hxx>
19 #include <sal/log.hxx>
20 #include <unotools/charclass.hxx>
21 #include <vcl/svapp.hxx>
22 
23 #include <utility>
24 
26 {
27  std::unique_ptr<weld::Builder> mxBuilder;
28  std::unique_ptr<weld::Container> mxGrid;
29  std::unique_ptr<weld::ComboBox> mxProviderList;
30  std::unique_ptr<weld::Entry> mxEditURL;
31  std::unique_ptr<weld::Entry> mxEditID;
32  std::unique_ptr<weld::Button> mxApplyBtn;
33 
34  OUString msApplyTooltip;
35 
37 
38  DECL_LINK(ProviderSelectHdl, weld::ComboBox&, void);
39  DECL_LINK(IDEditHdl, weld::Entry&, void);
40  DECL_LINK(URLEditHdl, weld::Entry&, void);
41  DECL_LINK(ApplyBtnHdl, weld::Button&, void);
42 
43  void updateApplyBtn(bool bValidConfig);
44 
45 public:
47 
48  void isValid();
49 
51 };
52 
54  const Link<ScDataProviderBaseControl*, void>& rImportCallback)
55  : mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/dataproviderentry.ui"))
56  , mxGrid(mxBuilder->weld_container("grid"))
57  , mxProviderList(mxBuilder->weld_combo_box("provider_lst"))
58  , mxEditURL(mxBuilder->weld_entry("ed_url"))
59  , mxEditID(mxBuilder->weld_entry("ed_id"))
60  , mxApplyBtn(mxBuilder->weld_button("apply"))
61  , maImportCallback(rImportCallback)
62 {
63  auto aDataProvider = sc::DataProviderFactory::getDataProviders();
64  for (const auto& rDataProvider : aDataProvider)
65  {
66  mxProviderList->append_text(rDataProvider);
67  }
68 
69  mxProviderList->connect_changed(LINK(this, ScDataProviderBaseControl, ProviderSelectHdl));
70  mxEditID->connect_changed(LINK(this, ScDataProviderBaseControl, IDEditHdl));
71  mxEditURL->connect_changed(LINK(this, ScDataProviderBaseControl, URLEditHdl));
72 
73  msApplyTooltip = mxApplyBtn->get_tooltip_text();
74  mxApplyBtn->connect_clicked(LINK(this, ScDataProviderBaseControl, ApplyBtnHdl));
75  isValid();
76 }
77 
79 {
80  bool bValid = !mxProviderList->get_active_text().isEmpty();
81  bValid &= !mxEditURL->get_text().isEmpty();
82  updateApplyBtn(bValid);
83 }
84 
86 {
87  OUString aURL = mxEditURL->get_text();
88  OUString aProvider = mxProviderList->get_active_text();
89  sc::ExternalDataSource aSource(aURL, aProvider, pDoc);
90 
91  OUString aID = mxEditID->get_text();
92  aSource.setID(aID);
93  return aSource;
94 }
95 
97 {
98  if (!bValidConfig)
99  {
100  mxApplyBtn->set_sensitive(false);
101  mxApplyBtn->set_tooltip_text(OUString());
102  return;
103  }
104 
105  mxApplyBtn->set_sensitive(true);
106  mxApplyBtn->set_tooltip_text(msApplyTooltip);
107 }
108 
110 {
111  isValid();
112 }
113 
115 {
116  isValid();
117 }
118 
120 {
121  isValid();
122 }
123 
125 {
126  updateApplyBtn(true);
127  maImportCallback.Call(this);
128 }
129 
131 {
132 protected:
133  std::unique_ptr<weld::Builder> mxBuilder;
134  std::unique_ptr<weld::Container> mxGrid;
136 
137  sal_uInt32 mnIndex;
138 
139 public:
140  ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex);
142 
143  void updateIndex(sal_uInt32 nIndex) { mnIndex = nIndex; }
144 
145  virtual std::shared_ptr<sc::DataTransformation> getTransformation() = 0;
146 };
147 
148 ScDataTransformationBaseControl::ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex)
149  : mxBuilder(Application::CreateBuilder(pParent, rUIFile))
150  , mxGrid(mxBuilder->weld_container("grid"))
151  , mpContainer(pParent)
152  , mnIndex(nIndex)
153 {
154 }
155 
157 {
158  mpContainer->move(mxGrid.get(), nullptr);
159 }
160 
161 namespace {
162 
163 struct MenuData
164 {
165  int nMenuID;
166  const char* aMenuName;
167  std::function<void(ScDataProviderDlg*)> maCallback;
168 };
169 
170 MenuData aStartData[] = {
171  { 0, "Apply & Quit", &ScDataProviderDlg::applyAndQuit },
172  { 1, "Cancel & Quit", &ScDataProviderDlg::cancelAndQuit }
173 };
174 
175 MenuData aColumnData[] = {
176  { 0, "Delete Column", &ScDataProviderDlg::deleteColumn },
177  { 1, "Split Column", &ScDataProviderDlg::splitColumn },
178  { 2, "Merge Columns", &ScDataProviderDlg::mergeColumns },
179  { 3, "Text Transformation", &ScDataProviderDlg::textTransformation },
180  { 4, "Sort Columns", &ScDataProviderDlg::sortTransformation },
181  { 5, "Aggregate Functions", &ScDataProviderDlg::aggregateFunction},
182  { 6, "Number Transformations", &ScDataProviderDlg::numberTransformation },
183  { 7, "Replace Null Transformations", &ScDataProviderDlg::replaceNullTransformation },
184  { 8, "Date & Time Transformations", &ScDataProviderDlg::dateTimeTransformation }
185 };
186 
187 class ScDeleteColumnTransformationControl : public ScDataTransformationBaseControl
188 {
189 private:
190  std::unique_ptr<weld::Entry> mxColumnNums;
191  std::unique_ptr<weld::Button> mxDelete;
192  std::function<void(sal_uInt32&)> maDeleteTransformation;
193  const ScDocument* mpDoc;
194 
195 public:
196  ScDeleteColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 aIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
197 
198  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
199  DECL_LINK(DeleteHdl, weld::Button&, void);
200 };
201 
202 ScDeleteColumnTransformationControl::ScDeleteColumnTransformationControl(
203  const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
204  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/deletecolumnentry.ui", nIndex)
205  , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
206  , mxDelete(mxBuilder->weld_button("ed_delete"))
207  , maDeleteTransformation(std::move(aDeleteTransformation))
208  , mpDoc(pDoc)
209 {
210  mxDelete->connect_clicked(LINK(this,ScDeleteColumnTransformationControl, DeleteHdl));
211 }
212 
213 std::shared_ptr<sc::DataTransformation> ScDeleteColumnTransformationControl::getTransformation()
214 {
215  OUString aColumnString = mxColumnNums->get_text();
216  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
217  std::set<SCCOL> ColNums;
218  for (const auto& rColStr : aSplitColumns)
219  {
220  sal_Int32 nCol = rColStr.toInt32();
221  if (nCol <= 0)
222  continue;
223 
224  if (nCol > mpDoc->MaxCol())
225  continue;
226 
227  // translate from 1-based column notations to internal Calc one
228  ColNums.insert(nCol - 1);
229  }
230 
231  return std::make_shared<sc::ColumnRemoveTransformation>(ColNums);
232 }
233 
234 class ScSplitColumnTransformationControl : public ScDataTransformationBaseControl
235 {
236 private:
237  std::unique_ptr<weld::Entry> mxSeparator;
238  std::unique_ptr<weld::SpinButton> mxNumColumns;
239  std::unique_ptr<weld::Button> mxDelete;
240  SCCOL mnCol;
241  std::function<void(sal_uInt32&)> maDeleteTransformation;
242 
243 public:
244  ScSplitColumnTransformationControl(weld::Container* pParent, SCCOL nCol, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
245 
246  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
247  DECL_LINK(DeleteHdl, weld::Button&, void);
248 };
249 
250 ScSplitColumnTransformationControl::ScSplitColumnTransformationControl(
251  weld::Container* pParent, SCCOL nCol, sal_uInt32 nIndex,
252  std::function<void(sal_uInt32&)> aDeleteTransformation)
253  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/splitcolumnentry.ui", nIndex)
254  , mxSeparator(mxBuilder->weld_entry("ed_separator"))
255  , mxNumColumns(mxBuilder->weld_spin_button("num_cols"))
256  , mxDelete(mxBuilder->weld_button("ed_delete"))
257  , mnCol(nCol)
258  , maDeleteTransformation(std::move(aDeleteTransformation))
259 {
260  mxDelete->connect_clicked(LINK(this,ScSplitColumnTransformationControl, DeleteHdl));
261 }
262 
263 std::shared_ptr<sc::DataTransformation> ScSplitColumnTransformationControl::getTransformation()
264 {
265  OUString aSeparator = mxSeparator->get_text();
266  sal_Unicode cSeparator = aSeparator.isEmpty() ? ',' : aSeparator[0];
267  return std::make_shared<sc::SplitColumnTransformation>(mnCol, cSeparator);
268 }
269 
270 class ScMergeColumnTransformationControl : public ScDataTransformationBaseControl
271 {
272 private:
273  std::unique_ptr<weld::Entry> mxSeparator;
274  std::unique_ptr<weld::Entry> mxEdColumns;
275  std::unique_ptr<weld::Button> mxDelete;
276  std::function<void(sal_uInt32&)> maDeleteTransformation;
277  const ScDocument* mpDoc;
278 
279 public:
280  ScMergeColumnTransformationControl(const ScDocument *pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
281 
282  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
283  DECL_LINK(DeleteHdl, weld::Button&, void);
284 };
285 
286 ScMergeColumnTransformationControl::ScMergeColumnTransformationControl(
287  const ScDocument* pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex,
288  std::function<void(sal_uInt32&)> aDeleteTransformation)
289  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/mergecolumnentry.ui", nIndex)
290  , mxSeparator(mxBuilder->weld_entry("ed_separator"))
291  , mxEdColumns(mxBuilder->weld_entry("ed_columns"))
292  , mxDelete(mxBuilder->weld_button("ed_delete"))
293  , maDeleteTransformation(std::move(aDeleteTransformation))
294  , mpDoc(pDoc)
295 {
296  mxDelete->connect_clicked(LINK(this,ScMergeColumnTransformationControl, DeleteHdl));
297 
298  OUStringBuffer aBuffer;
299 
300  // map from zero based to one based column numbers
301  aBuffer.append(OUString::number(nStartCol + 1));
302  for ( SCCOL nCol = nStartCol + 1; nCol <= nEndCol; ++nCol)
303  {
304  aBuffer.append(";").append(OUString::number(nCol + 1));
305  }
306 
307  mxEdColumns->set_text(aBuffer.makeStringAndClear());
308 }
309 
310 std::shared_ptr<sc::DataTransformation> ScMergeColumnTransformationControl::getTransformation()
311 {
312  OUString aColumnString = mxEdColumns->get_text();
313  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
314  std::set<SCCOL> aMergedColumns;
315  for (const auto& rColStr : aSplitColumns)
316  {
317  sal_Int32 nCol = rColStr.toInt32();
318  if (nCol <= 0)
319  continue;
320 
321  if (nCol > mpDoc->MaxCol())
322  continue;
323 
324  // translate from 1-based column notations to internal Calc one
325  aMergedColumns.insert(nCol - 1);
326  }
327  return std::make_shared<sc::MergeColumnTransformation>(aMergedColumns, mxSeparator->get_text());
328 }
329 
330 class ScSortTransformationControl : public ScDataTransformationBaseControl
331 {
332 private:
333  std::unique_ptr<weld::CheckButton> mxAscending;
334  std::unique_ptr<weld::Entry> mxEdColumns;
335  std::unique_ptr<weld::Button> mxDelete;
336  std::function<void(sal_uInt32&)> maDeleteTransformation;
337  const ScDocument* mpDoc;
338 
339 public:
340  ScSortTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
341 
342  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
343  DECL_LINK(DeleteHdl, weld::Button&, void);
344 };
345 
346 ScSortTransformationControl::ScSortTransformationControl(
347  const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
348  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/sorttransformationentry.ui", nIndex)
349  , mxAscending(mxBuilder->weld_check_button("ed_ascending"))
350  , mxEdColumns(mxBuilder->weld_entry("ed_columns"))
351  , mxDelete(mxBuilder->weld_button("ed_delete"))
352  , maDeleteTransformation(std::move(aDeleteTransformation))
353  , mpDoc(pDoc)
354 {
355  mxDelete->connect_clicked(LINK(this,ScSortTransformationControl, DeleteHdl));
356 }
357 
358 std::shared_ptr<sc::DataTransformation> ScSortTransformationControl::getTransformation()
359 {
360  OUString aColStr = mxEdColumns->get_text();
361  bool aIsAscending = mxAscending->get_active();
362  SCCOL aColumn = 0;
363  sal_Int32 nCol = aColStr.toInt32();
364  if (nCol > 0 && nCol <= mpDoc->MaxCol())
365  aColumn = nCol - 1; // translate from 1-based column notations to internal Calc one
366 
367  ScSortParam aSortParam;
368  ScSortKeyState aSortKey;
369  aSortKey.bDoSort = true;
370  aSortKey.nField = aColumn;
371  aSortKey.bAscending = aIsAscending;
372  aSortParam.maKeyState.push_back(aSortKey);
373  return std::make_shared<sc::SortTransformation>(aSortParam);
374 }
375 
376 class ScColumnTextTransformation : public ScDataTransformationBaseControl
377 {
378 private:
379  std::unique_ptr<weld::Entry> mxColumnNums;
380  std::unique_ptr<weld::ComboBox> mxType;
381  std::unique_ptr<weld::Button> mxDelete;
382  std::function<void(sal_uInt32&)> maDeleteTransformation;
383  const ScDocument* mpDoc;
384 
385 public:
386  ScColumnTextTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
387 
388  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
389  DECL_LINK(DeleteHdl, weld::Button&, void);
390 };
391 
392 ScColumnTextTransformation::ScColumnTextTransformation(
393  const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
394  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/texttransformationentry.ui", nIndex)
395  , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
396  , mxType(mxBuilder->weld_combo_box("ed_lst"))
397  , mxDelete(mxBuilder->weld_button("ed_delete"))
398  , maDeleteTransformation(std::move(aDeleteTransformation))
399  , mpDoc(pDoc)
400 {
401  mxDelete->connect_clicked(LINK(this,ScColumnTextTransformation, DeleteHdl));
402 }
403 
404 std::shared_ptr<sc::DataTransformation> ScColumnTextTransformation::getTransformation()
405 {
406  OUString aColumnString = mxColumnNums->get_text();
407  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
408  std::set<SCCOL> aColumns;
409  for (const auto& rColStr : aSplitColumns)
410  {
411  sal_Int32 nCol = rColStr.toInt32();
412  if (nCol <= 0)
413  continue;
414 
415  if (nCol > mpDoc->MaxCol())
416  continue;
417 
418  // translate from 1-based column notations to internal Calc one
419  aColumns.insert(nCol - 1);
420  }
421 
422  sal_Int32 nPos = mxType->get_active();
423  switch (nPos)
424  {
425  case 0:
426  return std::make_shared<sc::TextTransformation>(aColumns,sc::TEXT_TRANSFORM_TYPE::TO_LOWER);
427  case 1:
428  return std::make_shared<sc::TextTransformation>(aColumns,sc::TEXT_TRANSFORM_TYPE::TO_UPPER);
429  case 2:
430  return std::make_shared<sc::TextTransformation>(aColumns,sc::TEXT_TRANSFORM_TYPE::CAPITALIZE);
431  case 3:
432  return std::make_shared<sc::TextTransformation>(aColumns,sc::TEXT_TRANSFORM_TYPE::TRIM);
433  default:
434  assert(false);
435  }
436 
437  return nullptr;
438 }
439 
440 class ScAggregateFunction : public ScDataTransformationBaseControl
441 {
442 private:
443  std::unique_ptr<weld::Entry> mxColumnNums;
444  std::unique_ptr<weld::ComboBox> mxType;
445  std::unique_ptr<weld::Button> mxDelete;
446  std::function<void(sal_uInt32&)> maDeleteTransformation;
447  const ScDocument* mpDoc;
448 
449 public:
450  ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
451 
452  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
453  DECL_LINK(DeleteHdl, weld::Button&, void);
454 };
455 
456 ScAggregateFunction::ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex,
457  std::function<void(sal_uInt32&)> aDeleteTransformation)
458  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/aggregatefunctionentry.ui", nIndex)
459  , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
460  , mxType(mxBuilder->weld_combo_box("ed_lst"))
461  , mxDelete(mxBuilder->weld_button("ed_delete"))
462  , maDeleteTransformation(std::move(aDeleteTransformation))
463  , mpDoc(pDoc)
464 {
465  mxDelete->connect_clicked(LINK(this,ScAggregateFunction, DeleteHdl));
466 }
467 
468 std::shared_ptr<sc::DataTransformation> ScAggregateFunction::getTransformation()
469 {
470  OUString aColumnString = mxColumnNums->get_text();
471  sal_Int32 nPos = mxType->get_active();
472  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
473  std::set<SCCOL> aColumns;
474  for (const auto& rColStr : aSplitColumns)
475  {
476  sal_Int32 nCol = rColStr.toInt32();
477  if (nCol <= 0)
478  continue;
479 
480  if (nCol > mpDoc->MaxCol())
481  continue;
482 
483  // translate from 1-based column notations to internal Calc one
484  aColumns.insert(nCol - 1);
485  }
486  switch (nPos)
487  {
488  case 0:
489  return std::make_shared<sc::AggregateFunction>(aColumns,sc::AGGREGATE_FUNCTION::SUM);
490  case 1:
491  return std::make_shared<sc::AggregateFunction>(aColumns,sc::AGGREGATE_FUNCTION::AVERAGE);
492  case 2:
493  return std::make_shared<sc::AggregateFunction>(aColumns,sc::AGGREGATE_FUNCTION::MIN);
494  case 3:
495  return std::make_shared<sc::AggregateFunction>(aColumns,sc::AGGREGATE_FUNCTION::MAX);
496  default:
497  assert(false);
498  }
499 
500  return nullptr;
501 }
502 
503 class ScNumberTransformation : public ScDataTransformationBaseControl
504 {
505 private:
506  std::unique_ptr<weld::Entry> mxColumnNums;
507  std::unique_ptr<weld::ComboBox> mxType;
508  std::unique_ptr<weld::Button> mxDelete;
509  std::function<void(sal_uInt32&)> maDeleteTransformation;
510  const ScDocument* mpDoc;
511 
512 public:
513  ScNumberTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
514 
515  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
516  DECL_LINK(DeleteHdl, weld::Button&, void);
517 };
518 
519 ScNumberTransformation::ScNumberTransformation(
520  const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
521  : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/numbertransformationentry.ui", nIndex)
522  , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
523  , mxType(mxBuilder->weld_combo_box("ed_lst"))
524  , mxDelete(mxBuilder->weld_button("ed_delete"))
525  , maDeleteTransformation(std::move(aDeleteTransformation))
526  , mpDoc(pDoc)
527 {
528  mxDelete->connect_clicked(LINK(this,ScNumberTransformation, DeleteHdl));
529 }
530 
531 std::shared_ptr<sc::DataTransformation> ScNumberTransformation::getTransformation()
532 {
533  OUString aColumnString = mxColumnNums->get_text();
534  sal_Int32 nPos = mxType->get_active();
535  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
536  std::set<SCCOL> aColumns;
537  for (const auto& rColStr : aSplitColumns)
538  {
539  sal_Int32 nCol = rColStr.toInt32();
540  if (nCol <= 0)
541  continue;
542 
543  if (nCol > mpDoc->MaxCol())
544  continue;
545 
546  // translate from 1-based column notations to internal Calc one
547  aColumns.insert(nCol - 1);
548  }
549  switch (nPos)
550  {
551  case 0:
552  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::SIGN);
553  case 1:
554  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::ROUND);
555  case 2:
556  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::ROUND_UP);
557  case 3:
558  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN);
559  case 4:
560  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE);
561  case 5:
562  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::LOG_E);
563  case 6:
564  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::LOG_10);
565  case 7:
566  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::CUBE);
567  case 8:
568  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::SQUARE);
569  case 9:
570  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT);
571  case 10:
572  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::EXPONENT);
573  case 11:
574  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::IS_EVEN);
575  case 12:
576  return std::make_shared<sc::NumberTransformation>(aColumns,sc::NUMBER_TRANSFORM_TYPE::IS_ODD);
577  default:
578  assert(false);
579  }
580 
581  return nullptr;
582 }
583 
584 class ScReplaceNullTransformation : public ScDataTransformationBaseControl
585 {
586 private:
587  std::unique_ptr<weld::Entry> mxColumnNums;
588  std::unique_ptr<weld::Entry> mxReplaceString;
589  std::unique_ptr<weld::Button> mxDelete;
590  std::function<void(sal_uInt32&)> maDeleteTransformation;
591  const ScDocument *mpDoc;
592 
593 public:
594 
595  ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
596 
597  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
598  DECL_LINK(DeleteHdl, weld::Button&, void);
599 };
600 
601 ScReplaceNullTransformation::ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
602  : ScDataTransformationBaseControl(pParent,"modules/scalc/ui/replacenulltransformationentry.ui", nIndex)
603  , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
604  , mxReplaceString(mxBuilder->weld_entry("ed_str"))
605  , mxDelete(mxBuilder->weld_button("ed_delete"))
606  , maDeleteTransformation(aDeleteTransformation)
607  , mpDoc(pDoc)
608 {
609  mxDelete->connect_clicked(LINK(this,ScReplaceNullTransformation, DeleteHdl));
610 }
611 
612 
613 std::shared_ptr<sc::DataTransformation> ScReplaceNullTransformation::getTransformation()
614 {
615  OUString aColumnString = mxColumnNums->get_text();
616  OUString aReplaceWithString = mxReplaceString->get_text();
617  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
618  std::set<SCCOL> aColumns;
619  for (const auto& rColStr : aSplitColumns)
620  {
621  sal_Int32 nCol = rColStr.toInt32();
622  if (nCol <= 0)
623  continue;
624 
625  if (nCol > mpDoc->MaxCol())
626  continue;
627 
628  // translate from 1-based column notations to internal Calc one
629  aColumns.insert(nCol - 1);
630  }
631 
632  return std::make_shared<sc::ReplaceNullTransformation>(aColumns,aReplaceWithString);
633 }
634 
635 class ScDateTimeTransformation : public ScDataTransformationBaseControl
636 {
637 private:
638  std::unique_ptr<weld::Entry> mxColumnNums;
639  std::unique_ptr<weld::ComboBox> mxType;
640  std::unique_ptr<weld::Button> mxDelete;
641  std::function<void(sal_uInt32&)> maDeleteTransformation;
642  const ScDocument* mpDoc;
643 
644 public:
645 
646  ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
647 
648  virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
649  DECL_LINK(DeleteHdl, weld::Button&, void);
650 };
651 
652 ScDateTimeTransformation::ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
653  : ScDataTransformationBaseControl(pParent,"modules/scalc/ui/datetimetransformationentry.ui", nIndex)
654  , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
655  , mxType(mxBuilder->weld_combo_box("ed_lst"))
656  , mxDelete(mxBuilder->weld_button("ed_delete"))
657  , maDeleteTransformation(aDeleteTransformation)
658  , mpDoc(pDoc)
659 {
660  mxDelete->connect_clicked(LINK(this,ScDateTimeTransformation, DeleteHdl));
661 }
662 
663 std::shared_ptr<sc::DataTransformation> ScDateTimeTransformation::getTransformation()
664 {
665  OUString aColumnString = mxColumnNums->get_text();
666  sal_Int32 nPos = mxType->get_active();
667  std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
668  std::set<SCCOL> aColumns;
669  for (const auto& rColStr : aSplitColumns)
670  {
671  sal_Int32 nCol = rColStr.toInt32();
672  if (nCol <= 0)
673  continue;
674 
675  if (nCol > mpDoc->MaxCol())
676  continue;
677 
678  // translate from 1-based column notations to internal Calc one
679  aColumns.insert(nCol - 1);
680 }
681  switch (nPos)
682  {
683  case 0:
684  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING);
685  case 1:
686  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::YEAR);
687  case 2:
688  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR);
689  case 3:
690  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR);
691  case 4:
692  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::MONTH);
693  case 5:
694  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME);
695  case 6:
696  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH);
697  case 7:
698  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH);
699  case 8:
700  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DAY);
701  case 9:
702  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK);
703  case 10:
704  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR);
705  case 11:
706  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::QUARTER);
707  case 12:
708  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER);
709  case 13:
710  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER);
711  case 14:
712  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::HOUR);
713  case 15:
714  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::MINUTE);
715  case 16:
716  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::SECOND);
717  case 17:
718  return std::make_shared<sc::DateTimeTransformation>(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::TIME);
719  default:
720  assert(false);
721  }
722 
723  return nullptr;
724 }
725 
726 }
727 
728 ScDataProviderDlg::ScDataProviderDlg(weld::Window* pParent, std::shared_ptr<ScDocument> pDoc,
729  const ScDocument* pDocument)
730  : GenericDialogController(pParent, "modules/scalc/ui/dataproviderdlg.ui", "dataproviderdlg")
731  , mxDoc(std::move(pDoc))
732  , mxStartMenu(m_xBuilder->weld_menu("start"))
733  , mxColumnMenu(m_xBuilder->weld_menu("column"))
734  , mxBox(m_xBuilder->weld_container("data_table"))
735  , m_xTableParent(mxBox->CreateChildFrame())
736  , mxTable(VclPtr<ScDataTableView>::Create(m_xTableParent))
737  , mxScroll(m_xBuilder->weld_scrolled_window("scroll"))
738  , mxList(m_xBuilder->weld_container("operation_ctrl"))
739  , mxDataProviderCtrl(new ScDataProviderBaseControl(mxList.get(), LINK(this, ScDataProviderDlg, ImportHdl)))
740  , mxDBRanges(m_xBuilder->weld_combo_box("select_db_range"))
741  , mnIndex(0)
742 {
743  Size aPrefSize = mxTable->GetOptimalSize();
744  mxBox->set_size_request(aPrefSize.Width(), aPrefSize.Height());
745  mxTable->Show();
746 
747  mxTable->Init(mxDoc);
748  ScDBCollection* pDBCollection = pDocument->GetDBCollection();
749  auto& rNamedDBs = pDBCollection->getNamedDBs();
750  for (auto& rNamedDB : rNamedDBs)
751  {
752  mxDBRanges->append_text(rNamedDB->GetName());
753  }
754 
755  pDBData = new ScDBData("data", 0, 0, 0, mxDoc->MaxCol(), mxDoc->MaxRow());
756  bool bSuccess = mxDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr<ScDBData>(pDBData));
757  SAL_WARN_IF(!bSuccess, "sc", "temporary warning");
758 
759  InitMenu();
760 
761  maIdle.SetPriority( TaskPriority::LOWEST );
762  maIdle.SetInvokeHandler( LINK( this, ScDataProviderDlg, ScrollToEnd) );
763 }
764 
766 {
768  m_xTableParent->dispose();
769  m_xTableParent.clear();
770 }
771 
773 {
774  for (const auto& itrStartData : aStartData)
775  mxStartMenu->append(OUString::number(itrStartData.nMenuID), OUString::createFromAscii(itrStartData.aMenuName));
776  mxStartMenu->connect_activate(LINK(this, ScDataProviderDlg, StartMenuHdl));
777 
778  for (const auto& itrColumnData : aColumnData)
779  mxColumnMenu->append(OUString::number(itrColumnData.nMenuID), OUString::createFromAscii(itrColumnData.aMenuName));
780  mxColumnMenu->connect_activate(LINK(this, ScDataProviderDlg, ColumnMenuHdl));
781 }
782 
783 IMPL_LINK(ScDataProviderDlg, StartMenuHdl, const OString&, rIdent, void)
784 {
785  auto nId = rIdent.toInt32();
786  for (auto& i: aStartData)
787  {
788  if (i.nMenuID == nId)
789  {
790  i.maCallback(this);
791  return;
792  }
793  }
794 }
795 
797 {
798  mxScroll->vadjustment_set_value(mxScroll->vadjustment_get_upper());
799 }
800 
801 IMPL_LINK(ScDataProviderDlg, ColumnMenuHdl, const OString&, rIdent, void)
802 {
803  auto nId = rIdent.toInt32();
804  for (auto& i: aColumnData)
805  {
806  if (i.nMenuID == nId)
807  {
808  i.maCallback(this);
809  // scroll to bottom when something added to the list
810  maIdle.Start();
811  return;
812  }
813  }
814 }
815 
817 {
818  if (pCtrl == mxDataProviderCtrl.get())
819  {
820  import(*mxDoc, true);
821  }
822 }
823 
825 {
826  m_xDialog->response(RET_OK);
827 }
828 
830 {
831  m_xDialog->response(RET_CANCEL);
832 }
833 
835 {
836  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
837  maControls.emplace_back(std::make_unique<ScDeleteColumnTransformationControl>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
838 }
839 
841 {
842  SCCOL nStartCol = -1;
843  SCCOL nEndCol = -1;
844  mxTable->getColRange(nStartCol, nEndCol);
845  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
846  maControls.emplace_back(std::make_unique<ScSplitColumnTransformationControl>(mxList.get(), nStartCol, mnIndex++, adeleteTransformation));
847 }
848 
850 {
851  SCCOL nStartCol = -1;
852  SCCOL nEndCol = -1;
853  mxTable->getColRange(nStartCol, nEndCol);
854  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
855  maControls.emplace_back(std::make_unique<ScMergeColumnTransformationControl>(mxDoc.get(), mxList.get(), nStartCol, nEndCol, mnIndex++, adeleteTransformation));
856 }
857 
859 {
860  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
861  maControls.emplace_back(std::make_unique<ScColumnTextTransformation>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
862 }
863 
865 {
866  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
867  maControls.emplace_back(std::make_unique<ScSortTransformationControl>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
868 }
869 
871 {
872  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
873  maControls.emplace_back(std::make_unique<ScAggregateFunction>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
874 }
875 
877 {
878  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
879  maControls.emplace_back(std::make_unique<ScNumberTransformation>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
880 }
881 
883 {
884  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
885  maControls.emplace_back(std::make_unique<ScReplaceNullTransformation>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
886 }
887 
889 {
890  std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
891  maControls.emplace_back(std::make_unique<ScDateTimeTransformation>(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation));
892 }
893 
894 namespace {
895 
896 bool hasDBName(const OUString& rName, ScDBCollection* pDBCollection)
897 {
898  if (pDBCollection->getNamedDBs().findByUpperName(ScGlobal::getCharClassPtr()->uppercase(rName)))
899  return true;
900 
901  return false;
902 }
903 
904 }
905 
906 void ScDataProviderDlg::import(ScDocument& rDoc, bool bInternal)
907 {
908  sc::ExternalDataSource aSource = mxDataProviderCtrl->getDataSource(&rDoc);
909 
910  for (size_t i = 0; i < maControls.size(); ++i)
911  {
912  ScDataTransformationBaseControl* pTransformationCtrl = maControls[i].get();
913  aSource.AddDataTransformation(pTransformationCtrl->getTransformation());
914  }
915  if (bInternal)
916  aSource.setDBData(pDBData->GetName());
917  else
918  {
919  aSource.setDBData(mxDBRanges->get_active_text());
920  if (!hasDBName(aSource.getDBName(), rDoc.GetDBCollection()))
921  return;
922  rDoc.GetExternalDataMapper().insertDataSource(aSource);
923  }
924  aSource.refresh(&rDoc, true);
925  mxTable->Invalidate();
926 }
927 
928 void ScDataProviderDlg::deletefromList(sal_uInt32 nIndex)
929 {
930  auto itr = maControls.erase(maControls.begin() + nIndex);
931  while (itr != maControls.end())
932  {
933  (*itr)->updateIndex(nIndex++);
934  ++itr;
935  }
936  --mnIndex;
937 }
938 
939 IMPL_LINK_NOARG(ScDeleteColumnTransformationControl, DeleteHdl, weld::Button&, void)
940 {
941  maDeleteTransformation(mnIndex);
942 }
943 
944 IMPL_LINK_NOARG(ScSplitColumnTransformationControl, DeleteHdl, weld::Button&, void)
945 {
946  maDeleteTransformation(mnIndex);
947 }
948 
949 IMPL_LINK_NOARG(ScMergeColumnTransformationControl, DeleteHdl, weld::Button&, void)
950 {
951  maDeleteTransformation(mnIndex);
952 }
953 
954 IMPL_LINK_NOARG(ScNumberTransformation, DeleteHdl, weld::Button&, void)
955 {
956  maDeleteTransformation(mnIndex);
957 }
958 
959 IMPL_LINK_NOARG(ScAggregateFunction, DeleteHdl, weld::Button&, void)
960 {
961  maDeleteTransformation(mnIndex);
962 }
963 
964 IMPL_LINK_NOARG(ScSortTransformationControl, DeleteHdl, weld::Button&, void)
965 {
966  maDeleteTransformation(mnIndex);
967 }
968 
969 IMPL_LINK_NOARG(ScColumnTextTransformation, DeleteHdl, weld::Button&, void)
970 {
971  maDeleteTransformation(mnIndex);
972 }
973 
974 IMPL_LINK_NOARG(ScReplaceNullTransformation, DeleteHdl, weld::Button&, void)
975 {
976  maDeleteTransformation(mnIndex);
977 }
978 
979 IMPL_LINK_NOARG(ScDateTimeTransformation, DeleteHdl, weld::Button&, void)
980 {
981  maDeleteTransformation(mnIndex);
982 }
983 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
std::unique_ptr< ScDataProviderBaseControl > mxDataProviderCtrl
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:61
std::shared_ptr< weld::Dialog > m_xDialog
std::unique_ptr< weld::Container > mxGrid
std::shared_ptr< ScDocument > mxDoc
URL aURL
sc::ExternalDataSource getDataSource(ScDocument *pDoc)
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:813
void Init(std::shared_ptr< ScDocument > pDoc)
static std::vector< OUString > getDataProviders()
void getColRange(SCCOL &rStartCol, SCCOL &rEndCol) const
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
void disposeAndClear()
sal_Int32 mnCol
sal_Int16 nId
std::unique_ptr< weld::Menu > mxColumnMenu
RET_CANCEL
std::unique_ptr< weld::Container > mxBox
void AddDataTransformation(const std::shared_ptr< sc::DataTransformation > &mpDataTransformation)
std::vector< OUString > split(const OUString &rStr, sal_Unicode cSeparator)
sal_uInt16 sal_Unicode
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
SC_DLLPUBLIC sc::ExternalDataMapper & GetExternalDataMapper()
ScDataTransformationBaseControl(weld::Container *pParent, const OUString &rUIFile, sal_uInt32 nIndex)
std::unique_ptr< weld::Button > mxApplyBtn
std::unique_ptr< weld::Menu > mxStartMenu
void setID(const OUString &rID)
IMPL_LINK_NOARG(ScDataProviderBaseControl, ProviderSelectHdl, weld::ComboBox &, void)
IMPL_LINK(ScDataProviderDlg, StartMenuHdl, const OString &, rIdent, void)
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:869
css::uno::Reference< css::awt::XWindow > m_xTableParent
int i
void import(ScDocument &rDoc, bool bInternal=false)
void updateIndex(sal_uInt32 nIndex)
std::unique_ptr< weld::ComboBox > mxProviderList
sal_Int16 SCCOL
Definition: types.hxx:22
OUString getDBName() const
void deletefromList(sal_uInt32 nIndex)
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
std::unique_ptr< weld::Builder > mxBuilder
tools::Long Width() const
void refresh(ScDocument *pDoc, bool bDeterministic=false)
const OUString & GetName() const
Definition: dbdata.hxx:122
void updateApplyBtn(bool bValidConfig)
virtual void move(weld::Widget *pWidget, weld::Container *pNewParent)=0
ScDBData * findByUpperName(const OUString &rName)
Definition: dbdata.cxx:1144
virtual ~ScDataProviderDlg() override
std::unique_ptr< weld::Builder > mxBuilder
void insertDataSource(const ExternalDataSource &rSource)
std::unique_ptr< char[]> aBuffer
#define SAL_WARN_IF(condition, area, stream)
std::unique_ptr< weld::Entry > mxEditURL
Link< ScDataProviderBaseControl *, void > maImportCallback
RET_OK
std::unique_ptr< weld::Entry > mxEditID
SCCOLROW nField
Definition: sortparam.hxx:36
tools::Long Height() const
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1011
virtual std::shared_ptr< sc::DataTransformation > getTransformation()=0
void SetInvokeHandler(const Link< Timer *, void > &rLink)
ScDataProviderDlg(weld::Window *pWindow, std::shared_ptr< ScDocument > pDoc, const ScDocument *pDocument)
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:315
virtual Size GetOptimalSize() const override
void SetPriority(TaskPriority ePriority)
int mnIndex
ScDataProviderBaseControl(weld::Container *pParent, const Link< ScDataProviderBaseControl *, void > &rImportCallback)
std::unique_ptr< weld::ComboBox > mxDBRanges
VclPtr< ScDataTableView > mxTable
void setDBData(const OUString &rDBName)
std::vector< std::unique_ptr< ScDataTransformationBaseControl > > maControls
std::unique_ptr< weld::Container > mxGrid
std::unique_ptr< weld::Container > mxList
sal_uInt16 nPos
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
DECL_LINK(ProviderSelectHdl, weld::ComboBox &, void)