diff options
Diffstat (limited to '')
-rw-r--r-- | dbaccess/source/ui/dlg/indexdialog.cxx | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/dbaccess/source/ui/dlg/indexdialog.cxx b/dbaccess/source/ui/dlg/indexdialog.cxx new file mode 100644 index 000000000..978fa9f36 --- /dev/null +++ b/dbaccess/source/ui/dlg/indexdialog.cxx @@ -0,0 +1,707 @@ +/* -*- 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 <sal/config.h> + +#include <set> + +#include <core_resource.hxx> +#include <indexdialog.hxx> +#include <strings.hrc> +#include <bitmaps.hlst> +#include <indexfieldscontrol.hxx> +#include <indexcollection.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <connectivity/dbtools.hxx> +#include <osl/diagnose.h> + +namespace dbaui +{ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::lang; + using namespace ::dbtools; + + // helper + static bool operator ==(const OIndexField& _rLHS, const OIndexField& _rRHS) + { + return (_rLHS.sFieldName == _rRHS.sFieldName) + && (_rLHS.bSortAscending == _rRHS.bSortAscending); + } + + static bool operator ==(const IndexFields& _rLHS, const IndexFields& _rRHS) + { + return std::equal(_rLHS.begin(), _rLHS.end(), _rRHS.begin(), _rRHS.end()); + } + + static bool operator !=(const IndexFields& _rLHS, const IndexFields& _rRHS) + { + return !(_rLHS == _rRHS); + } + + // DbaIndexDialog + DbaIndexDialog::DbaIndexDialog(weld::Window* pParent, const Sequence< OUString >& _rFieldNames, + const Reference< XNameAccess >& _rxIndexes, + const Reference< XConnection >& _rxConnection, + const Reference< XComponentContext >& _rxContext) + : GenericDialogController(pParent, "dbaccess/ui/indexdesigndialog.ui", "IndexDesignDialog") + , m_xConnection(_rxConnection) + , m_bEditingActive(false) + , m_bEditAgain(false) + , m_bNoHandlerCall(false) + , m_xContext(_rxContext) + , m_xActions(m_xBuilder->weld_toolbar("ACTIONS")) + , m_xIndexList(m_xBuilder->weld_tree_view("INDEX_LIST")) + , m_xIndexDetails(m_xBuilder->weld_label("INDEX_DETAILS")) + , m_xDescriptionLabel(m_xBuilder->weld_label("DESC_LABEL")) + , m_xDescription(m_xBuilder->weld_label("DESCRIPTION")) + , m_xUnique(m_xBuilder->weld_check_button("UNIQUE")) + , m_xFieldsLabel(m_xBuilder->weld_label("FIELDS_LABEL")) + , m_xClose(m_xBuilder->weld_button("close")) + , m_xTable(m_xBuilder->weld_container("FIELDS")) + , m_xTableCtrlParent(m_xTable->CreateChildFrame()) + , m_xFields(VclPtr<IndexFieldsControl>::Create(m_xTableCtrlParent)) + { + m_xIndexList->set_size_request(m_xIndexList->get_approximate_digit_width() * 17, + m_xIndexList->get_height_rows(12)); + + int nWidth = m_xIndexList->get_approximate_digit_width() * 60; + int nHeight = m_xIndexList->get_height_rows(8); + m_xTable->set_size_request(nWidth, nHeight); + + m_xActions->connect_clicked(LINK(this, DbaIndexDialog, OnIndexAction)); + + m_xIndexList->connect_changed(LINK(this, DbaIndexDialog, OnIndexSelected)); + m_xIndexList->connect_editing(LINK(this, DbaIndexDialog, OnEntryEditing), + LINK(this, DbaIndexDialog, OnEntryEdited)); + + m_xFields->SetSizePixel(Size(nWidth, 100)); + m_xFields->Init(_rFieldNames, ::dbtools::getBooleanDataSourceSetting( m_xConnection, "AddIndexAppendix" )); + m_xFields->Show(); + + m_xIndexes.reset(new OIndexCollection()); + try + { + m_xIndexes->attach(_rxIndexes); + } + catch(SQLException& e) + { + ::dbtools::showError(SQLExceptionInfo(e), pParent->GetXWindow(), _rxContext); + } + catch(Exception&) + { + OSL_FAIL("DbaIndexDialog::DbaIndexDialog: could not retrieve basic information from the UNO collection!"); + } + + fillIndexList(); + + m_xUnique->connect_clicked(LINK(this, DbaIndexDialog, OnModifiedClick)); + m_xFields->SetModifyHdl(LINK(this, DbaIndexDialog, OnModified)); + + m_xClose->connect_clicked(LINK(this, DbaIndexDialog, OnCloseDialog)); + + // if all of the indexes have an empty description, we're not interested in displaying it + bool bFound = false; + for (auto const& check : *m_xIndexes) + { + if (!check.sDescription.isEmpty()) + { + bFound = true; + break; + } + } + if (!bFound) + { + // hide the controls which are necessary for the description + m_xDescription->hide(); + m_xDescriptionLabel->hide(); + } + } + + void DbaIndexDialog::updateToolbox() + { + m_xActions->set_item_sensitive("ID_INDEX_NEW", !m_bEditingActive); + + int nSelected = m_xIndexList->get_selected_index(); + bool bSelectedAnything = nSelected != -1; + if (bSelectedAnything) + { + // is the current entry modified? + Indexes::const_iterator aSelectedPos = m_xIndexes->begin() + m_xIndexList->get_id(nSelected).toUInt32(); + m_xActions->set_item_sensitive("ID_INDEX_SAVE", aSelectedPos->isModified() || aSelectedPos->isNew()); + m_xActions->set_item_sensitive("ID_INDEX_RESET", aSelectedPos->isModified() || aSelectedPos->isNew()); + bSelectedAnything = !aSelectedPos->bPrimaryKey; + } + else + { + m_xActions->set_item_sensitive("ID_INDEX_SAVE", false); + m_xActions->set_item_sensitive("ID_INDEX_RESET", false); + } + m_xActions->set_item_sensitive("ID_INDEX_DROP", bSelectedAnything); + m_xActions->set_item_sensitive("ID_INDEX_RENAME", bSelectedAnything); + } + + void DbaIndexDialog::fillIndexList() + { + OUString aPKeyIcon(BMP_PKEYICON); + // fill the list with the index names + m_xIndexList->clear(); + sal_uInt32 nPos = 0; + for (auto const& indexLoop : *m_xIndexes) + { + m_xIndexList->append(OUString::number(nPos), indexLoop.sName); + if (indexLoop.bPrimaryKey) + m_xIndexList->set_image(nPos, aPKeyIcon); + ++nPos; + } + + if (nPos) + m_xIndexList->select(0); + + IndexSelected(); + } + + DbaIndexDialog::~DbaIndexDialog( ) + { + m_xIndexes.reset(); + m_xFields.disposeAndClear(); + m_xTableCtrlParent->dispose(); + m_xTableCtrlParent.clear(); + } + + bool DbaIndexDialog::implCommit(const weld::TreeIter* pEntry) + { + assert(pEntry && "DbaIndexDialog::implCommit: invalid entry!"); + + Indexes::iterator aCommitPos = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32(); + + // if it's not a new index, remove it + // (we can't modify indexes, only drop'n'insert) + if (!aCommitPos->isNew()) + if (!implDropIndex(pEntry, false)) + return false; + + // create the new index + SQLExceptionInfo aExceptionInfo; + try + { + m_xIndexes->commitNewIndex(aCommitPos); + } + catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); } + + // reflect the new selection in the toolbox + updateToolbox(); + + if (aExceptionInfo.isValid()) + showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext); + else + { + m_xUnique->save_state(); + m_xFields->SaveValue(); + } + + return !aExceptionInfo.isValid(); + } + + void DbaIndexDialog::OnNewIndex() + { + // commit the current entry, if necessary + if (!implCommitPreviouslySelected()) + return; + + // get a new unique name for the new index + OUString sNewIndexName; + const OUString sNewIndexNameBase(DBA_RES(STR_LOGICAL_INDEX_NAME)); + sal_Int32 i; + + for ( i = 1; i < 0x7FFFFFFF; ++i ) + { + sNewIndexName = sNewIndexNameBase + OUString::number(i); + if (m_xIndexes->end() == m_xIndexes->find(sNewIndexName)) + break; + } + if (i == 0x7FFFFFFF) + { + OSL_FAIL("DbaIndexDialog::OnNewIndex: no free index name found!"); + // can't do anything ... of course we try another base, but this could end with the same result ... + return; + } + + std::unique_ptr<weld::TreeIter> xNewEntry(m_xIndexList->make_iterator()); + m_xIndexList->insert(nullptr, -1, &sNewIndexName, nullptr, nullptr, nullptr, nullptr, false, xNewEntry.get()); + m_xIndexes->insert(sNewIndexName); + + // update the user data on the entries in the list box: + // they're iterators of the index collection, and thus they have changed when removing the index + m_xIndexList->all_foreach([this](weld::TreeIter& rEntry){ + Indexes::const_iterator aAfterInsertPos = m_xIndexes->find(m_xIndexList->get_text(rEntry)); + OSL_ENSURE(aAfterInsertPos != m_xIndexes->end(), "DbaIndexDialog::OnNewIndex: problems with one of the entries!"); + m_xIndexList->set_id(rEntry, OUString::number(aAfterInsertPos - m_xIndexes->begin())); + return false; + }); + + // select the entry and start in-place editing + m_bNoHandlerCall = true; + m_xIndexList->select(*xNewEntry); + m_bNoHandlerCall = false; + IndexSelected(); + m_xIndexList->grab_focus(); + m_xIndexList->start_editing(*xNewEntry); + updateToolbox(); + } + + void DbaIndexDialog::OnDropIndex(bool _bConfirm) + { + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + // the selected index + if (!m_xIndexList->get_selected(xSelected.get())) + return; + + // let the user confirm the drop + if (_bConfirm) + { + OUString sConfirm(DBA_RES(STR_CONFIRM_DROP_INDEX)); + sConfirm = sConfirm.replaceFirst("$name$", m_xIndexList->get_text(*xSelected)); + std::unique_ptr<weld::MessageDialog> xConfirm(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + sConfirm)); + if (RET_YES != xConfirm->run()) + return; + } + + // do the drop + implDropIndex(xSelected.get(), true); + + // reflect the new selection in the toolbox + updateToolbox(); + } + + bool DbaIndexDialog::implDropIndex(const weld::TreeIter* pEntry, bool _bRemoveFromCollection) + { + // do the drop + Indexes::iterator aDropPos = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32(); + OSL_ENSURE(aDropPos != m_xIndexes->end(), "DbaIndexDialog::OnDropIndex: did not find the index in my collection!"); + + SQLExceptionInfo aExceptionInfo; + bool bSuccess = false; + try + { + if (_bRemoveFromCollection) + bSuccess = m_xIndexes->drop(aDropPos); + else + bSuccess = m_xIndexes->dropNoRemove(aDropPos); + } + catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); } + + if (aExceptionInfo.isValid()) + showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext); + else if (bSuccess && _bRemoveFromCollection) + { + m_bNoHandlerCall = true; + + // if the entry to remove is the selected on... + if (m_xPreviousSelection && m_xPreviousSelection->equal(*pEntry)) + m_xPreviousSelection.reset(); + m_xIndexList->remove(*pEntry); + + m_bNoHandlerCall = false; + + // update the user data on the entries in the list box: + // they're iterators of the index collection, and thus they have changed when removing the index + m_xIndexList->all_foreach([this](weld::TreeIter& rEntry){ + Indexes::const_iterator aAfterDropPos = m_xIndexes->find(m_xIndexList->get_text(rEntry)); + OSL_ENSURE(aAfterDropPos != m_xIndexes->end(), "DbaIndexDialog::OnDropIndex: problems with one of the remaining entries!"); + m_xIndexList->set_id(rEntry, OUString::number(aAfterDropPos - m_xIndexes->begin())); + return false; + }); + + // the Remove automatically selected another entry (if possible), but we disabled the calling of the handler + // to prevent that we missed something... call the handler directly + IndexSelected(); + } + + return !aExceptionInfo.isValid(); + } + + void DbaIndexDialog::OnRenameIndex() + { + // the selected iterator + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + if (!m_xIndexList->get_selected(xSelected.get())) + return; + + // save the changes made 'til here + // Upon leaving the edit mode, the control will be re-initialized with the + // settings from the current entry + implSaveModified(false); + + m_xIndexList->grab_focus(); + m_xIndexList->start_editing(*xSelected); + updateToolbox(); + } + + void DbaIndexDialog::OnSaveIndex() + { + // the selected index + implCommitPreviouslySelected(); + updateToolbox(); + } + + void DbaIndexDialog::OnResetIndex() + { + // the selected index + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + // the selected index + if (!m_xIndexList->get_selected(xSelected.get())) + xSelected.reset(); + OSL_ENSURE(xSelected, "DbaIndexDialog::OnResetIndex: invalid call!"); + if (!xSelected) + return; + + Indexes::iterator aResetPos = m_xIndexes->begin() + m_xIndexList->get_id(*xSelected).toUInt32(); + + if (aResetPos->isNew()) + { + OnDropIndex(false); + return; + } + + SQLExceptionInfo aExceptionInfo; + try + { + m_xIndexes->resetIndex(aResetPos); + } + catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); } + + if (aExceptionInfo.isValid()) + showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext); + else + m_xIndexList->set_text(*xSelected, aResetPos->sName); + + updateControls(xSelected.get()); + updateToolbox(); + } + + IMPL_LINK(DbaIndexDialog, OnIndexAction, const OString&, rClicked, void) + { + if (rClicked == "ID_INDEX_NEW") + OnNewIndex(); + else if (rClicked == "ID_INDEX_DROP") + OnDropIndex(); + else if (rClicked == "ID_INDEX_RENAME") + OnRenameIndex(); + else if (rClicked == "ID_INDEX_SAVE") + OnSaveIndex(); + else if (rClicked == "ID_INDEX_RESET") + OnResetIndex(); + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnCloseDialog, weld::Button&, void) + { + if (m_bEditingActive) + { + OSL_ENSURE(!m_bEditAgain, "DbaIndexDialog::OnCloseDialog: somebody was faster than hell!"); + // this means somebody entered a new name, which was invalid, which cause us to posted us an event, + // and before the event arrived the user clicked onto "close". VERY fast, this user... + m_xIndexList->end_editing(); + if (m_bEditAgain) + // could not commit the new name (started a new - asynchronous - edit trial) + return; + } + + // the currently selected entry + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + // the selected index + if (!m_xIndexList->get_selected(xSelected.get())) + xSelected.reset(); + + OSL_ENSURE(xSelected && m_xPreviousSelection && xSelected->equal(*m_xPreviousSelection), "DbaIndexDialog::OnCloseDialog: inconsistence!"); + + sal_Int32 nResponse = RET_NO; + if (xSelected) + { + // the descriptor + Indexes::const_iterator aSelected = m_xIndexes->begin() + m_xIndexList->get_id(*xSelected).toUInt32(); + if (aSelected->isModified() || aSelected->isNew()) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xDialog.get(), "dbaccess/ui/saveindexdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("SaveIndexDialog")); + nResponse = xQuery->run(); + } + } + + switch (nResponse) + { + case RET_YES: + if (!implCommitPreviouslySelected()) + return; + break; + case RET_NO: + break; + default: + return; + } + + m_xDialog->response(RET_OK); + } + + IMPL_LINK(DbaIndexDialog, OnEditIndexAgain, void*, p, void) + { + weld::TreeIter* pEntry = static_cast<weld::TreeIter*>(p); + m_bEditAgain = false; + m_xIndexList->grab_focus(); + m_xIndexList->start_editing(*pEntry); + delete pEntry; + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnEntryEditing, const weld::TreeIter&, bool) + { + m_bEditingActive = true; + return true; + } + + IMPL_LINK(DbaIndexDialog, OnEntryEdited, const IterString&, rIterString, bool) + { + m_bEditingActive = false; + + const weld::TreeIter& rEntry = rIterString.first; + OUString sNewName = rIterString.second; + + Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(rEntry).toUInt32(); + + OSL_ENSURE(aPosition >= m_xIndexes->begin() && aPosition < m_xIndexes->end(), + "DbaIndexDialog::OnEntryEdited: invalid entry!"); + + Indexes::const_iterator aSameName = m_xIndexes->find(sNewName); + if (aSameName != aPosition && m_xIndexes->end() != aSameName) + { + OUString sError(DBA_RES(STR_INDEX_NAME_ALREADY_USED)); + sError = sError.replaceFirst("$name$", sNewName); + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + sError)); + xError->run(); + + updateToolbox(); + m_bEditAgain = true; + std::unique_ptr<weld::TreeIter> xEntry(m_xIndexList->make_iterator(&rEntry)); + Application::PostUserEvent(LINK(this, DbaIndexDialog, OnEditIndexAgain), xEntry.release()); + return false; + } + + aPosition->sName = sNewName; + + // rename can be done by a drop/insert combination only + if (aPosition->isNew()) + { + updateToolbox(); + // no commitment needed here... + return true; + } + + if (aPosition->sName != aPosition->getOriginalName()) + { + aPosition->setModified(true); + updateToolbox(); + } + + return true; + } + + bool DbaIndexDialog::implSaveModified(bool _bPlausibility) + { + if (m_xPreviousSelection) + { + // try to commit the previously selected index + if (m_xFields->IsModified() && !m_xFields->SaveModified()) + return false; + + Indexes::iterator aPreviouslySelected = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32(); + + // the unique flag + aPreviouslySelected->bUnique = m_xUnique->get_active(); + if (m_xUnique->get_state_changed_from_saved()) + aPreviouslySelected->setModified(true); + + // the fields + m_xFields->commitTo(aPreviouslySelected->aFields); + if (m_xFields->GetSavedValue() != aPreviouslySelected->aFields) + aPreviouslySelected->setModified(true); + + // plausibility checks + if (_bPlausibility && !implCheckPlausibility(aPreviouslySelected)) + return false; + } + + return true; + } + + bool DbaIndexDialog::implCheckPlausibility(const Indexes::const_iterator& _rPos) + { + // need at least one field + if (_rPos->aFields.empty()) + { + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + DBA_RES(STR_NEED_INDEX_FIELDS))); + xError->run(); + m_xFields->GrabFocus(); + return false; + } + + // no double fields + std::set< OUString > aExistentFields; + for (auto const& fieldCheck : _rPos->aFields) + { + if (aExistentFields.end() != aExistentFields.find(fieldCheck.sFieldName)) + { + // a column is specified twice ... won't work anyway, so prevent this here and now + OUString sMessage(DBA_RES(STR_INDEXDESIGN_DOUBLE_COLUMN_NAME)); + sMessage = sMessage.replaceFirst("$name$", fieldCheck.sFieldName); + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + sMessage)); + xError->run(); + m_xFields->GrabFocus(); + return false; + } + aExistentFields.insert(fieldCheck.sFieldName); + } + + return true; + } + + bool DbaIndexDialog::implCommitPreviouslySelected() + { + if (m_xPreviousSelection) + { + Indexes::const_iterator aPreviouslySelected = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32(); + + if (!implSaveModified()) + return false; + + // commit the index (if necessary) + if (aPreviouslySelected->isModified() && !implCommit(m_xPreviousSelection.get())) + return false; + } + + return true; + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnModifiedClick, weld::Button&, void) + { + OnModified(*m_xFields); + } + + IMPL_LINK_NOARG( DbaIndexDialog, OnModified, IndexFieldsControl&, void ) + { + assert(m_xPreviousSelection && "DbaIndexDialog, OnModified: invalid call!"); + Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32(); + + aPosition->setModified(true); + updateToolbox(); + } + + void DbaIndexDialog::updateControls(const weld::TreeIter* pEntry) + { + if (pEntry) + { + // the descriptor of the selected index + Indexes::const_iterator aSelectedIndex = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32(); + + // fill the controls + m_xUnique->set_active(aSelectedIndex->bUnique); + m_xUnique->set_sensitive(!aSelectedIndex->bPrimaryKey); + m_xUnique->save_state(); + + m_xFields->initializeFrom(aSelectedIndex->aFields); + m_xFields->Enable(!aSelectedIndex->bPrimaryKey); + m_xFields->SaveValue(); + + m_xDescription->set_label(aSelectedIndex->sDescription); + m_xDescription->set_sensitive(!aSelectedIndex->bPrimaryKey); + + m_xDescriptionLabel->set_sensitive(!aSelectedIndex->bPrimaryKey); + } + else + { + m_xUnique->set_active(false); + m_xFields->initializeFrom(IndexFields()); + m_xDescription->set_label(OUString()); + } + } + + void DbaIndexDialog::IndexSelected() + { + if (m_bEditingActive) + m_xIndexList->end_editing(); + + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + if (!m_xIndexList->get_selected(xSelected.get())) + xSelected.reset(); + + // commit the old data + if (m_xPreviousSelection && (!xSelected || !m_xPreviousSelection->equal(*xSelected))) + { + // (this call may happen in case somebody ended an in-place edit with 'return', so we need to check this before committing) + if (!implCommitPreviouslySelected()) + { + m_bNoHandlerCall = true; + m_xIndexList->select(*m_xPreviousSelection); + m_bNoHandlerCall = false; + return; + } + } + + // disable/enable the detail controls + m_xIndexDetails->set_sensitive(xSelected != nullptr); + m_xUnique->set_sensitive(xSelected != nullptr); + m_xDescriptionLabel->set_sensitive(xSelected != nullptr); + m_xFieldsLabel->set_sensitive(xSelected != nullptr); + m_xFields->Enable(xSelected != nullptr); + + updateControls(xSelected.get()); + if (xSelected) + m_xIndexList->grab_focus(); + + m_xPreviousSelection = std::move(xSelected); + + updateToolbox(); + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnIndexSelected, weld::TreeView&, void) + { + if (m_bNoHandlerCall) + return; + IndexSelected(); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |