1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_dbaccess.hxx" 30 31 #ifndef _DBAUI_DBFINDEX_HXX_ 32 #include "dbfindex.hxx" 33 #endif 34 35 #ifndef _CONFIG_HXX 36 #include <tools/config.hxx> 37 #endif 38 #ifndef _SFXAPP_HXX //autogen 39 #include <sfx2/app.hxx> 40 #endif 41 #ifndef _DBAUI_MODULE_DBU_HXX_ 42 #include "moduledbu.hxx" 43 #endif 44 #ifndef _DBU_DLG_HRC_ 45 #include "dbu_dlg.hrc" 46 #endif 47 #ifndef _DBAUI_DBF_INDEXES_HRC_ 48 #include "dbfindex.hrc" 49 #endif 50 #ifndef _TOOLS_DEBUG_HXX 51 #include <tools/debug.hxx> 52 #endif 53 #ifndef _UNOTOOLS_LOCALFILEHELPER_HXX 54 #include <unotools/localfilehelper.hxx> 55 #endif 56 #ifndef _URLOBJ_HXX 57 #include <tools/urlobj.hxx> 58 #endif 59 #ifndef INCLUDED_SVTOOLS_PATHOPTIONS_HXX 60 #include <unotools/pathoptions.hxx> 61 #endif 62 #ifndef _UCBHELPER_CONTENT_HXX 63 #include <ucbhelper/content.hxx> 64 #endif 65 #ifndef SVTOOLS_FILENOTATION_HXX_ 66 #include <svl/filenotation.hxx> 67 #endif 68 69 70 //......................................................................... 71 namespace dbaui 72 { 73 //......................................................................... 74 75 using namespace ::com::sun::star::uno; 76 using namespace ::com::sun::star::ucb; 77 using namespace ::svt; 78 79 const ByteString aGroupIdent("dBase III"); 80 81 ////////////////////////////////////////////////////////////////////////// 82 // Klasse ODbaseIndexDialog 83 DBG_NAME(ODbaseIndexDialog) 84 //------------------------------------------------------------------------- 85 ODbaseIndexDialog::ODbaseIndexDialog( Window * pParent, String aDataSrcName ) 86 : ModalDialog( pParent, ModuleRes(DLG_DBASE_INDEXES) ), 87 aPB_OK( this, ModuleRes( PB_OK ) ), 88 aPB_CANCEL( this, ModuleRes( PB_CANCEL ) ), 89 aPB_HELP( this, ModuleRes( PB_HELP ) ), 90 m_FT_Tables( this, ModuleRes( FT_TABLES ) ), 91 aCB_Tables( this, ModuleRes( CB_TABLES ) ), 92 m_FL_Indexes( this, ModuleRes( FL_INDEXES ) ), 93 m_FT_TableIndexes( this, ModuleRes( FT_TABLEINDEXES ) ), 94 aLB_TableIndexes( this, ModuleRes( LB_TABLEINDEXES ) ), 95 m_FT_AllIndexes( this, ModuleRes( FT_ALLINDEXES ) ), 96 aLB_FreeIndexes( this, ModuleRes( LB_FREEINDEXES ) ), 97 aIB_Add( this, ModuleRes( IB_ADD ) ), 98 aIB_Remove( this, ModuleRes( IB_REMOVE ) ), 99 aIB_AddAll( this, ModuleRes( IB_ADDALL ) ), 100 aIB_RemoveAll( this, ModuleRes( IB_REMOVEALL ) ), 101 m_aDSN(aDataSrcName), 102 m_bCaseSensitiv(sal_True) 103 { 104 DBG_CTOR(ODbaseIndexDialog,NULL); 105 106 aCB_Tables.SetSelectHdl( LINK(this, ODbaseIndexDialog, TableSelectHdl) ); 107 aIB_Add.SetClickHdl( LINK(this, ODbaseIndexDialog, AddClickHdl) ); 108 aIB_Remove.SetClickHdl( LINK(this, ODbaseIndexDialog, RemoveClickHdl) ); 109 aIB_AddAll.SetClickHdl( LINK(this, ODbaseIndexDialog, AddAllClickHdl) ); 110 aIB_RemoveAll.SetClickHdl( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) ); 111 aPB_OK.SetClickHdl( LINK(this, ODbaseIndexDialog, OKClickHdl) ); 112 113 aLB_FreeIndexes.SetSelectHdl( LINK(this, ODbaseIndexDialog, OnListEntrySelected) ); 114 aLB_TableIndexes.SetSelectHdl( LINK(this, ODbaseIndexDialog, OnListEntrySelected) ); 115 116 aCB_Tables.SetDropDownLineCount(8); 117 Init(); 118 SetCtrls(); 119 FreeResource(); 120 121 // set Hi contrast bitmaps 122 aIB_Add.SetModeImage( ModuleRes(IMG_ONE_LEFT_H),BMP_COLOR_HIGHCONTRAST); 123 aIB_AddAll.SetModeImage( ModuleRes(IMG_ALL_LEFT_H),BMP_COLOR_HIGHCONTRAST); 124 aIB_Remove.SetModeImage( ModuleRes(IMG_ONE_RIGHT_H),BMP_COLOR_HIGHCONTRAST); 125 aIB_RemoveAll.SetModeImage( ModuleRes(IMG_ALL_RIGHT_H),BMP_COLOR_HIGHCONTRAST); 126 } 127 128 //------------------------------------------------------------------------- 129 ODbaseIndexDialog::~ODbaseIndexDialog() 130 { 131 132 DBG_DTOR(ODbaseIndexDialog,NULL); 133 } 134 135 //------------------------------------------------------------------------- 136 sal_Bool ODbaseIndexDialog::GetTable(const String& _rName, TableInfoListIterator& _rPosition) 137 { 138 for ( _rPosition = m_aTableInfoList.begin(); 139 _rPosition != m_aTableInfoList.end(); 140 ++_rPosition 141 ) 142 { 143 if (m_bCaseSensitiv) 144 { 145 if (_rPosition->aTableName.Equals(_rName)) 146 return sal_True; 147 } 148 else 149 { 150 if (_rPosition->aTableName.EqualsIgnoreCaseAscii(_rName)) 151 return sal_True; 152 } 153 } 154 return sal_False; 155 } 156 157 //------------------------------------------------------------------------- 158 void ODbaseIndexDialog::checkButtons() 159 { 160 aIB_Add.Enable(0 != aLB_FreeIndexes.GetSelectEntryCount()); 161 aIB_AddAll.Enable(0 != aLB_FreeIndexes.GetEntryCount()); 162 163 aIB_Remove.Enable(0 != aLB_TableIndexes.GetSelectEntryCount()); 164 aIB_RemoveAll.Enable(0 != aLB_TableIndexes.GetEntryCount()); 165 } 166 167 //------------------------------------------------------------------------- 168 OTableIndex ODbaseIndexDialog::implRemoveIndex(const String& _rName, TableIndexList& _rList, ListBox& _rDisplay, sal_Bool _bMustExist) 169 { 170 OTableIndex aReturn; 171 172 sal_Int32 nPos = 0; 173 174 TableIndexListIterator aSearch; 175 for ( aSearch = _rList.begin(); 176 aSearch != _rList.end(); 177 ++aSearch, ++nPos 178 ) 179 { 180 if ( m_bCaseSensitiv ? aSearch->GetIndexFileName().Equals(_rName) : aSearch->GetIndexFileName().EqualsIgnoreCaseAscii(_rName) ) 181 { 182 aReturn = *aSearch; 183 184 _rList.erase(aSearch); 185 _rDisplay.RemoveEntry( _rName ); 186 187 // adjust selection if necessary 188 if ((sal_uInt32)nPos == _rList.size()) 189 _rDisplay.SelectEntryPos((sal_uInt16)nPos-1); 190 else 191 _rDisplay.SelectEntryPos((sal_uInt16)nPos); 192 193 break; 194 } 195 } 196 197 (void)_bMustExist; 198 DBG_ASSERT(!_bMustExist || (aSearch != _rList.end()), "ODbaseIndexDialog::implRemoveIndex : did not find the index!"); 199 return aReturn; 200 } 201 202 //------------------------------------------------------------------------- 203 void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, ListBox& _rDisplay) 204 { 205 _rList.push_front( _rIndex ); 206 _rDisplay.InsertEntry( _rIndex.GetIndexFileName() ); 207 _rDisplay.SelectEntryPos(0); 208 } 209 210 //------------------------------------------------------------------------- 211 OTableIndex ODbaseIndexDialog::RemoveTableIndex( const String& _rTableName, const String& _rIndexName, sal_Bool _bMustExist ) 212 { 213 OTableIndex aReturn; 214 215 // does the table exist ? 216 TableInfoListIterator aTablePos; 217 if (!GetTable(_rTableName, aTablePos)) 218 return aReturn; 219 220 return implRemoveIndex(_rIndexName, aTablePos->aIndexList, aLB_TableIndexes, _bMustExist); 221 } 222 223 //------------------------------------------------------------------------- 224 void ODbaseIndexDialog::InsertTableIndex( const String& _rTableName, const OTableIndex& _rIndex) 225 { 226 TableInfoListIterator aTablePos; 227 if (!GetTable(_rTableName, aTablePos)) 228 return; 229 230 implInsertIndex(_rIndex, aTablePos->aIndexList, aLB_TableIndexes); 231 } 232 233 //------------------------------------------------------------------------- 234 IMPL_LINK( ODbaseIndexDialog, OKClickHdl, PushButton*, /*pButton*/ ) 235 { 236 // let all tables write their INF file 237 238 for ( ConstTableInfoListIterator aLoop = m_aTableInfoList.begin(); 239 aLoop != m_aTableInfoList.end(); 240 ++aLoop 241 ) 242 aLoop->WriteInfFile(m_aDSN); 243 244 EndDialog(); 245 return 0; 246 } 247 248 //------------------------------------------------------------------------- 249 IMPL_LINK( ODbaseIndexDialog, AddClickHdl, PushButton*, /*pButton*/ ) 250 { 251 String aSelection = aLB_FreeIndexes.GetSelectEntry(); 252 String aTableName = aCB_Tables.GetText(); 253 OTableIndex aIndex = RemoveFreeIndex( aSelection, sal_True ); 254 InsertTableIndex( aTableName, aIndex ); 255 256 checkButtons(); 257 return 0; 258 } 259 260 //------------------------------------------------------------------------- 261 IMPL_LINK( ODbaseIndexDialog, RemoveClickHdl, PushButton*, /*pButton*/ ) 262 { 263 String aSelection = aLB_TableIndexes.GetSelectEntry(); 264 String aTableName = aCB_Tables.GetText(); 265 OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection, sal_True ); 266 InsertFreeIndex( aIndex ); 267 268 checkButtons(); 269 return 0; 270 } 271 272 //------------------------------------------------------------------------- 273 IMPL_LINK( ODbaseIndexDialog, AddAllClickHdl, PushButton*, /*pButton*/ ) 274 { 275 sal_uInt16 nCnt = aLB_FreeIndexes.GetEntryCount(); 276 String aTableName = aCB_Tables.GetText(); 277 String aEntry; 278 279 for( sal_uInt16 nPos = 0; nPos < nCnt; ++nPos ) 280 InsertTableIndex( aTableName, RemoveFreeIndex( aLB_FreeIndexes.GetEntry(0), sal_True ) ); 281 282 checkButtons(); 283 return 0; 284 } 285 286 //------------------------------------------------------------------------- 287 IMPL_LINK( ODbaseIndexDialog, RemoveAllClickHdl, PushButton*, /*pButton*/ ) 288 { 289 sal_uInt16 nCnt = aLB_TableIndexes.GetEntryCount(); 290 String aTableName = aCB_Tables.GetText(); 291 String aEntry; 292 293 for( sal_uInt16 nPos = 0; nPos < nCnt; ++nPos ) 294 InsertFreeIndex( RemoveTableIndex( aTableName, aLB_TableIndexes.GetEntry(0), sal_True ) ); 295 296 checkButtons(); 297 return 0; 298 } 299 300 //------------------------------------------------------------------------- 301 IMPL_LINK( ODbaseIndexDialog, OnListEntrySelected, ListBox*, /*NOTINTERESTEDIN*/ ) 302 { 303 checkButtons(); 304 return 0; 305 } 306 307 //------------------------------------------------------------------------- 308 IMPL_LINK( ODbaseIndexDialog, TableSelectHdl, ComboBox*, pComboBox ) 309 { 310 // search the table 311 TableInfoListIterator aTablePos; 312 if (!GetTable(pComboBox->GetText(), aTablePos)) 313 return 0L; 314 315 // fill the listbox for the indexes 316 aLB_TableIndexes.Clear(); 317 for ( ConstTableIndexListIterator aLoop = aTablePos->aIndexList.begin(); 318 aLoop != aTablePos->aIndexList.end(); 319 ++aLoop 320 ) 321 aLB_TableIndexes.InsertEntry( aLoop->GetIndexFileName() ); 322 323 if ( aTablePos->aIndexList.size() ) 324 aLB_TableIndexes.SelectEntryPos(0); 325 326 checkButtons(); 327 return 0; 328 } 329 330 //------------------------------------------------------------------------- 331 void ODbaseIndexDialog::Init() 332 { 333 aPB_OK.Disable(); 334 m_FL_Indexes.Disable(); 335 m_FT_TableIndexes.Disable(); 336 aLB_TableIndexes.Disable(); 337 m_FT_AllIndexes.Disable(); 338 aLB_FreeIndexes.Disable(); 339 aIB_Add.Disable(); 340 aIB_Remove.Disable(); 341 aIB_AddAll.Disable(); 342 aIB_RemoveAll.Disable(); 343 344 /////////////////////////////////////////////////////////////////////////// 345 // Alle Indizes werden erst einmal zur Liste der freien Indizes hinzugefuegt. 346 // Dann wird fuer jede Tabelle in der Inf-Datei nachgeschaut, welche Indizes sie besitzt. 347 // Diese Indizes werden aus der Liste der freien Indizes entfernt 348 // und in die Indexliste der Tabelle eingetragen 349 350 /////////////////////////////////////////////////////////////////////////// 351 // if the string does not contain a path, cut the string 352 INetURLObject aURL; 353 aURL.SetSmartProtocol(INET_PROT_FILE); 354 { 355 SvtPathOptions aPathOptions; 356 m_aDSN = aPathOptions.SubstituteVariable(m_aDSN); 357 } 358 aURL.SetSmartURL(m_aDSN); 359 360 361 // String aFileName = aURL.PathToFileName(); 362 m_aDSN = aURL.GetMainURL(INetURLObject::NO_DECODE); 363 ::ucbhelper::Content aFile; 364 sal_Bool bFolder=sal_True; 365 try 366 { 367 aFile = ::ucbhelper::Content(m_aDSN,Reference< ::com::sun::star::ucb::XCommandEnvironment >()); 368 bFolder = aFile.isFolder(); 369 } 370 catch(Exception&) 371 { 372 return; 373 } 374 375 /////////////////////////////////////////////////////////////////////////// 376 // first assume for all indexes they're free 377 378 Sequence< ::rtl::OUString> aFolderContent( ::utl::LocalFileHelper::GetFolderContents(m_aDSN,bFolder)); 379 380 ::rtl::OUString aIndexExt = ::rtl::OUString::createFromAscii("ndx"); 381 ::rtl::OUString aTableExt = ::rtl::OUString::createFromAscii("dbf"); 382 383 ::std::vector< String > aUsedIndexes; 384 385 String aExt; 386 const ::rtl::OUString *pBegin = aFolderContent.getConstArray(); 387 const ::rtl::OUString *pEnd = pBegin + aFolderContent.getLength(); 388 aURL.SetSmartProtocol(INET_PROT_FILE); 389 for(;pBegin != pEnd;++pBegin) 390 { 391 String aName; 392 ::utl::LocalFileHelper::ConvertURLToPhysicalName(pBegin->getStr(),aName); 393 aURL.SetSmartURL(aName); 394 aExt = aURL.getExtension(); 395 if(aExt == aIndexExt.getStr()) 396 { 397 m_aFreeIndexList.push_back( OTableIndex(aURL.getName()) ); 398 } 399 else if(aExt == aTableExt.getStr()) 400 { 401 m_aTableInfoList.push_back( OTableInfo(aURL.getName()) ); 402 OTableInfo& rTabInfo = m_aTableInfoList.back(); 403 404 // open the INF file 405 aURL.setExtension(String::CreateFromAscii("inf")); 406 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL); 407 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) ); 408 aInfFile.SetGroup( aGroupIdent ); 409 410 /////////////////////////////////////////////////////////////////////////// 411 // fill the indexes list 412 ByteString aNDX; 413 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount(); 414 ByteString aKeyName; 415 String aEntry; 416 417 for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ ) 418 { 419 // does the key point to an index file ? 420 aKeyName = aInfFile.GetKeyName( nKey ); 421 aNDX = aKeyName.Copy(0,3); 422 423 // yes -> add to the tables index list 424 if (aNDX == "NDX" ) 425 { 426 aEntry = String(aInfFile.ReadKey(aKeyName), gsl_getSystemTextEncoding()); 427 rTabInfo.aIndexList.push_back( OTableIndex( aEntry ) ); 428 429 // and remove it from the free index list 430 aUsedIndexes.push_back(aEntry); 431 // do this later below. We may not have encountered the index file, yet, thus we may not 432 // know the index as beeing free, yet 433 } 434 435 } 436 } 437 } 438 439 for ( ::std::vector< String >::const_iterator aUsedIndex = aUsedIndexes.begin(); 440 aUsedIndex != aUsedIndexes.end(); 441 ++aUsedIndex 442 ) 443 RemoveFreeIndex( *aUsedIndex, sal_False ); 444 445 if (m_aTableInfoList.size()) 446 { 447 aPB_OK.Enable(); 448 m_FL_Indexes.Enable(); 449 m_FT_TableIndexes.Enable(); 450 aLB_TableIndexes.Enable(); 451 m_FT_AllIndexes.Enable(); 452 aLB_FreeIndexes.Enable(); 453 } 454 455 checkButtons(); 456 } 457 458 //------------------------------------------------------------------------- 459 void ODbaseIndexDialog::SetCtrls() 460 { 461 // ComboBox Tabellen 462 for ( ConstTableInfoListIterator aLoop = m_aTableInfoList.begin(); 463 aLoop != m_aTableInfoList.end(); 464 ++aLoop 465 ) 466 aCB_Tables.InsertEntry( aLoop->aTableName ); 467 468 // Den ersten Datensatz ins Edit stellen 469 if( m_aTableInfoList.size() ) 470 { 471 const OTableInfo& rTabInfo = m_aTableInfoList.front(); 472 aCB_Tables.SetText( rTabInfo.aTableName ); 473 474 // ListBox der Tabellenindizes aufbauen 475 for ( ConstTableIndexListIterator aIndex = rTabInfo.aIndexList.begin(); 476 aIndex != rTabInfo.aIndexList.end(); 477 ++aIndex 478 ) 479 aLB_TableIndexes.InsertEntry( aIndex->GetIndexFileName() ); 480 481 if( rTabInfo.aIndexList.size() ) 482 aLB_TableIndexes.SelectEntryPos( 0 ); 483 484 } 485 486 // ListBox freie Indizes 487 for ( ConstTableIndexListIterator aFree = m_aFreeIndexList.begin(); 488 aFree != m_aFreeIndexList.end(); 489 ++aFree 490 ) 491 aLB_FreeIndexes.InsertEntry( aFree->GetIndexFileName() ); 492 493 if( m_aFreeIndexList.size() ) 494 aLB_FreeIndexes.SelectEntryPos( 0 ); 495 496 497 TableSelectHdl(&aCB_Tables); 498 checkButtons(); 499 } 500 501 ////////////////////////////////////////////////////////////////////////// 502 // Klasse OTableInfo 503 //------------------------------------------------------------------------- 504 void OTableInfo::WriteInfFile( const String& rDSN ) const 505 { 506 // INF-Datei oeffnen 507 INetURLObject aURL; 508 aURL.SetSmartProtocol(INET_PROT_FILE); 509 String aDsn = rDSN; 510 { 511 SvtPathOptions aPathOptions; 512 aDsn = aPathOptions.SubstituteVariable(aDsn); 513 } 514 aURL.SetSmartURL(aDsn); 515 aURL.Append(aTableName); 516 aURL.setExtension(String::CreateFromAscii("inf")); 517 518 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL); 519 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) ); 520 aInfFile.SetGroup( aGroupIdent ); 521 522 // Erst einmal alle Tabellenindizes loeschen 523 ByteString aNDX; 524 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount(); 525 ByteString aKeyName; 526 ByteString aEntry; 527 sal_uInt16 nKey = 0; 528 529 while( nKey < nKeyCnt ) 530 { 531 // Verweist der Key auf ein Indexfile?... 532 aKeyName = aInfFile.GetKeyName( nKey ); 533 aNDX = aKeyName.Copy(0,3); 534 535 //...wenn ja, Indexfile loeschen, nKey steht dann auf nachfolgendem Key 536 if( aNDX == "NDX" ) 537 { 538 aInfFile.DeleteKey(aKeyName); 539 nKeyCnt--; 540 } 541 else 542 nKey++; 543 544 } 545 546 // Jetzt alle gespeicherten Indizes hinzufuegen 547 sal_uInt16 nPos = 0; 548 for ( ConstTableIndexListIterator aIndex = aIndexList.begin(); 549 aIndex != aIndexList.end(); 550 ++aIndex, ++nPos 551 ) 552 { 553 aKeyName = "NDX"; 554 if( nPos > 0 ) // Erster Index erhaelt keine Ziffer 555 aKeyName += ByteString::CreateFromInt32( nPos ); 556 aInfFile.WriteKey( aKeyName, ByteString(aIndex->GetIndexFileName(), gsl_getSystemTextEncoding()) ); 557 } 558 559 aInfFile.Flush(); 560 561 // Falls nur noch [dbase] in INF-File steht, Datei loeschen 562 if(!nPos) 563 { 564 try 565 { 566 ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>()); 567 aContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),makeAny( sal_Bool( sal_True ) ) ); 568 } 569 catch (const Exception& e ) 570 { 571 (void)e; // make compiler happy 572 // simply silent this. The strange algorithm here does a lot of things even if no files at all were 573 // created or accessed, so it's possible that the file we're trying to delete does not even exist, 574 // and this is a valid condition. 575 // 2003-05-15 - #109677# - fs@openoffice.org 576 } 577 } 578 } 579 580 //......................................................................... 581 } // namespace dbaui 582 //......................................................................... 583 584