nss: upgrade to release 3.73
[LibreOffice.git] / dbaccess / source / ui / misc / WColumnSelect.cxx
blob8941119e9234a5cfc17feeb51f9a40b11ae8c8d2
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::beans;
30 using namespace ::com::sun::star::container;
31 using namespace ::com::sun::star::sdbc;
32 using namespace ::com::sun::star::sdbcx;
33 using namespace dbaui;
35 namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
37 OUString OWizColumnSelect::GetTitle() const { return DBA_RES(STR_WIZ_COLUMN_SELECT_TITLE); }
39 OWizardPage::OWizardPage(weld::Container* pPage, OCopyTableWizard* pWizard, const OUString& rUIXMLDescription, const OString& rID)
40 : ::vcl::OWizardPage(pPage, pWizard, rUIXMLDescription, rID)
41 , m_pParent(pWizard)
42 , m_bFirstTime(true)
46 OWizardPage::~OWizardPage()
50 // OWizColumnSelect
51 OWizColumnSelect::OWizColumnSelect(weld::Container* pPage, OCopyTableWizard* pWizard)
52 : OWizardPage(pPage, pWizard, "dbaccess/ui/applycolpage.ui", "ApplyColPage")
53 , m_xOrgColumnNames(m_xBuilder->weld_tree_view("from"))
54 , m_xColumn_RH(m_xBuilder->weld_button("colrh"))
55 , m_xColumns_RH(m_xBuilder->weld_button("colsrh"))
56 , m_xColumn_LH(m_xBuilder->weld_button("collh"))
57 , m_xColumns_LH(m_xBuilder->weld_button("colslh"))
58 , m_xNewColumnNames(m_xBuilder->weld_tree_view("to"))
60 m_xColumn_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
61 m_xColumn_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
62 m_xColumns_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
63 m_xColumns_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
65 m_xOrgColumnNames->set_selection_mode(SelectionMode::Multiple);
66 m_xNewColumnNames->set_selection_mode(SelectionMode::Multiple);
68 m_xOrgColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
69 m_xNewColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
72 OWizColumnSelect::~OWizColumnSelect()
74 while (m_xNewColumnNames->n_children())
76 delete reinterpret_cast<OFieldDescription*>(m_xNewColumnNames->get_id(0).toInt64());
77 m_xNewColumnNames->remove(0);
81 void OWizColumnSelect::Reset()
83 // restore original state
84 clearListBox(*m_xOrgColumnNames);
85 clearListBox(*m_xNewColumnNames);
86 m_pParent->m_mNameMapping.clear();
88 // insert the source columns in the left listbox
89 const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
91 for (auto const& column : rSrcColumns)
93 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(column->second)));
94 m_xOrgColumnNames->append(sId, column->first);
97 if (m_xOrgColumnNames->n_children())
98 m_xOrgColumnNames->select(0);
100 m_bFirstTime = false;
103 void OWizColumnSelect::Activate( )
105 // if there are no dest columns reset the left side with the original columns
106 if(m_pParent->getDestColumns().empty())
107 Reset();
109 clearListBox(*m_xNewColumnNames);
111 const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
113 // tdf#113923, the added columns must exist in the table
114 // in the case where:
115 // 1: we enabled the creation of a primary key
116 // 2: we come back here from the "Back" button of the next page,
117 // we want to avoid to list the new column generated in the next page
118 const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
120 for (auto const& column : rDestColumns)
122 if (rSrcColumns.find(column->first) != rSrcColumns.end())
124 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(new OFieldDescription(*(column->second)))));
125 m_xNewColumnNames->append(sId, column->first);
126 int nRemove = m_xOrgColumnNames->find_text(column->first);
127 if (nRemove != -1)
128 m_xOrgColumnNames->remove(nRemove);
131 m_pParent->GetOKButton().set_sensitive(m_xNewColumnNames->n_children() != 0);
132 m_pParent->EnableNextButton(m_xNewColumnNames->n_children() && m_pParent->getOperation() != CopyTableOperation::AppendData);
133 m_xColumns_RH->grab_focus();
136 bool OWizColumnSelect::LeavePage()
139 m_pParent->clearDestColumns();
141 for(sal_Int32 i=0 ; i< m_xNewColumnNames->n_children();++i)
143 OFieldDescription* pField = reinterpret_cast<OFieldDescription*>(m_xNewColumnNames->get_id(i).toInt64());
144 OSL_ENSURE(pField,"The field information can not be null!");
145 m_pParent->insertColumn(i,pField);
148 clearListBox(*m_xNewColumnNames);
150 if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT
151 || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH
153 return !m_pParent->getDestColumns().empty();
154 else
155 return true;
158 IMPL_LINK(OWizColumnSelect, ButtonClickHdl, weld::Button&, rButton, void)
160 weld::TreeView *pLeft = nullptr;
161 weld::TreeView *pRight = nullptr;
162 bool bAll = false;
164 if (&rButton == m_xColumn_RH.get())
166 pLeft = m_xOrgColumnNames.get();
167 pRight = m_xNewColumnNames.get();
169 else if (&rButton == m_xColumn_LH.get())
171 pLeft = m_xNewColumnNames.get();
172 pRight = m_xOrgColumnNames.get();
174 else if (&rButton == m_xColumns_RH.get())
176 pLeft = m_xOrgColumnNames.get();
177 pRight = m_xNewColumnNames.get();
178 bAll = true;
180 else if (&rButton == m_xColumns_LH.get())
182 pLeft = m_xNewColumnNames.get();
183 pRight = m_xOrgColumnNames.get();
184 bAll = true;
187 if (!pLeft || !pRight)
188 return;
190 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
191 OUString sExtraChars = xMetaData->getExtraNameCharacters();
192 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
194 ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
195 std::vector< OUString> aRightColumns;
196 fillColumns(pRight,aRightColumns);
198 if(!bAll)
200 auto aRows = pLeft->get_selected_rows();
201 std::sort(aRows.begin(), aRows.end());
203 for (auto it = aRows.begin(); it != aRows.end(); ++it)
204 moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
206 for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
207 pLeft->remove(*it);
209 else
211 const sal_Int32 nEntries = pLeft->n_children();
212 for(sal_Int32 i=0; i < nEntries; ++i)
213 moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(i),sExtraChars,nMaxNameLen,aCase);
214 for(sal_Int32 j=pLeft->n_children(); j ; )
215 pLeft->remove(--j);
218 enableButtons();
220 if (m_xOrgColumnNames->n_children())
221 m_xOrgColumnNames->select(0);
224 IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, weld::TreeView&, rListBox, bool )
226 weld::TreeView *pLeft,*pRight;
227 if (&rListBox == m_xOrgColumnNames.get())
229 pLeft = m_xOrgColumnNames.get();
230 pRight = m_xNewColumnNames.get();
232 else
234 pRight = m_xOrgColumnNames.get();
235 pLeft = m_xNewColumnNames.get();
238 // If database is able to process PrimaryKeys, set PrimaryKey
239 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
240 OUString sExtraChars = xMetaData->getExtraNameCharacters();
241 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
243 ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
244 std::vector< OUString> aRightColumns;
245 fillColumns(pRight,aRightColumns);
247 auto aRows = pLeft->get_selected_rows();
248 std::sort(aRows.begin(), aRows.end());
250 for (auto it = aRows.begin(); it != aRows.end(); ++it)
251 moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
253 for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
254 pLeft->remove(*it);
256 enableButtons();
258 return true;
261 void OWizColumnSelect::clearListBox(weld::TreeView& rListBox)
263 rListBox.clear();
266 void OWizColumnSelect::fillColumns(weld::TreeView const * pRight,std::vector< OUString> &_rRightColumns)
268 const sal_Int32 nCount = pRight->n_children();
269 _rRightColumns.reserve(nCount);
270 for (sal_Int32 i=0; i < nCount; ++i)
271 _rRightColumns.push_back(pRight->get_text(i));
274 void OWizColumnSelect::createNewColumn( weld::TreeView* _pListbox,
275 OFieldDescription const * _pSrcField,
276 std::vector< OUString>& _rRightColumns,
277 const OUString& _sColumnName,
278 const OUString& _sExtraChars,
279 sal_Int32 _nMaxNameLen,
280 const ::comphelper::UStringMixEqual& _aCase)
282 OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase),
283 _sColumnName,
284 _sExtraChars,
285 _nMaxNameLen);
286 OFieldDescription* pNewField = new OFieldDescription(*_pSrcField);
287 pNewField->SetName(sConvertedName);
288 bool bNotConvert = true;
289 pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert));
290 if ( !m_pParent->supportsPrimaryKey() )
291 pNewField->SetPrimaryKey(false);
293 _pListbox->append(OUString::number(reinterpret_cast<sal_Int64>(pNewField)), sConvertedName);
294 _rRightColumns.push_back(sConvertedName);
296 if ( !bNotConvert )
297 m_pParent->showColumnTypeNotSupported(sConvertedName);
300 void OWizColumnSelect::moveColumn( weld::TreeView* _pRight,
301 weld::TreeView const * _pLeft,
302 std::vector< OUString>& _rRightColumns,
303 const OUString& _sColumnName,
304 const OUString& _sExtraChars,
305 sal_Int32 _nMaxNameLen,
306 const ::comphelper::UStringMixEqual& _aCase)
308 if(_pRight == m_xNewColumnNames.get())
310 // we copy the column into the new format for the dest
311 OFieldDescription* pSrcField = reinterpret_cast<OFieldDescription*>(_pLeft->get_id(_pLeft->find_text(_sColumnName)).toInt64());
312 createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase);
314 else
316 // find the new column in the dest name mapping to obtain the old column
317 OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
318 [&_aCase, &_sColumnName] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
319 return _aCase(nameMap.second, _sColumnName);
322 OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
323 if ( aIter == m_pParent->m_mNameMapping.end() )
324 return; // do nothing
325 const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
326 ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
327 if ( aSrcIter != rSrcColumns.end() )
329 // we need also the old position of this column to insert it back on that position again
330 const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
331 ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
332 OSL_ENSURE( aPos != rSrcVector.end(),"Invalid position for the iterator here!");
333 ODatabaseExport::TColumnVector::size_type nPos = (aPos - rSrcVector.begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - rSrcVector.begin()), _aCase);
335 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aSrcIter->second)));
336 const OUString& rStr = (*aIter).first;
337 _pRight->insert(nullptr, nPos, &rStr, &sId, nullptr, nullptr, false, nullptr);
338 _rRightColumns.push_back(rStr);
339 m_pParent->removeColumnNameFromNameMap(_sColumnName);
344 // Simply returning fields back to their original position is
345 // not enough. We need to take into account what fields have
346 // been removed earlier and adjust accordingly. Based on the
347 // algorithm employed in moveColumn().
348 sal_Int32 OWizColumnSelect::adjustColumnPosition(weld::TreeView const * _pLeft,
349 const OUString& _sColumnName,
350 ODatabaseExport::TColumnVector::size_type nCurrentPos,
351 const ::comphelper::UStringMixEqual& _aCase)
353 sal_Int32 nAdjustedPos = 0;
355 // if returning all entries to their original position,
356 // then there is no need to adjust the positions.
357 if (m_xColumns_LH->has_focus())
358 return nAdjustedPos;
360 const sal_Int32 nCount = _pLeft->n_children();
361 OUString sColumnString;
362 for(sal_Int32 i=0; i < nCount; ++i)
364 sColumnString = _pLeft->get_text(i);
365 if(_sColumnName != sColumnString)
367 // find the new column in the dest name mapping to obtain the old column
368 OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
369 [&_aCase, &sColumnString] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
370 return _aCase(nameMap.second, sColumnString);
373 OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
374 const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
375 ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
376 if ( aSrcIter != rSrcColumns.end() )
378 // we need also the old position of this column to insert it back on that position again
379 const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
380 ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
381 ODatabaseExport::TColumnVector::size_type nPos = aPos - rSrcVector.begin();
382 if( nPos < nCurrentPos)
384 nAdjustedPos++;
390 return nAdjustedPos;
393 void OWizColumnSelect::enableButtons()
395 bool bEntries = m_xNewColumnNames->n_children() != 0;
396 if (!bEntries)
397 m_pParent->m_mNameMapping.clear();
399 m_pParent->GetOKButton().set_sensitive(bEntries);
400 m_pParent->EnableNextButton(bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData);
403 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */