1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_dbaccess.hxx" 26 27 #ifndef DBAUI_WIZ_COLUMNSELECT_HXX 28 #include "WColumnSelect.hxx" 29 #endif 30 #ifndef _DBU_MISC_HRC_ 31 #include "dbu_misc.hrc" 32 #endif 33 #ifndef _TOOLS_DEBUG_HXX 34 #include <tools/debug.hxx> 35 #endif 36 #ifndef DBAUI_WIZARD_PAGES_HRC 37 #include "WizardPages.hrc" 38 #endif 39 #ifndef DBAUI_WIZ_COPYTABLEDIALOG_HXX 40 #include "WCopyTable.hxx" 41 #endif 42 #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ 43 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> 44 #endif 45 #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ 46 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 47 #endif 48 #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_ 49 #include <com/sun/star/sdbcx/XAppend.hpp> 50 #endif 51 #ifndef _DBAUI_MODULE_DBU_HXX_ 52 #include "moduledbu.hxx" 53 #endif 54 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ 55 #include <com/sun/star/sdbc/DataType.hpp> 56 #endif 57 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ 58 #include <com/sun/star/sdbc/ColumnValue.hpp> 59 #endif 60 #ifndef _COM_SUN_STAR_SDB_APPLICATION_COPYTABLEOPERATION_HPP_ 61 #include <com/sun/star/sdb/application/CopyTableOperation.hpp> 62 #endif 63 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC 64 #include "dbustrings.hrc" 65 #endif 66 #include <functional> 67 68 using namespace ::com::sun::star::uno; 69 using namespace ::com::sun::star::beans; 70 using namespace ::com::sun::star::container; 71 using namespace ::com::sun::star::sdbc; 72 using namespace ::com::sun::star::sdbcx; 73 using namespace dbaui; 74 75 namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation; 76 77 // ----------------------------------------------------------------------- 78 String OWizColumnSelect::GetTitle() const { return String(ModuleRes(STR_WIZ_COLUMN_SELECT_TITEL)); } 79 // ----------------------------------------------------------------------------- 80 OWizardPage::OWizardPage( Window* pParent, const ResId& rResId ) 81 : TabPage(pParent,rResId) 82 ,m_pParent(static_cast<OCopyTableWizard*>(pParent)) 83 ,m_bFirstTime(sal_True) 84 { 85 } 86 //======================================================================== 87 // OWizColumnSelect 88 DBG_NAME(OWizColumnSelect); 89 //======================================================================== 90 OWizColumnSelect::OWizColumnSelect( Window* pParent) 91 :OWizardPage( pParent, ModuleRes( TAB_WIZ_COLUMN_SELECT )) 92 ,m_flColumns( this, ModuleRes( FL_COLUMN_SELECT ) ) 93 ,m_lbOrgColumnNames( this, ModuleRes( LB_ORG_COLUMN_NAMES ) ) 94 ,m_ibColumn_RH( this, ModuleRes( IB_COLUMN_RH ) ) 95 ,m_ibColumns_RH( this, ModuleRes( IB_COLUMNS_RH ) ) 96 ,m_ibColumn_LH( this, ModuleRes( IB_COLUMN_LH ) ) 97 ,m_ibColumns_LH( this, ModuleRes( IB_COLUMNS_LH ) ) 98 ,m_lbNewColumnNames( this, ModuleRes( LB_NEW_COLUMN_NAMES ) ) 99 { 100 DBG_CTOR(OWizColumnSelect,NULL); 101 m_ibColumn_RH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 102 m_ibColumn_LH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 103 m_ibColumns_RH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 104 m_ibColumns_LH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 105 106 m_lbOrgColumnNames.EnableMultiSelection(sal_True); 107 m_lbNewColumnNames.EnableMultiSelection(sal_True); 108 109 m_lbOrgColumnNames.SetDoubleClickHdl(LINK(this,OWizColumnSelect,ListDoubleClickHdl)); 110 m_lbNewColumnNames.SetDoubleClickHdl(LINK(this,OWizColumnSelect,ListDoubleClickHdl)); 111 FreeResource(); 112 } 113 // ----------------------------------------------------------------------- 114 OWizColumnSelect::~OWizColumnSelect() 115 { 116 DBG_DTOR(OWizColumnSelect,NULL); 117 while ( m_lbNewColumnNames.GetEntryCount() ) 118 { 119 void* pData = m_lbNewColumnNames.GetEntryData(0); 120 if ( pData ) 121 delete static_cast<OFieldDescription*>(pData); 122 123 m_lbNewColumnNames.RemoveEntry(0); 124 } 125 m_lbNewColumnNames.Clear(); 126 } 127 128 // ----------------------------------------------------------------------- 129 void OWizColumnSelect::Reset() 130 { 131 // urspr"unglichen zustand wiederherstellen 132 DBG_CHKTHIS(OWizColumnSelect,NULL); 133 134 clearListBox(m_lbOrgColumnNames); 135 clearListBox(m_lbNewColumnNames); 136 m_pParent->m_mNameMapping.clear(); 137 138 // insert the source columns in the left listbox 139 const ODatabaseExport::TColumnVector* pSrcColumns = m_pParent->getSrcVector(); 140 ODatabaseExport::TColumnVector::const_iterator aIter = pSrcColumns->begin(); 141 ODatabaseExport::TColumnVector::const_iterator aEnd = pSrcColumns->end(); 142 143 for(;aIter != aEnd;++aIter) 144 { 145 sal_uInt16 nPos = m_lbOrgColumnNames.InsertEntry((*aIter)->first); 146 m_lbOrgColumnNames.SetEntryData(nPos,(*aIter)->second); 147 } 148 149 // m_pParent->clearDestColumns(); 150 151 if(m_lbOrgColumnNames.GetEntryCount()) 152 m_lbOrgColumnNames.SelectEntryPos(0); 153 154 m_bFirstTime = sal_False; 155 } 156 // ----------------------------------------------------------------------- 157 void OWizColumnSelect::ActivatePage( ) 158 { 159 DBG_CHKTHIS(OWizColumnSelect,NULL); 160 // if there are no dest columns reset the left side with the origibnal columns 161 if(m_pParent->getDestColumns()->size() == 0) 162 Reset(); 163 164 clearListBox(m_lbNewColumnNames); 165 166 const ODatabaseExport::TColumnVector* pDestColumns = m_pParent->getDestVector(); 167 168 ODatabaseExport::TColumnVector::const_iterator aIter = pDestColumns->begin(); 169 ODatabaseExport::TColumnVector::const_iterator aEnd = pDestColumns->end(); 170 for(;aIter != aEnd;++aIter) 171 { 172 sal_uInt16 nPos = m_lbNewColumnNames.InsertEntry((*aIter)->first); 173 m_lbNewColumnNames.SetEntryData(nPos,new OFieldDescription(*((*aIter)->second))); 174 m_lbOrgColumnNames.RemoveEntry((*aIter)->first); 175 } 176 m_pParent->GetOKButton().Enable(m_lbNewColumnNames.GetEntryCount() != 0); 177 m_pParent->EnableButton(OCopyTableWizard::WIZARD_NEXT,m_lbNewColumnNames.GetEntryCount() && m_pParent->getOperation() != CopyTableOperation::AppendData); 178 m_ibColumns_RH.GrabFocus(); 179 } 180 // ----------------------------------------------------------------------- 181 sal_Bool OWizColumnSelect::LeavePage() 182 { 183 DBG_CHKTHIS(OWizColumnSelect,NULL); 184 185 // m_pParent->getColumns()->clear(); 186 m_pParent->clearDestColumns(); 187 188 for(sal_uInt16 i=0 ; i< m_lbNewColumnNames.GetEntryCount();++i) 189 { 190 OFieldDescription* pField = static_cast<OFieldDescription*>(m_lbNewColumnNames.GetEntryData(i)); 191 OSL_ENSURE(pField,"The field information can not be null!"); 192 m_pParent->insertColumn(i,pField); 193 } 194 195 clearListBox(m_lbNewColumnNames); 196 197 198 if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT 199 || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH 200 ) 201 return m_pParent->getDestColumns()->size() != 0; 202 else 203 return sal_True; 204 } 205 // ----------------------------------------------------------------------- 206 IMPL_LINK( OWizColumnSelect, ButtonClickHdl, Button *, pButton ) 207 { 208 MultiListBox *pLeft = NULL; 209 MultiListBox *pRight = NULL; 210 sal_Bool bAll = sal_False; 211 212 if(pButton == &m_ibColumn_RH) 213 { 214 pLeft = &m_lbOrgColumnNames; 215 pRight = &m_lbNewColumnNames; 216 } 217 else if(pButton == &m_ibColumn_LH) 218 { 219 pLeft = &m_lbNewColumnNames; 220 pRight = &m_lbOrgColumnNames; 221 } 222 else if(pButton == &m_ibColumns_RH) 223 { 224 pLeft = &m_lbOrgColumnNames; 225 pRight = &m_lbNewColumnNames; 226 bAll = sal_True; 227 } 228 else if(pButton == &m_ibColumns_LH) 229 { 230 pLeft = &m_lbNewColumnNames; 231 pRight = &m_lbOrgColumnNames; 232 bAll = sal_True; 233 } 234 // else ???? 235 236 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() ); 237 ::rtl::OUString sExtraChars = xMetaData->getExtraNameCharacters(); 238 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength(); 239 240 ::comphelper::TStringMixEqualFunctor aCase(xMetaData->supportsMixedCaseQuotedIdentifiers()); 241 ::std::vector< ::rtl::OUString> aRightColumns; 242 fillColumns(pRight,aRightColumns); 243 244 String aColumnName; 245 if(!bAll) 246 { 247 for(sal_uInt16 i=0; i < pLeft->GetSelectEntryCount(); ++i) 248 moveColumn(pRight,pLeft,aRightColumns,pLeft->GetSelectEntry(i),sExtraChars,nMaxNameLen,aCase); 249 250 for(sal_uInt16 j=pLeft->GetSelectEntryCount(); j ; --j) 251 pLeft->RemoveEntry(pLeft->GetSelectEntry(j-1)); 252 } 253 else 254 { 255 sal_uInt16 nEntries = pLeft->GetEntryCount(); 256 for(sal_uInt16 i=0; i < nEntries; ++i) 257 moveColumn(pRight,pLeft,aRightColumns,pLeft->GetEntry(i),sExtraChars,nMaxNameLen,aCase); 258 for(sal_uInt16 j=pLeft->GetEntryCount(); j ; --j) 259 pLeft->RemoveEntry(j-1); 260 } 261 262 enableButtons(); 263 264 if(m_lbOrgColumnNames.GetEntryCount()) 265 m_lbOrgColumnNames.SelectEntryPos(0); 266 267 return 0; 268 } 269 // ----------------------------------------------------------------------- 270 IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, MultiListBox *, pListBox ) 271 { 272 MultiListBox *pLeft,*pRight; 273 if(pListBox == &m_lbOrgColumnNames) 274 { 275 pLeft = &m_lbOrgColumnNames; 276 pRight = &m_lbNewColumnNames; 277 } 278 else 279 { 280 pRight = &m_lbOrgColumnNames; 281 pLeft = &m_lbNewColumnNames; 282 } 283 284 ////////////////////////////////////////////////////////////////////// 285 // Wenn Datenbank PrimaryKeys verarbeiten kann, PrimaryKey anlegen 286 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() ); 287 ::rtl::OUString sExtraChars = xMetaData->getExtraNameCharacters(); 288 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength(); 289 290 ::comphelper::TStringMixEqualFunctor aCase(xMetaData->supportsMixedCaseQuotedIdentifiers()); 291 ::std::vector< ::rtl::OUString> aRightColumns; 292 fillColumns(pRight,aRightColumns); 293 294 String aColumnName; 295 for(sal_uInt16 i=0; i < pLeft->GetSelectEntryCount(); ++i) 296 moveColumn(pRight,pLeft,aRightColumns,pLeft->GetSelectEntry(i),sExtraChars,nMaxNameLen,aCase); 297 for(sal_uInt16 j=pLeft->GetSelectEntryCount(); j ; --j) 298 pLeft->RemoveEntry(pLeft->GetSelectEntry(j-1)); 299 300 enableButtons(); 301 return 0; 302 } 303 // ----------------------------------------------------------------------------- 304 void OWizColumnSelect::clearListBox(MultiListBox& _rListBox) 305 { 306 while(_rListBox.GetEntryCount()) 307 _rListBox.RemoveEntry(0); 308 _rListBox.Clear(); 309 } 310 // ----------------------------------------------------------------------------- 311 void OWizColumnSelect::fillColumns(ListBox* pRight,::std::vector< ::rtl::OUString> &_rRightColumns) 312 { 313 sal_uInt16 nCount = pRight->GetEntryCount(); 314 _rRightColumns.reserve(nCount); 315 for(sal_uInt16 i=0; i < nCount;++i) 316 _rRightColumns.push_back(pRight->GetEntry(i)); 317 } 318 // ----------------------------------------------------------------------------- 319 void OWizColumnSelect::createNewColumn( ListBox* _pListbox, 320 OFieldDescription* _pSrcField, 321 ::std::vector< ::rtl::OUString>& _rRightColumns, 322 const ::rtl::OUString& _sColumnName, 323 const ::rtl::OUString& _sExtraChars, 324 sal_Int32 _nMaxNameLen, 325 const ::comphelper::TStringMixEqualFunctor& _aCase) 326 { 327 ::rtl::OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase), 328 _sColumnName, 329 _sExtraChars, 330 _nMaxNameLen); 331 OFieldDescription* pNewField = new OFieldDescription(*_pSrcField); 332 pNewField->SetName(sConvertedName); 333 sal_Bool bNotConvert = sal_True; 334 pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert)); 335 if ( !m_pParent->supportsPrimaryKey() ) 336 pNewField->SetPrimaryKey(sal_False); 337 338 _pListbox->SetEntryData(_pListbox->InsertEntry(sConvertedName),pNewField); 339 _rRightColumns.push_back(sConvertedName); 340 341 if ( !bNotConvert ) 342 m_pParent->showColumnTypeNotSupported(sConvertedName); 343 } 344 // ----------------------------------------------------------------------------- 345 void OWizColumnSelect::moveColumn( ListBox* _pRight, 346 ListBox* _pLeft, 347 ::std::vector< ::rtl::OUString>& _rRightColumns, 348 const ::rtl::OUString& _sColumnName, 349 const ::rtl::OUString& _sExtraChars, 350 sal_Int32 _nMaxNameLen, 351 const ::comphelper::TStringMixEqualFunctor& _aCase) 352 { 353 if(_pRight == &m_lbNewColumnNames) 354 { 355 // we copy the column into the new format for the dest 356 OFieldDescription* pSrcField = static_cast<OFieldDescription*>(_pLeft->GetEntryData(_pLeft->GetEntryPos(String(_sColumnName)))); 357 createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase); 358 } 359 else 360 { 361 // find the new column in the dest name mapping to obtain the old column 362 OCopyTableWizard::TNameMapping::iterator aIter = ::std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(), 363 ::std::compose1( 364 ::std::bind2nd(_aCase, _sColumnName), 365 ::std::select2nd<OCopyTableWizard::TNameMapping::value_type>()) 366 ); 367 368 DBG_ASSERT(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined"); 369 if ( aIter == m_pParent->m_mNameMapping.end() ) 370 return; // do nothing 371 const ODatabaseExport::TColumns* pSrcColumns = m_pParent->getSourceColumns(); 372 ODatabaseExport::TColumns::const_iterator aSrcIter = pSrcColumns->find((*aIter).first); 373 if ( aSrcIter != pSrcColumns->end() ) 374 { 375 // we need also the old position of this column to insert it back on that position again 376 const ODatabaseExport::TColumnVector* pSrcVector = m_pParent->getSrcVector(); 377 ODatabaseExport::TColumnVector::const_iterator aPos = ::std::find(pSrcVector->begin(),pSrcVector->end(),aSrcIter); 378 OSL_ENSURE( aPos != pSrcVector->end(),"Invalid position for the iterator here!"); 379 ODatabaseExport::TColumnVector::size_type nPos = (aPos - pSrcVector->begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - pSrcVector->begin()), _aCase); 380 381 _pRight->SetEntryData( _pRight->InsertEntry( (*aIter).first, sal::static_int_cast< sal_uInt16 >(nPos)),aSrcIter->second ); 382 _rRightColumns.push_back((*aIter).first); 383 m_pParent->removeColumnNameFromNameMap(_sColumnName); 384 } 385 } 386 } 387 // ----------------------------------------------------------------------------- 388 // Simply returning fields back to their original position is 389 // not enough. We need to take into acccount what fields have 390 // been removed earlier and adjust accordingly. Based on the 391 // algorithm employed in moveColumn(). 392 sal_uInt16 OWizColumnSelect::adjustColumnPosition( ListBox* _pLeft, 393 const ::rtl::OUString& _sColumnName, 394 ODatabaseExport::TColumnVector::size_type nCurrentPos, 395 const ::comphelper::TStringMixEqualFunctor& _aCase) 396 { 397 sal_uInt16 nAdjustedPos = 0; 398 399 // if returning all entries to their original position, 400 // then there is no need to adjust the positions. 401 if (m_ibColumns_LH.HasFocus()) 402 return nAdjustedPos; 403 404 sal_uInt16 nCount = _pLeft->GetEntryCount(); 405 ::rtl::OUString sColumnString; 406 for(sal_uInt16 i=0; i < nCount; ++i) 407 { 408 sColumnString = _pLeft->GetEntry(i); 409 if(_sColumnName != sColumnString) 410 { 411 // find the new column in the dest name mapping to obtain the old column 412 OCopyTableWizard::TNameMapping::iterator aIter = ::std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(), 413 ::std::compose1( 414 ::std::bind2nd(_aCase, sColumnString), 415 ::std::select2nd<OCopyTableWizard::TNameMapping::value_type>()) 416 ); 417 418 DBG_ASSERT(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined"); 419 const ODatabaseExport::TColumns* pSrcColumns = m_pParent->getSourceColumns(); 420 ODatabaseExport::TColumns::const_iterator aSrcIter = pSrcColumns->find((*aIter).first); 421 if ( aSrcIter != pSrcColumns->end() ) 422 { 423 // we need also the old position of this column to insert it back on that position again 424 const ODatabaseExport::TColumnVector* pSrcVector = m_pParent->getSrcVector(); 425 ODatabaseExport::TColumnVector::const_iterator aPos = ::std::find(pSrcVector->begin(),pSrcVector->end(),aSrcIter); 426 ODatabaseExport::TColumnVector::size_type nPos = aPos - pSrcVector->begin(); 427 if( nPos < nCurrentPos) 428 { 429 nAdjustedPos++; 430 } 431 } 432 } 433 } 434 435 return nAdjustedPos; 436 } 437 // ----------------------------------------------------------------------------- 438 void OWizColumnSelect::enableButtons() 439 { 440 sal_Bool bEntries = m_lbNewColumnNames.GetEntryCount() != 0; 441 if(!bEntries) 442 m_pParent->m_mNameMapping.clear(); 443 444 m_pParent->GetOKButton().Enable(bEntries); 445 m_pParent->EnableButton(OCopyTableWizard::WIZARD_NEXT,bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData); 446 } 447 // ----------------------------------------------------------------------------- 448 449