tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / dbaccess / source / ui / misc / WColumnSelect.cxx
blob8cc8868760cd570093628654748fae06d2cfdc89
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <WColumnSelect.hxx>
21 #include <strings.hrc>
22 #include <osl/diagnose.h>
23 #include <WCopyTable.hxx>
24 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
25 #include <core_resource.hxx>
26 #include <com/sun/star/sdb/application/CopyTableOperation.hpp>
28 using namespace ::com::sun::star::uno;
29 using namespace ::com::sun::star::sdbc;
30 using namespace dbaui;
32 namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
34 OUString OWizColumnSelect::GetTitle() const { return DBA_RES(STR_WIZ_COLUMN_SELECT_TITLE); }
36 OWizardPage::OWizardPage(weld::Container* pPage, OCopyTableWizard* pWizard, const OUString& rUIXMLDescription, const OUString& rID)
37 : ::vcl::OWizardPage(pPage, pWizard, rUIXMLDescription, rID)
38 , m_pParent(pWizard)
39 , m_bFirstTime(true)
43 OWizardPage::~OWizardPage()
47 // OWizColumnSelect
48 OWizColumnSelect::OWizColumnSelect(weld::Container* pPage, OCopyTableWizard* pWizard)
49 : OWizardPage(pPage, pWizard, u"dbaccess/ui/applycolpage.ui"_ustr, u"ApplyColPage"_ustr)
50 , m_xOrgColumnNames(m_xBuilder->weld_tree_view(u"from"_ustr))
51 , m_xColumn_RH(m_xBuilder->weld_button(u"colrh"_ustr))
52 , m_xColumns_RH(m_xBuilder->weld_button(u"colsrh"_ustr))
53 , m_xColumn_LH(m_xBuilder->weld_button(u"collh"_ustr))
54 , m_xColumns_LH(m_xBuilder->weld_button(u"colslh"_ustr))
55 , m_xNewColumnNames(m_xBuilder->weld_tree_view(u"to"_ustr))
57 m_xColumn_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
58 m_xColumn_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
59 m_xColumns_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
60 m_xColumns_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
62 m_xOrgColumnNames->set_selection_mode(SelectionMode::Multiple);
63 m_xNewColumnNames->set_selection_mode(SelectionMode::Multiple);
65 m_xOrgColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
66 m_xNewColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
69 OWizColumnSelect::~OWizColumnSelect()
71 while (m_xNewColumnNames->n_children())
73 delete weld::fromId<OFieldDescription*>(m_xNewColumnNames->get_id(0));
74 m_xNewColumnNames->remove(0);
78 void OWizColumnSelect::Reset()
80 // restore original state
81 clearListBox(*m_xOrgColumnNames);
82 clearListBox(*m_xNewColumnNames);
83 m_pParent->m_mNameMapping.clear();
85 // insert the source columns in the left listbox
86 const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
88 for (auto const& column : rSrcColumns)
90 OUString sId(weld::toId(column->second));
91 m_xOrgColumnNames->append(sId, column->first);
94 if (m_xOrgColumnNames->n_children())
95 m_xOrgColumnNames->select(0);
97 m_bFirstTime = false;
100 void OWizColumnSelect::Activate( )
102 // if there are no dest columns reset the left side with the original columns
103 if(m_pParent->getDestColumns().empty())
104 Reset();
106 clearListBox(*m_xNewColumnNames);
108 const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
110 // tdf#113923, the added columns must exist in the table
111 // in the case where:
112 // 1: we enabled the creation of a primary key
113 // 2: we come back here from the "Back" button of the next page,
114 // we want to avoid to list the new column generated in the next page
115 const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
117 for (auto const& column : rDestColumns)
119 if (rSrcColumns.find(column->first) != rSrcColumns.end())
121 OUString sId(weld::toId(new OFieldDescription(*(column->second))));
122 m_xNewColumnNames->append(sId, column->first);
123 int nRemove = m_xOrgColumnNames->find_text(column->first);
124 if (nRemove != -1)
125 m_xOrgColumnNames->remove(nRemove);
128 m_pParent->GetOKButton().set_sensitive(m_xNewColumnNames->n_children() != 0);
129 m_pParent->EnableNextButton(m_xNewColumnNames->n_children() && m_pParent->getOperation() != CopyTableOperation::AppendData);
130 m_xColumns_RH->grab_focus();
133 bool OWizColumnSelect::LeavePage()
136 m_pParent->clearDestColumns();
138 for(sal_Int32 i=0 ; i< m_xNewColumnNames->n_children();++i)
140 OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xNewColumnNames->get_id(i));
141 OSL_ENSURE(pField,"The field information can not be null!");
142 m_pParent->insertColumn(i,pField);
145 clearListBox(*m_xNewColumnNames);
147 if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT
148 || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH
150 return !m_pParent->getDestColumns().empty();
151 else
152 return true;
155 IMPL_LINK(OWizColumnSelect, ButtonClickHdl, weld::Button&, rButton, void)
157 weld::TreeView *pLeft = nullptr;
158 weld::TreeView *pRight = nullptr;
159 bool bAll = false;
161 if (&rButton == m_xColumn_RH.get())
163 pLeft = m_xOrgColumnNames.get();
164 pRight = m_xNewColumnNames.get();
166 else if (&rButton == m_xColumn_LH.get())
168 pLeft = m_xNewColumnNames.get();
169 pRight = m_xOrgColumnNames.get();
171 else if (&rButton == m_xColumns_RH.get())
173 pLeft = m_xOrgColumnNames.get();
174 pRight = m_xNewColumnNames.get();
175 bAll = true;
177 else if (&rButton == m_xColumns_LH.get())
179 pLeft = m_xNewColumnNames.get();
180 pRight = m_xOrgColumnNames.get();
181 bAll = true;
184 if (!pLeft || !pRight)
185 return;
187 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
188 OUString sExtraChars = xMetaData->getExtraNameCharacters();
189 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
191 ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
192 std::vector< OUString> aRightColumns;
193 fillColumns(pRight,aRightColumns);
195 if(!bAll)
197 auto aRows = pLeft->get_selected_rows();
198 std::sort(aRows.begin(), aRows.end());
200 for (auto it = aRows.begin(); it != aRows.end(); ++it)
201 moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
203 for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
204 pLeft->remove(*it);
206 else
208 const sal_Int32 nEntries = pLeft->n_children();
209 for(sal_Int32 i=0; i < nEntries; ++i)
210 moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(i),sExtraChars,nMaxNameLen,aCase);
211 for(sal_Int32 j=pLeft->n_children(); j ; )
212 pLeft->remove(--j);
215 enableButtons();
217 if (m_xOrgColumnNames->n_children())
218 m_xOrgColumnNames->select(0);
221 IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, weld::TreeView&, rListBox, bool )
223 weld::TreeView *pLeft,*pRight;
224 if (&rListBox == m_xOrgColumnNames.get())
226 pLeft = m_xOrgColumnNames.get();
227 pRight = m_xNewColumnNames.get();
229 else
231 pRight = m_xOrgColumnNames.get();
232 pLeft = m_xNewColumnNames.get();
235 // If database is able to process PrimaryKeys, set PrimaryKey
236 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
237 OUString sExtraChars = xMetaData->getExtraNameCharacters();
238 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
240 ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
241 std::vector< OUString> aRightColumns;
242 fillColumns(pRight,aRightColumns);
244 auto aRows = pLeft->get_selected_rows();
245 std::sort(aRows.begin(), aRows.end());
247 for (auto it = aRows.begin(); it != aRows.end(); ++it)
248 moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
250 for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
251 pLeft->remove(*it);
253 enableButtons();
255 return true;
258 void OWizColumnSelect::clearListBox(weld::TreeView& rListBox)
260 rListBox.clear();
263 void OWizColumnSelect::fillColumns(weld::TreeView const * pRight,std::vector< OUString> &_rRightColumns)
265 const sal_Int32 nCount = pRight->n_children();
266 _rRightColumns.reserve(nCount);
267 for (sal_Int32 i=0; i < nCount; ++i)
268 _rRightColumns.push_back(pRight->get_text(i));
271 void OWizColumnSelect::createNewColumn( weld::TreeView* _pListbox,
272 OFieldDescription const * _pSrcField,
273 std::vector< OUString>& _rRightColumns,
274 const OUString& _sColumnName,
275 std::u16string_view _sExtraChars,
276 sal_Int32 _nMaxNameLen,
277 const ::comphelper::UStringMixEqual& _aCase)
279 OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase),
280 _sColumnName,
281 _sExtraChars,
282 _nMaxNameLen);
283 OFieldDescription* pNewField = new OFieldDescription(*_pSrcField);
284 pNewField->SetName(sConvertedName);
285 bool bNotConvert = true;
286 pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert));
287 if ( !m_pParent->supportsPrimaryKey() )
288 pNewField->SetPrimaryKey(false);
290 _pListbox->append(weld::toId(pNewField), sConvertedName);
291 _rRightColumns.push_back(sConvertedName);
293 if ( !bNotConvert )
294 m_pParent->showColumnTypeNotSupported(sConvertedName);
297 void OWizColumnSelect::moveColumn( weld::TreeView* _pRight,
298 weld::TreeView const * _pLeft,
299 std::vector< OUString>& _rRightColumns,
300 const OUString& _sColumnName,
301 std::u16string_view _sExtraChars,
302 sal_Int32 _nMaxNameLen,
303 const ::comphelper::UStringMixEqual& _aCase)
305 if(_pRight == m_xNewColumnNames.get())
307 // we copy the column into the new format for the dest
308 OFieldDescription* pSrcField = weld::fromId<OFieldDescription*>(_pLeft->get_id(_pLeft->find_text(_sColumnName)));
309 createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase);
311 else
313 // find the new column in the dest name mapping to obtain the old column
314 OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
315 [&_aCase, &_sColumnName] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
316 return _aCase(nameMap.second, _sColumnName);
319 OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
320 if ( aIter == m_pParent->m_mNameMapping.end() )
321 return; // do nothing
322 const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
323 ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
324 if ( aSrcIter != rSrcColumns.end() )
326 // we need also the old position of this column to insert it back on that position again
327 const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
328 ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
329 OSL_ENSURE( aPos != rSrcVector.end(),"Invalid position for the iterator here!");
330 ODatabaseExport::TColumnVector::size_type nPos = (aPos - rSrcVector.begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - rSrcVector.begin()), _aCase);
332 OUString sId(weld::toId(aSrcIter->second));
333 const OUString& rStr = (*aIter).first;
334 _pRight->insert(nullptr, nPos, &rStr, &sId, nullptr, nullptr, false, nullptr);
335 _rRightColumns.push_back(rStr);
336 m_pParent->removeColumnNameFromNameMap(_sColumnName);
341 // Simply returning fields back to their original position is
342 // not enough. We need to take into account what fields have
343 // been removed earlier and adjust accordingly. Based on the
344 // algorithm employed in moveColumn().
345 sal_Int32 OWizColumnSelect::adjustColumnPosition(weld::TreeView const * _pLeft,
346 std::u16string_view _sColumnName,
347 ODatabaseExport::TColumnVector::size_type nCurrentPos,
348 const ::comphelper::UStringMixEqual& _aCase)
350 sal_Int32 nAdjustedPos = 0;
352 // if returning all entries to their original position,
353 // then there is no need to adjust the positions.
354 if (m_xColumns_LH->has_focus())
355 return nAdjustedPos;
357 const sal_Int32 nCount = _pLeft->n_children();
358 OUString sColumnString;
359 for(sal_Int32 i=0; i < nCount; ++i)
361 sColumnString = _pLeft->get_text(i);
362 if(_sColumnName != sColumnString)
364 // find the new column in the dest name mapping to obtain the old column
365 OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
366 [&_aCase, &sColumnString] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
367 return _aCase(nameMap.second, sColumnString);
370 OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
371 const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
372 ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
373 if ( aSrcIter != rSrcColumns.end() )
375 // we need also the old position of this column to insert it back on that position again
376 const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
377 ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
378 ODatabaseExport::TColumnVector::size_type nPos = aPos - rSrcVector.begin();
379 if( nPos < nCurrentPos)
381 nAdjustedPos++;
387 return nAdjustedPos;
390 void OWizColumnSelect::enableButtons()
392 bool bEntries = m_xNewColumnNames->n_children() != 0;
393 if (!bEntries)
394 m_pParent->m_mNameMapping.clear();
396 m_pParent->GetOKButton().set_sensitive(bEntries);
397 m_pParent->EnableNextButton(bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData);
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */