Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / dbaccess / source / ui / dlg / dbfindex.cxx
blob9f73597d6a2af9c29dc2aa395a2a4dd3573394f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "dbfindex.hxx"
32 #include <tools/config.hxx>
33 #include <sfx2/app.hxx>
34 #include "moduledbu.hxx"
35 #include "dbu_dlg.hrc"
36 #include "dbfindex.hrc"
37 #include <osl/diagnose.h>
38 #include <unotools/localfilehelper.hxx>
39 #include <tools/urlobj.hxx>
40 #include <unotools/pathoptions.hxx>
41 #include <ucbhelper/content.hxx>
42 #include <svl/filenotation.hxx>
43 #include <rtl/strbuf.hxx>
46 //.........................................................................
47 namespace dbaui
49 //.........................................................................
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::ucb;
53 using namespace ::svt;
55 const rtl::OString aGroupIdent(RTL_CONSTASCII_STRINGPARAM("dBase III"));
57 //////////////////////////////////////////////////////////////////////////
58 // Klasse ODbaseIndexDialog
59 DBG_NAME(ODbaseIndexDialog)
60 //-------------------------------------------------------------------------
61 ODbaseIndexDialog::ODbaseIndexDialog( Window * pParent, String aDataSrcName )
62 : ModalDialog( pParent, ModuleRes(DLG_DBASE_INDEXES) ),
63 aPB_OK( this, ModuleRes( PB_OK ) ),
64 aPB_CANCEL( this, ModuleRes( PB_CANCEL ) ),
65 aPB_HELP( this, ModuleRes( PB_HELP ) ),
66 m_FT_Tables( this, ModuleRes( FT_TABLES ) ),
67 aCB_Tables( this, ModuleRes( CB_TABLES ) ),
68 m_FL_Indexes( this, ModuleRes( FL_INDEXES ) ),
69 m_FT_TableIndexes( this, ModuleRes( FT_TABLEINDEXES ) ),
70 aLB_TableIndexes( this, ModuleRes( LB_TABLEINDEXES ) ),
71 m_FT_AllIndexes( this, ModuleRes( FT_ALLINDEXES ) ),
72 aLB_FreeIndexes( this, ModuleRes( LB_FREEINDEXES ) ),
73 aIB_Add( this, ModuleRes( IB_ADD ) ),
74 aIB_Remove( this, ModuleRes( IB_REMOVE ) ),
75 aIB_AddAll( this, ModuleRes( IB_ADDALL ) ),
76 aIB_RemoveAll( this, ModuleRes( IB_REMOVEALL ) ),
77 m_aDSN(aDataSrcName),
78 m_bCaseSensitiv(sal_True)
80 DBG_CTOR(ODbaseIndexDialog,NULL);
82 aCB_Tables.SetSelectHdl( LINK(this, ODbaseIndexDialog, TableSelectHdl) );
83 aIB_Add.SetClickHdl( LINK(this, ODbaseIndexDialog, AddClickHdl) );
84 aIB_Remove.SetClickHdl( LINK(this, ODbaseIndexDialog, RemoveClickHdl) );
85 aIB_AddAll.SetClickHdl( LINK(this, ODbaseIndexDialog, AddAllClickHdl) );
86 aIB_RemoveAll.SetClickHdl( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) );
87 aPB_OK.SetClickHdl( LINK(this, ODbaseIndexDialog, OKClickHdl) );
89 aLB_FreeIndexes.SetSelectHdl( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
90 aLB_TableIndexes.SetSelectHdl( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
92 aCB_Tables.SetDropDownLineCount(8);
93 Init();
94 SetCtrls();
95 FreeResource();
98 //-------------------------------------------------------------------------
99 ODbaseIndexDialog::~ODbaseIndexDialog()
102 DBG_DTOR(ODbaseIndexDialog,NULL);
105 //-------------------------------------------------------------------------
106 sal_Bool ODbaseIndexDialog::GetTable(const String& _rName, TableInfoListIterator& _rPosition)
108 for ( _rPosition = m_aTableInfoList.begin();
109 _rPosition != m_aTableInfoList.end();
110 ++_rPosition
113 if (m_bCaseSensitiv)
115 if (_rPosition->aTableName.Equals(_rName))
116 return sal_True;
118 else
120 if (_rPosition->aTableName.EqualsIgnoreCaseAscii(_rName))
121 return sal_True;
124 return sal_False;
127 //-------------------------------------------------------------------------
128 void ODbaseIndexDialog::checkButtons()
130 aIB_Add.Enable(0 != aLB_FreeIndexes.GetSelectEntryCount());
131 aIB_AddAll.Enable(0 != aLB_FreeIndexes.GetEntryCount());
133 aIB_Remove.Enable(0 != aLB_TableIndexes.GetSelectEntryCount());
134 aIB_RemoveAll.Enable(0 != aLB_TableIndexes.GetEntryCount());
137 //-------------------------------------------------------------------------
138 OTableIndex ODbaseIndexDialog::implRemoveIndex(const String& _rName, TableIndexList& _rList, ListBox& _rDisplay, sal_Bool _bMustExist)
140 OTableIndex aReturn;
142 sal_Int32 nPos = 0;
144 TableIndexListIterator aSearch;
145 for ( aSearch = _rList.begin();
146 aSearch != _rList.end();
147 ++aSearch, ++nPos
150 if ( m_bCaseSensitiv ? aSearch->GetIndexFileName().Equals(_rName) : aSearch->GetIndexFileName().EqualsIgnoreCaseAscii(_rName) )
152 aReturn = *aSearch;
154 _rList.erase(aSearch);
155 _rDisplay.RemoveEntry( _rName );
157 // adjust selection if necessary
158 if ((sal_uInt32)nPos == _rList.size())
159 _rDisplay.SelectEntryPos((sal_uInt16)nPos-1);
160 else
161 _rDisplay.SelectEntryPos((sal_uInt16)nPos);
163 break;
167 (void)_bMustExist;
168 OSL_ENSURE(!_bMustExist || (aSearch != _rList.end()), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
169 return aReturn;
172 //-------------------------------------------------------------------------
173 void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, ListBox& _rDisplay)
175 _rList.push_front( _rIndex );
176 _rDisplay.InsertEntry( _rIndex.GetIndexFileName() );
177 _rDisplay.SelectEntryPos(0);
180 //-------------------------------------------------------------------------
181 OTableIndex ODbaseIndexDialog::RemoveTableIndex( const String& _rTableName, const String& _rIndexName, sal_Bool _bMustExist )
183 OTableIndex aReturn;
185 // does the table exist ?
186 TableInfoListIterator aTablePos;
187 if (!GetTable(_rTableName, aTablePos))
188 return aReturn;
190 return implRemoveIndex(_rIndexName, aTablePos->aIndexList, aLB_TableIndexes, _bMustExist);
193 //-------------------------------------------------------------------------
194 void ODbaseIndexDialog::InsertTableIndex( const String& _rTableName, const OTableIndex& _rIndex)
196 TableInfoListIterator aTablePos;
197 if (!GetTable(_rTableName, aTablePos))
198 return;
200 implInsertIndex(_rIndex, aTablePos->aIndexList, aLB_TableIndexes);
203 //-------------------------------------------------------------------------
204 IMPL_LINK( ODbaseIndexDialog, OKClickHdl, PushButton*, /*pButton*/ )
206 // let all tables write their INF file
208 for ( ConstTableInfoListIterator aLoop = m_aTableInfoList.begin();
209 aLoop != m_aTableInfoList.end();
210 ++aLoop
212 aLoop->WriteInfFile(m_aDSN);
214 EndDialog();
215 return 0;
218 //-------------------------------------------------------------------------
219 IMPL_LINK( ODbaseIndexDialog, AddClickHdl, PushButton*, /*pButton*/ )
221 String aSelection = aLB_FreeIndexes.GetSelectEntry();
222 String aTableName = aCB_Tables.GetText();
223 OTableIndex aIndex = RemoveFreeIndex( aSelection, sal_True );
224 InsertTableIndex( aTableName, aIndex );
226 checkButtons();
227 return 0;
230 //-------------------------------------------------------------------------
231 IMPL_LINK( ODbaseIndexDialog, RemoveClickHdl, PushButton*, /*pButton*/ )
233 String aSelection = aLB_TableIndexes.GetSelectEntry();
234 String aTableName = aCB_Tables.GetText();
235 OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection, sal_True );
236 InsertFreeIndex( aIndex );
238 checkButtons();
239 return 0;
242 //-------------------------------------------------------------------------
243 IMPL_LINK( ODbaseIndexDialog, AddAllClickHdl, PushButton*, /*pButton*/ )
245 sal_uInt16 nCnt = aLB_FreeIndexes.GetEntryCount();
246 String aTableName = aCB_Tables.GetText();
248 for( sal_uInt16 nPos = 0; nPos < nCnt; ++nPos )
249 InsertTableIndex( aTableName, RemoveFreeIndex( aLB_FreeIndexes.GetEntry(0), sal_True ) );
251 checkButtons();
252 return 0;
255 //-------------------------------------------------------------------------
256 IMPL_LINK( ODbaseIndexDialog, RemoveAllClickHdl, PushButton*, /*pButton*/ )
258 sal_uInt16 nCnt = aLB_TableIndexes.GetEntryCount();
259 String aTableName = aCB_Tables.GetText();
261 for( sal_uInt16 nPos = 0; nPos < nCnt; ++nPos )
262 InsertFreeIndex( RemoveTableIndex( aTableName, aLB_TableIndexes.GetEntry(0), sal_True ) );
264 checkButtons();
265 return 0;
268 //-------------------------------------------------------------------------
269 IMPL_LINK( ODbaseIndexDialog, OnListEntrySelected, ListBox*, /*NOTINTERESTEDIN*/ )
271 checkButtons();
272 return 0;
275 //-------------------------------------------------------------------------
276 IMPL_LINK( ODbaseIndexDialog, TableSelectHdl, ComboBox*, pComboBox )
278 // search the table
279 TableInfoListIterator aTablePos;
280 if (!GetTable(pComboBox->GetText(), aTablePos))
281 return 0L;
283 // fill the listbox for the indexes
284 aLB_TableIndexes.Clear();
285 for ( ConstTableIndexListIterator aLoop = aTablePos->aIndexList.begin();
286 aLoop != aTablePos->aIndexList.end();
287 ++aLoop
289 aLB_TableIndexes.InsertEntry( aLoop->GetIndexFileName() );
291 if ( aTablePos->aIndexList.size() )
292 aLB_TableIndexes.SelectEntryPos(0);
294 checkButtons();
295 return 0;
298 //-------------------------------------------------------------------------
299 void ODbaseIndexDialog::Init()
301 aPB_OK.Disable();
302 m_FL_Indexes.Disable();
303 m_FT_TableIndexes.Disable();
304 aLB_TableIndexes.Disable();
305 m_FT_AllIndexes.Disable();
306 aLB_FreeIndexes.Disable();
307 aIB_Add.Disable();
308 aIB_Remove.Disable();
309 aIB_AddAll.Disable();
310 aIB_RemoveAll.Disable();
312 ///////////////////////////////////////////////////////////////////////////
313 // Alle Indizes werden erst einmal zur Liste der freien Indizes hinzugefuegt.
314 // Dann wird fuer jede Tabelle in der Inf-Datei nachgeschaut, welche Indizes sie besitzt.
315 // Diese Indizes werden aus der Liste der freien Indizes entfernt
316 // und in die Indexliste der Tabelle eingetragen
318 ///////////////////////////////////////////////////////////////////////////
319 // if the string does not contain a path, cut the string
320 INetURLObject aURL;
321 aURL.SetSmartProtocol(INET_PROT_FILE);
323 SvtPathOptions aPathOptions;
324 m_aDSN = aPathOptions.SubstituteVariable(m_aDSN);
326 aURL.SetSmartURL(m_aDSN);
329 // String aFileName = aURL.PathToFileName();
330 m_aDSN = aURL.GetMainURL(INetURLObject::NO_DECODE);
331 ::ucbhelper::Content aFile;
332 sal_Bool bFolder=sal_True;
335 aFile = ::ucbhelper::Content(m_aDSN,Reference< ::com::sun::star::ucb::XCommandEnvironment >());
336 bFolder = aFile.isFolder();
338 catch(Exception&)
340 return;
343 ///////////////////////////////////////////////////////////////////////////
344 // first assume for all indexes they're free
346 Sequence< ::rtl::OUString> aFolderContent( ::utl::LocalFileHelper::GetFolderContents(m_aDSN,bFolder));
348 ::rtl::OUString aIndexExt(RTL_CONSTASCII_USTRINGPARAM("ndx"));
349 ::rtl::OUString aTableExt(RTL_CONSTASCII_USTRINGPARAM("dbf"));
351 ::std::vector< String > aUsedIndexes;
353 String aExt;
354 const ::rtl::OUString *pBegin = aFolderContent.getConstArray();
355 const ::rtl::OUString *pEnd = pBegin + aFolderContent.getLength();
356 aURL.SetSmartProtocol(INET_PROT_FILE);
357 for(;pBegin != pEnd;++pBegin)
359 rtl::OUString aName;
360 ::utl::LocalFileHelper::ConvertURLToPhysicalName(pBegin->getStr(),aName);
361 aURL.SetSmartURL(aName);
362 aExt = aURL.getExtension();
363 if(aExt == aIndexExt.getStr())
365 m_aFreeIndexList.push_back( OTableIndex(aURL.getName()) );
367 else if(aExt == aTableExt.getStr())
369 m_aTableInfoList.push_back( OTableInfo(aURL.getName()) );
370 OTableInfo& rTabInfo = m_aTableInfoList.back();
372 // open the INF file
373 aURL.setExtension(String::CreateFromAscii("inf"));
374 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
375 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
376 aInfFile.SetGroup( aGroupIdent );
378 ///////////////////////////////////////////////////////////////////////////
379 // fill the indexes list
380 rtl::OString aNDX;
381 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
382 rtl::OString aKeyName;
383 String aEntry;
385 for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ )
387 // does the key point to an index file ?
388 aKeyName = aInfFile.GetKeyName( nKey );
389 aNDX = aKeyName.copy(0,3);
391 // yes -> add to the tables index list
392 if (aNDX.equalsL(RTL_CONSTASCII_STRINGPARAM("NDX")))
394 aEntry = rtl::OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding());
395 rTabInfo.aIndexList.push_back( OTableIndex( aEntry ) );
397 // and remove it from the free index list
398 aUsedIndexes.push_back(aEntry);
399 // do this later below. We may not have encountered the index file, yet, thus we may not
400 // know the index as beeing free, yet
407 for ( ::std::vector< String >::const_iterator aUsedIndex = aUsedIndexes.begin();
408 aUsedIndex != aUsedIndexes.end();
409 ++aUsedIndex
411 RemoveFreeIndex( *aUsedIndex, sal_False );
413 if (m_aTableInfoList.size())
415 aPB_OK.Enable();
416 m_FL_Indexes.Enable();
417 m_FT_TableIndexes.Enable();
418 aLB_TableIndexes.Enable();
419 m_FT_AllIndexes.Enable();
420 aLB_FreeIndexes.Enable();
423 checkButtons();
426 //-------------------------------------------------------------------------
427 void ODbaseIndexDialog::SetCtrls()
429 // ComboBox Tabellen
430 for ( ConstTableInfoListIterator aLoop = m_aTableInfoList.begin();
431 aLoop != m_aTableInfoList.end();
432 ++aLoop
434 aCB_Tables.InsertEntry( aLoop->aTableName );
436 // Den ersten Datensatz ins Edit stellen
437 if( m_aTableInfoList.size() )
439 const OTableInfo& rTabInfo = m_aTableInfoList.front();
440 aCB_Tables.SetText( rTabInfo.aTableName );
442 // ListBox der Tabellenindizes aufbauen
443 for ( ConstTableIndexListIterator aIndex = rTabInfo.aIndexList.begin();
444 aIndex != rTabInfo.aIndexList.end();
445 ++aIndex
447 aLB_TableIndexes.InsertEntry( aIndex->GetIndexFileName() );
449 if( rTabInfo.aIndexList.size() )
450 aLB_TableIndexes.SelectEntryPos( 0 );
454 // ListBox freie Indizes
455 for ( ConstTableIndexListIterator aFree = m_aFreeIndexList.begin();
456 aFree != m_aFreeIndexList.end();
457 ++aFree
459 aLB_FreeIndexes.InsertEntry( aFree->GetIndexFileName() );
461 if( m_aFreeIndexList.size() )
462 aLB_FreeIndexes.SelectEntryPos( 0 );
465 TableSelectHdl(&aCB_Tables);
466 checkButtons();
469 //////////////////////////////////////////////////////////////////////////
470 // Klasse OTableInfo
471 //-------------------------------------------------------------------------
472 void OTableInfo::WriteInfFile( const String& rDSN ) const
474 // INF-Datei oeffnen
475 INetURLObject aURL;
476 aURL.SetSmartProtocol(INET_PROT_FILE);
477 String aDsn = rDSN;
479 SvtPathOptions aPathOptions;
480 aDsn = aPathOptions.SubstituteVariable(aDsn);
482 aURL.SetSmartURL(aDsn);
483 aURL.Append(aTableName);
484 aURL.setExtension(String::CreateFromAscii("inf"));
486 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
487 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
488 aInfFile.SetGroup( aGroupIdent );
490 // Erst einmal alle Tabellenindizes loeschen
491 rtl::OString aNDX;
492 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
493 sal_uInt16 nKey = 0;
495 while( nKey < nKeyCnt )
497 // Verweist der Key auf ein Indexfile?...
498 rtl::OString aKeyName = aInfFile.GetKeyName( nKey );
499 aNDX = aKeyName.copy(0,3);
501 //...wenn ja, Indexfile loeschen, nKey steht dann auf nachfolgendem Key
502 if (aNDX.equalsL(RTL_CONSTASCII_STRINGPARAM("NDX")))
504 aInfFile.DeleteKey(aKeyName);
505 nKeyCnt--;
507 else
508 nKey++;
512 // Jetzt alle gespeicherten Indizes hinzufuegen
513 sal_uInt16 nPos = 0;
514 for ( ConstTableIndexListIterator aIndex = aIndexList.begin();
515 aIndex != aIndexList.end();
516 ++aIndex, ++nPos
519 rtl::OStringBuffer aKeyName(RTL_CONSTASCII_STRINGPARAM("NDX"));
520 if( nPos > 0 ) // Erster Index erhaelt keine Ziffer
521 aKeyName.append(static_cast<sal_Int32>(nPos));
522 aInfFile.WriteKey(
523 aKeyName.makeStringAndClear(),
524 rtl::OUStringToOString(aIndex->GetIndexFileName(),
525 osl_getThreadTextEncoding()));
528 aInfFile.Flush();
530 // Falls nur noch [dbase] in INF-File steht, Datei loeschen
531 if(!nPos)
535 ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>());
536 aContent.executeCommand( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("delete")),makeAny( sal_Bool( sal_True ) ) );
538 catch (const Exception& e )
540 (void)e; // make compiler happy
541 // simply silent this. The strange algorithm here does a lot of things even if no files at all were
542 // created or accessed, so it's possible that the file we're trying to delete does not even exist,
543 // and this is a valid condition.
548 //.........................................................................
549 } // namespace dbaui
550 //.........................................................................
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */