summaryrefslogtreecommitdiffstats
path: root/dbaccess/source/ui/dlg/dbfindex.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/ui/dlg/dbfindex.cxx')
-rw-r--r--dbaccess/source/ui/dlg/dbfindex.cxx430
1 files changed, 430 insertions, 0 deletions
diff --git a/dbaccess/source/ui/dlg/dbfindex.cxx b/dbaccess/source/ui/dlg/dbfindex.cxx
new file mode 100644
index 000000000..89f74ab72
--- /dev/null
+++ b/dbaccess/source/ui/dlg/dbfindex.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "dbfindex.hxx"
+#include <comphelper/processfactory.hxx>
+#include <osl/file.hxx>
+#include <osl/thread.hxx>
+#include <tools/config.hxx>
+#include <osl/diagnose.h>
+#include <unotools/localfilehelper.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/pathoptions.hxx>
+#include <ucbhelper/content.hxx>
+#include <svl/filenotation.hxx>
+#include <rtl/strbuf.hxx>
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::svt;
+
+constexpr OStringLiteral aGroupIdent("dBase III");
+
+
+ODbaseIndexDialog::ODbaseIndexDialog(weld::Window * pParent, const OUString& aDataSrcName)
+ : GenericDialogController(pParent, "dbaccess/ui/dbaseindexdialog.ui", "DBaseIndexDialog")
+ , m_aDSN(aDataSrcName)
+ , m_xPB_OK(m_xBuilder->weld_button("ok"))
+ , m_xCB_Tables(m_xBuilder->weld_combo_box("table"))
+ , m_xIndexes(m_xBuilder->weld_widget("frame"))
+ , m_xLB_TableIndexes(m_xBuilder->weld_tree_view("tableindex"))
+ , m_xLB_FreeIndexes(m_xBuilder->weld_tree_view("freeindex"))
+ , m_xAdd(m_xBuilder->weld_button("add"))
+ , m_xRemove(m_xBuilder->weld_button("remove"))
+ , m_xAddAll(m_xBuilder->weld_button("addall"))
+ , m_xRemoveAll(m_xBuilder->weld_button("removeall"))
+{
+ int nWidth = m_xLB_TableIndexes->get_approximate_digit_width() * 18;
+ int nHeight = m_xLB_TableIndexes->get_height_rows(10);
+ m_xLB_TableIndexes->set_size_request(nWidth, nHeight);
+ m_xLB_FreeIndexes->set_size_request(nWidth, nHeight);
+
+ m_xCB_Tables->connect_changed( LINK(this, ODbaseIndexDialog, TableSelectHdl) );
+ m_xAdd->connect_clicked( LINK(this, ODbaseIndexDialog, AddClickHdl) );
+ m_xRemove->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveClickHdl) );
+ m_xAddAll->connect_clicked( LINK(this, ODbaseIndexDialog, AddAllClickHdl) );
+ m_xRemoveAll->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) );
+ m_xPB_OK->connect_clicked( LINK(this, ODbaseIndexDialog, OKClickHdl) );
+
+ m_xLB_FreeIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
+ m_xLB_TableIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) );
+
+ Init();
+ SetCtrls();
+}
+
+ODbaseIndexDialog::~ODbaseIndexDialog()
+{
+}
+
+void ODbaseIndexDialog::checkButtons()
+{
+ m_xAdd->set_sensitive(0 != m_xLB_FreeIndexes->count_selected_rows());
+ m_xAddAll->set_sensitive(0 != m_xLB_FreeIndexes->n_children());
+
+ m_xRemove->set_sensitive(0 != m_xLB_TableIndexes->count_selected_rows());
+ m_xRemoveAll->set_sensitive(0 != m_xLB_TableIndexes->n_children());
+}
+
+OTableIndex ODbaseIndexDialog::implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist)
+{
+ OTableIndex aReturn;
+
+ TableIndexList::iterator aSearch = std::find_if(_rList.begin(), _rList.end(),
+ [&_rName](const OTableIndex& rIndex) { return rIndex.GetIndexFileName() == _rName; });
+ if (aSearch != _rList.end())
+ {
+ sal_Int32 nPos = static_cast<sal_Int32>(std::distance(_rList.begin(), aSearch));
+
+ aReturn = *aSearch;
+
+ _rList.erase(aSearch);
+ _rDisplay.remove_text(_rName);
+
+ // adjust selection if necessary
+ if (static_cast<sal_uInt32>(nPos) == _rList.size())
+ _rDisplay.select(static_cast<sal_uInt16>(nPos)-1);
+ else
+ _rDisplay.select(static_cast<sal_uInt16>(nPos));
+ }
+ OSL_ENSURE(!_bMustExist || !aReturn.GetIndexFileName().isEmpty(), "ODbaseIndexDialog::implRemoveIndex : did not find the index!");
+ return aReturn;
+}
+
+void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, weld::TreeView& _rDisplay)
+{
+ _rList.push_front(_rIndex);
+ _rDisplay.append_text(_rIndex.GetIndexFileName());
+ _rDisplay.select(0);
+}
+
+OTableIndex ODbaseIndexDialog::RemoveTableIndex( std::u16string_view _rTableName, const OUString& _rIndexName )
+{
+ OTableIndex aReturn;
+
+ // does the table exist ?
+ TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
+ [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
+
+ if (aTablePos == m_aTableInfoList.end())
+ return aReturn;
+
+ return implRemoveIndex(_rIndexName, aTablePos->aIndexList, *m_xLB_TableIndexes, true/*_bMustExist*/);
+}
+
+void ODbaseIndexDialog::InsertTableIndex( std::u16string_view _rTableName, const OTableIndex& _rIndex)
+{
+ TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
+ [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; });
+
+ if (aTablePos == m_aTableInfoList.end())
+ return;
+
+ implInsertIndex(_rIndex, aTablePos->aIndexList, *m_xLB_TableIndexes);
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, OKClickHdl, weld::Button&, void)
+{
+ // let all tables write their INF file
+
+ for (auto const& tableInfo : m_aTableInfoList)
+ tableInfo.WriteInfFile(m_aDSN);
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, AddClickHdl, weld::Button&, void)
+{
+ OUString aSelection = m_xLB_FreeIndexes->get_selected_text();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+ OTableIndex aIndex = RemoveFreeIndex( aSelection, true );
+ InsertTableIndex( aTableName, aIndex );
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveClickHdl, weld::Button&, void)
+{
+ OUString aSelection = m_xLB_TableIndexes->get_selected_text();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+ OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection );
+ InsertFreeIndex( aIndex );
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, AddAllClickHdl, weld::Button&, void)
+{
+ const sal_Int32 nCnt = m_xLB_FreeIndexes->n_children();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+
+ for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
+ InsertTableIndex(aTableName, RemoveFreeIndex(m_xLB_FreeIndexes->get_text(0), true));
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveAllClickHdl, weld::Button&, void)
+{
+ const sal_Int32 nCnt = m_xLB_TableIndexes->n_children();
+ OUString aTableName = m_xCB_Tables->get_active_text();
+
+ for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos)
+ InsertFreeIndex(RemoveTableIndex(aTableName, m_xLB_TableIndexes->get_text(0)));
+
+ checkButtons();
+}
+
+IMPL_LINK_NOARG(ODbaseIndexDialog, OnListEntrySelected, weld::TreeView&, void)
+{
+ checkButtons();
+}
+
+IMPL_LINK(ODbaseIndexDialog, TableSelectHdl, weld::ComboBox&, rComboBox, void)
+{
+ // search the table
+ TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(),
+ [&] (const OTableInfo& arg) { return arg.aTableName == rComboBox.get_active_text() ; });
+
+ if (aTablePos == m_aTableInfoList.end())
+ return;
+
+ // fill the listbox for the indexes
+ m_xLB_TableIndexes->clear();
+ for (auto const& index : aTablePos->aIndexList)
+ m_xLB_TableIndexes->append_text(index.GetIndexFileName());
+
+ if (!aTablePos->aIndexList.empty())
+ m_xLB_TableIndexes->select(0);
+
+ checkButtons();
+}
+
+void ODbaseIndexDialog::Init()
+{
+ m_xPB_OK->set_sensitive(false);
+ m_xIndexes->set_sensitive(false);
+
+ // All indices are first added to a list of free indices.
+ // Afterwards, check the index of each table in the Inf-file.
+ // These indices are removed from the list of free indices and
+ // entered in the indexlist of the table.
+
+ // if the string does not contain a path, cut the string
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INetProtocol::File);
+ {
+ SvtPathOptions aPathOptions;
+ m_aDSN = aPathOptions.SubstituteVariable(m_aDSN);
+ }
+ aURL.SetSmartURL(m_aDSN);
+
+ // String aFileName = aURL.PathToFileName();
+ m_aDSN = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ ::ucbhelper::Content aFile;
+ bool bFolder=true;
+ try
+ {
+ aFile = ::ucbhelper::Content(m_aDSN,Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext());
+ bFolder = aFile.isFolder();
+ }
+ catch(Exception&)
+ {
+ return;
+ }
+
+ // first assume for all indexes they're free
+
+ OUString const aIndexExt("ndx");
+ OUString const aTableExt("dbf");
+
+ std::vector< OUString > aUsedIndexes;
+
+ aURL.SetSmartProtocol(INetProtocol::File);
+ const Sequence<OUString> aFolderUrls = ::utl::LocalFileHelper::GetFolderContents(m_aDSN, bFolder);
+ for(const OUString& rURL : aFolderUrls)
+ {
+ OUString aName;
+ osl::FileBase::getSystemPathFromFileURL(rURL,aName);
+ aURL.SetSmartURL(aName);
+ OUString aExt = aURL.getExtension();
+ if (aExt == aIndexExt)
+ {
+ m_aFreeIndexList.emplace_back(aURL.getName() );
+ }
+ else if (aExt == aTableExt)
+ {
+ m_aTableInfoList.emplace_back(aURL.getName() );
+ OTableInfo& rTabInfo = m_aTableInfoList.back();
+
+ // open the INF file
+ aURL.setExtension(u"inf");
+ OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
+ Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
+ aInfFile.SetGroup( aGroupIdent );
+
+ // fill the indexes list
+ OString aNDX;
+ sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
+ OString aKeyName;
+ OUString aEntry;
+
+ for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ )
+ {
+ // does the key point to an index file ?
+ aKeyName = aInfFile.GetKeyName( nKey );
+ aNDX = aKeyName.copy(0,3);
+
+ // yes -> add to the tables index list
+ if (aNDX == "NDX")
+ {
+ aEntry = OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding());
+ rTabInfo.aIndexList.emplace_back( aEntry );
+
+ // and remove it from the free index list
+ aUsedIndexes.push_back(aEntry);
+ // do this later below. We may not have encountered the index file, yet, thus we may not
+ // know the index as being free, yet
+ }
+ }
+ }
+ }
+
+ for (auto const& usedIndex : aUsedIndexes)
+ RemoveFreeIndex( usedIndex, false );
+
+ if (!m_aTableInfoList.empty())
+ {
+ m_xPB_OK->set_sensitive(true);
+ m_xIndexes->set_sensitive(true);
+ }
+
+ checkButtons();
+}
+
+void ODbaseIndexDialog::SetCtrls()
+{
+ // ComboBox tables
+ for (auto const& tableInfo : m_aTableInfoList)
+ m_xCB_Tables->append_text(tableInfo.aTableName);
+
+ // put the first dataset into Edit
+ if (!m_aTableInfoList.empty())
+ {
+ const OTableInfo& rTabInfo = m_aTableInfoList.front();
+ m_xCB_Tables->set_entry_text(rTabInfo.aTableName);
+
+ // build ListBox of the table indices
+ for (auto const& index : rTabInfo.aIndexList)
+ m_xLB_TableIndexes->append_text(index.GetIndexFileName());
+
+ if (!rTabInfo.aIndexList.empty())
+ m_xLB_TableIndexes->select(0);
+ }
+
+ // ListBox of the free indices
+ for (auto const& freeIndex : m_aFreeIndexList)
+ m_xLB_FreeIndexes->append_text(freeIndex.GetIndexFileName());
+
+ if (!m_aFreeIndexList.empty())
+ m_xLB_FreeIndexes->select(0);
+
+ TableSelectHdl(*m_xCB_Tables);
+ checkButtons();
+}
+
+void OTableInfo::WriteInfFile( const OUString& rDSN ) const
+{
+ // open INF file
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INetProtocol::File);
+ OUString aDsn = rDSN;
+ {
+ SvtPathOptions aPathOptions;
+ aDsn = aPathOptions.SubstituteVariable(aDsn);
+ }
+ aURL.SetSmartURL(aDsn);
+ aURL.Append(aTableName);
+ aURL.setExtension(u"inf");
+
+ OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL);
+ Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) );
+ aInfFile.SetGroup( aGroupIdent );
+
+ // first, delete all table indices
+ OString aNDX;
+ sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
+ sal_uInt16 nKey = 0;
+
+ while( nKey < nKeyCnt )
+ {
+ // Does the key point to an index file?...
+ OString aKeyName = aInfFile.GetKeyName( nKey );
+ aNDX = aKeyName.copy(0,3);
+
+ //...if yes, delete index file, nKey is at subsequent key
+ if (aNDX == "NDX")
+ {
+ aInfFile.DeleteKey(aKeyName);
+ nKeyCnt--;
+ }
+ else
+ nKey++;
+
+ }
+
+ // now add all saved indices
+ sal_uInt16 nPos = 0;
+ for (auto const& index : aIndexList)
+ {
+ OStringBuffer aKeyName("NDX");
+ if( nPos > 0 ) // first index contains no number
+ aKeyName.append(static_cast<sal_Int32>(nPos));
+ aInfFile.WriteKey(
+ aKeyName.makeStringAndClear(),
+ OUStringToOString(index.GetIndexFileName(),
+ osl_getThreadTextEncoding()));
+ ++nPos;
+ }
+
+ aInfFile.Flush();
+
+ // if only [dbase] is left in INF-file, delete file
+ if(nPos)
+ return;
+
+ try
+ {
+ ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
+ aContent.executeCommand( "delete", Any( true ) );
+ }
+ catch (const Exception& )
+ {
+ // simply silent this. The strange algorithm here does a lot of
+ // things even if no files at all were created or accessed, so it's
+ // possible that the file we're trying to delete does not even
+ // exist, and this is a valid condition.
+ }
+}
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */