summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/namedlg
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/namedlg')
-rw-r--r--sc/source/ui/namedlg/namedefdlg.cxx330
-rw-r--r--sc/source/ui/namedlg/namedlg.cxx512
-rw-r--r--sc/source/ui/namedlg/namemgrtable.cxx187
-rw-r--r--sc/source/ui/namedlg/namepast.cxx99
4 files changed, 1128 insertions, 0 deletions
diff --git a/sc/source/ui/namedlg/namedefdlg.cxx b/sc/source/ui/namedlg/namedefdlg.cxx
new file mode 100644
index 0000000000..3304f4d39b
--- /dev/null
+++ b/sc/source/ui/namedlg/namedefdlg.cxx
@@ -0,0 +1,330 @@
+/* -*- 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/.
+ */
+
+#include <namedefdlg.hxx>
+
+#include <formula/errorcodes.hxx>
+#include <sfx2/app.hxx>
+#include <unotools/charclass.hxx>
+
+#include <compiler.hxx>
+#include <document.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <globalnames.hxx>
+#include <rangenam.hxx>
+#include <reffact.hxx>
+#include <undorangename.hxx>
+#include <tabvwsh.hxx>
+#include <tokenarray.hxx>
+
+ScNameDefDlg::ScNameDefDlg( SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ const ScViewData& rViewData, std::map<OUString, ScRangeName*>&& aRangeMap,
+ const ScAddress& aCursorPos, const bool bUndo )
+ : ScAnyRefDlgController( pB, pCW, pParent, "modules/scalc/ui/definename.ui", "DefineNameDialog")
+ , mbUndo( bUndo )
+ , mrDoc(rViewData.GetDocument())
+ , mpDocShell ( rViewData.GetDocShell() )
+ , maCursorPos( aCursorPos )
+ , maGlobalNameStr ( ScResId(STR_GLOBAL_SCOPE) )
+ , maErrInvalidNameStr( ScResId(STR_ERR_NAME_INVALID))
+ , maErrInvalidNameCellRefStr( ScResId(STR_ERR_NAME_INVALID_CELL_REF))
+ , maErrNameInUse ( ScResId(STR_ERR_NAME_EXISTS))
+ , maRangeMap( std::move(aRangeMap) )
+ , m_xEdName(m_xBuilder->weld_entry("edit"))
+ , m_xEdRange(new formula::RefEdit(m_xBuilder->weld_entry("range")))
+ , m_xRbRange(new formula::RefButton(m_xBuilder->weld_button("refbutton")))
+ , m_xLbScope(m_xBuilder->weld_combo_box("scope"))
+ , m_xBtnRowHeader(m_xBuilder->weld_check_button("rowheader"))
+ , m_xBtnColHeader(m_xBuilder->weld_check_button("colheader"))
+ , m_xBtnPrintArea(m_xBuilder->weld_check_button("printarea"))
+ , m_xBtnCriteria(m_xBuilder->weld_check_button("filter"))
+ , m_xBtnAdd(m_xBuilder->weld_button("add"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+ , m_xFtInfo(m_xBuilder->weld_label("label"))
+ , m_xFtRange(m_xBuilder->weld_label("label3"))
+{
+ m_xEdRange->SetReferences(this, m_xFtRange.get());
+ m_xRbRange->SetReferences(this, m_xEdRange.get());
+ maStrInfoDefault = m_xFtInfo->get_label();
+
+ // Initialize scope list.
+ m_xLbScope->append_text(maGlobalNameStr);
+ m_xLbScope->set_active(0);
+ SCTAB n = mrDoc.GetTableCount();
+ for (SCTAB i = 0; i < n; ++i)
+ {
+ OUString aTabName;
+ mrDoc.GetName(i, aTabName);
+ m_xLbScope->append_text(aTabName);
+ }
+
+ m_xBtnCancel->connect_clicked( LINK( this, ScNameDefDlg, CancelBtnHdl));
+ m_xBtnAdd->connect_clicked( LINK( this, ScNameDefDlg, AddBtnHdl ));
+ m_xEdName->connect_changed( LINK( this, ScNameDefDlg, NameModifyHdl ));
+ m_xEdRange->SetGetFocusHdl( LINK( this, ScNameDefDlg, AssignGetFocusHdl ) );
+
+ m_xBtnAdd->set_sensitive(false); // empty name is invalid
+
+ ScRange aRange;
+
+ rViewData.GetSimpleArea( aRange );
+ OUString aAreaStr(aRange.Format(mrDoc, ScRefFlags::RANGE_ABS_3D,
+ ScAddress::Details(mrDoc.GetAddressConvention(), 0, 0)));
+
+ m_xEdRange->SetText( aAreaStr );
+
+ m_xEdName->grab_focus();
+ m_xEdName->select_region(0, -1);
+}
+
+ScNameDefDlg::~ScNameDefDlg()
+{
+}
+
+void ScNameDefDlg::CancelPushed()
+{
+ if (mbUndo)
+ response(RET_CANCEL);
+ else
+ {
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ pViewSh->SwitchBetweenRefDialogs(this);
+ }
+}
+
+bool ScNameDefDlg::IsFormulaValid()
+{
+ ScCompiler aComp(mrDoc, maCursorPos, mrDoc.GetGrammar());
+ std::unique_ptr<ScTokenArray> pCode = aComp.CompileString(m_xEdRange->GetText());
+ if (pCode->GetCodeError() != FormulaError::NONE)
+ {
+ //TODO: info message
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool ScNameDefDlg::IsNameValid()
+{
+ OUString aScope = m_xLbScope->get_active_text();
+ OUString aName = m_xEdName->get_text();
+
+ bool bIsNameValid = true;
+ OUString aHelpText = maStrInfoDefault;
+
+ ScRangeName* pRangeName = nullptr;
+ if(aScope == maGlobalNameStr)
+ {
+ const auto iter = maRangeMap.find(STR_GLOBAL_RANGE_NAME);
+ assert(iter != maRangeMap.end());
+ pRangeName = iter->second;
+ }
+ else
+ {
+ const auto iter = maRangeMap.find(aScope);
+ assert(iter != maRangeMap.end());
+ pRangeName = iter->second;
+ }
+
+ ScRangeData::IsNameValidType eType;
+ if ( aName.isEmpty() )
+ {
+ bIsNameValid = false;
+ }
+ else if ((eType = ScRangeData::IsNameValid(aName, mrDoc))
+ != ScRangeData::IsNameValidType::NAME_VALID)
+ {
+ if (eType == ScRangeData::IsNameValidType::NAME_INVALID_BAD_STRING)
+ {
+ aHelpText = maErrInvalidNameStr;
+ }
+ else if (eType == ScRangeData::IsNameValidType::NAME_INVALID_CELL_REF)
+ {
+ aHelpText = maErrInvalidNameCellRefStr;
+ }
+ bIsNameValid = false;
+ }
+ else if (pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(aName)))
+ {
+ aHelpText = maErrNameInUse;
+ bIsNameValid = false;
+ }
+
+ if (!IsFormulaValid())
+ {
+ bIsNameValid = false;
+ }
+
+ m_xEdName->set_tooltip_text(aHelpText);
+ m_xEdName->set_message_type(bIsNameValid || aName.isEmpty() ? weld::EntryMessageType::Normal
+ : weld::EntryMessageType::Error);
+ m_xBtnAdd->set_sensitive(bIsNameValid);
+ return bIsNameValid;
+}
+
+void ScNameDefDlg::AddPushed()
+{
+ OUString aScope = m_xLbScope->get_active_text();
+ OUString aName = m_xEdName->get_text();
+ OUString aExpression = m_xEdRange->GetText();
+
+ if (aName.isEmpty())
+ {
+ return;
+ }
+ if (aScope.isEmpty())
+ {
+ return;
+ }
+
+ ScRangeName* pRangeName = nullptr;
+ if(aScope == maGlobalNameStr)
+ {
+ const auto iter = maRangeMap.find(STR_GLOBAL_RANGE_NAME);
+ assert(iter != maRangeMap.end());
+ pRangeName = iter->second;
+ }
+ else
+ {
+ const auto iter = maRangeMap.find(aScope);
+ assert(iter != maRangeMap.end());
+ pRangeName = iter->second;
+ }
+ if (!pRangeName)
+ return;
+
+ if (!IsNameValid()) //should not happen, but make sure we don't break anything
+ return;
+ else
+ {
+ ScRangeData::Type nType = ScRangeData::Type::Name;
+
+ ScRangeData* pNewEntry = new ScRangeData( mrDoc,
+ aName,
+ aExpression,
+ maCursorPos,
+ nType );
+
+ if ( m_xBtnRowHeader->get_active() ) nType |= ScRangeData::Type::RowHeader;
+ if ( m_xBtnColHeader->get_active() ) nType |= ScRangeData::Type::ColHeader;
+ if ( m_xBtnPrintArea->get_active() ) nType |= ScRangeData::Type::PrintArea;
+ if ( m_xBtnCriteria->get_active() ) nType |= ScRangeData::Type::Criteria;
+
+ pNewEntry->AddType(nType);
+
+ // aExpression valid?
+ if ( FormulaError::NONE == pNewEntry->GetErrCode() )
+ {
+ if ( !pRangeName->insert( pNewEntry, false /*bReuseFreeIndex*/ ) )
+ pNewEntry = nullptr;
+
+ if (mbUndo)
+ {
+ // this means we called directly through the menu
+
+ SCTAB nTab;
+ // if no table with that name is found, assume global range name
+ if (!mrDoc.GetTable(aScope, nTab))
+ nTab = -1;
+
+ assert( pNewEntry); // undo of no insertion smells fishy
+ if (pNewEntry)
+ mpDocShell->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoAddRangeData>( mpDocShell, pNewEntry, nTab) );
+
+ // set table stream invalid, otherwise RangeName won't be saved if no other
+ // call invalidates the stream
+ if (nTab != -1)
+ mrDoc.SetStreamValid(nTab, false);
+ SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
+ mpDocShell->SetDocumentModified();
+ Close();
+ }
+ else
+ {
+ maName = aName;
+ maScope = aScope;
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ pViewSh->SwitchBetweenRefDialogs(this);
+ }
+ }
+ else
+ {
+ delete pNewEntry;
+ m_xEdRange->GrabFocus();
+ m_xEdRange->SelectAll();
+ }
+ }
+}
+
+void ScNameDefDlg::GetNewData(OUString& rName, OUString& rScope)
+{
+ rName = maName;
+ rScope = maScope;
+}
+
+bool ScNameDefDlg::IsRefInputMode() const
+{
+ return m_xEdRange->GetWidget()->get_sensitive();
+}
+
+void ScNameDefDlg::RefInputDone( bool bForced)
+{
+ ScAnyRefDlgController::RefInputDone(bForced);
+ IsNameValid();
+}
+
+void ScNameDefDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if (m_xEdRange->GetWidget()->get_sensitive())
+ {
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(m_xEdRange.get());
+ OUString aRefStr(rRef.Format(rDocP, ScRefFlags::RANGE_ABS_3D,
+ ScAddress::Details(rDocP.GetAddressConvention(), 0, 0)));
+ m_xEdRange->SetRefString( aRefStr );
+ }
+}
+
+void ScNameDefDlg::Close()
+{
+ DoClose( ScNameDefDlgWrapper::GetChildWindowId() );
+}
+
+void ScNameDefDlg::SetActive()
+{
+ m_xEdRange->GrabFocus();
+ RefInputDone();
+}
+
+IMPL_LINK_NOARG(ScNameDefDlg, CancelBtnHdl, weld::Button&, void)
+{
+ CancelPushed();
+}
+
+IMPL_LINK_NOARG(ScNameDefDlg, AddBtnHdl, weld::Button&, void)
+{
+ AddPushed();
+};
+
+IMPL_LINK_NOARG(ScNameDefDlg, NameModifyHdl, weld::Entry&, void)
+{
+ IsNameValid();
+}
+
+IMPL_LINK_NOARG(ScNameDefDlg, AssignGetFocusHdl, formula::RefEdit&, void)
+{
+ IsNameValid();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/namedlg/namedlg.cxx b/sc/source/ui/namedlg/namedlg.cxx
new file mode 100644
index 0000000000..a6a182cd82
--- /dev/null
+++ b/sc/source/ui/namedlg/namedlg.cxx
@@ -0,0 +1,512 @@
+/* -*- 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 <memory>
+#include <global.hxx>
+#include <reffact.hxx>
+#include <compiler.hxx>
+#include <document.hxx>
+#include <docfunc.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <namedlg.hxx>
+#include <viewdata.hxx>
+#include <tabvwsh.hxx>
+
+#include <globalnames.hxx>
+#include <tokenarray.hxx>
+
+#include <vcl/svapp.hxx>
+#include <formula/errorcodes.hxx>
+#include <unotools/charclass.hxx>
+
+#include <map>
+
+//logic
+
+ScNameDlg::ScNameDlg( SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ ScViewData& rViewData,
+ const ScAddress& aCursorPos,
+ std::map<OUString, ScRangeName> *const pRangeMap)
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/managenamesdialog.ui",
+ "ManageNamesDialog")
+
+ , maGlobalNameStr(ScResId(STR_GLOBAL_SCOPE))
+ , maErrInvalidNameStr(ScResId(STR_ERR_NAME_INVALID))
+ , maErrNameInUse(ScResId(STR_ERR_NAME_EXISTS))
+ , maStrMultiSelect(ScResId(STR_MULTI_SELECT))
+
+ , mrViewData(rViewData)
+ , mrDoc(rViewData.GetDocument())
+ , maCursorPos(aCursorPos)
+ , mbDataChanged(false)
+ , mbCloseWithoutUndo(false)
+
+ , m_xEdName(m_xBuilder->weld_entry("name"))
+ , m_xFtAssign(m_xBuilder->weld_label("label3"))
+ , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry("range")))
+ , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button("assign")))
+ , m_xLbScope(m_xBuilder->weld_combo_box("scope"))
+ , m_xBtnPrintArea(m_xBuilder->weld_check_button("printrange"))
+ , m_xBtnColHeader(m_xBuilder->weld_check_button("colheader"))
+ , m_xBtnCriteria(m_xBuilder->weld_check_button("filter"))
+ , m_xBtnRowHeader(m_xBuilder->weld_check_button("rowheader"))
+ , m_xBtnAdd(m_xBuilder->weld_button("add"))
+ , m_xBtnDelete(m_xBuilder->weld_button("delete"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+ , m_xFtInfo(m_xBuilder->weld_label("info"))
+{
+ m_xEdAssign->SetReferences(this, m_xFtAssign.get());
+ m_xRbAssign->SetReferences(this, m_xEdAssign.get());
+ maStrInfoDefault = m_xFtInfo->get_label();
+
+ if (!pRangeMap)
+ {
+ std::map<OUString, ScRangeName*> aRangeMap;
+ mrDoc.GetRangeNameMap(aRangeMap);
+ for (const auto& [aTemp, pRangeName] : aRangeMap)
+ {
+ m_RangeMap.insert(std::make_pair(aTemp, *pRangeName));
+ }
+ }
+ else
+ {
+ m_RangeMap.swap(*pRangeMap);
+ }
+ Init();
+}
+
+ScNameDlg::~ScNameDlg()
+{
+}
+
+void ScNameDlg::Init()
+{
+ //init UI
+
+ std::unique_ptr<weld::TreeView> xTreeView(m_xBuilder->weld_tree_view("names"));
+ xTreeView->set_size_request(xTreeView->get_approximate_digit_width() * 75,
+ xTreeView->get_height_rows(10));
+ m_xRangeManagerTable.reset(new ScRangeManagerTable(std::move(xTreeView), m_RangeMap, maCursorPos));
+
+ m_xRangeManagerTable->connect_changed( LINK( this, ScNameDlg, SelectionChangedHdl_Impl ) );
+
+ m_xBtnOk->connect_clicked( LINK( this, ScNameDlg, OkBtnHdl ) );
+ m_xBtnCancel->connect_clicked( LINK( this, ScNameDlg, CancelBtnHdl ) );
+ m_xBtnAdd->connect_clicked( LINK( this, ScNameDlg, AddBtnHdl ) );
+ m_xEdAssign->SetGetFocusHdl( LINK( this, ScNameDlg, AssignGetFocusHdl ) );
+ m_xEdAssign->SetModifyHdl ( LINK( this, ScNameDlg, RefEdModifyHdl ) );
+ m_xEdName->connect_changed( LINK( this, ScNameDlg, EdModifyHdl ) );
+ m_xLbScope->connect_changed( LINK(this, ScNameDlg, ScopeChangedHdl) );
+ m_xBtnDelete->connect_clicked( LINK( this, ScNameDlg, RemoveBtnHdl ) );
+ m_xBtnPrintArea->connect_toggled( LINK(this, ScNameDlg, EdModifyCheckBoxHdl ) );
+ m_xBtnCriteria->connect_toggled( LINK(this, ScNameDlg, EdModifyCheckBoxHdl ) );
+ m_xBtnRowHeader->connect_toggled( LINK(this, ScNameDlg, EdModifyCheckBoxHdl ) );
+ m_xBtnColHeader->connect_toggled( LINK(this, ScNameDlg, EdModifyCheckBoxHdl ) );
+
+ // Initialize scope list.
+ m_xLbScope->append_text(maGlobalNameStr);
+ m_xLbScope->set_active(0);
+ SCTAB n = mrDoc.GetTableCount();
+ for (SCTAB i = 0; i < n; ++i)
+ {
+ OUString aTabName;
+ mrDoc.GetName(i, aTabName);
+ m_xLbScope->append_text(aTabName);
+ }
+
+ CheckForEmptyTable();
+
+ if (m_xRangeManagerTable->n_children())
+ {
+ m_xRangeManagerTable->set_cursor(0);
+ m_xRangeManagerTable->CheckForFormulaString();
+ SelectionChanged();
+ }
+
+}
+
+bool ScNameDlg::IsRefInputMode() const
+{
+ return m_xEdAssign->GetWidget()->get_sensitive();
+}
+
+void ScNameDlg::RefInputDone( bool bForced)
+{
+ ScAnyRefDlgController::RefInputDone(bForced);
+ RefEdModifyHdl(*m_xEdAssign);
+}
+
+void ScNameDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if (m_xEdAssign->GetWidget()->get_sensitive())
+ {
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(m_xEdAssign.get());
+ OUString aRefStr(rRef.Format(rDocP, ScRefFlags::RANGE_ABS_3D,
+ ScAddress::Details(rDocP.GetAddressConvention(), 0, 0)));
+ m_xEdAssign->SetRefString( aRefStr );
+ }
+}
+
+void ScNameDlg::Close()
+{
+ if (mbDataChanged && !mbCloseWithoutUndo)
+ mrViewData.GetDocFunc().ModifyAllRangeNames(m_RangeMap);
+ DoClose(ScNameDlgWrapper::GetChildWindowId());
+}
+
+void ScNameDlg::CheckForEmptyTable()
+{
+ if (!m_xRangeManagerTable->n_children())
+ {
+ m_xBtnDelete->set_sensitive(false);
+ m_xEdAssign->GetWidget()->set_sensitive(false);
+ m_xRbAssign->GetWidget()->set_sensitive(false);
+ m_xEdName->set_sensitive(false);
+ m_xLbScope->set_sensitive(false);
+
+ m_xBtnCriteria->set_sensitive(false);
+ m_xBtnPrintArea->set_sensitive(false);
+ m_xBtnColHeader->set_sensitive(false);
+ m_xBtnRowHeader->set_sensitive(false);
+ }
+ else
+ {
+ m_xBtnDelete->set_sensitive(true);
+ m_xEdAssign->GetWidget()->set_sensitive(true);
+ m_xRbAssign->GetWidget()->set_sensitive(true);
+ m_xEdName->set_sensitive(true);
+ m_xLbScope->set_sensitive(true);
+
+ m_xBtnCriteria->set_sensitive(true);
+ m_xBtnPrintArea->set_sensitive(true);
+ m_xBtnColHeader->set_sensitive(true);
+ m_xBtnRowHeader->set_sensitive(true);
+ }
+}
+
+void ScNameDlg::SetActive()
+{
+ m_xEdAssign->GrabFocus();
+ RefInputDone();
+}
+
+void ScNameDlg::UpdateChecks(const ScRangeData* pData)
+{
+ // remove handlers, we only want the handlers to process
+ // user input and not when we are syncing the controls with our internal
+ // model ( also UpdateChecks is called already from some other event
+ // handlers, triggering handlers while already processing a handler can
+ // ( and does in this case ) corrupt the internal data
+
+ m_xBtnCriteria->connect_toggled( Link<weld::Toggleable&,void>() );
+ m_xBtnPrintArea->connect_toggled( Link<weld::Toggleable&,void>() );
+ m_xBtnColHeader->connect_toggled( Link<weld::Toggleable&,void>() );
+ m_xBtnRowHeader->connect_toggled( Link<weld::Toggleable&,void>() );
+
+ m_xBtnCriteria->set_active( pData->HasType( ScRangeData::Type::Criteria ) );
+ m_xBtnPrintArea->set_active( pData->HasType( ScRangeData::Type::PrintArea ) );
+ m_xBtnColHeader->set_active( pData->HasType( ScRangeData::Type::ColHeader ) );
+ m_xBtnRowHeader->set_active( pData->HasType( ScRangeData::Type::RowHeader ) );
+
+ // Restore handlers so user input is processed again
+ Link<weld::Toggleable&,void> aToggleHandler = LINK( this, ScNameDlg, EdModifyCheckBoxHdl );
+ m_xBtnCriteria->connect_toggled( aToggleHandler );
+ m_xBtnPrintArea->connect_toggled( aToggleHandler );
+ m_xBtnColHeader->connect_toggled( aToggleHandler );
+ m_xBtnRowHeader->connect_toggled( aToggleHandler );
+}
+
+bool ScNameDlg::IsNameValid()
+{
+ OUString aScope = m_xLbScope->get_active_text();
+ OUString aName = m_xEdName->get_text();
+ aName = aName.trim();
+
+ if (aName.isEmpty())
+ return false;
+
+ ScRangeName* pRangeName = GetRangeName( aScope );
+
+ if (ScRangeData::IsNameValid(aName, mrDoc) != ScRangeData::IsNameValidType::NAME_VALID)
+ {
+ m_xFtInfo->set_label_type(weld::LabelType::Error);
+ m_xFtInfo->set_label(maErrInvalidNameStr);
+ return false;
+ }
+ else if (pRangeName && pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(aName)))
+ {
+ m_xFtInfo->set_label_type(weld::LabelType::Error);
+ m_xFtInfo->set_label(maErrNameInUse);
+ return false;
+ }
+ m_xFtInfo->set_label( maStrInfoDefault );
+ return true;
+}
+
+bool ScNameDlg::IsFormulaValid()
+{
+ ScCompiler aComp(mrDoc, maCursorPos, mrDoc.GetGrammar());
+ std::unique_ptr<ScTokenArray> pCode = aComp.CompileString(m_xEdAssign->GetText());
+ if (pCode->GetCodeError() != FormulaError::NONE)
+ {
+ m_xFtInfo->set_label_type(weld::LabelType::Error);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+ScRangeName* ScNameDlg::GetRangeName(const OUString& rScope)
+{
+ if (rScope == maGlobalNameStr)
+ {
+ const auto iter = m_RangeMap.find(STR_GLOBAL_RANGE_NAME);
+ assert(iter != m_RangeMap.end());
+ return &iter->second;
+ }
+ else
+ {
+ const auto iter = m_RangeMap.find(rScope);
+ assert(iter != m_RangeMap.end());
+ return &iter->second;
+ }
+}
+
+void ScNameDlg::ShowOptions(const ScRangeNameLine& rLine)
+{
+ ScRangeName* pRangeName = GetRangeName(rLine.aScope);
+ ScRangeData* pData = pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(rLine.aName));
+ if (pData)
+ {
+ UpdateChecks(pData);
+ }
+}
+
+void ScNameDlg::AddPushed()
+{
+ mbCloseWithoutUndo = true;
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ pViewSh->SwitchBetweenRefDialogs(this);
+}
+
+void ScNameDlg::SetEntry(const OUString& rName, const OUString& rScope)
+{
+ if (!rName.isEmpty())
+ {
+ mbDataChanged = true;
+ ScRangeNameLine aLine;
+ aLine.aName = rName;
+ aLine.aScope = rScope;
+ m_xRangeManagerTable->SetEntry(aLine);
+ }
+}
+
+void ScNameDlg::RemovePushed()
+{
+ std::vector<ScRangeNameLine> aEntries = m_xRangeManagerTable->GetSelectedEntries();
+ m_xRangeManagerTable->DeleteSelectedEntries();
+ for (const auto& rEntry : aEntries)
+ {
+ ScRangeName* pRangeName = GetRangeName(rEntry.aScope);
+ ScRangeData* pData = pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(rEntry.aName));
+ OSL_ENSURE(pData, "table and model should be in sync");
+ // be safe and check for possible problems
+ if (pData)
+ pRangeName->erase(*pData);
+
+ mbDataChanged = true;
+ }
+ CheckForEmptyTable();
+}
+
+void ScNameDlg::NameModified()
+{
+ ScRangeNameLine aLine;
+ m_xRangeManagerTable->GetCurrentLine(aLine);
+ OUString aOldName = aLine.aName;
+ OUString aNewName = m_xEdName->get_text();
+ aNewName = aNewName.trim();
+ m_xFtInfo->set_label_type(weld::LabelType::Normal);
+ if (aNewName != aOldName)
+ {
+ if (!IsNameValid())
+ return;
+ }
+ else
+ {
+ m_xFtInfo->set_label( maStrInfoDefault );
+ }
+
+ if (!IsFormulaValid())
+ {
+ //TODO: implement an info text
+ return;
+ }
+
+ OUString aOldScope = aLine.aScope;
+ //empty table
+ if (aOldScope.isEmpty())
+ return;
+ OUString aExpr = m_xEdAssign->GetText();
+ OUString aNewScope = m_xLbScope->get_active_text();
+
+ ScRangeName* pOldRangeName = GetRangeName( aOldScope );
+ ScRangeData* pData = pOldRangeName->findByUpperName( ScGlobal::getCharClass().uppercase(aOldName) );
+ ScRangeName* pNewRangeName = GetRangeName( aNewScope );
+ OSL_ENSURE(pData, "model and table should be in sync");
+ // be safe and check for range data
+ if (!pData)
+ return;
+
+ // Assign new index (0) only if the scope is changed, else keep the
+ // existing index.
+ sal_uInt16 nIndex = (aNewScope != aOldScope ? 0 : pData->GetIndex());
+
+ pOldRangeName->erase(*pData);
+ m_xRangeManagerTable->BlockUpdate();
+ m_xRangeManagerTable->DeleteSelectedEntries();
+ ScRangeData::Type nType = ScRangeData::Type::Name;
+ if ( m_xBtnRowHeader->get_active() ) nType |= ScRangeData::Type::RowHeader;
+ if ( m_xBtnColHeader->get_active() ) nType |= ScRangeData::Type::ColHeader;
+ if ( m_xBtnPrintArea->get_active() ) nType |= ScRangeData::Type::PrintArea;
+ if ( m_xBtnCriteria->get_active() ) nType |= ScRangeData::Type::Criteria;
+
+ ScRangeData* pNewEntry = new ScRangeData( mrDoc, aNewName, aExpr,
+ maCursorPos, nType);
+ pNewEntry->SetIndex( nIndex);
+ pNewRangeName->insert(pNewEntry, false /*bReuseFreeIndex*/);
+ aLine.aName = aNewName;
+ aLine.aExpression = aExpr;
+ aLine.aScope = aNewScope;
+ m_xRangeManagerTable->addEntry(aLine, true);
+ // tdf#128137 process pending async row change events while UpdatesBlocked in place
+ Application::Reschedule(true);
+ m_xRangeManagerTable->UnblockUpdate();
+ mbDataChanged = true;
+}
+
+void ScNameDlg::SelectionChanged()
+{
+ //don't update if we have just modified due to user input
+ if (m_xRangeManagerTable->UpdatesBlocked())
+ {
+ return;
+ }
+
+ if (m_xRangeManagerTable->IsMultiSelection())
+ {
+ m_xEdName->set_text(maStrMultiSelect);
+ m_xEdAssign->SetText(maStrMultiSelect);
+
+ m_xEdName->set_sensitive(false);
+ m_xEdAssign->GetWidget()->set_sensitive(false);
+ m_xRbAssign->GetWidget()->set_sensitive(false);
+ m_xLbScope->set_sensitive(false);
+ m_xBtnRowHeader->set_sensitive(false);
+ m_xBtnColHeader->set_sensitive(false);
+ m_xBtnPrintArea->set_sensitive(false);
+ m_xBtnCriteria->set_sensitive(false);
+ }
+ else
+ {
+ ScRangeNameLine aLine;
+ m_xRangeManagerTable->GetCurrentLine(aLine);
+ m_xEdAssign->SetText(aLine.aExpression);
+ m_xEdName->set_text(aLine.aName);
+ m_xLbScope->set_active_text(aLine.aScope);
+ ShowOptions(aLine);
+ m_xBtnDelete->set_sensitive(true);
+ m_xEdName->set_sensitive(true);
+ m_xEdAssign->GetWidget()->set_sensitive(true);
+ m_xRbAssign->GetWidget()->set_sensitive(true);
+ m_xLbScope->set_sensitive(true);
+ m_xBtnRowHeader->set_sensitive(true);
+ m_xBtnColHeader->set_sensitive(true);
+ m_xBtnPrintArea->set_sensitive(true);
+ m_xBtnCriteria->set_sensitive(true);
+ }
+}
+
+void ScNameDlg::ScopeChanged()
+{
+ NameModified();
+}
+
+void ScNameDlg::GetRangeNames(std::map<OUString, ScRangeName>& rRangeMap)
+{
+ m_RangeMap.swap(rRangeMap);
+}
+
+IMPL_LINK_NOARG(ScNameDlg, OkBtnHdl, weld::Button&, void)
+{
+ response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScNameDlg, CancelBtnHdl, weld::Button&, void)
+{
+ mbCloseWithoutUndo = true;
+ response(RET_CANCEL);
+}
+
+IMPL_LINK_NOARG(ScNameDlg, AddBtnHdl, weld::Button&, void)
+{
+ AddPushed();
+}
+
+IMPL_LINK_NOARG(ScNameDlg, RemoveBtnHdl, weld::Button&, void)
+{
+ RemovePushed();
+}
+
+IMPL_LINK_NOARG(ScNameDlg, EdModifyCheckBoxHdl, weld::Toggleable&, void)
+{
+ NameModified();
+}
+
+IMPL_LINK_NOARG(ScNameDlg, EdModifyHdl, weld::Entry&, void)
+{
+ NameModified();
+}
+
+IMPL_LINK_NOARG(ScNameDlg, RefEdModifyHdl, formula::RefEdit&, void)
+{
+ NameModified();
+}
+
+IMPL_LINK_NOARG(ScNameDlg, AssignGetFocusHdl, formula::RefEdit&, void)
+{
+ RefEdModifyHdl(*m_xEdAssign);
+}
+
+IMPL_LINK_NOARG(ScNameDlg, SelectionChangedHdl_Impl, weld::TreeView&, void)
+{
+ SelectionChanged();
+}
+
+IMPL_LINK_NOARG(ScNameDlg, ScopeChangedHdl, weld::ComboBox&, void)
+{
+ ScopeChanged();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/namedlg/namemgrtable.cxx b/sc/source/ui/namedlg/namemgrtable.cxx
new file mode 100644
index 0000000000..5b23306653
--- /dev/null
+++ b/sc/source/ui/namedlg/namemgrtable.cxx
@@ -0,0 +1,187 @@
+/* -*- 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/.
+ */
+
+//ScRangeManagerTable
+#include <memory>
+#include <global.hxx>
+#include <globstr.hrc>
+#include <o3tl/safeint.hxx>
+#include <scresid.hxx>
+#include <globalnames.hxx>
+#include <namemgrtable.hxx>
+#include <rangenam.hxx>
+
+#include <unotools/charclass.hxx>
+#include <vcl/weld.hxx>
+#include <tools/link.hxx>
+
+void ScRangeManagerTable::GetCurrentLine(ScRangeNameLine& rLine)
+{
+ std::unique_ptr<weld::TreeIter> xCurrentEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_cursor(xCurrentEntry.get()))
+ GetLine(rLine, *xCurrentEntry);
+}
+
+void ScRangeManagerTable::DeleteSelectedEntries()
+{
+ std::vector<int> aRows = m_xTreeView->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+ for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
+ m_xTreeView->remove(*it);
+}
+
+bool ScRangeManagerTable::IsMultiSelection() const
+{
+ return m_xTreeView->count_selected_rows() > 1;
+}
+
+void ScRangeManagerTable::SetEntry(const ScRangeNameLine& rLine)
+{
+ for (int i = 0, nEntryCount = m_xTreeView->n_children(); i < nEntryCount; ++i)
+ {
+ if (rLine.aName == m_xTreeView->get_text(i, 0)
+ && rLine.aScope == m_xTreeView->get_text(i, 2))
+ {
+ m_xTreeView->set_cursor(i);
+ }
+ }
+}
+
+ScRangeManagerTable::ScRangeManagerTable(std::unique_ptr<weld::TreeView> xTreeView,
+ const std::map<OUString, ScRangeName>& rRangeMap,
+ const ScAddress& rPos)
+ : m_xTreeView(std::move(xTreeView))
+ , maGlobalString(ScResId(STR_GLOBAL_SCOPE))
+ , m_RangeMap(rRangeMap)
+ , maPos(rPos)
+ , m_nId(0)
+ , mbNeedUpdate(true)
+{
+ auto nColWidth = m_xTreeView->get_size_request().Width() / 7;
+ std::vector<int> aWidths{ o3tl::narrowing<int>(nColWidth * 2),
+ o3tl::narrowing<int>(nColWidth * 3) };
+ m_xTreeView->set_column_fixed_widths(aWidths);
+
+ Init();
+ m_xTreeView->set_selection_mode(SelectionMode::Multiple);
+ m_xTreeView->connect_size_allocate(LINK(this, ScRangeManagerTable, SizeAllocHdl));
+ m_xTreeView->connect_visible_range_changed(LINK(this, ScRangeManagerTable, VisRowsScrolledHdl));
+}
+
+IMPL_LINK_NOARG(ScRangeManagerTable, VisRowsScrolledHdl, weld::TreeView&, void)
+{
+ CheckForFormulaString();
+}
+
+const ScRangeData* ScRangeManagerTable::findRangeData(const ScRangeNameLine& rLine)
+{
+ const ScRangeName* pRangeName;
+ if (rLine.aScope == maGlobalString)
+ {
+ const auto iter = m_RangeMap.find(STR_GLOBAL_RANGE_NAME);
+ assert(iter != m_RangeMap.end());
+ pRangeName = &iter->second;
+ }
+ else
+ {
+ const auto iter = m_RangeMap.find(rLine.aScope);
+ assert(iter != m_RangeMap.end());
+ pRangeName = &iter->second;
+ }
+
+ return pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(rLine.aName));
+}
+
+void ScRangeManagerTable::CheckForFormulaString()
+{
+ if (UpdatesBlocked())
+ return;
+
+ auto lambda = [this](weld::TreeIter& rEntry) {
+ OUString sId(m_xTreeView->get_id(rEntry));
+ std::map<OUString, bool>::const_iterator itr = maCalculatedFormulaEntries.find(sId);
+ if (itr == maCalculatedFormulaEntries.end() || !itr->second)
+ {
+ ScRangeNameLine aLine;
+ GetLine(aLine, rEntry);
+ const ScRangeData* pData = findRangeData(aLine);
+ OUString aFormulaString = pData->GetSymbol(maPos);
+ m_xTreeView->set_text(rEntry, aFormulaString, 1);
+ maCalculatedFormulaEntries.insert(std::pair<OUString, bool>(sId, true));
+ }
+ return false;
+ };
+
+ // ensure all visible entries are up to date
+ m_xTreeView->visible_foreach(lambda);
+ // and ensure all selected entries are up to date
+ m_xTreeView->selected_foreach(lambda);
+}
+
+IMPL_LINK_NOARG(ScRangeManagerTable, SizeAllocHdl, const Size&, void) { CheckForFormulaString(); }
+
+void ScRangeManagerTable::addEntry(const ScRangeNameLine& rLine, bool bSetCurEntry)
+{
+ int nRow = m_xTreeView->n_children();
+ m_xTreeView->append();
+ m_xTreeView->set_text(nRow, rLine.aName, 0);
+ m_xTreeView->set_text(nRow, rLine.aExpression, 1);
+ m_xTreeView->set_text(nRow, rLine.aScope, 2);
+ // just unique to track which one has been cached by maCalculatedFormulaEntries
+ m_xTreeView->set_id(nRow, OUString::number(m_nId++));
+ if (bSetCurEntry)
+ m_xTreeView->set_cursor(nRow);
+}
+
+void ScRangeManagerTable::GetLine(ScRangeNameLine& rLine, const weld::TreeIter& rEntry)
+{
+ rLine.aName = m_xTreeView->get_text(rEntry, 0);
+ rLine.aExpression = m_xTreeView->get_text(rEntry, 1);
+ rLine.aScope = m_xTreeView->get_text(rEntry, 2);
+}
+
+void ScRangeManagerTable::Init()
+{
+ m_xTreeView->freeze();
+ m_xTreeView->clear();
+ for (auto const& itr : m_RangeMap)
+ {
+ const ScRangeName& rLocalRangeName = itr.second;
+ ScRangeNameLine aLine;
+ if (itr.first == STR_GLOBAL_RANGE_NAME)
+ aLine.aScope = maGlobalString;
+ else
+ aLine.aScope = itr.first;
+ for (const auto& rEntry : rLocalRangeName)
+ {
+ // Database and hidden named ranges are not shown in the Manage Names dialog
+ if (!rEntry.second->HasType(ScRangeData::Type::Database)
+ && !rEntry.second->HasType(ScRangeData::Type::Hidden))
+ {
+ aLine.aName = rEntry.second->GetName();
+ addEntry(aLine, false);
+ }
+ }
+ }
+ m_xTreeView->thaw();
+}
+
+std::vector<ScRangeNameLine> ScRangeManagerTable::GetSelectedEntries()
+{
+ std::vector<ScRangeNameLine> aSelectedEntries;
+ m_xTreeView->selected_foreach([this, &aSelectedEntries](weld::TreeIter& rEntry) {
+ ScRangeNameLine aLine;
+ GetLine(aLine, rEntry);
+ aSelectedEntries.push_back(aLine);
+ return false;
+ });
+ return aSelectedEntries;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/namedlg/namepast.cxx b/sc/source/ui/namedlg/namepast.cxx
new file mode 100644
index 0000000000..1d144f3fdf
--- /dev/null
+++ b/sc/source/ui/namedlg/namepast.cxx
@@ -0,0 +1,99 @@
+/* -*- 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 .
+ */
+
+#undef SC_DLLIMPLEMENTATION
+
+#include <namepast.hxx>
+#include <docsh.hxx>
+#include <rangenam.hxx>
+#include <viewdata.hxx>
+#include <scui_def.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <compiler.hxx>
+
+ScNamePasteDlg::ScNamePasteDlg(weld::Window* pParent, ScDocShell* pShell)
+ : GenericDialogController(pParent, "modules/scalc/ui/insertname.ui", "InsertNameDialog")
+ , m_xBtnPasteAll(m_xBuilder->weld_button("pasteall"))
+ , m_xBtnPaste(m_xBuilder->weld_button("paste"))
+ , m_xBtnClose(m_xBuilder->weld_button("close"))
+{
+ ScDocument& rDoc = pShell->GetDocument();
+ m_aSheetSep = OUString(rDoc.GetSheetSeparator());
+ std::map<OUString, ScRangeName*> aCopyMap;
+ rDoc.GetRangeNameMap(aCopyMap);
+ for (const auto & [ aTemp, pName ] : aCopyMap)
+ {
+ m_RangeMap.insert(std::make_pair(aTemp, *pName));
+ }
+
+ ScAddress aPos;
+ if (ScViewData* pViewData = ScDocShell::GetViewData())
+ aPos = ScAddress(pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo());
+
+ std::unique_ptr<weld::TreeView> xTreeView(m_xBuilder->weld_tree_view("ctrl"));
+ xTreeView->set_size_request(xTreeView->get_approximate_digit_width() * 75,
+ xTreeView->get_height_rows(10));
+ m_xTable.reset(new ScRangeManagerTable(std::move(xTreeView), m_RangeMap, aPos));
+
+ m_xBtnPaste->connect_clicked(LINK(this, ScNamePasteDlg, ButtonHdl));
+ m_xBtnPasteAll->connect_clicked(LINK(this, ScNamePasteDlg, ButtonHdl));
+ m_xBtnClose->connect_clicked(LINK(this, ScNamePasteDlg, ButtonHdl));
+
+ if (!m_xTable->n_children())
+ {
+ m_xBtnPaste->set_sensitive(false);
+ m_xBtnPasteAll->set_sensitive(false);
+ }
+}
+
+ScNamePasteDlg::~ScNamePasteDlg() {}
+
+IMPL_LINK(ScNamePasteDlg, ButtonHdl, weld::Button&, rButton, void)
+{
+ if (&rButton == m_xBtnPasteAll.get())
+ {
+ m_xDialog->response(BTN_PASTE_LIST);
+ }
+ else if (&rButton == m_xBtnPaste.get())
+ {
+ const OUString aGlobalScope(ScResId(STR_GLOBAL_SCOPE));
+ std::vector<ScRangeNameLine> aSelectedLines = m_xTable->GetSelectedEntries();
+ for (const auto& rLine : aSelectedLines)
+ {
+ if (rLine.aScope == aGlobalScope)
+ maSelectedNames.push_back(rLine.aName);
+ else
+ {
+ OUString aSheet(rLine.aScope);
+ ScCompiler::CheckTabQuotes(aSheet);
+ maSelectedNames.push_back(aSheet + m_aSheetSep + rLine.aName);
+ }
+ }
+ m_xDialog->response(BTN_PASTE_NAME);
+ }
+ else if (&rButton == m_xBtnClose.get())
+ {
+ m_xDialog->response(BTN_PASTE_CLOSE);
+ }
+}
+
+const std::vector<OUString>& ScNamePasteDlg::GetSelectedNames() const { return maSelectedNames; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */