1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 <osl/diagnose.h>
27 #include <unotools/localfilehelper.hxx>
28 #include <tools/urlobj.hxx>
29 #include <unotools/pathoptions.hxx>
30 #include <ucbhelper/content.hxx>
31 #include <svl/filenotation.hxx>
32 #include <rtl/strbuf.hxx>
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::ucb
;
38 using namespace ::svt
;
40 const OString
aGroupIdent("dBase III");
43 ODbaseIndexDialog::ODbaseIndexDialog(vcl::Window
* pParent
, const OUString
& aDataSrcName
)
44 : ModalDialog(pParent
, "DBaseIndexDialog", "dbaccess/ui/dbaseindexdialog.ui")
45 , m_aDSN(aDataSrcName
)
46 , m_bCaseSensitiv(true)
49 get(m_pCB_Tables
, "table");
50 get(m_pIndexes
, "frame");
51 get(m_pLB_TableIndexes
, "tableindex");
52 get(m_pLB_FreeIndexes
, "freeindex");
53 Size
aSize(LogicToPixel(Size(76, 98), MAP_APPFONT
));
54 m_pLB_TableIndexes
->set_height_request(aSize
.Height());
55 m_pLB_TableIndexes
->set_width_request(aSize
.Width());
56 m_pLB_FreeIndexes
->set_height_request(aSize
.Height());
57 m_pLB_FreeIndexes
->set_width_request(aSize
.Width());
59 get(m_pAddAll
, "addall");
60 get(m_pRemove
, "remove");
61 get(m_pRemoveAll
, "removeall");
64 m_pCB_Tables
->SetSelectHdl( LINK(this, ODbaseIndexDialog
, TableSelectHdl
) );
65 m_pAdd
->SetClickHdl( LINK(this, ODbaseIndexDialog
, AddClickHdl
) );
66 m_pRemove
->SetClickHdl( LINK(this, ODbaseIndexDialog
, RemoveClickHdl
) );
67 m_pAddAll
->SetClickHdl( LINK(this, ODbaseIndexDialog
, AddAllClickHdl
) );
68 m_pRemoveAll
->SetClickHdl( LINK(this, ODbaseIndexDialog
, RemoveAllClickHdl
) );
69 m_pPB_OK
->SetClickHdl( LINK(this, ODbaseIndexDialog
, OKClickHdl
) );
71 m_pLB_FreeIndexes
->SetSelectHdl( LINK(this, ODbaseIndexDialog
, OnListEntrySelected
) );
72 m_pLB_TableIndexes
->SetSelectHdl( LINK(this, ODbaseIndexDialog
, OnListEntrySelected
) );
74 m_pCB_Tables
->SetDropDownLineCount(8);
79 ODbaseIndexDialog::~ODbaseIndexDialog()
84 void ODbaseIndexDialog::dispose()
89 m_pLB_TableIndexes
.clear();
90 m_pLB_FreeIndexes
.clear();
95 ModalDialog::dispose();
98 bool ODbaseIndexDialog::GetTable(const OUString
& _rName
, TableInfoList::iterator
& _rPosition
)
100 for ( _rPosition
= m_aTableInfoList
.begin();
101 _rPosition
!= m_aTableInfoList
.end();
107 if (_rPosition
->aTableName
== _rName
)
112 if (_rPosition
->aTableName
.equalsIgnoreAsciiCase(_rName
))
119 void ODbaseIndexDialog::checkButtons()
121 m_pAdd
->Enable(0 != m_pLB_FreeIndexes
->GetSelectEntryCount());
122 m_pAddAll
->Enable(0 != m_pLB_FreeIndexes
->GetEntryCount());
124 m_pRemove
->Enable(0 != m_pLB_TableIndexes
->GetSelectEntryCount());
125 m_pRemoveAll
->Enable(0 != m_pLB_TableIndexes
->GetEntryCount());
128 OTableIndex
ODbaseIndexDialog::implRemoveIndex(const OUString
& _rName
, TableIndexList
& _rList
, ListBox
& _rDisplay
, bool _bMustExist
)
134 TableIndexList::iterator aSearch
;
135 for ( aSearch
= _rList
.begin();
136 aSearch
!= _rList
.end();
140 if ( m_bCaseSensitiv
? aSearch
->GetIndexFileName() == _rName
: aSearch
->GetIndexFileName().equalsIgnoreAsciiCase(_rName
) )
144 _rList
.erase(aSearch
);
145 _rDisplay
.RemoveEntry( _rName
);
147 // adjust selection if necessary
148 if ((sal_uInt32
)nPos
== _rList
.size())
149 _rDisplay
.SelectEntryPos((sal_uInt16
)nPos
-1);
151 _rDisplay
.SelectEntryPos((sal_uInt16
)nPos
);
158 OSL_ENSURE(!_bMustExist
|| (aSearch
!= _rList
.end()), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
162 void ODbaseIndexDialog::implInsertIndex(const OTableIndex
& _rIndex
, TableIndexList
& _rList
, ListBox
& _rDisplay
)
164 _rList
.push_front( _rIndex
);
165 _rDisplay
.InsertEntry( _rIndex
.GetIndexFileName() );
166 _rDisplay
.SelectEntryPos(0);
169 OTableIndex
ODbaseIndexDialog::RemoveTableIndex( const OUString
& _rTableName
, const OUString
& _rIndexName
, bool _bMustExist
)
173 // does the table exist ?
174 TableInfoList::iterator aTablePos
;
175 if (!GetTable(_rTableName
, aTablePos
))
178 return implRemoveIndex(_rIndexName
, aTablePos
->aIndexList
, *m_pLB_TableIndexes
, _bMustExist
);
181 void ODbaseIndexDialog::InsertTableIndex( const OUString
& _rTableName
, const OTableIndex
& _rIndex
)
183 TableInfoList::iterator aTablePos
;
184 if (!GetTable(_rTableName
, aTablePos
))
187 implInsertIndex(_rIndex
, aTablePos
->aIndexList
, *m_pLB_TableIndexes
);
190 IMPL_LINK( ODbaseIndexDialog
, OKClickHdl
, PushButton
*, /*pButton*/ )
192 // let all tables write their INF file
194 for ( TableInfoList::const_iterator aLoop
= m_aTableInfoList
.begin();
195 aLoop
!= m_aTableInfoList
.end();
198 aLoop
->WriteInfFile(m_aDSN
);
204 IMPL_LINK( ODbaseIndexDialog
, AddClickHdl
, PushButton
*, /*pButton*/ )
206 OUString aSelection
= m_pLB_FreeIndexes
->GetSelectEntry();
207 OUString aTableName
= m_pCB_Tables
->GetText();
208 OTableIndex aIndex
= RemoveFreeIndex( aSelection
, true );
209 InsertTableIndex( aTableName
, aIndex
);
215 IMPL_LINK( ODbaseIndexDialog
, RemoveClickHdl
, PushButton
*, /*pButton*/ )
217 OUString aSelection
= m_pLB_TableIndexes
->GetSelectEntry();
218 OUString aTableName
= m_pCB_Tables
->GetText();
219 OTableIndex aIndex
= RemoveTableIndex( aTableName
, aSelection
, true );
220 InsertFreeIndex( aIndex
);
226 IMPL_LINK( ODbaseIndexDialog
, AddAllClickHdl
, PushButton
*, /*pButton*/ )
228 sal_uInt16 nCnt
= m_pLB_FreeIndexes
->GetEntryCount();
229 OUString aTableName
= m_pCB_Tables
->GetText();
231 for( sal_uInt16 nPos
= 0; nPos
< nCnt
; ++nPos
)
232 InsertTableIndex( aTableName
, RemoveFreeIndex( m_pLB_FreeIndexes
->GetEntry(0), true ) );
238 IMPL_LINK( ODbaseIndexDialog
, RemoveAllClickHdl
, PushButton
*, /*pButton*/ )
240 sal_uInt16 nCnt
= m_pLB_TableIndexes
->GetEntryCount();
241 OUString aTableName
= m_pCB_Tables
->GetText();
243 for( sal_uInt16 nPos
= 0; nPos
< nCnt
; ++nPos
)
244 InsertFreeIndex( RemoveTableIndex( aTableName
, m_pLB_TableIndexes
->GetEntry(0), true ) );
250 IMPL_LINK( ODbaseIndexDialog
, OnListEntrySelected
, ListBox
*, /*NOTINTERESTEDIN*/ )
256 IMPL_LINK( ODbaseIndexDialog
, TableSelectHdl
, ComboBox
*, pComboBox
)
259 TableInfoList::iterator aTablePos
;
260 if (!GetTable(pComboBox
->GetText(), aTablePos
))
263 // fill the listbox for the indexes
264 m_pLB_TableIndexes
->Clear();
265 for ( TableIndexList::const_iterator aLoop
= aTablePos
->aIndexList
.begin();
266 aLoop
!= aTablePos
->aIndexList
.end();
269 m_pLB_TableIndexes
->InsertEntry( aLoop
->GetIndexFileName() );
271 if ( aTablePos
->aIndexList
.size() )
272 m_pLB_TableIndexes
->SelectEntryPos(0);
278 void ODbaseIndexDialog::Init()
281 m_pIndexes
->Disable();
283 // All indices are first added to a list of free indices.
284 // Afterwards, check the index of each table in the Inf-file.
285 // These indices are removed from the list of free indices and
286 // entered in the indexlist of the table.
288 // if the string does not contain a path, cut the string
290 aURL
.SetSmartProtocol(INetProtocol::File
);
292 SvtPathOptions aPathOptions
;
293 m_aDSN
= aPathOptions
.SubstituteVariable(m_aDSN
);
295 aURL
.SetSmartURL(m_aDSN
);
297 // String aFileName = aURL.PathToFileName();
298 m_aDSN
= aURL
.GetMainURL(INetURLObject::NO_DECODE
);
299 ::ucbhelper::Content aFile
;
303 aFile
= ::ucbhelper::Content(m_aDSN
,Reference
< ::com::sun::star::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext());
304 bFolder
= aFile
.isFolder();
311 // first assume for all indexes they're free
313 Sequence
< OUString
> aFolderContent( ::utl::LocalFileHelper::GetFolderContents(m_aDSN
,bFolder
));
315 OUString
aIndexExt("ndx");
316 OUString
aTableExt("dbf");
318 ::std::vector
< OUString
> aUsedIndexes
;
320 const OUString
*pBegin
= aFolderContent
.getConstArray();
321 const OUString
*pEnd
= pBegin
+ aFolderContent
.getLength();
322 aURL
.SetSmartProtocol(INetProtocol::File
);
323 for(;pBegin
!= pEnd
;++pBegin
)
326 ::utl::LocalFileHelper::ConvertURLToPhysicalName(pBegin
->getStr(),aName
);
327 aURL
.SetSmartURL(aName
);
328 OUString aExt
= aURL
.getExtension();
329 if (aExt
== aIndexExt
)
331 m_aFreeIndexList
.push_back( OTableIndex(aURL
.getName()) );
333 else if (aExt
== aTableExt
)
335 m_aTableInfoList
.push_back( OTableInfo(aURL
.getName()) );
336 OTableInfo
& rTabInfo
= m_aTableInfoList
.back();
339 aURL
.setExtension("inf");
340 OFileNotation
aTransformer(aURL
.GetURLNoPass(), OFileNotation::N_URL
);
341 Config
aInfFile( aTransformer
.get(OFileNotation::N_SYSTEM
) );
342 aInfFile
.SetGroup( aGroupIdent
);
344 // fill the indexes list
346 sal_uInt16 nKeyCnt
= aInfFile
.GetKeyCount();
350 for( sal_uInt16 nKey
= 0; nKey
< nKeyCnt
; nKey
++ )
352 // does the key point to an index file ?
353 aKeyName
= aInfFile
.GetKeyName( nKey
);
354 aNDX
= aKeyName
.copy(0,3);
356 // yes -> add to the tables index list
359 aEntry
= OStringToOUString(aInfFile
.ReadKey(aKeyName
), osl_getThreadTextEncoding());
360 rTabInfo
.aIndexList
.push_back( OTableIndex( aEntry
) );
362 // and remove it from the free index list
363 aUsedIndexes
.push_back(aEntry
);
364 // do this later below. We may not have encountered the index file, yet, thus we may not
365 // know the index as being free, yet
371 for ( ::std::vector
< OUString
>::const_iterator aUsedIndex
= aUsedIndexes
.begin();
372 aUsedIndex
!= aUsedIndexes
.end();
375 RemoveFreeIndex( *aUsedIndex
, false );
377 if (m_aTableInfoList
.size())
380 m_pIndexes
->Enable();
386 void ODbaseIndexDialog::SetCtrls()
389 for ( TableInfoList::const_iterator aLoop
= m_aTableInfoList
.begin();
390 aLoop
!= m_aTableInfoList
.end();
393 m_pCB_Tables
->InsertEntry( aLoop
->aTableName
);
395 // put the first dataset into Edit
396 if( m_aTableInfoList
.size() )
398 const OTableInfo
& rTabInfo
= m_aTableInfoList
.front();
399 m_pCB_Tables
->SetText( rTabInfo
.aTableName
);
401 // build ListBox of the table indices
402 for ( TableIndexList::const_iterator aIndex
= rTabInfo
.aIndexList
.begin();
403 aIndex
!= rTabInfo
.aIndexList
.end();
406 m_pLB_TableIndexes
->InsertEntry( aIndex
->GetIndexFileName() );
408 if( rTabInfo
.aIndexList
.size() )
409 m_pLB_TableIndexes
->SelectEntryPos( 0 );
412 // ListBox of the free indices
413 for ( TableIndexList::const_iterator aFree
= m_aFreeIndexList
.begin();
414 aFree
!= m_aFreeIndexList
.end();
417 m_pLB_FreeIndexes
->InsertEntry( aFree
->GetIndexFileName() );
419 if( m_aFreeIndexList
.size() )
420 m_pLB_FreeIndexes
->SelectEntryPos( 0 );
422 TableSelectHdl(m_pCB_Tables
);
426 void OTableInfo::WriteInfFile( const OUString
& rDSN
) const
430 aURL
.SetSmartProtocol(INetProtocol::File
);
431 OUString aDsn
= rDSN
;
433 SvtPathOptions aPathOptions
;
434 aDsn
= aPathOptions
.SubstituteVariable(aDsn
);
436 aURL
.SetSmartURL(aDsn
);
437 aURL
.Append(aTableName
);
438 aURL
.setExtension("inf");
440 OFileNotation
aTransformer(aURL
.GetURLNoPass(), OFileNotation::N_URL
);
441 Config
aInfFile( aTransformer
.get(OFileNotation::N_SYSTEM
) );
442 aInfFile
.SetGroup( aGroupIdent
);
444 // first, delete all table indices
446 sal_uInt16 nKeyCnt
= aInfFile
.GetKeyCount();
449 while( nKey
< nKeyCnt
)
451 // Does the key point to an index file?...
452 OString aKeyName
= aInfFile
.GetKeyName( nKey
);
453 aNDX
= aKeyName
.copy(0,3);
455 //...if yes, delete index file, nKey is at subsequent key
458 aInfFile
.DeleteKey(aKeyName
);
466 // now add all saved indices
468 for ( TableIndexList::const_iterator aIndex
= aIndexList
.begin();
469 aIndex
!= aIndexList
.end();
473 OStringBuffer
aKeyName("NDX");
474 if( nPos
> 0 ) // first index contains no number
475 aKeyName
.append(static_cast<sal_Int32
>(nPos
));
477 aKeyName
.makeStringAndClear(),
478 OUStringToOString(aIndex
->GetIndexFileName(),
479 osl_getThreadTextEncoding()));
484 // if only [dbase] is left in INF-file, delete file
489 ::ucbhelper::Content
aContent(aURL
.GetURLNoPass(),Reference
<XCommandEnvironment
>(), comphelper::getProcessComponentContext());
490 aContent
.executeCommand( OUString("delete"), makeAny( true ) );
492 catch (const Exception
& e
)
494 (void)e
; // make compiler happy
495 // simply silent this. The strange algorithm here does a lot of
496 // things even if no files at all were created or accessed, so it's
497 // possible that the file we're trying to delete does not even
498 // exist, and this is a valid condition.
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */