Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "WColumnSelect.hxx"
21 : #include "dbu_misc.hrc"
22 : #include <osl/diagnose.h>
23 : #include "WCopyTable.hxx"
24 : #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
25 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
26 : #include <com/sun/star/sdbcx/XAppend.hpp>
27 : #include "moduledbu.hxx"
28 : #include <com/sun/star/sdbc/DataType.hpp>
29 : #include <com/sun/star/sdbc/ColumnValue.hpp>
30 : #include <com/sun/star/sdb/application/CopyTableOperation.hpp>
31 : #include "dbustrings.hrc"
32 : #include <functional>
33 : #include <o3tl/compat_functional.hxx>
34 :
35 : using namespace ::com::sun::star::uno;
36 : using namespace ::com::sun::star::beans;
37 : using namespace ::com::sun::star::container;
38 : using namespace ::com::sun::star::sdbc;
39 : using namespace ::com::sun::star::sdbcx;
40 : using namespace dbaui;
41 :
42 : namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
43 :
44 0 : OUString OWizColumnSelect::GetTitle() const { return ModuleRes(STR_WIZ_COLUMN_SELECT_TITEL); }
45 :
46 0 : OWizardPage::OWizardPage(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription)
47 : : TabPage(pParent, rID, rUIXMLDescription)
48 : ,m_pParent(static_cast<OCopyTableWizard*>(pParent))
49 0 : ,m_bFirstTime(true)
50 : {
51 0 : }
52 :
53 : // OWizColumnSelect
54 0 : OWizColumnSelect::OWizColumnSelect( vcl::Window* pParent)
55 0 : :OWizardPage( pParent, "ApplyColPage", "dbaccess/ui/applycolpage.ui")
56 : {
57 0 : get(m_pOrgColumnNames, "from");
58 0 : get(m_pColumn_RH, "colrh");
59 0 : get(m_pColumns_RH, "colsrh");
60 0 : get(m_pColumn_LH, "collh");
61 0 : get(m_pColumns_LH, "colslh");
62 0 : get(m_pNewColumnNames, "to");
63 :
64 0 : Size aSize(approximate_char_width() * 30, GetTextHeight() * 40);
65 0 : m_pOrgColumnNames->set_width_request(aSize.Width());
66 0 : m_pOrgColumnNames->set_height_request(aSize.Height());
67 0 : m_pNewColumnNames->set_width_request(aSize.Width());
68 0 : m_pNewColumnNames->set_height_request(aSize.Height());
69 :
70 0 : m_pColumn_RH->SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl));
71 0 : m_pColumn_LH->SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl));
72 0 : m_pColumns_RH->SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl));
73 0 : m_pColumns_LH->SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl));
74 :
75 0 : m_pOrgColumnNames->EnableMultiSelection(true);
76 0 : m_pNewColumnNames->EnableMultiSelection(true);
77 :
78 0 : m_pOrgColumnNames->SetDoubleClickHdl(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
79 0 : m_pNewColumnNames->SetDoubleClickHdl(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
80 0 : }
81 :
82 0 : OWizColumnSelect::~OWizColumnSelect()
83 : {
84 0 : while ( m_pNewColumnNames->GetEntryCount() )
85 : {
86 0 : void* pData = m_pNewColumnNames->GetEntryData(0);
87 0 : if ( pData )
88 0 : delete static_cast<OFieldDescription*>(pData);
89 :
90 0 : m_pNewColumnNames->RemoveEntry(0);
91 : }
92 0 : m_pNewColumnNames->Clear();
93 0 : }
94 :
95 0 : void OWizColumnSelect::Reset()
96 : {
97 : // restore original state
98 0 : clearListBox(*m_pOrgColumnNames);
99 0 : clearListBox(*m_pNewColumnNames);
100 0 : m_pParent->m_mNameMapping.clear();
101 :
102 : // insert the source columns in the left listbox
103 0 : const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
104 0 : ODatabaseExport::TColumnVector::const_iterator aIter = rSrcColumns.begin();
105 0 : ODatabaseExport::TColumnVector::const_iterator aEnd = rSrcColumns.end();
106 :
107 0 : for(;aIter != aEnd;++aIter)
108 : {
109 0 : sal_uInt16 nPos = m_pOrgColumnNames->InsertEntry((*aIter)->first);
110 0 : m_pOrgColumnNames->SetEntryData(nPos,(*aIter)->second);
111 : }
112 :
113 0 : if(m_pOrgColumnNames->GetEntryCount())
114 0 : m_pOrgColumnNames->SelectEntryPos(0);
115 :
116 0 : m_bFirstTime = false;
117 0 : }
118 :
119 0 : void OWizColumnSelect::ActivatePage( )
120 : {
121 : // if there are no dest columns reset the left side with the origibnal columns
122 0 : if(m_pParent->getDestColumns().empty())
123 0 : Reset();
124 :
125 0 : clearListBox(*m_pNewColumnNames);
126 :
127 0 : const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
128 :
129 0 : ODatabaseExport::TColumnVector::const_iterator aIter = rDestColumns.begin();
130 0 : ODatabaseExport::TColumnVector::const_iterator aEnd = rDestColumns.end();
131 0 : for(;aIter != aEnd;++aIter)
132 : {
133 0 : sal_uInt16 nPos = m_pNewColumnNames->InsertEntry((*aIter)->first);
134 0 : m_pNewColumnNames->SetEntryData(nPos,new OFieldDescription(*((*aIter)->second)));
135 0 : m_pOrgColumnNames->RemoveEntry((*aIter)->first);
136 : }
137 0 : m_pParent->GetOKButton().Enable(m_pNewColumnNames->GetEntryCount() != 0);
138 0 : m_pParent->EnableButton(OCopyTableWizard::WIZARD_NEXT,m_pNewColumnNames->GetEntryCount() && m_pParent->getOperation() != CopyTableOperation::AppendData);
139 0 : m_pColumns_RH->GrabFocus();
140 0 : }
141 :
142 0 : bool OWizColumnSelect::LeavePage()
143 : {
144 :
145 0 : m_pParent->clearDestColumns();
146 :
147 0 : for(sal_uInt16 i=0 ; i< m_pNewColumnNames->GetEntryCount();++i)
148 : {
149 0 : OFieldDescription* pField = static_cast<OFieldDescription*>(m_pNewColumnNames->GetEntryData(i));
150 : OSL_ENSURE(pField,"The field information can not be null!");
151 0 : m_pParent->insertColumn(i,pField);
152 : }
153 :
154 0 : clearListBox(*m_pNewColumnNames);
155 :
156 0 : if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT
157 0 : || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH
158 : )
159 0 : return m_pParent->getDestColumns().size() != 0;
160 : else
161 0 : return true;
162 : }
163 :
164 0 : IMPL_LINK( OWizColumnSelect, ButtonClickHdl, Button *, pButton )
165 : {
166 0 : ListBox *pLeft = NULL;
167 0 : ListBox *pRight = NULL;
168 0 : bool bAll = false;
169 :
170 0 : if (pButton == m_pColumn_RH)
171 : {
172 0 : pLeft = m_pOrgColumnNames;
173 0 : pRight = m_pNewColumnNames;
174 : }
175 0 : else if(pButton == m_pColumn_LH)
176 : {
177 0 : pLeft = m_pNewColumnNames;
178 0 : pRight = m_pOrgColumnNames;
179 : }
180 0 : else if(pButton == m_pColumns_RH)
181 : {
182 0 : pLeft = m_pOrgColumnNames;
183 0 : pRight = m_pNewColumnNames;
184 0 : bAll = true;
185 : }
186 0 : else if(pButton == m_pColumns_LH)
187 : {
188 0 : pLeft = m_pNewColumnNames;
189 0 : pRight = m_pOrgColumnNames;
190 0 : bAll = true;
191 : }
192 :
193 0 : if (!pLeft || !pRight)
194 0 : return 0;
195 :
196 0 : Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
197 0 : OUString sExtraChars = xMetaData->getExtraNameCharacters();
198 0 : sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
199 :
200 0 : ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
201 0 : ::std::vector< OUString> aRightColumns;
202 0 : fillColumns(pRight,aRightColumns);
203 :
204 0 : if(!bAll)
205 : {
206 0 : for(sal_uInt16 i=0; i < pLeft->GetSelectEntryCount(); ++i)
207 0 : moveColumn(pRight,pLeft,aRightColumns,pLeft->GetSelectEntry(i),sExtraChars,nMaxNameLen,aCase);
208 :
209 0 : for(sal_uInt16 j=pLeft->GetSelectEntryCount(); j ; --j)
210 0 : pLeft->RemoveEntry(pLeft->GetSelectEntry(j-1));
211 : }
212 : else
213 : {
214 0 : sal_uInt16 nEntries = pLeft->GetEntryCount();
215 0 : for(sal_uInt16 i=0; i < nEntries; ++i)
216 0 : moveColumn(pRight,pLeft,aRightColumns,pLeft->GetEntry(i),sExtraChars,nMaxNameLen,aCase);
217 0 : for(sal_uInt16 j=pLeft->GetEntryCount(); j ; --j)
218 0 : pLeft->RemoveEntry(j-1);
219 : }
220 :
221 0 : enableButtons();
222 :
223 0 : if(m_pOrgColumnNames->GetEntryCount())
224 0 : m_pOrgColumnNames->SelectEntryPos(0);
225 :
226 0 : return 0;
227 : }
228 :
229 0 : IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, ListBox *, pListBox )
230 : {
231 : ListBox *pLeft,*pRight;
232 0 : if(pListBox == m_pOrgColumnNames)
233 : {
234 0 : pLeft = m_pOrgColumnNames;
235 0 : pRight = m_pNewColumnNames;
236 : }
237 : else
238 : {
239 0 : pRight = m_pOrgColumnNames;
240 0 : pLeft = m_pNewColumnNames;
241 : }
242 :
243 : // If database is able to process PrimaryKeys, set PrimaryKey
244 0 : Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
245 0 : OUString sExtraChars = xMetaData->getExtraNameCharacters();
246 0 : sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
247 :
248 0 : ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
249 0 : ::std::vector< OUString> aRightColumns;
250 0 : fillColumns(pRight,aRightColumns);
251 :
252 0 : for(sal_uInt16 i=0; i < pLeft->GetSelectEntryCount(); ++i)
253 0 : moveColumn(pRight,pLeft,aRightColumns,pLeft->GetSelectEntry(i),sExtraChars,nMaxNameLen,aCase);
254 0 : for(sal_uInt16 j=pLeft->GetSelectEntryCount(); j ; --j)
255 0 : pLeft->RemoveEntry(pLeft->GetSelectEntry(j-1));
256 :
257 0 : enableButtons();
258 0 : return 0;
259 : }
260 :
261 0 : void OWizColumnSelect::clearListBox(ListBox& _rListBox)
262 : {
263 0 : while(_rListBox.GetEntryCount())
264 0 : _rListBox.RemoveEntry(0);
265 0 : _rListBox.Clear();
266 0 : }
267 :
268 0 : void OWizColumnSelect::fillColumns(ListBox* pRight,::std::vector< OUString> &_rRightColumns)
269 : {
270 0 : sal_uInt16 nCount = pRight->GetEntryCount();
271 0 : _rRightColumns.reserve(nCount);
272 0 : for(sal_uInt16 i=0; i < nCount;++i)
273 0 : _rRightColumns.push_back(pRight->GetEntry(i));
274 0 : }
275 :
276 0 : void OWizColumnSelect::createNewColumn( ListBox* _pListbox,
277 : OFieldDescription* _pSrcField,
278 : ::std::vector< OUString>& _rRightColumns,
279 : const OUString& _sColumnName,
280 : const OUString& _sExtraChars,
281 : sal_Int32 _nMaxNameLen,
282 : const ::comphelper::UStringMixEqual& _aCase)
283 : {
284 : OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase),
285 : _sColumnName,
286 : _sExtraChars,
287 0 : _nMaxNameLen);
288 0 : OFieldDescription* pNewField = new OFieldDescription(*_pSrcField);
289 0 : pNewField->SetName(sConvertedName);
290 0 : bool bNotConvert = true;
291 0 : pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert));
292 0 : if ( !m_pParent->supportsPrimaryKey() )
293 0 : pNewField->SetPrimaryKey(false);
294 :
295 0 : _pListbox->SetEntryData(_pListbox->InsertEntry(sConvertedName),pNewField);
296 0 : _rRightColumns.push_back(sConvertedName);
297 :
298 0 : if ( !bNotConvert )
299 0 : m_pParent->showColumnTypeNotSupported(sConvertedName);
300 0 : }
301 :
302 0 : void OWizColumnSelect::moveColumn( ListBox* _pRight,
303 : ListBox* _pLeft,
304 : ::std::vector< OUString>& _rRightColumns,
305 : const OUString& _sColumnName,
306 : const OUString& _sExtraChars,
307 : sal_Int32 _nMaxNameLen,
308 : const ::comphelper::UStringMixEqual& _aCase)
309 : {
310 0 : if(_pRight == m_pNewColumnNames)
311 : {
312 : // we copy the column into the new format for the dest
313 0 : OFieldDescription* pSrcField = static_cast<OFieldDescription*>(_pLeft->GetEntryData(_pLeft->GetEntryPos(OUString(_sColumnName))));
314 0 : createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase);
315 : }
316 : else
317 : {
318 : // find the new column in the dest name mapping to obtain the old column
319 : OCopyTableWizard::TNameMapping::iterator aIter = ::std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
320 : ::o3tl::compose1(
321 : ::std::bind2nd(_aCase, _sColumnName),
322 : ::o3tl::select2nd<OCopyTableWizard::TNameMapping::value_type>())
323 0 : );
324 :
325 : OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
326 0 : if ( aIter == m_pParent->m_mNameMapping.end() )
327 0 : return; // do nothing
328 0 : const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
329 0 : ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
330 0 : if ( aSrcIter != rSrcColumns.end() )
331 : {
332 : // we need also the old position of this column to insert it back on that position again
333 0 : const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
334 0 : ODatabaseExport::TColumnVector::const_iterator aPos = ::std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
335 : OSL_ENSURE( aPos != rSrcVector.end(),"Invalid position for the iterator here!");
336 0 : ODatabaseExport::TColumnVector::size_type nPos = (aPos - rSrcVector.begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - rSrcVector.begin()), _aCase);
337 :
338 0 : _pRight->SetEntryData( _pRight->InsertEntry( (*aIter).first, sal::static_int_cast< sal_uInt16 >(nPos)),aSrcIter->second );
339 0 : _rRightColumns.push_back((*aIter).first);
340 0 : m_pParent->removeColumnNameFromNameMap(_sColumnName);
341 : }
342 : }
343 : }
344 :
345 : // Simply returning fields back to their original position is
346 : // not enough. We need to take into acccount what fields have
347 : // been removed earlier and adjust accordingly. Based on the
348 : // algorithm employed in moveColumn().
349 0 : sal_uInt16 OWizColumnSelect::adjustColumnPosition( ListBox* _pLeft,
350 : const OUString& _sColumnName,
351 : ODatabaseExport::TColumnVector::size_type nCurrentPos,
352 : const ::comphelper::UStringMixEqual& _aCase)
353 : {
354 0 : sal_uInt16 nAdjustedPos = 0;
355 :
356 : // if returning all entries to their original position,
357 : // then there is no need to adjust the positions.
358 0 : if (m_pColumns_LH->HasFocus())
359 0 : return nAdjustedPos;
360 :
361 0 : sal_uInt16 nCount = _pLeft->GetEntryCount();
362 0 : OUString sColumnString;
363 0 : for(sal_uInt16 i=0; i < nCount; ++i)
364 : {
365 0 : sColumnString = _pLeft->GetEntry(i);
366 0 : if(_sColumnName != sColumnString)
367 : {
368 : // find the new column in the dest name mapping to obtain the old column
369 : OCopyTableWizard::TNameMapping::iterator aIter = ::std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
370 : ::o3tl::compose1(
371 : ::std::bind2nd(_aCase, sColumnString),
372 : ::o3tl::select2nd<OCopyTableWizard::TNameMapping::value_type>())
373 0 : );
374 :
375 : OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
376 0 : const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
377 0 : ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
378 0 : if ( aSrcIter != rSrcColumns.end() )
379 : {
380 : // we need also the old position of this column to insert it back on that position again
381 0 : const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
382 0 : ODatabaseExport::TColumnVector::const_iterator aPos = ::std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
383 0 : ODatabaseExport::TColumnVector::size_type nPos = aPos - rSrcVector.begin();
384 0 : if( nPos < nCurrentPos)
385 : {
386 0 : nAdjustedPos++;
387 : }
388 : }
389 : }
390 : }
391 :
392 0 : return nAdjustedPos;
393 : }
394 :
395 0 : void OWizColumnSelect::enableButtons()
396 : {
397 0 : bool bEntries = m_pNewColumnNames->GetEntryCount() != 0;
398 0 : if(!bEntries)
399 0 : m_pParent->m_mNameMapping.clear();
400 :
401 0 : m_pParent->GetOKButton().Enable(bEntries);
402 0 : m_pParent->EnableButton(OCopyTableWizard::WIZARD_NEXT,bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData);
403 72 : }
404 :
405 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|