Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/miscdlgs/dataproviderdlg.cxx
Line
Count
Source
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
#include <scresid.hxx>
12
#include <globstr.hrc>
13
14
#include <document.hxx>
15
#include <dataprovider.hxx>
16
#include <datatransformation.hxx>
17
#include <datamapper.hxx>
18
#include <dbdata.hxx>
19
20
#include <comphelper/string.hxx>
21
#include <sal/log.hxx>
22
#include <sfx2/filedlghelper.hxx>
23
#include <unotools/charclass.hxx>
24
#include <utility>
25
#include <vcl/svapp.hxx>
26
#include <vcl/weld/Builder.hxx>
27
#include <vcl/weld/ComboBox.hxx>
28
#include <vcl/weld/Dialog.hxx>
29
#include <vcl/weld/MessageDialog.hxx>
30
31
class ScDataTransformationBaseControl
32
{
33
protected:
34
    std::unique_ptr<weld::Builder> mxBuilder;
35
    std::unique_ptr<weld::Container> mxGrid;
36
    weld::Container* mpContainer;
37
38
    sal_uInt32 mnIndex;
39
40
public:
41
    ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex);
42
    virtual ~ScDataTransformationBaseControl();
43
44
0
    void updateIndex(sal_uInt32 nIndex) { mnIndex = nIndex; }
45
46
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() = 0;
47
};
48
49
ScDataTransformationBaseControl::ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex)
50
0
    : mxBuilder(Application::CreateBuilder(pParent, rUIFile))
51
0
    , mxGrid(mxBuilder->weld_container(u"grid"_ustr))
52
0
    , mpContainer(pParent)
53
0
    , mnIndex(nIndex)
54
0
{
55
0
}
56
57
ScDataTransformationBaseControl::~ScDataTransformationBaseControl()
58
0
{
59
0
    mpContainer->move(mxGrid.get(), nullptr);
60
0
}
61
62
namespace {
63
64
class ScDeleteColumnTransformationControl : public ScDataTransformationBaseControl
65
{
66
private:
67
    std::unique_ptr<weld::Entry> mxColumnNums;
68
    std::unique_ptr<weld::Button> mxDelete;
69
    std::function<void(sal_uInt32&)> maDeleteTransformation;
70
    const ScDocument* mpDoc;
71
72
public:
73
    ScDeleteColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 aIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
74
75
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
76
    DECL_LINK(DeleteHdl, weld::Button&, void);
77
};
78
79
ScDeleteColumnTransformationControl::ScDeleteColumnTransformationControl(
80
    const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
81
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/deletecolumnentry.ui"_ustr, nIndex)
82
0
    , mxColumnNums(mxBuilder->weld_entry(u"ed_columns"_ustr))
83
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
84
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
85
0
    , mpDoc(pDoc)
86
0
{
87
0
    mxDelete->connect_clicked(LINK(this,ScDeleteColumnTransformationControl, DeleteHdl));
88
0
}
89
90
std::shared_ptr<sc::DataTransformation> ScDeleteColumnTransformationControl::getTransformation()
91
0
{
92
0
    OUString aColumnString = mxColumnNums->get_text();
93
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
94
0
    std::set<SCCOL> ColNums;
95
0
    for (const auto& rColStr : aSplitColumns)
96
0
    {
97
0
        sal_Int32 nCol = rColStr.toInt32();
98
0
        if (nCol <= 0)
99
0
            continue;
100
101
0
        if (nCol > mpDoc->MaxCol())
102
0
            continue;
103
104
        // translate from 1-based column notations to internal Calc one
105
0
        ColNums.insert(nCol - 1);
106
0
    }
107
108
0
    return std::make_shared<sc::ColumnRemoveTransformation>(std::move(ColNums));
109
0
}
110
111
class ScSplitColumnTransformationControl : public ScDataTransformationBaseControl
112
{
113
private:
114
    std::unique_ptr<weld::Entry> mxSeparator;
115
    std::unique_ptr<weld::Entry> mxNumColumns;
116
    std::unique_ptr<weld::Button> mxDelete;
117
    std::function<void(sal_uInt32&)> maDeleteTransformation;
118
    const ScDocument* mpDoc;
119
120
public:
121
    ScSplitColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
122
123
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
124
    DECL_LINK(DeleteHdl, weld::Button&, void);
125
};
126
127
ScSplitColumnTransformationControl::ScSplitColumnTransformationControl(
128
    const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex,
129
    std::function<void(sal_uInt32&)> aDeleteTransformation)
130
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/splitcolumnentry.ui"_ustr, nIndex)
131
0
    , mxSeparator(mxBuilder->weld_entry(u"ed_separator"_ustr))
132
0
    , mxNumColumns(mxBuilder->weld_entry(u"num_cols"_ustr))
133
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
134
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
135
0
    , mpDoc(pDoc)
136
0
{
137
    // for uitests
138
0
    mxSeparator->set_buildable_name(mxSeparator->get_buildable_name() + OUString::number(nIndex));
139
0
    mxNumColumns->set_buildable_name(mxNumColumns->get_buildable_name() + OUString::number(nIndex));
140
0
    mxDelete->set_buildable_name(mxDelete->get_buildable_name() + OUString::number(nIndex));
141
142
0
    mxDelete->connect_clicked(LINK(this,ScSplitColumnTransformationControl, DeleteHdl));
143
0
}
144
145
std::shared_ptr<sc::DataTransformation> ScSplitColumnTransformationControl::getTransformation()
146
0
{
147
0
    OUString aSeparator = mxSeparator->get_text();
148
0
    sal_Unicode cSeparator = aSeparator.isEmpty() ? ',' : aSeparator[0];
149
0
    OUString aColStr = mxNumColumns->get_text();
150
0
    SCCOL mnCol = -1;
151
0
    sal_Int32 nCol = aColStr.toInt32();
152
0
    if (nCol > 0 && nCol <= mpDoc->MaxCol())
153
0
        mnCol = nCol - 1;
154
0
    return std::make_shared<sc::SplitColumnTransformation>(mnCol, cSeparator);
155
0
}
156
157
class ScMergeColumnTransformationControl : public ScDataTransformationBaseControl
158
{
159
private:
160
    std::unique_ptr<weld::Entry> mxSeparator;
161
    std::unique_ptr<weld::Entry> mxEdColumns;
162
    std::unique_ptr<weld::Button> mxDelete;
163
    std::function<void(sal_uInt32&)> maDeleteTransformation;
164
    const ScDocument* mpDoc;
165
166
public:
167
    ScMergeColumnTransformationControl(const ScDocument *pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
168
169
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
170
    DECL_LINK(DeleteHdl, weld::Button&, void);
171
};
172
173
ScMergeColumnTransformationControl::ScMergeColumnTransformationControl(
174
    const ScDocument* pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex,
175
    std::function<void(sal_uInt32&)> aDeleteTransformation)
176
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/mergecolumnentry.ui"_ustr, nIndex)
177
0
    , mxSeparator(mxBuilder->weld_entry(u"ed_separator"_ustr))
178
0
    , mxEdColumns(mxBuilder->weld_entry(u"ed_columns"_ustr))
179
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
180
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
181
0
    , mpDoc(pDoc)
182
0
{
183
    // for uitests
184
0
    mxSeparator->set_buildable_name(mxSeparator->get_buildable_name() + OUString::number(nIndex));
185
0
    mxEdColumns->set_buildable_name(mxEdColumns->get_buildable_name() + OUString::number(nIndex));
186
0
    mxDelete->set_buildable_name(mxDelete->get_buildable_name() + OUString::number(nIndex));
187
188
0
    mxDelete->connect_clicked(LINK(this,ScMergeColumnTransformationControl, DeleteHdl));
189
190
0
    OUStringBuffer aBuffer;
191
192
    // map from zero based to one based column numbers
193
0
    aBuffer.append(static_cast<sal_Int32>(nStartCol + 1));
194
0
    for ( SCCOL nCol = nStartCol + 1; nCol <= nEndCol; ++nCol)
195
0
    {
196
0
        aBuffer.append(";" + OUString::number(nCol + 1));
197
0
    }
198
199
0
    mxEdColumns->set_text(aBuffer.makeStringAndClear());
200
0
}
201
202
std::shared_ptr<sc::DataTransformation> ScMergeColumnTransformationControl::getTransformation()
203
0
{
204
0
    OUString aColumnString = mxEdColumns->get_text();
205
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
206
0
    std::set<SCCOL> aMergedColumns;
207
0
    for (const auto& rColStr : aSplitColumns)
208
0
    {
209
0
        sal_Int32 nCol = rColStr.toInt32();
210
0
        if (nCol <= 0)
211
0
            continue;
212
213
0
        if (nCol > mpDoc->MaxCol())
214
0
            continue;
215
216
        // translate from 1-based column notations to internal Calc one
217
0
        aMergedColumns.insert(nCol - 1);
218
0
    }
219
0
    return std::make_shared<sc::MergeColumnTransformation>(std::move(aMergedColumns), mxSeparator->get_text());
220
0
}
221
222
class ScSortTransformationControl : public ScDataTransformationBaseControl
223
{
224
private:
225
    std::unique_ptr<weld::ComboBox> mxType;
226
    std::unique_ptr<weld::Entry> mxEdColumns;
227
    std::unique_ptr<weld::Button> mxDelete;
228
    std::function<void(sal_uInt32&)> maDeleteTransformation;
229
    const ScDocument* mpDoc;
230
231
public:
232
    ScSortTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
233
234
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
235
    DECL_LINK(DeleteHdl, weld::Button&, void);
236
};
237
238
ScSortTransformationControl::ScSortTransformationControl(
239
    const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
240
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/sorttransformationentry.ui"_ustr, nIndex)
241
0
    , mxType(mxBuilder->weld_combo_box(u"ed_ascending"_ustr))
242
0
    , mxEdColumns(mxBuilder->weld_entry(u"ed_columns"_ustr))
243
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
244
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
245
0
    , mpDoc(pDoc)
246
0
{
247
0
    mxDelete->connect_clicked(LINK(this,ScSortTransformationControl, DeleteHdl));
248
0
}
249
250
std::shared_ptr<sc::DataTransformation> ScSortTransformationControl::getTransformation()
251
0
{
252
0
    OUString aColStr = mxEdColumns->get_text();
253
0
    bool aIsAscending = mxType->get_active();
254
0
    SCCOL aColumn = 0;
255
0
    sal_Int32 nCol = aColStr.toInt32();
256
0
    if (nCol > 0 && nCol <= mpDoc->MaxCol())
257
0
        aColumn = nCol - 1;     // translate from 1-based column notations to internal Calc one
258
259
0
    ScSortParam aSortParam;
260
0
    SCCOL nEndCol = mpDoc->MaxCol();
261
0
    SCROW nEndRow = mpDoc->MaxRow();
262
0
    SCCOL nStartCol = 0;
263
0
    SCROW nStartRow = 0;
264
0
    SCTAB nTab = 0; // for internal doc in case of Apply and clipboard in case of OK
265
0
    if (!mpDoc->ShrinkToDataArea(nTab, nStartCol, nStartRow, nEndCol, nEndRow))
266
0
    {
267
        // tdf#169515 The preview document does not show the sorted data. Reason: ShrinkToDataArea
268
        // fails. ToDo: Why?
269
        // Workaround: We use the size of the "internalhelper" database range instead. In case the
270
        // user has defined a huge range, LibreOffice seems to hang. Thus the size is restricted here
271
        // although the preview does not show the final result in that case.
272
0
        ScDBCollection::NamedDBs& rLocalDBs = mpDoc->GetDBCollection()->getNamedDBs();
273
0
        ScDBData* pDB = rLocalDBs.findByName(u"internalhelper"_ustr);
274
0
        if (pDB)
275
0
        {
276
0
            pDB->GetArea(nTab, nStartCol, nStartRow, nEndCol, nEndRow);
277
0
            nEndCol = std::min<SCCOL>(nEndCol, nStartCol + 30);
278
0
            nEndRow = std::min<SCROW>(nEndRow, nStartRow + 10000);
279
0
        }
280
0
        else
281
0
        { // should not happen
282
0
            nEndCol = 30;
283
0
            nEndRow = 10000;
284
0
        }
285
0
    }
286
0
    aSortParam.nCol1 = nStartCol;
287
0
    aSortParam.nRow1 = nStartRow;
288
0
    aSortParam.nCol2 = nEndCol;
289
0
    aSortParam.nRow2 = nEndRow;
290
0
    {
291
0
        ScDBCollection::NamedDBs& rLocalDBs = mpDoc->GetDBCollection()->getNamedDBs();
292
0
        ScDBData* pDB = rLocalDBs.findByName(u"internalhelper"_ustr);
293
0
        if (pDB)
294
0
            aSortParam.bHasHeader = pDB->HasHeader();
295
0
        else
296
0
            aSortParam.bHasHeader = true;
297
0
    }
298
0
    aSortParam.maKeyState[0].bDoSort = true;
299
0
    aSortParam.maKeyState[0].nField = aColumn;
300
0
    aSortParam.maKeyState[0].bAscending = aIsAscending;
301
0
    return std::make_shared<sc::SortTransformation>(aSortParam);
302
0
}
303
304
class ScColumnTextTransformation : public ScDataTransformationBaseControl
305
{
306
private:
307
    std::unique_ptr<weld::Entry> mxColumnNums;
308
    std::unique_ptr<weld::ComboBox> mxType;
309
    std::unique_ptr<weld::Button> mxDelete;
310
    std::function<void(sal_uInt32&)> maDeleteTransformation;
311
    const ScDocument* mpDoc;
312
313
public:
314
    ScColumnTextTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
315
316
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
317
    DECL_LINK(DeleteHdl, weld::Button&, void);
318
};
319
320
ScColumnTextTransformation::ScColumnTextTransformation(
321
    const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
322
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/texttransformationentry.ui"_ustr, nIndex)
323
0
    , mxColumnNums(mxBuilder->weld_entry(u"ed_columns"_ustr))
324
0
    , mxType(mxBuilder->weld_combo_box(u"ed_lst"_ustr))
325
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
326
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
327
0
    , mpDoc(pDoc)
328
0
{
329
0
    mxDelete->connect_clicked(LINK(this,ScColumnTextTransformation, DeleteHdl));
330
0
}
331
332
std::shared_ptr<sc::DataTransformation> ScColumnTextTransformation::getTransformation()
333
0
{
334
0
    OUString aColumnString = mxColumnNums->get_text();
335
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
336
0
    std::set<SCCOL> aColumns;
337
0
    for (const auto& rColStr : aSplitColumns)
338
0
    {
339
0
        sal_Int32 nCol = rColStr.toInt32();
340
0
        if (nCol <= 0)
341
0
            continue;
342
343
0
        if (nCol > mpDoc->MaxCol())
344
0
            continue;
345
346
        // translate from 1-based column notations to internal Calc one
347
0
        aColumns.insert(nCol - 1);
348
0
    }
349
350
0
    sal_Int32 nPos = mxType->get_active();
351
0
    switch (nPos)
352
0
    {
353
0
        case 0:
354
0
            return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TO_LOWER);
355
0
        case 1:
356
0
            return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TO_UPPER);
357
0
        case 2:
358
0
            return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::CAPITALIZE);
359
0
        case 3:
360
0
            return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TRIM);
361
0
        default:
362
0
            assert(false);
363
0
    }
364
365
0
    return nullptr;
366
0
}
367
368
class ScAggregateFunction : public ScDataTransformationBaseControl
369
{
370
private:
371
    std::unique_ptr<weld::Entry> mxColumnNums;
372
    std::unique_ptr<weld::ComboBox> mxType;
373
    std::unique_ptr<weld::Button> mxDelete;
374
    std::function<void(sal_uInt32&)> maDeleteTransformation;
375
    const ScDocument* mpDoc;
376
377
public:
378
    ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
379
380
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
381
    DECL_LINK(DeleteHdl, weld::Button&, void);
382
};
383
384
ScAggregateFunction::ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex,
385
                                         std::function<void(sal_uInt32&)> aDeleteTransformation)
386
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/aggregatefunctionentry.ui"_ustr, nIndex)
387
0
    , mxColumnNums(mxBuilder->weld_entry(u"ed_columns"_ustr))
388
0
    , mxType(mxBuilder->weld_combo_box(u"ed_lst"_ustr))
389
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
390
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
391
0
    , mpDoc(pDoc)
392
0
{
393
0
    mxDelete->connect_clicked(LINK(this,ScAggregateFunction, DeleteHdl));
394
0
}
395
396
std::shared_ptr<sc::DataTransformation> ScAggregateFunction::getTransformation()
397
0
{
398
0
    OUString aColumnString = mxColumnNums->get_text();
399
0
    sal_Int32 nPos = mxType->get_active();
400
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
401
0
    std::set<SCCOL> aColumns;
402
0
    for (const auto& rColStr : aSplitColumns)
403
0
    {
404
0
        sal_Int32 nCol = rColStr.toInt32();
405
0
        if (nCol <= 0)
406
0
            continue;
407
408
0
        if (nCol > mpDoc->MaxCol())
409
0
            continue;
410
411
        // translate from 1-based column notations to internal Calc one
412
0
        aColumns.insert(nCol - 1);
413
0
    }
414
0
    switch (nPos)
415
0
    {
416
0
        case 0:
417
0
            return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::SUM);
418
0
        case 1:
419
0
            return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::AVERAGE);
420
0
        case 2:
421
0
            return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::MIN);
422
0
        case 3:
423
0
            return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::MAX);
424
0
        default:
425
0
            assert(false);
426
0
    }
427
428
0
    return nullptr;
429
0
}
430
431
class ScNumberTransformation : public ScDataTransformationBaseControl
432
{
433
private:
434
    std::unique_ptr<weld::Entry> mxColumnNums;
435
    std::unique_ptr<weld::ComboBox> mxType;
436
    std::unique_ptr<weld::Button> mxDelete;
437
    std::function<void(sal_uInt32&)> maDeleteTransformation;
438
    const ScDocument* mpDoc;
439
440
public:
441
    ScNumberTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
442
443
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
444
    DECL_LINK(DeleteHdl, weld::Button&, void);
445
};
446
447
ScNumberTransformation::ScNumberTransformation(
448
    const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
449
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/numbertransformationentry.ui"_ustr, nIndex)
450
0
    , mxColumnNums(mxBuilder->weld_entry(u"ed_columns"_ustr))
451
0
    , mxType(mxBuilder->weld_combo_box(u"ed_lst"_ustr))
452
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
453
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
454
0
    , mpDoc(pDoc)
455
0
{
456
0
    mxDelete->connect_clicked(LINK(this,ScNumberTransformation, DeleteHdl));
457
0
}
458
459
std::shared_ptr<sc::DataTransformation> ScNumberTransformation::getTransformation()
460
0
{
461
0
    OUString aColumnString = mxColumnNums->get_text();
462
0
    sal_Int32 nPos = mxType->get_active();
463
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
464
0
    std::set<SCCOL> aColumns;
465
0
    for (const auto& rColStr : aSplitColumns)
466
0
    {
467
0
        sal_Int32 nCol = rColStr.toInt32();
468
0
        if (nCol <= 0)
469
0
            continue;
470
471
0
        if (nCol > mpDoc->MaxCol())
472
0
            continue;
473
474
        // translate from 1-based column notations to internal Calc one
475
0
        aColumns.insert(nCol - 1);
476
0
    }
477
0
    switch (nPos)
478
0
    {
479
0
        case 0:
480
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SIGN);
481
0
        case 1:
482
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND);
483
0
        case 2:
484
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND_UP);
485
0
        case 3:
486
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN);
487
0
        case 4:
488
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE);
489
0
        case 5:
490
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::LOG_E);
491
0
        case 6:
492
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::LOG_10);
493
0
        case 7:
494
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::CUBE);
495
0
        case 8:
496
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SQUARE);
497
0
        case 9:
498
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT);
499
0
        case 10:
500
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::EXPONENT);
501
0
        case 11:
502
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::IS_EVEN);
503
0
        case 12:
504
0
            return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::IS_ODD);
505
0
        default:
506
0
            assert(false);
507
0
    }
508
509
0
    return nullptr;
510
0
}
511
512
class ScReplaceNullTransformation : public ScDataTransformationBaseControl
513
{
514
private:
515
    std::unique_ptr<weld::Entry> mxColumnNums;
516
    std::unique_ptr<weld::Entry> mxReplaceString;
517
    std::unique_ptr<weld::Button> mxDelete;
518
    std::function<void(sal_uInt32&)> maDeleteTransformation;
519
    const ScDocument *mpDoc;
520
521
public:
522
523
    ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
524
525
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
526
    DECL_LINK(DeleteHdl, weld::Button&, void);
527
};
528
529
ScReplaceNullTransformation::ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
530
0
    : ScDataTransformationBaseControl(pParent,u"modules/scalc/ui/replacenulltransformationentry.ui"_ustr, nIndex)
531
0
    , mxColumnNums(mxBuilder->weld_entry(u"ed_columns"_ustr))
532
0
    , mxReplaceString(mxBuilder->weld_entry(u"ed_str"_ustr))
533
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
534
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
535
0
    , mpDoc(pDoc)
536
0
{
537
0
    mxDelete->connect_clicked(LINK(this,ScReplaceNullTransformation, DeleteHdl));
538
0
}
539
540
541
std::shared_ptr<sc::DataTransformation> ScReplaceNullTransformation::getTransformation()
542
0
{
543
0
    OUString aColumnString = mxColumnNums->get_text();
544
0
    OUString aReplaceWithString = mxReplaceString->get_text();
545
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
546
0
    std::set<SCCOL> aColumns;
547
0
    for (const auto& rColStr : aSplitColumns)
548
0
    {
549
0
        sal_Int32 nCol = rColStr.toInt32();
550
0
        if (nCol <= 0)
551
0
            continue;
552
553
0
        if (nCol > mpDoc->MaxCol())
554
0
            continue;
555
556
        // translate from 1-based column notations to internal Calc one
557
0
        aColumns.insert(nCol - 1);
558
0
    }
559
560
0
    return std::make_shared<sc::ReplaceNullTransformation>(std::move(aColumns),aReplaceWithString);
561
0
}
562
563
class ScDateTimeTransformation : public ScDataTransformationBaseControl
564
{
565
private:
566
    std::unique_ptr<weld::Entry> mxColumnNums;
567
    std::unique_ptr<weld::ComboBox> mxType;
568
    std::unique_ptr<weld::Button> mxDelete;
569
    std::function<void(sal_uInt32&)> maDeleteTransformation;
570
    const ScDocument* mpDoc;
571
572
public:
573
574
    ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
575
576
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
577
    DECL_LINK(DeleteHdl, weld::Button&, void);
578
};
579
580
ScDateTimeTransformation::ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
581
0
    : ScDataTransformationBaseControl(pParent,u"modules/scalc/ui/datetimetransformationentry.ui"_ustr, nIndex)
582
0
    , mxColumnNums(mxBuilder->weld_entry(u"ed_columns"_ustr))
583
0
    , mxType(mxBuilder->weld_combo_box(u"ed_lst"_ustr))
584
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
585
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
586
0
    , mpDoc(pDoc)
587
0
{
588
0
    mxDelete->connect_clicked(LINK(this,ScDateTimeTransformation, DeleteHdl));
589
0
}
590
591
std::shared_ptr<sc::DataTransformation> ScDateTimeTransformation::getTransformation()
592
0
{
593
0
    OUString aColumnString = mxColumnNums->get_text();
594
0
    sal_Int32 nPos = mxType->get_active();
595
0
    std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
596
0
    std::set<SCCOL> aColumns;
597
0
    for (const auto& rColStr : aSplitColumns)
598
0
    {
599
0
        sal_Int32 nCol = rColStr.toInt32();
600
0
        if (nCol <= 0)
601
0
            continue;
602
603
0
        if (nCol > mpDoc->MaxCol())
604
0
            continue;
605
606
        // translate from 1-based column notations to internal Calc one
607
0
        aColumns.insert(nCol - 1);
608
0
    }
609
0
    switch (nPos)
610
0
    {
611
0
        case 0:
612
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING);
613
0
        case 1:
614
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::YEAR);
615
0
        case 2:
616
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR);
617
0
        case 3:
618
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR);
619
0
        case 4:
620
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MONTH);
621
0
        case 5:
622
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME);
623
0
        case 6:
624
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH);
625
0
        case 7:
626
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH);
627
0
        case 8:
628
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY);
629
0
        case 9:
630
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK);
631
0
        case 10:
632
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR);
633
0
        case 11:
634
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::QUARTER);
635
0
        case 12:
636
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER);
637
0
        case 13:
638
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER);
639
0
        case 14:
640
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::HOUR);
641
0
        case 15:
642
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MINUTE);
643
0
        case 16:
644
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::SECOND);
645
0
        case 17:
646
0
            return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::TIME);
647
0
        default:
648
0
            assert(false);
649
0
    }
650
651
0
    return nullptr;
652
0
}
653
654
class ScFindReplaceTransformation : public ScDataTransformationBaseControl
655
{
656
private:
657
    std::unique_ptr<weld::Entry> mxFindString;
658
    std::unique_ptr<weld::Entry> mxReplaceString;
659
    std::unique_ptr<weld::Entry> mxEdColumns;
660
    std::unique_ptr<weld::Button> mxDelete;
661
    std::function<void(sal_uInt32&)> maDeleteTransformation;
662
    const ScDocument* mpDoc;
663
664
public:
665
    ScFindReplaceTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
666
667
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
668
    DECL_LINK(DeleteHdl, weld::Button&, void);
669
};
670
671
ScFindReplaceTransformation::ScFindReplaceTransformation(
672
    const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex,
673
    std::function<void(sal_uInt32&)> aDeleteTransformation)
674
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/findreplaceentry.ui"_ustr, nIndex)
675
0
    , mxFindString(mxBuilder->weld_entry(u"ed_find"_ustr))
676
0
    , mxReplaceString(mxBuilder->weld_entry(u"ed_replace"_ustr))
677
0
    , mxEdColumns(mxBuilder->weld_entry(u"ed_columns"_ustr))
678
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
679
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
680
0
    , mpDoc(pDoc)
681
0
{
682
0
    mxDelete->connect_clicked(LINK(this, ScFindReplaceTransformation, DeleteHdl));
683
0
}
684
685
std::shared_ptr<sc::DataTransformation> ScFindReplaceTransformation::getTransformation()
686
0
{
687
0
    OUString aColStr = mxEdColumns->get_text();
688
0
    SCCOL aColumn = -1;
689
0
    sal_Int32 nCol = aColStr.toInt32();
690
0
    if (nCol > 0 && nCol <= mpDoc->MaxCol())
691
0
        aColumn = nCol - 1;
692
0
    return std::make_shared<sc::FindReplaceTransformation>(aColumn, mxFindString->get_text(), mxReplaceString->get_text());
693
0
}
694
695
class ScDeleteRowTransformation : public ScDataTransformationBaseControl
696
{
697
private:
698
    std::unique_ptr<weld::Entry> mxFindString;
699
    std::unique_ptr<weld::Entry> mxEdColumns;
700
    std::unique_ptr<weld::Button> mxDelete;
701
    std::function<void(sal_uInt32&)> maDeleteTransformation;
702
    const ScDocument* mpDoc;
703
704
public:
705
    ScDeleteRowTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
706
707
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
708
    DECL_LINK(DeleteHdl, weld::Button&, void);
709
};
710
711
ScDeleteRowTransformation::ScDeleteRowTransformation(
712
    const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex,
713
    std::function<void(sal_uInt32&)> aDeleteTransformation)
714
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/deleterowentry.ui"_ustr, nIndex)
715
0
    , mxFindString(mxBuilder->weld_entry(u"ed_find"_ustr))
716
0
    , mxEdColumns(mxBuilder->weld_entry(u"ed_columns"_ustr))
717
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
718
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
719
0
    , mpDoc(pDoc)
720
0
{
721
0
    mxDelete->connect_clicked(LINK(this, ScDeleteRowTransformation, DeleteHdl));
722
0
}
723
724
std::shared_ptr<sc::DataTransformation> ScDeleteRowTransformation::getTransformation()
725
0
{
726
0
    OUString aColStr = mxEdColumns->get_text();
727
0
    SCCOL aColumn = -1;
728
0
    sal_Int32 nCol = aColStr.toInt32();
729
0
    if (nCol > 0 && nCol <= mpDoc->MaxCol())
730
0
        aColumn = nCol - 1;
731
0
    return std::make_shared<sc::DeleteRowTransformation>(aColumn, mxFindString->get_text());
732
0
}
733
734
class ScSwapRowsTransformation : public ScDataTransformationBaseControl
735
{
736
private:
737
    std::unique_ptr<weld::Entry> mxRow;
738
    std::unique_ptr<weld::Entry> nxRow;
739
    std::unique_ptr<weld::Button> mxDelete;
740
    std::function<void(sal_uInt32&)> maDeleteTransformation;
741
    const ScDocument* mpDoc;
742
743
public:
744
    ScSwapRowsTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
745
746
    virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
747
    DECL_LINK(DeleteHdl, weld::Button&, void);
748
};
749
750
ScSwapRowsTransformation::ScSwapRowsTransformation(
751
    const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex,
752
    std::function<void(sal_uInt32&)> aDeleteTransformation)
753
0
    : ScDataTransformationBaseControl(pParent, u"modules/scalc/ui/swaprowsentry.ui"_ustr, nIndex)
754
0
    , mxRow(mxBuilder->weld_entry(u"ed_row1"_ustr))
755
0
    , nxRow(mxBuilder->weld_entry(u"ed_row2"_ustr))
756
0
    , mxDelete(mxBuilder->weld_button(u"ed_delete"_ustr))
757
0
    , maDeleteTransformation(std::move(aDeleteTransformation))
758
0
    , mpDoc(pDoc)
759
0
{
760
0
    mxDelete->connect_clicked(LINK(this, ScSwapRowsTransformation, DeleteHdl));
761
0
}
762
763
std::shared_ptr<sc::DataTransformation> ScSwapRowsTransformation::getTransformation()
764
0
{
765
0
    OUString aRowStr = mxRow->get_text();
766
0
    OUString bRowStr = nxRow->get_text();
767
0
    SCROW aRow = -1;
768
0
    SCROW bRow = -1;
769
0
    sal_Int32 mRow = aRowStr.toInt32();
770
0
    sal_Int32 nRow = bRowStr.toInt32();
771
0
    if (mRow > 0 && mRow <= mpDoc->MaxRow())
772
0
        aRow = mRow - 1;
773
0
    if (nRow > 0 && nRow <= mpDoc->MaxRow())
774
0
        bRow = nRow - 1;
775
0
    return std::make_shared<sc::SwapRowsTransformation>(aRow, bRow);
776
0
}
777
778
}
779
780
ScDataProviderDlg::ScDataProviderDlg(weld::Window* pParent, std::shared_ptr<ScDocument> pDoc,
781
                                     const ScDocument* pDocument)
782
0
    : GenericDialogController(pParent, u"modules/scalc/ui/dataproviderdlg.ui"_ustr, u"dataproviderdlg"_ustr)
783
0
    , mxDoc(std::move(pDoc))
784
0
    , mxBox(m_xBuilder->weld_container(u"data_table"_ustr))
