/* -*- 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/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #undef SC_DLLIMPLEMENTATION #include #include #include #include #include #include #include #include #include #include #include #include #include #include ScLinkedAreaDlg::ScLinkedAreaDlg(weld::Widget* pParent) : GenericDialogController(pParent, "modules/scalc/ui/externaldata.ui", "ExternalDataDialog") , m_pSourceShell(nullptr) , m_xCbUrl(new SvtURLBox(m_xBuilder->weld_combo_box("url"))) , m_xBtnBrowse(m_xBuilder->weld_button("browse")) , m_xLbRanges(m_xBuilder->weld_tree_view("ranges")) , m_xBtnReload(m_xBuilder->weld_check_button("reload")) , m_xNfDelay(m_xBuilder->weld_spin_button("delay")) , m_xFtSeconds(m_xBuilder->weld_label("secondsft")) , m_xBtnOk(m_xBuilder->weld_button("ok")) { m_xLbRanges->set_selection_mode(SelectionMode::Multiple); m_xCbUrl->connect_entry_activate(LINK(this, ScLinkedAreaDlg, FileHdl)); m_xBtnBrowse->connect_clicked(LINK( this, ScLinkedAreaDlg, BrowseHdl)); m_xLbRanges->connect_changed(LINK( this, ScLinkedAreaDlg, RangeHdl)); m_xLbRanges->set_size_request(m_xLbRanges->get_approximate_digit_width() * 54, m_xLbRanges->get_height_rows(5)); m_xBtnReload->connect_toggled(LINK( this, ScLinkedAreaDlg, ReloadHdl)); UpdateEnable(); } ScLinkedAreaDlg::~ScLinkedAreaDlg() { } constexpr OUStringLiteral FILTERNAME_HTML = u"HTML (StarCalc)"; constexpr OUStringLiteral FILTERNAME_QUERY = u"calc_HTML_WebQuery"; IMPL_LINK_NOARG(ScLinkedAreaDlg, BrowseHdl, weld::Button&, void) { m_xDocInserter.reset( new sfx2::DocumentInserter(m_xDialog.get(), ScDocShell::Factory().GetFactoryName()) ); m_xDocInserter->StartExecuteModal( LINK( this, ScLinkedAreaDlg, DialogClosedHdl ) ); } IMPL_LINK_NOARG(ScLinkedAreaDlg, FileHdl, weld::ComboBox&, bool) { OUString aEntered = m_xCbUrl->GetURL(); if (m_pSourceShell) { SfxMedium* pMed = m_pSourceShell->GetMedium(); if ( aEntered == pMed->GetName() ) { // already loaded - nothing to do return true; } } OUString aFilter; OUString aOptions; // get filter name by looking at the file content (bWithContent = true) // Break operation if any error occurred inside. if (!ScDocumentLoader::GetFilterName( aEntered, aFilter, aOptions, true, false )) return true; // #i53241# replace HTML filter with DataQuery filter if (aFilter == FILTERNAME_HTML) aFilter = FILTERNAME_QUERY; LoadDocument( aEntered, aFilter, aOptions ); UpdateSourceRanges(); UpdateEnable(); return true; } void ScLinkedAreaDlg::LoadDocument( const OUString& rFile, const OUString& rFilter, const OUString& rOptions ) { if (m_pSourceShell) { // unload old document m_pSourceShell->DoClose(); m_pSourceShell = nullptr; aSourceRef.clear(); } if ( rFile.isEmpty() ) return; weld::WaitObject aWait(m_xDialog.get()); OUString aNewFilter = rFilter; OUString aNewOptions = rOptions; SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, rFile ); ScDocumentLoader aLoader( rFile, aNewFilter, aNewOptions, 0, m_xDialog.get() ); // with interaction m_pSourceShell = aLoader.GetDocShell(); if (m_pSourceShell) { ErrCode nErr = m_pSourceShell->GetErrorCode(); if (nErr) ErrorHandler::HandleError( nErr ); // including warnings aSourceRef = m_pSourceShell; aLoader.ReleaseDocRef(); // don't call DoClose in DocLoader dtor } } void ScLinkedAreaDlg::InitFromOldLink( const OUString& rFile, const OUString& rFilter, const OUString& rOptions, std::u16string_view rSource, sal_Int32 nRefreshDelaySeconds ) { LoadDocument( rFile, rFilter, rOptions ); if (m_pSourceShell) { SfxMedium* pMed = m_pSourceShell->GetMedium(); m_xCbUrl->set_entry_text(pMed->GetName()); } else m_xCbUrl->set_entry_text(OUString()); UpdateSourceRanges(); if (!rSource.empty()) { sal_Int32 nIdx {0}; do { m_xLbRanges->select_text(OUString(o3tl::getToken(rSource, 0, ';', nIdx))); } while (nIdx>0); } bool bDoRefresh = (nRefreshDelaySeconds != 0); m_xBtnReload->set_active(bDoRefresh); if (bDoRefresh) m_xNfDelay->set_value(nRefreshDelaySeconds); UpdateEnable(); } IMPL_LINK_NOARG(ScLinkedAreaDlg, RangeHdl, weld::TreeView&, void) { UpdateEnable(); } IMPL_LINK_NOARG(ScLinkedAreaDlg, ReloadHdl, weld::Toggleable&, void) { UpdateEnable(); } IMPL_LINK( ScLinkedAreaDlg, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void ) { if ( _pFileDlg->GetError() != ERRCODE_NONE ) return; std::unique_ptr pMed = m_xDocInserter->CreateMedium(); if ( pMed ) { weld::WaitObject aWait(m_xDialog.get()); // replace HTML filter with DataQuery filter std::shared_ptr pFilter = pMed->GetFilter(); if (pFilter && FILTERNAME_HTML == pFilter->GetFilterName()) { std::shared_ptr pNewFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( FILTERNAME_QUERY ); if( pNewFilter ) pMed->SetFilter( pNewFilter ); } // ERRCTX_SFX_OPENDOC -> "Error loading document" SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() ); if (m_pSourceShell) m_pSourceShell->DoClose(); // deleted when assigning aSourceRef pMed->UseInteractionHandler( true ); // to enable the filter options dialog m_pSourceShell = new ScDocShell; aSourceRef = m_pSourceShell; m_pSourceShell->DoLoad( pMed.get() ); ErrCode nErr = m_pSourceShell->GetErrorCode(); if (nErr) ErrorHandler::HandleError( nErr ); // including warnings if (!m_pSourceShell->GetError()) // only errors { m_xCbUrl->set_entry_text(pMed->GetName()); } else { m_pSourceShell->DoClose(); m_pSourceShell = nullptr; aSourceRef.clear(); m_xCbUrl->set_entry_text(OUString()); } pMed.release(); // DoLoad takes ownership } UpdateSourceRanges(); UpdateEnable(); } #undef FILTERNAME_HTML #undef FILTERNAME_QUERY void ScLinkedAreaDlg::UpdateSourceRanges() { m_xLbRanges->freeze(); m_xLbRanges->clear(); if ( m_pSourceShell ) { std::shared_ptr pFilter = m_pSourceShell->GetMedium()->GetFilter(); if (pFilter && pFilter->GetFilterName() == SC_TEXT_CSV_FILTER_NAME) { // Insert dummy All range to have something selectable. m_xLbRanges->append_text("CSV_all"); } // tdf#142600 - list tables in order of their appearance in the document's source const ScRangeName* pRangeName = m_pSourceShell->GetDocument().GetRangeName(); for (size_t i = 1; i <= pRangeName->index_size(); i++) { if (const ScRangeData* pRangeData = pRangeName->findByIndex(i)) { m_xLbRanges->append_text(pRangeData->GetName()); } } } m_xLbRanges->thaw(); if (m_xLbRanges->n_children() >= 1) m_xLbRanges->select(0); else { m_xLbRanges->append_text(ScResId(STR_NO_NAMED_RANGES_AVAILABLE)); m_xLbRanges->set_sensitive(false); } } void ScLinkedAreaDlg::UpdateEnable() { bool bEnable = ( m_pSourceShell && m_xLbRanges->count_selected_rows() ); m_xBtnOk->set_sensitive(bEnable); bool bReload = m_xBtnReload->get_active(); m_xNfDelay->set_sensitive(bReload); m_xFtSeconds->set_sensitive(bReload); } OUString ScLinkedAreaDlg::GetURL() const { if (m_pSourceShell) { SfxMedium* pMed = m_pSourceShell->GetMedium(); return pMed->GetName(); } return OUString(); } OUString ScLinkedAreaDlg::GetFilter() const { if (m_pSourceShell) { SfxMedium* pMed = m_pSourceShell->GetMedium(); return pMed->GetFilter()->GetFilterName(); } return OUString(); } OUString ScLinkedAreaDlg::GetOptions() const { if (m_pSourceShell) { SfxMedium* pMed = m_pSourceShell->GetMedium(); return ScDocumentLoader::GetOptions( *pMed ); } return OUString(); } OUString ScLinkedAreaDlg::GetSource() const { OUStringBuffer aBuf; std::vector aSelection = m_xLbRanges->get_selected_rows_text(); for (size_t i = 0; i < aSelection.size(); ++i) { if (i > 0) aBuf.append(';'); aBuf.append(aSelection[i]); } return aBuf.makeStringAndClear(); } sal_Int32 ScLinkedAreaDlg::GetRefreshDelaySeconds() const { if (m_xBtnReload->get_active()) return m_xNfDelay->get_value(); else return 0; // disabled } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */