Coverage Report

Created: 2025-12-31 10:39

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