785
0
    , m_xTableParent(mxBox->CreateChildFrame())
786
0
    , mxTable(VclPtr<ScDataTableView>::Create(m_xTableParent, mxDoc))
787
0
    , mxDBRanges(m_xBuilder->weld_combo_box(u"select_db_range"_ustr))
788
0
    , mxOKBtn(m_xBuilder->weld_button(u"ok"_ustr))
789
0
    , mxCancelBtn(m_xBuilder->weld_button(u"cancel"_ustr))
790
0
    , mxAddTransformationBtn(m_xBuilder->weld_button(u"add_transformation"_ustr))
791
0
    , mxScroll(m_xBuilder->weld_scrolled_window(u"scroll"_ustr))
792
0
    , mxTransformationList(m_xBuilder->weld_container(u"transformation_ctrl"_ustr))
793
0
    , mxTransformationBox(m_xBuilder->weld_combo_box(u"transformation_box"_ustr))
794
0
    , mxProviderList(m_xBuilder->weld_combo_box(u"provider_lst"_ustr))
795
0
    , mxEditURL(m_xBuilder->weld_entry(u"ed_url"_ustr))
796
0
    , mxEditID(m_xBuilder->weld_entry(u"ed_id"_ustr))
797
0
    , mxApplyBtn(m_xBuilder->weld_button(u"apply"_ustr))
798
0
    , mxBrowseBtn(m_xBuilder->weld_button(u"browse"_ustr))
799
0
    , maIdle("ScDataProviderDlg maIdle")
800
0
    , mnIndex(0)
801
0
{
802
0
    Size aPrefSize = mxTable->GetOptimalSize();
803
0
    mxBox->set_size_request(aPrefSize.Width(), aPrefSize.Height());
804
0
    mxTable->Show();
805
806
0
    mpDestDBCollection = pDocument->GetDBCollection();
807
0
    auto& rNamedDBs = mpDestDBCollection->getNamedDBs();
808
0
    for (auto& rNamedDB : rNamedDBs)
809
0
    {
810
0
        mxDBRanges->append_text(rNamedDB->GetName());
811
0
    }
812
813
0
    pDBData = new ScDBData(u"data"_ustr, 0, 0, 0, mxDoc->MaxCol(), mxDoc->MaxRow());
814
0
    bool bSuccess = mxDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr<ScDBData>(pDBData));
815
0
    SAL_WARN_IF(!bSuccess, "sc", "temporary warning");
816
817
0
    mxOKBtn->connect_clicked(LINK(this, ScDataProviderDlg, ApplyQuitHdl));
818
0
    mxCancelBtn->connect_clicked(LINK(this, ScDataProviderDlg, CancelQuitHdl));
819
0
    mxAddTransformationBtn->connect_clicked(LINK(this, ScDataProviderDlg, TransformationListHdl));
820
0
    mxApplyBtn->connect_clicked(LINK(this, ScDataProviderDlg, ApplyBtnHdl));
821
0
    mxBrowseBtn->connect_clicked(LINK(this, ScDataProviderDlg, BrowseBtnHdl));
822
0
    mxTransformationBox->connect_changed(LINK(this, ScDataProviderDlg, TransformationSelectHdl));
823
0
    mxProviderList->connect_changed(LINK(this, ScDataProviderDlg, ProviderSelectHdl));
824
0
    mxEditID->connect_changed(LINK(this, ScDataProviderDlg, IDEditHdl));
825
0
    mxEditURL->connect_changed(LINK(this, ScDataProviderDlg, URLEditHdl));
826
827
0
    msApplyTooltip = mxApplyBtn->get_tooltip_text();
828
0
    msAddTransformationToolTip = mxAddTransformationBtn->get_tooltip_text();
829
0
    mxAddTransformationBtn->set_sensitive(false);
830
0
    mxAddTransformationBtn->set_tooltip_text(OUString());
831
0
    isValid();
832
833
0
    maIdle.SetPriority( TaskPriority::LOWEST );
834
0
    maIdle.SetInvokeHandler( LINK( this, ScDataProviderDlg, ScrollToEnd) );
835
0
}
836
837
ScDataProviderDlg::~ScDataProviderDlg()
838
0
{
839
0
    mxTable.disposeAndClear();
840
0
    m_xTableParent->dispose();
841
0
    m_xTableParent.clear();
842
0
}
843
844
IMPL_LINK_NOARG(ScDataProviderDlg, ScrollToEnd, Timer*, void)
845
0
{
846
0
    mxScroll->vadjustment_set_value(mxScroll->vadjustment_get_upper());
847
0
}
848
849
IMPL_LINK_NOARG(ScDataProviderDlg, ApplyQuitHdl, weld::Button&, void)
850
0
{
851
0
    m_xDialog->response(RET_OK);
852
0
}
853
854
IMPL_LINK_NOARG(ScDataProviderDlg, CancelQuitHdl, weld::Button&, void)
855
0
{
856
0
    m_xDialog->response(RET_CANCEL);
857
0
}
858
859
IMPL_LINK_NOARG(ScDataProviderDlg, TransformationListHdl, weld::Button&, void)
860
0
{
861
0
    static std::function<void(ScDataProviderDlg*)> aTransformationOp[12]{
862
0
        &ScDataProviderDlg::deleteColumn,
863
0
        &ScDataProviderDlg::deleteRowTransformation,
864
0
        &ScDataProviderDlg::swapRowsTransformation,
865
0
        &ScDataProviderDlg::splitColumn,
866
0
        &ScDataProviderDlg::mergeColumns,
867
0
        &ScDataProviderDlg::textTransformation,
868
0
        &ScDataProviderDlg::sortTransformation,
869
0
        &ScDataProviderDlg::aggregateFunction,
870
0
        &ScDataProviderDlg::numberTransformation,
871
0
        &ScDataProviderDlg::replaceNullTransformation,
872
0
        &ScDataProviderDlg::dateTimeTransformation,
873
0
        &ScDataProviderDlg::findReplaceTransformation
874
0
    };
875
0
    OUString rId = mxTransformationBox->get_active_id();
876
0
    int nPos = mxTransformationBox->find_id(rId);
877
878
0
    aTransformationOp[nPos](this);
879
0
    maIdle.Start();
880
0
    return;
881
0
}
882
883
IMPL_LINK_NOARG(ScDataProviderDlg, ProviderSelectHdl, weld::ComboBox&, void)
884
0
{
885
0
    isValid();
886
0
}
887
888
0
IMPL_LINK_NOARG(ScDataProviderDlg, IDEditHdl, weld::TextWidget&, void) { isValid(); }
889
890
0
IMPL_LINK_NOARG(ScDataProviderDlg, URLEditHdl, weld::TextWidget&, void) { isValid(); }
891
892
IMPL_LINK_NOARG(ScDataProviderDlg, ApplyBtnHdl, weld::Button&, void)
893
0
{
894
0
    updateApplyBtn(true);
895
0
    clearTablePreview();
896
0
    import(*mxDoc, true);
897
0
}
898
899
IMPL_LINK_NOARG(ScDataProviderDlg, BrowseBtnHdl, weld::Button&, void)
900
0
{
901
0
    sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, m_xDialog.get());
902
0
    aFileDialog.SetContext(sfx2::FileDialogHelper::CalcDataProvider);
903
0
    if (aFileDialog.Execute() != ERRCODE_NONE)
904
0
        return;
905
906
0
    mxEditURL->set_text(aFileDialog.GetPath());
907
0
    isValid();
908
0
}
909
910
IMPL_LINK_NOARG(ScDataProviderDlg, TransformationSelectHdl, weld::ComboBox&, void)
911
0
{
912
0
    mxAddTransformationBtn->set_sensitive(true);
913
0
    mxAddTransformationBtn->set_tooltip_text(msAddTransformationToolTip);
914
0
}
915
916
sc::ExternalDataSource ScDataProviderDlg::getDataSource(ScDocument* pDoc)
917
0
{
918
0
    sc::ExternalDataSource aSource(mxEditURL->get_text(), mxProviderList->get_active_id(), pDoc);
919
920
0
    aSource.setID(mxEditID->get_text());
921
0
    return aSource;
922
0
}
923
924
void ScDataProviderDlg::isValid()
925
0
{
926
0
    bool bValid = !mxProviderList->get_active_id().isEmpty();
927
0
    bValid &= !mxEditURL->get_text().isEmpty();
928
0
    updateApplyBtn(bValid);
929
0
}
930
931
void ScDataProviderDlg::updateApplyBtn(bool bValidConfig)
932
0
{
933
0
    if (!bValidConfig)
934
0
    {
935
0
        mxApplyBtn->set_sensitive(false);
936
0
        mxApplyBtn->set_tooltip_text(OUString());
937
0
        return;
938
0
    }
939
940
0
    mxApplyBtn->set_sensitive(true);
941
0
    mxApplyBtn->set_tooltip_text(msApplyTooltip);
942
0
}
943
944
void ScDataProviderDlg::deleteColumn()
945
0
{
946
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
947
0
    maControls.emplace_back(std::make_unique<ScDeleteColumnTransformationControl>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
948
0
}
949
950
void ScDataProviderDlg::splitColumn()
951
0
{
952
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
953
0
    maControls.emplace_back(std::make_unique<ScSplitColumnTransformationControl>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
954
0
}
955
956
void ScDataProviderDlg::mergeColumns()
957
0
{
958
0
    SCCOL nStartCol = -1;
959
0
    SCCOL nEndCol = -1;
960
0
    mxTable->getColRange(nStartCol, nEndCol);
961
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
962
0
    maControls.emplace_back(std::make_unique<ScMergeColumnTransformationControl>(mxDoc.get(), mxTransformationList.get(), nStartCol, nEndCol, mnIndex++, adeleteTransformation));
963
0
}
964
965
void ScDataProviderDlg::textTransformation()
966
0
{
967
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
968
0
    maControls.emplace_back(std::make_unique<ScColumnTextTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
969
0
}
970
971
void ScDataProviderDlg::sortTransformation()
972
0
{
973
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
974
0
    maControls.emplace_back(std::make_unique<ScSortTransformationControl>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
975
0
}
976
977
void ScDataProviderDlg::aggregateFunction()
978
0
{
979
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
980
0
    maControls.emplace_back(std::make_unique<ScAggregateFunction>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
981
0
}
982
983
void ScDataProviderDlg::numberTransformation()
984
0
{
985
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
986
0
    maControls.emplace_back(std::make_unique<ScNumberTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
987
0
}
988
989
void ScDataProviderDlg::replaceNullTransformation()
990
0
{
991
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
992
0
    maControls.emplace_back(std::make_unique<ScReplaceNullTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
993
0
}
994
995
void ScDataProviderDlg::dateTimeTransformation()
996
0
{
997
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
998
0
    maControls.emplace_back(std::make_unique<ScDateTimeTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
999
0
}
1000
1001
void ScDataProviderDlg::findReplaceTransformation()
1002
0
{
1003
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
1004
0
    maControls.emplace_back(std::make_unique<ScFindReplaceTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
1005
0
}
1006
1007
void ScDataProviderDlg::deleteRowTransformation()
1008
0
{
1009
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
1010
0
    maControls.emplace_back(std::make_unique<ScDeleteRowTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
1011
0
}
1012
1013
void ScDataProviderDlg::swapRowsTransformation()
1014
0
{
1015
0
    auto adeleteTransformation = [this](sal_uInt32 nIndex) {deletefromList(nIndex);};
1016
0
    maControls.emplace_back(std::make_unique<ScSwapRowsTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
1017
0
}
1018
1019
namespace {
1020
1021
bool lcl_hasDBName(const OUString& rName, ScDBCollection* pDBCollection)
1022
0
{
1023
0
    if (pDBCollection->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rName)))
1024
0
        return true;
1025
1026
0
    return false;
1027
0
}
1028
1029
}
1030
1031
// tdf#165502 Clear the contents of the temporary ScDocument in mxDoc and adds a sheet to
1032
// store the data to be previewed. This is needed if the newly imported content is smaller
1033
// than the previously shown content
1034
void ScDataProviderDlg::clearTablePreview()
1035
0
{
1036
0
    mxDoc->Clear();
1037
    // The name "test" below is just a dummy name for the tab that will hold the data
1038
0
    mxDoc->InsertTab(0, u"test"_ustr);
1039
0
}
1040
1041
void ScDataProviderDlg::import(ScDocument& rDoc, bool bInternal)
1042
0
{
1043
0
    OUString sDestDBUpperName = ScGlobal::getCharClass().uppercase(mxDBRanges->get_active_text());
1044
0
    ScDBData* pDestDBRange = mpDestDBCollection->getNamedDBs().findByUpperName(sDestDBUpperName);
1045
0
    if (!pDestDBRange)
1046
0
    {
1047
0
        if (bInternal)
1048
0
        {
1049
0
            std::unique_ptr<weld::MessageDialog> xMsgBox(
1050
0
                Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Error,
1051
0
                VclButtonsType::Close, ScResId(STR_DATAPROVIDER_NODATABASERANGE)));
1052
0
            xMsgBox->run();
1053
0
        }
1054
0
        return;
1055
0
    }
1056
1057
0
    if (bInternal)
1058
0
    {
1059
        // Use an additional database range in the temporary document to provide infos for transformations.
1060
        // Currently used for ersatz area in sorting and for HasHeader flag.
1061
0
        ScRange aDestRange;
1062
0
        pDestDBRange->GetArea(aDestRange);
1063
0
        SCCOL nHelperCol = aDestRange.aEnd.Col() - aDestRange.aStart.Col();
1064
0
        SCROW nHelperRow = aDestRange.aEnd.Row() - aDestRange.aStart.Row();
1065
0
        ScDBData* pDBHelper = new ScDBData(u"internalhelper"_ustr, 0, 0, 0, nHelperCol, nHelperRow);
1066
0
        pDBHelper->SetHeader(pDestDBRange->HasHeader());
1067
0
        ScDBCollection::NamedDBs& rLocalDBs = rDoc.GetDBCollection()->getNamedDBs();
1068
0
        auto iter = rLocalDBs.findByUpperName2(u"INTERNALHELPER"_ustr);
1069
0
        if (iter != rLocalDBs.end())
1070
0
            rLocalDBs.erase(iter);
1071
0
        bool bSuccess = rLocalDBs.insert(std::unique_ptr<ScDBData>(pDBHelper));
1072
0
        SAL_WARN_IF(!bSuccess, "sc", "Could not generate DBRange.");
1073
0
    }
1074
1075
0
    sc::ExternalDataSource aSource = getDataSource(&rDoc);
1076
1077
0
    for (size_t i = 0; i < maControls.size(); ++i)
1078
0
    {
1079
0
        ScDataTransformationBaseControl* pTransformationCtrl = maControls[i].get();
1080
0
        aSource.AddDataTransformation(pTransformationCtrl->getTransformation());
1081
0
    }
1082
0
    if (bInternal)
1083
0
        aSource.setDBData(pDBData->GetName());
1084
0
    else
1085
0
    {
1086
0
        aSource.setDBData(mxDBRanges->get_active_text());
1087
0
        if (!lcl_hasDBName(aSource.getDBName(), rDoc.GetDBCollection()))
1088
0
            return;
1089
0
        rDoc.GetExternalDataMapper().insertDataSource(aSource);
1090
0
    }
1091
1092
0
    try
1093
0
    {
1094
0
        aSource.refresh(&rDoc, true);
1095
0
    }
1096
0
    catch(const orcus::parse_error&)
1097
0
    {
1098
0
        std::unique_ptr<weld::MessageDialog> xMsgBox(Application::CreateMessageDialog(m_xDialog.get(),
1099
0
                                                  VclMessageType::Error, VclButtonsType::Close,
1100
0
                                                  ScResId(STD_ERR_CSV_PARSE)));
1101
0
        xMsgBox->run();
1102
0
    }
1103
1104
0
    mxTable->Invalidate();
1105
0
}
1106
1107
void ScDataProviderDlg::deletefromList(sal_uInt32 nIndex)
1108
0
{
1109
0
    auto itr = maControls.erase(maControls.begin() + nIndex);
1110
0
    while (itr != maControls.end())
1111
0
    {
1112
0
        (*itr)->updateIndex(nIndex++);
1113
0
        ++itr;
1114
0
    }
1115
0
    --mnIndex;
1116
0
}
1117
1118
IMPL_LINK_NOARG(ScDeleteColumnTransformationControl, DeleteHdl, weld::Button&, void)
1119
0
{
1120
0
   maDeleteTransformation(mnIndex);
1121
0
}
1122
1123
IMPL_LINK_NOARG(ScSplitColumnTransformationControl, DeleteHdl, weld::Button&, void)
1124
0
{
1125
0
   maDeleteTransformation(mnIndex);
1126
0
}
1127
1128
IMPL_LINK_NOARG(ScMergeColumnTransformationControl, DeleteHdl, weld::Button&, void)
1129
0
{
1130
0
   maDeleteTransformation(mnIndex);
1131
0
}
1132
1133
IMPL_LINK_NOARG(ScNumberTransformation, DeleteHdl, weld::Button&, void)
1134
0
{
1135
0
   maDeleteTransformation(mnIndex);
1136
0
}
1137
1138
IMPL_LINK_NOARG(ScAggregateFunction, DeleteHdl, weld::Button&, void)
1139
0
{
1140
0
   maDeleteTransformation(mnIndex);
1141
0
}
1142
1143
IMPL_LINK_NOARG(ScSortTransformationControl, DeleteHdl, weld::Button&, void)
1144
0
{
1145
0
   maDeleteTransformation(mnIndex);
1146
0
}
1147
1148
IMPL_LINK_NOARG(ScColumnTextTransformation, DeleteHdl, weld::Button&, void)
1149
0
{
1150
0
   maDeleteTransformation(mnIndex);
1151
0
}
1152
1153
IMPL_LINK_NOARG(ScReplaceNullTransformation, DeleteHdl, weld::Button&, void)
1154
0
{
1155
0
   maDeleteTransformation(mnIndex);
1156
0
}
1157
1158
IMPL_LINK_NOARG(ScDateTimeTransformation, DeleteHdl, weld::Button&, void)
1159
0
{
1160
0
   maDeleteTransformation(mnIndex);
1161
0
}
1162
1163
IMPL_LINK_NOARG(ScFindReplaceTransformation, DeleteHdl, weld::Button&, void)
1164
0
{
1165
0
   maDeleteTransformation(mnIndex);
1166
0
}
1167
1168
IMPL_LINK_NOARG(ScDeleteRowTransformation, DeleteHdl, weld::Button&, void)
1169
0
{
1170
0
    maDeleteTransformation(mnIndex);
1171
0
}
1172
1173
IMPL_LINK_NOARG(ScSwapRowsTransformation, DeleteHdl, weld::Button&, void)
1174
0
{
1175
0
   maDeleteTransformation(mnIndex);
1176
0
}
1177
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */