android: Update app icon to new startcenter icon
[LibreOffice.git] / dbaccess / source / ui / dlg / dbfindex.cxx
blob061486e9120141207ce49dc818278277c2b36828
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <osl/file.hxx>
23 #include <osl/thread.hxx>
24 #include <tools/config.hxx>
25 #include <osl/diagnose.h>
26 #include <unotools/localfilehelper.hxx>
27 #include <tools/urlobj.hxx>
28 #include <unotools/pathoptions.hxx>
29 #include <ucbhelper/content.hxx>
30 #include <svl/filenotation.hxx>
31 #include <rtl/strbuf.hxx>
32 #include <utility>
34 namespace dbaui
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::ucb;
38 using namespace ::svt;
40 constexpr OStringLiteral aGroupIdent("dBase III");
43 ODbaseIndexDialog::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"))
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);
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) );
68 m_xLB_FreeIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
69 m_xLB_TableIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
71 Init();
72 SetCtrls();
75 ODbaseIndexDialog::~ODbaseIndexDialog()
79 void ODbaseIndexDialog::checkButtons()
81 m_xAdd->set_sensitive(0 != m_xLB_FreeIndexes->count_selected_rows());
82 m_xAddAll->set_sensitive(0 != m_xLB_FreeIndexes->n_children());
84 m_xRemove->set_sensitive(0 != m_xLB_TableIndexes->count_selected_rows());
85 m_xRemoveAll->set_sensitive(0 != m_xLB_TableIndexes->n_children());
88 OTableIndex ODbaseIndexDialog::implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist)
90 OTableIndex aReturn;
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())
96 sal_Int32 nPos = static_cast<sal_Int32>(std::distance(_rList.begin(), aSearch));
98 aReturn = *aSearch;
100 _rList.erase(aSearch);
101 _rDisplay.remove_text(_rName);
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));
109 OSL_ENSURE(!_bMustExist || !aReturn.GetIndexFileName().isEmpty(), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
110 return aReturn;
113 void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, weld::TreeView& _rDisplay)
115 _rList.push_front(_rIndex);
116 _rDisplay.append_text(_rIndex.GetIndexFileName());
117 _rDisplay.select(0);
120 OTableIndex ODbaseIndexDialog::RemoveTableIndex( std::u16string_view _rTableName, const OUString& _rIndexName )
122 OTableIndex aReturn;
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; });
128 if (aTablePos == m_aTableInfoList.end())
129 return aReturn;
131 return implRemoveIndex(_rIndexName, aTablePos->aIndexList, *m_xLB_TableIndexes, true/*_bMustExist*/);
134 void ODbaseIndexDialog::InsertTableIndex( std::u16string_view _rTableName, const OTableIndex& _rIndex)
136 TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
137 [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
139 if (aTablePos == m_aTableInfoList.end())
140 return;
142 implInsertIndex(_rIndex, aTablePos->aIndexList, *m_xLB_TableIndexes);
145 IMPL_LINK_NOARG(ODbaseIndexDialog, OKClickHdl, weld::Button&, void)
147 // let all tables write their INF file
149 for (auto const& tableInfo : m_aTableInfoList)
150 tableInfo.WriteInfFile(m_aDSN);
152 m_xDialog->response(RET_OK);
155 IMPL_LINK_NOARG(ODbaseIndexDialog, AddClickHdl, weld::Button&, void)
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 );
162 checkButtons();
165 IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveClickHdl, weld::Button&, void)
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 );
172 checkButtons();
175 IMPL_LINK_NOARG(ODbaseIndexDialog, AddAllClickHdl, weld::Button&, void)
177 const sal_Int32 nCnt = m_xLB_FreeIndexes->n_children();
178 OUString aTableName = m_xCB_Tables->get_active_text();
180 for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
181 InsertTableIndex(aTableName, RemoveFreeIndex(m_xLB_FreeIndexes->get_text(0), true));
183 checkButtons();
186 IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveAllClickHdl, weld::Button&, void)
188 const sal_Int32 nCnt = m_xLB_TableIndexes->n_children();
189 OUString aTableName = m_xCB_Tables->get_active_text();
191 for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
192 InsertFreeIndex(RemoveTableIndex(aTableName, m_xLB_TableIndexes->get_text(0)));
194 checkButtons();
197 IMPL_LINK_NOARG(ODbaseIndexDialog, OnListEntrySelected, weld::TreeView&, void)
199 checkButtons();
202 IMPL_LINK(ODbaseIndexDialog, TableSelectHdl, weld::ComboBox&, rComboBox, void)
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() ; });
208 if (aTablePos == m_aTableInfoList.end())
209 return;
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());
216 if (!aTablePos->aIndexList.empty())
217 m_xLB_TableIndexes->select(0);
219 checkButtons();
222 void ODbaseIndexDialog::Init()
224 m_xPB_OK->set_sensitive(false);
225 m_xIndexes->set_sensitive(false);
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.
232 // if the string does not contain a path, cut the string
233 INetURLObject aURL;
234 aURL.SetSmartProtocol(INetProtocol::File);
236 SvtPathOptions aPathOptions;
237 m_aDSN = aPathOptions.SubstituteVariable(m_aDSN);
239 aURL.SetSmartURL(m_aDSN);
241 // String aFileName = aURL.PathToFileName();
242 m_aDSN = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
243 ::ucbhelper::Content aFile;
244 bool bFolder=true;
247 aFile = ::ucbhelper::Content(m_aDSN,Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext());
248 bFolder = aFile.isFolder();
250 catch(Exception&)
252 return;
255 // first assume for all indexes they're free
257 OUString const aIndexExt("ndx");
258 OUString const aTableExt("dbf");
260 std::vector< OUString > aUsedIndexes;
262 aURL.SetSmartProtocol(INetProtocol::File);
263 const Sequence<OUString> aFolderUrls = ::utl::LocalFileHelper::GetFolderContents(m_aDSN, bFolder);
264 for(const OUString& rURL : aFolderUrls)
266 OUString aName;
267 osl::FileBase::getSystemPathFromFileURL(rURL,aName);
268 aURL.SetSmartURL(aName);
269 OUString aExt = aURL.getExtension();
270 if (aExt == aIndexExt)
272 m_aFreeIndexList.emplace_back(aURL.getName() );
274 else if (aExt == aTableExt)
276 m_aTableInfoList.emplace_back(aURL.getName() );
277 OTableInfo& rTabInfo = m_aTableInfoList.back();
279 // open the INF file
280 aURL.setExtension(u"inf");
281 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
282 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
283 aInfFile.SetGroup( aGroupIdent );
285 // fill the indexes list
286 OString aNDX;
287 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
288 OString aKeyName;
289 OUString aEntry;
291 for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ )
293 // does the key point to an index file ?
294 aKeyName = aInfFile.GetKeyName( nKey );
295 aNDX = aKeyName.copy(0,3);
297 // yes -> add to the tables index list
298 if (aNDX == "NDX")
300 aEntry = OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding());
301 rTabInfo.aIndexList.emplace_back( aEntry );
303 // and remove it from the free index list
304 aUsedIndexes.push_back(aEntry);
305 // do this later below. We may not have encountered the index file, yet, thus we may not
306 // know the index as being free, yet
312 for (auto const& usedIndex : aUsedIndexes)
313 RemoveFreeIndex( usedIndex, false );
315 if (!m_aTableInfoList.empty())
317 m_xPB_OK->set_sensitive(true);
318 m_xIndexes->set_sensitive(true);
321 checkButtons();
324 void ODbaseIndexDialog::SetCtrls()
326 // ComboBox tables
327 for (auto const& tableInfo : m_aTableInfoList)
328 m_xCB_Tables->append_text(tableInfo.aTableName);
330 // put the first dataset into Edit
331 if (!m_aTableInfoList.empty())
333 const OTableInfo& rTabInfo = m_aTableInfoList.front();
334 m_xCB_Tables->set_entry_text(rTabInfo.aTableName);
336 // build ListBox of the table indices
337 for (auto const& index : rTabInfo.aIndexList)
338 m_xLB_TableIndexes->append_text(index.GetIndexFileName());
340 if (!rTabInfo.aIndexList.empty())
341 m_xLB_TableIndexes->select(0);
344 // ListBox of the free indices
345 for (auto const& freeIndex : m_aFreeIndexList)
346 m_xLB_FreeIndexes->append_text(freeIndex.GetIndexFileName());
348 if (!m_aFreeIndexList.empty())
349 m_xLB_FreeIndexes->select(0);
351 TableSelectHdl(*m_xCB_Tables);
352 checkButtons();
355 void OTableInfo::WriteInfFile( const OUString& rDSN ) const
357 // open INF file
358 INetURLObject aURL;
359 aURL.SetSmartProtocol(INetProtocol::File);
360 OUString aDsn = rDSN;
362 SvtPathOptions aPathOptions;
363 aDsn = aPathOptions.SubstituteVariable(aDsn);
365 aURL.SetSmartURL(aDsn);
366 aURL.Append(aTableName);
367 aURL.setExtension(u"inf");
369 OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
370 Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
371 aInfFile.SetGroup( aGroupIdent );
373 // first, delete all table indices
374 OString aNDX;
375 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
376 sal_uInt16 nKey = 0;
378 while( nKey < nKeyCnt )
380 // Does the key point to an index file?...
381 OString aKeyName = aInfFile.GetKeyName( nKey );
382 aNDX = aKeyName.copy(0,3);
384 //...if yes, delete index file, nKey is at subsequent key
385 if (aNDX == "NDX")
387 aInfFile.DeleteKey(aKeyName);
388 nKeyCnt--;
390 else
391 nKey++;
395 // now add all saved indices
396 sal_uInt16 nPos = 0;
397 for (auto const& index : aIndexList)
399 OStringBuffer aKeyName("NDX");
400 if( nPos > 0 ) // first index contains no number
401 aKeyName.append(static_cast<sal_Int32>(nPos));
402 aInfFile.WriteKey(
403 aKeyName.makeStringAndClear(),
404 OUStringToOString(index.GetIndexFileName(),
405 osl_getThreadTextEncoding()));
406 ++nPos;
409 aInfFile.Flush();
411 // if only [dbase] is left in INF-file, delete file
412 if(nPos)
413 return;
417 ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
418 aContent.executeCommand( "delete", Any( true ) );
420 catch (const Exception& )
422 // simply silent this. The strange algorithm here does a lot of
423 // things even if no files at all were created or accessed, so it's
424 // possible that the file we're trying to delete does not even
425 // exist, and this is a valid condition.
429 } // namespace
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */