/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include class ScDataTransformationBaseControl { protected: std::unique_ptr mxBuilder; std::unique_ptr mxGrid; weld::Container* mpContainer; sal_uInt32 mnIndex; public: ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex); virtual ~ScDataTransformationBaseControl(); void updateIndex(sal_uInt32 nIndex) { mnIndex = nIndex; } virtual std::shared_ptr getTransformation() = 0; static SCROW getLastRow(const ScDocument& rDoc); static SCCOL getLastCol(const ScDocument& rDoc); }; SCROW ScDataTransformationBaseControl::getLastRow(const ScDocument& rDoc) { SCROW nEndRow = rDoc.MaxRow(); return rDoc.GetLastDataRow(0, 0, 0, nEndRow); } SCCOL ScDataTransformationBaseControl::getLastCol(const ScDocument& rDoc) { for (SCCOL nCol = 1; nCol <= rDoc.MaxCol(); ++nCol) { if (rDoc.GetCellType(nCol, 0, 0) == CELLTYPE_NONE) { return static_cast(nCol - 1 ); } } return rDoc.MaxCol(); } ScDataTransformationBaseControl::ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex) : mxBuilder(Application::CreateBuilder(pParent, rUIFile)) , mxGrid(mxBuilder->weld_container("grid")) , mpContainer(pParent) , mnIndex(nIndex) { } ScDataTransformationBaseControl::~ScDataTransformationBaseControl() { mpContainer->move(mxGrid.get(), nullptr); } namespace { struct MenuData { const char* aTransformationName; std::function maCallback; }; MenuData aTransformationData[] = { { "Delete Column", &ScDataProviderDlg::deleteColumn }, { "Delete Row", &ScDataProviderDlg::deleteRowTransformation}, { "Swap Rows", &ScDataProviderDlg::swapRowsTransformation}, { "Split Column", &ScDataProviderDlg::splitColumn }, { "Merge Columns", &ScDataProviderDlg::mergeColumns }, { "Text Transformation", &ScDataProviderDlg::textTransformation }, { "Sort Columns", &ScDataProviderDlg::sortTransformation }, { "Aggregate Functions", &ScDataProviderDlg::aggregateFunction}, { "Number Transformations", &ScDataProviderDlg::numberTransformation }, { "Replace Null Transformations", &ScDataProviderDlg::replaceNullTransformation }, { "Date & Time Transformations", &ScDataProviderDlg::dateTimeTransformation }, { "Find Replace Transformation", &ScDataProviderDlg::findReplaceTransformation} }; class ScDeleteColumnTransformationControl : public ScDataTransformationBaseControl { private: std::unique_ptr mxColumnNums; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScDeleteColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 aIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScDeleteColumnTransformationControl::ScDeleteColumnTransformationControl( const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/deletecolumnentry.ui", nIndex) , mxColumnNums(mxBuilder->weld_entry("ed_columns")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScDeleteColumnTransformationControl, DeleteHdl)); } std::shared_ptr ScDeleteColumnTransformationControl::getTransformation() { OUString aColumnString = mxColumnNums->get_text(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set ColNums; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one ColNums.insert(nCol - 1); } return std::make_shared(std::move(ColNums)); } class ScSplitColumnTransformationControl : public ScDataTransformationBaseControl { private: std::unique_ptr mxSeparator; std::unique_ptr mxNumColumns; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScSplitColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScSplitColumnTransformationControl::ScSplitColumnTransformationControl( const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/splitcolumnentry.ui", nIndex) , mxSeparator(mxBuilder->weld_entry("ed_separator")) , mxNumColumns(mxBuilder->weld_entry("num_cols")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScSplitColumnTransformationControl, DeleteHdl)); } std::shared_ptr ScSplitColumnTransformationControl::getTransformation() { OUString aSeparator = mxSeparator->get_text(); sal_Unicode cSeparator = aSeparator.isEmpty() ? ',' : aSeparator[0]; OUString aColStr = mxNumColumns->get_text(); SCCOL mnCol = -1; sal_Int32 nCol = aColStr.toInt32(); if (nCol > 0 && nCol <= mpDoc->MaxCol()) mnCol = nCol - 1; return std::make_shared(mnCol, cSeparator); } class ScMergeColumnTransformationControl : public ScDataTransformationBaseControl { private: std::unique_ptr mxSeparator; std::unique_ptr mxEdColumns; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScMergeColumnTransformationControl(const ScDocument *pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScMergeColumnTransformationControl::ScMergeColumnTransformationControl( const ScDocument* pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/mergecolumnentry.ui", nIndex) , mxSeparator(mxBuilder->weld_entry("ed_separator")) , mxEdColumns(mxBuilder->weld_entry("ed_columns")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScMergeColumnTransformationControl, DeleteHdl)); OUStringBuffer aBuffer; // map from zero based to one based column numbers aBuffer.append(static_cast(nStartCol + 1)); for ( SCCOL nCol = nStartCol + 1; nCol <= nEndCol; ++nCol) { aBuffer.append(";" + OUString::number(nCol + 1)); } mxEdColumns->set_text(aBuffer.makeStringAndClear()); } std::shared_ptr ScMergeColumnTransformationControl::getTransformation() { OUString aColumnString = mxEdColumns->get_text(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set aMergedColumns; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one aMergedColumns.insert(nCol - 1); } return std::make_shared(std::move(aMergedColumns), mxSeparator->get_text()); } class ScSortTransformationControl : public ScDataTransformationBaseControl { private: std::unique_ptr mxType; std::unique_ptr mxEdColumns; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScSortTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScSortTransformationControl::ScSortTransformationControl( const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/sorttransformationentry.ui", nIndex) , mxType(mxBuilder->weld_combo_box("ed_ascending")) , mxEdColumns(mxBuilder->weld_entry("ed_columns")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScSortTransformationControl, DeleteHdl)); } std::shared_ptr ScSortTransformationControl::getTransformation() { OUString aColStr = mxEdColumns->get_text(); bool aIsAscending = mxType->get_active(); SCCOL aColumn = 0; sal_Int32 nCol = aColStr.toInt32(); if (nCol > 0 && nCol <= mpDoc->MaxCol()) aColumn = nCol - 1; // translate from 1-based column notations to internal Calc one ScSortParam aSortParam; aSortParam.nRow1=0; aSortParam.nRow2=getLastRow(*mpDoc); aSortParam.nCol1=0; aSortParam.nCol2=getLastCol(*mpDoc); aSortParam.maKeyState[0].bDoSort = true; aSortParam.maKeyState[0].nField = aColumn; aSortParam.maKeyState[0].bAscending = aIsAscending; return std::make_shared(aSortParam); } class ScColumnTextTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxColumnNums; std::unique_ptr mxType; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScColumnTextTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScColumnTextTransformation::ScColumnTextTransformation( const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/texttransformationentry.ui", nIndex) , mxColumnNums(mxBuilder->weld_entry("ed_columns")) , mxType(mxBuilder->weld_combo_box("ed_lst")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScColumnTextTransformation, DeleteHdl)); } std::shared_ptr ScColumnTextTransformation::getTransformation() { OUString aColumnString = mxColumnNums->get_text(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set aColumns; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one aColumns.insert(nCol - 1); } sal_Int32 nPos = mxType->get_active(); switch (nPos) { case 0: return std::make_shared(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TO_LOWER); case 1: return std::make_shared(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TO_UPPER); case 2: return std::make_shared(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::CAPITALIZE); case 3: return std::make_shared(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TRIM); default: assert(false); } return nullptr; } class ScAggregateFunction : public ScDataTransformationBaseControl { private: std::unique_ptr mxColumnNums; std::unique_ptr mxType; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScAggregateFunction::ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/aggregatefunctionentry.ui", nIndex) , mxColumnNums(mxBuilder->weld_entry("ed_columns")) , mxType(mxBuilder->weld_combo_box("ed_lst")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScAggregateFunction, DeleteHdl)); } std::shared_ptr ScAggregateFunction::getTransformation() { OUString aColumnString = mxColumnNums->get_text(); sal_Int32 nPos = mxType->get_active(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set aColumns; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one aColumns.insert(nCol - 1); } switch (nPos) { case 0: return std::make_shared(std::move(aColumns),sc::AGGREGATE_FUNCTION::SUM); case 1: return std::make_shared(std::move(aColumns),sc::AGGREGATE_FUNCTION::AVERAGE); case 2: return std::make_shared(std::move(aColumns),sc::AGGREGATE_FUNCTION::MIN); case 3: return std::make_shared(std::move(aColumns),sc::AGGREGATE_FUNCTION::MAX); default: assert(false); } return nullptr; } class ScNumberTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxColumnNums; std::unique_ptr mxType; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScNumberTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScNumberTransformation::ScNumberTransformation( const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/numbertransformationentry.ui", nIndex) , mxColumnNums(mxBuilder->weld_entry("ed_columns")) , mxType(mxBuilder->weld_combo_box("ed_lst")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScNumberTransformation, DeleteHdl)); } std::shared_ptr ScNumberTransformation::getTransformation() { OUString aColumnString = mxColumnNums->get_text(); sal_Int32 nPos = mxType->get_active(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set aColumns; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one aColumns.insert(nCol - 1); } switch (nPos) { case 0: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SIGN); case 1: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND); case 2: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND_UP); case 3: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN); case 4: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE); case 5: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::LOG_E); case 6: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::LOG_10); case 7: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::CUBE); case 8: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SQUARE); case 9: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT); case 10: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::EXPONENT); case 11: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::IS_EVEN); case 12: return std::make_shared(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::IS_ODD); default: assert(false); } return nullptr; } class ScReplaceNullTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxColumnNums; std::unique_ptr mxReplaceString; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument *mpDoc; public: ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScReplaceNullTransformation::ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent,"modules/scalc/ui/replacenulltransformationentry.ui", nIndex) , mxColumnNums(mxBuilder->weld_entry("ed_columns")) , mxReplaceString(mxBuilder->weld_entry("ed_str")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScReplaceNullTransformation, DeleteHdl)); } std::shared_ptr ScReplaceNullTransformation::getTransformation() { OUString aColumnString = mxColumnNums->get_text(); OUString aReplaceWithString = mxReplaceString->get_text(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set aColumns; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one aColumns.insert(nCol - 1); } return std::make_shared(std::move(aColumns),aReplaceWithString); } class ScDateTimeTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxColumnNums; std::unique_ptr mxType; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScDateTimeTransformation::ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent,"modules/scalc/ui/datetimetransformationentry.ui", nIndex) , mxColumnNums(mxBuilder->weld_entry("ed_columns")) , mxType(mxBuilder->weld_combo_box("ed_lst")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this,ScDateTimeTransformation, DeleteHdl)); } std::shared_ptr ScDateTimeTransformation::getTransformation() { OUString aColumnString = mxColumnNums->get_text(); sal_Int32 nPos = mxType->get_active(); std::vector aSplitColumns = comphelper::string::split(aColumnString, ';'); std::set aColumns; for (const auto& rColStr : aSplitColumns) { sal_Int32 nCol = rColStr.toInt32(); if (nCol <= 0) continue; if (nCol > mpDoc->MaxCol()) continue; // translate from 1-based column notations to internal Calc one aColumns.insert(nCol - 1); } switch (nPos) { case 0: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING); case 1: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::YEAR); case 2: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR); case 3: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR); case 4: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MONTH); case 5: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME); case 6: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH); case 7: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH); case 8: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY); case 9: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK); case 10: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR); case 11: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::QUARTER); case 12: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER); case 13: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER); case 14: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::HOUR); case 15: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MINUTE); case 16: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::SECOND); case 17: return std::make_shared(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::TIME); default: assert(false); } return nullptr; } class ScFindReplaceTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxFindString; std::unique_ptr mxReplaceString; std::unique_ptr mxEdColumns; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScFindReplaceTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScFindReplaceTransformation::ScFindReplaceTransformation( const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/findreplaceentry.ui", nIndex) , mxFindString(mxBuilder->weld_entry("ed_find")) , mxReplaceString(mxBuilder->weld_entry("ed_replace")) , mxEdColumns(mxBuilder->weld_entry("ed_columns")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this, ScFindReplaceTransformation, DeleteHdl)); } std::shared_ptr ScFindReplaceTransformation::getTransformation() { OUString aColStr = mxEdColumns->get_text(); SCCOL aColumn = -1; sal_Int32 nCol = aColStr.toInt32(); if (nCol > 0 && nCol <= mpDoc->MaxCol()) aColumn = nCol - 1; return std::make_shared(aColumn, mxFindString->get_text(), mxReplaceString->get_text()); } class ScDeleteRowTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxFindString; std::unique_ptr mxEdColumns; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScDeleteRowTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScDeleteRowTransformation::ScDeleteRowTransformation( const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/deleterowentry.ui", nIndex) , mxFindString(mxBuilder->weld_entry("ed_find")) , mxEdColumns(mxBuilder->weld_entry("ed_columns")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this, ScDeleteRowTransformation, DeleteHdl)); } std::shared_ptr ScDeleteRowTransformation::getTransformation() { OUString aColStr = mxEdColumns->get_text(); SCCOL aColumn = -1; sal_Int32 nCol = aColStr.toInt32(); if (nCol > 0 && nCol <= mpDoc->MaxCol()) aColumn = nCol - 1; return std::make_shared(aColumn, mxFindString->get_text()); } class ScSwapRowsTransformation : public ScDataTransformationBaseControl { private: std::unique_ptr mxRow; std::unique_ptr nxRow; std::unique_ptr mxDelete; std::function maDeleteTransformation; const ScDocument* mpDoc; public: ScSwapRowsTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScSwapRowsTransformation::ScSwapRowsTransformation( const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/swaprowsentry.ui", nIndex) , mxRow(mxBuilder->weld_entry("ed_row1")) , nxRow(mxBuilder->weld_entry("ed_row2")) , mxDelete(mxBuilder->weld_button("ed_delete")) , maDeleteTransformation(std::move(aDeleteTransformation)) , mpDoc(pDoc) { mxDelete->connect_clicked(LINK(this, ScSwapRowsTransformation, DeleteHdl)); } std::shared_ptr ScSwapRowsTransformation::getTransformation() { OUString aRowStr = mxRow->get_text(); OUString bRowStr = nxRow->get_text(); SCROW aRow = -1; SCROW bRow = -1; sal_Int32 mRow = aRowStr.toInt32(); sal_Int32 nRow = bRowStr.toInt32(); if (mRow > 0 && mRow <= mpDoc->MaxRow()) aRow = mRow - 1; if (nRow > 0 && nRow <= mpDoc->MaxRow()) bRow = nRow - 1; return std::make_shared(aRow, bRow); } } ScDataProviderDlg::ScDataProviderDlg(weld::Window* pParent, std::shared_ptr pDoc, const ScDocument* pDocument) : GenericDialogController(pParent, "modules/scalc/ui/dataproviderdlg.ui", "dataproviderdlg") , mxDoc(std::move(pDoc)) , mxBox(m_xBuilder->weld_container("data_table")) , m_xTableParent(mxBox->CreateChildFrame()) , mxTable(VclPtr::Create(m_xTableParent, mxDoc)) , mxDBRanges(m_xBuilder->weld_combo_box("select_db_range")) , mxOKBtn(m_xBuilder->weld_button("okay")) , mxCancelBtn(m_xBuilder->weld_button("cancel")) , mxAddTransformationBtn(m_xBuilder->weld_button("add_transformation")) , mxScroll(m_xBuilder->weld_scrolled_window("scroll")) , mxTransformationList(m_xBuilder->weld_container("transformation_ctrl")) , mxTransformationBox(m_xBuilder->weld_combo_box("transformation_box")) , mxProviderList(m_xBuilder->weld_combo_box("provider_lst")) , mxEditURL(m_xBuilder->weld_entry("ed_url")) , mxEditID(m_xBuilder->weld_entry("ed_id")) , mxApplyBtn(m_xBuilder->weld_button("apply")) , mxBrowseBtn(m_xBuilder->weld_button("browse")) , maIdle("ScDataProviderDlg maIdle") , mnIndex(0) { Size aPrefSize = mxTable->GetOptimalSize(); mxBox->set_size_request(aPrefSize.Width(), aPrefSize.Height()); mxTable->Show(); ScDBCollection* pDBCollection = pDocument->GetDBCollection(); auto& rNamedDBs = pDBCollection->getNamedDBs(); for (auto& rNamedDB : rNamedDBs) { mxDBRanges->append_text(rNamedDB->GetName()); } for (const auto& i : aTransformationData) { mxTransformationBox->append_text(OUString::createFromAscii(i.aTransformationName)); } pDBData = new ScDBData("data", 0, 0, 0, mxDoc->MaxCol(), mxDoc->MaxRow()); bool bSuccess = mxDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr(pDBData)); SAL_WARN_IF(!bSuccess, "sc", "temporary warning"); auto aDataProvider = sc::DataProviderFactory::getDataProviders(); for (const auto& rDataProvider : aDataProvider) { mxProviderList->append_text(rDataProvider); } mxOKBtn->connect_clicked(LINK(this, ScDataProviderDlg, ApplyQuitHdl)); mxCancelBtn->connect_clicked(LINK(this, ScDataProviderDlg, CancelQuitHdl)); mxAddTransformationBtn->connect_clicked(LINK(this, ScDataProviderDlg, TransformationListHdl)); mxApplyBtn->connect_clicked(LINK(this, ScDataProviderDlg, ApplyBtnHdl)); mxBrowseBtn->connect_clicked(LINK(this, ScDataProviderDlg, BrowseBtnHdl)); mxTransformationBox->connect_changed(LINK(this, ScDataProviderDlg, TransformationSelectHdl)); mxProviderList->connect_changed(LINK(this, ScDataProviderDlg, ProviderSelectHdl)); mxEditID->connect_changed(LINK(this, ScDataProviderDlg, IDEditHdl)); mxEditURL->connect_changed(LINK(this, ScDataProviderDlg, URLEditHdl)); msApplyTooltip = mxApplyBtn->get_tooltip_text(); msAddTransformationToolTip = mxAddTransformationBtn->get_tooltip_text(); mxAddTransformationBtn->set_sensitive(false); mxAddTransformationBtn->set_tooltip_text(OUString()); isValid(); maIdle.SetPriority( TaskPriority::LOWEST ); maIdle.SetInvokeHandler( LINK( this, ScDataProviderDlg, ScrollToEnd) ); } ScDataProviderDlg::~ScDataProviderDlg() { mxTable.disposeAndClear(); m_xTableParent->dispose(); m_xTableParent.clear(); } IMPL_LINK_NOARG(ScDataProviderDlg, ScrollToEnd, Timer*, void) { mxScroll->vadjustment_set_value(mxScroll->vadjustment_get_upper()); } IMPL_LINK_NOARG(ScDataProviderDlg, ApplyQuitHdl, weld::Button&, void) { m_xDialog->response(RET_OK); } IMPL_LINK_NOARG(ScDataProviderDlg, CancelQuitHdl, weld::Button&, void) { m_xDialog->response(RET_CANCEL); } IMPL_LINK_NOARG(ScDataProviderDlg, TransformationListHdl, weld::Button&, void) { OUString transformation_string = mxTransformationBox->get_active_text(); for (auto& i: aTransformationData) { if (transformation_string == OUString::createFromAscii(i.aTransformationName)) { i.maCallback(this); maIdle.Start(); return; } } } IMPL_LINK_NOARG(ScDataProviderDlg, ProviderSelectHdl, weld::ComboBox&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderDlg, IDEditHdl, weld::Entry&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderDlg, URLEditHdl, weld::Entry&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderDlg, ApplyBtnHdl, weld::Button&, void) { updateApplyBtn(true); import(*mxDoc, true); } IMPL_LINK_NOARG(ScDataProviderDlg, BrowseBtnHdl, weld::Button&, void) { sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, m_xDialog.get()); aFileDialog.SetContext(sfx2::FileDialogHelper::CalcDataProvider); if (aFileDialog.Execute() != ERRCODE_NONE) return; mxEditURL->set_text(aFileDialog.GetPath()); isValid(); } IMPL_LINK_NOARG(ScDataProviderDlg, TransformationSelectHdl, weld::ComboBox&, void) { mxAddTransformationBtn->set_sensitive(true); mxAddTransformationBtn->set_tooltip_text(msAddTransformationToolTip); } sc::ExternalDataSource ScDataProviderDlg::getDataSource(ScDocument* pDoc) { sc::ExternalDataSource aSource(mxEditURL->get_text(), mxProviderList->get_active_text(), pDoc); OUString aID = mxEditID->get_text(); aSource.setID(aID); return aSource; } void ScDataProviderDlg::isValid() { bool bValid = !mxProviderList->get_active_text().isEmpty(); bValid &= !mxEditURL->get_text().isEmpty(); updateApplyBtn(bValid); } void ScDataProviderDlg::updateApplyBtn(bool bValidConfig) { if (!bValidConfig) { mxApplyBtn->set_sensitive(false); mxApplyBtn->set_tooltip_text(OUString()); return; } mxApplyBtn->set_sensitive(true); mxApplyBtn->set_tooltip_text(msApplyTooltip); } void ScDataProviderDlg::deleteColumn() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::splitColumn() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::mergeColumns() { SCCOL nStartCol = -1; SCCOL nEndCol = -1; mxTable->getColRange(nStartCol, nEndCol); std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), nStartCol, nEndCol, mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::textTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::sortTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::aggregateFunction() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::numberTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::replaceNullTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::dateTimeTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::findReplaceTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList, this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::deleteRowTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList, this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::swapRowsTransformation() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList, this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation)); } namespace { bool hasDBName(const OUString& rName, ScDBCollection* pDBCollection) { if (pDBCollection->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rName))) return true; return false; } } void ScDataProviderDlg::import(ScDocument& rDoc, bool bInternal) { sc::ExternalDataSource aSource = getDataSource(&rDoc); for (size_t i = 0; i < maControls.size(); ++i) { ScDataTransformationBaseControl* pTransformationCtrl = maControls[i].get(); aSource.AddDataTransformation(pTransformationCtrl->getTransformation()); } if (bInternal) aSource.setDBData(pDBData->GetName()); else { aSource.setDBData(mxDBRanges->get_active_text()); if (!hasDBName(aSource.getDBName(), rDoc.GetDBCollection())) return; rDoc.GetExternalDataMapper().insertDataSource(aSource); } aSource.refresh(&rDoc, true); mxTable->Invalidate(); } void ScDataProviderDlg::deletefromList(sal_uInt32 nIndex) { auto itr = maControls.erase(maControls.begin() + nIndex); while (itr != maControls.end()) { (*itr)->updateIndex(nIndex++); ++itr; } --mnIndex; } IMPL_LINK_NOARG(ScDeleteColumnTransformationControl, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScSplitColumnTransformationControl, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScMergeColumnTransformationControl, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScNumberTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScAggregateFunction, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScSortTransformationControl, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScColumnTextTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScReplaceNullTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScDateTimeTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScFindReplaceTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScDeleteRowTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } IMPL_LINK_NOARG(ScSwapRowsTransformation, DeleteHdl, weld::Button&, void) { maDeleteTransformation(mnIndex); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */