LibreOffice Module dbaccess (master) 1
dbfindex.cxx
Go to the documentation of this file.
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"
22#include <osl/file.hxx>
23#include <osl/thread.hxx>
24#include <tools/config.hxx>
25#include <osl/diagnose.h>
27#include <tools/urlobj.hxx>
29#include <ucbhelper/content.hxx>
30#include <svl/filenotation.hxx>
31#include <rtl/strbuf.hxx>
32#include <utility>
33
34namespace dbaui
35{
36using namespace ::com::sun::star::uno;
37using namespace ::com::sun::star::ucb;
38using namespace ::svt;
39
40constexpr OStringLiteral aGroupIdent("dBase III");
41
42
43ODbaseIndexDialog::ODbaseIndexDialog(weld::Window * pParent, OUString aDataSrcName)
44 : GenericDialogController(pParent, "dbaccess/ui/dbaseindexdialog.ui", "DBaseIndexDialog")
45 , m_aDSN(std::move(aDataSrcName))
46 , m_xPB_OK(m_xBuilder->weld_button("ok"))
47 , m_xCB_Tables(m_xBuilder->weld_combo_box("table"))
48 , m_xIndexes(m_xBuilder->weld_widget("frame"))
49 , m_xLB_TableIndexes(m_xBuilder->weld_tree_view("tableindex"))
50 , m_xLB_FreeIndexes(m_xBuilder->weld_tree_view("freeindex"))
51 , m_xAdd(m_xBuilder->weld_button("add"))
52 , m_xRemove(m_xBuilder->weld_button("remove"))
53 , m_xAddAll(m_xBuilder->weld_button("addall"))
54 , m_xRemoveAll(m_xBuilder->weld_button("removeall"))
55{
56 int nWidth = m_xLB_TableIndexes->get_approximate_digit_width() * 18;
57 int nHeight = m_xLB_TableIndexes->get_height_rows(10);
58 m_xLB_TableIndexes->set_size_request(nWidth, nHeight);
59 m_xLB_FreeIndexes->set_size_request(nWidth, nHeight);
60
61 m_xCB_Tables->connect_changed( LINK(this, ODbaseIndexDialog, TableSelectHdl) );
62 m_xAdd->connect_clicked( LINK(this, ODbaseIndexDialog, AddClickHdl) );
63 m_xRemove->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveClickHdl) );
64 m_xAddAll->connect_clicked( LINK(this, ODbaseIndexDialog, AddAllClickHdl) );
65 m_xRemoveAll->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) );
66 m_xPB_OK->connect_clicked( LINK(this, ODbaseIndexDialog, OKClickHdl) );
67
68 m_xLB_FreeIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
69 m_xLB_TableIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
70
71 Init();
72 SetCtrls();
73}
74
76{
77}
78
80{
81 m_xAdd->set_sensitive(0 != m_xLB_FreeIndexes->count_selected_rows());
82 m_xAddAll->set_sensitive(0 != m_xLB_FreeIndexes->n_children());
83
84 m_xRemove->set_sensitive(0 != m_xLB_TableIndexes->count_selected_rows());
85 m_xRemoveAll->set_sensitive(0 != m_xLB_TableIndexes->n_children());
86}
87
88OTableIndex ODbaseIndexDialog::implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist)
89{
90 OTableIndex aReturn;
91
92 TableIndexList::iterator aSearch = std::find_if(_rList.begin(), _rList.end(),
93 [&_rName](const OTableIndex& rIndex) { return rIndex.GetIndexFileName() == _rName; });
94 if (aSearch != _rList.end())
95 {
96 sal_Int32 nPos = static_cast<sal_Int32>(std::distance(_rList.begin(), aSearch));
97
98 aReturn = *aSearch;
99
100 _rList.erase(aSearch);
101 _rDisplay.remove_text(_rName);
102
103 // adjust selection if necessary
104 if (static_cast<sal_uInt32>(nPos) == _rList.size())
105 _rDisplay.select(static_cast<sal_uInt16>(nPos)-1);
106 else
107 _rDisplay.select(static_cast<sal_uInt16>(nPos));
108 }
109 OSL_ENSURE(!_bMustExist || !aReturn.GetIndexFileName().isEmpty(), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
110 return aReturn;
111}
112
114{
115 _rList.push_front(_rIndex);
116 _rDisplay.append_text(_rIndex.GetIndexFileName());
117 _rDisplay.select(0);
118}
119
120OTableIndex ODbaseIndexDialog::RemoveTableIndex( std::u16string_view _rTableName, const OUString& _rIndexName )
121{
122 OTableIndex aReturn;
123
124 // does the table exist ?
125 TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
126 [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
127
128 if (aTablePos == m_aTableInfoList.end())
129 return aReturn;
130
131 return implRemoveIndex(_rIndexName, aTablePos->aIndexList, *m_xLB_TableIndexes, true/*_bMustExist*/);
132}
133
134void ODbaseIndexDialog::InsertTableIndex( std::u16string_view _rTableName, const OTableIndex& _rIndex)
135{
136 TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
137 [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
138
139 if (aTablePos == m_aTableInfoList.end())
140 return;
141
142 implInsertIndex(_rIndex, aTablePos->aIndexList, *m_xLB_TableIndexes);
143}
144
146{
147 // let all tables write their INF file
148
149 for (auto const& tableInfo : m_aTableInfoList)
150 tableInfo.WriteInfFile(m_aDSN);
151
152 m_xDialog->response(RET_OK);
153}
154
156{
157 OUString aSelection = m_xLB_FreeIndexes->get_selected_text();
158 OUString aTableName = m_xCB_Tables->get_active_text();
159 OTableIndex aIndex = RemoveFreeIndex( aSelection, true );
160 InsertTableIndex( aTableName, aIndex );
161
162 checkButtons();
163}
164
166{
167 OUString aSelection = m_xLB_TableIndexes->get_selected_text();
168 OUString aTableName = m_xCB_Tables->get_active_text();
169 OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection );
170 InsertFreeIndex( aIndex );
171
172 checkButtons();
173}
174
176{
177 const sal_Int32 nCnt = m_xLB_FreeIndexes->n_children();
178 OUString aTableName = m_xCB_Tables->get_active_text();
179
180 for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
181 InsertTableIndex(aTableName, RemoveFreeIndex(m_xLB_FreeIndexes->get_text(0), true));
182
183 checkButtons();
184}
185
187{
188 const sal_Int32 nCnt = m_xLB_TableIndexes->n_children();
189 OUString aTableName = m_xCB_Tables->get_active_text();
190
191 for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
192 InsertFreeIndex(RemoveTableIndex(aTableName, m_xLB_TableIndexes->get_text(0)));
193
194 checkButtons();
195}
196
198{
199 checkButtons();
200}
201
202IMPL_LINK(ODbaseIndexDialog, TableSelectHdl, weld::ComboBox&, rComboBox, void)
203{
204 // search the table
205 TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
206 [&] (const OTableInfo& arg) { return arg.aTableName == rComboBox.get_active_text() ; });
207
208 if (aTablePos == m_aTableInfoList.end())
209 return;
210
211 // fill the listbox for the indexes
212 m_xLB_TableIndexes->clear();
213 for (auto const& index : aTablePos->aIndexList)
214 m_xLB_TableIndexes->append_text(index.GetIndexFileName());
215
216 if (!aTablePos->aIndexList.empty())
217 m_xLB_TableIndexes->select(0);
218
219 checkButtons();
220}
221
223{
224 m_xPB_OK->set_sensitive(false);
225 m_xIndexes->set_sensitive(false);
226
227 // All indices are first added to a list of free indices.
228 // Afterwards, check the index of each table in the Inf-file.
229 // These indices are removed from the list of free indices and
230 // entered in the indexlist of the table.
231
232 // if the string does not contain a path, cut the string
234 aURL.SetSmartProtocol(INetProtocol::File);
235 {
236 SvtPathOptions aPathOptions;
237 m_aDSN = aPathOptions.SubstituteVariable(m_aDSN);
238 }
239 aURL.SetSmartURL(m_aDSN);
240
241 // String aFileName = aURL.PathToFileName();
244 bool bFolder=true;
245 try
246 {
248 bFolder = aFile.isFolder();
249 }
250 catch(Exception&)
251 {
252 return;
253 }
254
255 // first assume for all indexes they're free
256
257 std::vector< OUString > aUsedIndexes;
258
259 aURL.SetSmartProtocol(INetProtocol::File);
261 for(const OUString& rURL : aFolderUrls)
262 {
263 OUString aName;
264 osl::FileBase::getSystemPathFromFileURL(rURL,aName);
265 aURL.SetSmartURL(aName);
266 OUString aExt = aURL.getExtension();
267 if (aExt == "ndx")
268 {
269 m_aFreeIndexList.emplace_back(aURL.getName() );
270 }
271 else if (aExt == "dbf")
272 {
273 m_aTableInfoList.emplace_back(aURL.getName() );
274 OTableInfo& rTabInfo = m_aTableInfoList.back();
275
276 // open the INF file
277 aURL.setExtension(u"inf");
278 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
279 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
280 aInfFile.SetGroup( aGroupIdent );
281
282 // fill the indexes list
283 OString aNDX;
284 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
285 OString aKeyName;
286 OUString aEntry;
287
288 for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ )
289 {
290 // does the key point to an index file ?
291 aKeyName = aInfFile.GetKeyName( nKey );
292 aNDX = aKeyName.copy(0,3);
293
294 // yes -> add to the tables index list
295 if (aNDX == "NDX")
296 {
297 aEntry = OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding());
298 rTabInfo.aIndexList.emplace_back( aEntry );
299
300 // and remove it from the free index list
301 aUsedIndexes.push_back(aEntry);
302 // do this later below. We may not have encountered the index file, yet, thus we may not
303 // know the index as being free, yet
304 }
305 }
306 }
307 }
308
309 for (auto const& usedIndex : aUsedIndexes)
310 RemoveFreeIndex( usedIndex, false );
311
312 if (!m_aTableInfoList.empty())
313 {
314 m_xPB_OK->set_sensitive(true);
315 m_xIndexes->set_sensitive(true);
316 }
317
318 checkButtons();
319}
320
322{
323 // ComboBox tables
324 for (auto const& tableInfo : m_aTableInfoList)
325 m_xCB_Tables->append_text(tableInfo.aTableName);
326
327 // put the first dataset into Edit
328 if (!m_aTableInfoList.empty())
329 {
330 const OTableInfo& rTabInfo = m_aTableInfoList.front();
331 m_xCB_Tables->set_entry_text(rTabInfo.aTableName);
332
333 // build ListBox of the table indices
334 for (auto const& index : rTabInfo.aIndexList)
335 m_xLB_TableIndexes->append_text(index.GetIndexFileName());
336
337 if (!rTabInfo.aIndexList.empty())
338 m_xLB_TableIndexes->select(0);
339 }
340
341 // ListBox of the free indices
342 for (auto const& freeIndex : m_aFreeIndexList)
343 m_xLB_FreeIndexes->append_text(freeIndex.GetIndexFileName());
344
345 if (!m_aFreeIndexList.empty())
346 m_xLB_FreeIndexes->select(0);
347
348 TableSelectHdl(*m_xCB_Tables);
349 checkButtons();
350}
351
352void OTableInfo::WriteInfFile( const OUString& rDSN ) const
353{
354 // open INF file
356 aURL.SetSmartProtocol(INetProtocol::File);
357 OUString aDsn = rDSN;
358 {
359 SvtPathOptions aPathOptions;
360 aDsn = aPathOptions.SubstituteVariable(aDsn);
361 }
362 aURL.SetSmartURL(aDsn);
363 aURL.Append(aTableName);
364 aURL.setExtension(u"inf");
365
366 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
367 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
368 aInfFile.SetGroup( aGroupIdent );
369
370 // first, delete all table indices
371 OString aNDX;
372 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
373 sal_uInt16 nKey = 0;
374
375 while( nKey < nKeyCnt )
376 {
377 // Does the key point to an index file?...
378 OString aKeyName = aInfFile.GetKeyName( nKey );
379 aNDX = aKeyName.copy(0,3);
380
381 //...if yes, delete index file, nKey is at subsequent key
382 if (aNDX == "NDX")
383 {
384 aInfFile.DeleteKey(aKeyName);
385 nKeyCnt--;
386 }
387 else
388 nKey++;
389
390 }
391
392 // now add all saved indices
393 sal_uInt16 nPos = 0;
394 for (auto const& index : aIndexList)
395 {
396 OStringBuffer aKeyName("NDX");
397 if( nPos > 0 ) // first index contains no number
398 aKeyName.append(static_cast<sal_Int32>(nPos));
399 aInfFile.WriteKey(
400 aKeyName.makeStringAndClear(),
401 OUStringToOString(index.GetIndexFileName(),
402 osl_getThreadTextEncoding()));
403 ++nPos;
404 }
405
406 aInfFile.Flush();
407
408 // if only [dbase] is left in INF-file, delete file
409 if(nPos)
410 return;
411
412 try
413 {
415 aContent.executeCommand( "delete", Any( true ) );
416 }
417 catch (const Exception& )
418 {
419 // simply silent this. The strange algorithm here does a lot of
420 // things even if no files at all were created or accessed, so it's
421 // possible that the file we're trying to delete does not even
422 // exist, and this is a valid condition.
423 }
424}
425
426} // namespace
427
428/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XExecutableDialog > m_xDialog
void DeleteKey(std::string_view rKey)
OString GetKeyName(sal_uInt16 nKey) const
void SetGroup(const OString &rGroup)
sal_uInt16 GetKeyCount() const
void Flush()
OString ReadKey(const OString &rKey) const
void WriteKey(const OString &rKey, const OString &rValue)
OUString SubstituteVariable(const OUString &rVar) const
virtual ~ODbaseIndexDialog() override
Definition: dbfindex.cxx:75
TableInfoList m_aTableInfoList
Definition: dbfindex.hxx:68
std::unique_ptr< weld::Button > m_xAddAll
Definition: dbfindex.hxx:79
ODbaseIndexDialog(weld::Window *pParent, OUString aDataSrcName)
Definition: dbfindex.cxx:43
std::unique_ptr< weld::Button > m_xRemoveAll
Definition: dbfindex.hxx:80
std::unique_ptr< weld::TreeView > m_xLB_FreeIndexes
Definition: dbfindex.hxx:75
void InsertTableIndex(std::u16string_view _rTableName, const OTableIndex &_rIndex)
Definition: dbfindex.cxx:134
std::unique_ptr< weld::Button > m_xRemove
Definition: dbfindex.hxx:78
static void implInsertIndex(const OTableIndex &_rIndex, TableIndexList &_rList, weld::TreeView &_rDisplay)
Definition: dbfindex.cxx:113
OTableIndex RemoveFreeIndex(const OUString &_rName, bool _bMustExist)
Definition: dbfindex.hxx:97
std::unique_ptr< weld::Button > m_xAdd
Definition: dbfindex.hxx:77
static OTableIndex implRemoveIndex(const OUString &_rName, TableIndexList &_rList, weld::TreeView &_rDisplay, bool _bMustExist)
Definition: dbfindex.cxx:88
std::unique_ptr< weld::TreeView > m_xLB_TableIndexes
Definition: dbfindex.hxx:74
OTableIndex RemoveTableIndex(std::u16string_view _rTableName, const OUString &_rIndexName)
Definition: dbfindex.cxx:120
TableIndexList m_aFreeIndexList
Definition: dbfindex.hxx:69
std::unique_ptr< weld::Button > m_xPB_OK
Definition: dbfindex.hxx:71
std::unique_ptr< weld::Widget > m_xIndexes
Definition: dbfindex.hxx:73
std::unique_ptr< weld::ComboBox > m_xCB_Tables
Definition: dbfindex.hxx:72
represents a single dbf index
Definition: dbfindex.hxx:32
const OUString & GetIndexFileName() const
Definition: dbfindex.hxx:40
holds the INF file of a table
Definition: dbfindex.hxx:50
void WriteInfFile(const OUString &rDSN) const
Definition: dbfindex.cxx:352
TableIndexList aIndexList
Definition: dbfindex.hxx:54
OUString aTableName
Definition: dbfindex.hxx:53
OUString get(NOTATION _eOutputNotation) const
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
static css::uno::Sequence< OUString > GetFolderContents(const OUString &rFolder, bool bFolder)
void append_text(const OUString &rStr)
void remove_text(const OUString &rText)
virtual void select(int pos)=0
float u
std::deque< AttacherIndex_Impl > aIndex
URL aURL
Definition: intercept.cxx:87
OUString aName
sal_uInt16 nPos
@ Exception
Reference< XComponentContext > getProcessComponentContext()
IMPL_LINK_NOARG(OApplicationController, OnClipboardChanged, TransferableDataHelper *, void)
IMPL_LINK(OApplicationController, OnSelectContainer, void *, _pType, void)
constexpr OStringLiteral aGroupIdent("dBase III")
std::deque< OTableIndex > TableIndexList
Definition: dbfindex.hxx:43
index
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
RET_OK