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