Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "dbfindex.hxx"
21 : #include <comphelper/processfactory.hxx>
22 : #include <tools/config.hxx>
23 : #include <sfx2/app.hxx>
24 : #include "moduledbu.hxx"
25 : #include "dbu_dlg.hrc"
26 : #include "dbfindex.hrc"
27 : #include <osl/diagnose.h>
28 : #include <unotools/localfilehelper.hxx>
29 : #include <tools/urlobj.hxx>
30 : #include <unotools/pathoptions.hxx>
31 : #include <ucbhelper/content.hxx>
32 : #include <svl/filenotation.hxx>
33 : #include <rtl/strbuf.hxx>
34 :
35 : namespace dbaui
36 : {
37 : using namespace ::com::sun::star::uno;
38 : using namespace ::com::sun::star::ucb;
39 : using namespace ::svt;
40 :
41 0 : const rtl::OString aGroupIdent(RTL_CONSTASCII_STRINGPARAM("dBase III"));
42 :
43 : // ODbaseIndexDialog ----------------------------------------------------------
44 : DBG_NAME(ODbaseIndexDialog)
45 :
46 0 : ODbaseIndexDialog::ODbaseIndexDialog( Window * pParent, String aDataSrcName )
47 : : ModalDialog( pParent, ModuleRes(DLG_DBASE_INDEXES) ),
48 : aPB_OK( this, ModuleRes( PB_OK ) ),
49 : aPB_CANCEL( this, ModuleRes( PB_CANCEL ) ),
50 : aPB_HELP( this, ModuleRes( PB_HELP ) ),
51 : m_FT_Tables( this, ModuleRes( FT_TABLES ) ),
52 : aCB_Tables( this, ModuleRes( CB_TABLES ) ),
53 : m_FL_Indexes( this, ModuleRes( FL_INDEXES ) ),
54 : m_FT_TableIndexes( this, ModuleRes( FT_TABLEINDEXES ) ),
55 : aLB_TableIndexes( this, ModuleRes( LB_TABLEINDEXES ) ),
56 : m_FT_AllIndexes( this, ModuleRes( FT_ALLINDEXES ) ),
57 : aLB_FreeIndexes( this, ModuleRes( LB_FREEINDEXES ) ),
58 : aIB_Add( this, ModuleRes( IB_ADD ) ),
59 : aIB_Remove( this, ModuleRes( IB_REMOVE ) ),
60 : aIB_AddAll( this, ModuleRes( IB_ADDALL ) ),
61 : aIB_RemoveAll( this, ModuleRes( IB_REMOVEALL ) ),
62 : m_aDSN(aDataSrcName),
63 0 : m_bCaseSensitiv(sal_True)
64 : {
65 : DBG_CTOR(ODbaseIndexDialog,NULL);
66 :
67 0 : aCB_Tables.SetSelectHdl( LINK(this, ODbaseIndexDialog, TableSelectHdl) );
68 0 : aIB_Add.SetClickHdl( LINK(this, ODbaseIndexDialog, AddClickHdl) );
69 0 : aIB_Remove.SetClickHdl( LINK(this, ODbaseIndexDialog, RemoveClickHdl) );
70 0 : aIB_AddAll.SetClickHdl( LINK(this, ODbaseIndexDialog, AddAllClickHdl) );
71 0 : aIB_RemoveAll.SetClickHdl( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) );
72 0 : aPB_OK.SetClickHdl( LINK(this, ODbaseIndexDialog, OKClickHdl) );
73 :
74 0 : aLB_FreeIndexes.SetSelectHdl( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
75 0 : aLB_TableIndexes.SetSelectHdl( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
76 :
77 0 : aCB_Tables.SetDropDownLineCount(8);
78 0 : Init();
79 0 : SetCtrls();
80 0 : FreeResource();
81 0 : }
82 :
83 0 : ODbaseIndexDialog::~ODbaseIndexDialog()
84 : {
85 :
86 : DBG_DTOR(ODbaseIndexDialog,NULL);
87 0 : }
88 :
89 0 : sal_Bool ODbaseIndexDialog::GetTable(const String& _rName, TableInfoListIterator& _rPosition)
90 : {
91 0 : for ( _rPosition = m_aTableInfoList.begin();
92 0 : _rPosition != m_aTableInfoList.end();
93 : ++_rPosition
94 : )
95 : {
96 0 : if (m_bCaseSensitiv)
97 : {
98 0 : if (_rPosition->aTableName.Equals(_rName))
99 0 : return sal_True;
100 : }
101 : else
102 : {
103 0 : if (_rPosition->aTableName.EqualsIgnoreCaseAscii(_rName))
104 0 : return sal_True;
105 : }
106 : }
107 0 : return sal_False;
108 : }
109 :
110 0 : void ODbaseIndexDialog::checkButtons()
111 : {
112 0 : aIB_Add.Enable(0 != aLB_FreeIndexes.GetSelectEntryCount());
113 0 : aIB_AddAll.Enable(0 != aLB_FreeIndexes.GetEntryCount());
114 :
115 0 : aIB_Remove.Enable(0 != aLB_TableIndexes.GetSelectEntryCount());
116 0 : aIB_RemoveAll.Enable(0 != aLB_TableIndexes.GetEntryCount());
117 0 : }
118 :
119 0 : OTableIndex ODbaseIndexDialog::implRemoveIndex(const String& _rName, TableIndexList& _rList, ListBox& _rDisplay, sal_Bool _bMustExist)
120 : {
121 0 : OTableIndex aReturn;
122 :
123 0 : sal_Int32 nPos = 0;
124 :
125 0 : TableIndexListIterator aSearch;
126 0 : for ( aSearch = _rList.begin();
127 0 : aSearch != _rList.end();
128 : ++aSearch, ++nPos
129 : )
130 : {
131 0 : if ( m_bCaseSensitiv ? aSearch->GetIndexFileName().Equals(_rName) : aSearch->GetIndexFileName().EqualsIgnoreCaseAscii(_rName) )
132 : {
133 0 : aReturn = *aSearch;
134 :
135 0 : _rList.erase(aSearch);
136 0 : _rDisplay.RemoveEntry( _rName );
137 :
138 : // adjust selection if necessary
139 0 : if ((sal_uInt32)nPos == _rList.size())
140 0 : _rDisplay.SelectEntryPos((sal_uInt16)nPos-1);
141 : else
142 0 : _rDisplay.SelectEntryPos((sal_uInt16)nPos);
143 :
144 0 : break;
145 : }
146 : }
147 :
148 : (void)_bMustExist;
149 : OSL_ENSURE(!_bMustExist || (aSearch != _rList.end()), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
150 0 : return aReturn;
151 : }
152 :
153 0 : void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, ListBox& _rDisplay)
154 : {
155 0 : _rList.push_front( _rIndex );
156 0 : _rDisplay.InsertEntry( _rIndex.GetIndexFileName() );
157 0 : _rDisplay.SelectEntryPos(0);
158 0 : }
159 :
160 0 : OTableIndex ODbaseIndexDialog::RemoveTableIndex( const String& _rTableName, const String& _rIndexName, sal_Bool _bMustExist )
161 : {
162 0 : OTableIndex aReturn;
163 :
164 : // does the table exist ?
165 0 : TableInfoListIterator aTablePos;
166 0 : if (!GetTable(_rTableName, aTablePos))
167 0 : return aReturn;
168 :
169 0 : return implRemoveIndex(_rIndexName, aTablePos->aIndexList, aLB_TableIndexes, _bMustExist);
170 : }
171 :
172 0 : void ODbaseIndexDialog::InsertTableIndex( const String& _rTableName, const OTableIndex& _rIndex)
173 : {
174 0 : TableInfoListIterator aTablePos;
175 0 : if (!GetTable(_rTableName, aTablePos))
176 0 : return;
177 :
178 0 : implInsertIndex(_rIndex, aTablePos->aIndexList, aLB_TableIndexes);
179 : }
180 :
181 0 : IMPL_LINK( ODbaseIndexDialog, OKClickHdl, PushButton*, /*pButton*/ )
182 : {
183 : // let all tables write their INF file
184 :
185 0 : for ( ConstTableInfoListIterator aLoop = m_aTableInfoList.begin();
186 0 : aLoop != m_aTableInfoList.end();
187 : ++aLoop
188 : )
189 0 : aLoop->WriteInfFile(m_aDSN);
190 :
191 0 : EndDialog();
192 0 : return 0;
193 : }
194 :
195 0 : IMPL_LINK( ODbaseIndexDialog, AddClickHdl, PushButton*, /*pButton*/ )
196 : {
197 0 : String aSelection = aLB_FreeIndexes.GetSelectEntry();
198 0 : String aTableName = aCB_Tables.GetText();
199 0 : OTableIndex aIndex = RemoveFreeIndex( aSelection, sal_True );
200 0 : InsertTableIndex( aTableName, aIndex );
201 :
202 0 : checkButtons();
203 0 : return 0;
204 : }
205 :
206 0 : IMPL_LINK( ODbaseIndexDialog, RemoveClickHdl, PushButton*, /*pButton*/ )
207 : {
208 0 : String aSelection = aLB_TableIndexes.GetSelectEntry();
209 0 : String aTableName = aCB_Tables.GetText();
210 0 : OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection, sal_True );
211 0 : InsertFreeIndex( aIndex );
212 :
213 0 : checkButtons();
214 0 : return 0;
215 : }
216 :
217 0 : IMPL_LINK( ODbaseIndexDialog, AddAllClickHdl, PushButton*, /*pButton*/ )
218 : {
219 0 : sal_uInt16 nCnt = aLB_FreeIndexes.GetEntryCount();
220 0 : String aTableName = aCB_Tables.GetText();
221 :
222 0 : for( sal_uInt16 nPos = 0; nPos < nCnt; ++nPos )
223 0 : InsertTableIndex( aTableName, RemoveFreeIndex( aLB_FreeIndexes.GetEntry(0), sal_True ) );
224 :
225 0 : checkButtons();
226 0 : return 0;
227 : }
228 :
229 0 : IMPL_LINK( ODbaseIndexDialog, RemoveAllClickHdl, PushButton*, /*pButton*/ )
230 : {
231 0 : sal_uInt16 nCnt = aLB_TableIndexes.GetEntryCount();
232 0 : String aTableName = aCB_Tables.GetText();
233 :
234 0 : for( sal_uInt16 nPos = 0; nPos < nCnt; ++nPos )
235 0 : InsertFreeIndex( RemoveTableIndex( aTableName, aLB_TableIndexes.GetEntry(0), sal_True ) );
236 :
237 0 : checkButtons();
238 0 : return 0;
239 : }
240 :
241 0 : IMPL_LINK( ODbaseIndexDialog, OnListEntrySelected, ListBox*, /*NOTINTERESTEDIN*/ )
242 : {
243 0 : checkButtons();
244 0 : return 0;
245 : }
246 :
247 0 : IMPL_LINK( ODbaseIndexDialog, TableSelectHdl, ComboBox*, pComboBox )
248 : {
249 : // search the table
250 0 : TableInfoListIterator aTablePos;
251 0 : if (!GetTable(pComboBox->GetText(), aTablePos))
252 0 : return 0L;
253 :
254 : // fill the listbox for the indexes
255 0 : aLB_TableIndexes.Clear();
256 0 : for ( ConstTableIndexListIterator aLoop = aTablePos->aIndexList.begin();
257 0 : aLoop != aTablePos->aIndexList.end();
258 : ++aLoop
259 : )
260 0 : aLB_TableIndexes.InsertEntry( aLoop->GetIndexFileName() );
261 :
262 0 : if ( aTablePos->aIndexList.size() )
263 0 : aLB_TableIndexes.SelectEntryPos(0);
264 :
265 0 : checkButtons();
266 0 : return 0;
267 : }
268 :
269 0 : void ODbaseIndexDialog::Init()
270 : {
271 0 : aPB_OK.Disable();
272 0 : m_FL_Indexes.Disable();
273 0 : m_FT_TableIndexes.Disable();
274 0 : aLB_TableIndexes.Disable();
275 0 : m_FT_AllIndexes.Disable();
276 0 : aLB_FreeIndexes.Disable();
277 0 : aIB_Add.Disable();
278 0 : aIB_Remove.Disable();
279 0 : aIB_AddAll.Disable();
280 0 : aIB_RemoveAll.Disable();
281 :
282 : // All indizes are first added to a list of free indizes.
283 : // Afterwards, check the index of each table in the Inf-file.
284 : // These indizes are removed from the list of free indizes and
285 : // entered in the indexlist of the the table.
286 :
287 : // if the string does not contain a path, cut the string
288 0 : INetURLObject aURL;
289 0 : aURL.SetSmartProtocol(INET_PROT_FILE);
290 : {
291 0 : SvtPathOptions aPathOptions;
292 0 : m_aDSN = aPathOptions.SubstituteVariable(m_aDSN);
293 : }
294 0 : aURL.SetSmartURL(m_aDSN);
295 :
296 : // String aFileName = aURL.PathToFileName();
297 0 : m_aDSN = aURL.GetMainURL(INetURLObject::NO_DECODE);
298 0 : ::ucbhelper::Content aFile;
299 0 : sal_Bool bFolder=sal_True;
300 : try
301 : {
302 0 : aFile = ::ucbhelper::Content(m_aDSN,Reference< ::com::sun::star::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext());
303 0 : bFolder = aFile.isFolder();
304 : }
305 0 : catch(Exception&)
306 : {
307 0 : return;
308 : }
309 :
310 : // first assume for all indexes they're free
311 :
312 0 : Sequence< ::rtl::OUString> aFolderContent( ::utl::LocalFileHelper::GetFolderContents(m_aDSN,bFolder));
313 :
314 0 : ::rtl::OUString aIndexExt(RTL_CONSTASCII_USTRINGPARAM("ndx"));
315 0 : ::rtl::OUString aTableExt(RTL_CONSTASCII_USTRINGPARAM("dbf"));
316 :
317 0 : ::std::vector< String > aUsedIndexes;
318 :
319 0 : const ::rtl::OUString *pBegin = aFolderContent.getConstArray();
320 0 : const ::rtl::OUString *pEnd = pBegin + aFolderContent.getLength();
321 0 : aURL.SetSmartProtocol(INET_PROT_FILE);
322 0 : for(;pBegin != pEnd;++pBegin)
323 : {
324 0 : rtl::OUString aName;
325 0 : ::utl::LocalFileHelper::ConvertURLToPhysicalName(pBegin->getStr(),aName);
326 0 : aURL.SetSmartURL(aName);
327 0 : rtl::OUString aExt = aURL.getExtension();
328 0 : if (aExt == aIndexExt)
329 : {
330 0 : m_aFreeIndexList.push_back( OTableIndex(aURL.getName()) );
331 : }
332 0 : else if (aExt == aTableExt)
333 : {
334 0 : m_aTableInfoList.push_back( OTableInfo(aURL.getName()) );
335 0 : OTableInfo& rTabInfo = m_aTableInfoList.back();
336 :
337 : // open the INF file
338 0 : aURL.setExtension(rtl::OUString::createFromAscii("inf"));
339 0 : OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
340 0 : Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
341 0 : aInfFile.SetGroup( aGroupIdent );
342 :
343 : // fill the indexes list
344 0 : rtl::OString aNDX;
345 0 : sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
346 0 : rtl::OString aKeyName;
347 0 : String aEntry;
348 :
349 0 : for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ )
350 : {
351 : // does the key point to an index file ?
352 0 : aKeyName = aInfFile.GetKeyName( nKey );
353 0 : aNDX = aKeyName.copy(0,3);
354 :
355 : // yes -> add to the tables index list
356 0 : if (aNDX.equalsL(RTL_CONSTASCII_STRINGPARAM("NDX")))
357 : {
358 0 : aEntry = rtl::OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding());
359 0 : rTabInfo.aIndexList.push_back( OTableIndex( aEntry ) );
360 :
361 : // and remove it from the free index list
362 0 : aUsedIndexes.push_back(aEntry);
363 : // do this later below. We may not have encountered the index file, yet, thus we may not
364 : // know the index as beeing free, yet
365 : }
366 0 : }
367 : }
368 0 : }
369 :
370 0 : for ( ::std::vector< String >::const_iterator aUsedIndex = aUsedIndexes.begin();
371 0 : aUsedIndex != aUsedIndexes.end();
372 : ++aUsedIndex
373 : )
374 0 : RemoveFreeIndex( *aUsedIndex, sal_False );
375 :
376 0 : if (m_aTableInfoList.size())
377 : {
378 0 : aPB_OK.Enable();
379 0 : m_FL_Indexes.Enable();
380 0 : m_FT_TableIndexes.Enable();
381 0 : aLB_TableIndexes.Enable();
382 0 : m_FT_AllIndexes.Enable();
383 0 : aLB_FreeIndexes.Enable();
384 : }
385 :
386 0 : checkButtons();
387 : }
388 :
389 0 : void ODbaseIndexDialog::SetCtrls()
390 : {
391 : // ComboBox tables
392 0 : for ( ConstTableInfoListIterator aLoop = m_aTableInfoList.begin();
393 0 : aLoop != m_aTableInfoList.end();
394 : ++aLoop
395 : )
396 0 : aCB_Tables.InsertEntry( aLoop->aTableName );
397 :
398 : // put the first dataset into Edit
399 0 : if( m_aTableInfoList.size() )
400 : {
401 0 : const OTableInfo& rTabInfo = m_aTableInfoList.front();
402 0 : aCB_Tables.SetText( rTabInfo.aTableName );
403 :
404 : // build ListBox of the table indizes
405 0 : for ( ConstTableIndexListIterator aIndex = rTabInfo.aIndexList.begin();
406 0 : aIndex != rTabInfo.aIndexList.end();
407 : ++aIndex
408 : )
409 0 : aLB_TableIndexes.InsertEntry( aIndex->GetIndexFileName() );
410 :
411 0 : if( rTabInfo.aIndexList.size() )
412 0 : aLB_TableIndexes.SelectEntryPos( 0 );
413 : }
414 :
415 : // ListBox of the free indizes
416 0 : for ( ConstTableIndexListIterator aFree = m_aFreeIndexList.begin();
417 0 : aFree != m_aFreeIndexList.end();
418 : ++aFree
419 : )
420 0 : aLB_FreeIndexes.InsertEntry( aFree->GetIndexFileName() );
421 :
422 0 : if( m_aFreeIndexList.size() )
423 0 : aLB_FreeIndexes.SelectEntryPos( 0 );
424 :
425 0 : TableSelectHdl(&aCB_Tables);
426 0 : checkButtons();
427 0 : }
428 :
429 : // OTableInfo ------------------------------------------------------------------
430 0 : void OTableInfo::WriteInfFile( const String& rDSN ) const
431 : {
432 : // open INF file
433 0 : INetURLObject aURL;
434 0 : aURL.SetSmartProtocol(INET_PROT_FILE);
435 0 : String aDsn = rDSN;
436 : {
437 0 : SvtPathOptions aPathOptions;
438 0 : aDsn = aPathOptions.SubstituteVariable(aDsn);
439 : }
440 0 : aURL.SetSmartURL(aDsn);
441 0 : aURL.Append(aTableName);
442 0 : aURL.setExtension(rtl::OUString::createFromAscii("inf"));
443 :
444 0 : OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
445 0 : Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
446 0 : aInfFile.SetGroup( aGroupIdent );
447 :
448 : // first, delete all table indizes
449 0 : rtl::OString aNDX;
450 0 : sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
451 0 : sal_uInt16 nKey = 0;
452 :
453 0 : while( nKey < nKeyCnt )
454 : {
455 : // Does the key point to an index file?...
456 0 : rtl::OString aKeyName = aInfFile.GetKeyName( nKey );
457 0 : aNDX = aKeyName.copy(0,3);
458 :
459 : //...if yes, delete index file, nKey is at subsequent key
460 0 : if (aNDX.equalsL(RTL_CONSTASCII_STRINGPARAM("NDX")))
461 : {
462 0 : aInfFile.DeleteKey(aKeyName);
463 0 : nKeyCnt--;
464 : }
465 : else
466 0 : nKey++;
467 :
468 0 : }
469 :
470 : // now add all saved indizes
471 0 : sal_uInt16 nPos = 0;
472 0 : for ( ConstTableIndexListIterator aIndex = aIndexList.begin();
473 0 : aIndex != aIndexList.end();
474 : ++aIndex, ++nPos
475 : )
476 : {
477 0 : rtl::OStringBuffer aKeyName(RTL_CONSTASCII_STRINGPARAM("NDX"));
478 0 : if( nPos > 0 ) // first index contains no number
479 0 : aKeyName.append(static_cast<sal_Int32>(nPos));
480 : aInfFile.WriteKey(
481 : aKeyName.makeStringAndClear(),
482 : rtl::OUStringToOString(aIndex->GetIndexFileName(),
483 0 : osl_getThreadTextEncoding()));
484 0 : }
485 :
486 0 : aInfFile.Flush();
487 :
488 : // if only [dbase] is left in INF-file, delete file
489 0 : if(!nPos)
490 : {
491 : try
492 : {
493 0 : ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
494 0 : aContent.executeCommand( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("delete")),makeAny( sal_Bool( sal_True ) ) );
495 : }
496 0 : catch (const Exception& e )
497 : {
498 : (void)e; // make compiler happy
499 : // simply silent this. The strange algorithm here does a lot of
500 : // things even if no files at all were created or accessed, so it's
501 : // possible that the file we're trying to delete does not even
502 : // exist, and this is a valid condition.
503 : }
504 0 : }
505 0 : }
506 :
507 0 : } // namespace
508 :
509 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|