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_dbui.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
DBG_NAME(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 //-------------------------------------------------------------------------
~ODbaseIndexDialog()125 ODbaseIndexDialog::~ODbaseIndexDialog()
126 {
127
128 DBG_DTOR(ODbaseIndexDialog,NULL);
129 }
130
131 //-------------------------------------------------------------------------
GetTable(const String & _rName,TableInfoListIterator & _rPosition)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 //-------------------------------------------------------------------------
checkButtons()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 //-------------------------------------------------------------------------
implRemoveIndex(const String & _rName,TableIndexList & _rList,ListBox & _rDisplay,sal_Bool _bMustExist)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 //-------------------------------------------------------------------------
implInsertIndex(const OTableIndex & _rIndex,TableIndexList & _rList,ListBox & _rDisplay)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 //-------------------------------------------------------------------------
RemoveTableIndex(const String & _rTableName,const String & _rIndexName,sal_Bool _bMustExist)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 //-------------------------------------------------------------------------
InsertTableIndex(const String & _rTableName,const OTableIndex & _rIndex)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 //-------------------------------------------------------------------------
IMPL_LINK(ODbaseIndexDialog,TableSelectHdl,ComboBox *,pComboBox)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 //-------------------------------------------------------------------------
Init()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 being 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 //-------------------------------------------------------------------------
SetCtrls()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 //-------------------------------------------------------------------------
WriteInfFile(const String & rDSN) const500 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