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 "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"
33 #include <o3tl/compat_functional.hxx>
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
;
42 namespace CopyTableOperation
= ::com::sun::star::sdb::application::CopyTableOperation
;
44 OUString
OWizColumnSelect::GetTitle() const { return ModuleRes(STR_WIZ_COLUMN_SELECT_TITEL
); }
46 OWizardPage::OWizardPage(vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
)
47 : TabPage(pParent
, rID
, rUIXMLDescription
)
48 ,m_pParent(static_cast<OCopyTableWizard
*>(pParent
))
53 OWizardPage::~OWizardPage()
58 void OWizardPage::dispose()
65 OWizColumnSelect::OWizColumnSelect( vcl::Window
* pParent
)
66 :OWizardPage( pParent
, "ApplyColPage", "dbaccess/ui/applycolpage.ui")
68 get(m_pOrgColumnNames
, "from");
69 get(m_pColumn_RH
, "colrh");
70 get(m_pColumns_RH
, "colsrh");
71 get(m_pColumn_LH
, "collh");
72 get(m_pColumns_LH
, "colslh");
73 get(m_pNewColumnNames
, "to");
75 Size
aSize(approximate_char_width() * 30, GetTextHeight() * 40);
76 m_pOrgColumnNames
->set_width_request(aSize
.Width());
77 m_pOrgColumnNames
->set_height_request(aSize
.Height());
78 m_pNewColumnNames
->set_width_request(aSize
.Width());
79 m_pNewColumnNames
->set_height_request(aSize
.Height());
81 m_pColumn_RH
->SetClickHdl(LINK(this,OWizColumnSelect
,ButtonClickHdl
));
82 m_pColumn_LH
->SetClickHdl(LINK(this,OWizColumnSelect
,ButtonClickHdl
));
83 m_pColumns_RH
->SetClickHdl(LINK(this,OWizColumnSelect
,ButtonClickHdl
));
84 m_pColumns_LH
->SetClickHdl(LINK(this,OWizColumnSelect
,ButtonClickHdl
));
86 m_pOrgColumnNames
->EnableMultiSelection(true);
87 m_pNewColumnNames
->EnableMultiSelection(true);
89 m_pOrgColumnNames
->SetDoubleClickHdl(LINK(this,OWizColumnSelect
,ListDoubleClickHdl
));
90 m_pNewColumnNames
->SetDoubleClickHdl(LINK(this,OWizColumnSelect
,ListDoubleClickHdl
));
93 OWizColumnSelect::~OWizColumnSelect()
98 void OWizColumnSelect::dispose()
100 while ( m_pNewColumnNames
->GetEntryCount() )
102 void* pData
= m_pNewColumnNames
->GetEntryData(0);
104 delete static_cast<OFieldDescription
*>(pData
);
106 m_pNewColumnNames
->RemoveEntry(0);
108 m_pNewColumnNames
->Clear();
109 m_pOrgColumnNames
.clear();
110 m_pColumn_RH
.clear();
111 m_pColumns_RH
.clear();
112 m_pColumn_LH
.clear();
113 m_pColumns_LH
.clear();
114 m_pNewColumnNames
.clear();
115 OWizardPage::dispose();
118 void OWizColumnSelect::Reset()
120 // restore original state
121 clearListBox(*m_pOrgColumnNames
);
122 clearListBox(*m_pNewColumnNames
);
123 m_pParent
->m_mNameMapping
.clear();
125 // insert the source columns in the left listbox
126 const ODatabaseExport::TColumnVector
& rSrcColumns
= m_pParent
->getSrcVector();
127 ODatabaseExport::TColumnVector::const_iterator aIter
= rSrcColumns
.begin();
128 ODatabaseExport::TColumnVector::const_iterator aEnd
= rSrcColumns
.end();
130 for(;aIter
!= aEnd
;++aIter
)
132 sal_uInt16 nPos
= m_pOrgColumnNames
->InsertEntry((*aIter
)->first
);
133 m_pOrgColumnNames
->SetEntryData(nPos
,(*aIter
)->second
);
136 if(m_pOrgColumnNames
->GetEntryCount())
137 m_pOrgColumnNames
->SelectEntryPos(0);
139 m_bFirstTime
= false;
142 void OWizColumnSelect::ActivatePage( )
144 // if there are no dest columns reset the left side with the origibnal columns
145 if(m_pParent
->getDestColumns().empty())
148 clearListBox(*m_pNewColumnNames
);
150 const ODatabaseExport::TColumnVector
& rDestColumns
= m_pParent
->getDestVector();
152 ODatabaseExport::TColumnVector::const_iterator aIter
= rDestColumns
.begin();
153 ODatabaseExport::TColumnVector::const_iterator aEnd
= rDestColumns
.end();
154 for(;aIter
!= aEnd
;++aIter
)
156 sal_uInt16 nPos
= m_pNewColumnNames
->InsertEntry((*aIter
)->first
);
157 m_pNewColumnNames
->SetEntryData(nPos
,new OFieldDescription(*((*aIter
)->second
)));
158 m_pOrgColumnNames
->RemoveEntry((*aIter
)->first
);
160 m_pParent
->GetOKButton().Enable(m_pNewColumnNames
->GetEntryCount() != 0);
161 m_pParent
->EnableButton(OCopyTableWizard::WIZARD_NEXT
,m_pNewColumnNames
->GetEntryCount() && m_pParent
->getOperation() != CopyTableOperation::AppendData
);
162 m_pColumns_RH
->GrabFocus();
165 bool OWizColumnSelect::LeavePage()
168 m_pParent
->clearDestColumns();
170 for(sal_uInt16 i
=0 ; i
< m_pNewColumnNames
->GetEntryCount();++i
)
172 OFieldDescription
* pField
= static_cast<OFieldDescription
*>(m_pNewColumnNames
->GetEntryData(i
));
173 OSL_ENSURE(pField
,"The field information can not be null!");
174 m_pParent
->insertColumn(i
,pField
);
177 clearListBox(*m_pNewColumnNames
);
179 if ( m_pParent
->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT
180 || m_pParent
->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH
182 return m_pParent
->getDestColumns().size() != 0;
187 IMPL_LINK( OWizColumnSelect
, ButtonClickHdl
, Button
*, pButton
)
189 ListBox
*pLeft
= NULL
;
190 ListBox
*pRight
= NULL
;
193 if (pButton
== m_pColumn_RH
)
195 pLeft
= m_pOrgColumnNames
;
196 pRight
= m_pNewColumnNames
;
198 else if(pButton
== m_pColumn_LH
)
200 pLeft
= m_pNewColumnNames
;
201 pRight
= m_pOrgColumnNames
;
203 else if(pButton
== m_pColumns_RH
)
205 pLeft
= m_pOrgColumnNames
;
206 pRight
= m_pNewColumnNames
;
209 else if(pButton
== m_pColumns_LH
)
211 pLeft
= m_pNewColumnNames
;
212 pRight
= m_pOrgColumnNames
;
216 if (!pLeft
|| !pRight
)
219 Reference
< XDatabaseMetaData
> xMetaData( m_pParent
->m_xDestConnection
->getMetaData() );
220 OUString sExtraChars
= xMetaData
->getExtraNameCharacters();
221 sal_Int32 nMaxNameLen
= m_pParent
->getMaxColumnNameLength();
223 ::comphelper::UStringMixEqual
aCase(xMetaData
->supportsMixedCaseQuotedIdentifiers());
224 ::std::vector
< OUString
> aRightColumns
;
225 fillColumns(pRight
,aRightColumns
);
229 for(sal_uInt16 i
=0; i
< pLeft
->GetSelectEntryCount(); ++i
)
230 moveColumn(pRight
,pLeft
,aRightColumns
,pLeft
->GetSelectEntry(i
),sExtraChars
,nMaxNameLen
,aCase
);
232 for(sal_uInt16 j
=pLeft
->GetSelectEntryCount(); j
; --j
)
233 pLeft
->RemoveEntry(pLeft
->GetSelectEntry(j
-1));
237 sal_uInt16 nEntries
= pLeft
->GetEntryCount();
238 for(sal_uInt16 i
=0; i
< nEntries
; ++i
)
239 moveColumn(pRight
,pLeft
,aRightColumns
,pLeft
->GetEntry(i
),sExtraChars
,nMaxNameLen
,aCase
);
240 for(sal_uInt16 j
=pLeft
->GetEntryCount(); j
; --j
)
241 pLeft
->RemoveEntry(j
-1);
246 if(m_pOrgColumnNames
->GetEntryCount())
247 m_pOrgColumnNames
->SelectEntryPos(0);
252 IMPL_LINK( OWizColumnSelect
, ListDoubleClickHdl
, ListBox
*, pListBox
)
254 ListBox
*pLeft
,*pRight
;
255 if(pListBox
== m_pOrgColumnNames
)
257 pLeft
= m_pOrgColumnNames
;
258 pRight
= m_pNewColumnNames
;
262 pRight
= m_pOrgColumnNames
;
263 pLeft
= m_pNewColumnNames
;
266 // If database is able to process PrimaryKeys, set PrimaryKey
267 Reference
< XDatabaseMetaData
> xMetaData( m_pParent
->m_xDestConnection
->getMetaData() );
268 OUString sExtraChars
= xMetaData
->getExtraNameCharacters();
269 sal_Int32 nMaxNameLen
= m_pParent
->getMaxColumnNameLength();
271 ::comphelper::UStringMixEqual
aCase(xMetaData
->supportsMixedCaseQuotedIdentifiers());
272 ::std::vector
< OUString
> aRightColumns
;
273 fillColumns(pRight
,aRightColumns
);
275 for(sal_uInt16 i
=0; i
< pLeft
->GetSelectEntryCount(); ++i
)
276 moveColumn(pRight
,pLeft
,aRightColumns
,pLeft
->GetSelectEntry(i
),sExtraChars
,nMaxNameLen
,aCase
);
277 for(sal_uInt16 j
=pLeft
->GetSelectEntryCount(); j
; --j
)
278 pLeft
->RemoveEntry(pLeft
->GetSelectEntry(j
-1));
284 void OWizColumnSelect::clearListBox(ListBox
& _rListBox
)
286 while(_rListBox
.GetEntryCount())
287 _rListBox
.RemoveEntry(0);
291 void OWizColumnSelect::fillColumns(ListBox
* pRight
,::std::vector
< OUString
> &_rRightColumns
)
293 sal_uInt16 nCount
= pRight
->GetEntryCount();
294 _rRightColumns
.reserve(nCount
);
295 for(sal_uInt16 i
=0; i
< nCount
;++i
)
296 _rRightColumns
.push_back(pRight
->GetEntry(i
));
299 void OWizColumnSelect::createNewColumn( ListBox
* _pListbox
,
300 OFieldDescription
* _pSrcField
,
301 ::std::vector
< OUString
>& _rRightColumns
,
302 const OUString
& _sColumnName
,
303 const OUString
& _sExtraChars
,
304 sal_Int32 _nMaxNameLen
,
305 const ::comphelper::UStringMixEqual
& _aCase
)
307 OUString sConvertedName
= m_pParent
->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns
,_aCase
),
311 OFieldDescription
* pNewField
= new OFieldDescription(*_pSrcField
);
312 pNewField
->SetName(sConvertedName
);
313 bool bNotConvert
= true;
314 pNewField
->SetType(m_pParent
->convertType(_pSrcField
->getSpecialTypeInfo(),bNotConvert
));
315 if ( !m_pParent
->supportsPrimaryKey() )
316 pNewField
->SetPrimaryKey(false);
318 _pListbox
->SetEntryData(_pListbox
->InsertEntry(sConvertedName
),pNewField
);
319 _rRightColumns
.push_back(sConvertedName
);
322 m_pParent
->showColumnTypeNotSupported(sConvertedName
);
325 void OWizColumnSelect::moveColumn( ListBox
* _pRight
,
327 ::std::vector
< OUString
>& _rRightColumns
,
328 const OUString
& _sColumnName
,
329 const OUString
& _sExtraChars
,
330 sal_Int32 _nMaxNameLen
,
331 const ::comphelper::UStringMixEqual
& _aCase
)
333 if(_pRight
== m_pNewColumnNames
)
335 // we copy the column into the new format for the dest
336 OFieldDescription
* pSrcField
= static_cast<OFieldDescription
*>(_pLeft
->GetEntryData(_pLeft
->GetEntryPos(OUString(_sColumnName
))));
337 createNewColumn(_pRight
,pSrcField
,_rRightColumns
,_sColumnName
,_sExtraChars
,_nMaxNameLen
,_aCase
);
341 // find the new column in the dest name mapping to obtain the old column
342 OCopyTableWizard::TNameMapping::iterator aIter
= ::std::find_if(m_pParent
->m_mNameMapping
.begin(),m_pParent
->m_mNameMapping
.end(),
344 ::std::bind2nd(_aCase
, _sColumnName
),
345 ::o3tl::select2nd
<OCopyTableWizard::TNameMapping::value_type
>())
348 OSL_ENSURE(aIter
!= m_pParent
->m_mNameMapping
.end(),"Column must be defined");
349 if ( aIter
== m_pParent
->m_mNameMapping
.end() )
350 return; // do nothing
351 const ODatabaseExport::TColumns
& rSrcColumns
= m_pParent
->getSourceColumns();
352 ODatabaseExport::TColumns::const_iterator aSrcIter
= rSrcColumns
.find((*aIter
).first
);
353 if ( aSrcIter
!= rSrcColumns
.end() )
355 // we need also the old position of this column to insert it back on that position again
356 const ODatabaseExport::TColumnVector
& rSrcVector
= m_pParent
->getSrcVector();
357 ODatabaseExport::TColumnVector::const_iterator aPos
= ::std::find(rSrcVector
.begin(), rSrcVector
.end(), aSrcIter
);
358 OSL_ENSURE( aPos
!= rSrcVector
.end(),"Invalid position for the iterator here!");
359 ODatabaseExport::TColumnVector::size_type nPos
= (aPos
- rSrcVector
.begin()) - adjustColumnPosition(_pLeft
, _sColumnName
, (aPos
- rSrcVector
.begin()), _aCase
);
361 _pRight
->SetEntryData( _pRight
->InsertEntry( (*aIter
).first
, sal::static_int_cast
< sal_uInt16
>(nPos
)),aSrcIter
->second
);
362 _rRightColumns
.push_back((*aIter
).first
);
363 m_pParent
->removeColumnNameFromNameMap(_sColumnName
);
368 // Simply returning fields back to their original position is
369 // not enough. We need to take into acccount what fields have
370 // been removed earlier and adjust accordingly. Based on the
371 // algorithm employed in moveColumn().
372 sal_uInt16
OWizColumnSelect::adjustColumnPosition( ListBox
* _pLeft
,
373 const OUString
& _sColumnName
,
374 ODatabaseExport::TColumnVector::size_type nCurrentPos
,
375 const ::comphelper::UStringMixEqual
& _aCase
)
377 sal_uInt16 nAdjustedPos
= 0;
379 // if returning all entries to their original position,
380 // then there is no need to adjust the positions.
381 if (m_pColumns_LH
->HasFocus())
384 sal_uInt16 nCount
= _pLeft
->GetEntryCount();
385 OUString sColumnString
;
386 for(sal_uInt16 i
=0; i
< nCount
; ++i
)
388 sColumnString
= _pLeft
->GetEntry(i
);
389 if(_sColumnName
!= sColumnString
)
391 // find the new column in the dest name mapping to obtain the old column
392 OCopyTableWizard::TNameMapping::iterator aIter
= ::std::find_if(m_pParent
->m_mNameMapping
.begin(),m_pParent
->m_mNameMapping
.end(),
394 ::std::bind2nd(_aCase
, sColumnString
),
395 ::o3tl::select2nd
<OCopyTableWizard::TNameMapping::value_type
>())
398 OSL_ENSURE(aIter
!= m_pParent
->m_mNameMapping
.end(),"Column must be defined");
399 const ODatabaseExport::TColumns
& rSrcColumns
= m_pParent
->getSourceColumns();
400 ODatabaseExport::TColumns::const_iterator aSrcIter
= rSrcColumns
.find((*aIter
).first
);
401 if ( aSrcIter
!= rSrcColumns
.end() )
403 // we need also the old position of this column to insert it back on that position again
404 const ODatabaseExport::TColumnVector
& rSrcVector
= m_pParent
->getSrcVector();
405 ODatabaseExport::TColumnVector::const_iterator aPos
= ::std::find(rSrcVector
.begin(), rSrcVector
.end(), aSrcIter
);
406 ODatabaseExport::TColumnVector::size_type nPos
= aPos
- rSrcVector
.begin();
407 if( nPos
< nCurrentPos
)
418 void OWizColumnSelect::enableButtons()
420 bool bEntries
= m_pNewColumnNames
->GetEntryCount() != 0;
422 m_pParent
->m_mNameMapping
.clear();
424 m_pParent
->GetOKButton().Enable(bEntries
);
425 m_pParent
->EnableButton(OCopyTableWizard::WIZARD_NEXT
,bEntries
&& m_pParent
->getOperation() != CopyTableOperation::AppendData
);
428 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */