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 #include <core_resource.hxx>
21 #include "TextConnectionHelper.hxx"
22 #include <strings.hrc>
23 #include <strings.hxx>
24 #include <svl/itemset.hxx>
25 #include <svl/stritem.hxx>
26 #include <svl/eitem.hxx>
27 #include <dsitems.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/weld.hxx>
30 #include <vcl/mnemonic.hxx>
31 #include <o3tl/string_view.hxx>
36 OUString
lcl_getListEntry(std::u16string_view rStr
, sal_Int32
& rIdx
)
38 const OUString sTkn
{o3tl::getToken(rStr
, 0, '\t', rIdx
)};
41 size_t nFnd
= rStr
.find('\t', rIdx
);
42 if (nFnd
== std::u16string_view::npos
)
47 if (rIdx
>= static_cast<sal_Int32
>(rStr
.size()))
59 OTextConnectionHelper::OTextConnectionHelper(weld::Widget
* pParent
, const short _nAvailableSections
)
60 : m_aFieldSeparatorList (DBA_RES(STR_AUTOFIELDSEPARATORLIST
))
61 , m_aTextSeparatorList (STR_AUTOTEXTSEPARATORLIST
)
62 , m_aTextNone (DBA_RES(STR_AUTOTEXT_FIELD_SEP_NONE
))
63 , m_nAvailableSections( _nAvailableSections
)
64 , m_xBuilder(Application::CreateBuilder(pParent
, u
"dbaccess/ui/textpage.ui"_ustr
))
65 , m_xContainer(m_xBuilder
->weld_widget(u
"TextPage"_ustr
))
66 , m_xExtensionHeader(m_xBuilder
->weld_widget(u
"extensionframe"_ustr
))
67 , m_xAccessTextFiles(m_xBuilder
->weld_radio_button(u
"textfile"_ustr
))
68 , m_xAccessCSVFiles(m_xBuilder
->weld_radio_button(u
"csvfile"_ustr
))
69 , m_xAccessOtherFiles(m_xBuilder
->weld_radio_button(u
"custom"_ustr
))
70 , m_xOwnExtension(m_xBuilder
->weld_entry(u
"extension"_ustr
))
71 , m_xExtensionExample(m_xBuilder
->weld_label(u
"example"_ustr
))
72 , m_xFormatHeader(m_xBuilder
->weld_widget(u
"formatframe"_ustr
))
73 , m_xFieldSeparatorLabel(m_xBuilder
->weld_label(u
"fieldlabel"_ustr
))
74 , m_xFieldSeparator(m_xBuilder
->weld_combo_box(u
"fieldseparator"_ustr
))
75 , m_xTextSeparatorLabel(m_xBuilder
->weld_label(u
"textlabel"_ustr
))
76 , m_xTextSeparator(m_xBuilder
->weld_combo_box(u
"textseparator"_ustr
))
77 , m_xDecimalSeparatorLabel(m_xBuilder
->weld_label(u
"decimallabel"_ustr
))
78 , m_xDecimalSeparator(m_xBuilder
->weld_combo_box(u
"decimalseparator"_ustr
))
79 , m_xThousandsSeparatorLabel(m_xBuilder
->weld_label(u
"thousandslabel"_ustr
))
80 , m_xThousandsSeparator(m_xBuilder
->weld_combo_box(u
"thousandsseparator"_ustr
))
81 , m_xRowHeader(m_xBuilder
->weld_check_button(u
"containsheaders"_ustr
))
82 , m_xCharSetHeader(m_xBuilder
->weld_widget(u
"charsetframe"_ustr
))
83 , m_xCharSetLabel(m_xBuilder
->weld_label(u
"charsetlabel"_ustr
))
84 , m_xCharSet(new CharSetListBox(m_xBuilder
->weld_combo_box(u
"charset"_ustr
)))
86 for(sal_Int32 nIdx
{0}; nIdx
>=0;)
87 m_xFieldSeparator
->append_text( lcl_getListEntry(m_aFieldSeparatorList
, nIdx
) );
89 for(sal_Int32 nIdx
{0}; nIdx
>=0;)
90 m_xTextSeparator
->append_text( lcl_getListEntry(m_aTextSeparatorList
, nIdx
) );
91 m_xTextSeparator
->append_text(m_aTextNone
);
93 m_xOwnExtension
->connect_changed(LINK(this, OTextConnectionHelper
, OnEditModified
));
94 m_xAccessTextFiles
->connect_toggled(LINK(this, OTextConnectionHelper
, OnSetExtensionHdl
));
95 m_xAccessCSVFiles
->connect_toggled(LINK(this, OTextConnectionHelper
, OnSetExtensionHdl
));
96 m_xAccessOtherFiles
->connect_toggled(LINK(this, OTextConnectionHelper
, OnSetExtensionHdl
));
97 m_xAccessCSVFiles
->set_active(true);
99 struct SectionDescriptor
102 weld::Widget
* pFrame
;
103 } const aSections
[] = {
104 { TC_EXTENSION
, m_xExtensionHeader
.get() },
105 { TC_SEPARATORS
, m_xFormatHeader
.get() },
106 { TC_HEADER
, m_xRowHeader
.get() },
107 { TC_CHARSET
, m_xCharSetHeader
.get() }
110 for (auto const & section
: aSections
)
112 if ( ( m_nAvailableSections
& section
.nFlag
) != 0 )
114 // the section is visible, no need to do anything here
118 // hide all elements from this section
119 section
.pFrame
->hide();
122 m_xContainer
->show();
125 IMPL_LINK_NOARG(OTextConnectionHelper
, OnEditModified
, weld::Entry
&, void)
127 m_aGetExtensionHandler
.Call(this);
130 IMPL_LINK_NOARG(OTextConnectionHelper
, OnSetExtensionHdl
, weld::Toggleable
&, void)
132 bool bDoEnable
= m_xAccessOtherFiles
->get_active();
133 m_xOwnExtension
->set_sensitive(bDoEnable
);
134 m_xExtensionExample
->set_sensitive(bDoEnable
);
135 m_aGetExtensionHandler
.Call(this);
138 void OTextConnectionHelper::fillControls(std::vector
< std::unique_ptr
<ISaveValueWrapper
> >& _rControlList
)
140 _rControlList
.emplace_back(new OSaveValueWidgetWrapper
<weld::ComboBox
>(m_xFieldSeparator
.get()));
141 _rControlList
.emplace_back(new OSaveValueWidgetWrapper
<weld::ComboBox
>(m_xTextSeparator
.get()));
142 _rControlList
.emplace_back(new OSaveValueWidgetWrapper
<weld::ComboBox
>(m_xDecimalSeparator
.get()));
143 _rControlList
.emplace_back(new OSaveValueWidgetWrapper
<weld::ComboBox
>(m_xThousandsSeparator
.get()));
144 _rControlList
.emplace_back(new OSaveValueWidgetWrapper
<weld::Toggleable
>(m_xRowHeader
.get()));
145 _rControlList
.emplace_back(new OSaveValueWidgetWrapper
<weld::ComboBox
>(m_xCharSet
->get_widget()));
148 void OTextConnectionHelper::fillWindows(std::vector
< std::unique_ptr
<ISaveValueWrapper
> >& _rControlList
)
150 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::Label
>(m_xFieldSeparatorLabel
.get()));
151 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::Label
>(m_xTextSeparatorLabel
.get()));
152 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::Label
>(m_xDecimalSeparatorLabel
.get()));
153 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::Label
>(m_xThousandsSeparatorLabel
.get()));
154 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::Widget
>(m_xCharSetHeader
.get()));
155 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::Label
>(m_xCharSetLabel
.get()));
156 _rControlList
.emplace_back(new ODisableWidgetWrapper
<weld::ComboBox
>(m_xCharSet
->get_widget()));
159 void OTextConnectionHelper::implInitControls(const SfxItemSet
& _rSet
, bool _bValid
)
164 const SfxStringItem
* pDelItem
= _rSet
.GetItem
<SfxStringItem
>(DSID_FIELDDELIMITER
);
165 const SfxStringItem
* pStrItem
= _rSet
.GetItem
<SfxStringItem
>(DSID_TEXTDELIMITER
);
166 const SfxStringItem
* pDecdelItem
= _rSet
.GetItem
<SfxStringItem
>(DSID_DECIMALDELIMITER
);
167 const SfxStringItem
* pThodelItem
= _rSet
.GetItem
<SfxStringItem
>(DSID_THOUSANDSDELIMITER
);
168 const SfxStringItem
* pExtensionItem
= _rSet
.GetItem
<SfxStringItem
>(DSID_TEXTFILEEXTENSION
);
169 const SfxStringItem
* pCharsetItem
= _rSet
.GetItem
<SfxStringItem
>(DSID_CHARSET
);
171 if ( ( m_nAvailableSections
& TC_EXTENSION
) != 0 )
173 m_aOldExtension
= pExtensionItem
->GetValue();
174 SetExtension( m_aOldExtension
);
177 if ( ( m_nAvailableSections
& TC_HEADER
) != 0 )
179 const SfxBoolItem
* pHdrItem
= _rSet
.GetItem
<SfxBoolItem
>(DSID_TEXTFILEHEADER
);
180 m_xRowHeader
->set_active(pHdrItem
->GetValue());
183 if ( ( m_nAvailableSections
& TC_SEPARATORS
) != 0 )
185 SetSeparator(*m_xFieldSeparator
, m_aFieldSeparatorList
, pDelItem
->GetValue());
186 SetSeparator(*m_xTextSeparator
, m_aTextSeparatorList
, pStrItem
->GetValue());
187 m_xDecimalSeparator
->set_entry_text( pDecdelItem
->GetValue() );
188 m_xThousandsSeparator
->set_entry_text( pThodelItem
->GetValue() );
191 if ( ( m_nAvailableSections
& TC_CHARSET
) != 0 )
193 m_xCharSet
->SelectEntryByIanaName( pCharsetItem
->GetValue() );
197 bool OTextConnectionHelper::prepareLeave()
199 OUString sExtension
= GetExtension();
201 weld::Widget
* pErrorWin
= nullptr;
202 OUString
aDelText(m_xFieldSeparator
->get_active_text());
203 if(aDelText
.isEmpty())
204 { // No FieldSeparator
205 aErrorText
= DBA_RES(STR_AUTODELIMITER_MISSING
);
206 aErrorText
= aErrorText
.replaceFirst("#1",m_xFieldSeparatorLabel
->get_label());
207 pErrorWin
= m_xFieldSeparator
.get();
209 else if (m_xDecimalSeparator
->get_active_text().isEmpty())
210 { // No DecimalSeparator
211 aErrorText
= DBA_RES(STR_AUTODELIMITER_MISSING
);
212 aErrorText
= aErrorText
.replaceFirst("#1",m_xDecimalSeparatorLabel
->get_label());
213 pErrorWin
= m_xDecimalSeparator
.get();
215 else if (m_xTextSeparator
->get_active_text() == m_xFieldSeparator
->get_active_text())
216 { // Field and TextSeparator must not be the same
217 aErrorText
= DBA_RES(STR_AUTODELIMITER_MUST_DIFFER
);
218 aErrorText
= aErrorText
.replaceFirst("#1",m_xTextSeparatorLabel
->get_label());
219 aErrorText
= aErrorText
.replaceFirst("#2",m_xFieldSeparatorLabel
->get_label());
220 pErrorWin
= m_xTextSeparator
.get();
222 else if (m_xDecimalSeparator
->get_active_text() == m_xThousandsSeparator
->get_active_text())
223 { // Thousands and DecimalSeparator must not be the same
224 aErrorText
= DBA_RES(STR_AUTODELIMITER_MUST_DIFFER
);
225 aErrorText
= aErrorText
.replaceFirst("#1",m_xDecimalSeparatorLabel
->get_label());
226 aErrorText
= aErrorText
.replaceFirst("#2",m_xThousandsSeparatorLabel
->get_label());
227 pErrorWin
= m_xDecimalSeparator
.get();
229 else if (m_xFieldSeparator
->get_active_text() == m_xThousandsSeparator
->get_active_text())
230 { // Thousands and FieldSeparator must not be the same
231 aErrorText
= DBA_RES(STR_AUTODELIMITER_MUST_DIFFER
);
232 aErrorText
= aErrorText
.replaceFirst("#1",m_xFieldSeparatorLabel
->get_label());
233 aErrorText
= aErrorText
.replaceFirst("#2",m_xThousandsSeparatorLabel
->get_label());
234 pErrorWin
= m_xFieldSeparator
.get();
236 else if (m_xFieldSeparator
->get_active_text() == m_xDecimalSeparator
->get_active_text())
237 { // Tenner and FieldSeparator must not be the same
238 aErrorText
= DBA_RES(STR_AUTODELIMITER_MUST_DIFFER
);
239 aErrorText
= aErrorText
.replaceFirst("#1",m_xFieldSeparatorLabel
->get_label());
240 aErrorText
= aErrorText
.replaceFirst("#2",m_xDecimalSeparatorLabel
->get_label());
241 pErrorWin
= m_xFieldSeparator
.get();
243 else if (m_xTextSeparator
->get_active_text() == m_xThousandsSeparator
->get_active_text())
244 { // Thousands and TextSeparator must not be the same
245 aErrorText
= DBA_RES(STR_AUTODELIMITER_MUST_DIFFER
);
246 aErrorText
= aErrorText
.replaceFirst("#1",m_xTextSeparatorLabel
->get_label());
247 aErrorText
= aErrorText
.replaceFirst("#2",m_xThousandsSeparatorLabel
->get_label());
248 pErrorWin
= m_xTextSeparator
.get();
250 else if (m_xTextSeparator
->get_active_text() == m_xDecimalSeparator
->get_active_text())
251 { // Tenner and TextSeparator must not be the same
252 aErrorText
= DBA_RES(STR_AUTODELIMITER_MUST_DIFFER
);
253 aErrorText
= aErrorText
.replaceFirst("#1",m_xTextSeparatorLabel
->get_label());
254 aErrorText
= aErrorText
.replaceFirst("#2",m_xDecimalSeparatorLabel
->get_label());
255 pErrorWin
= m_xTextSeparator
.get();
257 else if ((sExtension
.indexOf('*') != -1) || (sExtension
.indexOf('?') != -1))
259 aErrorText
= DBA_RES(STR_AUTONO_WILDCARDS
);
260 aErrorText
= aErrorText
.replaceFirst("#1",sExtension
);
261 pErrorWin
= m_xOwnExtension
.get();
265 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xContainer
.get(),
266 VclMessageType::Warning
, VclButtonsType::Ok
,
267 MnemonicGenerator::EraseAllMnemonicChars(aErrorText
)));
269 pErrorWin
->grab_focus();
273 bool OTextConnectionHelper::FillItemSet( SfxItemSet
& rSet
, const bool _bChangedSomething
)
275 bool bChangedSomething
= _bChangedSomething
;
277 if ( ( m_nAvailableSections
& TC_EXTENSION
) != 0 )
279 OUString sExtension
= GetExtension();
280 if( m_aOldExtension
!= sExtension
)
282 rSet
.Put( SfxStringItem( DSID_TEXTFILEEXTENSION
, sExtension
) );
283 bChangedSomething
= true;
287 if ( ( m_nAvailableSections
& TC_HEADER
) != 0 )
289 if (m_xRowHeader
->get_state_changed_from_saved())
291 rSet
.Put(SfxBoolItem(DSID_TEXTFILEHEADER
, m_xRowHeader
->get_active()));
292 bChangedSomething
= true;
296 if ( ( m_nAvailableSections
& TC_SEPARATORS
) != 0 )
298 if (m_xFieldSeparator
->get_value_changed_from_saved())
300 rSet
.Put( SfxStringItem(DSID_FIELDDELIMITER
, GetSeparator( *m_xFieldSeparator
, m_aFieldSeparatorList
) ) );
301 bChangedSomething
= true;
303 if (m_xTextSeparator
->get_value_changed_from_saved())
305 rSet
.Put( SfxStringItem(DSID_TEXTDELIMITER
, GetSeparator( *m_xTextSeparator
, m_aTextSeparatorList
) ) );
306 bChangedSomething
= true;
309 if (m_xDecimalSeparator
->get_value_changed_from_saved())
311 rSet
.Put( SfxStringItem(DSID_DECIMALDELIMITER
, m_xDecimalSeparator
->get_active_text().copy(0, 1) ) );
312 bChangedSomething
= true;
314 if (m_xThousandsSeparator
->get_value_changed_from_saved())
316 rSet
.Put( SfxStringItem(DSID_THOUSANDSDELIMITER
, m_xThousandsSeparator
->get_active_text().copy(0,1) ) );
317 bChangedSomething
= true;
321 if ( ( m_nAvailableSections
& TC_CHARSET
) != 0 )
323 if ( m_xCharSet
->StoreSelectedCharSet( rSet
, DSID_CHARSET
) )
324 bChangedSomething
= true;
327 return bChangedSomething
;
330 void OTextConnectionHelper::SetExtension(const OUString
& _rVal
)
333 m_xAccessTextFiles
->set_active(true);
334 else if (_rVal
== "csv")
335 m_xAccessCSVFiles
->set_active(true);
338 m_xAccessOtherFiles
->set_active(true);
339 m_xExtensionExample
->set_label(_rVal
);
343 OUString
OTextConnectionHelper::GetExtension() const
346 if (m_xAccessTextFiles
->get_active())
348 else if (m_xAccessCSVFiles
->get_active())
352 sExtension
= m_xOwnExtension
->get_text();
353 if ( sExtension
.startsWith("*.") )
354 sExtension
= sExtension
.copy(2);
359 OUString
OTextConnectionHelper::GetSeparator(const weld::ComboBox
& rBox
, std::u16string_view rList
)
361 sal_Unicode
const nTok
= '\t';
362 int nPos(rBox
.find_text(rBox
.get_active_text()));
365 return rBox
.get_active_text();
367 if ( m_xTextSeparator
.get() != &rBox
|| nPos
!= (rBox
.get_count()-1) )
369 static_cast< sal_Unicode
>( o3tl::toInt32(o3tl::getToken(rList
, (nPos
*2)+1, nTok
)) ));
370 // somewhat strange ... translates for instance an "32" into " "
374 void OTextConnectionHelper::SetSeparator( weld::ComboBox
& rBox
, std::u16string_view rList
, const OUString
& rVal
)
376 if (rVal
.getLength()==1)
378 const sal_Unicode nVal
{rVal
[0]};
379 for(sal_Int32 nIdx
{0}; nIdx
>=0;)
381 sal_Int32 nPrevIdx
{nIdx
};
382 if (static_cast<sal_Unicode
>(o3tl::toInt32(o3tl::getToken(rList
, 1, '\t', nIdx
))) == nVal
)
384 rBox
.set_entry_text(OUString(o3tl::getToken(rList
,0, '\t', nPrevIdx
)));
388 rBox
.set_entry_text( rVal
);
390 else if ( m_xTextSeparator
.get() == &rBox
&& rVal
.isEmpty() )
391 rBox
.set_entry_text(m_aTextNone
);
393 rBox
.set_entry_text(rVal
.copy(0, 1));
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */