/* -*- 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 class ScDataProviderBaseControl { std::unique_ptr mxBuilder; std::unique_ptr mxGrid; std::unique_ptr mxProviderList; std::unique_ptr mxEditURL; std::unique_ptr mxEditID; std::unique_ptr mxApplyBtn; OUString msApplyTooltip; Link const maImportCallback; DECL_LINK(ProviderSelectHdl, weld::ComboBox&, void); DECL_LINK(IDEditHdl, weld::Entry&, void); DECL_LINK(URLEditHdl, weld::Entry&, void); DECL_LINK(ApplyBtnHdl, weld::Button&, void); void updateApplyBtn(bool bValidConfig); public: ScDataProviderBaseControl(weld::Container* pParent, const Link& rImportCallback); void isValid(); sc::ExternalDataSource getDataSource(ScDocument* pDoc); }; ScDataProviderBaseControl::ScDataProviderBaseControl(weld::Container* pParent, const Link& rImportCallback) : mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/dataproviderentry.ui")) , mxGrid(mxBuilder->weld_container("grid")) , mxProviderList(mxBuilder->weld_combo_box("provider_lst")) , mxEditURL(mxBuilder->weld_entry("ed_url")) , mxEditID(mxBuilder->weld_entry("ed_id")) , mxApplyBtn(mxBuilder->weld_button("apply")) , maImportCallback(rImportCallback) { auto aDataProvider = sc::DataProviderFactory::getDataProviders(); for (const auto& rDataProvider : aDataProvider) { mxProviderList->append_text(rDataProvider); } mxProviderList->connect_changed(LINK(this, ScDataProviderBaseControl, ProviderSelectHdl)); mxEditID->connect_changed(LINK(this, ScDataProviderBaseControl, IDEditHdl)); mxEditURL->connect_changed(LINK(this, ScDataProviderBaseControl, URLEditHdl)); msApplyTooltip = mxApplyBtn->get_tooltip_text(); mxApplyBtn->connect_clicked(LINK(this, ScDataProviderBaseControl, ApplyBtnHdl)); isValid(); } void ScDataProviderBaseControl::isValid() { bool bValid = !mxProviderList->get_active_text().isEmpty(); bValid &= !mxEditURL->get_text().isEmpty(); updateApplyBtn(bValid); } sc::ExternalDataSource ScDataProviderBaseControl::getDataSource(ScDocument* pDoc) { OUString aURL = mxEditURL->get_text(); OUString aProvider = mxProviderList->get_active_text(); sc::ExternalDataSource aSource(aURL, aProvider, pDoc); OUString aID = mxEditID->get_text(); aSource.setID(aID); return aSource; } void ScDataProviderBaseControl::updateApplyBtn(bool bValidConfig) { if (!bValidConfig) { mxApplyBtn->set_sensitive(false); mxApplyBtn->set_tooltip_text(OUString()); return; } mxApplyBtn->set_sensitive(true); mxApplyBtn->set_tooltip_text(msApplyTooltip); } IMPL_LINK_NOARG(ScDataProviderBaseControl, ProviderSelectHdl, weld::ComboBox&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderBaseControl, IDEditHdl, weld::Entry&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderBaseControl, URLEditHdl, weld::Entry&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderBaseControl, ApplyBtnHdl, weld::Button&, void) { updateApplyBtn(true); maImportCallback.Call(this); } 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; }; 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 { int const nMenuID; const char* aMenuName; std::function const maCallback; }; MenuData aStartData[] = { { 0, "Apply & Quit", &ScDataProviderDlg::applyAndQuit }, { 1, "Cancel & Quit", &ScDataProviderDlg::cancelAndQuit } }; MenuData aColumnData[] = { { 0, "Delete Column", &ScDataProviderDlg::deleteColumn }, { 1, "Split Column", &ScDataProviderDlg::splitColumn }, { 2, "Merge Columns", &ScDataProviderDlg::mergeColumns }, { 3, "Text Transformation", &ScDataProviderDlg::textTransformation }, { 4, "Sort Columns", &ScDataProviderDlg::sortTransformation }, { 5, "Aggregate Functions", &ScDataProviderDlg::aggregateFunction}, { 6, "Number Transformations", &ScDataProviderDlg::numberTransformation }, { 7, "Replace Null Transformations", &ScDataProviderDlg::replaceNullTransformation }, { 8, "Date & Time Transformations", &ScDataProviderDlg::dateTimeTransformation } }; 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(ColNums); } class ScSplitColumnTransformationControl : public ScDataTransformationBaseControl { private: std::unique_ptr mxSeparator; std::unique_ptr mxNumColumns; std::unique_ptr mxDelete; SCCOL mnCol; std::function maDeleteTransformation; public: ScSplitColumnTransformationControl(weld::Container* pParent, SCCOL nCol, sal_uInt32 nIndex, std::function aDeleteTransformation); virtual std::shared_ptr getTransformation() override; DECL_LINK(DeleteHdl, weld::Button&, void); }; ScSplitColumnTransformationControl::ScSplitColumnTransformationControl( weld::Container* pParent, SCCOL nCol, sal_uInt32 nIndex, std::function aDeleteTransformation) : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/splitcolumnentry.ui", nIndex) , mxSeparator(mxBuilder->weld_entry("ed_separator")) , mxNumColumns(mxBuilder->weld_spin_button("num_cols")) , mxDelete(mxBuilder->weld_button("ed_delete")) , mnCol(nCol) , maDeleteTransformation(std::move(aDeleteTransformation)) { mxDelete->connect_clicked(LINK(this,ScSplitColumnTransformationControl, DeleteHdl)); } std::shared_ptr ScSplitColumnTransformationControl::getTransformation() { OUString aSeparator = mxSeparator->get_text(); sal_Unicode cSeparator = aSeparator.isEmpty() ? ',' : aSeparator[0]; 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(OUString::number(nStartCol + 1)); for ( SCCOL nCol = nStartCol + 1; nCol <= nEndCol; ++nCol) { aBuffer.append(";").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(aMergedColumns, mxSeparator->get_text()); } class ScSortTransformationControl : public ScDataTransformationBaseControl { private: std::unique_ptr mxAscending; 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) , mxAscending(mxBuilder->weld_check_button("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 = mxAscending->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; ScSortKeyState aSortKey; aSortKey.bDoSort = true; aSortKey.nField = aColumn; aSortKey.bAscending = aIsAscending; aSortParam.maKeyState.push_back(aSortKey); 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(aColumns,sc::TEXT_TRANSFORM_TYPE::TO_LOWER); case 1: return std::make_shared(aColumns,sc::TEXT_TRANSFORM_TYPE::TO_UPPER); case 2: return std::make_shared(aColumns,sc::TEXT_TRANSFORM_TYPE::CAPITALIZE); case 3: return std::make_shared(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(aColumns,sc::AGGREGATE_FUNCTION::SUM); case 1: return std::make_shared(aColumns,sc::AGGREGATE_FUNCTION::AVERAGE); case 2: return std::make_shared(aColumns,sc::AGGREGATE_FUNCTION::MIN); case 3: return std::make_shared(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(aColumns,sc::NUMBER_TRANSFORM_TYPE::SIGN); case 1: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::ROUND); case 2: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::ROUND_UP); case 3: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN); case 4: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE); case 5: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::LOG_E); case 6: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::LOG_10); case 7: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::CUBE); case 8: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::SQUARE); case 9: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT); case 10: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::EXPONENT); case 11: return std::make_shared(aColumns,sc::NUMBER_TRANSFORM_TYPE::IS_EVEN); case 12: return std::make_shared(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(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(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(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(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING); case 1: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::YEAR); case 2: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR); case 3: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR); case 4: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::MONTH); case 5: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME); case 6: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH); case 7: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH); case 8: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DAY); case 9: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK); case 10: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR); case 11: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::QUARTER); case 12: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER); case 13: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER); case 14: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::HOUR); case 15: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::MINUTE); case 16: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::SECOND); case 17: return std::make_shared(aColumns,sc::DATETIME_TRANSFORMATION_TYPE::TIME); default: assert(false); } return nullptr; } } ScDataProviderDlg::ScDataProviderDlg(weld::Window* pParent, std::shared_ptr pDoc, const ScDocument* pDocument) : GenericDialogController(pParent, "modules/scalc/ui/dataproviderdlg.ui", "dataproviderdlg") , mxDoc(std::move(pDoc)) , mxStartMenu(m_xBuilder->weld_menu("start")) , mxColumnMenu(m_xBuilder->weld_menu("column")) , mxBox(m_xBuilder->weld_container("data_table")) , m_xTableParent(mxBox->CreateChildFrame()) , mxTable(VclPtr::Create(m_xTableParent)) , mxScroll(m_xBuilder->weld_scrolled_window("scroll")) , mxList(m_xBuilder->weld_container("operation_ctrl")) , mxDataProviderCtrl(new ScDataProviderBaseControl(mxList.get(), LINK(this, ScDataProviderDlg, ImportHdl))) , mxDBRanges(m_xBuilder->weld_combo_box("select_db_range")) , mnIndex(0) { Size aPrefSize = mxTable->GetOptimalSize(); mxBox->set_size_request(aPrefSize.Width(), aPrefSize.Height()); mxTable->Show(); mxTable->Init(mxDoc); ScDBCollection* pDBCollection = pDocument->GetDBCollection(); auto& rNamedDBs = pDBCollection->getNamedDBs(); for (auto& rNamedDB : rNamedDBs) { mxDBRanges->append_text(rNamedDB->GetName()); } 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"); InitMenu(); maIdle.SetPriority( TaskPriority::LOWEST ); maIdle.SetInvokeHandler( LINK( this, ScDataProviderDlg, ScrollToEnd) ); } ScDataProviderDlg::~ScDataProviderDlg() { mxTable.disposeAndClear(); m_xTableParent->dispose(); m_xTableParent.clear(); } void ScDataProviderDlg::InitMenu() { for (const auto& itrStartData : aStartData) mxStartMenu->append(OUString::number(itrStartData.nMenuID), OUString::createFromAscii(itrStartData.aMenuName)); mxStartMenu->connect_activate(LINK(this, ScDataProviderDlg, StartMenuHdl)); for (const auto& itrColumnData : aColumnData) mxColumnMenu->append(OUString::number(itrColumnData.nMenuID), OUString::createFromAscii(itrColumnData.aMenuName)); mxColumnMenu->connect_activate(LINK(this, ScDataProviderDlg, ColumnMenuHdl)); } IMPL_LINK(ScDataProviderDlg, StartMenuHdl, const OString&, rIdent, void) { auto nId = rIdent.toInt32(); for (auto& i: aStartData) { if (i.nMenuID == nId) { i.maCallback(this); return; } } } IMPL_LINK_NOARG(ScDataProviderDlg, ScrollToEnd, Timer*, void) { mxScroll->vadjustment_set_value(mxScroll->vadjustment_get_upper()); } IMPL_LINK(ScDataProviderDlg, ColumnMenuHdl, const OString&, rIdent, void) { auto nId = rIdent.toInt32(); for (auto& i: aColumnData) { if (i.nMenuID == nId) { i.maCallback(this); // scroll to bottom when something added to the list maIdle.Start(); return; } } } IMPL_LINK(ScDataProviderDlg, ImportHdl, ScDataProviderBaseControl*, pCtrl, void) { if (pCtrl == mxDataProviderCtrl.get()) { import(mxDoc.get(), true); } } void ScDataProviderDlg::applyAndQuit() { m_xDialog->response(RET_OK); } void ScDataProviderDlg::cancelAndQuit() { m_xDialog->response(RET_CANCEL); } void ScDataProviderDlg::deleteColumn() { std::function adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1); maControls.emplace_back(std::make_unique(mxDoc.get(), mxList.get(), mnIndex++, adeleteTransformation)); } void ScDataProviderDlg::splitColumn() { 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(mxList.get(), nStartCol, 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(), mxList.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(), mxList.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(), mxList.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(), mxList.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(), mxList.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(), mxList.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(), mxList.get(), mnIndex++, adeleteTransformation)); } namespace { bool hasDBName(const OUString& rName, ScDBCollection* pDBCollection) { if (pDBCollection->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rName))) return true; return false; } } void ScDataProviderDlg::import(ScDocument* pDoc, bool bInternal) { sc::ExternalDataSource aSource = mxDataProviderCtrl->getDataSource(pDoc); 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(), pDoc->GetDBCollection())) return; pDoc->GetExternalDataMapper().insertDataSource(aSource); } aSource.refresh(pDoc, 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); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */