1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #undef SC_DLLIMPLEMENTATION
22 #include <sfx2/docfile.hxx>
23 #include <sfx2/docfilt.hxx>
24 #include <sfx2/docinsert.hxx>
25 #include <sfx2/fcontnr.hxx>
26 #include <sfx2/filedlghelper.hxx>
27 #include <svtools/ehdl.hxx>
28 #include <svtools/inettbc.hxx>
29 #include <svtools/sfxecode.hxx>
30 #include <o3tl/string_view.hxx>
33 #include <linkarea.hxx>
35 #include <tablink.hxx>
36 #include <scresid.hxx>
37 #include <strings.hrc>
39 ScLinkedAreaDlg::ScLinkedAreaDlg(weld::Widget
* pParent
)
40 : GenericDialogController(pParent
, u
"modules/scalc/ui/externaldata.ui"_ustr
, u
"ExternalDataDialog"_ustr
)
41 , m_xCbUrl(new SvtURLBox(m_xBuilder
->weld_combo_box(u
"url"_ustr
)))
42 , m_xBtnBrowse(m_xBuilder
->weld_button(u
"browse"_ustr
))
43 , m_xLbRanges(m_xBuilder
->weld_tree_view(u
"ranges"_ustr
))
44 , m_xBtnReload(m_xBuilder
->weld_check_button(u
"reload"_ustr
))
45 , m_xNfDelay(m_xBuilder
->weld_spin_button(u
"delay"_ustr
))
46 , m_xFtSeconds(m_xBuilder
->weld_label(u
"secondsft"_ustr
))
47 , m_xBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
49 m_xLbRanges
->set_selection_mode(SelectionMode::Multiple
);
51 m_xCbUrl
->connect_entry_activate(LINK(this, ScLinkedAreaDlg
, FileHdl
));
52 m_xBtnBrowse
->connect_clicked(LINK( this, ScLinkedAreaDlg
, BrowseHdl
));
53 m_xLbRanges
->connect_selection_changed(LINK(this, ScLinkedAreaDlg
, RangeHdl
));
54 m_xLbRanges
->set_size_request(m_xLbRanges
->get_approximate_digit_width() * 54,
55 m_xLbRanges
->get_height_rows(5));
56 m_xBtnReload
->connect_toggled(LINK( this, ScLinkedAreaDlg
, ReloadHdl
));
60 ScLinkedAreaDlg::~ScLinkedAreaDlg()
64 constexpr OUString FILTERNAME_HTML
= u
"HTML (StarCalc)"_ustr
;
65 constexpr OUString FILTERNAME_QUERY
= u
"calc_HTML_WebQuery"_ustr
;
67 IMPL_LINK_NOARG(ScLinkedAreaDlg
, BrowseHdl
, weld::Button
&, void)
69 m_xDocInserter
.reset( new sfx2::DocumentInserter(m_xDialog
.get(), ScDocShell::Factory().GetFactoryName()) );
70 m_xDocInserter
->StartExecuteModal( LINK( this, ScLinkedAreaDlg
, DialogClosedHdl
) );
73 IMPL_LINK_NOARG(ScLinkedAreaDlg
, FileHdl
, weld::ComboBox
&, bool)
75 OUString aEntered
= m_xCbUrl
->GetURL();
78 SfxMedium
* pMed
= m_pSourceShell
->GetMedium();
79 if ( aEntered
== pMed
->GetName() )
81 // already loaded - nothing to do
88 // get filter name by looking at the file content (bWithContent = true)
89 // Break operation if any error occurred inside.
90 if (!ScDocumentLoader::GetFilterName( aEntered
, aFilter
, aOptions
, true, false ))
93 // #i53241# replace HTML filter with DataQuery filter
94 if (aFilter
== FILTERNAME_HTML
)
95 aFilter
= FILTERNAME_QUERY
;
97 LoadDocument( aEntered
, aFilter
, aOptions
);
105 void ScLinkedAreaDlg::LoadDocument( const OUString
& rFile
, const OUString
& rFilter
, const OUString
& rOptions
)
109 // unload old document
110 m_pSourceShell
->DoClose();
111 m_pSourceShell
.clear();
114 if ( rFile
.isEmpty() )
117 weld::WaitObject
aWait(m_xDialog
.get());
119 OUString aNewFilter
= rFilter
;
120 OUString aNewOptions
= rOptions
;
122 SfxErrorContext
aEc( ERRCTX_SFX_OPENDOC
, rFile
);
124 ScDocumentLoader
aLoader( rFile
, aNewFilter
, aNewOptions
, 0, m_xDialog
.get() ); // with interaction
125 m_pSourceShell
= aLoader
.GetDocShell();
128 ErrCodeMsg nErr
= m_pSourceShell
->GetErrorCode();
130 ErrorHandler::HandleError( nErr
); // including warnings
132 aLoader
.ReleaseDocRef(); // don't call DoClose in DocLoader dtor
136 void ScLinkedAreaDlg::InitFromOldLink( const OUString
& rFile
, const OUString
& rFilter
,
137 const OUString
& rOptions
, std::u16string_view rSource
,
138 sal_Int32 nRefreshDelaySeconds
)
140 LoadDocument( rFile
, rFilter
, rOptions
);
143 SfxMedium
* pMed
= m_pSourceShell
->GetMedium();
144 m_xCbUrl
->set_entry_text(pMed
->GetName());
147 m_xCbUrl
->set_entry_text(OUString());
149 UpdateSourceRanges();
151 if (!rSource
.empty())
156 m_xLbRanges
->select_text(OUString(o3tl::getToken(rSource
, 0, ';', nIdx
)));
161 bool bDoRefresh
= (nRefreshDelaySeconds
!= 0);
162 m_xBtnReload
->set_active(bDoRefresh
);
164 m_xNfDelay
->set_value(nRefreshDelaySeconds
);
169 IMPL_LINK_NOARG(ScLinkedAreaDlg
, RangeHdl
, weld::TreeView
&, void)
174 IMPL_LINK_NOARG(ScLinkedAreaDlg
, ReloadHdl
, weld::Toggleable
&, void)
179 IMPL_LINK( ScLinkedAreaDlg
, DialogClosedHdl
, sfx2::FileDialogHelper
*, _pFileDlg
, void )
181 if ( _pFileDlg
->GetError() != ERRCODE_NONE
)
184 std::unique_ptr
<SfxMedium
> pMed
= m_xDocInserter
->CreateMedium();
187 weld::WaitObject
aWait(m_xDialog
.get());
189 // replace HTML filter with DataQuery filter
190 std::shared_ptr
<const SfxFilter
> pFilter
= pMed
->GetFilter();
191 if (pFilter
&& FILTERNAME_HTML
== pFilter
->GetFilterName())
193 std::shared_ptr
<const SfxFilter
> pNewFilter
=
194 ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( FILTERNAME_QUERY
);
196 pMed
->SetFilter( pNewFilter
);
199 // ERRCTX_SFX_OPENDOC -> "Error loading document"
200 SfxErrorContext
aEc( ERRCTX_SFX_OPENDOC
, pMed
->GetName() );
203 m_pSourceShell
->DoClose(); // deleted when assigning aSourceRef
205 pMed
->UseInteractionHandler( true ); // to enable the filter options dialog
207 m_pSourceShell
= new ScDocShell
;
208 m_pSourceShell
->DoLoad( pMed
.get() );
210 ErrCodeMsg nErr
= m_pSourceShell
->GetErrorCode();
212 ErrorHandler::HandleError( nErr
); // including warnings
214 if (!m_pSourceShell
->GetErrorIgnoreWarning()) // only errors
216 m_xCbUrl
->set_entry_text(pMed
->GetName());
220 m_pSourceShell
->DoClose();
221 m_pSourceShell
.clear();
223 m_xCbUrl
->set_entry_text(OUString());
225 pMed
.release(); // DoLoad takes ownership
228 UpdateSourceRanges();
232 #undef FILTERNAME_HTML
233 #undef FILTERNAME_QUERY
235 void ScLinkedAreaDlg::UpdateSourceRanges()
237 m_xLbRanges
->freeze();
239 m_xLbRanges
->clear();
240 if ( m_pSourceShell
)
242 std::shared_ptr
<const SfxFilter
> pFilter
= m_pSourceShell
->GetMedium()->GetFilter();
243 if (pFilter
&& pFilter
->GetFilterName() == SC_TEXT_CSV_FILTER_NAME
)
245 // Insert dummy All range to have something selectable.
246 m_xLbRanges
->append_text(u
"CSV_all"_ustr
);
249 // tdf#142600 - list tables in order of their appearance in the document's source
250 const ScRangeName
* pRangeName
= m_pSourceShell
->GetDocument().GetRangeName();
251 for (size_t i
= 1; i
<= pRangeName
->index_size(); i
++)
253 if (const ScRangeData
* pRangeData
= pRangeName
->findByIndex(i
))
255 m_xLbRanges
->append_text(pRangeData
->GetName());
258 // tdf#142600 - list database ranges
259 if (const auto pDBs
= m_pSourceShell
->GetDocument().GetDBCollection())
261 const auto& rNamedDBs
= pDBs
->getNamedDBs();
262 for (const auto& rNamedDB
: rNamedDBs
)
263 m_xLbRanges
->append_text(rNamedDB
->GetName());
269 if (m_xLbRanges
->n_children() >= 1)
270 m_xLbRanges
->select(0);
273 m_xLbRanges
->append_text(ScResId(STR_NO_NAMED_RANGES_AVAILABLE
));
274 m_xLbRanges
->set_sensitive(false);
278 void ScLinkedAreaDlg::UpdateEnable()
280 bool bEnable
= ( m_pSourceShell
&& m_xLbRanges
->count_selected_rows() );
281 m_xBtnOk
->set_sensitive(bEnable
);
283 bool bReload
= m_xBtnReload
->get_active();
284 m_xNfDelay
->set_sensitive(bReload
);
285 m_xFtSeconds
->set_sensitive(bReload
);
288 OUString
ScLinkedAreaDlg::GetURL() const
292 SfxMedium
* pMed
= m_pSourceShell
->GetMedium();
293 return pMed
->GetName();
298 OUString
ScLinkedAreaDlg::GetFilter() const
302 SfxMedium
* pMed
= m_pSourceShell
->GetMedium();
303 return pMed
->GetFilter()->GetFilterName();
308 OUString
ScLinkedAreaDlg::GetOptions() const
312 SfxMedium
* pMed
= m_pSourceShell
->GetMedium();
313 return ScDocumentLoader::GetOptions( *pMed
);
318 OUString
ScLinkedAreaDlg::GetSource() const
321 std::vector
<OUString
> aSelection
= m_xLbRanges
->get_selected_rows_text();
322 for (size_t i
= 0; i
< aSelection
.size(); ++i
)
326 aBuf
.append(aSelection
[i
]);
328 return aBuf
.makeStringAndClear();
331 sal_Int32
ScLinkedAreaDlg::GetRefreshDelaySeconds() const
333 if (m_xBtnReload
->get_active())
334 return m_xNfDelay
->get_value();
336 return 0; // disabled
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */