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