summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/miscdlgs
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/miscdlgs')
-rw-r--r--sc/source/ui/miscdlgs/acredlin.cxx1792
-rw-r--r--sc/source/ui/miscdlgs/anyrefdg.cxx784
-rw-r--r--sc/source/ui/miscdlgs/autofmt.cxx531
-rw-r--r--sc/source/ui/miscdlgs/conflictsdlg.cxx643
-rw-r--r--sc/source/ui/miscdlgs/crdlg.cxx45
-rw-r--r--sc/source/ui/miscdlgs/crnrdlg.cxx800
-rw-r--r--sc/source/ui/miscdlgs/datafdlg.cxx355
-rw-r--r--sc/source/ui/miscdlgs/dataproviderdlg.cxx1125
-rw-r--r--sc/source/ui/miscdlgs/datastreamdlg.cxx178
-rw-r--r--sc/source/ui/miscdlgs/datatableview.cxx320
-rw-r--r--sc/source/ui/miscdlgs/delcldlg.cxx101
-rw-r--r--sc/source/ui/miscdlgs/delcodlg.cxx125
-rw-r--r--sc/source/ui/miscdlgs/filldlg.cxx290
-rw-r--r--sc/source/ui/miscdlgs/gototabdlg.cxx81
-rw-r--r--sc/source/ui/miscdlgs/groupdlg.cxx52
-rw-r--r--sc/source/ui/miscdlgs/highred.cxx221
-rw-r--r--sc/source/ui/miscdlgs/inscldlg.cxx110
-rw-r--r--sc/source/ui/miscdlgs/inscodlg.cxx367
-rw-r--r--sc/source/ui/miscdlgs/instbdlg.cxx356
-rw-r--r--sc/source/ui/miscdlgs/lbseldlg.cxx54
-rw-r--r--sc/source/ui/miscdlgs/linkarea.cxx336
-rw-r--r--sc/source/ui/miscdlgs/mergecellsdialog.cxx36
-rw-r--r--sc/source/ui/miscdlgs/mtrindlg.cxx104
-rw-r--r--sc/source/ui/miscdlgs/mvtabdlg.cxx319
-rw-r--r--sc/source/ui/miscdlgs/namecrea.cxx55
-rw-r--r--sc/source/ui/miscdlgs/optsolver.cxx1075
-rw-r--r--sc/source/ui/miscdlgs/protectiondlg.cxx154
-rw-r--r--sc/source/ui/miscdlgs/redcom.cxx167
-rw-r--r--sc/source/ui/miscdlgs/retypepassdlg.cxx366
-rw-r--r--sc/source/ui/miscdlgs/scuiautofmt.cxx385
-rw-r--r--sc/source/ui/miscdlgs/sharedocdlg.cxx213
-rw-r--r--sc/source/ui/miscdlgs/shtabdlg.cxx66
-rw-r--r--sc/source/ui/miscdlgs/simpref.cxx190
-rw-r--r--sc/source/ui/miscdlgs/solveroptions.cxx415
-rw-r--r--sc/source/ui/miscdlgs/solverutil.cxx175
-rw-r--r--sc/source/ui/miscdlgs/solvrdlg.cxx282
-rw-r--r--sc/source/ui/miscdlgs/strindlg.cxx42
-rw-r--r--sc/source/ui/miscdlgs/tabbgcolordlg.cxx141
-rw-r--r--sc/source/ui/miscdlgs/tabopdlg.cxx345
-rw-r--r--sc/source/ui/miscdlgs/textdlgs.cxx94
-rw-r--r--sc/source/ui/miscdlgs/warnbox.cxx52
41 files changed, 13342 insertions, 0 deletions
diff --git a/sc/source/ui/miscdlgs/acredlin.cxx b/sc/source/ui/miscdlgs/acredlin.cxx
new file mode 100644
index 000000000..87292fe06
--- /dev/null
+++ b/sc/source/ui/miscdlgs/acredlin.cxx
@@ -0,0 +1,1792 @@
+/* -*- 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 <svl/undo.hxx>
+#include <unotools/textsearch.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <vcl/commandevent.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <acredlin.hxx>
+#include <global.hxx>
+#include <reffact.hxx>
+#include <document.hxx>
+#include <docsh.hxx>
+#include <scresid.hxx>
+#include <strings.hrc>
+#include <scmod.hxx>
+#include <tabvwsh.hxx>
+
+// defines -------------------------------------------------------------------
+
+#define RD_SPECIAL_NONE 0
+#define RD_SPECIAL_CONTENT 1
+#define RD_SPECIAL_VISCONTENT 2
+
+
+ScRedlinData::ScRedlinData()
+{
+ nInfo=RD_SPECIAL_NONE;
+ nActionNo=0;
+ pData=nullptr;
+ bDisabled=false;
+ bIsRejectable=false;
+ bIsAcceptable=false;
+ nTable=SCTAB_MAX;
+ nCol=SCCOL_MAX;
+ nRow=SCROW_MAX;
+}
+
+ScRedlinData::~ScRedlinData()
+{
+ nInfo=RD_SPECIAL_NONE;
+ nActionNo=0;
+ pData=nullptr;
+ bDisabled=false;
+ bIsRejectable=false;
+ bIsAcceptable=false;
+}
+
+
+ScAcceptChgDlg::ScAcceptChgDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ ScViewData* ptrViewData)
+ : SfxModelessDialogController(pB, pCW, pParent,
+ "svx/ui/acceptrejectchangesdialog.ui", "AcceptRejectChangesDialog")
+ , aSelectionIdle( "ScAcceptChgDlg aSelectionIdle" )
+ , aReOpenIdle("ScAcceptChgDlg ReOpenIdle")
+ , pViewData( ptrViewData )
+ , pDoc( &ptrViewData->GetDocument() )
+ , aStrInsertCols(ScResId(STR_CHG_INSERT_COLS))
+ , aStrInsertRows(ScResId(STR_CHG_INSERT_ROWS))
+ , aStrInsertTabs(ScResId(STR_CHG_INSERT_TABS))
+ , aStrDeleteCols(ScResId(STR_CHG_DELETE_COLS))
+ , aStrDeleteRows(ScResId(STR_CHG_DELETE_ROWS))
+ , aStrDeleteTabs(ScResId(STR_CHG_DELETE_TABS))
+ , aStrMove(ScResId(STR_CHG_MOVE))
+ , aStrContent(ScResId(STR_CHG_CONTENT))
+ , aStrReject(ScResId(STR_CHG_REJECT))
+ , aStrAllAccepted(ScResId(STR_CHG_ACCEPTED))
+ , aStrAllRejected(ScResId(STR_CHG_REJECTED))
+ , aStrNoEntry(ScResId(STR_CHG_NO_ENTRY))
+ , aStrContentWithChild(ScResId(STR_CHG_CONTENT_WITH_CHILD))
+ , aStrChildContent(ScResId(STR_CHG_CHILD_CONTENT))
+ , aStrChildOrgContent(ScResId(STR_CHG_CHILD_ORGCONTENT))
+ , aStrEmpty(ScResId(STR_CHG_EMPTY))
+ , aUnknown("Unknown")
+ , bIgnoreMsg(false)
+ , bNoSelection(false)
+ , bHasFilterEntry(false)
+ , bUseColor(false)
+ , m_xContentArea(m_xDialog->weld_content_area())
+ , m_xPopup(m_xBuilder->weld_menu("calcmenu"))
+ , m_xSortMenu(m_xBuilder->weld_menu("calcsortmenu"))
+{
+ m_xAcceptChgCtr.reset(new SvxAcceptChgCtr(m_xContentArea.get()));
+ nAcceptCount=0;
+ nRejectCount=0;
+ aReOpenIdle.SetInvokeHandler(LINK( this, ScAcceptChgDlg, ReOpenTimerHdl ));
+
+ pTPFilter = m_xAcceptChgCtr->GetFilterPage();
+ pTPView = m_xAcceptChgCtr->GetViewPage();
+
+ // tdf#136062 Don't use "Reject/Clear formatting" instead of "Reject" buttons in Calc
+ pTPView->EnableClearFormat(false);
+ pTPView->EnableClearFormatAll(false);
+
+ pTheView = pTPView->GetTableControl();
+ pTheView->SetCalcView();
+ aSelectionIdle.SetInvokeHandler(LINK( this, ScAcceptChgDlg, UpdateSelectionHdl ));
+
+ pTPFilter->SetReadyHdl(LINK( this, ScAcceptChgDlg, FilterHandle ));
+ pTPFilter->SetRefHdl(LINK( this, ScAcceptChgDlg, RefHandle ));
+ pTPFilter->HideRange(false);
+ pTPView->SetRejectClickHdl( LINK( this, ScAcceptChgDlg,RejectHandle));
+ pTPView->SetAcceptClickHdl( LINK(this, ScAcceptChgDlg, AcceptHandle));
+ pTPView->SetRejectAllClickHdl( LINK( this, ScAcceptChgDlg,RejectAllHandle));
+ pTPView->SetAcceptAllClickHdl( LINK(this, ScAcceptChgDlg, AcceptAllHandle));
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.connect_expanding(LINK(this, ScAcceptChgDlg, ExpandingHandle));
+ rTreeView.connect_changed(LINK(this, ScAcceptChgDlg, SelectHandle));
+ rTreeView.connect_popup_menu(LINK(this, ScAcceptChgDlg, CommandHdl));
+ rTreeView.set_sort_func([this](const weld::TreeIter& rLeft, const weld::TreeIter& rRight){
+ return ColCompareHdl(rLeft, rRight);
+ });
+ rTreeView.set_selection_mode(SelectionMode::Multiple);
+
+ Init();
+
+ UpdateView();
+
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xEntry))
+ rTreeView.select(*xEntry);
+}
+
+ScAcceptChgDlg::~ScAcceptChgDlg()
+{
+ ClearView();
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ if (pChanges)
+ {
+ Link<ScChangeTrack&,void> aLink;
+ pChanges->SetModifiedLink(aLink);
+ }
+}
+
+void ScAcceptChgDlg::ReInit(ScViewData* ptrViewData)
+{
+ pViewData=ptrViewData;
+ if (pViewData)
+ pDoc = &ptrViewData->GetDocument();
+ else
+ pDoc = nullptr;
+
+ bNoSelection=false;
+ bIgnoreMsg=false;
+ nAcceptCount=0;
+ nRejectCount=0;
+
+ // don't call Init here (switching between views), just set link below
+ // (dialog is just hidden, not deleted anymore, when switching views)
+ ClearView();
+ UpdateView();
+
+ if ( pDoc )
+ {
+ ScChangeTrack* pChanges = pDoc->GetChangeTrack();
+ if ( pChanges )
+ pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg, ChgTrackModHdl ) );
+ }
+}
+
+void ScAcceptChgDlg::Init()
+{
+ OSL_ENSURE( pViewData && pDoc, "ViewData or Document not found!" );
+
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ if(pChanges!=nullptr)
+ {
+ pChanges->SetModifiedLink( LINK( this, ScAcceptChgDlg,ChgTrackModHdl));
+ aChangeViewSet.SetTheAuthorToShow(pChanges->GetUser());
+ pTPFilter->ClearAuthors();
+ const std::set<OUString>& rUserColl = pChanges->GetUserCollection();
+ for (const auto& rItem : rUserColl)
+ pTPFilter->InsertAuthor(rItem);
+ }
+
+ ScChangeViewSettings* pViewSettings=pDoc->GetChangeViewSettings();
+ if ( pViewSettings!=nullptr )
+ aChangeViewSet = *pViewSettings;
+ // adjust TimeField for filter tabpage
+ aChangeViewSet.AdjustDateMode( *pDoc );
+
+ pTPFilter->CheckDate(aChangeViewSet.HasDate());
+
+ DateTime aEmpty(DateTime::EMPTY);
+
+ DateTime aDateTime(aChangeViewSet.GetTheFirstDateTime());
+ if (aDateTime != aEmpty)
+ {
+ pTPFilter->SetFirstDate(aDateTime);
+ pTPFilter->SetFirstTime(aDateTime);
+ }
+ aDateTime = aChangeViewSet.GetTheLastDateTime();
+ if (aDateTime != aEmpty)
+ {
+ pTPFilter->SetLastDate(aDateTime);
+ pTPFilter->SetLastTime(aDateTime);
+ }
+
+ pTPFilter->SetDateMode(static_cast<sal_uInt16>(aChangeViewSet.GetTheDateMode()));
+ pTPFilter->CheckComment(aChangeViewSet.HasComment());
+ pTPFilter->SetComment(aChangeViewSet.GetTheComment());
+
+ pTPFilter->CheckAuthor(aChangeViewSet.HasAuthor());
+ OUString aString=aChangeViewSet.GetTheAuthorToShow();
+ if(!aString.isEmpty())
+ {
+ pTPFilter->SelectAuthor(aString);
+ if(pTPFilter->GetSelectedAuthor()!=aString)
+ {
+ pTPFilter->InsertAuthor(aString);
+ pTPFilter->SelectAuthor(aString);
+ }
+ }
+ else
+ pTPFilter->SelectedAuthorPos(0);
+
+ pTPFilter->CheckRange(aChangeViewSet.HasRange());
+
+ aRangeList=aChangeViewSet.GetTheRangeList();
+
+ if( !aChangeViewSet.GetTheRangeList().empty() )
+ {
+ const ScRange & rRangeEntry = aChangeViewSet.GetTheRangeList().front();
+ OUString aRefStr(rRangeEntry.Format(*pDoc, ScRefFlags::RANGE_ABS_3D));
+ pTPFilter->SetRange(aRefStr);
+ }
+
+ // init filter
+ if(!(pTPFilter->IsDate()||pTPFilter->IsRange()||
+ pTPFilter->IsAuthor()||pTPFilter->IsComment()))
+ return;
+
+ pTheView->SetFilterDate(pTPFilter->IsDate());
+ pTheView->SetDateTimeMode(pTPFilter->GetDateMode());
+ pTheView->SetFirstDate(pTPFilter->GetFirstDate());
+ pTheView->SetLastDate(pTPFilter->GetLastDate());
+ pTheView->SetFirstTime(pTPFilter->GetFirstTime());
+ pTheView->SetLastTime(pTPFilter->GetLastTime());
+ pTheView->SetFilterAuthor(pTPFilter->IsAuthor());
+ pTheView->SetAuthor(pTPFilter->GetSelectedAuthor());
+
+ pTheView->SetFilterComment(pTPFilter->IsComment());
+
+ utl::SearchParam aSearchParam( pTPFilter->GetComment(),
+ utl::SearchParam::SearchType::Regexp,false );
+
+ pTheView->SetCommentParams(&aSearchParam);
+
+ pTheView->UpdateFilterTest();
+}
+
+void ScAcceptChgDlg::ClearView()
+{
+ nAcceptCount=0;
+ nRejectCount=0;
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.all_foreach(
+ [&rTreeView](weld::TreeIter& rEntry)
+ {
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
+ delete pEntryData;
+ return false;
+ });
+ rTreeView.freeze();
+ rTreeView.clear();
+ rTreeView.thaw();
+}
+
+OUString* ScAcceptChgDlg::MakeTypeString(ScChangeActionType eType)
+{
+ OUString* pStr;
+
+ switch(eType)
+ {
+
+ case SC_CAT_INSERT_COLS: pStr=&aStrInsertCols;break;
+ case SC_CAT_INSERT_ROWS: pStr=&aStrInsertRows;break;
+ case SC_CAT_INSERT_TABS: pStr=&aStrInsertTabs;break;
+ case SC_CAT_DELETE_COLS: pStr=&aStrDeleteCols;break;
+ case SC_CAT_DELETE_ROWS: pStr=&aStrDeleteRows;break;
+ case SC_CAT_DELETE_TABS: pStr=&aStrDeleteTabs;break;
+ case SC_CAT_MOVE: pStr=&aStrMove;break;
+ case SC_CAT_CONTENT: pStr=&aStrContent;break;
+ case SC_CAT_REJECT: pStr=&aStrReject;break;
+ default: pStr=&aUnknown;break;
+ }
+ return pStr;
+}
+
+bool ScAcceptChgDlg::IsValidAction(const ScChangeAction* pScChangeAction)
+{
+ if(pScChangeAction==nullptr) return false;
+
+ bool bFlag = false;
+
+ ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
+ OUString aUser=pScChangeAction->GetUser();
+ DateTime aDateTime=pScChangeAction->GetDateTime();
+
+ ScChangeActionType eType=pScChangeAction->GetType();
+ OUString aDesc;
+
+ OUString aComment = pScChangeAction->GetComment().replaceAll("\n", "");
+
+ if(eType==SC_CAT_CONTENT)
+ {
+ if(!pScChangeAction->IsDialogParent())
+ aDesc = pScChangeAction->GetDescription(*pDoc, true);
+ }
+ else
+ aDesc = pScChangeAction->GetDescription(*pDoc, !pScChangeAction->IsMasterDelete());
+
+ if (!aDesc.isEmpty())
+ {
+ aComment += " (" + aDesc + ")";
+ }
+
+ if (pTheView->IsValidEntry(aUser, aDateTime, aComment))
+ {
+ if(pTPFilter->IsRange())
+ {
+ for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
+ {
+ ScRange const & rRangeEntry = aRangeList[ i ];
+ if (rRangeEntry.Intersects(aRef)) {
+ bFlag = true;
+ break;
+ }
+ }
+ }
+ else
+ bFlag=true;
+ }
+
+ return bFlag;
+}
+
+std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::AppendChangeAction(
+ const ScChangeAction* pScChangeAction, bool bCreateOnDemand,
+ const weld::TreeIter* pParent, bool bDelMaster, bool bDisabled)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr;
+
+ bool bFlag = false;
+
+ ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
+ DateTime aDateTime=pScChangeAction->GetDateTime();
+
+ ScChangeActionType eType=pScChangeAction->GetType();
+ OUString aActionString;
+ OUString aRefStr;
+ OUString aUser;
+ OUString aDate;
+ OUString aDesc;
+
+ std::unique_ptr<ScRedlinData> pNewData(new ScRedlinData);
+ pNewData->pData=const_cast<ScChangeAction *>(pScChangeAction);
+ pNewData->nActionNo=pScChangeAction->GetActionNumber();
+ pNewData->bIsAcceptable=pScChangeAction->IsClickable();
+ pNewData->bIsRejectable=pScChangeAction->IsRejectable();
+ pNewData->bDisabled=!pNewData->bIsAcceptable || bDisabled;
+ pNewData->aDateTime=aDateTime;
+ pNewData->nRow = aRef.aStart.Row();
+ pNewData->nCol = aRef.aStart.Col();
+ pNewData->nTable= aRef.aStart.Tab();
+
+ if(eType==SC_CAT_CONTENT)
+ {
+ if(pScChangeAction->IsDialogParent())
+ {
+ aActionString = aStrContentWithChild;
+ pNewData->nInfo=RD_SPECIAL_VISCONTENT;
+ pNewData->bIsRejectable=false;
+ pNewData->bIsAcceptable=false;
+ }
+ else
+ {
+ aActionString = *MakeTypeString(eType);
+ aDesc = pScChangeAction->GetDescription(*pDoc, true);
+ }
+ }
+ else
+ {
+ aActionString = *MakeTypeString(eType);
+
+ if(bDelMaster)
+ {
+ aDesc = pScChangeAction->GetDescription(*pDoc,true);
+ pNewData->bDisabled=true;
+ pNewData->bIsRejectable=false;
+ }
+ else
+ aDesc = pScChangeAction->GetDescription(*pDoc, !pScChangeAction->IsMasterDelete());
+
+ }
+
+ aRefStr = pScChangeAction->GetRefString(*pDoc, true);
+
+ bool bIsGenerated = false;
+
+ if(!pChanges->IsGenerated(pScChangeAction->GetActionNumber()))
+ {
+ aUser = pScChangeAction->GetUser();
+ aDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime);
+ bIsGenerated = false;
+ }
+ else
+ {
+ bIsGenerated = true;
+ }
+
+ OUString aComment = pScChangeAction->GetComment().replaceAll("\n", "");
+
+ if (!aDesc.isEmpty())
+ {
+ aComment += " (" + aDesc + ")";
+ }
+
+ if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated)
+ {
+ if (pTheView->IsValidComment(aComment))
+ {
+ if(pTPFilter->IsRange())
+ {
+ for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
+ {
+ ScRange const & rRangeEntry = aRangeList[ i ];
+ if( rRangeEntry.Intersects(aRef) )
+ {
+ bHasFilterEntry=true;
+ bFlag=true;
+ break;
+ }
+ }
+ }
+ else if(!bIsGenerated)
+ {
+ bHasFilterEntry=true;
+ bFlag=true;
+ }
+ }
+ }
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ OUString sId(weld::toId(pNewData.release()));
+ rTreeView.insert(pParent, -1, &aActionString, &sId, nullptr, nullptr, bCreateOnDemand, xEntry.get());
+ rTreeView.set_text( *xEntry, aRefStr, 1);
+ if (!aUser.isEmpty())
+ rTreeView.set_text( *xEntry, aUser, 2);
+ if (!aDate.isEmpty())
+ rTreeView.set_text( *xEntry, aDate, 3);
+ if (!aComment.isEmpty())
+ rTreeView.set_text( *xEntry, aComment, 4);
+ if (!bFlag && bUseColor && !pParent)
+ {
+ rTreeView.set_font_color(*xEntry, COL_LIGHTBLUE);
+ }
+ else if (bFlag && bUseColor && pParent)
+ {
+ rTreeView.set_font_color(*xEntry, COL_GREEN);
+
+ std::unique_ptr<weld::TreeIter> xExpEntry(rTreeView.make_iterator(pParent));
+
+ while (!rTreeView.get_row_expanded(*xExpEntry))
+ {
+ if (rTreeView.get_iter_depth(*xExpEntry))
+ rTreeView.expand_row(*xExpEntry);
+
+ if (!rTreeView.iter_parent(*xExpEntry))
+ break;
+ }
+ }
+ return xEntry;
+}
+
+std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::AppendFilteredAction(
+ const ScChangeAction* pScChangeAction, ScChangeActionState eState,
+ bool bCreateOnDemand,
+ const weld::TreeIter* pParent, bool bDelMaster, bool bDisabled)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr;
+
+ bool bIsGenerated = pChanges->IsGenerated(pScChangeAction->GetActionNumber());
+
+ bool bFlag = false;
+
+ ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
+ OUString aUser=pScChangeAction->GetUser();
+ DateTime aDateTime=pScChangeAction->GetDateTime();
+
+ if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated)
+ {
+ if(pTPFilter->IsRange())
+ {
+ for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
+ {
+ ScRange const & rRangeEntry=aRangeList[ i ];
+ if( rRangeEntry.Intersects(aRef) )
+ {
+ if( pScChangeAction->GetState()==eState )
+ bFlag = true;
+ break;
+ }
+ }
+ }
+ else if(pScChangeAction->GetState()==eState && !bIsGenerated)
+ bFlag = true;
+ }
+
+ std::unique_ptr<weld::TreeIter> xEntry;
+ if(bFlag)
+ {
+ ScChangeActionType eType=pScChangeAction->GetType();
+ OUString aActionString;
+ OUString aDesc;
+
+ std::unique_ptr<ScRedlinData> pNewData(new ScRedlinData);
+ pNewData->pData=const_cast<ScChangeAction *>(pScChangeAction);
+ pNewData->nActionNo=pScChangeAction->GetActionNumber();
+ pNewData->bIsAcceptable=pScChangeAction->IsClickable();
+ pNewData->bIsRejectable=pScChangeAction->IsRejectable();
+ pNewData->bDisabled=!pNewData->bIsAcceptable || bDisabled;
+ pNewData->aDateTime=aDateTime;
+ pNewData->nRow = aRef.aStart.Row();
+ pNewData->nCol = aRef.aStart.Col();
+ pNewData->nTable= aRef.aStart.Tab();
+
+ if(eType==SC_CAT_CONTENT)
+ {
+ if(pScChangeAction->IsDialogParent())
+ {
+ aActionString=aStrContentWithChild;
+ pNewData->nInfo=RD_SPECIAL_VISCONTENT;
+ pNewData->bIsRejectable=false;
+ pNewData->bIsAcceptable=false;
+ }
+ else
+ {
+ aActionString=*MakeTypeString(eType);
+ aDesc = pScChangeAction->GetDescription(*pDoc, true);
+ }
+ }
+ else
+ {
+ aActionString=*MakeTypeString(eType);
+
+ if(bDelMaster)
+ {
+ aDesc = pScChangeAction->GetDescription(*pDoc,true);
+ pNewData->bDisabled=true;
+ pNewData->bIsRejectable=false;
+ }
+ else
+ aDesc = pScChangeAction->GetDescription(*pDoc,!pScChangeAction->IsMasterDelete());
+
+ }
+
+
+ OUString aComment = pScChangeAction->GetComment().replaceAll("\n", "");
+ if (!aDesc.isEmpty())
+ {
+ aComment += " (" + aDesc + ")";
+ }
+ if (pTheView->IsValidComment(aComment))
+ {
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ xEntry = rTreeView.make_iterator();
+ OUString sId(weld::toId(pNewData.release()));
+ rTreeView.insert(pParent, -1, &aActionString, &sId, nullptr, nullptr, bCreateOnDemand, xEntry.get());
+
+ OUString aRefStr = pScChangeAction->GetRefString(*pDoc, true);
+ rTreeView.set_text(*xEntry, aRefStr, 1);
+
+ if (!bIsGenerated)
+ {
+ rTreeView.set_text(*xEntry, aUser, 2);
+ OUString sDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime);
+ rTreeView.set_text(*xEntry, sDate, 3);
+ }
+
+ rTreeView.set_text(*xEntry, aComment, 4);
+ }
+ }
+ return xEntry;
+}
+
+std::unique_ptr<weld::TreeIter> ScAcceptChgDlg::InsertChangeActionContent(const ScChangeActionContent* pScChangeAction,
+ const weld::TreeIter& rParent, sal_uLong nSpecial)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ if(pScChangeAction==nullptr || pChanges==nullptr) return nullptr;
+
+ bool bIsGenerated = pChanges->IsGenerated(pScChangeAction->GetActionNumber());
+
+ bool bFlag = false;
+
+ ScRange aRef=pScChangeAction->GetBigRange().MakeRange(*pDoc);
+ OUString aUser=pScChangeAction->GetUser();
+ DateTime aDateTime=pScChangeAction->GetDateTime();
+
+ if (pTheView->IsValidEntry(aUser, aDateTime) || bIsGenerated)
+ {
+ if(pTPFilter->IsRange())
+ {
+ for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
+ {
+ ScRange const & rRangeEntry = aRangeList[ i ];
+ if( rRangeEntry.Intersects(aRef) )
+ {
+ bFlag=true;
+ break;
+ }
+ }
+ }
+ else if(!bIsGenerated)
+ bFlag=true;
+ }
+
+ OUString aContent;
+ OUString aRefStr;
+ OUString aDate;
+ OUString aDesc;
+
+ if(nSpecial==RD_SPECIAL_CONTENT)
+ {
+ aContent = pScChangeAction->GetOldString(pDoc);
+ if (aContent.isEmpty())
+ aContent = aStrEmpty;
+ aDesc = aStrChildOrgContent + ": " + aContent;
+ }
+ else
+ {
+ const OUString aTmp( pScChangeAction->GetNewString(pDoc));
+ if (aTmp.isEmpty())
+ aContent = aStrEmpty;
+ else
+ aContent = "\'" + aTmp + "\'";
+ aDesc = aStrChildContent + aContent;
+ }
+
+ aRefStr = pScChangeAction->GetRefString(*pDoc, true);
+
+ if(!bIsGenerated)
+ {
+ // aUser is kept.
+ aDate = ScGlobal::getLocaleData().getDate(aDateTime) + " " + ScGlobal::getLocaleData().getTime(aDateTime);
+ }
+ else
+ {
+ aUser.clear();
+ }
+
+ OUString aComment = pScChangeAction->GetComment().replaceAll("\n", "");
+
+ if(!aDesc.isEmpty())
+ {
+ aComment += " (" + aDesc + ")";
+ }
+
+ std::unique_ptr<ScRedlinData> pNewData(new ScRedlinData);
+ pNewData->nInfo=nSpecial;
+ pNewData->pData=const_cast<ScChangeActionContent *>(pScChangeAction);
+ pNewData->nActionNo=pScChangeAction->GetActionNumber();
+ pNewData->bIsAcceptable=pScChangeAction->IsClickable();
+ pNewData->bIsRejectable=false;
+ pNewData->bDisabled=!pNewData->bIsAcceptable;
+ pNewData->aDateTime=aDateTime;
+ pNewData->nRow = aRef.aStart.Row();
+ pNewData->nCol = aRef.aStart.Col();
+ pNewData->nTable= aRef.aStart.Tab();
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ OUString sId(weld::toId(pNewData.release()));
+ rTreeView.insert(&rParent, -1, &aContent, &sId, nullptr, nullptr, false, xEntry.get());
+ rTreeView.set_text( *xEntry, aRefStr, 1);
+ if (!aUser.isEmpty())
+ rTreeView.set_text( *xEntry, aUser, 2);
+ if (!aDate.isEmpty())
+ rTreeView.set_text( *xEntry, aDate, 3);
+ if (!aComment.isEmpty())
+ rTreeView.set_text( *xEntry, aComment, 4);
+ if (pTheView->IsValidComment(aComment) && bFlag)
+ bHasFilterEntry=true;
+ else
+ {
+ rTreeView.set_font_color(*xEntry, COL_LIGHTBLUE);
+ }
+ return xEntry;
+}
+
+void ScAcceptChgDlg::UpdateView()
+{
+ std::unique_ptr<weld::TreeIter> xParent;
+ ScChangeTrack* pChanges=nullptr;
+ const ScChangeAction* pScChangeAction=nullptr;
+ m_xDialog->set_busy_cursor(true);
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.freeze();
+ bool bFilterFlag = pTPFilter->IsDate() || pTPFilter->IsRange() ||
+ pTPFilter->IsAuthor() || pTPFilter->IsComment();
+
+ bUseColor = bFilterFlag;
+
+ if(pDoc!=nullptr)
+ {
+ pChanges=pDoc->GetChangeTrack();
+ if(pChanges!=nullptr)
+ pScChangeAction=pChanges->GetFirst();
+ }
+ bool bTheFlag = false;
+
+ while(pScChangeAction!=nullptr)
+ {
+ bHasFilterEntry=false;
+ switch (pScChangeAction->GetState())
+ {
+ case SC_CAS_VIRGIN:
+
+ if (pScChangeAction->IsDialogRoot())
+ {
+ bool bOnDemandChildren = !bFilterFlag && pScChangeAction->IsDialogParent();
+ if (pScChangeAction->IsDialogParent())
+ xParent = AppendChangeAction(pScChangeAction, bOnDemandChildren);
+ else
+ xParent = AppendFilteredAction(pScChangeAction, SC_CAS_VIRGIN, bOnDemandChildren);
+ }
+ else
+ xParent.reset();
+
+ bTheFlag=true;
+ break;
+
+ case SC_CAS_ACCEPTED:
+ xParent.reset();
+ nAcceptCount++;
+ break;
+
+ case SC_CAS_REJECTED:
+ xParent.reset();
+ nRejectCount++;
+ break;
+ }
+
+ if (xParent && pScChangeAction->IsDialogParent() && bFilterFlag)
+ {
+ bool bTestFlag = bHasFilterEntry;
+ bHasFilterEntry=false;
+ if (Expand(pChanges, pScChangeAction, *xParent, !bTestFlag) && !bTestFlag)
+ rTreeView.remove(*xParent);
+ }
+
+ pScChangeAction=pScChangeAction->GetNext();
+ }
+
+ if( bTheFlag && (!pDoc->IsDocEditable() || pChanges->IsProtected()) )
+ bTheFlag=false;
+
+ pTPView->EnableAccept(bTheFlag);
+ pTPView->EnableAcceptAll(bTheFlag);
+ pTPView->EnableReject(bTheFlag);
+ pTPView->EnableRejectAll(bTheFlag);
+
+ if (nAcceptCount>0)
+ rTreeView.insert(nullptr, -1, &aStrAllAccepted, nullptr, nullptr, nullptr, true, nullptr);
+ if (nRejectCount>0)
+ rTreeView.insert(nullptr, -1, &aStrAllRejected, nullptr, nullptr, nullptr, true, nullptr);
+ rTreeView.thaw();
+ m_xDialog->set_busy_cursor(false);
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xEntry))
+ rTreeView.select(*xEntry);
+}
+
+IMPL_LINK_NOARG(ScAcceptChgDlg, RefHandle, SvxTPFilter*, void)
+{
+ sal_uInt16 nId =ScSimpleRefDlgWrapper::GetChildWindowId();
+
+ SC_MOD()->SetRefDialog( nId, true );
+
+ SfxViewFrame* pViewFrm = pViewData->GetViewShell()->GetViewFrame();
+ ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(pViewFrm->GetChildWindow( nId ));
+
+ if(pWnd!=nullptr)
+ {
+ sal_uInt16 nAcceptId=ScAcceptChgDlgWrapper::GetChildWindowId();
+ pViewFrm->ShowChildWindow(nAcceptId,false);
+ pWnd->SetCloseHdl(LINK( this, ScAcceptChgDlg,RefInfoHandle));
+ pWnd->SetRefString(pTPFilter->GetRange());
+ ScSimpleRefDlgWrapper::SetAutoReOpen(false);
+ auto xWin = pWnd->GetController();
+ m_xDialog->hide();
+ xWin->set_title(m_xDialog->get_title());
+ pWnd->StartRefInput();
+ }
+}
+
+IMPL_LINK( ScAcceptChgDlg, RefInfoHandle, const OUString*, pResult, void)
+{
+ sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId();
+
+ ScSimpleRefDlgWrapper::SetAutoReOpen(true);
+
+ SfxViewFrame* pViewFrm = pViewData->GetViewShell()->GetViewFrame();
+ if (pResult)
+ {
+ pTPFilter->SetRange(*pResult);
+ FilterHandle(pTPFilter);
+
+ pViewFrm->ShowChildWindow(nId);
+ }
+ else
+ {
+ pViewFrm->SetChildWindow(nId, false);
+ }
+}
+
+IMPL_LINK( ScAcceptChgDlg, FilterHandle, SvxTPFilter*, pRef, void )
+{
+ if(pRef!=nullptr)
+ {
+ ClearView();
+ aRangeList.RemoveAll();
+ aRangeList.Parse(pTPFilter->GetRange(), *pDoc);
+ UpdateView();
+ }
+}
+
+IMPL_LINK( ScAcceptChgDlg, RejectHandle, SvxTPView*, pRef, void )
+{
+ m_xDialog->set_busy_cursor(true);
+
+ bIgnoreMsg=true;
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ if(pRef!=nullptr)
+ {
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.selected_foreach([this, pChanges, &rTreeView](weld::TreeIter& rEntry){
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
+ if (pEntryData)
+ {
+ ScChangeAction* pScChangeAction= static_cast<ScChangeAction*>(pEntryData->pData);
+ if (pScChangeAction->GetType()==SC_CAT_INSERT_TABS)
+ pViewData->SetTabNo(0);
+ pChanges->Reject(pScChangeAction);
+ }
+ return false;
+ });
+ ScDocShell* pDocSh=pViewData->GetDocShell();
+ pDocSh->PostPaintExtras();
+ pDocSh->PostPaintGridAll();
+ pDocSh->GetUndoManager()->Clear();
+ pDocSh->SetDocumentModified();
+ ClearView();
+ UpdateView();
+ }
+
+ m_xDialog->set_busy_cursor(false);
+
+ bIgnoreMsg=false;
+}
+IMPL_LINK( ScAcceptChgDlg, AcceptHandle, SvxTPView*, pRef, void )
+{
+ m_xDialog->set_busy_cursor(true);
+
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ bIgnoreMsg=true;
+ if(pRef!=nullptr)
+ {
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.selected_foreach([pChanges, &rTreeView](weld::TreeIter& rEntry) {
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
+ if (pEntryData)
+ {
+ ScChangeAction* pScChangeAction=
+ static_cast<ScChangeAction*>(pEntryData->pData);
+ if(pScChangeAction->GetType()==SC_CAT_CONTENT)
+ {
+ if(pEntryData->nInfo==RD_SPECIAL_CONTENT)
+ pChanges->SelectContent(pScChangeAction,true);
+ else
+ pChanges->SelectContent(pScChangeAction);
+ }
+ else
+ pChanges->Accept(pScChangeAction);
+ }
+ return false;
+ });
+ ScDocShell* pDocSh=pViewData->GetDocShell();
+ pDocSh->PostPaintExtras();
+ pDocSh->PostPaintGridAll();
+ pDocSh->SetDocumentModified();
+ ClearView();
+ UpdateView();
+ }
+ m_xDialog->set_busy_cursor(false);
+ bIgnoreMsg=false;
+}
+
+void ScAcceptChgDlg::RejectFiltered()
+{
+ if(pDoc==nullptr) return;
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ const ScChangeAction* pScChangeAction=nullptr;
+
+ if(pChanges!=nullptr)
+ {
+ pScChangeAction=pChanges->GetLast();
+ }
+
+ while(pScChangeAction!=nullptr)
+ {
+ if(pScChangeAction->IsDialogRoot())
+ if(IsValidAction(pScChangeAction))
+ pChanges->Reject(const_cast<ScChangeAction*>(pScChangeAction));
+
+ pScChangeAction=pScChangeAction->GetPrev();
+ }
+}
+void ScAcceptChgDlg::AcceptFiltered()
+{
+ if(pDoc==nullptr) return;
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ const ScChangeAction* pScChangeAction=nullptr;
+
+ if(pChanges!=nullptr)
+ pScChangeAction=pChanges->GetLast();
+
+ while(pScChangeAction!=nullptr)
+ {
+ if(pScChangeAction->IsDialogRoot())
+ if(IsValidAction(pScChangeAction))
+ pChanges->Accept(const_cast<ScChangeAction*>(pScChangeAction));
+
+ pScChangeAction=pScChangeAction->GetPrev();
+ }
+}
+
+IMPL_LINK_NOARG(ScAcceptChgDlg, RejectAllHandle, SvxTPView*, void)
+{
+ m_xDialog->set_busy_cursor(true);
+ bIgnoreMsg=true;
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ if(pChanges!=nullptr)
+ {
+ if(pTPFilter->IsDate()||pTPFilter->IsAuthor()||pTPFilter->IsRange()||pTPFilter->IsComment())
+ RejectFiltered();
+ else
+ pChanges->RejectAll();
+
+ pViewData->SetTabNo(0);
+
+ ScDocShell* pDocSh=pViewData->GetDocShell();
+ pDocSh->PostPaintExtras();
+ pDocSh->PostPaintGridAll();
+ pDocSh->GetUndoManager()->Clear();
+ pDocSh->SetDocumentModified();
+ ClearView();
+ UpdateView();
+ }
+ m_xDialog->set_busy_cursor(false);
+
+ bIgnoreMsg=false;
+}
+
+IMPL_LINK_NOARG(ScAcceptChgDlg, AcceptAllHandle, SvxTPView*, void)
+{
+ m_xDialog->set_busy_cursor(true);
+
+ bIgnoreMsg=true;
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ if(pChanges!=nullptr)
+ {
+ if(pTPFilter->IsDate()||pTPFilter->IsAuthor()||pTPFilter->IsRange()||pTPFilter->IsComment())
+ AcceptFiltered();
+ else
+ pChanges->AcceptAll();
+
+ ScDocShell* pDocSh=pViewData->GetDocShell();
+ pDocSh->PostPaintExtras();
+ pDocSh->PostPaintGridAll();
+ pDocSh->SetDocumentModified();
+ ClearView();
+ UpdateView();
+ }
+ bIgnoreMsg=false;
+
+ m_xDialog->set_busy_cursor(false);
+}
+
+IMPL_LINK_NOARG(ScAcceptChgDlg, SelectHandle, weld::TreeView&, void)
+{
+ if (!bNoSelection)
+ aSelectionIdle.Start();
+
+ bNoSelection=false;
+}
+
+void ScAcceptChgDlg::GetDependents(const ScChangeAction* pScChangeAction,
+ ScChangeActionMap& aActionMap,
+ const weld::TreeIter& rEntry)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
+ if (rTreeView.iter_parent(*xParent))
+ {
+ ScRedlinData *pParentData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xParent));
+ ScChangeAction* pParentAction=static_cast<ScChangeAction*>(pParentData->pData);
+
+ if(pParentAction!=pScChangeAction)
+ pChanges->GetDependents(const_cast<ScChangeAction*>(pScChangeAction),
+ aActionMap,pScChangeAction->IsMasterDelete());
+ else
+ pChanges->GetDependents( const_cast<ScChangeAction*>(pScChangeAction),
+ aActionMap );
+ }
+ else
+ pChanges->GetDependents(const_cast<ScChangeAction*>(pScChangeAction),
+ aActionMap, pScChangeAction->IsMasterDelete() );
+}
+
+bool ScAcceptChgDlg::InsertContentChildren(ScChangeActionMap* pActionMap, const weld::TreeIter& rParent)
+{
+ bool bTheTestFlag = true;
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rParent));
+ const ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
+ bool bParentInserted = false;
+ // If the parent is a MatrixOrigin then place it in the right order before
+ // the MatrixReferences. Also if it is the first content change at this
+ // position don't insert the first dependent MatrixReference as the special
+ // content (original value) but insert the predecessor of the MatrixOrigin
+ // itself instead.
+ if ( pScChangeAction->GetType() == SC_CAT_CONTENT &&
+ static_cast<const ScChangeActionContent*>(pScChangeAction)->IsMatrixOrigin() )
+ {
+ pActionMap->insert( ::std::make_pair( pScChangeAction->GetActionNumber(),
+ const_cast<ScChangeAction*>( pScChangeAction ) ) );
+ bParentInserted = true;
+ }
+
+ ScChangeActionMap::iterator itChangeAction = std::find_if(pActionMap->begin(), pActionMap->end(),
+ [](const std::pair<sal_uLong, ScChangeAction*>& rEntry) { return rEntry.second->GetState() == SC_CAS_VIRGIN; });
+
+ if( itChangeAction == pActionMap->end() )
+ return true;
+
+ std::unique_ptr<weld::TreeIter> xOriginal = InsertChangeActionContent(
+ dynamic_cast<const ScChangeActionContent*>( itChangeAction->second ),
+ rParent, RD_SPECIAL_CONTENT );
+
+ if (xOriginal)
+ {
+ bTheTestFlag=false;
+ ScRedlinData *pParentData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xOriginal));
+ pParentData->pData=const_cast<ScChangeAction *>(pScChangeAction);
+ pParentData->nActionNo=pScChangeAction->GetActionNumber();
+ pParentData->bIsAcceptable=pScChangeAction->IsRejectable(); // select old value
+ pParentData->bIsRejectable=false;
+ pParentData->bDisabled=false;
+ }
+ while( itChangeAction != pActionMap->end() )
+ {
+ if( itChangeAction->second->GetState() == SC_CAS_VIRGIN )
+ {
+ std::unique_ptr<weld::TreeIter> xEntry =
+ InsertChangeActionContent( dynamic_cast<const ScChangeActionContent*>( itChangeAction->second ),
+ rParent, RD_SPECIAL_NONE );
+
+ if (xEntry)
+ bTheTestFlag=false;
+ }
+ ++itChangeAction;
+ }
+
+ if ( !bParentInserted )
+ {
+ std::unique_ptr<weld::TreeIter> xEntry =
+ InsertChangeActionContent(static_cast<const ScChangeActionContent*>(
+ pScChangeAction),rParent,RD_SPECIAL_NONE);
+
+ if (xEntry)
+ {
+ bTheTestFlag=false;
+ ScRedlinData *pParentData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+ pParentData->pData=const_cast<ScChangeAction *>(pScChangeAction);
+ pParentData->nActionNo=pScChangeAction->GetActionNumber();
+ pParentData->bIsAcceptable=pScChangeAction->IsClickable();
+ pParentData->bIsRejectable=false;
+ pParentData->bDisabled=false;
+ }
+ }
+
+ return bTheTestFlag;
+}
+
+bool ScAcceptChgDlg::InsertAcceptedORejected(const weld::TreeIter& rParent)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ bool bTheTestFlag = true;
+
+ ScChangeActionState eState = SC_CAS_VIRGIN;
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ OUString aString = rTreeView.get_text(rParent, 0);
+ OUString a2String = aString.copy(0, aStrAllAccepted.getLength());
+ if (a2String == aStrAllAccepted)
+ eState=SC_CAS_ACCEPTED;
+ else
+ {
+ a2String = aString.copy(0, aStrAllRejected.getLength());
+ if (a2String == aStrAllRejected)
+ eState=SC_CAS_REJECTED;
+ }
+
+ ScChangeAction* pScChangeAction = pChanges->GetFirst();
+ while (pScChangeAction)
+ {
+ if (pScChangeAction->GetState()==eState &&
+ AppendFilteredAction(pScChangeAction, eState, false, &rParent))
+ bTheTestFlag=false;
+ pScChangeAction=pScChangeAction->GetNext();
+ }
+ return bTheTestFlag;
+}
+
+bool ScAcceptChgDlg::InsertChildren(ScChangeActionMap* pActionMap, const weld::TreeIter& rParent)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ bool bTheTestFlag = true;
+
+ for( const auto& rChangeAction : *pActionMap )
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, false, true);
+
+ if (xEntry)
+ {
+ bTheTestFlag=false;
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+ pEntryData->bIsRejectable=false;
+ pEntryData->bIsAcceptable=false;
+ pEntryData->bDisabled=true;
+
+ if (rChangeAction.second->IsDialogParent())
+ Expand(pChanges, rChangeAction.second, *xEntry);
+ }
+ }
+ return bTheTestFlag;
+}
+
+bool ScAcceptChgDlg::InsertDeletedChildren(const ScChangeAction* pScChangeAction,
+ ScChangeActionMap* pActionMap, const weld::TreeIter& rParent)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ bool bTheTestFlag = true;
+ std::unique_ptr<weld::TreeIter> xEntry;
+
+ for( const auto& rChangeAction : *pActionMap )
+ {
+
+ if( pScChangeAction != rChangeAction.second )
+ xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, false, true);
+ else
+ xEntry = AppendChangeAction(rChangeAction.second, false, &rParent, true, true);
+
+ if (xEntry)
+ {
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+ pEntryData->bIsRejectable=false;
+ pEntryData->bIsAcceptable=false;
+ pEntryData->bDisabled=true;
+
+ bTheTestFlag=false;
+
+ if (rChangeAction.second->IsDialogParent())
+ Expand(pChanges, rChangeAction.second, *xEntry);
+ }
+ }
+ return bTheTestFlag;
+}
+
+bool ScAcceptChgDlg::Expand(const ScChangeTrack* pChanges, const ScChangeAction* pScChangeAction,
+ const weld::TreeIter& rEntry, bool bFilter)
+{
+ bool bTheTestFlag = true;
+
+ if (pChanges && pScChangeAction)
+ {
+ ScChangeActionMap aActionMap;
+
+ GetDependents(pScChangeAction, aActionMap, rEntry);
+
+ switch(pScChangeAction->GetType())
+ {
+ case SC_CAT_CONTENT:
+ {
+ InsertContentChildren(&aActionMap, rEntry);
+ bTheTestFlag=!bHasFilterEntry;
+ break;
+ }
+ case SC_CAT_DELETE_COLS:
+ case SC_CAT_DELETE_ROWS:
+ case SC_CAT_DELETE_TABS:
+ {
+ InsertDeletedChildren(pScChangeAction, &aActionMap, rEntry);
+ bTheTestFlag=!bHasFilterEntry;
+ break;
+ }
+ default:
+ {
+ if(!bFilter)
+ bTheTestFlag = InsertChildren(&aActionMap, rEntry);
+ break;
+ }
+ }
+ aActionMap.clear();
+ }
+ return bTheTestFlag;
+}
+
+IMPL_LINK(ScAcceptChgDlg, ExpandingHandle, const weld::TreeIter&, rEntry, bool)
+{
+ ScChangeTrack* pChanges=pDoc->GetChangeTrack();
+ if (pChanges)
+ {
+ m_xDialog->set_busy_cursor(true);
+ ScChangeActionMap aActionMap;
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
+ if (!rTreeView.iter_has_child(rEntry))
+ {
+ bool bTheTestFlag = true;
+
+ if (pEntryData)
+ {
+ ScChangeAction* pScChangeAction=static_cast<ScChangeAction*>(pEntryData->pData);
+
+ GetDependents(pScChangeAction, aActionMap, rEntry);
+
+ switch (pScChangeAction->GetType())
+ {
+ case SC_CAT_CONTENT:
+ {
+ bTheTestFlag = InsertContentChildren( &aActionMap, rEntry );
+ break;
+ }
+ case SC_CAT_DELETE_COLS:
+ case SC_CAT_DELETE_ROWS:
+ case SC_CAT_DELETE_TABS:
+ {
+ bTheTestFlag = InsertDeletedChildren( pScChangeAction, &aActionMap, rEntry );
+ break;
+ }
+ default:
+ {
+ bTheTestFlag = InsertChildren( &aActionMap, rEntry );
+ break;
+ }
+ }
+ aActionMap.clear();
+
+ }
+ else
+ {
+ bTheTestFlag = InsertAcceptedORejected(rEntry);
+ }
+ if (bTheTestFlag)
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ rTreeView.insert(&rEntry, -1, &aStrNoEntry, nullptr, nullptr, nullptr, false, xEntry.get());
+ rTreeView.set_font_color(*xEntry, COL_GRAY);
+ }
+ }
+ m_xDialog->set_busy_cursor(false);
+ }
+ return true;
+}
+
+void ScAcceptChgDlg::AppendChanges(const ScChangeTrack* pChanges,sal_uLong nStartAction,
+ sal_uLong nEndAction)
+{
+ if(pChanges==nullptr)
+ return;
+
+ std::unique_ptr<weld::TreeIter> xParent;
+ m_xDialog->set_busy_cursor(true);
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.freeze();
+
+ bool bTheFlag = false;
+
+ bool bFilterFlag = pTPFilter->IsDate() || pTPFilter->IsRange() ||
+ pTPFilter->IsAuthor() || pTPFilter->IsComment();
+
+ bUseColor = bFilterFlag;
+
+ for(sal_uLong i=nStartAction;i<=nEndAction;i++)
+ {
+ const ScChangeAction* pScChangeAction=pChanges->GetAction(i);
+ if(pScChangeAction==nullptr) continue;
+
+ switch (pScChangeAction->GetState())
+ {
+ case SC_CAS_VIRGIN:
+
+ if (pScChangeAction->IsDialogRoot())
+ {
+ bool bOnDemandChildren = !bFilterFlag && pScChangeAction->IsDialogParent();
+ if (pScChangeAction->IsDialogParent())
+ xParent = AppendChangeAction(pScChangeAction, bOnDemandChildren);
+ else
+ xParent = AppendFilteredAction(pScChangeAction, SC_CAS_VIRGIN, bOnDemandChildren);
+ }
+ else
+ xParent.reset();
+
+ bTheFlag=true;
+ break;
+
+ case SC_CAS_ACCEPTED:
+ xParent.reset();
+ nAcceptCount++;
+ break;
+
+ case SC_CAS_REJECTED:
+ xParent.reset();
+ nRejectCount++;
+ break;
+ }
+
+ if (xParent && pScChangeAction->IsDialogParent() && bFilterFlag)
+ {
+ bool bTestFlag = bHasFilterEntry;
+ bHasFilterEntry = false;
+ if (Expand(pChanges,pScChangeAction,*xParent,!bTestFlag)&&!bTestFlag)
+ rTreeView.remove(*xParent);
+ }
+ }
+
+ if( bTheFlag && (!pDoc->IsDocEditable() || pChanges->IsProtected()) )
+ bTheFlag=false;
+
+ pTPView->EnableAccept(bTheFlag);
+ pTPView->EnableAcceptAll(bTheFlag);
+ pTPView->EnableReject(bTheFlag);
+ pTPView->EnableRejectAll(bTheFlag);
+
+ rTreeView.thaw();
+ m_xDialog->set_busy_cursor(false);
+}
+
+void ScAcceptChgDlg::RemoveEntries(sal_uLong nStartAction,sal_uLong nEndAction)
+{
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+
+ ScRedlinData *pEntryData=nullptr;
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ if (rTreeView.get_cursor(xEntry.get()))
+ pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+
+ if (!rTreeView.get_iter_first(*xEntry))
+ return;
+
+ sal_uLong nAction=0;
+ if (pEntryData)
+ nAction=pEntryData->nActionNo;
+
+ if (nAction>=nStartAction && nAction<=nEndAction)
+ rTreeView.set_cursor(*xEntry);
+
+ std::vector<OUString> aIdsToRemove;
+
+ do
+ {
+ OUString sId(rTreeView.get_id(*xEntry));
+ pEntryData = weld::fromId<ScRedlinData*>(sId);
+ if (pEntryData)
+ {
+ nAction = pEntryData->nActionNo;
+ if (nStartAction <= nAction && nAction <= nEndAction)
+ {
+ aIdsToRemove.push_back(sId);
+ delete pEntryData;
+ }
+ }
+ }
+ while (rTreeView.iter_next(*xEntry));
+
+ rTreeView.freeze();
+
+ // MUST do it backwards, don't delete parents before children and GPF
+ for (auto it = aIdsToRemove.rbegin(); it != aIdsToRemove.rend(); ++it)
+ rTreeView.remove_id(*it);
+
+ rTreeView.thaw();
+}
+
+void ScAcceptChgDlg::UpdateEntries(const ScChangeTrack* pChgTrack, sal_uLong nStartAction,sal_uLong nEndAction)
+{
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.freeze();
+
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ std::unique_ptr<weld::TreeIter> xLastEntry(rTreeView.make_iterator());
+ std::unique_ptr<weld::TreeIter> xNextEntry(rTreeView.make_iterator());
+
+ bool bEntry = rTreeView.get_iter_first(*xEntry);
+ bool bLastEntry = false;
+
+ while (bEntry)
+ {
+ bool bRemove = false;
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+ if (pEntryData)
+ {
+ ScChangeAction* pScChangeAction=
+ static_cast<ScChangeAction*>(pEntryData->pData);
+
+ sal_uLong nAction=pScChangeAction->GetActionNumber();
+
+ if(nStartAction<=nAction && nAction<=nEndAction) bRemove=true;
+ }
+
+ bool bNextEntry;
+ if (bRemove)
+ {
+ rTreeView.remove(*xEntry);
+ delete pEntryData;
+
+ if (!bLastEntry)
+ bLastEntry = rTreeView.get_iter_first(*xLastEntry);
+ if (bLastEntry)
+ {
+ rTreeView.copy_iterator(*xLastEntry, *xNextEntry);
+ bNextEntry = rTreeView.iter_next(*xNextEntry);
+ if (!bNextEntry)
+ {
+ rTreeView.copy_iterator(*xLastEntry, *xNextEntry);
+ bLastEntry = false;
+ }
+ }
+ else
+ bNextEntry = false;
+ }
+ else
+ {
+ rTreeView.copy_iterator(*xEntry, *xLastEntry);
+ bLastEntry = true;
+
+ rTreeView.copy_iterator(*xEntry, *xNextEntry);
+ bNextEntry = rTreeView.iter_next(*xNextEntry);
+ }
+
+ rTreeView.copy_iterator(*xNextEntry, *xEntry);
+ bEntry = bNextEntry;
+ }
+
+ AppendChanges(pChgTrack,nStartAction,nEndAction);
+
+ rTreeView.thaw();
+}
+
+IMPL_LINK( ScAcceptChgDlg, ChgTrackModHdl, ScChangeTrack&, rChgTrack, void)
+{
+ ScChangeTrackMsgQueue& aMsgQueue= rChgTrack.GetMsgQueue();
+
+ sal_uLong nStartAction;
+ sal_uLong nEndAction;
+
+ for (const auto& rMsg : aMsgQueue)
+ {
+ nStartAction = rMsg.nStartAction;
+ nEndAction = rMsg.nEndAction;
+
+ if(!bIgnoreMsg)
+ {
+ bNoSelection=true;
+
+ switch(rMsg.eMsgType)
+ {
+ case ScChangeTrackMsgType::Append:
+ AppendChanges(&rChgTrack,nStartAction,nEndAction);
+ break;
+ case ScChangeTrackMsgType::Remove:
+ RemoveEntries(nStartAction,nEndAction);
+ break;
+ case ScChangeTrackMsgType::Parent:
+ case ScChangeTrackMsgType::Change: //bNeedsUpdate=true;
+ UpdateEntries(&rChgTrack,nStartAction,nEndAction);
+ break;
+ default: assert(false); break;
+ }
+ }
+ }
+
+ aMsgQueue.clear();
+}
+
+IMPL_LINK_NOARG(ScAcceptChgDlg, ReOpenTimerHdl, Timer *, void)
+{
+ ScSimpleRefDlgWrapper::SetAutoReOpen(true);
+ m_xAcceptChgCtr->ShowFilterPage();
+ RefHandle(nullptr);
+}
+
+IMPL_LINK_NOARG(ScAcceptChgDlg, UpdateSelectionHdl, Timer *, void)
+{
+ ScTabView* pTabView = pViewData->GetView();
+
+ bool bAcceptFlag = true;
+ bool bRejectFlag = true;
+
+ pTabView->DoneBlockMode(); // clears old marking
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ std::vector<const ScChangeAction*> aActions;
+ rTreeView.selected_foreach([&rTreeView, &bAcceptFlag, &bRejectFlag, &aActions](weld::TreeIter& rEntry){
+ ScRedlinData* pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rEntry));
+ if (pEntryData)
+ {
+ bRejectFlag &= pEntryData->bIsRejectable;
+ bAcceptFlag &= pEntryData->bIsAcceptable;
+
+ const ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
+ if( pScChangeAction && (pScChangeAction->GetType() != SC_CAT_DELETE_TABS) &&
+ (!pEntryData->bDisabled || pScChangeAction->IsVisible()) )
+ {
+ aActions.push_back(pScChangeAction);
+ }
+ }
+ else
+ {
+ bAcceptFlag = false;
+ bRejectFlag = false;
+ }
+ return false;
+ });
+
+ bool bContMark = false;
+ for (size_t i = 0, nCount = aActions.size(); i < nCount; ++i)
+ {
+ const ScBigRange& rBigRange = aActions[i]->GetBigRange();
+ if (rBigRange.IsValid(*pDoc) && m_xDialog->has_toplevel_focus())
+ {
+ bool bSetCursor = i == nCount - 1;
+ pTabView->MarkRange(rBigRange.MakeRange(*pDoc), bSetCursor, bContMark);
+ bContMark = true;
+ }
+ }
+
+ ScChangeTrack* pChanges = pDoc->GetChangeTrack();
+ bool bEnable = pDoc->IsDocEditable() && pChanges && !pChanges->IsProtected();
+ pTPView->EnableAccept( bAcceptFlag && bEnable );
+ pTPView->EnableReject( bRejectFlag && bEnable );
+}
+
+IMPL_LINK(ScAcceptChgDlg, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ bool bEntry = rTreeView.get_cursor(xEntry.get());
+ if (bEntry)
+ rTreeView.select(*xEntry);
+
+ int nSortedCol = rTreeView.get_sort_column();
+ for (sal_Int32 i = 0; i < 5; ++i)
+ m_xSortMenu->set_active("calcsort" + OString::number(i), i == nSortedCol);
+
+ m_xPopup->set_sensitive("calcedit", false);
+
+ if (pDoc->IsDocEditable() && bEntry)
+ {
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+ if (pEntryData)
+ {
+ ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
+ if (pScChangeAction && !rTreeView.get_iter_depth(*xEntry))
+ m_xPopup->set_sensitive("calcedit", true);
+ }
+ }
+
+ OString sCommand = m_xPopup->popup_at_rect(&rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
+
+ if (!sCommand.isEmpty())
+ {
+ if (sCommand == "calcedit")
+ {
+ if (bEntry)
+ {
+ ScRedlinData *pEntryData = weld::fromId<ScRedlinData*>(rTreeView.get_id(*xEntry));
+ if (pEntryData)
+ {
+ ScChangeAction* pScChangeAction = static_cast<ScChangeAction*>(pEntryData->pData);
+ pViewData->GetDocShell()->ExecuteChangeCommentDialog(pScChangeAction, m_xDialog.get(), false);
+ }
+ }
+ }
+ else
+ {
+ int nDialogCol = o3tl::toInt32(sCommand.subView(8));
+ pTheView->HeaderBarClick(nDialogCol);
+ }
+ }
+
+ return true;
+}
+
+namespace
+{
+ //at one point we were writing multiple AcceptChgDat strings,
+ //so strip all of them and keep the results of the last one
+ OUString lcl_StripAcceptChgDat(OUString &rExtraString)
+ {
+ OUString aStr;
+ while (true)
+ {
+ sal_Int32 nPos = rExtraString.indexOf("AcceptChgDat:");
+ if (nPos == -1)
+ break;
+ // Try to read the alignment string "ALIGN:(...)"; if it is missing
+ // we have an old version
+ sal_Int32 n1 = rExtraString.indexOf('(', nPos);
+ if ( n1 != -1 )
+ {
+ sal_Int32 n2 = rExtraString.indexOf(')', n1);
+ if ( n2 != -1 )
+ {
+ // cut out alignment string
+ aStr = rExtraString.copy(nPos, n2 - nPos + 1);
+ rExtraString = rExtraString.replaceAt(nPos, n2 - nPos + 1, u"");
+ aStr = aStr.copy( n1-nPos+1 );
+ }
+ }
+ }
+ return aStr;
+ }
+}
+
+void ScAcceptChgDlg::Initialize(SfxChildWinInfo* pInfo)
+{
+ OUString aStr;
+ if (pInfo && !pInfo->aExtraString.isEmpty())
+ aStr = lcl_StripAcceptChgDat(pInfo->aExtraString);
+
+ SfxModelessDialogController::Initialize(pInfo);
+
+ if (aStr.isEmpty())
+ return;
+
+ int nCount = aStr.toInt32();
+ if (nCount <= 2)
+ return;
+
+ std::vector<int> aEndPos;
+
+ for (int i = 0; i < nCount; ++i)
+ {
+ sal_Int32 n1 = aStr.indexOf(';');
+ aStr = aStr.copy( n1+1 );
+ aEndPos.push_back(aStr.toInt32());
+ }
+
+ std::vector<int> aWidths;
+ for (int i = 1; i < nCount; ++i)
+ aWidths.push_back(aEndPos[i] - aEndPos[i - 1]);
+
+ // turn column end points back to column widths, ignoring the small
+ // value used for the expander column
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ rTreeView.set_column_fixed_widths(aWidths);
+}
+
+void ScAcceptChgDlg::FillInfo(SfxChildWinInfo& rInfo) const
+{
+ SfxModelessDialogController::FillInfo(rInfo);
+ //remove any old one before adding a new one
+ lcl_StripAcceptChgDat(rInfo.aExtraString);
+ rInfo.aExtraString += "AcceptChgDat:(";
+
+ const int nTabCount = 5;
+
+ rInfo.aExtraString += OUString::number(nTabCount);
+ rInfo.aExtraString += ";";
+
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+ std::vector<int> aWidths;
+ // turn column widths back into column end points for compatibility
+ // with how they used to be stored, including a small value for the
+ // expander column
+ aWidths.push_back(rTreeView.get_checkbox_column_width());
+ for (int i = 0; i < nTabCount - 1; ++i)
+ aWidths.push_back(aWidths.back() + rTreeView.get_column_width(i));
+
+ for (auto a : aWidths)
+ {
+ rInfo.aExtraString += OUString::number(a);
+ rInfo.aExtraString += ";";
+ }
+ rInfo.aExtraString += ")";
+}
+
+#define CALC_DATE 3
+#define CALC_POS 1
+
+int ScAcceptChgDlg::ColCompareHdl(const weld::TreeIter& rLeft, const weld::TreeIter& rRight) const
+{
+ weld::TreeView& rTreeView = pTheView->GetWidget();
+
+ sal_Int32 nCompare = 0;
+ SCCOL nSortCol = rTreeView.get_sort_column();
+
+ if (CALC_DATE == nSortCol)
+ {
+ RedlinData *pLeftData = weld::fromId<RedlinData*>(rTreeView.get_id(rLeft));
+ RedlinData *pRightData = weld::fromId<RedlinData*>(rTreeView.get_id(rRight));
+ if (pLeftData && pRightData)
+ {
+ if(pLeftData->aDateTime < pRightData->aDateTime)
+ nCompare = -1;
+ else if(pLeftData->aDateTime > pRightData->aDateTime)
+ nCompare = 1;
+ return nCompare;
+ }
+ }
+ else if (CALC_POS == nSortCol)
+ {
+ ScRedlinData *pLeftData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rLeft));
+ ScRedlinData *pRightData = weld::fromId<ScRedlinData*>(rTreeView.get_id(rRight));
+ if (pLeftData && pRightData)
+ {
+ nCompare = 1;
+
+ if(pLeftData->nTable < pRightData->nTable)
+ nCompare = -1;
+ else if(pLeftData->nTable == pRightData->nTable)
+ {
+ if(pLeftData->nRow < pRightData->nRow)
+ nCompare = -1;
+ else if(pLeftData->nRow == pRightData->nRow)
+ {
+ if(pLeftData->nCol < pRightData->nCol)
+ nCompare = -1;
+ else if(pLeftData->nCol == pRightData->nCol)
+ nCompare = 0;
+ }
+ }
+
+ return nCompare;
+ }
+ }
+
+ return ScGlobal::GetCaseCollator().compareString(rTreeView.get_text(rLeft, nSortCol),
+ rTreeView.get_text(rRight, nSortCol));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/anyrefdg.cxx b/sc/source/ui/miscdlgs/anyrefdg.cxx
new file mode 100644
index 000000000..0ffad93cf
--- /dev/null
+++ b/sc/source/ui/miscdlgs/anyrefdg.cxx
@@ -0,0 +1,784 @@
+/* -*- 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 <rangelst.hxx>
+#include <comphelper/string.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+#include <anyrefdg.hxx>
+#include <sc.hrc>
+#include <inputhdl.hxx>
+#include <scmod.hxx>
+#include <inputwin.hxx>
+#include <tabvwsh.hxx>
+#include <docsh.hxx>
+#include <rfindlst.hxx>
+#include <compiler.hxx>
+#include <inputopt.hxx>
+#include <rangeutl.hxx>
+#include <tokenarray.hxx>
+#include <comphelper/lok.hxx>
+#include <output.hxx>
+
+#include <memory>
+
+ScFormulaReferenceHelper::ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindings* _pBindings)
+ : m_pDlg(_pDlg)
+ , m_pRefEdit (nullptr)
+ , m_pRefBtn (nullptr)
+ , m_pDialog(nullptr)
+ , m_pBindings(_pBindings)
+ , m_nRefTab(0)
+ , m_bHighlightRef(false)
+{
+ ScInputOptions aInputOption=SC_MOD()->GetInputOptions();
+ m_bEnableColorRef=aInputOption.GetRangeFinder();
+}
+
+ScFormulaReferenceHelper::~ScFormulaReferenceHelper() COVERITY_NOEXCEPT_FALSE
+{
+ dispose();
+}
+
+void ScFormulaReferenceHelper::dispose()
+{
+ // common cleanup for ScAnyRefDlg and ScFormulaDlg is done here
+ HideReference();
+ enableInput( true );
+
+ ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
+ if ( pInputHdl )
+ pInputHdl->ResetDelayTimer(); // stop the timer for disabling the input line
+
+ m_pDialog = nullptr;
+}
+
+void ScFormulaReferenceHelper::enableInput( bool bEnable )
+{
+ ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
+ while( pDocShell )
+ {
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
+ while( pFrame )
+ {
+ // enable everything except InPlace, including bean frames
+ if ( !pFrame->GetFrame().IsInPlace() )
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
+ if(pViewSh!=nullptr)
+ {
+ vcl::Window *pWin=pViewSh->GetWindow();
+ if(pWin)
+ {
+ vcl::Window *pParent=pWin->GetParent();
+ if(pParent)
+ {
+ pParent->EnableInput(bEnable);
+ pViewSh->EnableRefInput(bEnable);
+ }
+ }
+ }
+ }
+ pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
+ }
+
+ pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
+ }
+}
+
+void ScFormulaReferenceHelper::ShowSimpleReference(std::u16string_view rStr)
+{
+ if (!m_bEnableColorRef)
+ return;
+
+ m_bHighlightRef = true;
+ ScViewData* pViewData=ScDocShell::GetViewData();
+ if ( !pViewData )
+ return;
+
+ ScDocument& rDoc = pViewData->GetDocument();
+ ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
+
+ ScRangeList aRangeList;
+
+ pTabViewShell->DoneRefMode();
+ pTabViewShell->ClearHighlightRanges();
+
+ if( ParseWithNames( aRangeList, rStr, rDoc ) )
+ {
+ for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
+ {
+ ScRange const & rRangeEntry = aRangeList[ i ];
+ Color aColName = ScRangeFindList::GetColorName( i );
+ pTabViewShell->AddHighlightRange( rRangeEntry, aColName );
+ }
+ }
+}
+
+bool ScFormulaReferenceHelper::ParseWithNames( ScRangeList& rRanges, std::u16string_view rStr, const ScDocument& rDoc )
+{
+ rRanges.RemoveAll();
+
+ if (rStr.empty())
+ return true;
+
+ ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
+
+ bool bError = false;
+ sal_Int32 nIdx {0};
+ do
+ {
+ ScRange aRange;
+ OUString aRangeStr( o3tl::getToken(rStr, 0, ';', nIdx ) );
+
+ ScRefFlags nFlags = aRange.ParseAny( aRangeStr, rDoc, aDetails );
+ if ( nFlags & ScRefFlags::VALID )
+ {
+ if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO )
+ aRange.aStart.SetTab( m_nRefTab );
+ if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO )
+ aRange.aEnd.SetTab( aRange.aStart.Tab() );
+ rRanges.push_back( aRange );
+ }
+ else if ( ScRangeUtil::MakeRangeFromName( aRangeStr, rDoc, m_nRefTab, aRange, RUTL_NAMES, aDetails ) )
+ rRanges.push_back( aRange );
+ else
+ bError = true;
+ }
+ while (nIdx>0);
+
+ return !bError;
+}
+
+void ScFormulaReferenceHelper::ShowFormulaReference(const OUString& rStr)
+{
+ if( !m_bEnableColorRef)
+ return;
+
+ m_bHighlightRef=true;
+ ScViewData* pViewData=ScDocShell::GetViewData();
+ if ( !(pViewData && m_pRefComp) )
+ return;
+
+ ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
+ SCCOL nCol = pViewData->GetCurX();
+ SCROW nRow = pViewData->GetCurY();
+ SCTAB nTab = pViewData->GetTabNo();
+ ScAddress aPos( nCol, nRow, nTab );
+
+ std::unique_ptr<ScTokenArray> pScTokA(m_pRefComp->CompileString(rStr));
+
+ if (!(pTabViewShell && pScTokA))
+ return;
+
+ const ScViewData& rViewData = pTabViewShell->GetViewData();
+ ScDocument& rDoc = rViewData.GetDocument();
+ pTabViewShell->DoneRefMode();
+ pTabViewShell->ClearHighlightRanges();
+
+ formula::FormulaTokenArrayPlainIterator aIter(*pScTokA);
+ const formula::FormulaToken* pToken = aIter.GetNextReference();
+
+ sal_uInt16 nIndex=0;
+
+ while(pToken!=nullptr)
+ {
+ bool bDoubleRef=(pToken->GetType()==formula::svDoubleRef);
+
+ if(pToken->GetType()==formula::svSingleRef || bDoubleRef)
+ {
+ ScRange aRange;
+ if(bDoubleRef)
+ {
+ ScComplexRefData aRef( *pToken->GetDoubleRef() );
+ aRange = aRef.toAbs(rDoc, aPos);
+ }
+ else
+ {
+ ScSingleRefData aRef( *pToken->GetSingleRef() );
+ aRange.aStart = aRef.toAbs(rDoc, aPos);
+ aRange.aEnd = aRange.aStart;
+ }
+ Color aColName=ScRangeFindList::GetColorName(nIndex++);
+ pTabViewShell->AddHighlightRange(aRange, aColName);
+ }
+
+ pToken = aIter.GetNextReference();
+ }
+}
+
+void ScFormulaReferenceHelper::HideReference( bool bDoneRefMode )
+{
+ ScViewData* pViewData=ScDocShell::GetViewData();
+
+ if( !(pViewData && m_bHighlightRef && m_bEnableColorRef))
+ return;
+
+ ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
+
+ if(pTabViewShell!=nullptr)
+ {
+ // bDoneRefMode is sal_False when called from before SetReference.
+ // In that case, RefMode was just started and must not be ended now.
+
+ if ( bDoneRefMode )
+ pTabViewShell->DoneRefMode();
+ pTabViewShell->ClearHighlightRanges();
+
+ if( comphelper::LibreOfficeKit::isActive() )
+ {
+ // Clear
+ std::vector<ReferenceMark> aReferenceMarks;
+ ScInputHandler::SendReferenceMarks( pTabViewShell, aReferenceMarks );
+ }
+ }
+ m_bHighlightRef=false;
+}
+
+void ScFormulaReferenceHelper::ShowReference(const OUString& rStr)
+{
+ if( !m_bEnableColorRef )
+ return;
+
+ if( rStr.indexOf('(') != -1 ||
+ rStr.indexOf('+') != -1 ||
+ rStr.indexOf('*') != -1 ||
+ rStr.indexOf('-') != -1 ||
+ rStr.indexOf('/') != -1 ||
+ rStr.indexOf('&') != -1 ||
+ rStr.indexOf('<') != -1 ||
+ rStr.indexOf('>') != -1 ||
+ rStr.indexOf('=') != -1 ||
+ rStr.indexOf('^') != -1 )
+ {
+ ShowFormulaReference(rStr);
+ }
+ else
+ {
+ ShowSimpleReference(rStr);
+ }
+}
+
+void ScFormulaReferenceHelper::ReleaseFocus( formula::RefEdit* pEdit )
+{
+ if( !m_pRefEdit && pEdit )
+ {
+ m_pDlg->RefInputStart( pEdit );
+ }
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if( !pViewShell )
+ return;
+
+ pViewShell->ActiveGrabFocus();
+ if( !m_pRefEdit )
+ return;
+
+ const ScViewData& rViewData = pViewShell->GetViewData();
+ ScDocument& rDoc = rViewData.GetDocument();
+ ScRangeList aRangeList;
+ if( !ParseWithNames( aRangeList, m_pRefEdit->GetText(), rDoc ) )
+ return;
+
+ if ( !aRangeList.empty() )
+ {
+ const ScRange & rRange = aRangeList.front();
+ pViewShell->SetTabNo( rRange.aStart.Tab() );
+ pViewShell->MoveCursorAbs( rRange.aStart.Col(),
+ rRange.aStart.Row(), SC_FOLLOW_JUMP, false, false );
+ pViewShell->MoveCursorAbs( rRange.aEnd.Col(),
+ rRange.aEnd.Row(), SC_FOLLOW_JUMP, true, false );
+ m_pDlg->SetReference( rRange, rDoc );
+ }
+}
+
+void ScFormulaReferenceHelper::Init()
+{
+ ScViewData* pViewData=ScDocShell::GetViewData(); //! use pScViewShell?
+ if ( !pViewData )
+ return;
+
+ ScDocument& rDoc = pViewData->GetDocument();
+ SCCOL nCol = pViewData->GetCurX();
+ SCROW nRow = pViewData->GetCurY();
+ SCTAB nTab = pViewData->GetTabNo();
+ ScAddress aCursorPos( nCol, nRow, nTab );
+
+ m_pRefComp.reset( new ScCompiler( rDoc, aCursorPos, rDoc.GetGrammar()) );
+ m_pRefComp->EnableJumpCommandReorder(false);
+ m_pRefComp->EnableStopOnError(false);
+
+ m_nRefTab = nTab;
+}
+
+IMPL_LINK_NOARG(ScFormulaReferenceHelper, ActivateHdl, weld::Widget&, bool)
+{
+ if (m_pRefEdit)
+ m_pRefEdit->GrabFocus();
+ m_pDlg->RefInputDone(true);
+ return true;
+}
+
+void ScFormulaReferenceHelper::RefInputDone( bool bForced )
+{
+ if ( !CanInputDone( bForced ) )
+ return;
+
+ if (!m_pDialog)
+ return;
+
+ // Adjust window title
+ m_pDialog->set_title(m_sOldDialogText);
+
+ if (m_pRefEdit)
+ m_pRefEdit->SetActivateHdl(Link<weld::Widget&, bool>());
+
+ // set button image
+ if (m_pRefBtn)
+ {
+ m_pRefBtn->SetActivateHdl(Link<weld::Widget&, bool>());
+ m_pRefBtn->SetStartImage();
+ }
+
+ m_pDialog->undo_collapse();
+
+ m_pRefEdit = nullptr;
+ m_pRefBtn = nullptr;
+}
+
+void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
+{
+ if (m_pRefEdit)
+ return;
+
+ m_pRefEdit = pEdit;
+ m_pRefBtn = pButton;
+
+ // Save and adjust window title
+ m_sOldDialogText = m_pDialog->get_title();
+ if (weld::Label *pLabel = m_pRefEdit->GetLabelWidgetForShrinkMode())
+ {
+ const OUString sLabel = pLabel->get_label();
+ if (!sLabel.isEmpty())
+ {
+ const OUString sNewDialogText = m_sOldDialogText + ": " + comphelper::string::stripEnd(sLabel, ':');
+ m_pDialog->set_title(pLabel->strip_mnemonic(sNewDialogText));
+ }
+ }
+
+ m_pDialog->collapse(pEdit->GetWidget(), pButton ? pButton->GetWidget() : nullptr);
+
+ // set button image
+ if (pButton)
+ pButton->SetEndImage();
+
+ m_pRefEdit->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl));
+ if (m_pRefBtn)
+ m_pRefBtn->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl));
+}
+
+void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
+{
+ if( !pEdit )
+ return;
+
+ if( m_pRefEdit == pEdit ) // is this the active ref edit field?
+ {
+ m_pRefEdit->GrabFocus(); // before RefInputDone()
+ m_pDlg->RefInputDone( true ); // finish ref input
+ }
+ else
+ {
+ m_pDlg->RefInputDone( true ); // another active ref edit?
+ m_pDlg->RefInputStart( pEdit, pButton ); // start ref input
+ // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg)
+ if( m_pRefEdit )
+ m_pRefEdit->GrabFocus();
+ }
+}
+
+void ScFormulaReferenceHelper::DoClose( sal_uInt16 nId )
+{
+ SfxApplication* pSfxApp = SfxGetpApp();
+
+ SetDispatcherLock( false ); //! here and in dtor ?
+
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && pViewFrm->HasChildWindow(FID_INPUTLINE_STATUS) )
+ {
+ // The input row is disabled with ToolBox::Disable disabled, thus it must be
+ // reenabled with ToolBox::Enable (before the AppWindow is enabled)
+ // for the buttons to be drawn as enabled.
+ SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_INPUTLINE_STATUS);
+ if (pChild)
+ {
+ ScInputWindow* pWin = static_cast<ScInputWindow*>(pChild->GetWindow());
+ pWin->Enable();
+ }
+ }
+
+ // find parent view frame to close dialog
+ SfxViewFrame* pMyViewFrm = nullptr;
+ if ( m_pBindings )
+ {
+ SfxDispatcher* pMyDisp = m_pBindings->GetDispatcher();
+ if (pMyDisp)
+ pMyViewFrm = pMyDisp->GetFrame();
+ }
+ SC_MOD()->SetRefDialog( nId, false, pMyViewFrm );
+
+ pSfxApp->Broadcast( SfxHint( SfxHintId::ScKillEditView ) );
+
+ ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
+ if ( pScViewShell )
+ pScViewShell->UpdateInputHandler(true);
+}
+
+void ScFormulaReferenceHelper::SetDispatcherLock( bool bLock )
+{
+ if (!comphelper::LibreOfficeKit::isActive())
+ {
+ // lock / unlock only the dispatchers of Calc documents
+ ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
+ while (pDocShell)
+ {
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDocShell);
+ while (pFrame)
+ {
+ SfxDispatcher* pDisp = pFrame->GetDispatcher();
+ if (pDisp)
+ pDisp->Lock(bLock);
+ pFrame = SfxViewFrame::GetNext(*pFrame, pDocShell);
+ }
+ pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
+ }
+ return;
+ // if a new view is created while the dialog is open,
+ // that view's dispatcher is locked when trying to create the dialog
+ // for that view (ScTabViewShell::CreateRefDialog)
+ }
+
+ // lock / unlock only the dispatcher of Calc document
+ SfxDispatcher* pDisp = nullptr;
+ if ( m_pBindings )
+ {
+ pDisp = m_pBindings->GetDispatcher();
+ }
+ else if(SfxViewFrame* pViewFrame = SfxViewFrame::Current())
+ {
+ if (dynamic_cast< ScTabViewShell* >(pViewFrame->GetViewShell()))
+ pDisp = pViewFrame->GetDispatcher();
+ }
+
+ if (pDisp)
+ pDisp->Lock(bLock);
+}
+
+void ScFormulaReferenceHelper::ViewShellChanged()
+{
+ enableInput( false );
+
+ EnableSpreadsheets();
+}
+void ScFormulaReferenceHelper::EnableSpreadsheets(bool bFlag)
+{
+ ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
+ while( pDocShell )
+ {
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
+ while( pFrame )
+ {
+ // enable everything except InPlace, including bean frames
+ if ( !pFrame->GetFrame().IsInPlace() )
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
+ if(pViewSh!=nullptr)
+ {
+ vcl::Window *pWin=pViewSh->GetWindow();
+ if(pWin)
+ {
+ vcl::Window *pParent=pWin->GetParent();
+ if(pParent)
+ {
+ pParent->EnableInput(bFlag,false);
+ pViewSh->EnableRefInput(bFlag);
+ }
+ }
+ }
+ }
+ pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
+ }
+
+ pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
+ }
+}
+
+static void lcl_InvalidateWindows()
+{
+ ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
+ while( pDocShell )
+ {
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
+ while( pFrame )
+ {
+ // enable everything except InPlace, including bean frames
+ if ( !pFrame->GetFrame().IsInPlace() )
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
+ if(pViewSh!=nullptr)
+ {
+ vcl::Window *pWin=pViewSh->GetWindow();
+ if(pWin)
+ {
+ vcl::Window *pParent=pWin->GetParent();
+ if(pParent)
+ pParent->Invalidate();
+ }
+ }
+ }
+ pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
+ }
+
+ pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
+ }
+}
+
+static void lcl_HideAllReferences()
+{
+ SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> );
+ while ( pSh )
+ {
+ static_cast<ScTabViewShell*>(pSh)->ClearHighlightRanges();
+ pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> );
+ }
+}
+
+ScRefHandler::ScRefHandler(SfxDialogController& rController, SfxBindings* pB, bool bBindRef)
+ : m_pController(&rController)
+ , m_bInRefMode(false)
+ , m_aHelper(this, pB)
+ , m_pMyBindings(pB)
+{
+ m_aHelper.SetDialog(rController.getDialog());
+
+ if( bBindRef ) EnterRefMode();
+}
+
+bool ScRefHandler::EnterRefMode()
+{
+ if( m_bInRefMode ) return false;
+
+ SC_MOD()->InputEnterHandler();
+
+ ScTabViewShell* pScViewShell = nullptr;
+
+ // title has to be from the view that opened the dialog,
+ // even if it's not the current view
+
+ SfxObjectShell* pParentDoc = nullptr;
+ if ( m_pMyBindings )
+ {
+ SfxDispatcher* pMyDisp = m_pMyBindings->GetDispatcher();
+ if (pMyDisp)
+ {
+ SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
+ if (pMyViewFrm)
+ {
+ pScViewShell = dynamic_cast<ScTabViewShell*>( pMyViewFrm->GetViewShell() );
+ if( pScViewShell )
+ pScViewShell->UpdateInputHandler(true);
+ pParentDoc = pMyViewFrm->GetObjectShell();
+ }
+ }
+ }
+ if ( !pParentDoc && pScViewShell ) // use current only if above fails
+ pParentDoc = pScViewShell->GetObjectShell();
+ if ( pParentDoc )
+ m_aDocName = pParentDoc->GetTitle();
+
+ ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(pScViewShell);
+
+ OSL_ENSURE( pInputHdl, "Missing input handler :-/" );
+
+ if ( pInputHdl )
+ pInputHdl->NotifyChange( nullptr );
+
+ ScFormulaReferenceHelper::enableInput( false );
+
+ ScFormulaReferenceHelper::EnableSpreadsheets();
+
+ m_aHelper.Init();
+
+ m_aHelper.SetDispatcherLock( true );
+
+ m_bInRefMode = true;
+ return m_bInRefMode;
+}
+
+ScRefHandler::~ScRefHandler() COVERITY_NOEXCEPT_FALSE
+{
+ disposeRefHandler();
+}
+
+void ScRefHandler::disposeRefHandler()
+{
+ m_pController = nullptr;
+ LeaveRefMode();
+ m_aHelper.dispose();
+}
+
+bool ScRefHandler::LeaveRefMode()
+{
+ if( !m_bInRefMode ) return false;
+
+ lcl_HideAllReferences();
+
+ SetDispatcherLock( false ); //! here and in DoClose ?
+
+ ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
+ if( pScViewShell )
+ pScViewShell->UpdateInputHandler(true);
+
+ lcl_InvalidateWindows();
+
+ m_bInRefMode = false;
+ return true;
+}
+
+void ScRefHandler::SwitchToDocument()
+{
+ ScTabViewShell* pCurrent = ScTabViewShell::GetActiveViewShell();
+ if (pCurrent)
+ {
+ SfxObjectShell* pObjSh = pCurrent->GetObjectShell();
+ if ( pObjSh && pObjSh->GetTitle() == m_aDocName )
+ {
+ // right document already visible -> nothing to do
+ return;
+ }
+ }
+
+ SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> );
+ while ( pSh )
+ {
+ SfxObjectShell* pObjSh = pSh->GetObjectShell();
+ if ( pObjSh && pObjSh->GetTitle() == m_aDocName )
+ {
+ // switch to first TabViewShell for document
+ static_cast<ScTabViewShell*>(pSh)->SetActive();
+ return;
+ }
+ pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> );
+ }
+}
+
+bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const // pDocSh may be 0
+{
+ // if aDocName isn't initialized, allow
+ if ( m_aDocName.isEmpty() )
+ return true;
+
+ if ( !pDocSh )
+ return false;
+
+ // default: allow only same document (overridden in function dialog)
+ return m_aDocName==pDocSh->GetTitle();
+}
+
+bool ScRefHandler::IsRefInputMode() const
+{
+ return m_pController->getDialog()->get_visible();
+}
+
+bool ScRefHandler::DoClose( sal_uInt16 nId )
+{
+ m_aHelper.DoClose(nId);
+ return true;
+}
+
+void ScRefHandler::SetDispatcherLock( bool bLock )
+{
+ m_aHelper.SetDispatcherLock( bLock );
+}
+
+void ScRefHandler::ViewShellChanged()
+{
+ ScFormulaReferenceHelper::ViewShellChanged();
+}
+
+void ScRefHandler::AddRefEntry()
+{
+ // override this for multi-references
+}
+
+bool ScRefHandler::IsTableLocked() const
+{
+ // the default is that the sheet can be switched during while the reference is edited
+
+ return false;
+}
+
+// RefInputStart/Done: Zoom-In (AutoHide) on single field
+// (using button or movement)
+
+void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
+{
+ m_aHelper.RefInputStart( pEdit, pButton );
+}
+
+void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
+{
+ m_aHelper.ToggleCollapsed( pEdit, pButton );
+}
+
+bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, std::u16string_view rStr, const ScDocument& rDoc )
+{
+ return m_aHelper.ParseWithNames( rRanges, rStr, rDoc );
+}
+
+void ScRefHandler::HideReference( bool bDoneRefMode )
+{
+ m_aHelper.HideReference( bDoneRefMode );
+}
+
+void ScRefHandler::ShowReference(const OUString& rStr)
+{
+ m_aHelper.ShowReference(rStr);
+}
+
+void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit )
+{
+ m_aHelper.ReleaseFocus( pEdit );
+}
+
+void ScRefHandler::RefInputDone( bool bForced )
+{
+ m_aHelper.RefInputDone( bForced );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/autofmt.cxx b/sc/source/ui/miscdlgs/autofmt.cxx
new file mode 100644
index 000000000..877c412a5
--- /dev/null
+++ b/sc/source/ui/miscdlgs/autofmt.cxx
@@ -0,0 +1,531 @@
+/* -*- 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 <scitems.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/justifyitem.hxx>
+#include <editeng/lineitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <o3tl/unit_conversion.hxx>
+#include <osl/diagnose.h>
+#include <svl/numformat.hxx>
+#include <svtools/scriptedtext.hxx>
+#include <svx/framelink.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <comphelper/processfactory.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+
+#include <strings.hrc>
+#include <zforauto.hxx>
+#include <global.hxx>
+#include <autoform.hxx>
+#include <autofmt.hxx>
+#include <scresid.hxx>
+#include <document.hxx>
+#include <viewdata.hxx>
+#include <svtools/colorcfg.hxx>
+#include <scmod.hxx>
+
+#define FRAME_OFFSET 4
+
+// ScAutoFmtPreview
+
+ScAutoFmtPreview::ScAutoFmtPreview()
+ : pCurData(nullptr)
+ , bFitWidth(false)
+ , mbRTL(false)
+ , aStrJan(ScResId(STR_JAN))
+ , aStrFeb(ScResId(STR_FEB))
+ , aStrMar(ScResId(STR_MAR))
+ , aStrNorth(ScResId(STR_NORTH))
+ , aStrMid(ScResId(STR_MID))
+ , aStrSouth(ScResId(STR_SOUTH))
+ , aStrSum(ScResId(STR_SUM))
+ , pNumFmt(new SvNumberFormatter(::comphelper::getProcessComponentContext(), ScGlobal::eLnge))
+{
+ Init();
+}
+
+void ScAutoFmtPreview::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ aVD.disposeAndReset(VclPtr<VirtualDevice>::Create(pDrawingArea->get_ref_device()));
+ CustomWidgetController::SetDrawingArea(pDrawingArea);
+}
+
+void ScAutoFmtPreview::Resize()
+{
+ Size aSize(GetOutputSizePixel());
+ aPrvSize = Size(aSize.Width() - 6, aSize.Height() - 30);
+ mnLabelColWidth = (aPrvSize.Width() - 4) / 4 - 12;
+ mnDataColWidth1 = (aPrvSize.Width() - 4 - 2 * mnLabelColWidth) / 3;
+ mnDataColWidth2 = (aPrvSize.Width() - 4 - 2 * mnLabelColWidth) / 4;
+ mnRowHeight = (aPrvSize.Height() - 4) / 5;
+ NotifyChange(pCurData);
+}
+
+ScAutoFmtPreview::~ScAutoFmtPreview()
+{
+}
+
+static void lcl_SetFontProperties(
+ vcl::Font& rFont,
+ const SvxFontItem& rFontItem,
+ const SvxWeightItem& rWeightItem,
+ const SvxPostureItem& rPostureItem )
+{
+ rFont.SetFamily ( rFontItem.GetFamily() );
+ rFont.SetFamilyName ( rFontItem.GetFamilyName() );
+ rFont.SetStyleName ( rFontItem.GetStyleName() );
+ rFont.SetCharSet ( rFontItem.GetCharSet() );
+ rFont.SetPitch ( rFontItem.GetPitch() );
+ rFont.SetWeight ( rWeightItem.GetValue() );
+ rFont.SetItalic ( rPostureItem.GetValue() );
+}
+
+void ScAutoFmtPreview::MakeFonts(vcl::RenderContext const& rRenderContext, sal_uInt16 nIndex, vcl::Font& rFont, vcl::Font& rCJKFont, vcl::Font& rCTLFont)
+{
+ if ( !pCurData )
+ return;
+
+ rFont = rCJKFont = rCTLFont = rRenderContext.GetFont();
+ Size aFontSize(rFont.GetFontSize().Width(), 10 * rRenderContext.GetDPIScaleFactor());
+
+ const SvxFontItem* pFontItem = pCurData->GetItem( nIndex, ATTR_FONT );
+ const SvxWeightItem* pWeightItem = pCurData->GetItem( nIndex, ATTR_FONT_WEIGHT );
+ const SvxPostureItem* pPostureItem = pCurData->GetItem( nIndex, ATTR_FONT_POSTURE );
+ const SvxFontItem* pCJKFontItem = pCurData->GetItem( nIndex, ATTR_CJK_FONT );
+ const SvxWeightItem* pCJKWeightItem = pCurData->GetItem( nIndex, ATTR_CJK_FONT_WEIGHT );
+ const SvxPostureItem* pCJKPostureItem = pCurData->GetItem( nIndex, ATTR_CJK_FONT_POSTURE );
+ const SvxFontItem* pCTLFontItem = pCurData->GetItem( nIndex, ATTR_CTL_FONT );
+ const SvxWeightItem* pCTLWeightItem = pCurData->GetItem( nIndex, ATTR_CTL_FONT_WEIGHT );
+ const SvxPostureItem* pCTLPostureItem = pCurData->GetItem( nIndex, ATTR_CTL_FONT_POSTURE );
+ const SvxUnderlineItem* pUnderlineItem = pCurData->GetItem( nIndex, ATTR_FONT_UNDERLINE );
+ const SvxOverlineItem* pOverlineItem = pCurData->GetItem( nIndex, ATTR_FONT_OVERLINE );
+ const SvxCrossedOutItem* pCrossedOutItem = pCurData->GetItem( nIndex, ATTR_FONT_CROSSEDOUT );
+ const SvxContourItem* pContourItem = pCurData->GetItem( nIndex, ATTR_FONT_CONTOUR );
+ const SvxShadowedItem* pShadowedItem = pCurData->GetItem( nIndex, ATTR_FONT_SHADOWED );
+ const SvxColorItem* pColorItem = pCurData->GetItem( nIndex, ATTR_FONT_COLOR );
+
+ lcl_SetFontProperties( rFont, *pFontItem, *pWeightItem, *pPostureItem );
+ lcl_SetFontProperties( rCJKFont, *pCJKFontItem, *pCJKWeightItem, *pCJKPostureItem );
+ lcl_SetFontProperties( rCTLFont, *pCTLFontItem, *pCTLWeightItem, *pCTLPostureItem );
+
+ Color aColor( pColorItem->GetValue() );
+ if( aColor == COL_TRANSPARENT )
+ aColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor();
+
+#define SETONALLFONTS( MethodName, Value ) \
+rFont.MethodName( Value ); rCJKFont.MethodName( Value ); rCTLFont.MethodName( Value );
+
+ SETONALLFONTS( SetUnderline, pUnderlineItem->GetValue() )
+ SETONALLFONTS( SetOverline, pOverlineItem->GetValue() )
+ SETONALLFONTS( SetStrikeout, pCrossedOutItem->GetValue() )
+ SETONALLFONTS( SetOutline, pContourItem->GetValue() )
+ SETONALLFONTS( SetShadow, pShadowedItem->GetValue() )
+ SETONALLFONTS( SetColor, aColor )
+ SETONALLFONTS( SetFontSize, aFontSize )
+ SETONALLFONTS( SetTransparent, true )
+
+#undef SETONALLFONTS
+}
+
+sal_uInt16 ScAutoFmtPreview::GetFormatIndex( size_t nCol, size_t nRow ) const
+{
+ static const sal_uInt16 pnFmtMap[] =
+ {
+ 0, 1, 2, 1, 3,
+ 4, 5, 6, 5, 7,
+ 8, 9, 10, 9, 11,
+ 4, 5, 6, 5, 7,
+ 12, 13, 14, 13, 15
+ };
+ return pnFmtMap[ maArray.GetCellIndex( nCol, nRow, mbRTL ) ];
+}
+
+const SvxBoxItem& ScAutoFmtPreview::GetBoxItem( size_t nCol, size_t nRow ) const
+{
+ OSL_ENSURE( pCurData, "ScAutoFmtPreview::GetBoxItem - no format data found" );
+ return * pCurData->GetItem( GetFormatIndex( nCol, nRow ), ATTR_BORDER );
+}
+
+const SvxLineItem& ScAutoFmtPreview::GetDiagItem( size_t nCol, size_t nRow, bool bTLBR ) const
+{
+ OSL_ENSURE( pCurData, "ScAutoFmtPreview::GetDiagItem - no format data found" );
+ return * pCurData->GetItem( GetFormatIndex( nCol, nRow ), bTLBR ? ATTR_BORDER_TLBR : ATTR_BORDER_BLTR );
+}
+
+void ScAutoFmtPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCol, size_t nRow)
+{
+ if (!pCurData)
+ {
+ return;
+ }
+
+ // Emit the cell text
+
+ OUString cellString;
+ bool bNumFormat = pCurData->GetIncludeValueFormat();
+ sal_uInt32 nNum;
+ double nVal;
+ const Color* pDummy = nullptr;
+ sal_uInt16 nIndex = static_cast<sal_uInt16>(maArray.GetCellIndex(nCol, nRow, mbRTL));
+
+ switch (nIndex)
+ {
+ case 1: cellString = aStrJan; break;
+ case 2: cellString = aStrFeb; break;
+ case 3: cellString = aStrMar; break;
+ case 5: cellString = aStrNorth; break;
+ case 10: cellString = aStrMid; break;
+ case 15: cellString = aStrSouth; break;
+ case 4:
+ case 20: cellString = aStrSum; break;
+
+ case 6:
+ case 8:
+ case 16:
+ case 18: nVal = nIndex;
+ nNum = 5;
+ goto mknum;
+ case 17:
+ case 7: nVal = nIndex;
+ nNum = 6;
+ goto mknum;
+ case 11:
+ case 12:
+ case 13: nVal = nIndex;
+ nNum = 12 == nIndex ? 10 : 9;
+ goto mknum;
+
+ case 9: nVal = 21; nNum = 7; goto mknum;
+ case 14: nVal = 36; nNum = 11; goto mknum;
+ case 19: nVal = 51; nNum = 7; goto mknum;
+ case 21: nVal = 33; nNum = 13; goto mknum;
+ case 22: nVal = 36; nNum = 14; goto mknum;
+ case 23: nVal = 39; nNum = 13; goto mknum;
+ case 24: nVal = 108; nNum = 15;
+ mknum:
+ if (bNumFormat)
+ {
+ ScNumFormatAbbrev& rNumFormat = const_cast<ScNumFormatAbbrev&>(pCurData->GetNumFormat(sal_uInt16(nNum)));
+ nNum = rNumFormat.GetFormatIndex(*pNumFmt);
+ }
+ else
+ nNum = 0;
+ pNumFmt->GetOutputString(nVal, nNum, cellString, &pDummy);
+ break;
+ }
+
+ if (cellString.isEmpty())
+ return;
+
+ Size aStrSize;
+ sal_uInt16 nFmtIndex = GetFormatIndex( nCol, nRow );
+ const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow ));
+ Point aPos(basegfx::fround(cellRange.getMinX()), basegfx::fround(cellRange.getMinY()));
+ sal_uInt16 nRightX = 0;
+ bool bJustify = pCurData->GetIncludeJustify();
+ SvxCellHorJustify eJustification;
+
+ SvtScriptedTextHelper aScriptedText(rRenderContext);
+
+ // Justification:
+
+ eJustification = mbRTL ? SvxCellHorJustify::Right : bJustify ?
+ pCurData->GetItem(nFmtIndex, ATTR_HOR_JUSTIFY)->GetValue() :
+ SvxCellHorJustify::Standard;
+
+ if (pCurData->GetIncludeFont())
+ {
+ vcl::Font aFont, aCJKFont, aCTLFont;
+ Size theMaxStrSize;
+
+ MakeFonts(rRenderContext, nFmtIndex, aFont, aCJKFont, aCTLFont);
+
+ theMaxStrSize = Size(basegfx::fround(cellRange.getWidth()), basegfx::fround(cellRange.getHeight()));
+ theMaxStrSize.AdjustWidth( -(FRAME_OFFSET) );
+ theMaxStrSize.AdjustHeight( -(FRAME_OFFSET) );
+
+ aScriptedText.SetFonts( &aFont, &aCJKFont, &aCTLFont );
+ aScriptedText.SetText(cellString, xBreakIter);
+ aStrSize = aScriptedText.GetTextSize();
+
+ if (theMaxStrSize.Height() < aStrSize.Height())
+ {
+ // if the string does not fit in the row using this font,
+ // the default font is used
+ aScriptedText.SetDefaultFont();
+ aStrSize = aScriptedText.GetTextSize();
+ }
+ while((theMaxStrSize.Width() <= aStrSize.Width()) && (cellString.getLength() > 1))
+ {
+ if( eJustification == SvxCellHorJustify::Right )
+ cellString = cellString.copy(1);
+ else
+ cellString = cellString.copy(0, cellString.getLength() - 1 );
+
+ aScriptedText.SetText( cellString, xBreakIter );
+ aStrSize = aScriptedText.GetTextSize();
+ }
+ }
+ else
+ {
+ aScriptedText.SetDefaultFont();
+ aScriptedText.SetText( cellString, xBreakIter );
+ aStrSize = aScriptedText.GetTextSize();
+ }
+
+ nRightX = sal_uInt16(basegfx::fround(cellRange.getWidth()) - aStrSize.Width() - FRAME_OFFSET);
+
+ // vertical (always center):
+
+ aPos.AdjustY((mnRowHeight - static_cast<sal_uInt16>(aStrSize.Height())) / 2 );
+
+ // horizontal
+
+ if (eJustification != SvxCellHorJustify::Standard)
+ {
+ sal_uInt16 nHorPos = sal_uInt16((basegfx::fround(cellRange.getWidth())-aStrSize.Width()) / 2);
+ //sal_uInt16 nHorPos = sal_uInt16((basegfx::fround(cellRange.getWidth())-aStrSize.Width()) / 2);
+
+ switch (eJustification)
+ {
+ case SvxCellHorJustify::Left:
+ aPos.AdjustX(FRAME_OFFSET );
+ break;
+ case SvxCellHorJustify::Right:
+ aPos.AdjustX(nRightX );
+ break;
+ case SvxCellHorJustify::Block:
+ case SvxCellHorJustify::Repeat:
+ case SvxCellHorJustify::Center:
+ aPos.AdjustX(nHorPos );
+ break;
+ // coverity[dead_error_line] - following conditions exist to avoid compiler warning
+ case SvxCellHorJustify::Standard:
+ default:
+ // Standard is not handled here
+ break;
+ }
+ }
+ else
+ {
+
+ // Standard justification
+
+ if (nCol == 0 || nRow == 0)
+ {
+ // Text label to the left or sum left adjusted
+ aPos.AdjustX(FRAME_OFFSET );
+ }
+ else
+ {
+ // Numbers/Dates right adjusted
+ aPos.AdjustX(nRightX );
+ }
+ }
+ aScriptedText.DrawText(aPos);
+}
+
+#undef FRAME_OFFSET
+
+void ScAutoFmtPreview::DrawBackground(vcl::RenderContext& rRenderContext)
+{
+ if (!pCurData)
+ return;
+
+ for(size_t nRow = 0; nRow < 5; ++nRow)
+ {
+ for(size_t nCol = 0; nCol < 5; ++nCol)
+ {
+ const SvxBrushItem* pItem =
+ pCurData->GetItem( GetFormatIndex( nCol, nRow ), ATTR_BACKGROUND );
+
+ rRenderContext.Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor( pItem->GetColor() );
+
+ const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+ rRenderContext.DrawRect(
+ tools::Rectangle(
+ basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
+ basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY())));
+
+ rRenderContext.Pop();
+ }
+ }
+}
+
+void ScAutoFmtPreview::PaintCells(vcl::RenderContext& rRenderContext)
+{
+ if (!pCurData)
+ return;
+
+ // 1) background
+ if (pCurData->GetIncludeBackground())
+ DrawBackground(rRenderContext);
+
+ // 2) values
+ for(size_t nRow = 0; nRow < 5; ++nRow)
+ for(size_t nCol = 0; nCol < 5; ++nCol)
+ DrawString(rRenderContext, nCol, nRow);
+
+ // 3) border
+ if (!pCurData->GetIncludeFrame())
+ return;
+
+ const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
+ drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
+ rRenderContext,
+ aNewViewInformation2D));
+
+ pProcessor2D->process(maArray.CreateB2DPrimitiveArray());
+ pProcessor2D.reset();
+}
+
+void ScAutoFmtPreview::Init()
+{
+ maArray.Initialize( 5, 5 );
+ mnLabelColWidth = 0;
+ mnDataColWidth1 = 0;
+ mnDataColWidth2 = 0;
+ mnRowHeight = 0;
+ CalcCellArray( false );
+ CalcLineMap();
+}
+
+void ScAutoFmtPreview::DetectRTL(const ScViewData& rViewData)
+{
+ SCTAB nCurrentTab = rViewData.GetTabNo();
+ ScDocument& rDoc = rViewData.GetDocument();
+ mbRTL = rDoc.IsLayoutRTL(nCurrentTab);
+ xBreakIter = rDoc.GetBreakIterator();
+}
+
+void ScAutoFmtPreview::CalcCellArray( bool bFitWidthP )
+{
+ maArray.SetXOffset( 2 );
+ maArray.SetAllColWidths( bFitWidthP ? mnDataColWidth2 : mnDataColWidth1 );
+ maArray.SetColWidth( 0, mnLabelColWidth );
+ maArray.SetColWidth( 4, mnLabelColWidth );
+
+ maArray.SetYOffset( 2 );
+ maArray.SetAllRowHeights( mnRowHeight );
+
+ aPrvSize.setWidth( maArray.GetWidth() + 4 );
+ aPrvSize.setHeight( maArray.GetHeight() + 4 );
+}
+
+static void lclSetStyleFromBorder( svx::frame::Style& rStyle, const ::editeng::SvxBorderLine* pBorder )
+{
+ rStyle.Set(pBorder, o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::pt), 5);
+}
+
+void ScAutoFmtPreview::CalcLineMap()
+{
+ if ( !pCurData )
+ return;
+
+ for( size_t nRow = 0; nRow < 5; ++nRow )
+ {
+ for( size_t nCol = 0; nCol < 5; ++nCol )
+ {
+ svx::frame::Style aStyle;
+
+ const SvxBoxItem& rItem = GetBoxItem( nCol, nRow );
+ lclSetStyleFromBorder( aStyle, rItem.GetLeft() );
+ maArray.SetCellStyleLeft( nCol, nRow, aStyle );
+ lclSetStyleFromBorder( aStyle, rItem.GetRight() );
+ maArray.SetCellStyleRight( nCol, nRow, aStyle );
+ lclSetStyleFromBorder( aStyle, rItem.GetTop() );
+ maArray.SetCellStyleTop( nCol, nRow, aStyle );
+ lclSetStyleFromBorder( aStyle, rItem.GetBottom() );
+ maArray.SetCellStyleBottom( nCol, nRow, aStyle );
+
+ lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, true ).GetLine() );
+ maArray.SetCellStyleTLBR( nCol, nRow, aStyle );
+ lclSetStyleFromBorder( aStyle, GetDiagItem( nCol, nRow, false ).GetLine() );
+ maArray.SetCellStyleBLTR( nCol, nRow, aStyle );
+ }
+ }
+}
+
+void ScAutoFmtPreview::NotifyChange( ScAutoFormatData* pNewData )
+{
+ if (pNewData)
+ {
+ pCurData = pNewData;
+ bFitWidth = pNewData->GetIncludeWidthHeight();
+ }
+
+ CalcCellArray( bFitWidth );
+ CalcLineMap();
+
+ Invalidate();
+}
+
+void ScAutoFmtPreview::DoPaint(vcl::RenderContext& rRenderContext)
+{
+ rRenderContext.Push(vcl::PushFlags::ALL);
+ DrawModeFlags nOldDrawMode = aVD->GetDrawMode();
+
+ Size aWndSize(GetOutputSizePixel());
+ vcl::Font aFont(aVD->GetFont());
+ const Color& aBackCol = SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
+ tools::Rectangle aRect(Point(), aWndSize);
+
+ aFont.SetTransparent( true );
+ aVD->SetFont(aFont);
+ aVD->SetLineColor();
+ aVD->SetFillColor(aBackCol);
+ aVD->SetOutputSize(aWndSize);
+ aVD->DrawRect(aRect);
+
+ PaintCells(*aVD);
+
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(aBackCol);
+ rRenderContext.DrawRect(aRect);
+
+ Point aPos((aWndSize.Width() - aPrvSize.Width()) / 2, (aWndSize.Height() - aPrvSize.Height()) / 2);
+ if (AllSettings::GetLayoutRTL())
+ aPos.setX( -aPos.X() );
+ rRenderContext.DrawOutDev(aPos, aWndSize, Point(), aWndSize, *aVD);
+ aVD->SetDrawMode(nOldDrawMode);
+ rRenderContext.Pop();
+}
+
+void ScAutoFmtPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
+{
+ DoPaint(rRenderContext);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/conflictsdlg.cxx b/sc/source/ui/miscdlgs/conflictsdlg.cxx
new file mode 100644
index 000000000..3a48325aa
--- /dev/null
+++ b/sc/source/ui/miscdlgs/conflictsdlg.cxx
@@ -0,0 +1,643 @@
+/* -*- 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 <comphelper/string.hxx>
+#include <osl/diagnose.h>
+
+#include <conflictsdlg.hxx>
+#include <o3tl/safeint.hxx>
+#include <strings.hrc>
+#include <scresid.hxx>
+#include <viewdata.hxx>
+#include <dbfunc.hxx>
+#include <chgtrack.hxx>
+
+// struct ScConflictsListEntry
+
+bool ScConflictsListEntry::HasSharedAction( sal_uLong nSharedAction ) const
+{
+ auto aEnd = maSharedActions.cend();
+ auto aItr = std::find(maSharedActions.cbegin(), aEnd, nSharedAction);
+
+ return aItr != aEnd;
+}
+
+bool ScConflictsListEntry::HasOwnAction( sal_uLong nOwnAction ) const
+{
+ auto aEnd = maOwnActions.cend();
+ auto aItr = std::find(maOwnActions.cbegin(), aEnd, nOwnAction);
+
+ return aItr != aEnd;
+}
+
+
+bool ScConflictsListHelper::HasOwnAction( ScConflictsList& rConflictsList, sal_uLong nOwnAction )
+{
+ return std::any_of(rConflictsList.begin(), rConflictsList.end(),
+ [nOwnAction](ScConflictsListEntry& rConflict) { return rConflict.HasOwnAction( nOwnAction ); });
+}
+
+ScConflictsListEntry* ScConflictsListHelper::GetSharedActionEntry( ScConflictsList& rConflictsList, sal_uLong nSharedAction )
+{
+ auto aEnd = rConflictsList.end();
+ auto aItr = std::find_if(rConflictsList.begin(), aEnd,
+ [nSharedAction](ScConflictsListEntry& rConflict) { return rConflict.HasSharedAction( nSharedAction ); });
+
+ if (aItr != aEnd)
+ return &(*aItr);
+
+ return nullptr;
+}
+
+ScConflictsListEntry* ScConflictsListHelper::GetOwnActionEntry( ScConflictsList& rConflictsList, sal_uLong nOwnAction )
+{
+ auto aEnd = rConflictsList.end();
+ auto aItr = std::find_if(rConflictsList.begin(), aEnd,
+ [nOwnAction](ScConflictsListEntry& rConflict) { return rConflict.HasOwnAction( nOwnAction ); });
+
+ if (aItr != aEnd)
+ return &(*aItr);
+
+ return nullptr;
+}
+
+void ScConflictsListHelper::Transform_Impl( std::vector<sal_uLong>& rActionList, ScChangeActionMergeMap* pMergeMap )
+{
+ if ( !pMergeMap )
+ {
+ return;
+ }
+
+ for ( auto aItr = rActionList.begin(); aItr != rActionList.end(); )
+ {
+ ScChangeActionMergeMap::iterator aItrMap = pMergeMap->find( *aItr );
+ if ( aItrMap != pMergeMap->end() )
+ {
+ *aItr = aItrMap->second;
+ ++aItr;
+ }
+ else
+ {
+ aItr = rActionList.erase( aItr );
+ OSL_FAIL( "ScConflictsListHelper::Transform_Impl: erased action from conflicts list!" );
+ }
+ }
+}
+
+void ScConflictsListHelper::TransformConflictsList( ScConflictsList& rConflictsList,
+ ScChangeActionMergeMap* pSharedMap, ScChangeActionMergeMap* pOwnMap )
+{
+ for ( auto& rConflictEntry : rConflictsList )
+ {
+ if ( pSharedMap )
+ {
+ ScConflictsListHelper::Transform_Impl( rConflictEntry.maSharedActions, pSharedMap );
+ }
+
+ if ( pOwnMap )
+ {
+ ScConflictsListHelper::Transform_Impl( rConflictEntry.maOwnActions, pOwnMap );
+ }
+ }
+}
+
+
+ScConflictsFinder::ScConflictsFinder( ScChangeTrack* pTrack, sal_uLong nStartShared, sal_uLong nEndShared,
+ sal_uLong nStartOwn, sal_uLong nEndOwn, ScConflictsList& rConflictsList )
+ :mpTrack( pTrack )
+ ,mnStartShared( nStartShared )
+ ,mnEndShared( nEndShared )
+ ,mnStartOwn( nStartOwn )
+ ,mnEndOwn( nEndOwn )
+ ,mrConflictsList( rConflictsList )
+{
+}
+
+bool ScConflictsFinder::DoActionsIntersect( const ScChangeAction* pAction1, const ScChangeAction* pAction2 )
+{
+ return pAction1 && pAction2 && pAction1->GetBigRange().Intersects( pAction2->GetBigRange() );
+}
+
+ScConflictsListEntry* ScConflictsFinder::GetIntersectingEntry( const ScChangeAction* pAction ) const
+{
+ auto doActionsIntersect = [this, pAction](const sal_uLong& aAction) { return DoActionsIntersect( mpTrack->GetAction( aAction ), pAction ); };
+
+ for ( auto& rConflict : mrConflictsList )
+ {
+ if (std::any_of( rConflict.maSharedActions.cbegin(), rConflict.maSharedActions.cend(), doActionsIntersect ))
+ return &rConflict;
+
+ if (std::any_of( rConflict.maOwnActions.cbegin(), rConflict.maOwnActions.cend(), doActionsIntersect ))
+ return &rConflict;
+ }
+
+ return nullptr;
+}
+
+ScConflictsListEntry& ScConflictsFinder::GetEntry( sal_uLong nSharedAction, const std::vector<sal_uLong>& rOwnActions )
+{
+ // try to get a list entry which already contains the shared action
+ ScConflictsListEntry* pEntry = ScConflictsListHelper::GetSharedActionEntry( mrConflictsList, nSharedAction );
+ if ( pEntry )
+ {
+ return *pEntry;
+ }
+
+ // try to get a list entry for which the shared action intersects with any
+ // other action of this entry
+ pEntry = GetIntersectingEntry( mpTrack->GetAction( nSharedAction ) );
+ if ( pEntry )
+ {
+ pEntry->maSharedActions.push_back( nSharedAction );
+ return *pEntry;
+ }
+
+ // try to get a list entry for which any of the own actions intersects with
+ // any other action of this entry
+ for ( auto& rOwnAction : rOwnActions )
+ {
+ pEntry = GetIntersectingEntry( mpTrack->GetAction( rOwnAction ) );
+ if ( pEntry )
+ {
+ pEntry->maSharedActions.push_back( nSharedAction );
+ return *pEntry;
+ }
+ }
+
+ // if no entry was found, create a new one
+ ScConflictsListEntry aEntry;
+ aEntry.meConflictAction = SC_CONFLICT_ACTION_NONE;
+ aEntry.maSharedActions.push_back( nSharedAction );
+ mrConflictsList.push_back( aEntry );
+ return mrConflictsList.back();
+}
+
+bool ScConflictsFinder::Find()
+{
+ if ( !mpTrack )
+ {
+ return false;
+ }
+
+ bool bReturn = false;
+ ScChangeAction* pSharedAction = mpTrack->GetAction( mnStartShared );
+ while ( pSharedAction && pSharedAction->GetActionNumber() <= mnEndShared )
+ {
+ std::vector<sal_uLong> aOwnActions;
+ ScChangeAction* pOwnAction = mpTrack->GetAction( mnStartOwn );
+ while ( pOwnAction && pOwnAction->GetActionNumber() <= mnEndOwn )
+ {
+ if ( DoActionsIntersect( pSharedAction, pOwnAction ) )
+ {
+ aOwnActions.push_back( pOwnAction->GetActionNumber() );
+ }
+ pOwnAction = pOwnAction->GetNext();
+ }
+
+ if ( !aOwnActions.empty() )
+ {
+ ScConflictsListEntry& rEntry = GetEntry(pSharedAction->GetActionNumber(), aOwnActions);
+ for ( const auto& aOwnAction : aOwnActions )
+ {
+ if (!ScConflictsListHelper::HasOwnAction(mrConflictsList, aOwnAction))
+ {
+ rEntry.maOwnActions.push_back(aOwnAction);
+ }
+ }
+ bReturn = true;
+ }
+
+ pSharedAction = pSharedAction->GetNext();
+ }
+
+ return bReturn;
+}
+
+
+ScConflictsResolver::ScConflictsResolver( ScChangeTrack* pTrack, ScConflictsList& rConflictsList )
+ :mpTrack ( pTrack )
+ ,mrConflictsList ( rConflictsList )
+{
+ OSL_ENSURE( mpTrack, "ScConflictsResolver CTOR: mpTrack is null!" );
+}
+
+void ScConflictsResolver::HandleAction( ScChangeAction* pAction, bool bIsSharedAction,
+ bool bHandleContentAction, bool bHandleNonContentAction )
+{
+ if ( !mpTrack || !pAction )
+ {
+ return;
+ }
+
+ if ( bIsSharedAction )
+ {
+ ScConflictsListEntry* pConflictEntry = ScConflictsListHelper::GetSharedActionEntry(
+ mrConflictsList, pAction->GetActionNumber() );
+ if ( pConflictEntry )
+ {
+ ScConflictAction eConflictAction = pConflictEntry->meConflictAction;
+ if ( eConflictAction == SC_CONFLICT_ACTION_KEEP_MINE )
+ {
+ if ( pAction->GetType() == SC_CAT_CONTENT )
+ {
+ if ( bHandleContentAction )
+ {
+ mpTrack->Reject( pAction );
+ }
+ }
+ else
+ {
+ if ( bHandleNonContentAction )
+ {
+ mpTrack->Reject( pAction );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ScConflictsListEntry* pConflictEntry = ScConflictsListHelper::GetOwnActionEntry(
+ mrConflictsList, pAction->GetActionNumber() );
+ if ( pConflictEntry )
+ {
+ ScConflictAction eConflictAction = pConflictEntry->meConflictAction;
+ if ( eConflictAction == SC_CONFLICT_ACTION_KEEP_MINE )
+ {
+ if ( pAction->GetType() == SC_CAT_CONTENT )
+ {
+ if ( bHandleContentAction )
+ {
+ // do nothing
+ //mpTrack->SelectContent( pAction );
+ }
+ }
+ else
+ {
+ if ( bHandleNonContentAction )
+ {
+ // do nothing
+ //mpTrack->Accept( pAction );
+ }
+ }
+ }
+ else if ( eConflictAction == SC_CONFLICT_ACTION_KEEP_OTHER )
+ {
+ if ( pAction->GetType() == SC_CAT_CONTENT )
+ {
+ if ( bHandleContentAction )
+ {
+ mpTrack->Reject( pAction );
+ }
+ }
+ else
+ {
+ if ( bHandleNonContentAction )
+ {
+ mpTrack->Reject( pAction );
+ }
+ }
+ }
+ }
+ }
+}
+
+
+ScConflictsDlg::ScConflictsDlg(weld::Window* pParent, ScViewData* pViewData, ScDocument* pSharedDoc, ScConflictsList& rConflictsList)
+ : GenericDialogController(pParent, "modules/scalc/ui/conflictsdialog.ui", "ConflictsDialog")
+ , maStrUnknownUser ( ScResId( STR_UNKNOWN_USER_CONFLICT ) )
+ , mpViewData ( pViewData )
+ , mpOwnDoc ( nullptr )
+ , mpOwnTrack ( nullptr )
+ , mpSharedDoc ( pSharedDoc )
+ , mpSharedTrack ( nullptr )
+ , mrConflictsList ( rConflictsList )
+ , maSelectionIdle ( "ScConflictsDlg maSelectionIdle" )
+ , mbInSelectHdl ( false )
+ , m_xBtnKeepMine(m_xBuilder->weld_button("keepmine"))
+ , m_xBtnKeepOther(m_xBuilder->weld_button("keepother"))
+ , m_xBtnKeepAllMine(m_xBuilder->weld_button("keepallmine"))
+ , m_xBtnKeepAllOthers(m_xBuilder->weld_button("keepallothers"))
+ , m_xLbConflicts(new SvxRedlinTable(m_xBuilder->weld_tree_view("container"), nullptr))
+{
+ OSL_ENSURE( mpViewData, "ScConflictsDlg CTOR: mpViewData is null!" );
+ mpOwnDoc = ( mpViewData ? &mpViewData->GetDocument() : nullptr );
+ OSL_ENSURE( mpOwnDoc, "ScConflictsDlg CTOR: mpOwnDoc is null!" );
+ mpOwnTrack = ( mpOwnDoc ? mpOwnDoc->GetChangeTrack() : nullptr );
+ OSL_ENSURE( mpOwnTrack, "ScConflictsDlg CTOR: mpOwnTrack is null!" );
+ OSL_ENSURE( mpSharedDoc, "ScConflictsDlg CTOR: mpSharedDoc is null!" );
+ mpSharedTrack = ( mpSharedDoc ? mpSharedDoc->GetChangeTrack() : nullptr );
+ OSL_ENSURE( mpSharedTrack, "ScConflictsDlg CTOR: mpSharedTrack is null!" );
+
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+
+ auto nDigitWidth = rTreeView.get_approximate_digit_width();
+ std::vector<int> aWidths
+ {
+ o3tl::narrowing<int>(nDigitWidth * 60),
+ o3tl::narrowing<int>(nDigitWidth * 20)
+ };
+ rTreeView.set_column_fixed_widths(aWidths);
+
+ rTreeView.set_selection_mode(SelectionMode::Multiple);
+ rTreeView.set_size_request(-1, rTreeView.get_height_rows(16));
+
+ maSelectionIdle.SetInvokeHandler( LINK( this, ScConflictsDlg, UpdateSelectionHdl ) );
+
+ rTreeView.connect_changed(LINK(this, ScConflictsDlg, SelectHandle));
+
+ m_xBtnKeepMine->connect_clicked( LINK( this, ScConflictsDlg, KeepMineHandle ) );
+ m_xBtnKeepOther->connect_clicked( LINK( this, ScConflictsDlg, KeepOtherHandle ) );
+ m_xBtnKeepAllMine->connect_clicked( LINK( this, ScConflictsDlg, KeepAllMineHandle ) );
+ m_xBtnKeepAllOthers->connect_clicked( LINK( this, ScConflictsDlg, KeepAllOthersHandle ) );
+
+ UpdateView();
+
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ if (rTreeView.get_iter_first(*xEntry))
+ rTreeView.select(*xEntry);
+}
+
+ScConflictsDlg::~ScConflictsDlg()
+{
+}
+
+OUString ScConflictsDlg::GetConflictString( const ScConflictsListEntry& rConflictEntry )
+{
+ OUString aString;
+ if ( mpOwnTrack )
+ {
+ const ScChangeAction* pAction = mpOwnTrack->GetAction( rConflictEntry.maOwnActions[ 0 ] );
+ if ( pAction && mpOwnDoc )
+ {
+ SCTAB nTab = pAction->GetBigRange().MakeRange( *mpOwnDoc ).aStart.Tab();
+ mpOwnDoc->GetName( nTab, aString );
+ }
+ }
+ return aString;
+}
+
+void ScConflictsDlg::SetActionString(const ScChangeAction* pAction, ScDocument* pDoc, const weld::TreeIter& rEntry)
+{
+ OSL_ENSURE( pAction, "ScConflictsDlg::GetActionString(): pAction is null!" );
+ OSL_ENSURE( pDoc, "ScConflictsDlg::GetActionString(): pDoc is null!" );
+ if (!pAction || !pDoc)
+ return;
+
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ OUString aDesc = pAction->GetDescription(*pDoc, true, false);
+ rTreeView.set_text(rEntry, aDesc, 0);
+
+ OUString aUser = comphelper::string::strip(pAction->GetUser(), ' ');
+ if ( aUser.isEmpty() )
+ {
+ aUser = maStrUnknownUser;
+ }
+ rTreeView.set_text(rEntry, aUser, 1);
+
+ DateTime aDateTime = pAction->GetDateTime();
+ OUString aString = ScGlobal::getLocaleData().getDate( aDateTime ) + " " +
+ ScGlobal::getLocaleData().getTime( aDateTime, false );
+ rTreeView.set_text(rEntry, aString, 2);
+}
+
+void ScConflictsDlg::HandleListBoxSelection()
+{
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ bool bSelEntry = rTreeView.get_cursor(xEntry.get());
+ if (!bSelEntry)
+ bSelEntry = rTreeView.get_selected(xEntry.get());
+ if (!bSelEntry)
+ return;
+
+ bool bSelectHandle = rTreeView.is_selected(*xEntry);
+
+ while (rTreeView.get_iter_depth(*xEntry))
+ rTreeView.iter_parent(*xEntry);
+
+ if (bSelectHandle)
+ rTreeView.unselect_all();
+ if (!rTreeView.is_selected(*xEntry))
+ rTreeView.select(*xEntry);
+ if (rTreeView.iter_children(*xEntry))
+ {
+ do
+ {
+ if (!rTreeView.is_selected(*xEntry))
+ rTreeView.select(*xEntry);
+ } while (rTreeView.iter_next_sibling(*xEntry));
+ }
+}
+
+IMPL_LINK_NOARG(ScConflictsDlg, SelectHandle, weld::TreeView&, void)
+{
+ if (mbInSelectHdl)
+ return;
+
+ mbInSelectHdl = true;
+ HandleListBoxSelection();
+ maSelectionIdle.Start();
+ mbInSelectHdl = false;
+}
+
+IMPL_LINK_NOARG(ScConflictsDlg, UpdateSelectionHdl, Timer *, void)
+{
+ if ( !mpViewData || !mpOwnDoc )
+ {
+ return;
+ }
+
+ ScTabView* pTabView = mpViewData->GetView();
+ pTabView->DoneBlockMode();
+
+ std::vector<const ScChangeAction*> aActions;
+
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ rTreeView.selected_foreach([&rTreeView, &aActions](weld::TreeIter& rEntry){
+ if (rTreeView.get_iter_depth(rEntry))
+ {
+ RedlinData* pUserData = weld::fromId<RedlinData*>(rTreeView.get_id(rEntry));
+ if (pUserData)
+ {
+ ScChangeAction* pAction = static_cast< ScChangeAction* >( pUserData->pData );
+ if ( pAction && ( pAction->GetType() != SC_CAT_DELETE_TABS ) &&
+ ( pAction->IsClickable() || pAction->IsVisible() ) )
+ {
+ aActions.push_back(pAction);
+ }
+ }
+ }
+ return false;
+ });
+
+ bool bContMark = false;
+ for (size_t i = 0, nCount = aActions.size(); i < nCount; ++i)
+ {
+ const ScBigRange& rBigRange = aActions[i]->GetBigRange();
+ if (rBigRange.IsValid(*mpOwnDoc))
+ {
+ bool bSetCursor = i == nCount - 1;
+ pTabView->MarkRange(rBigRange.MakeRange( *mpOwnDoc ), bSetCursor, bContMark);
+ bContMark = true;
+ }
+ }
+}
+
+void ScConflictsDlg::SetConflictAction(const weld::TreeIter& rRootEntry, ScConflictAction eConflictAction)
+{
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ RedlinData* pUserData = weld::fromId<RedlinData*>(rTreeView.get_id(rRootEntry));
+ ScConflictsListEntry* pConflictEntry = static_cast< ScConflictsListEntry* >( pUserData ? pUserData->pData : nullptr );
+ if ( pConflictEntry )
+ {
+ pConflictEntry->meConflictAction = eConflictAction;
+ }
+}
+
+void ScConflictsDlg::KeepHandler(bool bMine)
+{
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ if (!rTreeView.get_selected(xEntry.get()))
+ return;
+
+ while (rTreeView.get_iter_depth(*xEntry))
+ rTreeView.iter_parent(*xEntry);
+
+ m_xDialog->set_busy_cursor(true);
+ ScConflictAction eConflictAction = ( bMine ? SC_CONFLICT_ACTION_KEEP_MINE : SC_CONFLICT_ACTION_KEEP_OTHER );
+ SetConflictAction(*xEntry, eConflictAction);
+ rTreeView.remove(*xEntry);
+ m_xDialog->set_busy_cursor(false);
+ if (rTreeView.n_children() == 0)
+ m_xDialog->response(RET_OK);
+}
+
+void ScConflictsDlg::KeepAllHandler( bool bMine )
+{
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ if (!rTreeView.get_iter_first(*xEntry))
+ return;
+
+ while (rTreeView.get_iter_depth(*xEntry))
+ rTreeView.iter_parent(*xEntry);
+
+ m_xDialog->set_busy_cursor(true);
+
+ ScConflictAction eConflictAction = ( bMine ? SC_CONFLICT_ACTION_KEEP_MINE : SC_CONFLICT_ACTION_KEEP_OTHER );
+ do
+ {
+ SetConflictAction(*xEntry, eConflictAction);
+ } while (rTreeView.iter_next_sibling(*xEntry));
+
+ rTreeView.freeze();
+ rTreeView.clear();
+ rTreeView.thaw();
+
+ m_xDialog->set_busy_cursor(false);
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScConflictsDlg, KeepMineHandle, weld::Button&, void)
+{
+ KeepHandler( true );
+}
+
+IMPL_LINK_NOARG(ScConflictsDlg, KeepOtherHandle, weld::Button&, void)
+{
+ KeepHandler( false );
+}
+
+IMPL_LINK_NOARG(ScConflictsDlg, KeepAllMineHandle, weld::Button&, void)
+{
+ KeepAllHandler( true );
+}
+
+IMPL_LINK_NOARG(ScConflictsDlg, KeepAllOthersHandle, weld::Button&, void)
+{
+ KeepAllHandler( false );
+}
+
+void ScConflictsDlg::UpdateView()
+{
+ weld::TreeView& rTreeView = m_xLbConflicts->GetWidget();
+ for ( ScConflictsListEntry& rConflictEntry : mrConflictsList )
+ {
+ if (rConflictEntry.meConflictAction == SC_CONFLICT_ACTION_NONE)
+ {
+ std::unique_ptr<RedlinData> pRootUserData(new RedlinData());
+ pRootUserData->pData = static_cast<void*>(&rConflictEntry);
+ OUString sString(GetConflictString(rConflictEntry));
+ OUString sId(weld::toId(pRootUserData.release()));
+ std::unique_ptr<weld::TreeIter> xRootEntry(rTreeView.make_iterator());
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ rTreeView.insert(nullptr, -1, &sString, &sId, nullptr, nullptr, false, xRootEntry.get());
+
+ for ( const auto& aSharedAction : rConflictEntry.maSharedActions )
+ {
+ ScChangeAction* pAction = mpSharedTrack ? mpSharedTrack->GetAction(aSharedAction) : nullptr;
+ if ( pAction )
+ {
+ // only display shared top content entries
+ if ( pAction->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionContent* pNextContent = dynamic_cast<ScChangeActionContent&>(*pAction).GetNextContent();
+ if ( pNextContent && rConflictEntry.HasSharedAction( pNextContent->GetActionNumber() ) )
+ {
+ continue;
+ }
+ }
+
+ rTreeView.insert(xRootEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xEntry.get());
+ SetActionString(pAction, mpSharedDoc, *xEntry);
+ }
+ }
+
+ for ( const auto& aOwnAction : rConflictEntry.maOwnActions )
+ {
+ ScChangeAction* pAction = mpOwnTrack ? mpOwnTrack->GetAction(aOwnAction) : nullptr;
+ if ( pAction )
+ {
+ // only display own top content entries
+ if ( pAction->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionContent* pNextContent = dynamic_cast<ScChangeActionContent&>(*pAction).GetNextContent();
+ if ( pNextContent && rConflictEntry.HasOwnAction( pNextContent->GetActionNumber() ) )
+ {
+ continue;
+ }
+ }
+
+ std::unique_ptr<RedlinData> pUserData(new RedlinData());
+ pUserData->pData = static_cast< void* >( pAction );
+ OUString aId(weld::toId(pUserData.release()));
+ rTreeView.insert(xRootEntry.get(), -1, nullptr, &aId, nullptr, nullptr, false, xEntry.get());
+ SetActionString(pAction, mpOwnDoc, *xEntry);
+ }
+ }
+
+ rTreeView.expand_row(*xRootEntry);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/crdlg.cxx b/sc/source/ui/miscdlgs/crdlg.cxx
new file mode 100644
index 000000000..9d778595e
--- /dev/null
+++ b/sc/source/ui/miscdlgs/crdlg.cxx
@@ -0,0 +1,45 @@
+/* -*- 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 <crdlg.hxx>
+#include <scui_def.hxx>
+
+ScColOrRowDlg::ScColOrRowDlg(weld::Window* pParent, const OUString& rStrTitle,
+ const OUString& rStrLabel)
+ : GenericDialogController(pParent, "modules/scalc/ui/colorrowdialog.ui", "ColOrRowDialog")
+ , m_xFrame(m_xBuilder->weld_frame("frame"))
+ , m_xBtnRows(m_xBuilder->weld_radio_button("rows"))
+ , m_xBtnCols(m_xBuilder->weld_radio_button("columns"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+{
+ m_xDialog->set_title(rStrTitle);
+ m_xFrame->set_label(rStrLabel);
+ m_xBtnOk->connect_clicked(LINK(this, ScColOrRowDlg, OkHdl));
+}
+
+ScColOrRowDlg::~ScColOrRowDlg() {}
+
+IMPL_LINK_NOARG(ScColOrRowDlg, OkHdl, weld::Button&, void)
+{
+ m_xDialog->response(m_xBtnCols->get_active() ? SCRET_COLS : SCRET_ROWS);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/crnrdlg.cxx b/sc/source/ui/miscdlgs/crnrdlg.cxx
new file mode 100644
index 000000000..38a0cfe66
--- /dev/null
+++ b/sc/source/ui/miscdlgs/crnrdlg.cxx
@@ -0,0 +1,800 @@
+/* -*- 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 <reffact.hxx>
+#include <document.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <docsh.hxx>
+#include <crnrdlg.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <o3tl/string_view.hxx>
+#include <memory>
+
+namespace
+{
+ void ERRORBOX(weld::Window* pParent, const OUString& rString)
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
+ VclMessageType::Warning, VclButtonsType::Ok,
+ rString));
+ xBox->run();
+ }
+
+ int QUERYBOX(weld::Window* pParent, const OUString& rString)
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
+ VclMessageType::Question, VclButtonsType::YesNo,
+ rString));
+ xBox->set_default_response(RET_YES);
+ return xBox->run();
+ }
+
+}
+
+const sal_uLong nEntryDataCol = 0;
+const sal_uLong nEntryDataRow = 1;
+const sal_uLong nEntryDataDelim = 2;
+
+
+// note: some of the initialisation is done in Init
+ScColRowNameRangesDlg::ScColRowNameRangesDlg( SfxBindings* pB,
+ SfxChildWindow* pCW,
+ weld::Window* pParent,
+ ScViewData& rViewData )
+
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/namerangesdialog.ui", "NameRangesDialog")
+ , m_rViewData(rViewData)
+ , rDoc(rViewData.GetDocument())
+ , bDlgLostFocus(false)
+ , m_pEdActive(nullptr)
+ , m_xLbRange(m_xBuilder->weld_tree_view("range"))
+ , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry("edassign")))
+ , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button("rbassign")))
+ , m_xBtnColHead(m_xBuilder->weld_radio_button("colhead"))
+ , m_xBtnRowHead(m_xBuilder->weld_radio_button("rowhead"))
+ , m_xEdAssign2(new formula::RefEdit(m_xBuilder->weld_entry("edassign2")))
+ , m_xRbAssign2(new formula::RefButton(m_xBuilder->weld_button("rbassign2")))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+ , m_xBtnAdd(m_xBuilder->weld_button("add"))
+ , m_xBtnRemove(m_xBuilder->weld_button("delete"))
+ , m_xRangeFrame(m_xBuilder->weld_frame("rangeframe"))
+ , m_xRangeFT(m_xRangeFrame->weld_label_widget())
+ , m_xDataFT(m_xBuilder->weld_label("datarange"))
+{
+ m_xRbAssign->SetReferences(this, m_xEdAssign.get());
+ m_xEdAssign->SetReferences(this, m_xRangeFT.get());
+ m_xRbAssign2->SetReferences(this, m_xEdAssign2.get());
+ m_xEdAssign2->SetReferences(this, m_xDataFT.get());
+
+ xColNameRanges = rDoc.GetColNameRanges()->Clone();
+ xRowNameRanges = rDoc.GetRowNameRanges()->Clone();
+ Init();
+}
+
+ScColRowNameRangesDlg::~ScColRowNameRangesDlg()
+{
+}
+
+// initialises event handlers and start parameters in the dialog
+void ScColRowNameRangesDlg::Init()
+{
+ m_xBtnOk->connect_clicked ( LINK( this, ScColRowNameRangesDlg, OkBtnHdl ) );
+ m_xBtnCancel->connect_clicked ( LINK( this, ScColRowNameRangesDlg, CancelBtnHdl ) );
+ m_xBtnAdd->connect_clicked ( LINK( this, ScColRowNameRangesDlg, AddBtnHdl ) );
+ m_xBtnRemove->connect_clicked ( LINK( this, ScColRowNameRangesDlg, RemoveBtnHdl ) );
+ m_xLbRange->connect_changed( LINK( this, ScColRowNameRangesDlg, Range1SelectHdl ) );
+ m_xEdAssign->SetModifyHdl ( LINK( this, ScColRowNameRangesDlg, Range1DataModifyHdl ) );
+ m_xBtnColHead->connect_toggled ( LINK( this, ScColRowNameRangesDlg, ColRowToggleHdl ) );
+ m_xEdAssign2->SetModifyHdl ( LINK( this, ScColRowNameRangesDlg, Range2DataModifyHdl ) );
+
+ Link<formula::RefEdit&,void> aEditLink = LINK( this, ScColRowNameRangesDlg, GetEditFocusHdl );
+ m_xEdAssign->SetGetFocusHdl( aEditLink );
+ m_xEdAssign2->SetGetFocusHdl( aEditLink );
+
+ Link<formula::RefButton&,void> aButtonLink = LINK( this, ScColRowNameRangesDlg, GetButtonFocusHdl );
+ m_xRbAssign->SetGetFocusHdl( aButtonLink );
+ m_xRbAssign2->SetGetFocusHdl( aButtonLink );
+
+ aEditLink = LINK( this, ScColRowNameRangesDlg, LoseEditFocusHdl );
+ m_xEdAssign->SetLoseFocusHdl( aEditLink );
+ m_xEdAssign2->SetLoseFocusHdl( aEditLink );
+
+ aButtonLink = LINK( this, ScColRowNameRangesDlg, LoseButtonFocusHdl );
+ m_xRbAssign2->SetLoseFocusHdl( aButtonLink );
+ m_xRbAssign->SetLoseFocusHdl( aButtonLink );
+
+ m_pEdActive = m_xEdAssign.get();
+
+ UpdateNames();
+
+ SCCOL nStartCol = 0;
+ SCROW nStartRow = 0;
+ SCTAB nStartTab = 0;
+ SCCOL nEndCol = 0;
+ SCROW nEndRow = 0;
+ SCTAB nEndTab = 0;
+ m_rViewData.GetSimpleArea(nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab );
+ SetColRowData( ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab));
+
+ m_xBtnColHead->set_sensitive(true);
+ m_xBtnRowHead->set_sensitive(true);
+ m_xEdAssign->GetWidget()->set_sensitive(true);
+ m_xEdAssign->GrabFocus();
+ m_xRbAssign->GetWidget()->set_sensitive(true);
+
+ Range1SelectHdl( *m_xLbRange );
+}
+
+// set data range of a labeled range to default values and set the
+// form elements for the reference
+void ScColRowNameRangesDlg::SetColRowData( const ScRange& rLabelRange, bool bRef)
+{
+ theCurData = theCurArea = rLabelRange;
+ bool bValid = true;
+ SCCOL nCol1 = theCurArea.aStart.Col();
+ SCCOL nCol2 = theCurArea.aEnd.Col();
+ SCROW nRow1 = theCurArea.aStart.Row();
+ SCROW nRow2 = theCurArea.aEnd.Row();
+ if ( (static_cast<SCCOLROW>(nCol2 - nCol1) >= nRow2 - nRow1) || (nCol1 == 0 && nCol2 == rDoc.MaxCol()) )
+ { // Column headers and the limiting case of the whole sheet
+ m_xBtnColHead->set_active(true);
+ m_xBtnRowHead->set_active(false);
+ if ( nRow2 == rDoc.MaxRow() )
+ {
+ if ( nRow1 == 0 )
+ bValid = false; // limiting case of the whole sheet
+ else
+ { // Header at bottom, data above
+ theCurData.aStart.SetRow( 0 );
+ theCurData.aEnd.SetRow( nRow1 - 1 );
+ }
+ }
+ else
+ { // Header at top, data below
+ theCurData.aStart.SetRow( nRow2 + 1 );
+ theCurData.aEnd.SetRow( rDoc.MaxRow() );
+ }
+ }
+ else
+ { // Column headers
+ m_xBtnRowHead->set_active(true);
+ m_xBtnColHead->set_active(false);
+ if ( nCol2 == rDoc.MaxCol() )
+ { // Header at the right, data to the left
+ theCurData.aStart.SetCol( 0 );
+ theCurData.aEnd.SetCol( nCol2 - 1 );
+ }
+ else
+ { // Header at the left, data to the right
+ theCurData.aStart.SetCol( nCol2 + 1 );
+ theCurData.aEnd.SetCol( rDoc.MaxCol() );
+ }
+ }
+ if ( bValid )
+ {
+ const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
+ OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv));
+
+ if(bRef)
+ m_xEdAssign->SetRefString( aStr );
+ else
+ m_xEdAssign->SetText( aStr );
+
+ m_xEdAssign->SetCursorAtLast();
+ aStr = theCurData.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv);
+
+ if(bRef)
+ m_xEdAssign2->SetRefString( aStr );
+ else
+ m_xEdAssign2->SetText( aStr );
+ }
+ else
+ {
+ theCurData = theCurArea = ScRange();
+
+ if(bRef)
+ {
+ m_xEdAssign->SetRefString( OUString() );
+ m_xEdAssign2->SetRefString( OUString() );
+ }
+ else
+ {
+ m_xEdAssign->SetText( OUString() );
+ m_xEdAssign2->SetText( OUString() );
+ }
+
+ m_xBtnColHead->set_sensitive(false);
+ m_xBtnRowHead->set_sensitive(false);
+ m_xEdAssign2->GetWidget()->set_sensitive(false);
+ m_xRbAssign2->GetWidget()->set_sensitive(false);
+ }
+}
+
+// adjust label range and set the data reference form element
+void ScColRowNameRangesDlg::AdjustColRowData( const ScRange& rDataRange, bool bRef)
+{
+ theCurData = rDataRange;
+ if ( m_xBtnColHead->get_active() )
+ { // Data range is the same columns as the header
+ theCurData.aStart.SetCol( theCurArea.aStart.Col() );
+ theCurData.aEnd.SetCol( theCurArea.aEnd.Col() );
+ if ( theCurData.Intersects( theCurArea ) )
+ {
+ SCROW nRow1 = theCurArea.aStart.Row();
+ SCROW nRow2 = theCurArea.aEnd.Row();
+ if ( nRow1 > 0
+ && (theCurData.aEnd.Row() < nRow2 || nRow2 == rDoc.MaxRow()) )
+ { // Data above header
+ theCurData.aEnd.SetRow( nRow1 - 1 );
+ if ( theCurData.aStart.Row() > theCurData.aEnd.Row() )
+ theCurData.aStart.SetRow( theCurData.aEnd.Row() );
+ }
+ else
+ { // Data below header
+ theCurData.aStart.SetRow( nRow2 + 1 );
+ if ( theCurData.aStart.Row() > theCurData.aEnd.Row() )
+ theCurData.aEnd.SetRow( theCurData.aStart.Row() );
+ }
+ }
+ }
+ else
+ { // Data range in the same rows as header
+ theCurData.aStart.SetRow( theCurArea.aStart.Row() );
+ theCurData.aEnd.SetRow( theCurArea.aEnd.Row() );
+ if ( theCurData.Intersects( theCurArea ) )
+ {
+ SCCOL nCol1 = theCurArea.aStart.Col();
+ SCCOL nCol2 = theCurArea.aEnd.Col();
+ if ( nCol1 > 0
+ && (theCurData.aEnd.Col() < nCol2 || nCol2 == rDoc.MaxCol()) )
+ { // Data left of header
+ theCurData.aEnd.SetCol( nCol1 - 1 );
+ if ( theCurData.aStart.Col() > theCurData.aEnd.Col() )
+ theCurData.aStart.SetCol( theCurData.aEnd.Col() );
+ }
+ else
+ { // Data right of header
+ theCurData.aStart.SetCol( nCol2 + 1 );
+ if ( theCurData.aStart.Col() > theCurData.aEnd.Col() )
+ theCurData.aEnd.SetCol( theCurData.aStart.Col() );
+ }
+ }
+ }
+ OUString aStr(theCurData.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
+
+ if(bRef)
+ m_xEdAssign2->SetRefString( aStr );
+ else
+ m_xEdAssign2->SetText( aStr );
+
+ m_xEdAssign2->SetCursorAtLast();
+}
+
+// Set the reference to a cell range selected with the mouse and update
+// the selection form element
+void ScColRowNameRangesDlg::SetReference( const ScRange& rRef, ScDocument& /* rDoc */ )
+{
+ if ( !m_pEdActive )
+ return;
+
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart( m_pEdActive );
+
+ if (m_pEdActive == m_xEdAssign.get())
+ SetColRowData( rRef, true );
+ else
+ AdjustColRowData( rRef, true );
+ m_xBtnColHead->set_sensitive(true);
+ m_xBtnRowHead->set_sensitive(true);
+ m_xBtnAdd->set_sensitive(true);
+ m_xBtnRemove->set_sensitive(false);
+}
+
+void ScColRowNameRangesDlg::Close()
+{
+ DoClose( ScColRowNameRangesDlgWrapper::GetChildWindowId() );
+}
+
+void ScColRowNameRangesDlg::SetActive()
+{
+ if ( bDlgLostFocus )
+ {
+ bDlgLostFocus = false;
+ if( m_pEdActive )
+ m_pEdActive->GrabFocus();
+ }
+ else
+ m_xDialog->grab_focus();
+
+ if( m_pEdActive == m_xEdAssign.get() )
+ Range1DataModifyHdl( *m_xEdAssign );
+ else if( m_pEdActive == m_xEdAssign2.get() )
+ Range2DataModifyHdl( *m_xEdAssign2 );
+
+ RefInputDone();
+}
+
+void ScColRowNameRangesDlg::UpdateNames()
+{
+ m_xLbRange->freeze();
+
+ m_xLbRange->clear();
+ aRangeMap.clear();
+ m_xEdAssign->SetText( OUString() );
+
+ size_t nCount, j;
+
+ SCCOL nCol1;
+ SCROW nRow1; //Extension for range names
+ SCTAB nTab1;
+ SCCOL nCol2;
+ SCROW nRow2;
+ SCTAB nTab2;
+ OUString rString;
+ const ScAddress::Details aDetails(rDoc.GetAddressConvention());
+
+ OUString strDelim(" --- ");
+ OUString aString = strDelim + ScResId( STR_COLUMN ) + strDelim;
+ m_xLbRange->append(OUString::number(nEntryDataDelim), aString);
+ if ( xColNameRanges->size() > 0 )
+ {
+ std::vector<const ScRangePair*> aSortArray(xColNameRanges->CreateNameSortedArray(
+ rDoc ));
+ nCount = aSortArray.size();
+ for ( j=0; j < nCount; j++ )
+ {
+ const ScRange aRange(aSortArray[j]->GetRange(0));
+ aString = aRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, aDetails);
+
+ //@008 get range parameters from document
+ aSortArray[j]->GetRange(0).GetVars( nCol1, nRow1, nTab1,
+ nCol2, nRow2, nTab2 );
+ SCCOL q=nCol1+3;
+ if(q>nCol2) q=nCol2;
+ //@008 construct string
+ OUStringBuffer strShow = " [";
+ rString = rDoc.GetString(nCol1, nRow1, nTab1);
+ strShow.append(rString);
+ for(SCCOL i=nCol1+1;i<=q;i++)
+ {
+ strShow.append(", ");
+ rString = rDoc.GetString(i, nRow1, nTab1);
+ strShow.append(rString);
+ }
+ if(q<nCol2) // Too long? Add ",..."
+ {
+ strShow.append(", ...");
+ }
+ strShow.append("]");
+
+ //@008 Add string to listbox
+ OUString aInsStr = aString + strShow;
+ aRangeMap.emplace( aInsStr, aRange );
+ m_xLbRange->append(OUString::number(nEntryDataCol), aInsStr);
+ }
+ }
+ aString = strDelim + ScResId( STR_ROW ) + strDelim;
+ m_xLbRange->append(OUString::number(nEntryDataDelim), aString);
+ if ( xRowNameRanges->size() > 0 )
+ {
+ std::vector<const ScRangePair*> aSortArray(xRowNameRanges->CreateNameSortedArray(
+ rDoc ));
+ nCount = aSortArray.size();
+ for ( j=0; j < nCount; j++ )
+ {
+ const ScRange aRange(aSortArray[j]->GetRange(0));
+ aString = aRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, aDetails);
+
+ //@008 Build string for rows below
+ aSortArray[j]->GetRange(0).GetVars( nCol1, nRow1, nTab1,
+ nCol2, nRow2, nTab2 );
+ SCROW q=nRow1+3;
+ if(q>nRow2) q=nRow2;
+ OUStringBuffer strShow = " [";
+ rString = rDoc.GetString(nCol1, nRow1, nTab1);
+ strShow.append(rString);
+ for(SCROW i=nRow1+1;i<=q;i++)
+ {
+ strShow.append(", ");
+ rString = rDoc.GetString(nCol1, i, nTab1);
+ strShow.append(rString);
+ }
+ if(q<nRow2)
+ {
+ strShow.append(", ...");
+ }
+ strShow.append("]");
+
+ OUString aInsStr = aString + strShow;
+ aRangeMap.emplace( aInsStr, aRange );
+ m_xLbRange->append(OUString::number(nEntryDataRow), aInsStr);
+ }
+ }
+
+ m_xLbRange->thaw();
+}
+
+void ScColRowNameRangesDlg::UpdateRangeData( const ScRange& rRange, bool bColName )
+{
+ ScRangePair* pPair = nullptr;
+ bool bFound = false;
+ if ( bColName && (pPair = xColNameRanges->Find( rRange )) != nullptr )
+ bFound = true;
+ else if ( !bColName && (pPair = xRowNameRanges->Find( rRange )) != nullptr )
+ bFound = true;
+
+ if ( bFound )
+ {
+ const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
+ theCurArea = rRange;
+ OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv));
+ m_xEdAssign->SetText( aStr );
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(true);
+ m_xBtnColHead->set_active(bColName);
+ m_xBtnRowHead->set_active(!bColName);
+ theCurData = pPair->GetRange(1);
+ aStr = theCurData.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv);
+ m_xEdAssign2->SetText( aStr );
+ }
+ else
+ {
+ m_xBtnAdd->set_sensitive(true);
+ m_xBtnRemove->set_sensitive(false);
+ }
+ m_xBtnColHead->set_sensitive(true);
+ m_xBtnRowHead->set_sensitive(true);
+ m_xEdAssign2->GetWidget()->set_sensitive(true);
+ m_xRbAssign2->GetWidget()->set_sensitive(true);
+}
+
+bool ScColRowNameRangesDlg::IsRefInputMode() const
+{
+ return (m_pEdActive != nullptr);
+}
+
+// Handler:
+
+// handler called when OK is clicked, calls the add button handler before
+// passing the range lists to the document
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, OkBtnHdl, weld::Button&, void)
+{
+ AddBtnHdl(*m_xBtnAdd);
+
+ // assign RangeLists to the references in the document
+ rDoc.GetColNameRangesRef() = xColNameRanges;
+ rDoc.GetRowNameRangesRef() = xRowNameRanges;
+ // changed ranges need to take effect
+ rDoc.CompileColRowNameFormula();
+ ScDocShell* pDocShell = m_rViewData.GetDocShell();
+ pDocShell->PostPaint(ScRange(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), MAXTAB), PaintPartFlags::Grid);
+ pDocShell->SetDocumentModified();
+
+ response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, CancelBtnHdl, weld::Button&, void)
+{
+ response(RET_CANCEL);
+}
+
+// handler called when add button clicked: set ranges and add to listbox
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, AddBtnHdl, weld::Button&, void)
+{
+ OUString aNewArea( m_xEdAssign->GetText() );
+ OUString aNewData( m_xEdAssign2->GetText() );
+
+ if (aNewArea.isEmpty() || aNewData.isEmpty())
+ return;
+
+ const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
+ ScRange aRange1, aRange2;
+ bool bOk1 = (aRange1.ParseAny( aNewArea, rDoc, eConv ) & ScRefFlags::VALID) == ScRefFlags::VALID;
+ if ( bOk1 && (aRange2.ParseAny( aNewData, rDoc, eConv ) & ScRefFlags::VALID) == ScRefFlags::VALID)
+ {
+ theCurArea = aRange1;
+ AdjustColRowData( aRange2 );
+ ScRangePair* pPair;
+ if ( ( pPair = xColNameRanges->Find( theCurArea ) ) != nullptr )
+ {
+ xColNameRanges->Remove( *pPair );
+ }
+ if ( ( pPair = xRowNameRanges->Find( theCurArea ) ) != nullptr )
+ {
+ xRowNameRanges->Remove( *pPair );
+ }
+ if ( m_xBtnColHead->get_active() )
+ xColNameRanges->Join( ScRangePair( theCurArea, theCurData ) );
+ else
+ xRowNameRanges->Join( ScRangePair( theCurArea, theCurData ) );
+
+ UpdateNames();
+
+ m_xEdAssign->GrabFocus();
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(false);
+ m_xEdAssign->SetText( OUString() );
+ m_xBtnColHead->set_active(true);
+ m_xBtnRowHead->set_active(false);
+ m_xEdAssign2->SetText( OUString() );
+ theCurArea = ScRange();
+ theCurData = theCurArea;
+ Range1SelectHdl( *m_xLbRange );
+ }
+ else
+ {
+ ERRORBOX(m_xDialog.get(), ScResId(STR_INVALIDTABNAME));
+ if ( !bOk1 )
+ m_xEdAssign->GrabFocus();
+ else
+ m_xEdAssign2->GrabFocus();
+ }
+}
+
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, RemoveBtnHdl, weld::Button&, void)
+{
+ OUString aRangeStr = m_xLbRange->get_selected_text();
+ sal_Int32 nSelectPos = m_xLbRange->get_selected_index();
+ bool bColName = nSelectPos != -1 && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataCol;
+ NameRangeMap::const_iterator itr = aRangeMap.find(aRangeStr);
+ if (itr == aRangeMap.end())
+ return;
+ const ScRange& rRange = itr->second;
+
+ ScRangePair* pPair = nullptr;
+ bool bFound = false;
+ if ( bColName && (pPair = xColNameRanges->Find( rRange )) != nullptr )
+ bFound = true;
+ else if ( !bColName && (pPair = xRowNameRanges->Find( rRange )) != nullptr )
+ bFound = true;
+ if ( !bFound )
+ return;
+
+ OUString aStrDelMsg = ScResId( STR_QUERY_DELENTRY );
+ OUString aMsg = o3tl::getToken(aStrDelMsg, 0, '#' )
+ + aRangeStr
+ + o3tl::getToken(aStrDelMsg, 1, '#' );
+
+ if (RET_YES != QUERYBOX(m_xDialog.get(), aMsg))
+ return;
+
+ if ( bColName )
+ xColNameRanges->Remove( *pPair );
+ else
+ xRowNameRanges->Remove( *pPair );
+
+ UpdateNames();
+ const sal_Int32 nCnt = m_xLbRange->n_children();
+ if ( nSelectPos >= nCnt )
+ {
+ if ( nCnt )
+ nSelectPos = nCnt - 1;
+ else
+ nSelectPos = 0;
+ }
+ m_xLbRange->select(nSelectPos);
+ if (nSelectPos && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataDelim)
+ m_xLbRange->select( --nSelectPos ); // ---Row---
+
+ m_xLbRange->grab_focus();
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(false);
+ m_xEdAssign->SetText( OUString() );
+ theCurArea = theCurData = ScRange();
+ m_xBtnColHead->set_active(true);
+ m_xBtnRowHead->set_active(false);
+ m_xEdAssign2->SetText( OUString() );
+ Range1SelectHdl( *m_xLbRange );
+}
+
+// handler called when a row in the listbox is selected, updates form input fields
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range1SelectHdl, weld::TreeView&, void)
+{
+ sal_Int32 nSelectPos = m_xLbRange->get_selected_index();
+ const sal_Int32 nCnt = m_xLbRange->n_children();
+ sal_uInt16 nMoves = 0;
+ while (nSelectPos != -1 && nSelectPos < nCnt && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataDelim)
+ { // skip Delimiter
+ ++nMoves;
+ ++nSelectPos;
+ }
+ OUString aRangeStr = m_xLbRange->get_selected_text();
+ if ( nMoves )
+ {
+ if ( nSelectPos > 1 && nSelectPos >= nCnt )
+ { // if entries exist before the " --- Row --- " Delimiter then
+ // do not stop at the delimiter
+ nSelectPos = nCnt - 2;
+ m_xLbRange->select(nSelectPos);
+ aRangeStr = m_xLbRange->get_selected_text();
+ }
+ else if ( nSelectPos > 2 && nSelectPos < nCnt && !aRangeStr.isEmpty()
+ && aRangeStr == m_xEdAssign->GetText() )
+ { // move upwards instead of below to the previous position
+ nSelectPos -= 2;
+ m_xLbRange->select( nSelectPos );
+ aRangeStr = m_xLbRange->get_selected_text();
+ }
+ else
+ m_xLbRange->select(nSelectPos);
+ }
+ NameRangeMap::const_iterator itr = aRangeMap.find(aRangeStr);
+ if ( itr != aRangeMap.end() )
+ {
+ bool bColName = m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataCol;
+ UpdateRangeData( itr->second, bColName );
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(true);
+ }
+ else
+ {
+ if ( !m_xEdAssign->GetText().isEmpty() )
+ {
+ if ( !m_xEdAssign2->GetText().isEmpty() )
+ m_xBtnAdd->set_sensitive(true);
+ else
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnColHead->set_sensitive(true);
+ m_xBtnRowHead->set_sensitive(true);
+ m_xEdAssign2->GetWidget()->set_sensitive(true);
+ m_xRbAssign2->GetWidget()->set_sensitive(true);
+ }
+ else
+ {
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnColHead->set_sensitive(false);
+ m_xBtnRowHead->set_sensitive(false);
+ m_xEdAssign2->GetWidget()->set_sensitive(false);
+ m_xRbAssign2->GetWidget()->set_sensitive(false);
+ }
+ m_xBtnRemove->set_sensitive(false);
+ m_xEdAssign->GrabFocus();
+ }
+
+ m_xEdAssign->GetWidget()->set_sensitive(true);
+ m_xRbAssign->GetWidget()->set_sensitive(true);
+}
+
+// handler called when the label range has changed
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range1DataModifyHdl, formula::RefEdit&, void)
+{
+ OUString aNewArea( m_xEdAssign->GetText() );
+ bool bValid = false;
+ if (!aNewArea.isEmpty())
+ {
+ ScRange aRange;
+ if ( (aRange.ParseAny(aNewArea, rDoc, rDoc.GetAddressConvention() ) & ScRefFlags::VALID) == ScRefFlags::VALID)
+ {
+ SetColRowData( aRange );
+ bValid = true;
+ }
+ }
+ if ( bValid )
+ {
+ m_xBtnAdd->set_sensitive(true);
+ m_xBtnColHead->set_sensitive(true);
+ m_xBtnRowHead->set_sensitive(true);
+ m_xEdAssign2->GetWidget()->set_sensitive(true);
+ m_xRbAssign2->GetWidget()->set_sensitive(true);
+ }
+ else
+ {
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnColHead->set_sensitive(false);
+ m_xBtnRowHead->set_sensitive(false);
+ m_xEdAssign2->GetWidget()->set_sensitive(false);
+ m_xRbAssign2->GetWidget()->set_sensitive(false);
+ }
+ m_xBtnRemove->set_sensitive(false);
+}
+
+// handler called when the data range has changed
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range2DataModifyHdl, formula::RefEdit&, void)
+{
+ OUString aNewData( m_xEdAssign2->GetText() );
+ if ( !aNewData.isEmpty() )
+ {
+ ScRange aRange;
+ if ( (aRange.ParseAny(aNewData, rDoc, rDoc.GetAddressConvention() ) & ScRefFlags::VALID) == ScRefFlags::VALID)
+ {
+ AdjustColRowData( aRange );
+ m_xBtnAdd->set_sensitive(true);
+ }
+ else
+ m_xBtnAdd->set_sensitive(false);
+ }
+ else
+ {
+ m_xBtnAdd->set_sensitive(false);
+ }
+}
+
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, ColRowToggleHdl, weld::Toggleable&, void)
+{
+ if (m_xBtnColHead->get_active())
+ {
+ // handler for the radio button for columns, adjust ranges
+ if ( theCurArea.aStart.Row() == 0 && theCurArea.aEnd.Row() == rDoc.MaxRow() )
+ {
+ theCurArea.aEnd.SetRow( rDoc.MaxRow() - 1 );
+ OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
+ m_xEdAssign->SetText( aStr );
+ }
+ ScRange aRange( theCurData );
+ aRange.aStart.SetRow( std::min( static_cast<tools::Long>(theCurArea.aEnd.Row() + 1), static_cast<tools::Long>(rDoc.MaxRow()) ) );
+ aRange.aEnd.SetRow( rDoc.MaxRow() );
+ AdjustColRowData( aRange );
+ }
+ else if (m_xBtnRowHead->get_active())
+ {
+ // handler for the radio button for columns, adjust range
+ if ( theCurArea.aStart.Col() == 0 && theCurArea.aEnd.Col() == rDoc.MaxCol() )
+ {
+ theCurArea.aEnd.SetCol( rDoc.MaxCol() - 1 );
+ OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
+ m_xEdAssign->SetText( aStr );
+ }
+ ScRange aRange( theCurData );
+ aRange.aStart.SetCol( static_cast<SCCOL>(std::min( static_cast<tools::Long>(theCurArea.aEnd.Col() + 1), static_cast<tools::Long>(rDoc.MaxCol()) )) );
+ aRange.aEnd.SetCol( rDoc.MaxCol() );
+ AdjustColRowData( aRange );
+ }
+}
+
+IMPL_LINK( ScColRowNameRangesDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
+{
+ if (&rCtrl == m_xEdAssign.get())
+ m_pEdActive = m_xEdAssign.get();
+ else if (&rCtrl == m_xEdAssign2.get())
+ m_pEdActive = m_xEdAssign2.get();
+ else
+ m_pEdActive = nullptr;
+
+ if( m_pEdActive )
+ m_pEdActive->SelectAll();
+}
+
+IMPL_LINK( ScColRowNameRangesDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
+{
+ if (&rCtrl == m_xRbAssign.get())
+ m_pEdActive = m_xEdAssign.get();
+ else if (&rCtrl == m_xRbAssign2.get())
+ m_pEdActive = m_xEdAssign2.get();
+ else
+ m_pEdActive = nullptr;
+
+ if( m_pEdActive )
+ m_pEdActive->SelectAll();
+}
+
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, LoseEditFocusHdl, formula::RefEdit&, void)
+{
+ bDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(ScColRowNameRangesDlg, LoseButtonFocusHdl, formula::RefButton&, void)
+{
+ bDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/datafdlg.cxx b/sc/source/ui/miscdlgs/datafdlg.cxx
new file mode 100644
index 000000000..0ed421cba
--- /dev/null
+++ b/sc/source/ui/miscdlgs/datafdlg.cxx
@@ -0,0 +1,355 @@
+/* -*- 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/.
+ */
+
+#undef SC_DLLIMPLEMENTATION
+
+#include <datafdlg.hxx>
+#include <viewdata.hxx>
+#include <docsh.hxx>
+#include <tabvwsh.hxx>
+
+#include <vcl/svapp.hxx>
+#include <osl/diagnose.h>
+
+ScDataFormDlg::ScDataFormDlg(weld::Window* pParent, ScTabViewShell* pTabViewShellOri)
+ : GenericDialogController(pParent, "modules/scalc/ui/dataform.ui", "DataFormDialog")
+ , pTabViewShell(pTabViewShellOri)
+ , aColLength(0)
+ , nCurrentRow(0)
+ , nStartCol(0)
+ , nEndCol(0)
+ , nStartRow(0)
+ , nEndRow(0)
+ , nTab(0)
+ , m_xBtnNew(m_xBuilder->weld_button("new"))
+ , m_xBtnDelete(m_xBuilder->weld_button("delete"))
+ , m_xBtnRestore(m_xBuilder->weld_button("restore"))
+ , m_xBtnPrev(m_xBuilder->weld_button("prev"))
+ , m_xBtnNext(m_xBuilder->weld_button("next"))
+ , m_xBtnClose(m_xBuilder->weld_button("close"))
+ , m_xSlider(m_xBuilder->weld_scrolled_window("scrollbar", true))
+ , m_xGrid(m_xBuilder->weld_container("grid"))
+ , m_xFixedText(m_xBuilder->weld_label("label"))
+{
+ sNewRecord = m_xFixedText->get_label();
+
+ //read header from current document, and add new controls
+ OSL_ENSURE( pTabViewShell, "pTabViewShell is NULL! :-/" );
+ ScViewData& rViewData = pTabViewShell->GetViewData();
+
+ pDoc = &rViewData.GetDocument();
+
+ {
+ ScRange aRange;
+ rViewData.GetSimpleArea( aRange );
+ ScAddress aStart = aRange.aStart;
+ ScAddress aEnd = aRange.aEnd;
+
+ nStartCol = aStart.Col();
+ nEndCol = aEnd.Col();
+ nStartRow = aStart.Row();
+ nEndRow = aEnd.Row();
+
+ nTab = rViewData.GetTabNo();
+ bool bNoSelection(false);
+ //if there is no selection
+ if ((nStartCol == nEndCol) && (nStartRow == nEndRow))
+ bNoSelection = true;
+
+ if (bNoSelection)
+ {
+ //find last not blank cell in row
+ for (int i=1;i<=MAX_DATAFORM_COLS;i++)
+ {
+ nEndCol++;
+ OUString aColName = pDoc->GetString(nEndCol, nStartRow, nTab);
+ int nColWidth = pDoc->GetColWidth( nEndCol, nTab );
+ if (aColName.isEmpty() && nColWidth)
+ {
+ nEndCol--;
+ break;
+ }
+ }
+
+ //find first not blank cell in row
+ for (int i=1;i<=MAX_DATAFORM_COLS;i++)
+ {
+ if (nStartCol <= 0)
+ break;
+ nStartCol--;
+
+ OUString aColName = pDoc->GetString(nStartCol, nStartRow, nTab);
+ int nColWidth = pDoc->GetColWidth( nEndCol, nTab );
+ if (aColName.isEmpty() && nColWidth)
+ {
+ nStartCol++;
+ break;
+ }
+ }
+
+ //skip leading hide column
+ for (int i=1;i<=MAX_DATAFORM_COLS;i++)
+ {
+ int nColWidth = pDoc->GetColWidth( nStartCol, nTab );
+ if (nColWidth)
+ break;
+ nStartCol++;
+ }
+
+ if (nEndCol < nStartCol)
+ nEndCol = nStartCol;
+
+ //find last not blank cell in row
+ for (int i=1;i<=MAX_DATAFORM_ROWS;i++)
+ {
+ nEndRow++;
+ OUString aColName = pDoc->GetString(nStartCol, nEndRow, nTab);
+ if (aColName.isEmpty())
+ {
+ nEndRow--;
+ break;
+ }
+ }
+
+ //find first not blank cell in row
+ for (int i=1;i<=MAX_DATAFORM_ROWS;i++)
+ {
+ if (nStartRow <= 0)
+ break;
+ nStartRow--;
+
+ OUString aColName = pDoc->GetString(nStartCol, nStartRow, nTab);
+ if (aColName.isEmpty())
+ {
+ nStartRow++;
+ break;
+ }
+ }
+
+ if (nEndRow < nStartRow)
+ nEndRow = nStartRow;
+ }
+
+ nCurrentRow = nStartRow + 1;
+
+ aColLength = nEndCol - nStartCol + 1;
+
+ //new the controls
+ m_aEntries.reserve(aColLength);
+
+ sal_Int32 nGridRow = 0;
+ for(sal_uInt16 nIndex = 0; nIndex < aColLength; ++nIndex)
+ {
+ OUString aFieldName = pDoc->GetString(nIndex + nStartCol, nStartRow, nTab);
+ int nColWidth = pDoc->GetColWidth( nIndex + nStartCol, nTab );
+ if (nColWidth)
+ {
+ m_aEntries.emplace_back(new ScDataFormFragment(m_xGrid.get(), nGridRow));
+
+ ++nGridRow;
+
+ m_aEntries[nIndex]->m_xLabel->set_label(aFieldName);
+ m_aEntries[nIndex]->m_xLabel->show();
+ m_aEntries[nIndex]->m_xEdit->show();
+ }
+ else
+ {
+ m_aEntries.emplace_back(nullptr );
+ }
+ if (m_aEntries[nIndex] != nullptr)
+ {
+ m_aEntries[nIndex]->m_xEdit->connect_changed(LINK( this, ScDataFormDlg, Impl_DataModifyHdl));
+ m_aEntries[nIndex]->m_xEdit->save_value();
+ }
+ }
+ }
+
+ FillCtrls();
+
+ m_xSlider->vadjustment_configure(0, 0, nEndRow - nStartRow + 1, 1, 10, 1);
+
+ m_xBtnNew->connect_clicked(LINK( this, ScDataFormDlg, Impl_NewHdl));
+ m_xBtnPrev->connect_clicked(LINK( this, ScDataFormDlg, Impl_PrevHdl));
+ m_xBtnNext->connect_clicked(LINK( this, ScDataFormDlg, Impl_NextHdl));
+
+ m_xBtnRestore->connect_clicked(LINK( this, ScDataFormDlg, Impl_RestoreHdl));
+ m_xBtnDelete->connect_clicked(LINK( this, ScDataFormDlg, Impl_DeleteHdl));
+ m_xBtnClose->connect_clicked(LINK( this, ScDataFormDlg, Impl_CloseHdl));
+
+ m_xSlider->connect_vadjustment_changed(LINK( this, ScDataFormDlg, Impl_ScrollHdl));
+
+ SetButtonState();
+}
+
+ScDataFormDlg::~ScDataFormDlg()
+{
+}
+
+void ScDataFormDlg::FillCtrls()
+{
+ for (sal_uInt16 i = 0; i < aColLength; ++i)
+ {
+ if (m_aEntries[i])
+ {
+ if (nCurrentRow<=nEndRow && pDoc)
+ {
+ OUString aFieldName(pDoc->GetString(i + nStartCol, nCurrentRow, nTab));
+ m_aEntries[i]->m_xEdit->set_text(aFieldName);
+ }
+ else
+ m_aEntries[i]->m_xEdit->set_text(OUString());
+ }
+ }
+
+ if (nCurrentRow <= nEndRow)
+ {
+ OUString sLabel =
+ OUString::number(static_cast<sal_Int32>(nCurrentRow - nStartRow)) +
+ " / " +
+ OUString::number(static_cast<sal_Int32>(nEndRow - nStartRow));
+ m_xFixedText->set_label(sLabel);
+ }
+ else
+ m_xFixedText->set_label(sNewRecord);
+
+ m_xSlider->vadjustment_set_value(nCurrentRow-nStartRow-1);
+}
+
+IMPL_LINK( ScDataFormDlg, Impl_DataModifyHdl, weld::Entry&, rEdit, void)
+{
+ if (rEdit.get_value_changed_from_saved())
+ m_xBtnRestore->set_sensitive(true);
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_NewHdl, weld::Button&, void)
+{
+ ScViewData& rViewData = pTabViewShell->GetViewData();
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+ if ( !pDoc )
+ return;
+
+ bool bHasData = std::any_of(m_aEntries.begin(), m_aEntries.end(),
+ [](const std::unique_ptr<ScDataFormFragment>& rElem) { return (rElem != nullptr) && (!rElem->m_xEdit->get_text().isEmpty()); });
+
+ if ( !bHasData )
+ return;
+
+ pTabViewShell->DataFormPutData(nCurrentRow, nStartRow, nStartCol, nEndRow, nEndCol, m_aEntries, aColLength);
+ nCurrentRow++;
+ if (nCurrentRow >= nEndRow + 2)
+ {
+ nEndRow++;
+ m_xSlider->vadjustment_set_upper(nEndRow - nStartRow + 1);
+ }
+ SetButtonState();
+ FillCtrls();
+ pDocSh->SetDocumentModified();
+ pDocSh->PostPaintGridAll();
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_PrevHdl, weld::Button&, void)
+{
+ if (pDoc)
+ {
+ if ( nCurrentRow > nStartRow +1 )
+ nCurrentRow--;
+
+ SetButtonState();
+ FillCtrls();
+ }
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_NextHdl, weld::Button&, void)
+{
+ if (pDoc)
+ {
+ if ( nCurrentRow <= nEndRow)
+ nCurrentRow++;
+
+ SetButtonState();
+ FillCtrls();
+ }
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_RestoreHdl, weld::Button&, void)
+{
+ if (pDoc)
+ {
+ FillCtrls();
+ }
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_DeleteHdl, weld::Button&, void)
+{
+ ScViewData& rViewData = pTabViewShell->GetViewData();
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+ if (!pDoc)
+ return;
+
+ ScRange aRange(nStartCol, nCurrentRow, nTab, nEndCol, nCurrentRow, nTab);
+ pDoc->DeleteRow(aRange);
+ nEndRow--;
+
+ SetButtonState();
+ pDocSh->GetUndoManager()->Clear();
+
+ FillCtrls();
+ pDocSh->SetDocumentModified();
+ pDocSh->PostPaintGridAll();
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_CloseHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_CANCEL);
+}
+
+IMPL_LINK_NOARG(ScDataFormDlg, Impl_ScrollHdl, weld::ScrolledWindow&, void)
+{
+ auto nOffset = m_xSlider->vadjustment_get_value();
+ nCurrentRow = nStartRow + nOffset + 1;
+ SetButtonState();
+ FillCtrls();
+}
+
+void ScDataFormDlg::SetButtonState()
+{
+ if (nCurrentRow > nEndRow)
+ {
+ m_xBtnDelete->set_sensitive( false );
+ m_xBtnNext->set_sensitive( false );
+ }
+ else
+ {
+ m_xBtnDelete->set_sensitive(true);
+ m_xBtnNext->set_sensitive(true);
+ }
+
+ if (nCurrentRow == nStartRow + 1)
+ m_xBtnPrev->set_sensitive( false );
+ else
+ m_xBtnPrev->set_sensitive(true);
+
+ m_xBtnRestore->set_sensitive( false );
+ if (!m_aEntries.empty() && m_aEntries[0] != nullptr)
+ m_aEntries[0]->m_xEdit->grab_focus();
+}
+
+ScDataFormFragment::ScDataFormFragment(weld::Container* pGrid, int nLine)
+ : m_xBuilder(Application::CreateBuilder(pGrid, "modules/scalc/ui/dataformfragment.ui"))
+ , m_xLabel(m_xBuilder->weld_label("label"))
+ , m_xEdit(m_xBuilder->weld_entry("entry"))
+{
+ m_xLabel->set_grid_left_attach(0);
+ m_xLabel->set_grid_top_attach(nLine);
+
+ m_xEdit->set_grid_left_attach(1);
+ m_xEdit->set_grid_top_attach(nLine);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/dataproviderdlg.cxx b/sc/source/ui/miscdlgs/dataproviderdlg.cxx
new file mode 100644
index 000000000..f26e2ae7a
--- /dev/null
+++ b/sc/source/ui/miscdlgs/dataproviderdlg.cxx
@@ -0,0 +1,1125 @@
+/* -*- 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 <dataproviderdlg.hxx>
+
+#include <document.hxx>
+#include <dataprovider.hxx>
+#include <datatransformation.hxx>
+#include <datamapper.hxx>
+#include <dbdata.hxx>
+
+#include <comphelper/string.hxx>
+#include <sal/log.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <unotools/charclass.hxx>
+#include <vcl/svapp.hxx>
+
+#include <utility>
+
+class ScDataTransformationBaseControl
+{
+protected:
+ std::unique_ptr<weld::Builder> mxBuilder;
+ std::unique_ptr<weld::Container> mxGrid;
+ weld::Container* mpContainer;
+
+ sal_uInt32 mnIndex;
+
+public:
+ ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex);
+ virtual ~ScDataTransformationBaseControl();
+
+ void updateIndex(sal_uInt32 nIndex) { mnIndex = nIndex; }
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() = 0;
+
+ static SCROW getLastRow(const ScDocument& rDoc);
+ static SCCOL getLastCol(const ScDocument& rDoc);
+};
+
+SCROW ScDataTransformationBaseControl::getLastRow(const ScDocument& rDoc)
+{
+ SCROW nEndRow = rDoc.MaxRow();
+ return rDoc.GetLastDataRow(0, 0, 0, nEndRow);
+}
+
+SCCOL ScDataTransformationBaseControl::getLastCol(const ScDocument& rDoc)
+{
+ for (SCCOL nCol = 1; nCol <= rDoc.MaxCol(); ++nCol)
+ {
+ if (rDoc.GetCellType(nCol, 0, 0) == CELLTYPE_NONE)
+ {
+ return static_cast<SCCOL>(nCol - 1 );
+ }
+ }
+ return rDoc.MaxCol();
+}
+
+ScDataTransformationBaseControl::ScDataTransformationBaseControl(weld::Container* pParent, const OUString& rUIFile, sal_uInt32 nIndex)
+ : mxBuilder(Application::CreateBuilder(pParent, rUIFile))
+ , mxGrid(mxBuilder->weld_container("grid"))
+ , mpContainer(pParent)
+ , mnIndex(nIndex)
+{
+}
+
+ScDataTransformationBaseControl::~ScDataTransformationBaseControl()
+{
+ mpContainer->move(mxGrid.get(), nullptr);
+}
+
+namespace {
+
+struct MenuData
+{
+ const char* aTransformationName;
+ std::function<void(ScDataProviderDlg*)> maCallback;
+};
+
+MenuData aTransformationData[] = {
+ { "Delete Column", &ScDataProviderDlg::deleteColumn },
+ { "Delete Row", &ScDataProviderDlg::deleteRowTransformation},
+ { "Swap Rows", &ScDataProviderDlg::swapRowsTransformation},
+ { "Split Column", &ScDataProviderDlg::splitColumn },
+ { "Merge Columns", &ScDataProviderDlg::mergeColumns },
+ { "Text Transformation", &ScDataProviderDlg::textTransformation },
+ { "Sort Columns", &ScDataProviderDlg::sortTransformation },
+ { "Aggregate Functions", &ScDataProviderDlg::aggregateFunction},
+ { "Number Transformations", &ScDataProviderDlg::numberTransformation },
+ { "Replace Null Transformations", &ScDataProviderDlg::replaceNullTransformation },
+ { "Date & Time Transformations", &ScDataProviderDlg::dateTimeTransformation },
+ { "Find Replace Transformation", &ScDataProviderDlg::findReplaceTransformation}
+};
+
+class ScDeleteColumnTransformationControl : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxColumnNums;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScDeleteColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 aIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScDeleteColumnTransformationControl::ScDeleteColumnTransformationControl(
+ const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/deletecolumnentry.ui", nIndex)
+ , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScDeleteColumnTransformationControl, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScDeleteColumnTransformationControl::getTransformation()
+{
+ OUString aColumnString = mxColumnNums->get_text();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> ColNums;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ ColNums.insert(nCol - 1);
+ }
+
+ return std::make_shared<sc::ColumnRemoveTransformation>(std::move(ColNums));
+}
+
+class ScSplitColumnTransformationControl : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxSeparator;
+ std::unique_ptr<weld::Entry> mxNumColumns;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScSplitColumnTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScSplitColumnTransformationControl::ScSplitColumnTransformationControl(
+ const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex,
+ std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/splitcolumnentry.ui", nIndex)
+ , mxSeparator(mxBuilder->weld_entry("ed_separator"))
+ , mxNumColumns(mxBuilder->weld_entry("num_cols"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScSplitColumnTransformationControl, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScSplitColumnTransformationControl::getTransformation()
+{
+ OUString aSeparator = mxSeparator->get_text();
+ sal_Unicode cSeparator = aSeparator.isEmpty() ? ',' : aSeparator[0];
+ OUString aColStr = mxNumColumns->get_text();
+ SCCOL mnCol = -1;
+ sal_Int32 nCol = aColStr.toInt32();
+ if (nCol > 0 && nCol <= mpDoc->MaxCol())
+ mnCol = nCol - 1;
+ return std::make_shared<sc::SplitColumnTransformation>(mnCol, cSeparator);
+}
+
+class ScMergeColumnTransformationControl : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxSeparator;
+ std::unique_ptr<weld::Entry> mxEdColumns;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScMergeColumnTransformationControl(const ScDocument *pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScMergeColumnTransformationControl::ScMergeColumnTransformationControl(
+ const ScDocument* pDoc, weld::Container* pParent, SCCOL nStartCol, SCCOL nEndCol, sal_uInt32 nIndex,
+ std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/mergecolumnentry.ui", nIndex)
+ , mxSeparator(mxBuilder->weld_entry("ed_separator"))
+ , mxEdColumns(mxBuilder->weld_entry("ed_columns"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScMergeColumnTransformationControl, DeleteHdl));
+
+ OUStringBuffer aBuffer;
+
+ // map from zero based to one based column numbers
+ aBuffer.append(static_cast<sal_Int32>(nStartCol + 1));
+ for ( SCCOL nCol = nStartCol + 1; nCol <= nEndCol; ++nCol)
+ {
+ aBuffer.append(";" + OUString::number(nCol + 1));
+ }
+
+ mxEdColumns->set_text(aBuffer.makeStringAndClear());
+}
+
+std::shared_ptr<sc::DataTransformation> ScMergeColumnTransformationControl::getTransformation()
+{
+ OUString aColumnString = mxEdColumns->get_text();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> aMergedColumns;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ aMergedColumns.insert(nCol - 1);
+ }
+ return std::make_shared<sc::MergeColumnTransformation>(std::move(aMergedColumns), mxSeparator->get_text());
+}
+
+class ScSortTransformationControl : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::ComboBox> mxType;
+ std::unique_ptr<weld::Entry> mxEdColumns;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScSortTransformationControl(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScSortTransformationControl::ScSortTransformationControl(
+ const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/sorttransformationentry.ui", nIndex)
+ , mxType(mxBuilder->weld_combo_box("ed_ascending"))
+ , mxEdColumns(mxBuilder->weld_entry("ed_columns"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScSortTransformationControl, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScSortTransformationControl::getTransformation()
+{
+ OUString aColStr = mxEdColumns->get_text();
+ bool aIsAscending = mxType->get_active();
+ SCCOL aColumn = 0;
+ sal_Int32 nCol = aColStr.toInt32();
+ if (nCol > 0 && nCol <= mpDoc->MaxCol())
+ aColumn = nCol - 1; // translate from 1-based column notations to internal Calc one
+
+ ScSortParam aSortParam;
+ aSortParam.nRow1=0;
+ aSortParam.nRow2=getLastRow(*mpDoc);
+ aSortParam.nCol1=0;
+ aSortParam.nCol2=getLastCol(*mpDoc);
+ aSortParam.maKeyState[0].bDoSort = true;
+ aSortParam.maKeyState[0].nField = aColumn;
+ aSortParam.maKeyState[0].bAscending = aIsAscending;
+ return std::make_shared<sc::SortTransformation>(aSortParam);
+}
+
+class ScColumnTextTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxColumnNums;
+ std::unique_ptr<weld::ComboBox> mxType;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScColumnTextTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScColumnTextTransformation::ScColumnTextTransformation(
+ const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/texttransformationentry.ui", nIndex)
+ , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
+ , mxType(mxBuilder->weld_combo_box("ed_lst"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScColumnTextTransformation, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScColumnTextTransformation::getTransformation()
+{
+ OUString aColumnString = mxColumnNums->get_text();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> aColumns;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ aColumns.insert(nCol - 1);
+ }
+
+ sal_Int32 nPos = mxType->get_active();
+ switch (nPos)
+ {
+ case 0:
+ return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TO_LOWER);
+ case 1:
+ return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TO_UPPER);
+ case 2:
+ return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::CAPITALIZE);
+ case 3:
+ return std::make_shared<sc::TextTransformation>(std::move(aColumns),sc::TEXT_TRANSFORM_TYPE::TRIM);
+ default:
+ assert(false);
+ }
+
+ return nullptr;
+}
+
+class ScAggregateFunction : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxColumnNums;
+ std::unique_ptr<weld::ComboBox> mxType;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScAggregateFunction::ScAggregateFunction(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex,
+ std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/aggregatefunctionentry.ui", nIndex)
+ , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
+ , mxType(mxBuilder->weld_combo_box("ed_lst"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScAggregateFunction, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScAggregateFunction::getTransformation()
+{
+ OUString aColumnString = mxColumnNums->get_text();
+ sal_Int32 nPos = mxType->get_active();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> aColumns;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ aColumns.insert(nCol - 1);
+ }
+ switch (nPos)
+ {
+ case 0:
+ return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::SUM);
+ case 1:
+ return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::AVERAGE);
+ case 2:
+ return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::MIN);
+ case 3:
+ return std::make_shared<sc::AggregateFunction>(std::move(aColumns),sc::AGGREGATE_FUNCTION::MAX);
+ default:
+ assert(false);
+ }
+
+ return nullptr;
+}
+
+class ScNumberTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxColumnNums;
+ std::unique_ptr<weld::ComboBox> mxType;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScNumberTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScNumberTransformation::ScNumberTransformation(
+ const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/numbertransformationentry.ui", nIndex)
+ , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
+ , mxType(mxBuilder->weld_combo_box("ed_lst"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScNumberTransformation, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScNumberTransformation::getTransformation()
+{
+ OUString aColumnString = mxColumnNums->get_text();
+ sal_Int32 nPos = mxType->get_active();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> aColumns;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ aColumns.insert(nCol - 1);
+ }
+ switch (nPos)
+ {
+ case 0:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SIGN);
+ case 1:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND);
+ case 2:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND_UP);
+ case 3:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ROUND_DOWN);
+ case 4:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::ABSOLUTE);
+ case 5:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::LOG_E);
+ case 6:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::LOG_10);
+ case 7:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::CUBE);
+ case 8:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SQUARE);
+ case 9:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::SQUARE_ROOT);
+ case 10:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::EXPONENT);
+ case 11:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::IS_EVEN);
+ case 12:
+ return std::make_shared<sc::NumberTransformation>(std::move(aColumns),sc::NUMBER_TRANSFORM_TYPE::IS_ODD);
+ default:
+ assert(false);
+ }
+
+ return nullptr;
+}
+
+class ScReplaceNullTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxColumnNums;
+ std::unique_ptr<weld::Entry> mxReplaceString;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument *mpDoc;
+
+public:
+
+ ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScReplaceNullTransformation::ScReplaceNullTransformation(const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent,"modules/scalc/ui/replacenulltransformationentry.ui", nIndex)
+ , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
+ , mxReplaceString(mxBuilder->weld_entry("ed_str"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(aDeleteTransformation)
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScReplaceNullTransformation, DeleteHdl));
+}
+
+
+std::shared_ptr<sc::DataTransformation> ScReplaceNullTransformation::getTransformation()
+{
+ OUString aColumnString = mxColumnNums->get_text();
+ OUString aReplaceWithString = mxReplaceString->get_text();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> aColumns;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ aColumns.insert(nCol - 1);
+ }
+
+ return std::make_shared<sc::ReplaceNullTransformation>(std::move(aColumns),aReplaceWithString);
+}
+
+class ScDateTimeTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxColumnNums;
+ std::unique_ptr<weld::ComboBox> mxType;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+
+ ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScDateTimeTransformation::ScDateTimeTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent,"modules/scalc/ui/datetimetransformationentry.ui", nIndex)
+ , mxColumnNums(mxBuilder->weld_entry("ed_columns"))
+ , mxType(mxBuilder->weld_combo_box("ed_lst"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(aDeleteTransformation)
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this,ScDateTimeTransformation, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScDateTimeTransformation::getTransformation()
+{
+ OUString aColumnString = mxColumnNums->get_text();
+ sal_Int32 nPos = mxType->get_active();
+ std::vector<OUString> aSplitColumns = comphelper::string::split(aColumnString, ';');
+ std::set<SCCOL> aColumns;
+ for (const auto& rColStr : aSplitColumns)
+ {
+ sal_Int32 nCol = rColStr.toInt32();
+ if (nCol <= 0)
+ continue;
+
+ if (nCol > mpDoc->MaxCol())
+ continue;
+
+ // translate from 1-based column notations to internal Calc one
+ aColumns.insert(nCol - 1);
+ }
+ switch (nPos)
+ {
+ case 0:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DATE_STRING);
+ case 1:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::YEAR);
+ case 2:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_YEAR);
+ case 3:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_YEAR);
+ case 4:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MONTH);
+ case 5:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MONTH_NAME);
+ case 6:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_MONTH);
+ case 7:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_MONTH);
+ case 8:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY);
+ case 9:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_WEEK);
+ case 10:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::DAY_OF_YEAR);
+ case 11:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::QUARTER);
+ case 12:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::START_OF_QUARTER);
+ case 13:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::END_OF_QUARTER);
+ case 14:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::HOUR);
+ case 15:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::MINUTE);
+ case 16:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::SECOND);
+ case 17:
+ return std::make_shared<sc::DateTimeTransformation>(std::move(aColumns),sc::DATETIME_TRANSFORMATION_TYPE::TIME);
+ default:
+ assert(false);
+ }
+
+ return nullptr;
+}
+
+class ScFindReplaceTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxFindString;
+ std::unique_ptr<weld::Entry> mxReplaceString;
+ std::unique_ptr<weld::Entry> mxEdColumns;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScFindReplaceTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScFindReplaceTransformation::ScFindReplaceTransformation(
+ const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex,
+ std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/findreplaceentry.ui", nIndex)
+ , mxFindString(mxBuilder->weld_entry("ed_find"))
+ , mxReplaceString(mxBuilder->weld_entry("ed_replace"))
+ , mxEdColumns(mxBuilder->weld_entry("ed_columns"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this, ScFindReplaceTransformation, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScFindReplaceTransformation::getTransformation()
+{
+ OUString aColStr = mxEdColumns->get_text();
+ SCCOL aColumn = -1;
+ sal_Int32 nCol = aColStr.toInt32();
+ if (nCol > 0 && nCol <= mpDoc->MaxCol())
+ aColumn = nCol - 1;
+ return std::make_shared<sc::FindReplaceTransformation>(aColumn, mxFindString->get_text(), mxReplaceString->get_text());
+}
+
+class ScDeleteRowTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxFindString;
+ std::unique_ptr<weld::Entry> mxEdColumns;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScDeleteRowTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScDeleteRowTransformation::ScDeleteRowTransformation(
+ const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex,
+ std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/deleterowentry.ui", nIndex)
+ , mxFindString(mxBuilder->weld_entry("ed_find"))
+ , mxEdColumns(mxBuilder->weld_entry("ed_columns"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this, ScDeleteRowTransformation, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScDeleteRowTransformation::getTransformation()
+{
+ OUString aColStr = mxEdColumns->get_text();
+ SCCOL aColumn = -1;
+ sal_Int32 nCol = aColStr.toInt32();
+ if (nCol > 0 && nCol <= mpDoc->MaxCol())
+ aColumn = nCol - 1;
+ return std::make_shared<sc::DeleteRowTransformation>(aColumn, mxFindString->get_text());
+}
+
+class ScSwapRowsTransformation : public ScDataTransformationBaseControl
+{
+private:
+ std::unique_ptr<weld::Entry> mxRow;
+ std::unique_ptr<weld::Entry> nxRow;
+ std::unique_ptr<weld::Button> mxDelete;
+ std::function<void(sal_uInt32&)> maDeleteTransformation;
+ const ScDocument* mpDoc;
+
+public:
+ ScSwapRowsTransformation(const ScDocument* pDoc, weld::Container* pParent, sal_uInt32 nIndex, std::function<void(sal_uInt32&)> aDeleteTransformation);
+
+ virtual std::shared_ptr<sc::DataTransformation> getTransformation() override;
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+};
+
+ScSwapRowsTransformation::ScSwapRowsTransformation(
+ const ScDocument *pDoc, weld::Container* pParent, sal_uInt32 nIndex,
+ std::function<void(sal_uInt32&)> aDeleteTransformation)
+ : ScDataTransformationBaseControl(pParent, "modules/scalc/ui/swaprowsentry.ui", nIndex)
+ , mxRow(mxBuilder->weld_entry("ed_row1"))
+ , nxRow(mxBuilder->weld_entry("ed_row2"))
+ , mxDelete(mxBuilder->weld_button("ed_delete"))
+ , maDeleteTransformation(std::move(aDeleteTransformation))
+ , mpDoc(pDoc)
+{
+ mxDelete->connect_clicked(LINK(this, ScSwapRowsTransformation, DeleteHdl));
+}
+
+std::shared_ptr<sc::DataTransformation> ScSwapRowsTransformation::getTransformation()
+{
+ OUString aRowStr = mxRow->get_text();
+ OUString bRowStr = nxRow->get_text();
+ SCROW aRow = -1;
+ SCROW bRow = -1;
+ sal_Int32 mRow = aRowStr.toInt32();
+ sal_Int32 nRow = bRowStr.toInt32();
+ if (mRow > 0 && mRow <= mpDoc->MaxRow())
+ aRow = mRow - 1;
+ if (nRow > 0 && nRow <= mpDoc->MaxRow())
+ bRow = nRow - 1;
+ return std::make_shared<sc::SwapRowsTransformation>(aRow, bRow);
+}
+
+}
+
+ScDataProviderDlg::ScDataProviderDlg(weld::Window* pParent, std::shared_ptr<ScDocument> pDoc,
+ const ScDocument* pDocument)
+ : GenericDialogController(pParent, "modules/scalc/ui/dataproviderdlg.ui", "dataproviderdlg")
+ , mxDoc(std::move(pDoc))
+ , mxBox(m_xBuilder->weld_container("data_table"))
+ , m_xTableParent(mxBox->CreateChildFrame())
+ , mxTable(VclPtr<ScDataTableView>::Create(m_xTableParent, mxDoc))
+ , mxDBRanges(m_xBuilder->weld_combo_box("select_db_range"))
+ , mxOKBtn(m_xBuilder->weld_button("okay"))
+ , mxCancelBtn(m_xBuilder->weld_button("cancel"))
+ , mxAddTransformationBtn(m_xBuilder->weld_button("add_transformation"))
+ , mxScroll(m_xBuilder->weld_scrolled_window("scroll"))
+ , mxTransformationList(m_xBuilder->weld_container("transformation_ctrl"))
+ , mxTransformationBox(m_xBuilder->weld_combo_box("transformation_box"))
+ , mxProviderList(m_xBuilder->weld_combo_box("provider_lst"))
+ , mxEditURL(m_xBuilder->weld_entry("ed_url"))
+ , mxEditID(m_xBuilder->weld_entry("ed_id"))
+ , mxApplyBtn(m_xBuilder->weld_button("apply"))
+ , mxBrowseBtn(m_xBuilder->weld_button("browse"))
+ , maIdle("ScDataProviderDlg maIdle")
+ , mnIndex(0)
+{
+ Size aPrefSize = mxTable->GetOptimalSize();
+ mxBox->set_size_request(aPrefSize.Width(), aPrefSize.Height());
+ mxTable->Show();
+
+ ScDBCollection* pDBCollection = pDocument->GetDBCollection();
+ auto& rNamedDBs = pDBCollection->getNamedDBs();
+ for (auto& rNamedDB : rNamedDBs)
+ {
+ mxDBRanges->append_text(rNamedDB->GetName());
+ }
+
+ for (const auto& i : aTransformationData)
+ {
+ mxTransformationBox->append_text(OUString::createFromAscii(i.aTransformationName));
+ }
+
+ pDBData = new ScDBData("data", 0, 0, 0, mxDoc->MaxCol(), mxDoc->MaxRow());
+ bool bSuccess = mxDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr<ScDBData>(pDBData));
+ SAL_WARN_IF(!bSuccess, "sc", "temporary warning");
+
+ auto aDataProvider = sc::DataProviderFactory::getDataProviders();
+ for (const auto& rDataProvider : aDataProvider)
+ {
+ mxProviderList->append_text(rDataProvider);
+ }
+
+ mxOKBtn->connect_clicked(LINK(this, ScDataProviderDlg, ApplyQuitHdl));
+ mxCancelBtn->connect_clicked(LINK(this, ScDataProviderDlg, CancelQuitHdl));
+ mxAddTransformationBtn->connect_clicked(LINK(this, ScDataProviderDlg, TransformationListHdl));
+ mxApplyBtn->connect_clicked(LINK(this, ScDataProviderDlg, ApplyBtnHdl));
+ mxBrowseBtn->connect_clicked(LINK(this, ScDataProviderDlg, BrowseBtnHdl));
+ mxTransformationBox->connect_changed(LINK(this, ScDataProviderDlg, TransformationSelectHdl));
+ mxProviderList->connect_changed(LINK(this, ScDataProviderDlg, ProviderSelectHdl));
+ mxEditID->connect_changed(LINK(this, ScDataProviderDlg, IDEditHdl));
+ mxEditURL->connect_changed(LINK(this, ScDataProviderDlg, URLEditHdl));
+
+ msApplyTooltip = mxApplyBtn->get_tooltip_text();
+ msAddTransformationToolTip = mxAddTransformationBtn->get_tooltip_text();
+ mxAddTransformationBtn->set_sensitive(false);
+ mxAddTransformationBtn->set_tooltip_text(OUString());
+ isValid();
+
+ maIdle.SetPriority( TaskPriority::LOWEST );
+ maIdle.SetInvokeHandler( LINK( this, ScDataProviderDlg, ScrollToEnd) );
+}
+
+ScDataProviderDlg::~ScDataProviderDlg()
+{
+ mxTable.disposeAndClear();
+ m_xTableParent->dispose();
+ m_xTableParent.clear();
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, ScrollToEnd, Timer*, void)
+{
+ mxScroll->vadjustment_set_value(mxScroll->vadjustment_get_upper());
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, ApplyQuitHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, CancelQuitHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_CANCEL);
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, TransformationListHdl, weld::Button&, void)
+{
+ OUString transformation_string = mxTransformationBox->get_active_text();
+ for (auto& i: aTransformationData)
+ {
+ if (transformation_string == OUString::createFromAscii(i.aTransformationName))
+ {
+ i.maCallback(this);
+ maIdle.Start();
+ return;
+ }
+ }
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, ProviderSelectHdl, weld::ComboBox&, void)
+{
+ isValid();
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, IDEditHdl, weld::Entry&, void)
+{
+ isValid();
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, URLEditHdl, weld::Entry&, void)
+{
+ isValid();
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, ApplyBtnHdl, weld::Button&, void)
+{
+ updateApplyBtn(true);
+ import(*mxDoc, true);
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, BrowseBtnHdl, weld::Button&, void)
+{
+ sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, m_xDialog.get());
+ aFileDialog.SetContext(sfx2::FileDialogHelper::CalcDataProvider);
+ if (aFileDialog.Execute() != ERRCODE_NONE)
+ return;
+
+ mxEditURL->set_text(aFileDialog.GetPath());
+ isValid();
+}
+
+IMPL_LINK_NOARG(ScDataProviderDlg, TransformationSelectHdl, weld::ComboBox&, void)
+{
+ mxAddTransformationBtn->set_sensitive(true);
+ mxAddTransformationBtn->set_tooltip_text(msAddTransformationToolTip);
+}
+
+sc::ExternalDataSource ScDataProviderDlg::getDataSource(ScDocument* pDoc)
+{
+ OUString aURL = mxEditURL->get_text();
+ OUString aProvider = mxProviderList->get_active_text();
+ sc::ExternalDataSource aSource(aURL, aProvider, pDoc);
+
+ OUString aID = mxEditID->get_text();
+ aSource.setID(aID);
+ return aSource;
+}
+
+void ScDataProviderDlg::isValid()
+{
+ bool bValid = !mxProviderList->get_active_text().isEmpty();
+ bValid &= !mxEditURL->get_text().isEmpty();
+ updateApplyBtn(bValid);
+}
+
+void ScDataProviderDlg::updateApplyBtn(bool bValidConfig)
+{
+ if (!bValidConfig)
+ {
+ mxApplyBtn->set_sensitive(false);
+ mxApplyBtn->set_tooltip_text(OUString());
+ return;
+ }
+
+ mxApplyBtn->set_sensitive(true);
+ mxApplyBtn->set_tooltip_text(msApplyTooltip);
+}
+
+void ScDataProviderDlg::deleteColumn()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScDeleteColumnTransformationControl>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::splitColumn()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScSplitColumnTransformationControl>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::mergeColumns()
+{
+ SCCOL nStartCol = -1;
+ SCCOL nEndCol = -1;
+ mxTable->getColRange(nStartCol, nEndCol);
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScMergeColumnTransformationControl>(mxDoc.get(), mxTransformationList.get(), nStartCol, nEndCol, mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::textTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScColumnTextTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::sortTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScSortTransformationControl>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::aggregateFunction()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScAggregateFunction>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::numberTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScNumberTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::replaceNullTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScReplaceNullTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::dateTimeTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList,this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScDateTimeTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::findReplaceTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList, this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScFindReplaceTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::deleteRowTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList, this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScDeleteRowTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+void ScDataProviderDlg::swapRowsTransformation()
+{
+ std::function<void(sal_uInt32&)> adeleteTransformation = std::bind(&ScDataProviderDlg::deletefromList, this, std::placeholders::_1);
+ maControls.emplace_back(std::make_unique<ScSwapRowsTransformation>(mxDoc.get(), mxTransformationList.get(), mnIndex++, adeleteTransformation));
+}
+
+namespace {
+
+bool hasDBName(const OUString& rName, ScDBCollection* pDBCollection)
+{
+ if (pDBCollection->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rName)))
+ return true;
+
+ return false;
+}
+
+}
+
+void ScDataProviderDlg::import(ScDocument& rDoc, bool bInternal)
+{
+ sc::ExternalDataSource aSource = getDataSource(&rDoc);
+
+ for (size_t i = 0; i < maControls.size(); ++i)
+ {
+ ScDataTransformationBaseControl* pTransformationCtrl = maControls[i].get();
+ aSource.AddDataTransformation(pTransformationCtrl->getTransformation());
+ }
+ if (bInternal)
+ aSource.setDBData(pDBData->GetName());
+ else
+ {
+ aSource.setDBData(mxDBRanges->get_active_text());
+ if (!hasDBName(aSource.getDBName(), rDoc.GetDBCollection()))
+ return;
+ rDoc.GetExternalDataMapper().insertDataSource(aSource);
+ }
+ aSource.refresh(&rDoc, true);
+ mxTable->Invalidate();
+}
+
+void ScDataProviderDlg::deletefromList(sal_uInt32 nIndex)
+{
+ auto itr = maControls.erase(maControls.begin() + nIndex);
+ while (itr != maControls.end())
+ {
+ (*itr)->updateIndex(nIndex++);
+ ++itr;
+ }
+ --mnIndex;
+}
+
+IMPL_LINK_NOARG(ScDeleteColumnTransformationControl, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScSplitColumnTransformationControl, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScMergeColumnTransformationControl, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScNumberTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScAggregateFunction, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScSortTransformationControl, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScColumnTextTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScReplaceNullTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScDateTimeTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScFindReplaceTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScDeleteRowTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+
+IMPL_LINK_NOARG(ScSwapRowsTransformation, DeleteHdl, weld::Button&, void)
+{
+ maDeleteTransformation(mnIndex);
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
new file mode 100644
index 000000000..cd03a3e66
--- /dev/null
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -0,0 +1,178 @@
+/* -*- 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 <datastreamdlg.hxx>
+
+#include <sfx2/filedlghelper.hxx>
+#include <svtools/inettbc.hxx>
+#include <address.hxx>
+#include <docsh.hxx>
+#include <datastream.hxx>
+
+namespace sc
+{
+DataStreamDlg::DataStreamDlg(ScDocShell* pDocShell, weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/datastreams.ui", "DataStreamDialog")
+ , m_pDocShell(pDocShell)
+ , m_xCbUrl(new SvtURLBox(m_xBuilder->weld_combo_box("url")))
+ , m_xBtnBrowse(m_xBuilder->weld_button("browse"))
+ , m_xRBValuesInLine(m_xBuilder->weld_radio_button("valuesinline"))
+ , m_xRBAddressValue(m_xBuilder->weld_radio_button("addressvalue"))
+ , m_xCBRefreshOnEmpty(m_xBuilder->weld_check_button("refresh_ui"))
+ , m_xRBDataDown(m_xBuilder->weld_radio_button("datadown"))
+ , m_xRBRangeDown(m_xBuilder->weld_radio_button("rangedown"))
+ , m_xRBNoMove(m_xBuilder->weld_radio_button("nomove"))
+ , m_xRBMaxLimit(m_xBuilder->weld_radio_button("maxlimit"))
+ , m_xRBUnlimited(m_xBuilder->weld_radio_button("unlimited"))
+ , m_xEdRange(m_xBuilder->weld_entry("range"))
+ , m_xEdLimit(m_xBuilder->weld_entry("limit"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xVclFrameLimit(m_xBuilder->weld_frame("framelimit"))
+ , m_xVclFrameMove(m_xBuilder->weld_frame("framemove"))
+{
+ m_xCbUrl->connect_changed(LINK(this, DataStreamDlg, UpdateComboBoxHdl));
+ m_xRBAddressValue->connect_toggled(LINK(this, DataStreamDlg, UpdateClickHdl));
+ m_xRBAddressValue->set_sensitive(false);
+ m_xRBNoMove->hide();
+ m_xRBValuesInLine->connect_toggled(LINK(this, DataStreamDlg, UpdateClickHdl));
+ m_xEdRange->connect_changed(LINK(this, DataStreamDlg, UpdateHdl));
+ m_xBtnBrowse->connect_clicked(LINK(this, DataStreamDlg, BrowseHdl));
+ UpdateEnable();
+}
+
+DataStreamDlg::~DataStreamDlg() {}
+
+IMPL_LINK_NOARG(DataStreamDlg, BrowseHdl, weld::Button&, void)
+{
+ sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, m_xDialog.get());
+ aFileDialog.SetContext(sfx2::FileDialogHelper::CalcDataStream);
+ if (aFileDialog.Execute() != ERRCODE_NONE)
+ return;
+
+ m_xCbUrl->set_entry_text(aFileDialog.GetPath());
+ UpdateEnable();
+}
+
+IMPL_LINK_NOARG(DataStreamDlg, UpdateClickHdl, weld::Toggleable&, void) { UpdateEnable(); }
+
+IMPL_LINK_NOARG(DataStreamDlg, UpdateComboBoxHdl, weld::ComboBox&, void) { UpdateEnable(); }
+
+IMPL_LINK_NOARG(DataStreamDlg, UpdateHdl, weld::Entry&, void) { UpdateEnable(); }
+
+void DataStreamDlg::UpdateEnable()
+{
+ bool bOk = !m_xCbUrl->GetURL().isEmpty();
+ if (m_xRBAddressValue->get_active())
+ {
+ m_xVclFrameLimit->set_sensitive(false);
+ m_xVclFrameMove->set_sensitive(false);
+ m_xEdRange->set_sensitive(false);
+ }
+ else
+ {
+ m_xVclFrameLimit->set_sensitive(true);
+ m_xVclFrameMove->set_sensitive(true);
+ m_xEdRange->set_sensitive(true);
+ if (bOk)
+ {
+ // Check the given range to make sure it's valid.
+ ScRange aTest = GetStartRange();
+ if (!aTest.IsValid())
+ bOk = false;
+ }
+ }
+ m_xBtnOk->set_sensitive(bOk);
+ // setOptimalLayoutSize();
+}
+
+ScRange DataStreamDlg::GetStartRange()
+{
+ OUString aStr = m_xEdRange->get_text();
+ ScDocument& rDoc = m_pDocShell->GetDocument();
+ ScRange aRange;
+ ScRefFlags nRes = aRange.Parse(aStr, rDoc, rDoc.GetAddressConvention());
+ if (((nRes & ScRefFlags::VALID) == ScRefFlags::ZERO) || !aRange.IsValid())
+ {
+ // Invalid range.
+ aRange.SetInvalid();
+ return aRange;
+ }
+
+ // Make sure it's only one row tall.
+ if (aRange.aStart.Row() != aRange.aEnd.Row())
+ aRange.SetInvalid();
+
+ return aRange;
+}
+
+void DataStreamDlg::Init(const DataStream& rStrm)
+{
+ m_xCbUrl->set_entry_text(rStrm.GetURL());
+ ScDocument& rDoc = m_pDocShell->GetDocument();
+
+ ScRange aRange = rStrm.GetRange();
+ ScRange aTopRange = aRange;
+ aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
+ OUString aStr = aTopRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention());
+ m_xEdRange->set_text(aStr);
+ SCROW nRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+
+ if (aRange.aEnd.Row() == rDoc.MaxRow())
+ m_xRBUnlimited->set_active(true);
+ else
+ {
+ m_xRBMaxLimit->set_active(true);
+ m_xEdLimit->set_text(OUString::number(nRows));
+ }
+
+ DataStream::MoveType eMove = rStrm.GetMove();
+ switch (eMove)
+ {
+ case DataStream::MOVE_DOWN:
+ m_xRBDataDown->set_active(true);
+ break;
+ case DataStream::RANGE_DOWN:
+ m_xRBRangeDown->set_active(true);
+ break;
+ case DataStream::MOVE_UP:
+ case DataStream::NO_MOVE:
+ default:;
+ }
+
+ m_xCBRefreshOnEmpty->set_active(rStrm.IsRefreshOnEmptyLine());
+
+ UpdateEnable();
+}
+
+void DataStreamDlg::StartStream()
+{
+ ScRange aStartRange = GetStartRange();
+ if (!aStartRange.IsValid())
+ // Don't start the stream without a valid range.
+ return;
+
+ sal_Int32 nLimit = 0;
+ if (m_xRBMaxLimit->get_active())
+ nLimit = m_xEdLimit->get_text().toInt32();
+ OUString rURL = m_xCbUrl->get_active_text();
+ sal_uInt32 nSettings = 0;
+ if (m_xRBValuesInLine->get_active())
+ nSettings |= DataStream::VALUES_IN_LINE;
+
+ DataStream::MoveType eMove
+ = m_xRBRangeDown->get_active() ? DataStream::RANGE_DOWN : DataStream::MOVE_DOWN;
+
+ DataStream* pStream = DataStream::Set(m_pDocShell, rURL, aStartRange, nLimit, eMove, nSettings);
+ pStream->SetRefreshOnEmptyLine(m_xCBRefreshOnEmpty->get_active());
+ DataStream::MakeToolbarVisible();
+ pStream->StartImport();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/datatableview.cxx b/sc/source/ui/miscdlgs/datatableview.cxx
new file mode 100644
index 000000000..d74df0e81
--- /dev/null
+++ b/sc/source/ui/miscdlgs/datatableview.cxx
@@ -0,0 +1,320 @@
+/* -*- 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 <datatableview.hxx>
+
+#include <document.hxx>
+#include <utility>
+#include <viewdata.hxx>
+#include <output.hxx>
+#include <fillinfo.hxx>
+#include <table.hxx>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/scrbar.hxx>
+#include <vcl/seleng.hxx>
+#include <sal/log.hxx>
+
+constexpr double nPPTX = 0.06666;
+constexpr double nPPTY = 0.06666;
+
+constexpr sal_uInt16 nRowHeaderWidth = 100;
+constexpr sal_uInt16 nColHeaderHeight = 20;
+constexpr sal_uInt16 nScrollBarSize = 10;
+
+ScDataTableColView::ScDataTableColView(vcl::Window* pParent, ScDocument* pDoc, SelectionEngine* pSelectionEngine):
+ ScHeaderControl(pParent, pSelectionEngine, pDoc->MaxCol()+1, false, nullptr),
+ mpDoc(pDoc),
+ mnCol(0)
+{
+}
+
+void ScDataTableColView::SetPos(SCCOLROW nCol)
+{
+ mnCol = nCol;
+}
+
+SCCOLROW ScDataTableColView::GetPos() const
+{
+ return mnCol;
+}
+
+sal_uInt16 ScDataTableColView::GetEntrySize(SCCOLROW nPos) const
+{
+ return ScViewData::ToPixel(mpDoc->GetColWidth(nPos, 0), nPPTX);
+}
+
+OUString ScDataTableColView::GetEntryText(SCCOLROW nPos) const
+{
+ return "Col: " + OUString::number(nPos + 1);
+}
+
+bool ScDataTableColView::IsLayoutRTL() const
+{
+ return false;
+}
+
+void ScDataTableColView::SetEntrySize(SCCOLROW nPos, sal_uInt16 nColWidth)
+{
+ mpDoc->SetColWidthOnly(nPos, 0, nColWidth/nPPTX);
+}
+
+void ScDataTableColView::HideEntries(SCCOLROW nPos, SCCOLROW nEndPos)
+{
+ for (SCCOLROW nCol = nPos; nCol <= nEndPos; ++nCol)
+ {
+ mpDoc->ShowCol(nCol, 0, false);
+ }
+}
+
+
+ScDataTableRowView::ScDataTableRowView(vcl::Window* pParent, ScDocument* pDoc, SelectionEngine* pSelectionEngine):
+ ScHeaderControl(pParent, pSelectionEngine, pDoc->MaxRow()+1, true, nullptr),
+ mpDoc(pDoc),
+ mnRow(0)
+{
+}
+
+void ScDataTableRowView::SetPos(SCCOLROW nRow)
+{
+ mnRow = nRow;
+}
+
+SCCOLROW ScDataTableRowView::GetPos() const
+{
+ return mnRow;
+}
+
+sal_uInt16 ScDataTableRowView::GetEntrySize(SCCOLROW nPos) const
+{
+ return ScViewData::ToPixel(mpDoc->GetRowHeight(nPos, SCTAB(0), true), nPPTX);
+}
+
+OUString ScDataTableRowView::GetEntryText(SCCOLROW nPos) const
+{
+ return OUString::number(nPos + 1);
+}
+
+bool ScDataTableRowView::IsLayoutRTL() const
+{
+ return false;
+}
+
+void ScDataTableRowView::SetEntrySize(SCCOLROW nPos, sal_uInt16 nColWidth)
+{
+ mpDoc->SetRowHeight(nPos, 0, nColWidth/nPPTX);
+}
+
+void ScDataTableRowView::HideEntries(SCCOLROW nPos, SCCOLROW nEndPos)
+{
+ for (SCCOLROW nCol = nPos; nCol <= nEndPos; ++nCol)
+ {
+ mpDoc->ShowRow(nCol, 0, false);
+ }
+}
+
+ScDataTableView::ScDataTableView(const css::uno::Reference<css::awt::XWindow> &rParent, std::shared_ptr<ScDocument> pDoc) :
+ Control(VCLUnoHelper::GetWindow(rParent)),
+ mpDoc(std::move(pDoc)),
+ mpSelectionEngine(new SelectionEngine(this)),
+ mpTopLeft(VclPtr<ScrollBarBox>::Create(this, WB_SIZEABLE)),
+ mpColView(VclPtr<ScDataTableColView>::Create(this, mpDoc.get(), mpSelectionEngine.get())),
+ mpRowView(VclPtr<ScDataTableRowView>::Create(this, mpDoc.get(), mpSelectionEngine.get())),
+ mpVScroll(VclPtr<ScrollBar>::Create(this, WinBits(WB_VSCROLL | WB_DRAG))),
+ mpHScroll(VclPtr<ScrollBar>::Create(this, WinBits(WB_HSCROLL | WB_DRAG))),
+ mnFirstVisibleRow(0),
+ mnFirstVisibleCol(0)
+{
+ mpTopLeft->setPosSizePixel(0, 0, nRowHeaderWidth, nColHeaderHeight);
+ mpColView->setPosSizePixel(nRowHeaderWidth, 0, nRowHeaderWidth, nColHeaderHeight);
+ mpRowView->setPosSizePixel(0, nColHeaderHeight, nRowHeaderWidth, nColHeaderHeight);
+
+ mpVScroll->SetRangeMin(0);
+ mpVScroll->SetRangeMax(100);
+ mpVScroll->SetEndScrollHdl(LINK(this, ScDataTableView, ScrollHdl));
+
+ mpHScroll->SetRangeMin(0);
+ mpHScroll->SetRangeMax(50);
+ mpHScroll->SetEndScrollHdl(LINK(this, ScDataTableView, ScrollHdl));
+
+ mpTopLeft->Show();
+ mpColView->Show();
+ mpRowView->Show();
+ mpVScroll->Show();
+ mpHScroll->Show();
+}
+
+ScDataTableView::~ScDataTableView()
+{
+ disposeOnce();
+}
+
+void ScDataTableView::dispose()
+{
+ mpTopLeft.disposeAndClear();
+ mpColView.disposeAndClear();
+ mpRowView.disposeAndClear();
+ mpVScroll.disposeAndClear();
+ mpHScroll.disposeAndClear();
+ Control::dispose();
+}
+
+void ScDataTableView::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ if (!rMEvt.IsLeft())
+ return;
+
+ mpMouseEvent.reset(new MouseEvent(rMEvt));
+}
+
+namespace {
+
+SCCOL findColFromPos(sal_uInt16 nPixelPos, const ScDocument* pDoc, SCCOL nStartCol = 0)
+{
+ nPixelPos -= nRowHeaderWidth;
+ sal_uInt32 nPixelLength = 0;
+ for (SCCOL nCol : pDoc->GetColumnsRange(0, nStartCol, pDoc->MaxCol()))
+ {
+ sal_uInt16 nColWidth = pDoc->GetColWidth(nCol, 0, true);
+ sal_uInt32 nPixel = ScViewData::ToPixel(nColWidth, nPPTX);
+ nPixelLength += nPixel;
+
+ if (nPixelLength >= nPixelPos)
+ {
+ return nCol;
+ }
+ }
+
+ SAL_WARN("sc", "Could not find the corresponding column");
+ return pDoc->MaxCol();
+}
+
+SCROW findRowFromPos(sal_uInt16 nPixelPos, const ScDocument* pDoc, SCROW nStartRow = 0)
+{
+ nPixelPos -= nColHeaderHeight;
+ sal_uInt32 nPixelLength = 0;
+ for (SCROW nRow = nStartRow; nRow <= pDoc->MaxRow(); ++nRow)
+ {
+ sal_uInt16 nColWidth = pDoc->GetRowHeight(nRow, SCTAB(0), true);
+ sal_uInt32 nPixel = ScViewData::ToPixel(nColWidth, nPPTX);
+ nPixelLength += nPixel;
+
+ if (nPixelLength >= nPixelPos)
+ {
+ return nRow;
+ }
+ }
+
+ SAL_WARN("sc", "Could not find the corresponding row");
+ return pDoc->MaxRow();
+}
+
+}
+
+void ScDataTableView::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ if (!rMEvt.IsLeft())
+ return;
+ if (!mpMouseEvent) // tdf#120528 The event originated in another window, like context menu
+ return;
+
+ SCCOL nStartCol = findColFromPos(mpMouseEvent->GetPosPixel().getX(), mpDoc.get());
+ SCCOL nEndCol = findColFromPos(rMEvt.GetPosPixel().getX(), mpDoc.get());
+ SCROW nStartRow = findRowFromPos(mpMouseEvent->GetPosPixel().getY(), mpDoc.get());
+ SCROW nEndRow = findRowFromPos(rMEvt.GetPosPixel().getY(), mpDoc.get());
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ mpColView->SetMark(true, nStartCol, nEndCol);
+ mpRowView->SetMark(true, nStartRow, nEndRow);
+
+ mpMouseEvent.reset();
+}
+
+void ScDataTableView::Resize()
+{
+ Size aSize = GetSizePixel();
+ mpTopLeft->setPosSizePixel(0, 0, nRowHeaderWidth, nColHeaderHeight);
+ mpColView->setPosSizePixel(nRowHeaderWidth, 0, aSize.Width() - nScrollBarSize, nColHeaderHeight);
+ mpRowView->setPosSizePixel(0, nColHeaderHeight, nRowHeaderWidth, aSize.Height());
+
+ mpVScroll->setPosSizePixel(aSize.Width() - nScrollBarSize, nColHeaderHeight, nScrollBarSize, aSize.Height() - nColHeaderHeight - nScrollBarSize);
+ mpHScroll->setPosSizePixel(nRowHeaderWidth, aSize.Height() - nScrollBarSize, aSize.Width() - nRowHeaderWidth - nScrollBarSize, nScrollBarSize);
+}
+
+void ScDataTableView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRectangle)
+{
+ Size aSize = GetSizePixel();
+ SCCOL nMaxVisibleCol = findColFromPos(aSize.Width() - nScrollBarSize, mpDoc.get(), mnFirstVisibleCol);
+ SCROW nMaxVisibleRow = findRowFromPos(aSize.Height(), mpDoc.get(), mnFirstVisibleRow);
+
+ ScTableInfo aTableInfo;
+ mpDoc->FillInfo(aTableInfo, mnFirstVisibleCol, mnFirstVisibleRow, nMaxVisibleCol, nMaxVisibleRow, 0, 0.06666, 0.06666, false, false);
+ ScOutputData aOutput(&rRenderContext, OUTTYPE_WINDOW, aTableInfo, mpDoc.get(), 0,
+ nRowHeaderWidth, nColHeaderHeight, mnFirstVisibleCol, mnFirstVisibleRow, nMaxVisibleCol, nMaxVisibleRow, nPPTX, nPPTY);
+
+ aOutput.SetGridColor(COL_BLACK);
+ aOutput.SetSolidBackground(true);
+ aOutput.DrawClear();
+ aOutput.DrawDocumentBackground();
+ aOutput.DrawGrid(rRenderContext, true, false);
+ aOutput.DrawStrings();
+ Control::Paint(rRenderContext, rRectangle);
+}
+
+Size ScDataTableView::GetOptimalSize() const
+{
+ return Size(450, 400);
+}
+
+void ScDataTableView::getColRange(SCCOL& rStartCol, SCCOL& rEndCol) const
+{
+ SCCOLROW aStart = 0;
+ SCCOLROW aEnd = 0;
+ mpColView->GetMarkRange(aStart, aEnd);
+ rStartCol = static_cast<SCCOL>(aStart);
+ rEndCol = static_cast<SCCOL>(aEnd);
+}
+
+void ScDataTableView::getRowRange(SCROW& rStartCol, SCROW& rEndCol) const
+{
+ SCCOLROW aStart = 0;
+ SCCOLROW aEnd = 0;
+ mpRowView->GetMarkRange(aStart, aEnd);
+ rStartCol = static_cast<SCROW>(aStart);
+ rEndCol = static_cast<SCROW>(aEnd);
+}
+
+IMPL_LINK(ScDataTableView, ScrollHdl, ScrollBar*, pScrollBar, void)
+{
+ if (pScrollBar == mpVScroll.get())
+ {
+ mnFirstVisibleRow = pScrollBar->GetThumbPos();
+ pScrollBar->SetRangeMax(std::min(mpDoc->MaxRow(), static_cast<SCROW>(mnFirstVisibleRow + 100)));
+ mpRowView->SetPos(mnFirstVisibleRow);
+ }
+ else
+ {
+ mnFirstVisibleCol = pScrollBar->GetThumbPos();
+ pScrollBar->SetRangeMax(std::min(mpDoc->MaxCol(), static_cast<SCCOL>(mnFirstVisibleCol + 50)));
+ mpColView->SetPos(mnFirstVisibleCol);
+ }
+ Invalidate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/delcldlg.cxx b/sc/source/ui/miscdlgs/delcldlg.cxx
new file mode 100644
index 000000000..71ce6b99e
--- /dev/null
+++ b/sc/source/ui/miscdlgs/delcldlg.cxx
@@ -0,0 +1,101 @@
+/* -*- 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 <delcldlg.hxx>
+
+static sal_uInt8 nDelItemChecked = 0;
+
+ScDeleteCellDlg::ScDeleteCellDlg(weld::Window* pParent, bool bDisallowCellMove)
+ : GenericDialogController(pParent, "modules/scalc/ui/deletecells.ui", "DeleteCellsDialog")
+ , m_xBtnCellsUp(m_xBuilder->weld_radio_button("up"))
+ , m_xBtnCellsLeft(m_xBuilder->weld_radio_button("left"))
+ , m_xBtnDelRows(m_xBuilder->weld_radio_button("rows"))
+ , m_xBtnDelCols(m_xBuilder->weld_radio_button("cols"))
+{
+ if (bDisallowCellMove)
+ {
+ m_xBtnCellsUp->set_sensitive(false);
+ m_xBtnCellsLeft->set_sensitive(false);
+
+ switch (nDelItemChecked)
+ {
+ case 2:
+ m_xBtnDelRows->set_active(true);
+ break;
+ case 3:
+ m_xBtnDelCols->set_active(true);
+ break;
+ default:
+ m_xBtnDelRows->set_active(true);
+ break;
+ }
+ }
+ else
+ {
+ switch (nDelItemChecked)
+ {
+ case 0:
+ m_xBtnCellsUp->set_active(true);
+ break;
+ case 1:
+ m_xBtnCellsLeft->set_active(true);
+ break;
+ case 2:
+ m_xBtnDelRows->set_active(true);
+ break;
+ case 3:
+ m_xBtnDelCols->set_active(true);
+ break;
+ }
+ }
+}
+
+ScDeleteCellDlg::~ScDeleteCellDlg() {}
+
+DelCellCmd ScDeleteCellDlg::GetDelCellCmd() const
+{
+ DelCellCmd nReturn = DelCellCmd::NONE;
+
+ if (m_xBtnCellsUp->get_active())
+ {
+ nDelItemChecked = 0;
+ nReturn = DelCellCmd::CellsUp;
+ }
+ else if (m_xBtnCellsLeft->get_active())
+ {
+ nDelItemChecked = 1;
+ nReturn = DelCellCmd::CellsLeft;
+ }
+ else if (m_xBtnDelRows->get_active())
+ {
+ nDelItemChecked = 2;
+ nReturn = DelCellCmd::Rows;
+ }
+ else if (m_xBtnDelCols->get_active())
+ {
+ nDelItemChecked = 3;
+ nReturn = DelCellCmd::Cols;
+ }
+
+ return nReturn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/delcodlg.cxx b/sc/source/ui/miscdlgs/delcodlg.cxx
new file mode 100644
index 000000000..9d804c252
--- /dev/null
+++ b/sc/source/ui/miscdlgs/delcodlg.cxx
@@ -0,0 +1,125 @@
+/* -*- 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 <delcodlg.hxx>
+
+bool ScDeleteContentsDlg::bPreviousAllCheck = false;
+InsertDeleteFlags ScDeleteContentsDlg::nPreviousChecks = InsertDeleteFlags::DATETIME | InsertDeleteFlags::STRING |
+ InsertDeleteFlags::NOTE | InsertDeleteFlags::FORMULA |
+ InsertDeleteFlags::VALUE;
+
+ScDeleteContentsDlg::ScDeleteContentsDlg(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/deletecontents.ui", "DeleteContentsDialog")
+ , m_bObjectsDisabled(false)
+ , m_xBtnDelAll(m_xBuilder->weld_check_button("deleteall"))
+ , m_xBtnDelStrings(m_xBuilder->weld_check_button("text"))
+ , m_xBtnDelNumbers(m_xBuilder->weld_check_button("numbers"))
+ , m_xBtnDelDateTime(m_xBuilder->weld_check_button("datetime"))
+ , m_xBtnDelFormulas(m_xBuilder->weld_check_button("formulas"))
+ , m_xBtnDelNotes(m_xBuilder->weld_check_button("comments"))
+ , m_xBtnDelAttrs(m_xBuilder->weld_check_button("formats"))
+ , m_xBtnDelObjects(m_xBuilder->weld_check_button("objects"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+{
+ m_xBtnDelAll->set_active( ScDeleteContentsDlg::bPreviousAllCheck );
+ m_xBtnDelStrings->set_active( bool(InsertDeleteFlags::STRING & ScDeleteContentsDlg::nPreviousChecks) );
+ m_xBtnDelNumbers->set_active( bool(InsertDeleteFlags::VALUE & ScDeleteContentsDlg::nPreviousChecks) );
+ m_xBtnDelDateTime->set_active( bool(InsertDeleteFlags::DATETIME & ScDeleteContentsDlg::nPreviousChecks) );
+ m_xBtnDelFormulas->set_active( bool(InsertDeleteFlags::FORMULA & ScDeleteContentsDlg::nPreviousChecks) );
+ m_xBtnDelNotes->set_active( bool(InsertDeleteFlags::NOTE & ScDeleteContentsDlg::nPreviousChecks) );
+ m_xBtnDelAttrs->set_active( (InsertDeleteFlags::ATTRIB & ScDeleteContentsDlg::nPreviousChecks) == InsertDeleteFlags::ATTRIB );
+ m_xBtnDelObjects->set_active( bool(InsertDeleteFlags::OBJECTS & ScDeleteContentsDlg::nPreviousChecks) );
+
+ DisableChecks( m_xBtnDelAll->get_active() );
+
+ m_xBtnDelAll->connect_toggled( LINK( this, ScDeleteContentsDlg, DelAllHdl ) );
+}
+
+ScDeleteContentsDlg::~ScDeleteContentsDlg()
+{
+}
+
+InsertDeleteFlags ScDeleteContentsDlg::GetDelContentsCmdBits() const
+{
+ ScDeleteContentsDlg::nPreviousChecks = InsertDeleteFlags::NONE;
+
+ if ( m_xBtnDelStrings->get_active() )
+ ScDeleteContentsDlg::nPreviousChecks = InsertDeleteFlags::STRING;
+ if ( m_xBtnDelNumbers->get_active() )
+ ScDeleteContentsDlg::nPreviousChecks |= InsertDeleteFlags::VALUE;
+ if ( m_xBtnDelDateTime->get_active())
+ ScDeleteContentsDlg::nPreviousChecks |= InsertDeleteFlags::DATETIME;
+ if ( m_xBtnDelFormulas->get_active())
+ ScDeleteContentsDlg::nPreviousChecks |= InsertDeleteFlags::FORMULA;
+ if ( m_xBtnDelNotes->get_active() )
+ ScDeleteContentsDlg::nPreviousChecks |= InsertDeleteFlags::NOTE;
+ if ( m_xBtnDelAttrs->get_active() )
+ ScDeleteContentsDlg::nPreviousChecks |= InsertDeleteFlags::ATTRIB;
+ if ( m_xBtnDelObjects->get_active() )
+ ScDeleteContentsDlg::nPreviousChecks |= InsertDeleteFlags::OBJECTS;
+
+ ScDeleteContentsDlg::bPreviousAllCheck = m_xBtnDelAll->get_active();
+
+ return ( ScDeleteContentsDlg::bPreviousAllCheck
+ ? InsertDeleteFlags::ALL
+ : ScDeleteContentsDlg::nPreviousChecks );
+}
+
+void ScDeleteContentsDlg::DisableChecks( bool bDelAllChecked )
+{
+ if ( bDelAllChecked )
+ {
+ m_xBtnDelStrings->set_sensitive(false);
+ m_xBtnDelNumbers->set_sensitive(false);
+ m_xBtnDelDateTime->set_sensitive(false);
+ m_xBtnDelFormulas->set_sensitive(false);
+ m_xBtnDelNotes->set_sensitive(false);
+ m_xBtnDelAttrs->set_sensitive(false);
+ m_xBtnDelObjects->set_sensitive(false);
+ }
+ else
+ {
+ m_xBtnDelStrings->set_sensitive(true);
+ m_xBtnDelNumbers->set_sensitive(true);
+ m_xBtnDelDateTime->set_sensitive(true);
+ m_xBtnDelFormulas->set_sensitive(true);
+ m_xBtnDelNotes->set_sensitive(true);
+ m_xBtnDelAttrs->set_sensitive(true);
+ if (m_bObjectsDisabled)
+ m_xBtnDelObjects->set_sensitive(false);
+ else
+ m_xBtnDelObjects->set_sensitive(true);
+ }
+}
+
+void ScDeleteContentsDlg::DisableObjects()
+{
+ m_bObjectsDisabled = true;
+ m_xBtnDelObjects->set_active(false);
+ m_xBtnDelObjects->set_sensitive(false);
+}
+
+IMPL_LINK_NOARG(ScDeleteContentsDlg, DelAllHdl, weld::Toggleable&, void)
+{
+ DisableChecks( m_xBtnDelAll->get_active() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/filldlg.cxx b/sc/source/ui/miscdlgs/filldlg.cxx
new file mode 100644
index 000000000..c72201d26
--- /dev/null
+++ b/sc/source/ui/miscdlgs/filldlg.cxx
@@ -0,0 +1,290 @@
+/* -*- 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 <svl/numformat.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+#include <scresid.hxx>
+#include <document.hxx>
+#include <strings.hrc>
+#include <filldlg.hxx>
+#include <scui_def.hxx>
+
+
+ScFillSeriesDlg::ScFillSeriesDlg( weld::Window* pParent,
+ ScDocument& rDocument,
+ FillDir eFillDir,
+ FillCmd eFillCmd,
+ FillDateCmd eFillDateCmd,
+ const OUString& aStartStr,
+ double fStep,
+ double fMax,
+ const SCSIZE nSelectHeight,
+ const SCSIZE nSelectWidth,
+ sal_uInt16 nPossDir )
+ : GenericDialogController(pParent, "modules/scalc/ui/filldlg.ui", "FillSeriesDialog")
+ , aStartStrVal(aStartStr)
+ , aErrMsgInvalidVal(ScResId(SCSTR_VALERR))
+ , rDoc(rDocument)
+ , theFillDir(eFillDir)
+ , theFillCmd(eFillCmd)
+ , theFillDateCmd(eFillDateCmd)
+ , fIncrement(fStep)
+ , fEndVal(fMax)
+ , m_nSelectHeight(nSelectHeight)
+ , m_nSelectWidth(nSelectWidth)
+ , m_xFtStartVal(m_xBuilder->weld_label("startL"))
+ , m_xEdStartVal(m_xBuilder->weld_entry("startValue"))
+ , m_xFtEndVal(m_xBuilder->weld_label("endL"))
+ , m_xEdEndVal(m_xBuilder->weld_entry("endValue"))
+ , m_xFtIncrement(m_xBuilder->weld_label("incrementL"))
+ , m_xEdIncrement(m_xBuilder->weld_entry("increment"))
+ , m_xBtnDown(m_xBuilder->weld_radio_button("down"))
+ , m_xBtnRight(m_xBuilder->weld_radio_button("right"))
+ , m_xBtnUp(m_xBuilder->weld_radio_button("up"))
+ , m_xBtnLeft(m_xBuilder->weld_radio_button("left"))
+ , m_xBtnArithmetic(m_xBuilder->weld_radio_button("linear"))
+ , m_xBtnGeometric(m_xBuilder->weld_radio_button("growth"))
+ , m_xBtnDate(m_xBuilder->weld_radio_button("date"))
+ , m_xBtnAutoFill(m_xBuilder->weld_radio_button("autofill"))
+ , m_xFtTimeUnit(m_xBuilder->weld_label("tuL"))
+ , m_xBtnDay(m_xBuilder->weld_radio_button("day"))
+ , m_xBtnDayOfWeek(m_xBuilder->weld_radio_button("week"))
+ , m_xBtnMonth(m_xBuilder->weld_radio_button("month"))
+ , m_xBtnYear(m_xBuilder->weld_radio_button("year"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+{
+ Init(nPossDir);
+}
+
+ScFillSeriesDlg::~ScFillSeriesDlg()
+{
+}
+
+void ScFillSeriesDlg::SetEdStartValEnabled(bool bFlag)
+{
+ if(bFlag)
+ {
+ m_xFtStartVal->set_sensitive(true);
+ m_xEdStartVal->set_sensitive(true);
+ }
+ else
+ {
+ m_xFtStartVal->set_sensitive(false);
+ m_xEdStartVal->set_sensitive(false);
+ }
+}
+
+void ScFillSeriesDlg::Init( sal_uInt16 nPossDir )
+{
+ m_xBtnOk->connect_clicked ( LINK( this, ScFillSeriesDlg, OKHdl ) );
+ m_xBtnArithmetic->connect_toggled ( LINK( this, ScFillSeriesDlg, DisableHdl ) );
+ m_xBtnGeometric->connect_toggled ( LINK( this, ScFillSeriesDlg, DisableHdl ) );
+ m_xBtnDate->connect_toggled ( LINK( this, ScFillSeriesDlg, DisableHdl ) );
+ m_xBtnAutoFill->connect_toggled ( LINK( this, ScFillSeriesDlg, DisableHdl ) );
+
+ if( nPossDir == FDS_OPT_NONE )
+ {
+ m_xBtnLeft->set_sensitive(false);
+ m_xBtnRight->set_sensitive(false);
+ m_xBtnDown->set_sensitive(false);
+ m_xBtnUp->set_sensitive(false);
+ }
+
+ if( nPossDir == FDS_OPT_HORZ )
+ {
+ m_xBtnDown->set_sensitive(false);
+ m_xBtnUp->set_sensitive(false);
+ }
+
+ if( nPossDir == FDS_OPT_VERT )
+ {
+ m_xBtnLeft->set_sensitive(false);
+ m_xBtnRight->set_sensitive(false);
+ }
+
+ switch ( theFillDir )
+ {
+ case FILL_TO_LEFT: m_xBtnLeft->set_active(true); break;
+ case FILL_TO_RIGHT: m_xBtnRight->set_active(true); break;
+ case FILL_TO_BOTTOM: m_xBtnDown->set_active(true); break;
+ case FILL_TO_TOP: m_xBtnUp->set_active(true); break;
+ default:
+ break;
+ }
+
+ switch ( theFillCmd )
+ {
+ case FILL_LINEAR:
+ m_xBtnArithmetic->set_active(true);
+ DisableHdl(*m_xBtnArithmetic);
+ break;
+ case FILL_GROWTH:
+ m_xBtnGeometric->set_active(true);
+ DisableHdl(*m_xBtnGeometric );
+ break;
+ case FILL_DATE:
+ m_xBtnDate->set_active(true);
+ DisableHdl(*m_xBtnDate);
+ break;
+ case FILL_AUTO:
+ m_xBtnAutoFill->set_active(true);
+ DisableHdl(*m_xBtnAutoFill);
+ break;
+ default:
+ break;
+ }
+
+ switch ( theFillDateCmd )
+ {
+ case FILL_DAY: m_xBtnDay->set_active(true); break;
+ case FILL_WEEKDAY: m_xBtnDayOfWeek->set_active(true); break;
+ case FILL_MONTH: m_xBtnMonth->set_active(true); break;
+ case FILL_YEAR: m_xBtnYear->set_active(true); break;
+ default:
+ break;
+ }
+
+ fStartVal = MAXDOUBLE;
+
+ m_xEdStartVal->set_text( aStartStrVal);
+
+ OUString aIncrTxt;
+ rDoc.GetFormatTable()->GetInputLineString( fIncrement, 0, aIncrTxt );
+ m_xEdIncrement->set_text( aIncrTxt );
+
+ OUString aEndTxt;
+ if ( fEndVal != MAXDOUBLE )
+ rDoc.GetFormatTable()->GetInputLineString( fEndVal, 0, aEndTxt );
+ m_xEdEndVal->set_text( aEndTxt );
+}
+
+weld::Entry* ScFillSeriesDlg::CheckValues()
+{
+ OUString aStartStr = m_xEdStartVal->get_text();
+ OUString aIncStr = m_xEdIncrement->get_text();
+ OUString aEndStr = m_xEdEndVal->get_text();
+ sal_uInt32 nKey = 0;
+
+ // If entry is filled, capture value before handling special cases.
+ if ( !aStartStr.isEmpty()
+ && theFillCmd != FILL_AUTO
+ && !rDoc.GetFormatTable()->IsNumberFormat( aStartStr, nKey, fStartVal ) )
+ return m_xEdStartVal.get();
+ if ( !aIncStr.isEmpty()
+ && !rDoc.GetFormatTable()->IsNumberFormat( aIncStr, nKey, fIncrement ) )
+ return m_xEdIncrement.get();
+ if ( !aEndStr.isEmpty()
+ && !rDoc.GetFormatTable()->IsNumberFormat( aEndStr, nKey, fEndVal ) )
+ return m_xEdEndVal.get();
+
+ if ( theFillCmd == FILL_LINEAR && !aEndStr.isEmpty()
+ && aStartStr.isEmpty() != aIncStr.isEmpty()
+ && ( ( m_nSelectHeight == 1 ) != ( m_nSelectWidth == 1 ) ) )
+ {
+ SCSIZE nStepAmount = ( theFillDir == FILL_TO_BOTTOM || theFillDir == FILL_TO_TOP ) ?
+ m_nSelectHeight - 1 : m_nSelectWidth - 1 ;
+ if ( aStartStr.isEmpty() )
+ fStartVal = fEndVal - fIncrement * nStepAmount;
+ if ( aIncStr.isEmpty() && nStepAmount != 0 )
+ fIncrement = (fEndVal - fStartVal) / nStepAmount;
+ }
+ else
+ {
+ if ( aStartStr.isEmpty() || m_xBtnAutoFill->get_active() )
+ fStartVal = MAXDOUBLE;
+ if ( aIncStr.isEmpty() )
+ return m_xEdIncrement.get();
+ if ( aEndStr.isEmpty() )
+ fEndVal = ( fIncrement < 0 ) ? -MAXDOUBLE : MAXDOUBLE;
+ }
+ return nullptr;
+}
+
+// Handler:
+IMPL_LINK(ScFillSeriesDlg, DisableHdl, weld::Toggleable&, rBtn, void)
+{
+ if (&rBtn == m_xBtnDate.get())
+ {
+ m_xBtnDay->set_sensitive(true);
+ m_xBtnDayOfWeek->set_sensitive(true);
+ m_xBtnMonth->set_sensitive(true);
+ m_xBtnYear->set_sensitive(true);
+ m_xFtTimeUnit->set_sensitive(true);
+ }
+ else
+ {
+ m_xBtnDay->set_sensitive(false);
+ m_xBtnDayOfWeek->set_sensitive(false);
+ m_xBtnMonth->set_sensitive(false);
+ m_xBtnYear->set_sensitive(false);
+ m_xFtTimeUnit->set_sensitive(false);
+ }
+
+ if (&rBtn != m_xBtnAutoFill.get())
+ {
+ m_xFtIncrement->set_sensitive(true);
+ m_xEdIncrement->set_sensitive(true);
+ m_xFtEndVal->set_sensitive(true);
+ m_xEdEndVal->set_sensitive(true);
+ }
+ else
+ {
+ m_xFtIncrement->set_sensitive(false);
+ m_xEdIncrement->set_sensitive(false);
+ m_xFtEndVal->set_sensitive(false);
+ m_xEdEndVal->set_sensitive(false);
+ }
+}
+
+IMPL_LINK_NOARG(ScFillSeriesDlg, OKHdl, weld::Button&, void)
+{
+ if ( m_xBtnLeft->get_active() ) theFillDir = FILL_TO_LEFT;
+ else if ( m_xBtnRight->get_active() ) theFillDir = FILL_TO_RIGHT;
+ else if ( m_xBtnDown->get_active() ) theFillDir = FILL_TO_BOTTOM;
+ else if ( m_xBtnUp->get_active() ) theFillDir = FILL_TO_TOP;
+
+ if ( m_xBtnArithmetic->get_active() ) theFillCmd = FILL_LINEAR;
+ else if ( m_xBtnGeometric->get_active() ) theFillCmd = FILL_GROWTH;
+ else if ( m_xBtnDate->get_active() ) theFillCmd = FILL_DATE;
+ else if ( m_xBtnAutoFill->get_active() ) theFillCmd = FILL_AUTO;
+
+ if ( m_xBtnDay->get_active() ) theFillDateCmd = FILL_DAY;
+ else if ( m_xBtnDayOfWeek->get_active() ) theFillDateCmd = FILL_WEEKDAY;
+ else if ( m_xBtnMonth->get_active() ) theFillDateCmd = FILL_MONTH;
+ else if ( m_xBtnYear->get_active() ) theFillDateCmd = FILL_YEAR;
+
+ weld::Entry* pEdWrong = CheckValues();
+ if ( pEdWrong == nullptr )
+ {
+ m_xDialog->response(RET_OK);
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning,
+ VclButtonsType::Ok, aErrMsgInvalidVal));
+ xBox->run();
+ pEdWrong->grab_focus();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/gototabdlg.cxx b/sc/source/ui/miscdlgs/gototabdlg.cxx
new file mode 100644
index 000000000..e38e67100
--- /dev/null
+++ b/sc/source/ui/miscdlgs/gototabdlg.cxx
@@ -0,0 +1,81 @@
+/* -*- 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/.
+ *
+ */
+
+#undef SC_DLLIMPLEMENTATION
+
+#include <gototabdlg.hxx>
+
+ScGoToTabDlg::ScGoToTabDlg(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/gotosheetdialog.ui", "GoToSheetDialog")
+ , m_xFrameMask(m_xBuilder->weld_frame("frame-mask"))
+ , m_xEnNameMask(m_xBuilder->weld_entry("entry-mask"))
+ , m_xFrameSheets(m_xBuilder->weld_frame("frame-sheets"))
+ , m_xLb(m_xBuilder->weld_tree_view("treeview"))
+{
+ m_xLb->set_selection_mode(SelectionMode::Single);
+ m_xLb->set_size_request(-1, m_xLb->get_height_rows(10));
+ m_xLb->connect_row_activated(LINK(this, ScGoToTabDlg, DblClkHdl));
+ m_xEnNameMask->connect_changed(LINK(this, ScGoToTabDlg, FindNameHdl));
+}
+
+ScGoToTabDlg::~ScGoToTabDlg() {}
+
+void ScGoToTabDlg::SetDescription(const OUString& rTitle, const OUString& rEntryLabel,
+ const OUString& rListLabel, const OString& rDlgHelpId,
+ const OString& rEnHelpId, const OString& rLbHelpId)
+{
+ m_xDialog->set_title(rTitle);
+ m_xFrameMask->set_label(rEntryLabel);
+ m_xFrameSheets->set_label(rListLabel);
+ m_xDialog->set_help_id(rDlgHelpId);
+ m_xEnNameMask->set_help_id(rEnHelpId);
+ m_xLb->set_help_id(rLbHelpId);
+}
+
+void ScGoToTabDlg::Insert(const OUString& rString, bool bSelected)
+{
+ maCacheSheetsNames.push_back(rString);
+ m_xLb->append_text(rString);
+ if (bSelected)
+ m_xLb->select(m_xLb->n_children() - 1);
+}
+
+OUString ScGoToTabDlg::GetSelectedEntry() const { return m_xLb->get_selected_text(); }
+
+IMPL_LINK_NOARG(ScGoToTabDlg, DblClkHdl, weld::TreeView&, bool)
+{
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+IMPL_LINK_NOARG(ScGoToTabDlg, FindNameHdl, weld::Entry&, void)
+{
+ const OUString aMask = m_xEnNameMask->get_text();
+ m_xLb->clear();
+ if (aMask.isEmpty())
+ {
+ for (const OUString& s : maCacheSheetsNames)
+ {
+ m_xLb->append_text(s);
+ }
+ }
+ else
+ {
+ for (const OUString& s : maCacheSheetsNames)
+ {
+ if (s.indexOf(aMask) >= 0)
+ {
+ m_xLb->append_text(s);
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/groupdlg.cxx b/sc/source/ui/miscdlgs/groupdlg.cxx
new file mode 100644
index 000000000..839cc4f74
--- /dev/null
+++ b/sc/source/ui/miscdlgs/groupdlg.cxx
@@ -0,0 +1,52 @@
+/* -*- 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 <groupdlg.hxx>
+
+ScGroupDlg::ScGroupDlg(weld::Window* pParent, bool bUngroup, bool bRows)
+ : GenericDialogController(pParent,
+ bUngroup ?
+ OUString("modules/scalc/ui/ungroupdialog.ui") :
+ OUString("modules/scalc/ui/groupdialog.ui")
+ ,
+ bUngroup ?
+ OString("UngroupDialog") :
+ OString("GroupDialog"))
+ , m_xBtnRows(m_xBuilder->weld_radio_button("rows"))
+ , m_xBtnCols(m_xBuilder->weld_radio_button("cols"))
+{
+ if (bRows)
+ m_xBtnRows->set_active(true);
+ else
+ m_xBtnCols->set_active(true);
+ m_xBtnRows->grab_focus();
+}
+
+ScGroupDlg::~ScGroupDlg()
+{
+}
+
+bool ScGroupDlg::GetColsChecked() const
+{
+ return m_xBtnCols->get_active();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/highred.cxx b/sc/source/ui/miscdlgs/highred.cxx
new file mode 100644
index 000000000..fa655f80e
--- /dev/null
+++ b/sc/source/ui/miscdlgs/highred.cxx
@@ -0,0 +1,221 @@
+/* -*- 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 <reffact.hxx>
+#include <document.hxx>
+#include <docsh.hxx>
+#include <chgtrack.hxx>
+
+#include <highred.hxx>
+
+
+ScHighlightChgDlg::ScHighlightChgDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ ScViewData& rViewData)
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/showchangesdialog.ui", "ShowChangesDialog")
+ , m_rViewData(rViewData)
+ , rDoc(rViewData.GetDocument())
+ , m_xHighlightBox(m_xBuilder->weld_check_button("showchanges"))
+ , m_xCbAccept(m_xBuilder->weld_check_button("showaccepted"))
+ , m_xCbReject(m_xBuilder->weld_check_button("showrejected"))
+ , m_xOkButton(m_xBuilder->weld_button("ok"))
+ , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry("range")))
+ , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button("rangeref")))
+ , m_xBox(m_xBuilder->weld_container("box"))
+ , m_xFilterCtr(new SvxTPFilter(m_xBox.get()))
+{
+ m_xEdAssign->SetReferences(this, nullptr);
+ m_xRbAssign->SetReferences(this, m_xEdAssign.get());
+
+ m_xOkButton->connect_clicked(LINK( this, ScHighlightChgDlg, OKBtnHdl));
+ m_xHighlightBox->connect_toggled(LINK( this, ScHighlightChgDlg, HighlightHandle ));
+ m_xFilterCtr->SetRefHdl(LINK( this, ScHighlightChgDlg, RefHandle ));
+ m_xFilterCtr->HideRange(false);
+ m_xFilterCtr->Show();
+ SetDispatcherLock( true );
+
+ Init();
+}
+
+ScHighlightChgDlg::~ScHighlightChgDlg()
+{
+ SetDispatcherLock( false );
+}
+
+void ScHighlightChgDlg::Init()
+{
+ ScChangeTrack* pChanges = rDoc.GetChangeTrack();
+ if(pChanges!=nullptr)
+ {
+ aChangeViewSet.SetTheAuthorToShow(pChanges->GetUser());
+ m_xFilterCtr->ClearAuthors();
+ const std::set<OUString>& rUserColl = pChanges->GetUserCollection();
+ for (const auto& rItem : rUserColl)
+ m_xFilterCtr->InsertAuthor(rItem);
+ }
+
+ ScChangeViewSettings* pViewSettings = rDoc.GetChangeViewSettings();
+
+ if(pViewSettings!=nullptr)
+ aChangeViewSet=*pViewSettings;
+ m_xHighlightBox->set_active(aChangeViewSet.ShowChanges());
+ m_xFilterCtr->CheckDate(aChangeViewSet.HasDate());
+
+ DateTime aEmpty(DateTime::EMPTY);
+
+ DateTime aDateTime(aChangeViewSet.GetTheFirstDateTime());
+ if (aDateTime != aEmpty)
+ {
+ m_xFilterCtr->SetFirstDate(aDateTime);
+ m_xFilterCtr->SetFirstTime(aDateTime);
+ }
+ aDateTime = aChangeViewSet.GetTheLastDateTime();
+ if (aDateTime != aEmpty)
+ {
+ m_xFilterCtr->SetLastDate(aDateTime);
+ m_xFilterCtr->SetLastTime(aDateTime);
+ }
+
+ m_xFilterCtr->SetDateMode(static_cast<sal_uInt16>(aChangeViewSet.GetTheDateMode()));
+ m_xFilterCtr->CheckAuthor(aChangeViewSet.HasAuthor());
+ m_xFilterCtr->CheckComment(aChangeViewSet.HasComment());
+ m_xFilterCtr->SetComment(aChangeViewSet.GetTheComment());
+
+ m_xCbAccept->set_active(aChangeViewSet.IsShowAccepted());
+ m_xCbReject->set_active(aChangeViewSet.IsShowRejected());
+
+ OUString aString=aChangeViewSet.GetTheAuthorToShow();
+ if(!aString.isEmpty())
+ {
+ m_xFilterCtr->SelectAuthor(aString);
+ }
+ else
+ {
+ m_xFilterCtr->SelectedAuthorPos(0);
+ }
+
+ m_xFilterCtr->CheckRange(aChangeViewSet.HasRange());
+
+ if ( !aChangeViewSet.GetTheRangeList().empty() )
+ {
+ const ScRange & rRangeEntry = aChangeViewSet.GetTheRangeList().front();
+ OUString aRefStr(rRangeEntry.Format(rDoc, ScRefFlags::RANGE_ABS_3D));
+ m_xFilterCtr->SetRange(aRefStr);
+ }
+ m_xFilterCtr->Enable(true);
+ HighlightHandle(*m_xHighlightBox);
+}
+
+// Set the reference to a cell range selected with the mouse. This is then
+// shown as the new selection in the reference field.
+void ScHighlightChgDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if (m_xEdAssign->GetWidget()->get_visible())
+ {
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(m_xEdAssign.get());
+ OUString aRefStr(rRef.Format(rDocP, ScRefFlags::RANGE_ABS_3D, rDocP.GetAddressConvention()));
+ m_xEdAssign->SetRefString( aRefStr );
+ m_xFilterCtr->SetRange(aRefStr);
+ }
+}
+
+void ScHighlightChgDlg::Close()
+{
+ DoClose( ScHighlightChgDlgWrapper::GetChildWindowId() );
+}
+
+void ScHighlightChgDlg::RefInputDone( bool bForced)
+{
+ ScAnyRefDlgController::RefInputDone(bForced);
+ if (bForced || !m_xRbAssign->GetWidget()->get_visible())
+ {
+ m_xFilterCtr->SetRange(m_xEdAssign->GetText());
+ m_xFilterCtr->SetFocusToRange();
+ m_xEdAssign->GetWidget()->hide();
+ m_xRbAssign->GetWidget()->hide();
+ }
+}
+
+void ScHighlightChgDlg::SetActive()
+{
+}
+
+bool ScHighlightChgDlg::IsRefInputMode() const
+{
+ return m_xEdAssign->GetWidget()->get_visible();
+}
+
+IMPL_LINK_NOARG(ScHighlightChgDlg, HighlightHandle, weld::Toggleable&, void)
+{
+ if (m_xHighlightBox->get_active())
+ {
+ m_xFilterCtr->Enable(true);
+ m_xCbAccept->set_sensitive(true);
+ m_xCbReject->set_sensitive(true);
+ }
+ else
+ {
+ m_xFilterCtr->Enable(false);
+ m_xCbAccept->set_sensitive(false);
+ m_xCbReject->set_sensitive(false);
+ }
+}
+
+IMPL_LINK( ScHighlightChgDlg, RefHandle, SvxTPFilter*, pRef, void )
+{
+ if(pRef!=nullptr)
+ {
+ SetDispatcherLock( true );
+ m_xEdAssign->GetWidget()->show();
+ m_xRbAssign->GetWidget()->show();
+ m_xEdAssign->SetText(m_xFilterCtr->GetRange());
+ m_xEdAssign->GrabFocus();
+ ScAnyRefDlgController::RefInputStart(m_xEdAssign.get(), m_xRbAssign.get());
+ }
+}
+
+IMPL_LINK_NOARG(ScHighlightChgDlg, OKBtnHdl, weld::Button&, void)
+{
+ aChangeViewSet.SetShowChanges(m_xHighlightBox->get_active());
+ aChangeViewSet.SetHasDate(m_xFilterCtr->IsDate());
+ SvxRedlinDateMode eMode = m_xFilterCtr->GetDateMode();
+ aChangeViewSet.SetTheDateMode( eMode );
+ Date aFirstDate( m_xFilterCtr->GetFirstDate() );
+ tools::Time aFirstTime( m_xFilterCtr->GetFirstTime() );
+ Date aLastDate( m_xFilterCtr->GetLastDate() );
+ tools::Time aLastTime( m_xFilterCtr->GetLastTime() );
+ aChangeViewSet.SetTheFirstDateTime( DateTime( aFirstDate, aFirstTime ) );
+ aChangeViewSet.SetTheLastDateTime( DateTime( aLastDate, aLastTime ) );
+ aChangeViewSet.SetHasAuthor(m_xFilterCtr->IsAuthor());
+ aChangeViewSet.SetTheAuthorToShow(m_xFilterCtr->GetSelectedAuthor());
+ aChangeViewSet.SetHasRange(m_xFilterCtr->IsRange());
+ aChangeViewSet.SetShowAccepted(m_xCbAccept->get_active());
+ aChangeViewSet.SetShowRejected(m_xCbReject->get_active());
+ aChangeViewSet.SetHasComment(m_xFilterCtr->IsComment());
+ aChangeViewSet.SetTheComment(m_xFilterCtr->GetComment());
+ ScRangeList aLocalRangeList;
+ aLocalRangeList.Parse(m_xFilterCtr->GetRange(), rDoc);
+ aChangeViewSet.SetTheRangeList(aLocalRangeList);
+ aChangeViewSet.AdjustDateMode( rDoc );
+ rDoc.SetChangeViewSettings(aChangeViewSet);
+ m_rViewData.GetDocShell()->PostPaintGridAll();
+ response(RET_OK);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/inscldlg.cxx b/sc/source/ui/miscdlgs/inscldlg.cxx
new file mode 100644
index 000000000..ac97c6ac3
--- /dev/null
+++ b/sc/source/ui/miscdlgs/inscldlg.cxx
@@ -0,0 +1,110 @@
+/* -*- 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 <inscldlg.hxx>
+#include <viewdata.hxx>
+#include <strings.hrc>
+#include <scresid.hxx>
+
+static sal_uInt8 nInsItemChecked = 0;
+
+ScInsertCellDlg::ScInsertCellDlg(weld::Window* pParent, bool bDisallowCellMove)
+ : GenericDialogController(pParent, "modules/scalc/ui/insertcells.ui", "InsertCellsDialog")
+ , m_xBtnCellsDown(m_xBuilder->weld_radio_button("down"))
+ , m_xBtnCellsRight(m_xBuilder->weld_radio_button("right"))
+ , m_xBtnInsRow(m_xBuilder->weld_radio_button("rows"))
+ , m_xBtnInsCol(m_xBuilder->weld_radio_button("cols"))
+ , m_xLbCellsRight(m_xBuilder->weld_label("right"))
+{
+ const ScViewData* pViewData = ScDocShell::GetViewData();
+ if (pViewData && pViewData->GetDocument().IsLayoutRTL(pViewData->GetTabNo()))
+ m_xLbCellsRight->set_label(ScResId(SCSTR_INSERT_RTL));
+
+ if (bDisallowCellMove)
+ {
+ m_xBtnCellsDown->set_sensitive(false);
+ m_xBtnCellsRight->set_sensitive(false);
+ m_xBtnInsRow->set_active(true);
+
+ switch (nInsItemChecked)
+ {
+ case 2:
+ m_xBtnInsRow->set_active(true);
+ break;
+ case 3:
+ m_xBtnInsCol->set_active(true);
+ break;
+ default:
+ m_xBtnInsRow->set_active(true);
+ break;
+ }
+ }
+ else
+ {
+ switch (nInsItemChecked)
+ {
+ case 0:
+ m_xBtnCellsDown->set_active(true);
+ break;
+ case 1:
+ m_xBtnCellsRight->set_active(true);
+ break;
+ case 2:
+ m_xBtnInsRow->set_active(true);
+ break;
+ case 3:
+ m_xBtnInsCol->set_active(true);
+ break;
+ }
+ }
+}
+
+ScInsertCellDlg::~ScInsertCellDlg() {}
+
+InsCellCmd ScInsertCellDlg::GetInsCellCmd() const
+{
+ InsCellCmd nReturn = INS_NONE;
+
+ if (m_xBtnCellsDown->get_active())
+ {
+ nInsItemChecked = 0;
+ nReturn = INS_CELLSDOWN;
+ }
+ else if (m_xBtnCellsRight->get_active())
+ {
+ nInsItemChecked = 1;
+ nReturn = INS_CELLSRIGHT;
+ }
+ else if (m_xBtnInsRow->get_active())
+ {
+ nInsItemChecked = 2;
+ nReturn = INS_INSROWS_BEFORE;
+ }
+ else if (m_xBtnInsCol->get_active())
+ {
+ nInsItemChecked = 3;
+ nReturn = INS_INSCOLS_BEFORE;
+ }
+
+ return nReturn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/inscodlg.cxx b/sc/source/ui/miscdlgs/inscodlg.cxx
new file mode 100644
index 000000000..879ed2835
--- /dev/null
+++ b/sc/source/ui/miscdlgs/inscodlg.cxx
@@ -0,0 +1,367 @@
+/* -*- 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 <inscodlg.hxx>
+
+InsertDeleteFlags ScInsertContentsDlg::nPreviousChecks = InsertDeleteFlags::VALUE | InsertDeleteFlags::DATETIME | InsertDeleteFlags::STRING;
+ScPasteFunc ScInsertContentsDlg::nPreviousFormulaChecks = ScPasteFunc::NONE;
+InsertContentsFlags ScInsertContentsDlg::nPreviousChecks2 = InsertContentsFlags::NONE;
+InsCellCmd ScInsertContentsDlg::nPreviousMoveMode = InsCellCmd::INS_NONE;
+
+ScInsertContentsDlg::ScInsertContentsDlg(weld::Window* pParent,
+ const OUString* pStrTitle )
+ : GenericDialogController(pParent, "modules/scalc/ui/pastespecial.ui", "PasteSpecial")
+ , bOtherDoc(false)
+ , bFillMode(false)
+ , bChangeTrack(false)
+ , bMoveDownDisabled(false)
+ , bMoveRightDisabled(false)
+ , mxBtnInsAll(m_xBuilder->weld_check_button("paste_all"))
+ , mxBtnInsStrings(m_xBuilder->weld_check_button("text"))
+ , mxBtnInsNumbers(m_xBuilder->weld_check_button("numbers"))
+ , mxBtnInsDateTime(m_xBuilder->weld_check_button("datetime"))
+ , mxBtnInsFormulas(m_xBuilder->weld_check_button("formulas"))
+ , mxBtnInsNotes(m_xBuilder->weld_check_button("comments"))
+ , mxBtnInsAttrs(m_xBuilder->weld_check_button("formats"))
+ , mxBtnInsObjects(m_xBuilder->weld_check_button("objects"))
+ , mxBtnSkipEmptyCells(m_xBuilder->weld_check_button("skip_empty"))
+ , mxBtnTranspose(m_xBuilder->weld_check_button("transpose"))
+ , mxBtnLink(m_xBuilder->weld_check_button("link"))
+ , mxRbNoOp(m_xBuilder->weld_radio_button("none"))
+ , mxRbAdd(m_xBuilder->weld_radio_button("add"))
+ , mxRbSub(m_xBuilder->weld_radio_button("subtract"))
+ , mxRbMul(m_xBuilder->weld_radio_button("multiply"))
+ , mxRbDiv(m_xBuilder->weld_radio_button("divide"))
+ , mxRbMoveNone(m_xBuilder->weld_radio_button("no_shift"))
+ , mxRbMoveDown(m_xBuilder->weld_radio_button("move_down"))
+ , mxRbMoveRight(m_xBuilder->weld_radio_button("move_right"))
+ , mxBtnShortCutPasteValuesOnly(m_xBuilder->weld_button("paste_values_only"))
+ , mxBtnShortCutPasteValuesFormats(m_xBuilder->weld_button("paste_values_formats"))
+ , mxBtnShortCutPasteTranspose(m_xBuilder->weld_button("paste_transpose"))
+ , mxBtnShortCutPasteFormats(m_xBuilder->weld_button("paste_formats"))
+ , mxImmediately(m_xBuilder->weld_check_button("cbImmediately"))
+{
+ if (pStrTitle)
+ m_xDialog->set_title(*pStrTitle);
+
+ SetInsContentsCmdBits( ScInsertContentsDlg::nPreviousChecks );
+ SetFormulaCmdBits( ScInsertContentsDlg::nPreviousFormulaChecks );
+ SetCellCmdFlags( ScInsertContentsDlg::nPreviousMoveMode );
+ SetContentsFlags( ScInsertContentsDlg::nPreviousChecks2 );
+ DisableChecks( mxBtnInsAll->get_active() );
+
+ mxBtnInsAll->connect_toggled( LINK( this, ScInsertContentsDlg, InsAllHdl ) );
+ mxBtnLink->connect_toggled( LINK( this, ScInsertContentsDlg, LinkBtnHdl ) );
+ mxBtnShortCutPasteValuesOnly->connect_clicked( LINK( this, ScInsertContentsDlg, ShortCutHdl ) );
+ mxBtnShortCutPasteValuesFormats->connect_clicked( LINK( this, ScInsertContentsDlg, ShortCutHdl ) );
+ mxBtnShortCutPasteTranspose->connect_clicked( LINK( this, ScInsertContentsDlg, ShortCutHdl ) );
+ mxBtnShortCutPasteFormats->connect_clicked( LINK( this, ScInsertContentsDlg, ShortCutHdl ) );
+}
+
+InsertDeleteFlags ScInsertContentsDlg::GetInsContentsCmdBits() const
+{
+ ScInsertContentsDlg::nPreviousChecks = InsertDeleteFlags::NONE;
+
+ if ( mxBtnInsStrings->get_active() )
+ ScInsertContentsDlg::nPreviousChecks = InsertDeleteFlags::STRING;
+ if ( mxBtnInsNumbers->get_active() )
+ ScInsertContentsDlg::nPreviousChecks |= InsertDeleteFlags::VALUE;
+ if ( mxBtnInsDateTime->get_active())
+ ScInsertContentsDlg::nPreviousChecks |= InsertDeleteFlags::DATETIME;
+ if ( mxBtnInsFormulas->get_active())
+ ScInsertContentsDlg::nPreviousChecks |= InsertDeleteFlags::FORMULA;
+ if ( mxBtnInsNotes->get_active() )
+ ScInsertContentsDlg::nPreviousChecks |= InsertDeleteFlags::NOTE;
+ if ( mxBtnInsAttrs->get_active() )
+ ScInsertContentsDlg::nPreviousChecks |= InsertDeleteFlags::ATTRIB;
+ if ( mxBtnInsObjects->get_active() )
+ ScInsertContentsDlg::nPreviousChecks |= InsertDeleteFlags::OBJECTS;
+
+ return ( mxBtnInsAll->get_active()
+ ? InsertDeleteFlags::ALL
+ : ScInsertContentsDlg::nPreviousChecks );
+}
+
+void ScInsertContentsDlg::SetInsContentsCmdBits(const InsertDeleteFlags eFlags)
+{
+ mxBtnInsNumbers->set_active((InsertDeleteFlags::VALUE & eFlags) == InsertDeleteFlags::VALUE);
+ mxBtnInsDateTime->set_active((InsertDeleteFlags::DATETIME & eFlags) == InsertDeleteFlags::DATETIME);
+ mxBtnInsStrings->set_active((InsertDeleteFlags::STRING & eFlags) == InsertDeleteFlags::STRING);
+ mxBtnInsNotes->set_active((InsertDeleteFlags::NOTE & eFlags) == InsertDeleteFlags::NOTE);
+ mxBtnInsFormulas->set_active((InsertDeleteFlags::FORMULA & eFlags) == InsertDeleteFlags::FORMULA);
+ mxBtnInsAttrs->set_active((InsertDeleteFlags::ATTRIB & eFlags) == InsertDeleteFlags::ATTRIB);
+ mxBtnInsObjects->set_active((InsertDeleteFlags::OBJECTS & eFlags) == InsertDeleteFlags::OBJECTS);
+ mxBtnInsAll->set_active((InsertDeleteFlags::ALL & eFlags) == InsertDeleteFlags::ALL);
+ DisableChecks( mxBtnInsAll->get_active() );
+}
+
+void ScInsertContentsDlg::SetFormulaCmdBits(const ScPasteFunc eFlags)
+{
+ switch( eFlags )
+ {
+ case ScPasteFunc::NONE: mxRbNoOp->set_active(true); break;
+ case ScPasteFunc::ADD: mxRbAdd->set_active(true); break;
+ case ScPasteFunc::SUB: mxRbSub->set_active(true); break;
+ case ScPasteFunc::MUL: mxRbMul->set_active(true); break;
+ case ScPasteFunc::DIV: mxRbDiv->set_active(true); break;
+ }
+}
+
+void ScInsertContentsDlg::SetCellCmdFlags(const InsCellCmd eFlags)
+{
+ switch( eFlags )
+ {
+ case INS_NONE: mxRbMoveNone->set_active(true); break;
+ case INS_CELLSDOWN: mxRbMoveDown->set_active(true); break;
+ case INS_CELLSRIGHT: mxRbMoveRight->set_active(true); break;
+ case INS_INSROWS_BEFORE:
+ case INS_INSCOLS_BEFORE:
+ case INS_INSROWS_AFTER:
+ case INS_INSCOLS_AFTER: break;
+ }
+}
+
+void ScInsertContentsDlg::SetContentsFlags(const InsertContentsFlags eFlags)
+{
+ mxBtnSkipEmptyCells->set_active(bool(InsertContentsFlags::NoEmpty & eFlags));
+ mxBtnTranspose->set_active(bool(InsertContentsFlags::Trans & eFlags));
+ mxBtnLink->set_active(bool(InsertContentsFlags::Link & eFlags));
+}
+
+InsCellCmd ScInsertContentsDlg::GetMoveMode() const
+{
+ if ( mxRbMoveDown->get_active() )
+ return INS_CELLSDOWN;
+ if ( mxRbMoveRight->get_active() )
+ return INS_CELLSRIGHT;
+
+ return INS_NONE;
+}
+
+bool ScInsertContentsDlg::IsSkipEmptyCells() const
+{
+ return mxBtnSkipEmptyCells->get_active();
+}
+
+bool ScInsertContentsDlg::IsTranspose() const
+{
+ return mxBtnTranspose->get_active();
+}
+
+bool ScInsertContentsDlg::IsLink() const
+{
+ return mxBtnLink->get_active();
+}
+
+void ScInsertContentsDlg::DisableChecks( bool bInsAllChecked )
+{
+ if ( bInsAllChecked )
+ {
+ mxBtnInsStrings->set_sensitive(false);
+ mxBtnInsNumbers->set_sensitive(false);
+ mxBtnInsDateTime->set_sensitive(false);
+ mxBtnInsFormulas->set_sensitive(false);
+ mxBtnInsNotes->set_sensitive(false);
+ mxBtnInsAttrs->set_sensitive(false);
+ mxBtnInsObjects->set_sensitive(false);
+ }
+ else
+ {
+ mxBtnInsStrings->set_sensitive(true);
+ mxBtnInsNumbers->set_sensitive(true);
+ mxBtnInsDateTime->set_sensitive(true);
+ mxBtnInsFormulas->set_sensitive(true);
+ mxBtnInsNotes->set_sensitive(true);
+ mxBtnInsAttrs->set_sensitive(true);
+
+ // "Objects" is disabled for "Fill Tables"
+ if ( bFillMode )
+ mxBtnInsObjects->set_sensitive(false);
+ else
+ mxBtnInsObjects->set_sensitive(true);
+ }
+}
+
+// Link to other document -> everything else is disabled
+
+void ScInsertContentsDlg::TestModes()
+{
+ if ( bOtherDoc && mxBtnLink->get_active() )
+ {
+ mxBtnSkipEmptyCells->set_sensitive(false);
+ mxBtnTranspose->set_sensitive(false);
+ mxRbNoOp->set_sensitive(false);
+ mxRbAdd->set_sensitive(false);
+ mxRbSub->set_sensitive(false);
+ mxRbMul->set_sensitive(false);
+ mxRbDiv->set_sensitive(false);
+
+ mxRbMoveNone->set_sensitive(false);
+ mxRbMoveDown->set_sensitive(false);
+ mxRbMoveRight->set_sensitive(false);
+
+ mxBtnInsAll->set_sensitive(false);
+ DisableChecks(true);
+ }
+ else
+ {
+ mxBtnSkipEmptyCells->set_sensitive(true);
+ mxBtnTranspose->set_sensitive(!bFillMode);
+ mxRbNoOp->set_sensitive(true);
+ mxRbAdd->set_sensitive(true);
+ mxRbSub->set_sensitive(true);
+ mxRbMul->set_sensitive(true);
+ mxRbDiv->set_sensitive(true);
+
+ mxRbMoveNone->set_sensitive(!bFillMode && !bChangeTrack && !(bMoveDownDisabled && bMoveRightDisabled));
+ mxRbMoveDown->set_sensitive(!bFillMode && !bChangeTrack && !bMoveDownDisabled);
+ mxRbMoveRight->set_sensitive(!bFillMode && !bChangeTrack && !bMoveRightDisabled);
+
+ mxBtnInsAll->set_sensitive(true);
+ DisableChecks( mxBtnInsAll->get_active() );
+ }
+}
+
+void ScInsertContentsDlg::SetOtherDoc( bool bSet )
+{
+ if ( bSet != bOtherDoc )
+ {
+ bOtherDoc = bSet;
+ TestModes();
+ if ( bSet )
+ mxRbMoveNone->set_active(true);
+ }
+}
+
+void ScInsertContentsDlg::SetFillMode( bool bSet )
+{
+ if ( bSet != bFillMode )
+ {
+ bFillMode = bSet;
+ TestModes();
+ if ( bSet )
+ mxRbMoveNone->set_active(true);
+ }
+}
+
+void ScInsertContentsDlg::SetChangeTrack( bool bSet )
+{
+ if ( bSet != bChangeTrack )
+ {
+ bChangeTrack = bSet;
+ TestModes();
+ if ( bSet )
+ mxRbMoveNone->set_active(true);
+ }
+}
+
+void ScInsertContentsDlg::SetCellShiftDisabled( CellShiftDisabledFlags nDisable )
+{
+ bool bDown(nDisable & CellShiftDisabledFlags::Down);
+ bool bRight(nDisable & CellShiftDisabledFlags::Right);
+ if ( bDown != bMoveDownDisabled || bRight != bMoveRightDisabled )
+ {
+ bMoveDownDisabled = bDown;
+ bMoveRightDisabled = bRight;
+ TestModes();
+ if ( bMoveDownDisabled && mxRbMoveDown->get_active() )
+ mxRbMoveNone->set_active(true);
+ if ( bMoveRightDisabled && mxRbMoveRight->get_active() )
+ mxRbMoveNone->set_active(true);
+ }
+}
+
+IMPL_LINK(ScInsertContentsDlg, ShortCutHdl, weld::Button&, rBtn, void)
+{
+ if (&rBtn == mxBtnShortCutPasteValuesOnly.get())
+ {
+ SetInsContentsCmdBits( InsertDeleteFlags::STRING | InsertDeleteFlags::VALUE | InsertDeleteFlags::DATETIME );
+ SetContentsFlags( InsertContentsFlags::NONE );
+ }
+ else if (&rBtn == mxBtnShortCutPasteValuesFormats.get())
+ {
+ SetInsContentsCmdBits( InsertDeleteFlags::STRING | InsertDeleteFlags::VALUE | InsertDeleteFlags::DATETIME | InsertDeleteFlags::ATTRIB );
+ SetContentsFlags( InsertContentsFlags::NONE );
+ }
+ else if (&rBtn == mxBtnShortCutPasteTranspose.get())
+ {
+ SetInsContentsCmdBits( InsertDeleteFlags::ALL );
+ SetContentsFlags( InsertContentsFlags::Trans );
+ }
+ else if (&rBtn == mxBtnShortCutPasteFormats.get())
+ {
+ SetInsContentsCmdBits( InsertDeleteFlags::ATTRIB );
+ SetContentsFlags( InsertContentsFlags::NONE );
+ }
+ else
+ return;
+
+ SetCellCmdFlags( InsCellCmd::INS_NONE );
+ SetFormulaCmdBits(ScPasteFunc::NONE);
+ if (mxImmediately->get_active()) m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScInsertContentsDlg, InsAllHdl, weld::Toggleable&, void)
+{
+ DisableChecks( mxBtnInsAll->get_active() );
+}
+
+IMPL_LINK_NOARG(ScInsertContentsDlg, LinkBtnHdl, weld::Toggleable&, void)
+{
+ TestModes();
+}
+
+ScInsertContentsDlg::~ScInsertContentsDlg()
+{
+ ScInsertContentsDlg::nPreviousChecks2 = InsertContentsFlags::NONE;
+ if(mxBtnSkipEmptyCells->get_active())
+ ScInsertContentsDlg::nPreviousChecks2 |= InsertContentsFlags::NoEmpty;
+ if( mxBtnTranspose->get_active())
+ ScInsertContentsDlg::nPreviousChecks2 |= InsertContentsFlags::Trans;
+ if( mxBtnLink->get_active() )
+ ScInsertContentsDlg::nPreviousChecks2 |= InsertContentsFlags::Link;
+
+ if (!bFillMode) // in FillMode, None is checked and all three options are disabled
+ {
+ if ( mxRbMoveNone->get_active() )
+ ScInsertContentsDlg::nPreviousMoveMode = INS_NONE;
+ else if ( mxRbMoveDown->get_active() )
+ ScInsertContentsDlg::nPreviousMoveMode = INS_CELLSDOWN;
+ else if ( mxRbMoveRight->get_active() )
+ ScInsertContentsDlg::nPreviousMoveMode = INS_CELLSRIGHT;
+ }
+}
+
+ScPasteFunc ScInsertContentsDlg::GetFormulaCmdBits() const
+{
+ ScInsertContentsDlg::nPreviousFormulaChecks = ScPasteFunc::NONE;
+ if(mxRbAdd->get_active())
+ ScInsertContentsDlg::nPreviousFormulaChecks = ScPasteFunc::ADD;
+ else if(mxRbSub->get_active())
+ ScInsertContentsDlg::nPreviousFormulaChecks = ScPasteFunc::SUB;
+ else if(mxRbMul->get_active())
+ ScInsertContentsDlg::nPreviousFormulaChecks = ScPasteFunc::MUL;
+ else if(mxRbDiv->get_active())
+ ScInsertContentsDlg::nPreviousFormulaChecks = ScPasteFunc::DIV;
+ return ScInsertContentsDlg::nPreviousFormulaChecks;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/instbdlg.cxx b/sc/source/ui/miscdlgs/instbdlg.cxx
new file mode 100644
index 000000000..947b983ec
--- /dev/null
+++ b/sc/source/ui/miscdlgs/instbdlg.cxx
@@ -0,0 +1,356 @@
+/* -*- 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 <sfx2/docfile.hxx>
+#include <sfx2/docinsert.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <svtools/ehdl.hxx>
+#include <svtools/sfxecode.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+#include <docsh.hxx>
+#include <viewdata.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <instbdlg.hxx>
+
+ScInsertTableDlg::ScInsertTableDlg(weld::Window* pParent, ScViewData& rData, SCTAB nTabCount, bool bFromFile)
+ : GenericDialogController(pParent, "modules/scalc/ui/insertsheet.ui", "InsertSheetDialog")
+ , aBrowseTimer("ScInsertTableDlg aBrowseTimer")
+ , rViewData(rData)
+ , rDoc(rData.GetDocument())
+ , pDocShTables(nullptr)
+ , bMustClose(false)
+ , nSelTabIndex(0)
+ , nTableCount(nTabCount)
+ , m_xBtnBefore(m_xBuilder->weld_radio_button("before"))
+ , m_xBtnBehind(m_xBuilder->weld_radio_button("after"))
+ , m_xBtnNew(m_xBuilder->weld_radio_button("new"))
+ , m_xBtnFromFile(m_xBuilder->weld_radio_button("fromfile"))
+ , m_xFtCount(m_xBuilder->weld_label("countft"))
+ , m_xNfCount(m_xBuilder->weld_spin_button("countnf"))
+ , m_xFtName(m_xBuilder->weld_label("nameft"))
+ , m_xEdName(m_xBuilder->weld_entry("nameed"))
+ , m_xLbTables(m_xBuilder->weld_tree_view("tables"))
+ , m_xFtPath(m_xBuilder->weld_label("path"))
+ , m_xBtnBrowse(m_xBuilder->weld_button("browse"))
+ , m_xBtnLink(m_xBuilder->weld_check_button("link"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+{
+ m_sSheetDotDotDot = m_xEdName->get_text();
+ m_xLbTables->set_size_request(-1, m_xLbTables->get_height_rows(8));
+ Init_Impl(bFromFile);
+}
+
+ScInsertTableDlg::~ScInsertTableDlg()
+{
+ if (pDocShTables)
+ pDocShTables->DoClose();
+ pDocInserter.reset();
+}
+
+void ScInsertTableDlg::Init_Impl( bool bFromFile )
+{
+ m_xLbTables->set_selection_mode(SelectionMode::Multiple);
+ m_xBtnBrowse->connect_clicked( LINK( this, ScInsertTableDlg, BrowseHdl_Impl ) );
+ m_xBtnNew->connect_toggled( LINK( this, ScInsertTableDlg, ChoiceHdl_Impl ) );
+ m_xBtnFromFile->connect_toggled( LINK( this, ScInsertTableDlg, ChoiceHdl_Impl ) );
+ m_xLbTables->connect_changed( LINK( this, ScInsertTableDlg, SelectHdl_Impl ) );
+ m_xNfCount->connect_value_changed( LINK( this, ScInsertTableDlg, CountHdl_Impl));
+ m_xBtnOk->connect_clicked( LINK( this, ScInsertTableDlg, DoEnterHdl ));
+ m_xBtnBefore->set_active(true);
+
+ m_xNfCount->set_max(MAXTAB - rDoc.GetTableCount() + 1);
+ m_xNfCount->set_value(nTableCount);
+
+ if(nTableCount==1)
+ {
+ OUString aName;
+ rDoc.CreateValidTabName( aName );
+ m_xEdName->set_text( aName );
+ }
+ else
+ {
+ m_xEdName->set_text(m_sSheetDotDotDot);
+ m_xFtName->set_sensitive(false);
+ m_xEdName->set_sensitive(false);
+ }
+
+ bool bShared = rViewData.GetDocShell() && rViewData.GetDocShell()->IsDocShared();
+
+ if ( !bFromFile || bShared )
+ {
+ m_xBtnNew->set_active(true);
+ SetNewTable_Impl();
+ if ( bShared )
+ {
+ m_xBtnFromFile->set_sensitive(false);
+ }
+ }
+ else
+ {
+ m_xBtnFromFile->set_active(true);
+ SetFromTo_Impl();
+
+ aBrowseTimer.SetInvokeHandler( LINK( this, ScInsertTableDlg, BrowseTimeoutHdl ) );
+ aBrowseTimer.SetTimeout( 200 );
+ }
+}
+
+short ScInsertTableDlg::run()
+{
+ if (m_xBtnFromFile->get_active())
+ aBrowseTimer.Start();
+
+ return GenericDialogController::run();
+}
+
+void ScInsertTableDlg::SetNewTable_Impl()
+{
+ if (!m_xBtnNew->get_active() )
+ return;
+
+ m_xNfCount->set_sensitive(true);
+ m_xFtCount->set_sensitive(true);
+ m_xLbTables->set_sensitive(false);
+ m_xFtPath->set_sensitive(false);
+ m_xBtnBrowse->set_sensitive(false);
+ m_xBtnLink->set_sensitive(false);
+
+ if(nTableCount==1)
+ {
+ m_xEdName->set_sensitive(true);
+ m_xFtName->set_sensitive(true);
+ }
+}
+
+void ScInsertTableDlg::SetFromTo_Impl()
+{
+ if (m_xBtnFromFile->get_active() )
+ {
+ m_xEdName->set_sensitive(false);
+ m_xFtName->set_sensitive(false);
+ m_xFtCount->set_sensitive(false);
+ m_xNfCount->set_sensitive(false);
+ m_xLbTables->set_sensitive(true);
+ m_xFtPath->set_sensitive(true);
+ m_xBtnBrowse->set_sensitive(true);
+ m_xBtnLink->set_sensitive(true);
+ }
+}
+
+void ScInsertTableDlg::FillTables_Impl( const ScDocument* pSrcDoc )
+{
+ m_xLbTables->freeze();
+ m_xLbTables->clear();
+
+ if ( pSrcDoc )
+ {
+ SCTAB nCount = pSrcDoc->GetTableCount();
+ OUString aName;
+
+ for (SCTAB i=0; i<nCount; ++i)
+ {
+ pSrcDoc->GetName( i, aName );
+ m_xLbTables->append_text(aName);
+ }
+ }
+
+ m_xLbTables->thaw();
+
+ if (m_xLbTables->n_children() == 1)
+ m_xLbTables->select(0);
+}
+
+const OUString* ScInsertTableDlg::GetFirstTable( sal_uInt16* pN )
+{
+ const OUString* pStr = nullptr;
+
+ if ( m_xBtnNew->get_active() )
+ {
+ aStrCurSelTable = m_xEdName->get_text();
+ pStr = &aStrCurSelTable;
+ }
+ else
+ {
+ std::vector<int> aRows(m_xLbTables->get_selected_rows());
+ if (nSelTabIndex < aRows.size())
+ {
+ aStrCurSelTable = m_xLbTables->get_text(aRows[0]);
+ pStr = &aStrCurSelTable;
+ if ( pN )
+ *pN = aRows[0];
+ nSelTabIndex = 1;
+ }
+ }
+
+ return pStr;
+}
+
+const OUString* ScInsertTableDlg::GetNextTable( sal_uInt16* pN )
+{
+ if (m_xBtnNew->get_active())
+ return nullptr;
+
+ std::vector<int> aRows(m_xLbTables->get_selected_rows());
+
+ const OUString* pStr = nullptr;
+ if (nSelTabIndex < aRows.size())
+ {
+ aStrCurSelTable = m_xLbTables->get_text(aRows[nSelTabIndex]);
+ pStr = &aStrCurSelTable;
+ if ( pN )
+ *pN = aRows[nSelTabIndex];
+ nSelTabIndex++;
+ }
+
+ return pStr;
+}
+
+// Handler:
+
+IMPL_LINK_NOARG(ScInsertTableDlg, CountHdl_Impl, weld::SpinButton&, void)
+{
+ nTableCount = static_cast<SCTAB>(m_xNfCount->get_value());
+ if ( nTableCount==1)
+ {
+ OUString aName;
+ rDoc.CreateValidTabName( aName );
+ m_xEdName->set_text( aName );
+ m_xFtName->set_sensitive(true);
+ m_xEdName->set_sensitive(true);
+ }
+ else
+ {
+ m_xEdName->set_text(m_sSheetDotDotDot);
+ m_xFtName->set_sensitive(false);
+ m_xEdName->set_sensitive(false);
+ }
+
+ DoEnable_Impl();
+}
+
+IMPL_LINK(ScInsertTableDlg, ChoiceHdl_Impl, weld::Toggleable&, rButton, void)
+{
+ if (!rButton.get_active())
+ return;
+
+ if ( m_xBtnNew->get_active() )
+ SetNewTable_Impl();
+ else
+ SetFromTo_Impl();
+
+ DoEnable_Impl();
+}
+
+IMPL_LINK_NOARG(ScInsertTableDlg, BrowseHdl_Impl, weld::Button&, void)
+{
+ pDocInserter.reset();
+ pDocInserter.reset( new ::sfx2::DocumentInserter(m_xDialog.get(), ScDocShell::Factory().GetFactoryName()) );
+ pDocInserter->StartExecuteModal( LINK( this, ScInsertTableDlg, DialogClosedHdl ) );
+}
+
+IMPL_LINK_NOARG(ScInsertTableDlg, SelectHdl_Impl, weld::TreeView&, void)
+{
+ DoEnable_Impl();
+}
+
+void ScInsertTableDlg::DoEnable_Impl()
+{
+ if ( m_xBtnNew->get_active() || ( pDocShTables && m_xLbTables->count_selected_rows() ) )
+ m_xBtnOk->set_sensitive(true);
+ else
+ m_xBtnOk->set_sensitive(false);
+}
+
+IMPL_LINK_NOARG(ScInsertTableDlg, DoEnterHdl, weld::Button&, void)
+{
+ if (nTableCount > 1 || ScDocument::ValidTabName(m_xEdName->get_text()))
+ {
+ m_xDialog->response(RET_OK);
+ }
+ else
+ {
+ OUString aErrMsg ( ScResId( STR_INVALIDTABNAME ) );
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning,
+ VclButtonsType::Ok, aErrMsg));
+ xBox->run();
+ }
+}
+
+IMPL_LINK_NOARG(ScInsertTableDlg, BrowseTimeoutHdl, Timer *, void)
+{
+ bMustClose = true;
+ BrowseHdl_Impl(*m_xBtnBrowse);
+}
+
+IMPL_LINK( ScInsertTableDlg, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
+{
+ if ( ERRCODE_NONE == _pFileDlg->GetError() )
+ {
+ std::unique_ptr<SfxMedium> pMed = pDocInserter->CreateMedium();
+ if ( pMed )
+ {
+ // ERRCTX_SFX_OPENDOC -> "Error loading document"
+ SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
+
+ if ( pDocShTables )
+ pDocShTables->DoClose(); // deletion is done when assigning to the reference
+
+ pMed->UseInteractionHandler( true ); // to enable the filter options dialog
+
+ pDocShTables = new ScDocShell;
+ aDocShTablesRef = pDocShTables;
+
+ {
+ weld::WaitObject aWait(m_xDialog.get());
+ pDocShTables->DoLoad(pMed.release());
+ }
+
+ ErrCode nErr = pDocShTables->GetErrorCode();
+ if ( nErr )
+ ErrorHandler::HandleError(nErr, m_xDialog.get()); // warnings, too
+
+ if ( !pDocShTables->GetError() ) // errors only
+ {
+ FillTables_Impl( &pDocShTables->GetDocument() );
+ m_xFtPath->set_label(pDocShTables->GetTitle(SFX_TITLE_FULLNAME));
+ }
+ else
+ {
+ pDocShTables->DoClose();
+ aDocShTablesRef.clear();
+ pDocShTables = nullptr;
+
+ FillTables_Impl( nullptr );
+ m_xFtPath->set_label(OUString());
+ }
+ }
+
+ DoEnable_Impl();
+ }
+ else if ( bMustClose )
+ // execute slot FID_INS_TABLE_EXT and cancel file dialog
+ m_xDialog->response(RET_CANCEL);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/lbseldlg.cxx b/sc/source/ui/miscdlgs/lbseldlg.cxx
new file mode 100644
index 000000000..4c0b592c7
--- /dev/null
+++ b/sc/source/ui/miscdlgs/lbseldlg.cxx
@@ -0,0 +1,54 @@
+/* -*- 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 <lbseldlg.hxx>
+
+ScSelEntryDlg::ScSelEntryDlg(weld::Window* pParent, const std::vector<OUString> &rEntryList)
+ : GenericDialogController(pParent, "modules/scalc/ui/selectrange.ui", "SelectRangeDialog")
+ , m_xLb(m_xBuilder->weld_tree_view("treeview"))
+{
+ m_xLb->set_size_request(m_xLb->get_approximate_digit_width() * 32,
+ m_xLb->get_height_rows(8));
+ m_xLb->connect_row_activated(LINK(this, ScSelEntryDlg, DblClkHdl));
+
+ for (const auto& rEntry : rEntryList)
+ m_xLb->append_text(rEntry);
+
+ if (m_xLb->n_children() > 0)
+ m_xLb->select(0);
+}
+
+ScSelEntryDlg::~ScSelEntryDlg()
+{
+}
+
+OUString ScSelEntryDlg::GetSelectedEntry() const
+{
+ return m_xLb->get_selected_text();
+}
+
+IMPL_LINK_NOARG(ScSelEntryDlg, DblClkHdl, weld::TreeView&, bool)
+{
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/linkarea.cxx b/sc/source/ui/miscdlgs/linkarea.cxx
new file mode 100644
index 000000000..09cfe6c3c
--- /dev/null
+++ b/sc/source/ui/miscdlgs/linkarea.cxx
@@ -0,0 +1,336 @@
+/* -*- 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 <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/docinsert.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <svtools/ehdl.hxx>
+#include <svtools/inettbc.hxx>
+#include <svtools/sfxecode.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <linkarea.hxx>
+#include <docsh.hxx>
+#include <tablink.hxx>
+#include <scresid.hxx>
+#include <strings.hrc>
+
+ScLinkedAreaDlg::ScLinkedAreaDlg(weld::Widget* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/externaldata.ui", "ExternalDataDialog")
+ , m_pSourceShell(nullptr)
+ , m_xCbUrl(new SvtURLBox(m_xBuilder->weld_combo_box("url")))
+ , m_xBtnBrowse(m_xBuilder->weld_button("browse"))
+ , m_xLbRanges(m_xBuilder->weld_tree_view("ranges"))
+ , m_xBtnReload(m_xBuilder->weld_check_button("reload"))
+ , m_xNfDelay(m_xBuilder->weld_spin_button("delay"))
+ , m_xFtSeconds(m_xBuilder->weld_label("secondsft"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+{
+ m_xLbRanges->set_selection_mode(SelectionMode::Multiple);
+
+ m_xCbUrl->connect_entry_activate(LINK(this, ScLinkedAreaDlg, FileHdl));
+ m_xBtnBrowse->connect_clicked(LINK( this, ScLinkedAreaDlg, BrowseHdl));
+ m_xLbRanges->connect_changed(LINK( this, ScLinkedAreaDlg, RangeHdl));
+ m_xLbRanges->set_size_request(m_xLbRanges->get_approximate_digit_width() * 54,
+ m_xLbRanges->get_height_rows(5));
+ m_xBtnReload->connect_toggled(LINK( this, ScLinkedAreaDlg, ReloadHdl));
+ UpdateEnable();
+}
+
+ScLinkedAreaDlg::~ScLinkedAreaDlg()
+{
+}
+
+constexpr OUStringLiteral FILTERNAME_HTML = u"HTML (StarCalc)";
+constexpr OUStringLiteral FILTERNAME_QUERY = u"calc_HTML_WebQuery";
+
+IMPL_LINK_NOARG(ScLinkedAreaDlg, BrowseHdl, weld::Button&, void)
+{
+ m_xDocInserter.reset( new sfx2::DocumentInserter(m_xDialog.get(), ScDocShell::Factory().GetFactoryName()) );
+ m_xDocInserter->StartExecuteModal( LINK( this, ScLinkedAreaDlg, DialogClosedHdl ) );
+}
+
+IMPL_LINK_NOARG(ScLinkedAreaDlg, FileHdl, weld::ComboBox&, bool)
+{
+ OUString aEntered = m_xCbUrl->GetURL();
+ if (m_pSourceShell)
+ {
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
+ if ( aEntered == pMed->GetName() )
+ {
+ // already loaded - nothing to do
+ return true;
+ }
+ }
+
+ OUString aFilter;
+ OUString aOptions;
+ // get filter name by looking at the file content (bWithContent = true)
+ // Break operation if any error occurred inside.
+ if (!ScDocumentLoader::GetFilterName( aEntered, aFilter, aOptions, true, false ))
+ return true;
+
+ // #i53241# replace HTML filter with DataQuery filter
+ if (aFilter == FILTERNAME_HTML)
+ aFilter = FILTERNAME_QUERY;
+
+ LoadDocument( aEntered, aFilter, aOptions );
+
+ UpdateSourceRanges();
+ UpdateEnable();
+
+ return true;
+}
+
+void ScLinkedAreaDlg::LoadDocument( const OUString& rFile, const OUString& rFilter, const OUString& rOptions )
+{
+ if (m_pSourceShell)
+ {
+ // unload old document
+ m_pSourceShell->DoClose();
+ m_pSourceShell = nullptr;
+ aSourceRef.clear();
+ }
+
+ if ( rFile.isEmpty() )
+ return;
+
+ weld::WaitObject aWait(m_xDialog.get());
+
+ OUString aNewFilter = rFilter;
+ OUString aNewOptions = rOptions;
+
+ SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, rFile );
+
+ ScDocumentLoader aLoader( rFile, aNewFilter, aNewOptions, 0, m_xDialog.get() ); // with interaction
+ m_pSourceShell = aLoader.GetDocShell();
+ if (m_pSourceShell)
+ {
+ ErrCode nErr = m_pSourceShell->GetErrorCode();
+ if (nErr)
+ ErrorHandler::HandleError( nErr ); // including warnings
+
+ aSourceRef = m_pSourceShell;
+ aLoader.ReleaseDocRef(); // don't call DoClose in DocLoader dtor
+ }
+}
+
+void ScLinkedAreaDlg::InitFromOldLink( const OUString& rFile, const OUString& rFilter,
+ const OUString& rOptions, std::u16string_view rSource,
+ sal_Int32 nRefreshDelaySeconds )
+{
+ LoadDocument( rFile, rFilter, rOptions );
+ if (m_pSourceShell)
+ {
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
+ m_xCbUrl->set_entry_text(pMed->GetName());
+ }
+ else
+ m_xCbUrl->set_entry_text(OUString());
+
+ UpdateSourceRanges();
+
+ if (!rSource.empty())
+ {
+ sal_Int32 nIdx {0};
+ do
+ {
+ m_xLbRanges->select_text(OUString(o3tl::getToken(rSource, 0, ';', nIdx)));
+ }
+ while (nIdx>0);
+ }
+
+ bool bDoRefresh = (nRefreshDelaySeconds != 0);
+ m_xBtnReload->set_active(bDoRefresh);
+ if (bDoRefresh)
+ m_xNfDelay->set_value(nRefreshDelaySeconds);
+
+ UpdateEnable();
+}
+
+IMPL_LINK_NOARG(ScLinkedAreaDlg, RangeHdl, weld::TreeView&, void)
+{
+ UpdateEnable();
+}
+
+IMPL_LINK_NOARG(ScLinkedAreaDlg, ReloadHdl, weld::Toggleable&, void)
+{
+ UpdateEnable();
+}
+
+IMPL_LINK( ScLinkedAreaDlg, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
+{
+ if ( _pFileDlg->GetError() != ERRCODE_NONE )
+ return;
+
+ std::unique_ptr<SfxMedium> pMed = m_xDocInserter->CreateMedium();
+ if ( pMed )
+ {
+ weld::WaitObject aWait(m_xDialog.get());
+
+ // replace HTML filter with DataQuery filter
+ std::shared_ptr<const SfxFilter> pFilter = pMed->GetFilter();
+ if (pFilter && FILTERNAME_HTML == pFilter->GetFilterName())
+ {
+ std::shared_ptr<const SfxFilter> pNewFilter =
+ ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( FILTERNAME_QUERY );
+ if( pNewFilter )
+ pMed->SetFilter( pNewFilter );
+ }
+
+ // ERRCTX_SFX_OPENDOC -> "Error loading document"
+ SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
+
+ if (m_pSourceShell)
+ m_pSourceShell->DoClose(); // deleted when assigning aSourceRef
+
+ pMed->UseInteractionHandler( true ); // to enable the filter options dialog
+
+ m_pSourceShell = new ScDocShell;
+ aSourceRef = m_pSourceShell;
+ m_pSourceShell->DoLoad( pMed.get() );
+
+ ErrCode nErr = m_pSourceShell->GetErrorCode();
+ if (nErr)
+ ErrorHandler::HandleError( nErr ); // including warnings
+
+ if (!m_pSourceShell->GetError()) // only errors
+ {
+ m_xCbUrl->set_entry_text(pMed->GetName());
+ }
+ else
+ {
+ m_pSourceShell->DoClose();
+ m_pSourceShell = nullptr;
+ aSourceRef.clear();
+
+ m_xCbUrl->set_entry_text(OUString());
+ }
+ pMed.release(); // DoLoad takes ownership
+ }
+
+ UpdateSourceRanges();
+ UpdateEnable();
+}
+
+#undef FILTERNAME_HTML
+#undef FILTERNAME_QUERY
+
+void ScLinkedAreaDlg::UpdateSourceRanges()
+{
+ m_xLbRanges->freeze();
+
+ m_xLbRanges->clear();
+ if ( m_pSourceShell )
+ {
+ std::shared_ptr<const SfxFilter> pFilter = m_pSourceShell->GetMedium()->GetFilter();
+ if (pFilter && pFilter->GetFilterName() == SC_TEXT_CSV_FILTER_NAME)
+ {
+ // Insert dummy All range to have something selectable.
+ m_xLbRanges->append_text("CSV_all");
+ }
+
+ // tdf#142600 - list tables in order of their appearance in the document's source
+ const ScRangeName* pRangeName = m_pSourceShell->GetDocument().GetRangeName();
+ for (size_t i = 1; i <= pRangeName->index_size(); i++)
+ {
+ if (const ScRangeData* pRangeData = pRangeName->findByIndex(i))
+ {
+ m_xLbRanges->append_text(pRangeData->GetName());
+ }
+ }
+ }
+
+ m_xLbRanges->thaw();
+
+ if (m_xLbRanges->n_children() >= 1)
+ m_xLbRanges->select(0);
+ else
+ {
+ m_xLbRanges->append_text(ScResId(STR_NO_NAMED_RANGES_AVAILABLE));
+ m_xLbRanges->set_sensitive(false);
+ }
+}
+
+void ScLinkedAreaDlg::UpdateEnable()
+{
+ bool bEnable = ( m_pSourceShell && m_xLbRanges->count_selected_rows() );
+ m_xBtnOk->set_sensitive(bEnable);
+
+ bool bReload = m_xBtnReload->get_active();
+ m_xNfDelay->set_sensitive(bReload);
+ m_xFtSeconds->set_sensitive(bReload);
+}
+
+OUString ScLinkedAreaDlg::GetURL() const
+{
+ if (m_pSourceShell)
+ {
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
+ return pMed->GetName();
+ }
+ return OUString();
+}
+
+OUString ScLinkedAreaDlg::GetFilter() const
+{
+ if (m_pSourceShell)
+ {
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
+ return pMed->GetFilter()->GetFilterName();
+ }
+ return OUString();
+}
+
+OUString ScLinkedAreaDlg::GetOptions() const
+{
+ if (m_pSourceShell)
+ {
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
+ return ScDocumentLoader::GetOptions( *pMed );
+ }
+ return OUString();
+}
+
+OUString ScLinkedAreaDlg::GetSource() const
+{
+ OUStringBuffer aBuf;
+ std::vector<OUString> aSelection = m_xLbRanges->get_selected_rows_text();
+ for (size_t i = 0; i < aSelection.size(); ++i)
+ {
+ if (i > 0)
+ aBuf.append(';');
+ aBuf.append(aSelection[i]);
+ }
+ return aBuf.makeStringAndClear();
+}
+
+sal_Int32 ScLinkedAreaDlg::GetRefreshDelaySeconds() const
+{
+ if (m_xBtnReload->get_active())
+ return m_xNfDelay->get_value();
+ else
+ return 0; // disabled
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/mergecellsdialog.cxx b/sc/source/ui/miscdlgs/mergecellsdialog.cxx
new file mode 100644
index 000000000..2bfcc5da3
--- /dev/null
+++ b/sc/source/ui/miscdlgs/mergecellsdialog.cxx
@@ -0,0 +1,36 @@
+/* -*- 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 <mergecellsdialog.hxx>
+
+ScMergeCellsDialog::ScMergeCellsDialog(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/mergecellsdialog.ui", "MergeCellsDialog")
+ , m_xRBMoveContent(m_xBuilder->weld_radio_button("move-cells-radio"))
+ , m_xRBKeepContent(m_xBuilder->weld_radio_button("keep-content-radio"))
+ , m_xRBEmptyContent(m_xBuilder->weld_radio_button("empty-cells-radio"))
+{
+ m_xRBKeepContent->set_active(true);
+}
+
+ScMergeCellsDialog::~ScMergeCellsDialog() {}
+
+ScMergeCellsOption ScMergeCellsDialog::GetMergeCellsOption() const
+{
+ if (m_xRBMoveContent->get_active())
+ return MoveContentHiddenCells;
+ if (m_xRBKeepContent->get_active())
+ return KeepContentHiddenCells;
+ if (m_xRBEmptyContent->get_active())
+ return EmptyContentHiddenCells;
+ assert(!"Unknown selection for merge cells.");
+ return KeepContentHiddenCells; // default value
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/mtrindlg.cxx b/sc/source/ui/miscdlgs/mtrindlg.cxx
new file mode 100644
index 000000000..7f234131f
--- /dev/null
+++ b/sc/source/ui/miscdlgs/mtrindlg.cxx
@@ -0,0 +1,104 @@
+/* -*- 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 <mtrindlg.hxx>
+
+ScMetricInputDlg::ScMetricInputDlg( weld::Window* pParent,
+ const OString& sDialogName,
+ tools::Long nCurrent,
+ tools::Long nDefault,
+ FieldUnit eFUnit,
+ sal_uInt16 nDecimals,
+ tools::Long nMaximum,
+ tools::Long nMinimum)
+
+ : GenericDialogController(pParent, "modules/scalc/ui/" + OStringToOUString(
+ sDialogName.toAsciiLowerCase(), RTL_TEXTENCODING_UTF8) + ".ui", sDialogName)
+ , m_xEdValue(m_xBuilder->weld_metric_spin_button("value", FieldUnit::CM))
+ , m_xBtnDefVal(m_xBuilder->weld_check_button("default"))
+{
+ m_xBtnDefVal->connect_toggled(LINK(this, ScMetricInputDlg, SetDefValHdl));
+ m_xEdValue->connect_value_changed(LINK( this, ScMetricInputDlg, ModifyHdl));
+
+ m_xEdValue->set_unit(eFUnit);
+ m_xEdValue->set_digits(nDecimals);
+ m_xEdValue->set_range(m_xEdValue->normalize(nMinimum),
+ m_xEdValue->normalize(nMaximum), FieldUnit::TWIP);
+
+ sal_Int64 nMin(0), nMax(0);
+ m_xEdValue->get_range(nMin, nMax, FieldUnit::TWIP);
+
+ auto nIncrement = m_xEdValue->normalize(1);
+ m_xEdValue->set_increments(nIncrement / 10, nIncrement, FieldUnit::NONE);
+ m_xEdValue->set_value(m_xEdValue->normalize(nDefault), FieldUnit::TWIP);
+ nDefaultValue = m_xEdValue->get_value(FieldUnit::NONE);
+ m_xEdValue->set_value(m_xEdValue->normalize(nCurrent), FieldUnit::TWIP);
+ nCurrentValue = m_xEdValue->get_value(FieldUnit::NONE);
+ m_xBtnDefVal->set_active(nCurrentValue == nDefaultValue);
+}
+
+ScMetricInputDlg::~ScMetricInputDlg()
+{
+}
+
+int ScMetricInputDlg::GetInputValue() const
+{
+/*
+ with decimal digits
+
+ double nVal = m_xEdValue->GetValue( eUnit );
+ sal_uInt16 nDecs = m_xEdValue->GetDecimalDigits();
+ double nFactor = 0.0;
+
+ // static long ImpPower10( sal_uInt16 nDecs )
+ {
+ nFactor = 1.0;
+
+ for ( sal_uInt16 i=0; i < nDecs; i++ )
+ nFactor *= 10.0;
+ }
+
+ return nVal / nFactor;
+*/
+ // first cut off the decimal digits - not that great...
+
+ return m_xEdValue->denormalize(m_xEdValue->get_value(FieldUnit::TWIP));
+}
+
+// Handler:
+
+IMPL_LINK_NOARG(ScMetricInputDlg, SetDefValHdl, weld::Toggleable&, void)
+{
+ if (m_xBtnDefVal->get_active())
+ {
+ nCurrentValue = m_xEdValue->get_value(FieldUnit::NONE);
+ m_xEdValue->set_value(nDefaultValue, FieldUnit::NONE);
+ }
+ else
+ m_xEdValue->set_value(nCurrentValue, FieldUnit::NONE);
+}
+
+IMPL_LINK_NOARG(ScMetricInputDlg, ModifyHdl, weld::MetricSpinButton&, void)
+{
+ m_xBtnDefVal->set_active(nDefaultValue == m_xEdValue->get_value(FieldUnit::NONE));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/mvtabdlg.cxx b/sc/source/ui/miscdlgs/mvtabdlg.cxx
new file mode 100644
index 000000000..80eeaeade
--- /dev/null
+++ b/sc/source/ui/miscdlgs/mvtabdlg.cxx
@@ -0,0 +1,319 @@
+/* -*- 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 <mvtabdlg.hxx>
+#include <document.hxx>
+#include <docsh.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <comphelper/lok.hxx>
+
+ScMoveTableDlg::ScMoveTableDlg(weld::Window* pParent, const OUString& rDefault)
+ : GenericDialogController(pParent, "modules/scalc/ui/movecopysheet.ui", "MoveCopySheetDialog")
+ , maDefaultName(rDefault)
+ , mnCurrentDocPos(0)
+ , nDocument(0)
+ , nTable(0)
+ , bCopyTable(false)
+ , bRenameTable(false)
+ , mbEverEdited(false)
+ , m_xBtnMove(m_xBuilder->weld_radio_button("move"))
+ , m_xBtnCopy(m_xBuilder->weld_radio_button("copy"))
+ , m_xFtDoc(m_xBuilder->weld_label("toDocumentLabel"))
+ , m_xLbDoc(m_xBuilder->weld_combo_box("toDocument"))
+ , m_xLbTable(m_xBuilder->weld_tree_view("insertBefore"))
+ , m_xEdTabName(m_xBuilder->weld_entry("newName"))
+ , m_xFtWarn(m_xBuilder->weld_label("newNameWarn"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xUnusedLabel(m_xBuilder->weld_label("warnunused"))
+ , m_xEmptyLabel(m_xBuilder->weld_label("warnempty"))
+ , m_xInvalidLabel(m_xBuilder->weld_label("warninvalid"))
+{
+ assert(m_xLbDoc->get_count() == 2);
+ msCurrentDoc = m_xLbDoc->get_text(0);
+ msNewDoc = m_xLbDoc->get_text(1);
+ m_xLbDoc->clear();
+ assert(m_xLbDoc->get_count() == 0);
+
+ m_xLbTable->set_size_request(-1, m_xLbTable->get_height_rows(8));
+
+ msStrTabNameUsed = m_xUnusedLabel->get_label();
+ msStrTabNameEmpty = m_xEmptyLabel->get_label();
+ msStrTabNameInvalid = m_xInvalidLabel->get_label();
+
+ Init();
+}
+
+ScMoveTableDlg::~ScMoveTableDlg() {}
+
+void ScMoveTableDlg::GetTabNameString(OUString& rString) const
+{
+ rString = m_xEdTabName->get_text();
+}
+
+void ScMoveTableDlg::SetForceCopyTable()
+{
+ m_xBtnCopy->set_active(true);
+ m_xBtnMove->set_sensitive(false);
+ m_xBtnCopy->set_sensitive(false);
+ SetOkBtnLabel();
+}
+
+void ScMoveTableDlg::EnableRenameTable(bool bFlag)
+{
+ bRenameTable = bFlag;
+ m_xEdTabName->set_sensitive(bFlag);
+ ResetRenameInput();
+}
+
+void ScMoveTableDlg::ResetRenameInput()
+{
+ if (mbEverEdited)
+ {
+ // Don't reset the name when the sheet name has ever been edited.
+ // But check the name, as this is also called for change of copy/move
+ // buttons and document listbox selection.
+ CheckNewTabName();
+ return;
+ }
+
+ if (!m_xEdTabName->get_sensitive())
+ {
+ m_xEdTabName->set_text(OUString());
+ return;
+ }
+
+ bool bVal = m_xBtnCopy->get_active();
+ if (bVal)
+ {
+ // copy
+ ScDocument* pDoc = GetSelectedDoc();
+ if (pDoc)
+ {
+ OUString aStr = maDefaultName;
+ pDoc->CreateValidTabName(aStr);
+ m_xEdTabName->set_text(aStr);
+ }
+ else
+ m_xEdTabName->set_text(maDefaultName);
+ }
+ else
+ {
+ // move
+ m_xEdTabName->set_text(maDefaultName);
+ }
+
+ CheckNewTabName();
+}
+
+void ScMoveTableDlg::CheckNewTabName()
+{
+ const OUString aNewName = m_xEdTabName->get_text();
+ if (aNewName.isEmpty())
+ {
+ // New sheet name is empty. This is not good.
+ m_xFtWarn->show();
+ //TODO m_xFtWarn->SetControlBackground(COL_YELLOW);
+ m_xFtWarn->set_label(msStrTabNameEmpty);
+ m_xBtnOk->set_sensitive(false);
+ return;
+ }
+
+ if (!ScDocument::ValidTabName(aNewName))
+ {
+ // New sheet name contains invalid characters.
+ m_xFtWarn->show();
+ //TODO m_xFtWarn->SetControlBackground(COL_YELLOW);
+ m_xFtWarn->set_label(msStrTabNameInvalid);
+ m_xBtnOk->set_sensitive(false);
+ return;
+ }
+
+ bool bMoveInCurrentDoc = m_xBtnMove->get_active() && m_xLbDoc->get_active() == mnCurrentDocPos;
+ bool bFound = false;
+ const int nLast = m_xLbTable->n_children();
+ for (int i = 0; i < nLast && !bFound; ++i)
+ {
+ if (aNewName == m_xLbTable->get_text(i))
+ {
+ // Only for move within same document the same name is allowed.
+ if (!bMoveInCurrentDoc || maDefaultName != m_xEdTabName->get_text())
+ bFound = true;
+ }
+ }
+
+ if (bFound)
+ {
+ m_xFtWarn->show();
+ //TODO m_xFtWarn->SetControlBackground(COL_YELLOW);
+ m_xFtWarn->set_label(msStrTabNameUsed);
+ m_xBtnOk->set_sensitive(false);
+ }
+ else
+ {
+ m_xFtWarn->hide();
+ //TODO m_xFtWarn->SetControlBackground();
+ m_xFtWarn->set_label(OUString());
+ m_xBtnOk->set_sensitive(true);
+ }
+}
+
+ScDocument* ScMoveTableDlg::GetSelectedDoc()
+{
+ return weld::fromId<ScDocument*>(m_xLbDoc->get_active_id());
+}
+
+void ScMoveTableDlg::Init()
+{
+ m_xBtnOk->connect_clicked(LINK(this, ScMoveTableDlg, OkHdl));
+ m_xLbDoc->connect_changed(LINK(this, ScMoveTableDlg, SelHdl));
+ m_xBtnCopy->connect_toggled(LINK(this, ScMoveTableDlg, CheckBtnHdl));
+ m_xBtnMove->connect_toggled(LINK(this, ScMoveTableDlg, CheckBtnHdl));
+ m_xEdTabName->connect_changed(LINK(this, ScMoveTableDlg, CheckNameHdl));
+ m_xBtnMove->set_active(true);
+ m_xBtnCopy->set_active(false);
+ m_xEdTabName->set_sensitive(false);
+ m_xFtWarn->hide();
+ InitDocListBox();
+ SelHdl(*m_xLbDoc);
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ m_xFtDoc->hide();
+ m_xLbDoc->hide();
+ }
+ SetOkBtnLabel();
+}
+
+void ScMoveTableDlg::InitDocListBox()
+{
+ SfxObjectShell* pSh = SfxObjectShell::GetFirst();
+ ScDocShell* pScSh = nullptr;
+ sal_uInt16 nSelPos = 0;
+ sal_uInt16 i = 0;
+
+ m_xLbDoc->clear();
+ m_xLbDoc->freeze();
+
+ while (pSh)
+ {
+ pScSh = dynamic_cast<ScDocShell*>(pSh);
+
+ if (pScSh)
+ {
+ OUString aEntryName = pScSh->GetTitle();
+
+ if (pScSh == SfxObjectShell::Current())
+ {
+ mnCurrentDocPos = nSelPos = i;
+ aEntryName += " " + msCurrentDoc;
+ }
+
+ OUString sId(weld::toId(&pScSh->GetDocument()));
+ m_xLbDoc->insert(i, aEntryName, &sId, nullptr, nullptr);
+
+ i++;
+ }
+ pSh = SfxObjectShell::GetNext(*pSh);
+ }
+
+ m_xLbDoc->thaw();
+ m_xLbDoc->append_text(msNewDoc);
+ m_xLbDoc->set_active(nSelPos);
+}
+
+void ScMoveTableDlg::SetOkBtnLabel()
+{
+ // tdf#139464 Write "Copy" or "Move" on OK button
+ m_xBtnOk->set_label(m_xBtnCopy->get_active() ? m_xBtnCopy->get_label()
+ : m_xBtnMove->get_label());
+}
+
+// Handler:
+
+IMPL_LINK(ScMoveTableDlg, CheckBtnHdl, weld::Toggleable&, rBtn, void)
+{
+ if (&rBtn == m_xBtnCopy.get())
+ ResetRenameInput();
+ SetOkBtnLabel();
+}
+
+IMPL_LINK_NOARG(ScMoveTableDlg, OkHdl, weld::Button&, void)
+{
+ const sal_Int32 nDocSel = m_xLbDoc->get_active();
+ const sal_Int32 nDocLast = m_xLbDoc->get_count() - 1;
+ const sal_Int32 nTabSel = m_xLbTable->get_selected_index();
+ const sal_Int32 nTabLast = m_xLbTable->n_children() - 1;
+
+ nDocument = (nDocSel != nDocLast) ? nDocSel : SC_DOC_NEW;
+ nTable = (nTabSel != nTabLast) ? static_cast<SCTAB>(nTabSel) : SC_TAB_APPEND;
+ bCopyTable = m_xBtnCopy->get_active();
+
+ if (bCopyTable)
+ {
+ // Return an empty string when the new name is the same as the
+ // automatic name assigned by the document.
+ OUString aCopyName = maDefaultName;
+ ScDocument* pDoc = GetSelectedDoc();
+ if (pDoc)
+ pDoc->CreateValidTabName(aCopyName);
+ if (aCopyName == m_xEdTabName->get_text())
+ m_xEdTabName->set_text(OUString());
+ }
+ else
+ {
+ // Return an empty string, when the new name is the same as the
+ // original name.
+ if (maDefaultName == m_xEdTabName->get_text())
+ m_xEdTabName->set_text(OUString());
+ }
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScMoveTableDlg, SelHdl, weld::ComboBox&, void)
+{
+ ScDocument* pDoc = GetSelectedDoc();
+ OUString aName;
+
+ m_xLbTable->clear();
+ m_xLbTable->freeze();
+ if (pDoc)
+ {
+ SCTAB nLast = pDoc->GetTableCount() - 1;
+ for (SCTAB i = 0; i <= nLast; ++i)
+ {
+ pDoc->GetName(i, aName);
+ m_xLbTable->append_text(aName);
+ }
+ }
+ m_xLbTable->append_text(ScResId(STR_MOVE_TO_END));
+ m_xLbTable->thaw();
+ m_xLbTable->select(0);
+ ResetRenameInput();
+}
+
+IMPL_LINK_NOARG(ScMoveTableDlg, CheckNameHdl, weld::Entry&, void)
+{
+ mbEverEdited = true;
+ CheckNewTabName();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/namecrea.cxx b/sc/source/ui/miscdlgs/namecrea.cxx
new file mode 100644
index 000000000..334b89d8b
--- /dev/null
+++ b/sc/source/ui/miscdlgs/namecrea.cxx
@@ -0,0 +1,55 @@
+/* -*- 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 <namecrea.hxx>
+
+ScNameCreateDlg::ScNameCreateDlg(weld::Window* pParent, CreateNameFlags nFlags)
+ : GenericDialogController(pParent, "modules/scalc/ui/createnamesdialog.ui", "CreateNamesDialog")
+ , m_xTopBox(m_xBuilder->weld_check_button("top"))
+ , m_xLeftBox(m_xBuilder->weld_check_button("left"))
+ , m_xBottomBox(m_xBuilder->weld_check_button("bottom"))
+ , m_xRightBox(m_xBuilder->weld_check_button("right"))
+{
+ m_xTopBox->set_active(bool(nFlags & CreateNameFlags::Top));
+ m_xLeftBox->set_active(bool(nFlags & CreateNameFlags::Left));
+ m_xBottomBox->set_active(bool(nFlags & CreateNameFlags::Bottom));
+ m_xRightBox->set_active(bool(nFlags & CreateNameFlags::Right));
+}
+
+ScNameCreateDlg::~ScNameCreateDlg() {}
+
+CreateNameFlags ScNameCreateDlg::GetFlags() const
+{
+ CreateNameFlags nResult = CreateNameFlags::NONE;
+
+ if (m_xTopBox->get_active())
+ nResult |= CreateNameFlags::Top;
+ if (m_xLeftBox->get_active())
+ nResult |= CreateNameFlags::Left;
+ if (m_xBottomBox->get_active())
+ nResult |= CreateNameFlags::Bottom;
+ if (m_xRightBox->get_active())
+ nResult |= CreateNameFlags::Right;
+
+ return nResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/optsolver.cxx b/sc/source/ui/miscdlgs/optsolver.cxx
new file mode 100644
index 000000000..f0f5eb30c
--- /dev/null
+++ b/sc/source/ui/miscdlgs/optsolver.cxx
@@ -0,0 +1,1075 @@
+/* -*- 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 <rangelst.hxx>
+#include <sfx2/bindings.hxx>
+#include <svl/numformat.hxx>
+#include <vcl/commandinfoprovider.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+
+#include <reffact.hxx>
+#include <docsh.hxx>
+#include <docfunc.hxx>
+#include <rangeutl.hxx>
+#include <convuno.hxx>
+#include <unonames.hxx>
+#include <solveroptions.hxx>
+#include <solverutil.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+
+#include <optsolver.hxx>
+
+#include <com/sun/star/sheet/SolverConstraint.hpp>
+#include <com/sun/star/sheet/SolverConstraintOperator.hpp>
+#include <com/sun/star/sheet/XSolverDescription.hpp>
+#include <com/sun/star/sheet/XSolver.hpp>
+
+using namespace com::sun::star;
+
+ScSolverProgressDialog::ScSolverProgressDialog(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/solverprogressdialog.ui",
+ "SolverProgressDialog")
+ , m_xFtTime(m_xBuilder->weld_label("progress"))
+{
+}
+
+ScSolverProgressDialog::~ScSolverProgressDialog()
+{
+}
+
+void ScSolverProgressDialog::HideTimeLimit()
+{
+ m_xFtTime->hide();
+}
+
+void ScSolverProgressDialog::SetTimeLimit( sal_Int32 nSeconds )
+{
+ OUString aOld = m_xFtTime->get_label();
+ OUString aNew = aOld.replaceFirst("#", OUString::number(nSeconds));
+ m_xFtTime->set_label(aNew);
+}
+
+ScSolverNoSolutionDialog::ScSolverNoSolutionDialog(weld::Window* pParent, const OUString& rErrorText)
+ : GenericDialogController(pParent, "modules/scalc/ui/nosolutiondialog.ui", "NoSolutionDialog")
+ , m_xFtErrorText(m_xBuilder->weld_label("error"))
+{
+ m_xFtErrorText->set_label(rErrorText);
+}
+
+ScSolverNoSolutionDialog::~ScSolverNoSolutionDialog()
+{
+}
+
+ScSolverSuccessDialog::ScSolverSuccessDialog(weld::Window* pParent, std::u16string_view rSolution)
+ : GenericDialogController(pParent, "modules/scalc/ui/solversuccessdialog.ui", "SolverSuccessDialog")
+ , m_xFtResult(m_xBuilder->weld_label("result"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+{
+ m_xBtnOk->connect_clicked(LINK(this, ScSolverSuccessDialog, ClickHdl));
+ m_xBtnCancel->connect_clicked(LINK(this, ScSolverSuccessDialog, ClickHdl));
+ OUString aMessage = m_xFtResult->get_label() + " " + rSolution;
+ m_xFtResult->set_label(aMessage);
+}
+
+ScSolverSuccessDialog::~ScSolverSuccessDialog()
+{
+}
+
+IMPL_LINK(ScSolverSuccessDialog, ClickHdl, weld::Button&, rBtn, void)
+{
+ if (&rBtn == m_xBtnOk.get())
+ m_xDialog->response(RET_OK);
+ else
+ m_xDialog->response(RET_CANCEL);
+}
+
+ScCursorRefEdit::ScCursorRefEdit(std::unique_ptr<weld::Entry> xControl)
+ : formula::RefEdit(std::move(xControl))
+{
+ xEntry->connect_key_press(Link<const KeyEvent&, bool>()); //acknowledge we first remove the old one
+ xEntry->connect_key_press(LINK(this, ScCursorRefEdit, KeyInputHdl));
+}
+
+void ScCursorRefEdit::SetCursorLinks( const Link<ScCursorRefEdit&,void>& rUp, const Link<ScCursorRefEdit&,void>& rDown )
+{
+ maCursorUpLink = rUp;
+ maCursorDownLink = rDown;
+}
+
+IMPL_LINK(ScCursorRefEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ vcl::KeyCode aCode = rKEvt.GetKeyCode();
+ bool bUp = (aCode.GetCode() == KEY_UP);
+ bool bDown = (aCode.GetCode() == KEY_DOWN);
+ if ( !aCode.IsShift() && !aCode.IsMod1() && !aCode.IsMod2() && ( bUp || bDown ) )
+ {
+ if ( bUp )
+ maCursorUpLink.Call( *this );
+ else
+ maCursorDownLink.Call( *this );
+ return true;
+ }
+ return formula::RefEdit::KeyInput(rKEvt);
+}
+
+ScOptSolverSave::ScOptSolverSave( const OUString& rObjective, bool bMax, bool bMin, bool bValue,
+ const OUString& rTarget, const OUString& rVariable,
+ std::vector<ScOptConditionRow>&& rConditions,
+ const OUString& rEngine,
+ const uno::Sequence<beans::PropertyValue>& rProperties ) :
+ maObjective( rObjective ),
+ mbMax( bMax ),
+ mbMin( bMin ),
+ mbValue( bValue ),
+ maTarget( rTarget ),
+ maVariable( rVariable ),
+ maConditions( std::move(rConditions) ),
+ maEngine( rEngine ),
+ maProperties( rProperties )
+{
+}
+
+ScOptSolverDlg::ScOptSolverDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ ScDocShell* pDocSh, const ScAddress& aCursorPos)
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/solverdlg.ui", "SolverDialog")
+ , maInputError(ScResId(STR_INVALIDINPUT))
+ , maConditionError(ScResId(STR_INVALIDCONDITION))
+
+ , mpDocShell(pDocSh)
+ , mrDoc(pDocSh->GetDocument())
+ , mnCurTab(aCursorPos.Tab())
+ , mbDlgLostFocus(false)
+ , nScrollPos(0)
+ , mpEdActive(nullptr)
+ , m_xFtObjectiveCell(m_xBuilder->weld_label("targetlabel"))
+ , m_xEdObjectiveCell(new formula::RefEdit(m_xBuilder->weld_entry("targetedit")))
+ , m_xRBObjectiveCell(new formula::RefButton(m_xBuilder->weld_button("targetbutton")))
+ , m_xRbMax(m_xBuilder->weld_radio_button("max"))
+ , m_xRbMin(m_xBuilder->weld_radio_button("min"))
+ , m_xRbValue(m_xBuilder->weld_radio_button("value"))
+ , m_xEdTargetValue(new formula::RefEdit(m_xBuilder->weld_entry("valueedit")))
+ , m_xRBTargetValue(new formula::RefButton(m_xBuilder->weld_button("valuebutton")))
+ , m_xFtVariableCells(m_xBuilder->weld_label("changelabel"))
+ , m_xEdVariableCells(new formula::RefEdit(m_xBuilder->weld_entry("changeedit")))
+ , m_xRBVariableCells(new formula::RefButton(m_xBuilder->weld_button("changebutton")))
+ , m_xFtCellRef(m_xBuilder->weld_label("cellreflabel"))
+ , m_xEdLeft1(new ScCursorRefEdit(m_xBuilder->weld_entry("ref1edit")))
+ , m_xRBLeft1(new formula::RefButton(m_xBuilder->weld_button("ref1button")))
+ , m_xFtOperator(m_xBuilder->weld_label("oplabel"))
+ , m_xLbOp1(m_xBuilder->weld_combo_box("op1list"))
+ , m_xFtConstraint(m_xBuilder->weld_label("constraintlabel"))
+ , m_xEdRight1(new ScCursorRefEdit(m_xBuilder->weld_entry("val1edit")))
+ , m_xRBRight1(new formula::RefButton(m_xBuilder->weld_button("val1button")))
+ , m_xBtnDel1(m_xBuilder->weld_button("del1"))
+ , m_xEdLeft2(new ScCursorRefEdit(m_xBuilder->weld_entry("ref2edit")))
+ , m_xRBLeft2(new formula::RefButton(m_xBuilder->weld_button("ref2button")))
+ , m_xLbOp2(m_xBuilder->weld_combo_box("op2list"))
+ , m_xEdRight2(new ScCursorRefEdit(m_xBuilder->weld_entry("val2edit")))
+ , m_xRBRight2(new formula::RefButton(m_xBuilder->weld_button("val2button")))
+ , m_xBtnDel2(m_xBuilder->weld_button("del2"))
+ , m_xEdLeft3(new ScCursorRefEdit(m_xBuilder->weld_entry("ref3edit")))
+ , m_xRBLeft3(new formula::RefButton(m_xBuilder->weld_button("ref3button")))
+ , m_xLbOp3(m_xBuilder->weld_combo_box("op3list"))
+ , m_xEdRight3(new ScCursorRefEdit(m_xBuilder->weld_entry("val3edit")))
+ , m_xRBRight3(new formula::RefButton(m_xBuilder->weld_button("val3button")))
+ , m_xBtnDel3(m_xBuilder->weld_button("del3"))
+ , m_xEdLeft4(new ScCursorRefEdit(m_xBuilder->weld_entry("ref4edit")))
+ , m_xRBLeft4(new formula::RefButton(m_xBuilder->weld_button("ref4button")))
+ , m_xLbOp4(m_xBuilder->weld_combo_box("op4list"))
+ , m_xEdRight4(new ScCursorRefEdit(m_xBuilder->weld_entry("val4edit")))
+ , m_xRBRight4(new formula::RefButton(m_xBuilder->weld_button("val4button")))
+ , m_xBtnDel4(m_xBuilder->weld_button("del4"))
+ , m_xScrollBar(m_xBuilder->weld_scrolled_window("scrollbar", true))
+ , m_xBtnOpt(m_xBuilder->weld_button("options"))
+ , m_xBtnClose(m_xBuilder->weld_button("close"))
+ , m_xBtnSolve(m_xBuilder->weld_button("ok"))
+ , m_xBtnResetAll(m_xBuilder->weld_button("resetall"))
+ , m_xResultFT(m_xBuilder->weld_label("result"))
+ , m_xContents(m_xBuilder->weld_widget("grid"))
+{
+ m_xEdObjectiveCell->SetReferences(this, m_xFtObjectiveCell.get());
+ m_xRBObjectiveCell->SetReferences(this, m_xEdObjectiveCell.get());
+ m_xEdTargetValue->SetReferences(this, m_xResultFT.get());
+ m_xRBTargetValue->SetReferences(this, m_xEdTargetValue.get());
+ m_xEdVariableCells->SetReferences(this, m_xFtVariableCells.get());
+ m_xRBVariableCells->SetReferences(this, m_xEdVariableCells.get());
+ m_xEdLeft1->SetReferences(this, m_xFtCellRef.get());
+ m_xRBLeft1->SetReferences(this, m_xEdLeft1.get());
+ m_xEdRight1->SetReferences(this, m_xFtConstraint.get());
+ m_xRBRight1->SetReferences(this, m_xEdRight1.get());
+ m_xEdLeft2->SetReferences(this, m_xFtCellRef.get());
+ m_xRBLeft2->SetReferences(this, m_xEdLeft2.get());
+ m_xEdRight2->SetReferences(this, m_xFtConstraint.get());
+ m_xRBRight2->SetReferences(this, m_xEdRight2.get());
+ m_xEdLeft3->SetReferences(this, m_xFtCellRef.get());
+ m_xRBLeft3->SetReferences(this, m_xEdLeft3.get());
+ m_xEdRight3->SetReferences(this, m_xFtConstraint.get());
+ m_xRBRight3->SetReferences(this, m_xEdRight3.get());
+ m_xEdLeft4->SetReferences(this, m_xFtCellRef.get());
+ m_xRBLeft4->SetReferences(this, m_xEdLeft4.get());
+ m_xEdRight4->SetReferences(this, m_xFtConstraint.get());
+ m_xRBRight4->SetReferences(this, m_xEdRight4.get());
+
+ mpLeftEdit[0] = m_xEdLeft1.get();
+ mpLeftButton[0] = m_xRBLeft1.get();
+ mpRightEdit[0] = m_xEdRight1.get();
+ mpRightButton[0] = m_xRBRight1.get();
+ mpOperator[0] = m_xLbOp1.get();
+ mpDelButton[0] = m_xBtnDel1.get();
+
+ mpLeftEdit[1] = m_xEdLeft2.get();
+ mpLeftButton[1] = m_xRBLeft2.get();
+ mpRightEdit[1] = m_xEdRight2.get();
+ mpRightButton[1] = m_xRBRight2.get();
+ mpOperator[1] = m_xLbOp2.get();
+ mpDelButton[1] = m_xBtnDel2.get();
+
+ mpLeftEdit[2] = m_xEdLeft3.get();
+ mpLeftButton[2] = m_xRBLeft3.get();
+ mpRightEdit[2] = m_xEdRight3.get();
+ mpRightButton[2] = m_xRBRight3.get();
+ mpOperator[2] = m_xLbOp3.get();
+ mpDelButton[2] = m_xBtnDel3.get();
+
+ mpLeftEdit[3] = m_xEdLeft4.get();
+ mpLeftButton[3] = m_xRBLeft4.get();
+ mpRightEdit[3] = m_xEdRight4.get();
+ mpRightButton[3] = m_xRBRight4.get();
+ mpOperator[3] = m_xLbOp4.get();
+ mpDelButton[3] = m_xBtnDel4.get();
+
+ Init( aCursorPos );
+}
+
+ScOptSolverDlg::~ScOptSolverDlg()
+{
+}
+
+void ScOptSolverDlg::Init(const ScAddress& rCursorPos)
+{
+ uno::Reference<frame::XFrame> xFrame = GetBindings().GetActiveFrame();
+ auto xDelNm = vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:DeleteRows", xFrame);
+ for (weld::Button* pButton : mpDelButton)
+ pButton->set_image(xDelNm);
+
+ m_xBtnOpt->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
+ m_xBtnClose->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
+ m_xBtnSolve->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
+ m_xBtnResetAll->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
+
+ Link<formula::RefEdit&,void> aEditLink = LINK( this, ScOptSolverDlg, GetEditFocusHdl );
+ Link<formula::RefButton&,void> aButtonLink = LINK( this, ScOptSolverDlg, GetButtonFocusHdl );
+ m_xEdObjectiveCell->SetGetFocusHdl( aEditLink );
+ m_xRBObjectiveCell->SetGetFocusHdl( aButtonLink );
+ m_xEdTargetValue->SetGetFocusHdl( aEditLink );
+ m_xRBTargetValue->SetGetFocusHdl( aButtonLink );
+ m_xEdVariableCells->SetGetFocusHdl( aEditLink );
+ m_xRBVariableCells->SetGetFocusHdl( aButtonLink );
+ Link<weld::Widget&,void> aLink = LINK(this, ScOptSolverDlg, GetFocusHdl);
+ m_xRbValue->connect_focus_in(aLink);
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ mpLeftEdit[nRow]->SetGetFocusHdl( aEditLink );
+ mpLeftButton[nRow]->SetGetFocusHdl( aButtonLink );
+ mpRightEdit[nRow]->SetGetFocusHdl( aEditLink );
+ mpRightButton[nRow]->SetGetFocusHdl( aButtonLink );
+ mpOperator[nRow]->connect_focus_in(aLink);
+ }
+
+ aEditLink = LINK( this, ScOptSolverDlg, LoseEditFocusHdl );
+ aButtonLink = LINK( this, ScOptSolverDlg, LoseButtonFocusHdl );
+ m_xEdObjectiveCell->SetLoseFocusHdl( aEditLink );
+ m_xRBObjectiveCell->SetLoseFocusHdl( aButtonLink );
+ m_xEdTargetValue->SetLoseFocusHdl( aEditLink );
+ m_xRBTargetValue-> SetLoseFocusHdl( aButtonLink );
+ m_xEdVariableCells->SetLoseFocusHdl( aEditLink );
+ m_xRBVariableCells->SetLoseFocusHdl( aButtonLink );
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ mpLeftEdit[nRow]->SetLoseFocusHdl( aEditLink );
+ mpLeftButton[nRow]->SetLoseFocusHdl( aButtonLink );
+ mpRightEdit[nRow]->SetLoseFocusHdl( aEditLink );
+ mpRightButton[nRow]->SetLoseFocusHdl( aButtonLink );
+ }
+
+ Link<ScCursorRefEdit&,void> aCursorUp = LINK( this, ScOptSolverDlg, CursorUpHdl );
+ Link<ScCursorRefEdit&,void> aCursorDown = LINK( this, ScOptSolverDlg, CursorDownHdl );
+ Link<formula::RefEdit&,void> aCondModify = LINK( this, ScOptSolverDlg, CondModifyHdl );
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ mpLeftEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
+ mpRightEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
+ mpLeftEdit[nRow]->SetModifyHdl( aCondModify );
+ mpRightEdit[nRow]->SetModifyHdl( aCondModify );
+ mpDelButton[nRow]->connect_clicked( LINK( this, ScOptSolverDlg, DelBtnHdl ) );
+ mpOperator[nRow]->connect_changed( LINK( this, ScOptSolverDlg, SelectHdl ) );
+ }
+ m_xEdTargetValue->SetModifyHdl( LINK( this, ScOptSolverDlg, TargetModifyHdl ) );
+
+ Size aSize(m_xContents->get_preferred_size());
+ m_xContents->set_size_request(aSize.Width(), aSize.Height());
+ m_xScrollBar->connect_vadjustment_changed( LINK( this, ScOptSolverDlg, ScrollHdl ) );
+
+ m_xScrollBar->vadjustment_set_page_increment( EDIT_ROW_COUNT );
+ m_xScrollBar->vadjustment_set_page_size( EDIT_ROW_COUNT );
+ // Range is set in ShowConditions
+
+ // get available solver implementations
+ //! sort by descriptions?
+ ScSolverUtil::GetImplementations( maImplNames, maDescriptions );
+ bool bImplHasElements = maImplNames.hasElements();
+
+ const ScOptSolverSave* pOldData = mpDocShell->GetSolverSaveData();
+ if ( pOldData )
+ {
+ m_xEdObjectiveCell->SetRefString( pOldData->GetObjective() );
+ m_xRbMax->set_active( pOldData->GetMax() );
+ m_xRbMin->set_active( pOldData->GetMin() );
+ m_xRbValue->set_active( pOldData->GetValue() );
+ m_xEdTargetValue->SetRefString( pOldData->GetTarget() );
+ m_xEdVariableCells->SetRefString( pOldData->GetVariable() );
+ maConditions = pOldData->GetConditions();
+ maEngine = pOldData->GetEngine();
+ maProperties = pOldData->GetProperties();
+ }
+ else
+ {
+ m_xRbMax->set_active(true);
+ OUString aCursorStr;
+ if ( !mrDoc.GetRangeAtBlock( ScRange(rCursorPos), aCursorStr ) )
+ aCursorStr = rCursorPos.Format(ScRefFlags::ADDR_ABS, nullptr, mrDoc.GetAddressConvention());
+ m_xEdObjectiveCell->SetRefString( aCursorStr );
+ if ( bImplHasElements )
+ maEngine = maImplNames[0]; // use first implementation
+ }
+ ShowConditions();
+
+ m_xEdObjectiveCell->GrabFocus();
+ mpEdActive = m_xEdObjectiveCell.get();
+}
+
+void ScOptSolverDlg::ReadConditions()
+{
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ ScOptConditionRow aRowEntry;
+ aRowEntry.aLeftStr = mpLeftEdit[nRow]->GetText();
+ aRowEntry.aRightStr = mpRightEdit[nRow]->GetText();
+ aRowEntry.nOperator = mpOperator[nRow]->get_active();
+
+ tools::Long nVecPos = nScrollPos + nRow;
+ if ( nVecPos >= static_cast<tools::Long>(maConditions.size()) && !aRowEntry.IsDefault() )
+ maConditions.resize( nVecPos + 1 );
+
+ if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
+ maConditions[nVecPos] = aRowEntry;
+
+ // remove default entries at the end
+ size_t nSize = maConditions.size();
+ while ( nSize > 0 && maConditions[ nSize-1 ].IsDefault() )
+ --nSize;
+ maConditions.resize( nSize );
+ }
+}
+
+void ScOptSolverDlg::ShowConditions()
+{
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ ScOptConditionRow aRowEntry;
+
+ tools::Long nVecPos = nScrollPos + nRow;
+ if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
+ aRowEntry = maConditions[nVecPos];
+
+ mpLeftEdit[nRow]->SetRefString( aRowEntry.aLeftStr );
+ mpRightEdit[nRow]->SetRefString( aRowEntry.aRightStr );
+ mpOperator[nRow]->set_active( aRowEntry.nOperator );
+ }
+
+ // allow to scroll one page behind the visible or stored rows
+ tools::Long nVisible = nScrollPos + EDIT_ROW_COUNT;
+ tools::Long nMax = std::max( nVisible, static_cast<tools::Long>(maConditions.size()) );
+ m_xScrollBar->vadjustment_configure(nScrollPos, 0, nMax + EDIT_ROW_COUNT, 1,
+ EDIT_ROW_COUNT - 1, EDIT_ROW_COUNT);
+
+ EnableButtons();
+}
+
+void ScOptSolverDlg::EnableButtons()
+{
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ tools::Long nVecPos = nScrollPos + nRow;
+ mpDelButton[nRow]->set_sensitive(nVecPos < static_cast<tools::Long>(maConditions.size()));
+ }
+}
+
+void ScOptSolverDlg::Close()
+{
+ if (m_xOptDlg)
+ m_xOptDlg->response(RET_CANCEL);
+ assert(!m_xOptDlg);
+ DoClose( ScOptSolverDlgWrapper::GetChildWindowId() );
+}
+
+void ScOptSolverDlg::SetActive()
+{
+ if ( mbDlgLostFocus )
+ {
+ mbDlgLostFocus = false;
+ if( mpEdActive )
+ mpEdActive->GrabFocus();
+ }
+ else
+ {
+ m_xDialog->grab_focus();
+ }
+ RefInputDone();
+}
+
+void ScOptSolverDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if( !mpEdActive )
+ return;
+
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(mpEdActive);
+
+ // "target"/"value": single cell
+ bool bSingle = ( mpEdActive == m_xEdObjectiveCell.get() || mpEdActive == m_xEdTargetValue.get() );
+
+ OUString aStr;
+ ScAddress aAdr = rRef.aStart;
+ ScRange aNewRef( rRef );
+ if ( bSingle )
+ aNewRef.aEnd = aAdr;
+
+ OUString aName;
+ if ( rDocP.GetRangeAtBlock( aNewRef, aName ) ) // named range: show name
+ aStr = aName;
+ else // format cell/range reference
+ {
+ ScRefFlags nFmt = ( aAdr.Tab() == mnCurTab ) ? ScRefFlags::ADDR_ABS : ScRefFlags::ADDR_ABS_3D;
+ if ( bSingle )
+ aStr = aAdr.Format(nFmt, &rDocP, rDocP.GetAddressConvention());
+ else
+ aStr = rRef.Format(rDocP, nFmt | ScRefFlags::RANGE_ABS, rDocP.GetAddressConvention());
+ }
+
+ // variable cells can be several ranges, so only the selection is replaced
+ if ( mpEdActive == m_xEdVariableCells.get() )
+ {
+ OUString aVal = mpEdActive->GetText();
+ Selection aSel = mpEdActive->GetSelection();
+ aSel.Justify();
+ aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr );
+ Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() );
+ mpEdActive->SetRefString( aVal );
+ mpEdActive->SetSelection( aNewSel );
+ }
+ else
+ mpEdActive->SetRefString( aStr );
+
+ ReadConditions();
+ EnableButtons();
+
+ // select "Value of" if a ref is input into "target" edit
+ if ( mpEdActive == m_xEdTargetValue.get() )
+ m_xRbValue->set_active(true);
+}
+
+bool ScOptSolverDlg::IsRefInputMode() const
+{
+ return mpEdActive != nullptr;
+}
+
+// Handler:
+
+IMPL_LINK(ScOptSolverDlg, BtnHdl, weld::Button&, rBtn, void)
+{
+ auto xKeepAlive = shared_from_this();
+ if (&rBtn == m_xBtnSolve.get() || &rBtn == m_xBtnClose.get())
+ {
+ bool bSolve = ( &rBtn == m_xBtnSolve.get() );
+
+ SetDispatcherLock( false );
+ SwitchToDocument();
+
+ bool bClose = true;
+ if ( bSolve )
+ bClose = CallSolver();
+
+ if ( bClose )
+ {
+ // Close: write dialog settings to DocShell for subsequent calls
+ ReadConditions();
+ std::unique_ptr<ScOptSolverSave> pSave( new ScOptSolverSave(
+ m_xEdObjectiveCell->GetText(), m_xRbMax->get_active(), m_xRbMin->get_active(), m_xRbValue->get_active(),
+ m_xEdTargetValue->GetText(), m_xEdVariableCells->GetText(), std::vector(maConditions), maEngine, maProperties ) );
+ mpDocShell->SetSolverSaveData( std::move(pSave) );
+ response(RET_CLOSE);
+ }
+ else
+ {
+ // no solution -> dialog is kept open
+ SetDispatcherLock( true );
+ }
+ }
+ else if (&rBtn == m_xBtnOpt.get())
+ {
+ //! move options dialog to UI lib?
+ m_xOptDlg = std::make_shared<ScSolverOptionsDialog>(m_xDialog.get(), maImplNames, maDescriptions, maEngine, maProperties);
+ weld::DialogController::runAsync(m_xOptDlg, [this](sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ maEngine = m_xOptDlg->GetEngine();
+ maProperties = m_xOptDlg->GetProperties();
+ }
+ m_xOptDlg.reset();
+ });
+ }
+ else if (&rBtn == m_xBtnResetAll.get())
+ {
+ OUString sEmpty;
+ m_xEdObjectiveCell->SetText(sEmpty);
+ m_xEdTargetValue->SetText(sEmpty);
+ m_xEdVariableCells->SetText(sEmpty);
+
+ // Get default property values of solver implementations
+ maEngine = maImplNames[0];
+ maProperties = ScSolverUtil::GetDefaults( maEngine );
+
+ // Clear all conditions (Constraints)
+ maConditions.clear();
+ std::unique_ptr<ScOptSolverSave> pEmpty( new ScOptSolverSave(
+ sEmpty, true, false, false,
+ sEmpty, sEmpty, std::vector(maConditions), maEngine, maProperties ) );
+ mpDocShell->SetSolverSaveData( std::move(pEmpty) );
+ ShowConditions();
+
+ m_xRbMax->set_active(true);
+ m_xEdObjectiveCell->GrabFocus();
+ mpEdActive = m_xEdObjectiveCell.get();
+ }
+}
+
+IMPL_LINK( ScOptSolverDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
+{
+ formula::RefEdit* pEdit = nullptr;
+ mpEdActive = nullptr;
+
+ if( &rCtrl == m_xEdObjectiveCell.get() )
+ pEdit = mpEdActive = m_xEdObjectiveCell.get();
+ else if( &rCtrl == m_xEdTargetValue.get() )
+ pEdit = mpEdActive = m_xEdTargetValue.get();
+ else if( &rCtrl == m_xEdVariableCells.get() )
+ pEdit = mpEdActive = m_xEdVariableCells.get();
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ if( &rCtrl == mpLeftEdit[nRow] )
+ pEdit = mpEdActive = mpLeftEdit[nRow];
+ else if( &rCtrl == mpRightEdit[nRow] )
+ pEdit = mpEdActive = mpRightEdit[nRow];
+ }
+
+ if( pEdit )
+ pEdit->SelectAll();
+}
+
+IMPL_LINK( ScOptSolverDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
+{
+ formula::RefEdit* pEdit = nullptr;
+ mpEdActive = nullptr;
+
+ if( &rCtrl == m_xRBObjectiveCell.get() )
+ pEdit = mpEdActive = m_xEdObjectiveCell.get();
+ else if( &rCtrl == m_xRBTargetValue.get() )
+ pEdit = mpEdActive = m_xEdTargetValue.get();
+ else if( &rCtrl == m_xRBVariableCells.get() )
+ pEdit = mpEdActive = m_xEdVariableCells.get();
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ if( &rCtrl == mpLeftButton[nRow] )
+ pEdit = mpEdActive = mpLeftEdit[nRow];
+ else if( &rCtrl == mpRightButton[nRow] )
+ pEdit = mpEdActive = mpRightEdit[nRow];
+ }
+
+ if( pEdit )
+ pEdit->SelectAll();
+}
+
+
+IMPL_LINK(ScOptSolverDlg, GetFocusHdl, weld::Widget&, rCtrl, void)
+{
+ if( &rCtrl == m_xRbValue.get() ) // focus on "Value of" radio button
+ mpEdActive = m_xEdTargetValue.get(); // use value edit for ref input, but don't change selection
+ else
+ {
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ {
+ if( &rCtrl == mpOperator[nRow] ) // focus on "operator" list box
+ mpEdActive = mpRightEdit[nRow]; // use right edit for ref input, but don't change selection
+ }
+ }
+}
+
+IMPL_LINK_NOARG(ScOptSolverDlg, LoseEditFocusHdl, formula::RefEdit&, void)
+{
+ mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(ScOptSolverDlg, LoseButtonFocusHdl, formula::RefButton&, void)
+{
+ mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK(ScOptSolverDlg, DelBtnHdl, weld::Button&, rBtn, void)
+{
+ for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
+ if (&rBtn == mpDelButton[nRow])
+ {
+ bool bHadFocus = rBtn.has_focus();
+
+ ReadConditions();
+ tools::Long nVecPos = nScrollPos + nRow;
+ if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
+ {
+ maConditions.erase( maConditions.begin() + nVecPos );
+ ShowConditions();
+
+ if ( bHadFocus && !rBtn.get_sensitive() )
+ {
+ // If the button is disabled, focus would normally move to the next control,
+ // (left edit of the next row). Move it to left edit of this row instead.
+
+ mpEdActive = mpLeftEdit[nRow];
+ mpEdActive->GrabFocus();
+ }
+ }
+ }
+}
+
+IMPL_LINK_NOARG(ScOptSolverDlg, TargetModifyHdl, formula::RefEdit&, void)
+{
+ // modify handler for the target edit:
+ // select "Value of" if something is input into the edit
+ if ( !m_xEdTargetValue->GetText().isEmpty() )
+ m_xRbValue->set_active(true);
+}
+
+IMPL_LINK_NOARG(ScOptSolverDlg, CondModifyHdl, formula::RefEdit&, void)
+{
+ // modify handler for the condition edits, just to enable/disable "delete" buttons
+ ReadConditions();
+ EnableButtons();
+}
+
+IMPL_LINK_NOARG(ScOptSolverDlg, SelectHdl, weld::ComboBox&, void)
+{
+ // select handler for operator list boxes, just to enable/disable "delete" buttons
+ ReadConditions();
+ EnableButtons();
+}
+
+IMPL_LINK_NOARG(ScOptSolverDlg, ScrollHdl, weld::ScrolledWindow&, void)
+{
+ ReadConditions();
+ nScrollPos = m_xScrollBar->vadjustment_get_value();
+ ShowConditions();
+ if( mpEdActive )
+ mpEdActive->SelectAll();
+}
+
+IMPL_LINK( ScOptSolverDlg, CursorUpHdl, ScCursorRefEdit&, rEdit, void )
+{
+ if ( &rEdit == mpLeftEdit[0] || &rEdit == mpRightEdit[0] )
+ {
+ if ( nScrollPos > 0 )
+ {
+ ReadConditions();
+ --nScrollPos;
+ ShowConditions();
+ if( mpEdActive )
+ mpEdActive->SelectAll();
+ }
+ }
+ else
+ {
+ formula::RefEdit* pFocus = nullptr;
+ for ( sal_uInt16 nRow = 1; nRow < EDIT_ROW_COUNT; ++nRow ) // second row or below: move focus
+ {
+ if ( &rEdit == mpLeftEdit[nRow] )
+ pFocus = mpLeftEdit[nRow-1];
+ else if ( &rEdit == mpRightEdit[nRow] )
+ pFocus = mpRightEdit[nRow-1];
+ }
+ if (pFocus)
+ {
+ mpEdActive = pFocus;
+ pFocus->GrabFocus();
+ }
+ }
+}
+
+IMPL_LINK( ScOptSolverDlg, CursorDownHdl, ScCursorRefEdit&, rEdit, void )
+{
+ if ( &rEdit == mpLeftEdit[EDIT_ROW_COUNT-1] || &rEdit == mpRightEdit[EDIT_ROW_COUNT-1] )
+ {
+ //! limit scroll position?
+ ReadConditions();
+ ++nScrollPos;
+ ShowConditions();
+ if( mpEdActive )
+ mpEdActive->SelectAll();
+ }
+ else
+ {
+ formula::RefEdit* pFocus = nullptr;
+ for ( sal_uInt16 nRow = 0; nRow+1 < EDIT_ROW_COUNT; ++nRow ) // before last row: move focus
+ {
+ if ( &rEdit == mpLeftEdit[nRow] )
+ pFocus = mpLeftEdit[nRow+1];
+ else if ( &rEdit == mpRightEdit[nRow] )
+ pFocus = mpRightEdit[nRow+1];
+ }
+ if (pFocus)
+ {
+ mpEdActive = pFocus;
+ pFocus->GrabFocus();
+ }
+ }
+}
+
+void ScOptSolverDlg::ShowError( bool bCondition, formula::RefEdit* pFocus )
+{
+ OUString aMessage = bCondition ? maConditionError : maInputError;
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ aMessage));
+ xBox->run();
+ if (pFocus)
+ {
+ mpEdActive = pFocus;
+ pFocus->GrabFocus();
+ }
+}
+
+bool ScOptSolverDlg::ParseRef( ScRange& rRange, const OUString& rInput, bool bAllowRange )
+{
+ ScAddress::Details aDetails(mrDoc.GetAddressConvention(), 0, 0);
+ ScRefFlags nFlags = rRange.ParseAny( rInput, mrDoc, aDetails );
+ if ( nFlags & ScRefFlags::VALID )
+ {
+ if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO)
+ rRange.aStart.SetTab( mnCurTab );
+ if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO)
+ rRange.aEnd.SetTab( rRange.aStart.Tab() );
+ return ( bAllowRange || rRange.aStart == rRange.aEnd );
+ }
+ else if ( ScRangeUtil::MakeRangeFromName( rInput, mrDoc, mnCurTab, rRange, RUTL_NAMES, aDetails ) )
+ return ( bAllowRange || rRange.aStart == rRange.aEnd );
+
+ return false; // not recognized
+}
+
+bool ScOptSolverDlg::FindTimeout( sal_Int32& rTimeout )
+{
+ bool bFound = false;
+
+ if ( !maProperties.hasElements() )
+ maProperties = ScSolverUtil::GetDefaults( maEngine ); // get property defaults from component
+
+ sal_Int32 nPropCount = maProperties.getLength();
+ for (sal_Int32 nProp=0; nProp<nPropCount && !bFound; ++nProp)
+ {
+ const beans::PropertyValue& rValue = maProperties[nProp];
+ if ( rValue.Name == SC_UNONAME_TIMEOUT )
+ bFound = ( rValue.Value >>= rTimeout );
+ }
+ return bFound;
+}
+
+bool ScOptSolverDlg::CallSolver() // return true -> close dialog after calling
+{
+ // show progress dialog
+
+ auto xProgress = std::make_shared<ScSolverProgressDialog>(m_xDialog.get());
+ sal_Int32 nTimeout = 0;
+ if ( FindTimeout( nTimeout ) )
+ xProgress->SetTimeLimit( nTimeout );
+ else
+ xProgress->HideTimeLimit();
+
+ weld::DialogController::runAsync(xProgress, [](sal_Int32 /*nResult*/){});
+
+ // try to make sure the progress dialog is painted before continuing
+ Application::Reschedule(true);
+
+ // collect solver parameters
+
+ ReadConditions();
+
+ uno::Reference<sheet::XSpreadsheetDocument> xDocument( mpDocShell->GetModel(), uno::UNO_QUERY );
+
+ ScRange aObjRange;
+ if ( !ParseRef( aObjRange, m_xEdObjectiveCell->GetText(), false ) )
+ {
+ ShowError( false, m_xEdObjectiveCell.get() );
+ return false;
+ }
+ table::CellAddress aObjective( aObjRange.aStart.Tab(), aObjRange.aStart.Col(), aObjRange.aStart.Row() );
+
+ // "changing cells" can be several ranges
+ ScRangeList aVarRanges;
+ if ( !ParseWithNames( aVarRanges, m_xEdVariableCells->GetText(), mrDoc ) )
+ {
+ ShowError( false, m_xEdVariableCells.get() );
+ return false;
+ }
+ uno::Sequence<table::CellAddress> aVariables;
+ sal_Int32 nVarPos = 0;
+
+ for ( size_t nRangePos=0, nRange = aVarRanges.size(); nRangePos < nRange; ++nRangePos )
+ {
+ ScRange aRange( aVarRanges[ nRangePos ] );
+ aRange.PutInOrder();
+ SCTAB nTab = aRange.aStart.Tab();
+
+ // resolve into single cells
+
+ sal_Int32 nAdd = ( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ) *
+ ( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
+ aVariables.realloc( nVarPos + nAdd );
+ auto pVariables = aVariables.getArray();
+
+ for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
+ for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
+ pVariables[nVarPos++] = table::CellAddress( nTab, nCol, nRow );
+ }
+
+ uno::Sequence<sheet::SolverConstraint> aConstraints;
+ sal_Int32 nConstrPos = 0;
+ for ( const auto& rConstr : maConditions )
+ {
+ if ( !rConstr.aLeftStr.isEmpty() )
+ {
+ sheet::SolverConstraint aConstraint;
+ // order of list box entries must match enum values
+ aConstraint.Operator = static_cast<sheet::SolverConstraintOperator>(rConstr.nOperator);
+
+ ScRange aLeftRange;
+ if ( !ParseRef( aLeftRange, rConstr.aLeftStr, true ) )
+ {
+ ShowError( true, nullptr );
+ return false;
+ }
+
+ bool bIsRange = false;
+ ScRange aRightRange;
+ if ( ParseRef( aRightRange, rConstr.aRightStr, true ) )
+ {
+ if ( aRightRange.aStart == aRightRange.aEnd )
+ aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
+ aRightRange.aStart.Col(), aRightRange.aStart.Row() );
+ else if ( aRightRange.aEnd.Col()-aRightRange.aStart.Col() == aLeftRange.aEnd.Col()-aLeftRange.aStart.Col() &&
+ aRightRange.aEnd.Row()-aRightRange.aStart.Row() == aLeftRange.aEnd.Row()-aLeftRange.aStart.Row() )
+ bIsRange = true; // same size as "left" range, resolve into single cells
+ else
+ {
+ ShowError( true, nullptr );
+ return false;
+ }
+ }
+ else
+ {
+ sal_uInt32 nFormat = 0; //! explicit language?
+ double fValue = 0.0;
+ if ( mrDoc.GetFormatTable()->IsNumberFormat( rConstr.aRightStr, nFormat, fValue ) )
+ aConstraint.Right <<= fValue;
+ else if ( aConstraint.Operator != sheet::SolverConstraintOperator_INTEGER &&
+ aConstraint.Operator != sheet::SolverConstraintOperator_BINARY )
+ {
+ ShowError( true, nullptr );
+ return false;
+ }
+ }
+
+ // resolve into single cells
+
+ sal_Int32 nAdd = ( aLeftRange.aEnd.Col() - aLeftRange.aStart.Col() + 1 ) *
+ ( aLeftRange.aEnd.Row() - aLeftRange.aStart.Row() + 1 );
+ aConstraints.realloc( nConstrPos + nAdd );
+ auto pConstraints = aConstraints.getArray();
+
+ for (SCROW nRow = aLeftRange.aStart.Row(); nRow <= aLeftRange.aEnd.Row(); ++nRow)
+ for (SCCOL nCol = aLeftRange.aStart.Col(); nCol <= aLeftRange.aEnd.Col(); ++nCol)
+ {
+ aConstraint.Left = table::CellAddress( aLeftRange.aStart.Tab(), nCol, nRow );
+ if ( bIsRange )
+ aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
+ aRightRange.aStart.Col() + ( nCol - aLeftRange.aStart.Col() ),
+ aRightRange.aStart.Row() + ( nRow - aLeftRange.aStart.Row() ) );
+
+ pConstraints[nConstrPos++] = aConstraint;
+ }
+ }
+ }
+
+ bool bMaximize = m_xRbMax->get_active();
+ if ( m_xRbValue->get_active() )
+ {
+ // handle "value of" with an additional constraint (and then minimize)
+
+ sheet::SolverConstraint aConstraint;
+ aConstraint.Left = aObjective;
+ aConstraint.Operator = sheet::SolverConstraintOperator_EQUAL;
+
+ OUString aValStr = m_xEdTargetValue->GetText();
+ ScRange aRightRange;
+ if ( ParseRef( aRightRange, aValStr, false ) )
+ aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
+ aRightRange.aStart.Col(), aRightRange.aStart.Row() );
+ else
+ {
+ sal_uInt32 nFormat = 0; //! explicit language?
+ double fValue = 0.0;
+ if ( mrDoc.GetFormatTable()->IsNumberFormat( aValStr, nFormat, fValue ) )
+ aConstraint.Right <<= fValue;
+ else
+ {
+ ShowError( false, m_xEdTargetValue.get() );
+ return false;
+ }
+ }
+
+ aConstraints.realloc( nConstrPos + 1 );
+ aConstraints.getArray()[nConstrPos++] = aConstraint;
+ }
+
+ // copy old document values
+
+ sal_Int32 nVarCount = aVariables.getLength();
+ uno::Sequence<double> aOldValues( nVarCount );
+ std::transform(std::cbegin(aVariables), std::cend(aVariables), aOldValues.getArray(),
+ [this](const table::CellAddress& rVariable) -> double {
+ ScAddress aCellPos;
+ ScUnoConversion::FillScAddress( aCellPos, rVariable );
+ return mrDoc.GetValue( aCellPos );
+ });
+
+ // create and initialize solver
+
+ uno::Reference<sheet::XSolver> xSolver = ScSolverUtil::GetSolver( maEngine );
+ OSL_ENSURE( xSolver.is(), "can't get solver component" );
+ if ( !xSolver.is() )
+ return false;
+
+ xSolver->setDocument( xDocument );
+ xSolver->setObjective( aObjective );
+ xSolver->setVariables( aVariables );
+ xSolver->setConstraints( aConstraints );
+ xSolver->setMaximize( bMaximize );
+
+ // set options
+ uno::Reference<beans::XPropertySet> xOptProp(xSolver, uno::UNO_QUERY);
+ if ( xOptProp.is() )
+ {
+ for (const beans::PropertyValue& rValue : std::as_const(maProperties))
+ {
+ try
+ {
+ xOptProp->setPropertyValue( rValue.Name, rValue.Value );
+ }
+ catch ( uno::Exception & )
+ {
+ OSL_FAIL("Exception in solver option property");
+ }
+ }
+ }
+
+ xSolver->solve();
+ bool bSuccess = xSolver->getSuccess();
+
+ xProgress->response(RET_CLOSE);
+
+ bool bClose = false;
+ bool bRestore = true; // restore old values unless a solution is accepted
+ if ( bSuccess )
+ {
+ // put solution into document so it is visible when asking
+ uno::Sequence<double> aSolution = xSolver->getSolution();
+ if ( aSolution.getLength() == nVarCount )
+ {
+ mpDocShell->LockPaint();
+ ScDocFunc &rFunc = mpDocShell->GetDocFunc();
+ for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
+ {
+ ScAddress aCellPos;
+ ScUnoConversion::FillScAddress( aCellPos, std::as_const(aVariables)[nVarPos] );
+ rFunc.SetValueCell(aCellPos, aSolution[nVarPos], false);
+ }
+ mpDocShell->UnlockPaint();
+ }
+ //! else error?
+
+ // take formatted result from document (result value from component is ignored)
+ OUString aResultStr = mrDoc.GetString(
+ static_cast<SCCOL>(aObjective.Column), static_cast<SCROW>(aObjective.Row),
+ static_cast<SCTAB>(aObjective.Sheet));
+
+ ScSolverSuccessDialog aDialog(m_xDialog.get(), aResultStr);
+ if (aDialog.run() == RET_OK)
+ {
+ // keep results and close dialog
+ bRestore = false;
+ bClose = true;
+ }
+ }
+ else
+ {
+ OUString aError;
+ uno::Reference<sheet::XSolverDescription> xDesc( xSolver, uno::UNO_QUERY );
+ if ( xDesc.is() )
+ aError = xDesc->getStatusDescription(); // error description from component
+ ScSolverNoSolutionDialog aDialog(m_xDialog.get(), aError);
+ aDialog.run();
+ }
+
+ if ( bRestore ) // restore old values
+ {
+ mpDocShell->LockPaint();
+ ScDocFunc &rFunc = mpDocShell->GetDocFunc();
+ for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
+ {
+ ScAddress aCellPos;
+ ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
+ rFunc.SetValueCell(aCellPos, std::as_const(aOldValues)[nVarPos], false);
+ }
+ mpDocShell->UnlockPaint();
+ }
+
+ return bClose;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/protectiondlg.cxx b/sc/source/ui/miscdlgs/protectiondlg.cxx
new file mode 100644
index 000000000..920e7bfc4
--- /dev/null
+++ b/sc/source/ui/miscdlgs/protectiondlg.cxx
@@ -0,0 +1,154 @@
+/* -*- 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 <protectiondlg.hxx>
+#include <tabprotection.hxx>
+
+#include <vector>
+
+namespace {
+
+// The order must match that of the list box.
+const std::vector<ScTableProtection::Option> aOptions = {
+ ScTableProtection::SELECT_LOCKED_CELLS,
+ ScTableProtection::SELECT_UNLOCKED_CELLS,
+ ScTableProtection::INSERT_COLUMNS,
+ ScTableProtection::INSERT_ROWS,
+ ScTableProtection::DELETE_COLUMNS,
+ ScTableProtection::DELETE_ROWS,
+};
+
+}
+
+ScTableProtectionDlg::ScTableProtectionDlg(weld::Window* pParent)
+ : weld::GenericDialogController(pParent, "modules/scalc/ui/protectsheetdlg.ui", "ProtectSheetDialog")
+ , m_xBtnProtect(m_xBuilder->weld_check_button("protect"))
+ , m_xPasswords(m_xBuilder->weld_container("passwords"))
+ , m_xOptions(m_xBuilder->weld_container("options"))
+ , m_xPassword1Edit(m_xBuilder->weld_entry("password1"))
+ , m_xPassword2Edit(m_xBuilder->weld_entry("password2"))
+ , m_xOptionsListBox(m_xBuilder->weld_tree_view("checklist"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xProtected(m_xBuilder->weld_label("protected"))
+ , m_xUnprotected(m_xBuilder->weld_label("unprotected"))
+ , m_xInsertColumns(m_xBuilder->weld_label("insert-columns"))
+ , m_xInsertRows(m_xBuilder->weld_label("insert-rows"))
+ , m_xDeleteColumns(m_xBuilder->weld_label("delete-columns"))
+ , m_xDeleteRows(m_xBuilder->weld_label("delete-rows"))
+{
+ m_aSelectLockedCells = m_xProtected->get_label();
+ m_aSelectUnlockedCells = m_xUnprotected->get_label();
+ m_aInsertColumns = m_xInsertColumns->get_label();
+ m_aInsertRows = m_xInsertRows->get_label();
+ m_aDeleteColumns = m_xDeleteColumns->get_label();
+ m_aDeleteRows = m_xDeleteRows->get_label();
+
+ m_xOptionsListBox->enable_toggle_buttons(weld::ColumnToggleType::Check);
+
+ Init();
+}
+
+ScTableProtectionDlg::~ScTableProtectionDlg()
+{
+}
+
+void ScTableProtectionDlg::SetDialogData(const ScTableProtection& rData)
+{
+ for (size_t i = 0; i < aOptions.size(); ++i)
+ m_xOptionsListBox->set_toggle(i, rData.isOptionEnabled(aOptions[i]) ? TRISTATE_TRUE : TRISTATE_FALSE);
+}
+
+void ScTableProtectionDlg::WriteData(ScTableProtection& rData) const
+{
+ rData.setProtected(m_xBtnProtect->get_active());
+
+ // We assume that the two password texts match.
+ rData.setPassword(m_xPassword1Edit->get_text());
+
+ for (size_t i = 0; i < aOptions.size(); ++i)
+ rData.setOption(aOptions[i], m_xOptionsListBox->get_toggle(i) == TRISTATE_TRUE);
+}
+
+void ScTableProtectionDlg::InsertEntry(const OUString& rTxt)
+{
+ m_xOptionsListBox->append();
+ const int nRow = m_xOptionsListBox->n_children() - 1;
+ m_xOptionsListBox->set_toggle(nRow, TRISTATE_FALSE);
+ m_xOptionsListBox->set_text(nRow, rTxt, 0);
+}
+
+void ScTableProtectionDlg::Init()
+{
+ m_xBtnProtect->connect_toggled(LINK(this, ScTableProtectionDlg, CheckBoxHdl));
+
+ m_xBtnOk->connect_clicked(LINK(this, ScTableProtectionDlg, OKHdl));
+
+ Link<weld::Entry&,void> aLink = LINK(this, ScTableProtectionDlg, PasswordModifyHdl);
+ m_xPassword1Edit->connect_changed(aLink);
+ m_xPassword2Edit->connect_changed(aLink);
+
+ m_xOptionsListBox->freeze();
+ m_xOptionsListBox->clear();
+
+ InsertEntry(m_aSelectLockedCells);
+ InsertEntry(m_aSelectUnlockedCells);
+ InsertEntry(m_aInsertColumns);
+ InsertEntry(m_aInsertRows);
+ InsertEntry(m_aDeleteColumns);
+ InsertEntry(m_aDeleteRows);
+
+ m_xOptionsListBox->set_toggle(0, TRISTATE_TRUE);
+ m_xOptionsListBox->set_toggle(1, TRISTATE_TRUE);
+
+ m_xOptionsListBox->thaw();
+
+ // Set the default state of the dialog.
+ m_xBtnProtect->set_active(true);
+ m_xPassword1Edit->grab_focus();
+}
+
+void ScTableProtectionDlg::EnableOptionalWidgets(bool bEnable)
+{
+ m_xPasswords->set_sensitive(bEnable);
+ m_xOptions->set_sensitive(bEnable);
+}
+
+IMPL_LINK(ScTableProtectionDlg, CheckBoxHdl, weld::Toggleable&, rBtn, void)
+{
+ if (&rBtn == m_xBtnProtect.get())
+ {
+ bool bChecked = m_xBtnProtect->get_active();
+ EnableOptionalWidgets(bChecked);
+ m_xBtnOk->set_sensitive(bChecked);
+ }
+}
+
+IMPL_LINK_NOARG(ScTableProtectionDlg, OKHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(ScTableProtectionDlg, PasswordModifyHdl, weld::Entry&, void)
+{
+ OUString aPass1 = m_xPassword1Edit->get_text();
+ OUString aPass2 = m_xPassword2Edit->get_text();
+ m_xBtnOk->set_sensitive(aPass1 == aPass2);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/redcom.cxx b/sc/source/ui/miscdlgs/redcom.cxx
new file mode 100644
index 000000000..ef04bd57e
--- /dev/null
+++ b/sc/source/ui/miscdlgs/redcom.cxx
@@ -0,0 +1,167 @@
+/* -*- 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 <unotools/localedatawrapper.hxx>
+
+#include <chgtrack.hxx>
+#include <redcom.hxx>
+#include <docsh.hxx>
+#include <dbfunc.hxx>
+#include <tabview.hxx>
+#include <viewutil.hxx>
+#include <svx/svxdlg.hxx>
+
+ScRedComDialog::ScRedComDialog( weld::Window* pParent, const SfxItemSet& rCoreSet,
+ ScDocShell *pShell, ScChangeAction *pAction, bool bPrevNext)
+ : pChangeAction(nullptr)
+ , pDocShell(nullptr)
+ , pDlg(nullptr)
+{
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg = pFact->CreateSvxPostItDialog( pParent, rCoreSet, bPrevNext );
+ pDocShell=pShell;
+ pDlg->DontChangeAuthor();
+ pDlg->HideAuthor();
+
+ pDlg->SetPrevHdl(LINK( this, ScRedComDialog, PrevHdl));
+ pDlg->SetNextHdl(LINK( this, ScRedComDialog, NextHdl));
+
+ ReInit(pAction);
+}
+
+ScRedComDialog::~ScRedComDialog()
+{
+ pDlg.disposeAndClear();
+}
+
+ScChangeAction *ScRedComDialog::FindPrev(ScChangeAction *pAction)
+{
+ if(pAction!=nullptr && pDocShell !=nullptr)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChangeViewSettings* pSettings = rDoc.GetChangeViewSettings();
+
+ pAction=pAction->GetPrev();
+
+ while(pAction!=nullptr)
+ {
+ if( pAction->GetState()==SC_CAS_VIRGIN &&
+ pAction->IsDialogRoot() &&
+ ScViewUtil::IsActionShown(*pAction,*pSettings,rDoc)) break;
+
+ pAction=pAction->GetPrev();
+ }
+ }
+ return pAction;
+}
+
+ScChangeAction *ScRedComDialog::FindNext(ScChangeAction *pAction)
+{
+ if(pAction!=nullptr && pDocShell !=nullptr)
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScChangeViewSettings* pSettings = rDoc.GetChangeViewSettings();
+
+ pAction=pAction->GetNext();
+
+ while(pAction!=nullptr)
+ {
+ if( pAction->GetState()==SC_CAS_VIRGIN &&
+ pAction->IsDialogRoot() &&
+ ScViewUtil::IsActionShown(*pAction,*pSettings,rDoc)) break;
+
+ pAction=pAction->GetNext();
+ }
+ }
+ return pAction;
+}
+
+void ScRedComDialog::ReInit(ScChangeAction *pAction)
+{
+ pChangeAction=pAction;
+ if(pChangeAction==nullptr || pDocShell ==nullptr)
+ return;
+
+ OUString aTitle = pChangeAction->GetDescription(pDocShell->GetDocument());
+ pDlg->SetText(aTitle);
+ aComment=pChangeAction->GetComment();
+
+ bool bNext=FindNext(pChangeAction)!=nullptr;
+ bool bPrev=FindPrev(pChangeAction)!=nullptr;
+ pDlg->EnableTravel(bNext,bPrev);
+
+ OUString aAuthor = pChangeAction->GetUser();
+
+ DateTime aDT = pChangeAction->GetDateTime();
+ OUString aDate = ScGlobal::getLocaleData().getDate( aDT ) + " " +
+ ScGlobal::getLocaleData().getTime( aDT, false );
+
+ pDlg->ShowLastAuthor(aAuthor, aDate);
+ pDlg->SetNote(aComment);
+}
+
+void ScRedComDialog::Execute()
+{
+ short nRet=pDlg->Execute();
+
+ if(nRet== RET_OK )
+ {
+ if ( pDocShell!=nullptr && pDlg->GetNote() != aComment )
+ pDocShell->SetChangeComment( pChangeAction, pDlg->GetNote());
+ }
+}
+
+void ScRedComDialog::SelectCell()
+{
+ if (!pChangeAction || !pDocShell)
+ return;
+
+ const ScChangeAction* pAction=pChangeAction;
+ const ScBigRange& rRange = pAction->GetBigRange();
+
+ if(rRange.IsValid(pDocShell->GetDocument()))
+ {
+ if (ScViewData* pViewData = ScDocShell::GetViewData())
+ {
+ ScRange aRef = rRange.MakeRange(pDocShell->GetDocument());
+ ScTabView* pTabView = pViewData->GetView();
+ pTabView->MarkRange(aRef);
+ }
+ }
+}
+
+IMPL_LINK(ScRedComDialog, PrevHdl, AbstractSvxPostItDialog&, rDlgP, void )
+{
+ if (pDocShell!=nullptr && rDlgP.GetNote() != aComment )
+ pDocShell->SetChangeComment( pChangeAction, rDlgP.GetNote());
+
+ ReInit(FindPrev(pChangeAction));
+ SelectCell();
+}
+
+IMPL_LINK(ScRedComDialog, NextHdl, AbstractSvxPostItDialog&, rDlgP, void )
+{
+ if ( pDocShell!=nullptr && rDlgP.GetNote() != aComment )
+ pDocShell->SetChangeComment( pChangeAction, rDlgP.GetNote());
+
+ ReInit(FindNext(pChangeAction));
+ SelectCell();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx
new file mode 100644
index 000000000..c7b9084a8
--- /dev/null
+++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx
@@ -0,0 +1,366 @@
+/* -*- 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 <vcl/svapp.hxx>
+#include <strings.hrc>
+#include <retypepassdlg.hxx>
+#include <scresid.hxx>
+#include <document.hxx>
+#include <tabprotection.hxx>
+
+ScRetypePassDlg::ScRetypePassDlg(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/retypepassdialog.ui", "RetypePass")
+ , maTextNotProtected(ScResId(STR_NOT_PROTECTED))
+ , maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED))
+ , maTextHashBad(ScResId(STR_HASH_BAD))
+ , maTextHashGood(ScResId(STR_HASH_GOOD))
+ , meDesiredHash(PASSHASH_SHA1)
+ , mxBtnOk(m_xBuilder->weld_button("ok"))
+ , mxTextDocStatus(m_xBuilder->weld_label("docStatusLabel"))
+ , mxBtnRetypeDoc(m_xBuilder->weld_button("retypeDocButton"))
+ , mxScrolledWindow(m_xBuilder->weld_scrolled_window("scrolledwindow"))
+ , mxSheetsBox(m_xBuilder->weld_container("sheetsBox"))
+{
+ mxScrolledWindow->set_size_request(mxScrolledWindow->get_approximate_digit_width() * 46,
+ mxScrolledWindow->get_text_height() * 10);
+ Init();
+}
+
+ScRetypePassDlg::~ScRetypePassDlg() {}
+
+void ScRetypePassDlg::DeleteSheets() { maSheets.clear(); }
+
+short ScRetypePassDlg::run()
+{
+ PopulateDialog();
+ CheckHashStatus();
+ return GenericDialogController::run();
+}
+
+PassFragment::PassFragment(weld::Widget* pParent)
+ : m_xBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/passfragment.ui"))
+ , m_xSheetsBox(m_xBuilder->weld_container("PassEntry"))
+ , m_xName(m_xBuilder->weld_label("name"))
+ , m_xStatus(m_xBuilder->weld_label("status"))
+ , m_xButton(m_xBuilder->weld_button("button"))
+{
+ m_xButton->set_label(ScResId(STR_RETYPE));
+}
+
+void ScRetypePassDlg::SetDataFromDocument(const ScDocument& rDoc)
+{
+ DeleteSheets();
+ const ScDocProtection* pDocProtect = rDoc.GetDocProtection();
+ if (pDocProtect && pDocProtect->isProtected())
+ mpDocItem = std::make_shared<ScDocProtection>(*pDocProtect);
+
+ SCTAB nTabCount = rDoc.GetTableCount();
+ maTableItems.reserve(nTabCount);
+ maSheets.reserve(nTabCount);
+ for (SCTAB i = 0; i < nTabCount; ++i)
+ {
+ TableItem aTabItem;
+ rDoc.GetName(i, aTabItem.maName);
+
+ const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i);
+ if (pTabProtect && pTabProtect->isProtected())
+ aTabItem.mpProtect = std::make_shared<ScTableProtection>(*pTabProtect);
+
+ maTableItems.push_back(aTabItem);
+ maSheets.emplace_back(new PassFragment(mxSheetsBox.get()));
+ maSheets.back()->m_xButton->connect_clicked(LINK(this, ScRetypePassDlg, RetypeBtnHdl));
+ }
+}
+
+void ScRetypePassDlg::SetDesiredHash(ScPasswordHash eHash) { meDesiredHash = eHash; }
+
+void ScRetypePassDlg::WriteNewDataToDocument(ScDocument& rDoc) const
+{
+ if (mpDocItem)
+ rDoc.SetDocProtection(mpDocItem.get());
+
+ size_t nTabCount = static_cast<size_t>(rDoc.GetTableCount());
+ size_t n = maTableItems.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (i >= nTabCount)
+ break;
+
+ ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get();
+ if (pTabProtect)
+ rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect);
+ }
+}
+
+void ScRetypePassDlg::Init()
+{
+ Link<weld::Button&, void> aLink = LINK(this, ScRetypePassDlg, OKHdl);
+ mxBtnOk->connect_clicked(aLink);
+
+ aLink = LINK(this, ScRetypePassDlg, RetypeBtnHdl);
+ mxBtnRetypeDoc->connect_clicked(aLink);
+
+ mxTextDocStatus->set_label(maTextNotProtected);
+ mxBtnRetypeDoc->set_sensitive(false);
+}
+
+void ScRetypePassDlg::PopulateDialog()
+{
+ // Document protection first.
+ SetDocData();
+
+ // Sheet protection next.
+ for (size_t i = 0; i < maTableItems.size(); ++i)
+ SetTableData(i, static_cast<SCTAB>(i));
+}
+
+void ScRetypePassDlg::SetDocData()
+{
+ bool bBtnEnabled = false;
+ if (mpDocItem && mpDocItem->isProtected())
+ {
+ if (mpDocItem->isPasswordEmpty())
+ mxTextDocStatus->set_label(maTextNotPassProtected);
+ else if (mpDocItem->hasPasswordHash(meDesiredHash))
+ mxTextDocStatus->set_label(maTextHashGood);
+ else
+ {
+ // incompatible hash
+ mxTextDocStatus->set_label(maTextHashBad);
+ bBtnEnabled = true;
+ }
+ }
+ mxBtnRetypeDoc->set_sensitive(bBtnEnabled);
+}
+
+void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab)
+{
+ if (nRowPos >= maSheets.size())
+ return;
+
+ weld::Label& rName = *maSheets[nRowPos]->m_xName;
+ weld::Label& rStatus = *maSheets[nRowPos]->m_xStatus;
+ weld::Button& rBtn = *maSheets[nRowPos]->m_xButton;
+
+ bool bBtnEnabled = false;
+ rName.set_label(maTableItems[nTab].maName);
+ const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
+ if (pTabProtect && pTabProtect->isProtected())
+ {
+ if (pTabProtect->isPasswordEmpty())
+ rStatus.set_label(maTextNotPassProtected);
+ else if (pTabProtect->hasPasswordHash(meDesiredHash))
+ rStatus.set_label(maTextHashGood);
+ else
+ {
+ // incompatible hash
+ rStatus.set_label(maTextHashBad);
+ bBtnEnabled = true;
+ }
+ }
+ else
+ rStatus.set_label(maTextNotProtected);
+
+ rBtn.set_sensitive(bBtnEnabled);
+}
+
+static bool lcl_IsInGoodStatus(const ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash)
+{
+ if (!pProtected || !pProtected->isProtected())
+ // Not protected.
+ return true;
+
+ if (pProtected->isPasswordEmpty())
+ return true;
+
+ if (pProtected->hasPasswordHash(eDesiredHash))
+ return true;
+
+ return false;
+}
+
+void ScRetypePassDlg::CheckHashStatus()
+{
+ do
+ {
+ if (!lcl_IsInGoodStatus(mpDocItem.get(), meDesiredHash))
+ break;
+
+ bool bStatusGood = true;
+ size_t nTabCount = maTableItems.size();
+ for (size_t i = 0; i < nTabCount && bStatusGood; ++i)
+ {
+ if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash))
+ bStatusGood = false;
+ }
+ if (!bStatusGood)
+ break;
+
+ mxBtnOk->set_sensitive(true);
+ return;
+ } while (false);
+
+ mxBtnOk->set_sensitive(false);
+}
+
+IMPL_LINK_NOARG(ScRetypePassDlg, OKHdl, weld::Button&, void) { m_xDialog->response(RET_OK); }
+
+IMPL_LINK(ScRetypePassDlg, RetypeBtnHdl, weld::Button&, rBtn, void)
+{
+ ScPassHashProtectable* pProtected = nullptr;
+ if (&rBtn == mxBtnRetypeDoc.get())
+ {
+ // document protection.
+ pProtected = mpDocItem.get();
+ }
+ else
+ {
+ // sheet protection.
+ size_t aPos = 0;
+ while (aPos < maSheets.size() && &rBtn != maSheets[aPos]->m_xButton.get())
+ ++aPos;
+
+ pProtected = aPos < maSheets.size() ? maTableItems[aPos].mpProtect.get() : nullptr;
+ }
+
+ if (!pProtected)
+ // What the ... !?
+ return;
+
+ ScRetypePassInputDlg aDlg(m_xDialog.get(), pProtected);
+ if (aDlg.run() != RET_OK)
+ return;
+
+ // OK is pressed. Update the protected item.
+ if (aDlg.IsRemovePassword())
+ {
+ // Remove password from this item.
+ pProtected->setPassword(OUString());
+ }
+ else
+ {
+ // Set a new password.
+ OUString aNewPass = aDlg.GetNewPassword();
+ pProtected->setPassword(aNewPass);
+ }
+
+ SetDocData();
+ CheckHashStatus();
+}
+
+ScRetypePassInputDlg::ScRetypePassInputDlg(weld::Window* pParent, ScPassHashProtectable* pProtected)
+ : GenericDialogController(pParent, "modules/scalc/ui/retypepassworddialog.ui",
+ "RetypePasswordDialog")
+ , m_pProtected(pProtected)
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnRetypePassword(m_xBuilder->weld_radio_button("retypepassword"))
+ , m_xPasswordGrid(m_xBuilder->weld_widget("passwordgrid"))
+ , m_xPassword1Edit(m_xBuilder->weld_entry("newpassEntry"))
+ , m_xPassword2Edit(m_xBuilder->weld_entry("confirmpassEntry"))
+ , m_xBtnMatchOldPass(m_xBuilder->weld_check_button("mustmatch"))
+ , m_xBtnRemovePassword(m_xBuilder->weld_radio_button("removepassword"))
+{
+ Init();
+}
+
+ScRetypePassInputDlg::~ScRetypePassInputDlg() {}
+
+bool ScRetypePassInputDlg::IsRemovePassword() const { return m_xBtnRemovePassword->get_active(); }
+
+OUString ScRetypePassInputDlg::GetNewPassword() const { return m_xPassword1Edit->get_text(); }
+
+void ScRetypePassInputDlg::Init()
+{
+ m_xBtnOk->connect_clicked(LINK(this, ScRetypePassInputDlg, OKHdl));
+ m_xBtnRetypePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl));
+ m_xBtnRemovePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl));
+ m_xBtnMatchOldPass->connect_toggled(LINK(this, ScRetypePassInputDlg, CheckBoxHdl));
+ Link<weld::Entry&, void> aLink2 = LINK(this, ScRetypePassInputDlg, PasswordModifyHdl);
+ m_xPassword1Edit->connect_changed(aLink2);
+ m_xPassword2Edit->connect_changed(aLink2);
+
+ m_xBtnOk->set_sensitive(false);
+ m_xBtnRetypePassword->set_active(true);
+ m_xBtnMatchOldPass->set_active(true);
+ m_xPassword1Edit->grab_focus();
+}
+
+void ScRetypePassInputDlg::CheckPasswordInput()
+{
+ OUString aPass1 = m_xPassword1Edit->get_text();
+ OUString aPass2 = m_xPassword2Edit->get_text();
+
+ if (aPass1.isEmpty() || aPass2.isEmpty())
+ {
+ // Empty password is not allowed.
+ m_xBtnOk->set_sensitive(false);
+ return;
+ }
+
+ if (aPass1 != aPass2)
+ {
+ // The two passwords differ.
+ m_xBtnOk->set_sensitive(false);
+ return;
+ }
+
+ if (!m_xBtnMatchOldPass->get_active())
+ {
+ m_xBtnOk->set_sensitive(true);
+ return;
+ }
+
+ if (!m_pProtected)
+ {
+ // This should never happen!
+ m_xBtnOk->set_sensitive(false);
+ return;
+ }
+
+ bool bPassGood = m_pProtected->verifyPassword(aPass1);
+ m_xBtnOk->set_sensitive(bPassGood);
+}
+
+IMPL_LINK_NOARG(ScRetypePassInputDlg, OKHdl, weld::Button&, void) { m_xDialog->response(RET_OK); }
+
+IMPL_LINK_NOARG(ScRetypePassInputDlg, RadioBtnHdl, weld::Toggleable&, void)
+{
+ if (m_xBtnRetypePassword->get_active())
+ {
+ m_xPasswordGrid->set_sensitive(true);
+ CheckPasswordInput();
+ }
+ else
+ {
+ m_xPasswordGrid->set_sensitive(false);
+ m_xBtnOk->set_sensitive(true);
+ }
+}
+
+IMPL_LINK_NOARG(ScRetypePassInputDlg, CheckBoxHdl, weld::Toggleable&, void)
+{
+ CheckPasswordInput();
+}
+
+IMPL_LINK_NOARG(ScRetypePassInputDlg, PasswordModifyHdl, weld::Entry&, void)
+{
+ CheckPasswordInput();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/scuiautofmt.cxx b/sc/source/ui/miscdlgs/scuiautofmt.cxx
new file mode 100644
index 000000000..ecf446081
--- /dev/null
+++ b/sc/source/ui/miscdlgs/scuiautofmt.cxx
@@ -0,0 +1,385 @@
+/* -*- 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 <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/strings.hrc>
+#include <sfx2/sfxresid.hxx>
+#include <o3tl/string_view.hxx>
+#include <strings.hrc>
+#include <global.hxx>
+#include <globstr.hrc>
+#include <autoform.hxx>
+#include <strindlg.hxx>
+#include <scuiautofmt.hxx>
+#include <scresid.hxx>
+#include <helpids.h>
+
+// AutoFormat-Dialog:
+
+ScAutoFormatDlg::ScAutoFormatDlg(weld::Window* pParent,
+ ScAutoFormat* pAutoFormat,
+ const ScAutoFormatData* pSelFormatData,
+ const ScViewData& rViewData)
+ : GenericDialogController(pParent, "modules/scalc/ui/autoformattable.ui", "AutoFormatTableDialog")
+ , aStrTitle(ScResId(STR_ADD_AUTOFORMAT_TITLE))
+ , aStrLabel(ScResId(STR_ADD_AUTOFORMAT_LABEL))
+ , aStrClose(ScResId(STR_BTN_AUTOFORMAT_CLOSE))
+ , aStrDelMsg(ScResId(STR_DEL_AUTOFORMAT_MSG))
+ , aStrRename(ScResId(STR_RENAME_AUTOFORMAT_TITLE))
+ , pFormat(pAutoFormat)
+ , pSelFmtData(pSelFormatData)
+ , nIndex(0)
+ , bCoreDataChanged(false)
+ , bFmtInserted(false)
+ , m_xLbFormat(m_xBuilder->weld_tree_view("formatlb"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+ , m_xBtnAdd(m_xBuilder->weld_button("add"))
+ , m_xBtnRemove(m_xBuilder->weld_button("remove"))
+ , m_xBtnRename(m_xBuilder->weld_button("rename"))
+ , m_xBtnNumFormat(m_xBuilder->weld_check_button("numformatcb"))
+ , m_xBtnBorder(m_xBuilder->weld_check_button("bordercb"))
+ , m_xBtnFont(m_xBuilder->weld_check_button("fontcb"))
+ , m_xBtnPattern(m_xBuilder->weld_check_button("patterncb"))
+ , m_xBtnAlignment(m_xBuilder->weld_check_button("alignmentcb"))
+ , m_xBtnAdjust(m_xBuilder->weld_check_button("autofitcb"))
+ , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aWndPreview))
+{
+ m_aWndPreview.DetectRTL(rViewData);
+
+ const int nWidth = m_xLbFormat->get_approximate_digit_width() * 32;
+ const int nHeight = m_xLbFormat->get_height_rows(8);
+ m_xLbFormat->set_size_request(nWidth, nHeight);
+ m_xWndPreview->set_size_request(nWidth, nHeight);
+
+ Init();
+ ScAutoFormat::iterator it = pFormat->begin();
+ m_aWndPreview.NotifyChange(it->second.get());
+}
+
+ScAutoFormatDlg::~ScAutoFormatDlg()
+{
+}
+
+void ScAutoFormatDlg::Init()
+{
+ m_xLbFormat->connect_changed( LINK( this, ScAutoFormatDlg, SelFmtHdl ) );
+ m_xBtnNumFormat->connect_toggled( LINK( this, ScAutoFormatDlg, CheckHdl ) );
+ m_xBtnBorder->connect_toggled( LINK( this, ScAutoFormatDlg, CheckHdl ) );
+ m_xBtnFont->connect_toggled( LINK( this, ScAutoFormatDlg, CheckHdl ) );
+ m_xBtnPattern->connect_toggled( LINK( this, ScAutoFormatDlg, CheckHdl ) );
+ m_xBtnAlignment->connect_toggled( LINK( this, ScAutoFormatDlg, CheckHdl ) );
+ m_xBtnAdjust->connect_toggled( LINK( this, ScAutoFormatDlg, CheckHdl ) );
+ m_xBtnAdd->connect_clicked ( LINK( this, ScAutoFormatDlg, AddHdl ) );
+ m_xBtnRemove->connect_clicked ( LINK( this, ScAutoFormatDlg, RemoveHdl ) );
+ m_xBtnOk->connect_clicked ( LINK( this, ScAutoFormatDlg, CloseHdl ) );
+ m_xBtnCancel->connect_clicked ( LINK( this, ScAutoFormatDlg, CloseHdl ) );
+ m_xBtnRename->connect_clicked ( LINK( this, ScAutoFormatDlg, RenameHdl ) );
+ m_xLbFormat->connect_row_activated( LINK( this, ScAutoFormatDlg, DblClkHdl ) );
+
+ for (const auto& rEntry : *pFormat)
+ m_xLbFormat->append_text(rEntry.second->GetName());
+
+ if (pFormat->size() == 1)
+ m_xBtnRemove->set_sensitive(false);
+
+ m_xLbFormat->select(0);
+ m_xBtnRename->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(false);
+
+ nIndex = 0;
+ UpdateChecks();
+
+ if ( !pSelFmtData )
+ {
+ m_xBtnAdd->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(false);
+ bFmtInserted = true;
+ }
+}
+
+void ScAutoFormatDlg::UpdateChecks()
+{
+ const ScAutoFormatData* pData = pFormat->findByIndex(nIndex);
+
+ m_xBtnNumFormat->set_active( pData->GetIncludeValueFormat() );
+ m_xBtnBorder->set_active( pData->GetIncludeFrame() );
+ m_xBtnFont->set_active( pData->GetIncludeFont() );
+ m_xBtnPattern->set_active( pData->GetIncludeBackground() );
+ m_xBtnAlignment->set_active( pData->GetIncludeJustify() );
+ m_xBtnAdjust->set_active( pData->GetIncludeWidthHeight() );
+}
+
+// Handler:
+
+IMPL_LINK(ScAutoFormatDlg, CloseHdl, weld::Button&, rBtn, void)
+{
+ if (&rBtn == m_xBtnOk.get() || &rBtn == m_xBtnCancel.get())
+ {
+ if ( bCoreDataChanged )
+ ScGlobal::GetOrCreateAutoFormat()->Save();
+
+ m_xDialog->response( (&rBtn == m_xBtnOk.get()) ? RET_OK : RET_CANCEL );
+ }
+}
+
+IMPL_LINK_NOARG(ScAutoFormatDlg, DblClkHdl, weld::TreeView&, bool)
+{
+ if ( bCoreDataChanged )
+ ScGlobal::GetOrCreateAutoFormat()->Save();
+
+ m_xDialog->response( RET_OK );
+
+ return true;
+}
+
+IMPL_LINK(ScAutoFormatDlg, CheckHdl, weld::Toggleable&, rBtn, void)
+{
+ ScAutoFormatData* pData = pFormat->findByIndex(nIndex);
+ bool bCheck = rBtn.get_active();
+
+ if (&rBtn == m_xBtnNumFormat.get())
+ pData->SetIncludeValueFormat( bCheck );
+ else if (&rBtn == m_xBtnBorder.get())
+ pData->SetIncludeFrame( bCheck );
+ else if (&rBtn == m_xBtnFont.get())
+ pData->SetIncludeFont( bCheck );
+ else if (&rBtn == m_xBtnPattern.get())
+ pData->SetIncludeBackground( bCheck );
+ else if (&rBtn == m_xBtnAlignment.get())
+ pData->SetIncludeJustify( bCheck );
+ else if (&rBtn == m_xBtnAdjust.get())
+ pData->SetIncludeWidthHeight( bCheck );
+
+ if ( !bCoreDataChanged )
+ {
+ m_xBtnCancel->set_label(aStrClose);
+ bCoreDataChanged = true;
+ }
+
+ m_aWndPreview.NotifyChange( pData );
+}
+
+IMPL_LINK_NOARG(ScAutoFormatDlg, AddHdl, weld::Button&, void)
+{
+ if ( bFmtInserted || !pSelFmtData )
+ return;
+
+ OUString aStrStandard( SfxResId(STR_STANDARD) );
+ OUString aFormatName;
+ bool bOk = false;
+
+ while ( !bOk )
+ {
+ ScStringInputDlg aDlg(m_xDialog.get(), aStrTitle, aStrLabel, aFormatName,
+ HID_SC_ADD_AUTOFMT, HID_SC_AUTOFMT_NAME);
+
+ if (aDlg.run() == RET_OK)
+ {
+ aFormatName = aDlg.GetInputString();
+
+ if ( !aFormatName.isEmpty() && aFormatName != aStrStandard && pFormat->find(aFormatName) == pFormat->end() )
+ {
+ std::unique_ptr<ScAutoFormatData> pNewData(
+ new ScAutoFormatData( *pSelFmtData ));
+
+ pNewData->SetName( aFormatName );
+ ScAutoFormat::iterator it = pFormat->insert(std::move(pNewData));
+ bFmtInserted = it != pFormat->end();
+
+ if ( bFmtInserted )
+ {
+ size_t nPos = std::distance(pFormat->begin(), it);
+ m_xLbFormat->insert_text(nPos, aFormatName);
+ m_xLbFormat->select_text( aFormatName );
+ m_xBtnAdd->set_sensitive(false);
+
+ if ( !bCoreDataChanged )
+ {
+ m_xBtnCancel->set_label( aStrClose );
+ bCoreDataChanged = true;
+ }
+
+ SelFmtHdl( *m_xLbFormat );
+ bOk = true;
+ }
+ }
+
+ if ( !bFmtInserted )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Error, VclButtonsType::OkCancel,
+ ScResId(STR_INVALID_AFNAME)));
+
+ sal_uInt16 nRet = xBox->run();
+
+ bOk = ( nRet == RET_CANCEL );
+ }
+ }
+ else
+ bOk = true;
+ }
+}
+
+IMPL_LINK_NOARG(ScAutoFormatDlg, RemoveHdl, weld::Button&, void)
+{
+ if ( (nIndex > 0) && (m_xLbFormat->n_children() > 0) )
+ {
+ OUString aMsg = o3tl::getToken(aStrDelMsg, 0, '#' )
+ + m_xLbFormat->get_selected_text()
+ + o3tl::getToken(aStrDelMsg, 1, '#' );
+
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ aMsg));
+ xQueryBox->set_default_response(RET_YES);
+
+ if (RET_YES == xQueryBox->run())
+ {
+ m_xLbFormat->remove(nIndex);
+ m_xLbFormat->select(nIndex-1);
+
+ if ( nIndex-1 == 0 )
+ m_xBtnRemove->set_sensitive(false);
+
+ if ( !bCoreDataChanged )
+ {
+ m_xBtnCancel->set_label( aStrClose );
+ bCoreDataChanged = true;
+ }
+
+ ScAutoFormat::iterator it = pFormat->begin();
+ std::advance(it, nIndex);
+ pFormat->erase(it);
+ nIndex--;
+
+ SelFmtHdl( *m_xLbFormat );
+ }
+ }
+
+ SelFmtHdl( *m_xLbFormat );
+}
+
+IMPL_LINK_NOARG(ScAutoFormatDlg, RenameHdl, weld::Button&, void)
+{
+ bool bOk = false;
+ while( !bOk )
+ {
+
+ OUString aFormatName = m_xLbFormat->get_selected_text();
+ OUString aEntry;
+
+ ScStringInputDlg aDlg(m_xDialog.get(), aStrRename, aStrLabel, aFormatName,
+ HID_SC_REN_AFMT_DLG, HID_SC_REN_AFMT_NAME);
+ if (aDlg.run() == RET_OK)
+ {
+ bool bFmtRenamed = false;
+ aFormatName = aDlg.GetInputString();
+
+ if (!aFormatName.isEmpty())
+ {
+ ScAutoFormat::iterator it = pFormat->begin(), itEnd = pFormat->end();
+ for (; it != itEnd; ++it)
+ {
+ aEntry = it->second->GetName();
+ if (aFormatName == aEntry)
+ break;
+ }
+ if (it == itEnd)
+ {
+ // no format with this name yet, so we can rename
+
+ m_xLbFormat->remove(nIndex);
+ const ScAutoFormatData* p = pFormat->findByIndex(nIndex);
+ std::unique_ptr<ScAutoFormatData> pNewData(new ScAutoFormatData(*p));
+
+ it = pFormat->begin();
+ std::advance(it, nIndex);
+ pFormat->erase(it);
+
+ pNewData->SetName( aFormatName );
+
+ pFormat->insert(std::move(pNewData));
+
+ m_xLbFormat->freeze();
+ m_xLbFormat->clear();
+ for (it = pFormat->begin(); it != itEnd; ++it)
+ {
+ aEntry = it->second->GetName();
+ m_xLbFormat->append_text(aEntry);
+ }
+
+ m_xLbFormat->thaw();
+ m_xLbFormat->select_text(aFormatName);
+
+ if ( !bCoreDataChanged )
+ {
+ m_xBtnCancel->set_label( aStrClose );
+ bCoreDataChanged = true;
+ }
+
+ SelFmtHdl( *m_xLbFormat );
+ bOk = true;
+ bFmtRenamed = true;
+ }
+ }
+ if( !bFmtRenamed )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Error, VclButtonsType::OkCancel,
+ ScResId(STR_INVALID_AFNAME)));
+
+ bOk = RET_CANCEL == xBox->run();
+ }
+ }
+ else
+ bOk = true;
+ }
+}
+
+IMPL_LINK_NOARG(ScAutoFormatDlg, SelFmtHdl, weld::TreeView&, void)
+{
+ nIndex = m_xLbFormat->get_selected_index();
+ UpdateChecks();
+
+ if ( nIndex == 0 )
+ {
+ m_xBtnRename->set_sensitive(false);
+ m_xBtnRemove->set_sensitive(false);
+ }
+ else
+ {
+ m_xBtnRename->set_sensitive(true);
+ m_xBtnRemove->set_sensitive(true);
+ }
+
+ ScAutoFormatData* p = pFormat->findByIndex(nIndex);
+ m_aWndPreview.NotifyChange(p);
+}
+
+OUString ScAutoFormatDlg::GetCurrFormatName()
+{
+ const ScAutoFormatData* p = pFormat->findByIndex(nIndex);
+ return p ? p->GetName() : OUString();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/sharedocdlg.cxx b/sc/source/ui/miscdlgs/sharedocdlg.cxx
new file mode 100644
index 000000000..9abf05c6b
--- /dev/null
+++ b/sc/source/ui/miscdlgs/sharedocdlg.cxx
@@ -0,0 +1,213 @@
+/* -*- 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 <o3tl/safeint.hxx>
+#include <osl/security.hxx>
+#include <osl/diagnose.h>
+#include <sfx2/dialoghelper.hxx>
+#include <svl/sharecontrolfile.hxx>
+#include <unotools/useroptions.hxx>
+#include <tools/diagnose_ex.h>
+#include <o3tl/string_view.hxx>
+
+#include <docsh.hxx>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+#include <scresid.hxx>
+#include <sharedocdlg.hxx>
+#include <strings.hrc>
+#include <viewdata.hxx>
+
+using namespace ::com::sun::star;
+
+IMPL_LINK(ScShareDocumentDlg, SizeAllocated, const Size&, rSize, void)
+{
+ OUString sWidestAccessString = getWidestDateTime(ScGlobal::getLocaleData(), false);
+ const int nAccessWidth = m_xLbUsers->get_pixel_size(sWidestAccessString).Width() * 2;
+ std::vector<int> aWidths
+ {
+ o3tl::narrowing<int>(rSize.Width() - nAccessWidth)
+ };
+ m_xLbUsers->set_column_fixed_widths(aWidths);
+}
+
+
+ScShareDocumentDlg::ScShareDocumentDlg(weld::Window* pParent, const ScViewData* pViewData)
+ : GenericDialogController(pParent, "modules/scalc/ui/sharedocumentdlg.ui",
+ "ShareDocumentDialog")
+ , m_aStrNoUserData(ScResId(STR_NO_USER_DATA_AVAILABLE))
+ , m_aStrUnknownUser(ScResId(STR_UNKNOWN_USER_CONFLICT))
+ , m_aStrExclusiveAccess(ScResId(STR_EXCLUSIVE_ACCESS))
+ , mpDocShell(nullptr)
+ , m_xCbShare(m_xBuilder->weld_check_button("share"))
+ , m_xFtWarning(m_xBuilder->weld_label("warning"))
+ , m_xLbUsers(m_xBuilder->weld_tree_view("users"))
+{
+
+ OSL_ENSURE( pViewData, "ScShareDocumentDlg CTOR: mpViewData is null!" );
+ mpDocShell = ( pViewData ? pViewData->GetDocShell() : nullptr );
+ OSL_ENSURE( mpDocShell, "ScShareDocumentDlg CTOR: mpDocShell is null!" );
+
+ std::vector<int> aWidths
+ {
+ o3tl::narrowing<int>(m_xLbUsers->get_approximate_digit_width() * 25)
+ };
+ m_xLbUsers->set_column_fixed_widths(aWidths);
+
+ m_xLbUsers->set_size_request(-1, m_xLbUsers->get_height_rows(9));
+ m_xLbUsers->connect_size_allocate(LINK(this, ScShareDocumentDlg, SizeAllocated));
+
+ bool bIsDocShared = mpDocShell && mpDocShell->IsDocShared();
+ m_xCbShare->set_active(bIsDocShared);
+ m_xCbShare->connect_toggled( LINK( this, ScShareDocumentDlg, ToggleHandle ) );
+ m_xFtWarning->set_sensitive(bIsDocShared);
+
+ m_xLbUsers->set_selection_mode(SelectionMode::NONE);
+
+ UpdateView();
+}
+
+ScShareDocumentDlg::~ScShareDocumentDlg()
+{
+}
+
+IMPL_LINK_NOARG(ScShareDocumentDlg, ToggleHandle, weld::Toggleable&, void)
+{
+ m_xFtWarning->set_sensitive(m_xCbShare->get_active());
+}
+
+bool ScShareDocumentDlg::IsShareDocumentChecked() const
+{
+ return m_xCbShare->get_active();
+}
+
+void ScShareDocumentDlg::UpdateView()
+{
+ if ( !mpDocShell )
+ {
+ return;
+ }
+
+ if ( mpDocShell->IsDocShared() )
+ {
+ try
+ {
+ ::svt::ShareControlFile aControlFile( mpDocShell->GetSharedFileURL() );
+ std::vector<LockFileEntry> aUsersData = aControlFile.GetUsersData();
+ sal_Int32 nLength = aUsersData.size();
+
+ if ( nLength > 0 )
+ {
+ sal_Int32 nUnknownUser = 1;
+
+ for ( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ if ( !aUsersData[i][LockFileComponent::EDITTIME].isEmpty() )
+ {
+ OUString aUser;
+ if ( !aUsersData[i][LockFileComponent::OOOUSERNAME].isEmpty() )
+ {
+ aUser = aUsersData[i][LockFileComponent::OOOUSERNAME];
+ }
+ else if ( !aUsersData[i][LockFileComponent::SYSUSERNAME].isEmpty() )
+ {
+ aUser = aUsersData[i][LockFileComponent::SYSUSERNAME];
+ }
+ else
+ {
+ aUser = m_aStrUnknownUser + " " + OUString::number( nUnknownUser++ );
+ }
+
+ // parse the edit time string of the format "DD.MM.YYYY hh:mm"
+ OUString aDateTimeStr = aUsersData[i][LockFileComponent::EDITTIME];
+ sal_Int32 nIndex = 0;
+ std::u16string_view aDateStr = o3tl::getToken(aDateTimeStr, 0, ' ', nIndex );
+ std::u16string_view aTimeStr = o3tl::getToken(aDateTimeStr, 0, ' ', nIndex );
+ nIndex = 0;
+ sal_uInt16 nDay = sal::static_int_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(aDateStr, 0, '.', nIndex )) );
+ sal_uInt16 nMonth = sal::static_int_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(aDateStr, 0, '.', nIndex )) );
+ sal_uInt16 nYear = sal::static_int_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(aDateStr, 0, '.', nIndex )) );
+ nIndex = 0;
+ sal_uInt16 nHours = sal::static_int_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(aTimeStr, 0, ':', nIndex )) );
+ sal_uInt16 nMinutes = sal::static_int_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(aTimeStr, 0, ':', nIndex )) );
+ Date aDate( nDay, nMonth, nYear );
+ tools::Time aTime( nHours, nMinutes );
+ DateTime aDateTime( aDate, aTime );
+
+ OUString aString = formatDateTime(aDateTime, ScGlobal::getLocaleData(), false);
+
+ m_xLbUsers->append_text(aUser);
+ m_xLbUsers->set_text(m_xLbUsers->n_children() - 1, aString, 1);
+ }
+ }
+ }
+ else
+ {
+ m_xLbUsers->append_text(m_aStrNoUserData);
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sc", "ScShareDocumentDlg::UpdateView()" );
+ m_xLbUsers->clear();
+ m_xLbUsers->append_text(m_aStrNoUserData);
+ }
+ }
+ else
+ {
+ // get OOO user name
+ SvtUserOptions aUserOpt;
+ OUString aUser = aUserOpt.GetFirstName();
+ if ( !aUser.isEmpty() )
+ {
+ aUser += " ";
+ }
+ aUser += aUserOpt.GetLastName();
+ if ( aUser.isEmpty() )
+ {
+ // get sys user name
+ OUString aUserName;
+ ::osl::Security aSecurity;
+ aSecurity.getUserName( aUserName );
+ aUser = aUserName;
+ }
+ if ( aUser.isEmpty() )
+ {
+ // unknown user name
+ aUser = m_aStrUnknownUser;
+ }
+ aUser += " " + m_aStrExclusiveAccess;
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
+
+ util::DateTime uDT(xDocProps->getModificationDate());
+ DateTime aDateTime(uDT);
+
+ OUString aString = formatDateTime(aDateTime, ScGlobal::getLocaleData(), false) + " " +
+ ScGlobal::getLocaleData().getTime( aDateTime, false );
+
+ m_xLbUsers->append_text(aUser);
+ m_xLbUsers->set_text(m_xLbUsers->n_children() - 1, aString, 1);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/shtabdlg.cxx b/sc/source/ui/miscdlgs/shtabdlg.cxx
new file mode 100644
index 000000000..cf0c10918
--- /dev/null
+++ b/sc/source/ui/miscdlgs/shtabdlg.cxx
@@ -0,0 +1,66 @@
+/* -*- 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 <shtabdlg.hxx>
+
+ScShowTabDlg::ScShowTabDlg(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/showsheetdialog.ui", "ShowSheetDialog")
+ , m_xFrame(m_xBuilder->weld_frame("frame"))
+ , m_xLb(m_xBuilder->weld_tree_view("treeview"))
+{
+ m_xLb->set_selection_mode(SelectionMode::Multiple);
+ m_xLb->set_size_request(-1, m_xLb->get_height_rows(10));
+ m_xLb->connect_row_activated(LINK(this, ScShowTabDlg, DblClkHdl));
+}
+
+ScShowTabDlg::~ScShowTabDlg() {}
+
+void ScShowTabDlg::SetDescription(const OUString& rTitle, const OUString& rFixedText,
+ const OString& rDlgHelpId, const OString& sLbHelpId)
+{
+ m_xDialog->set_title(rTitle);
+ m_xFrame->set_label(rFixedText);
+ m_xDialog->set_help_id(rDlgHelpId);
+ m_xLb->set_help_id(sLbHelpId);
+}
+
+void ScShowTabDlg::Insert(const OUString& rString, bool bSelected)
+{
+ m_xLb->append_text(rString);
+ if (bSelected)
+ m_xLb->select(m_xLb->n_children() - 1);
+}
+
+std::vector<sal_Int32> ScShowTabDlg::GetSelectedRows() const
+{
+ auto aTmp = m_xLb->get_selected_rows();
+ return std::vector<sal_Int32>(aTmp.begin(), aTmp.end());
+}
+
+OUString ScShowTabDlg::GetEntry(sal_Int32 nIndex) const { return m_xLb->get_text(nIndex); }
+
+IMPL_LINK_NOARG(ScShowTabDlg, DblClkHdl, weld::TreeView&, bool)
+{
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/simpref.cxx b/sc/source/ui/miscdlgs/simpref.cxx
new file mode 100644
index 000000000..27e8e3bb6
--- /dev/null
+++ b/sc/source/ui/miscdlgs/simpref.cxx
@@ -0,0 +1,190 @@
+/* -*- 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 <reffact.hxx>
+#include <document.hxx>
+#include <simpref.hxx>
+
+ScSimpleRefDlg::ScSimpleRefDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent)
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/simplerefdialog.ui", "SimpleRefDialog")
+ , bAutoReOpen(true)
+ , bCloseOnButtonUp(false)
+ , bSingleCell(false)
+ , bMultiSelection(false)
+ , m_xFtAssign(m_xBuilder->weld_label("area"))
+ , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry("assign")))
+ , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button("assignref")))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+{
+ m_xEdAssign->SetReferences(this, m_xFtAssign.get());
+ m_xRbAssign->SetReferences(this, m_xEdAssign.get());
+
+ // in order to keep the Strings with the FixedTexts in the resource:
+ Init();
+ SetDispatcherLock( true ); // activate modal mode
+}
+
+ScSimpleRefDlg::~ScSimpleRefDlg()
+{
+ SetDispatcherLock( false ); // deactivate modal mode
+}
+
+void ScSimpleRefDlg::FillInfo(SfxChildWinInfo& rWinInfo) const
+{
+ ScAnyRefDlgController::FillInfo(rWinInfo);
+ rWinInfo.bVisible = bAutoReOpen;
+}
+
+void ScSimpleRefDlg::SetRefString(const OUString &rStr)
+{
+ m_xEdAssign->SetText(rStr);
+}
+
+void ScSimpleRefDlg::Init()
+{
+ m_xBtnOk->connect_clicked( LINK( this, ScSimpleRefDlg, OkBtnHdl ) );
+ m_xBtnCancel->connect_clicked( LINK( this, ScSimpleRefDlg, CancelBtnHdl ) );
+ bCloseFlag=false;
+}
+
+// Set the reference to a cell range selected with the mouse. This is then
+// shown as the new selection in the reference field.
+void ScSimpleRefDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if (!m_xEdAssign->GetWidget()->get_sensitive())
+ return;
+
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(m_xEdAssign.get());
+
+ theCurArea = rRef;
+ OUString aRefStr;
+ if ( bSingleCell )
+ {
+ ScAddress aAdr = rRef.aStart;
+ aRefStr = aAdr.Format(ScRefFlags::ADDR_ABS_3D, &rDocP, rDocP.GetAddressConvention());
+ }
+ else
+ aRefStr = theCurArea.Format(rDocP, ScRefFlags::RANGE_ABS_3D, rDocP.GetAddressConvention());
+
+ if ( bMultiSelection )
+ {
+ OUString aVal = m_xEdAssign->GetText();
+ Selection aSel = m_xEdAssign->GetSelection();
+ aSel.Justify();
+ aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aRefStr );
+ Selection aNewSel( aSel.Min(), aSel.Min()+aRefStr.getLength() );
+ m_xEdAssign->SetRefString( aVal );
+ m_xEdAssign->SetSelection( aNewSel );
+ }
+ else
+ m_xEdAssign->SetRefString( aRefStr );
+
+ aChangeHdl.Call( aRefStr );
+}
+
+void ScSimpleRefDlg::Close()
+{
+ CancelBtnHdl(*m_xBtnCancel);
+}
+
+void ScSimpleRefDlg::SetActive()
+{
+ m_xEdAssign->GrabFocus();
+
+ // no NameModifyHdl. Otherwise ranges could not be altered
+ // (after marking the reference, the old field content would be shown)
+ // (also, the selected DB name has also not been altered)
+
+ RefInputDone();
+}
+
+bool ScSimpleRefDlg::IsRefInputMode() const
+{
+ return true;
+}
+
+void ScSimpleRefDlg::SetCloseHdl( const Link<const OUString*,void>& rLink )
+{
+ aCloseHdl=rLink;
+}
+
+void ScSimpleRefDlg::SetUnoLinks( const Link<const OUString&,void>& rDone,
+ const Link<const OUString&,void>& rAbort,
+ const Link<const OUString&,void>& rChange )
+{
+ aDoneHdl = rDone;
+ aAbortedHdl = rAbort;
+ aChangeHdl = rChange;
+}
+
+void ScSimpleRefDlg::SetFlags( bool bSetCloseOnButtonUp, bool bSetSingleCell, bool bSetMultiSelection )
+{
+ bCloseOnButtonUp = bSetCloseOnButtonUp;
+ bSingleCell = bSetSingleCell;
+ bMultiSelection = bSetMultiSelection;
+}
+
+void ScSimpleRefDlg::StartRefInput()
+{
+ if ( bMultiSelection )
+ {
+ // initially select the whole string, so it gets replaced by default
+ m_xEdAssign->SelectAll();
+ }
+
+ m_xRbAssign->DoRef();
+ bCloseFlag = true;
+}
+
+void ScSimpleRefDlg::RefInputDone( bool bForced)
+{
+ ScAnyRefDlgController::RefInputDone(bForced);
+ if ( (bForced || bCloseOnButtonUp) && bCloseFlag )
+ OkBtnHdl(*m_xBtnOk);
+}
+
+// Handler:
+
+IMPL_LINK_NOARG(ScSimpleRefDlg, OkBtnHdl, weld::Button&, void)
+{
+ if (IsClosing())
+ return;
+ bAutoReOpen = false;
+ OUString aResult=m_xEdAssign->GetText();
+ aCloseHdl.Call(&aResult);
+ Link<const OUString&,void> aUnoLink = aDoneHdl; // stack var because this is deleted in DoClose
+ DoClose( ScSimpleRefDlgWrapper::GetChildWindowId() );
+ aUnoLink.Call( aResult );
+}
+
+IMPL_LINK_NOARG(ScSimpleRefDlg, CancelBtnHdl, weld::Button&, void)
+{
+ if (IsClosing())
+ return;
+ bAutoReOpen = false;
+ OUString aResult=m_xEdAssign->GetText();
+ aCloseHdl.Call(nullptr);
+ Link<const OUString&,void> aUnoLink = aAbortedHdl; // stack var because this is deleted in DoClose
+ DoClose( ScSimpleRefDlgWrapper::GetChildWindowId() );
+ aUnoLink.Call( aResult );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/solveroptions.cxx b/sc/source/ui/miscdlgs/solveroptions.cxx
new file mode 100644
index 000000000..41603b6d5
--- /dev/null
+++ b/sc/source/ui/miscdlgs/solveroptions.cxx
@@ -0,0 +1,415 @@
+/* -*- 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 <solveroptions.hxx>
+#include <global.hxx>
+#include <miscuno.hxx>
+#include <solverutil.hxx>
+
+#include <rtl/math.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+
+#include <com/sun/star/sheet/XSolver.hpp>
+#include <com/sun/star/sheet/XSolverDescription.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+using namespace com::sun::star;
+
+namespace {
+
+/// Helper for sorting properties
+struct ScSolverOptionsEntry
+{
+ sal_Int32 nPosition;
+ OUString aDescription;
+
+ ScSolverOptionsEntry() : nPosition(0) {}
+
+ bool operator< (const ScSolverOptionsEntry& rOther) const
+ {
+ return (ScGlobal::GetCollator().compareString( aDescription, rOther.aDescription ) < 0);
+ }
+};
+
+}
+
+ScSolverOptionsDialog::ScSolverOptionsDialog(weld::Window* pParent,
+ const uno::Sequence<OUString>& rImplNames,
+ const uno::Sequence<OUString>& rDescriptions,
+ const OUString& rEngine,
+ const uno::Sequence<beans::PropertyValue>& rProperties )
+ : GenericDialogController(pParent, "modules/scalc/ui/solveroptionsdialog.ui", "SolverOptionsDialog")
+ , maImplNames(rImplNames)
+ , maEngine(rEngine)
+ , maProperties(rProperties)
+ , m_xLbEngine(m_xBuilder->weld_combo_box("engine"))
+ , m_xLbSettings(m_xBuilder->weld_tree_view("settings"))
+ , m_xBtnEdit(m_xBuilder->weld_button("edit"))
+{
+ m_xLbSettings->set_size_request(m_xLbSettings->get_approximate_digit_width() * 32,
+ m_xLbSettings->get_height_rows(6));
+
+ m_xLbSettings->enable_toggle_buttons(weld::ColumnToggleType::Check);
+
+ m_xLbEngine->connect_changed( LINK( this, ScSolverOptionsDialog, EngineSelectHdl ) );
+
+ m_xBtnEdit->connect_clicked( LINK( this, ScSolverOptionsDialog, ButtonHdl ) );
+
+ m_xLbSettings->connect_changed( LINK( this, ScSolverOptionsDialog, SettingsSelHdl ) );
+ m_xLbSettings->connect_row_activated( LINK( this, ScSolverOptionsDialog, SettingsDoubleClickHdl ) );
+
+ sal_Int32 nSelect = -1;
+ sal_Int32 nImplCount = maImplNames.getLength();
+ for (sal_Int32 nImpl=0; nImpl<nImplCount; ++nImpl)
+ {
+ OUString aImplName( maImplNames[nImpl] );
+ OUString aDescription( rDescriptions[nImpl] ); // user-visible descriptions in list box
+ m_xLbEngine->append_text(aDescription);
+ if ( aImplName == maEngine )
+ nSelect = nImpl;
+ }
+ if ( nSelect < 0 ) // no (valid) engine given
+ {
+ if ( nImplCount > 0 )
+ {
+ maEngine = maImplNames[0]; // use first implementation
+ nSelect = 0;
+ }
+ else
+ maEngine.clear();
+ maProperties.realloc(0); // don't use options from different engine
+ }
+ if ( nSelect >= 0 ) // select in list box
+ m_xLbEngine->set_active(nSelect);
+
+ if ( !maProperties.hasElements() )
+ ReadFromComponent(); // fill maProperties from component (using maEngine)
+ FillListBox(); // using maProperties
+}
+
+ScSolverOptionsDialog::~ScSolverOptionsDialog()
+{
+ if (m_xIntDialog)
+ m_xIntDialog->response(RET_CANCEL);
+ assert(!m_xIntDialog);
+ if (m_xValDialog)
+ m_xValDialog->response(RET_CANCEL);
+ assert(!m_xValDialog);
+}
+
+const uno::Sequence<beans::PropertyValue>& ScSolverOptionsDialog::GetProperties()
+{
+ // update maProperties from list box content
+ // order of entries in list box and maProperties is the same
+ sal_Int32 nEntryCount = maProperties.getLength();
+ if (nEntryCount == m_xLbSettings->n_children())
+ {
+ auto maPropertiesRange = asNonConstRange(maProperties);
+ for (sal_Int32 nEntryPos=0; nEntryPos<nEntryCount; ++nEntryPos)
+ {
+ uno::Any& rValue = maPropertiesRange[nEntryPos].Value;
+ if (ScSolverOptionsString* pStringItem = weld::fromId<ScSolverOptionsString*>(m_xLbSettings->get_id(nEntryPos)))
+ {
+ if (pStringItem->IsDouble())
+ rValue <<= pStringItem->GetDoubleValue();
+ else
+ rValue <<= pStringItem->GetIntValue();
+ }
+ else
+ rValue <<= m_xLbSettings->get_toggle(nEntryPos) == TRISTATE_TRUE;
+ }
+ }
+ else
+ {
+ OSL_FAIL( "wrong count" );
+ }
+
+ return maProperties;
+}
+
+void ScSolverOptionsDialog::FillListBox()
+{
+ // get property descriptions, sort by them
+
+ uno::Reference<sheet::XSolverDescription> xDesc( ScSolverUtil::GetSolver( maEngine ), uno::UNO_QUERY );
+ sal_Int32 nCount = maProperties.getLength();
+ std::vector<ScSolverOptionsEntry> aDescriptions( nCount );
+ for (sal_Int32 nPos=0; nPos<nCount; nPos++)
+ {
+ OUString aPropName( maProperties[nPos].Name );
+ OUString aVisName;
+ if ( xDesc.is() )
+ aVisName = xDesc->getPropertyDescription( aPropName );
+ if ( aVisName.isEmpty() )
+ aVisName = aPropName;
+ aDescriptions[nPos].nPosition = nPos;
+ aDescriptions[nPos].aDescription = aVisName;
+ }
+ std::sort( aDescriptions.begin(), aDescriptions.end() );
+
+ // also update maProperties to the order of descriptions
+
+ uno::Sequence<beans::PropertyValue> aNewSeq;
+ aNewSeq.realloc( nCount );
+ std::transform(aDescriptions.begin(), aDescriptions.end(), aNewSeq.getArray(),
+ [this](const ScSolverOptionsEntry& rDescr) -> beans::PropertyValue { return maProperties[ rDescr.nPosition ]; });
+ maProperties = aNewSeq;
+
+ // fill the list box
+
+ m_xLbSettings->freeze();
+ m_xLbSettings->clear();
+
+ for (sal_Int32 nPos=0; nPos<nCount; nPos++)
+ {
+ OUString aVisName = aDescriptions[nPos].aDescription;
+
+ uno::Any aValue = maProperties[nPos].Value;
+ uno::TypeClass eClass = aValue.getValueTypeClass();
+
+ m_xLbSettings->append();
+
+ if ( eClass == uno::TypeClass_BOOLEAN )
+ {
+ // check box entry
+ m_xLbSettings->set_toggle(nPos, ScUnoHelpFunctions::GetBoolFromAny(aValue) ? TRISTATE_TRUE : TRISTATE_FALSE);
+ m_xLbSettings->set_text(nPos, aVisName, 0);
+ }
+ else
+ {
+ // value entry
+ m_xLbSettings->set_text(nPos, aVisName, 0);
+ m_aOptions.emplace_back(new ScSolverOptionsString(aVisName));
+ if (eClass == uno::TypeClass_DOUBLE)
+ {
+ double fDoubleValue = 0.0;
+ if (aValue >>= fDoubleValue)
+ m_aOptions.back()->SetDoubleValue(fDoubleValue);
+
+ OUString sTxt = aVisName + ": ";
+ sTxt += rtl::math::doubleToUString(fDoubleValue,
+ rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
+ ScGlobal::getLocaleData().getNumDecimalSep()[0], true );
+
+ m_xLbSettings->set_text(nPos, sTxt, 0);
+ }
+ else
+ {
+ sal_Int32 nIntValue = 0;
+ if (aValue >>= nIntValue)
+ m_aOptions.back()->SetIntValue(nIntValue);
+
+ OUString sTxt = aVisName + ": " + OUString::number(nIntValue);
+
+ m_xLbSettings->set_text(nPos, sTxt, 0);
+ }
+ m_xLbSettings->set_id(nPos, weld::toId(m_aOptions.back().get()));
+ }
+ }
+
+ m_xLbSettings->thaw();
+}
+
+void ScSolverOptionsDialog::ReadFromComponent()
+{
+ maProperties = ScSolverUtil::GetDefaults( maEngine );
+}
+
+void ScSolverOptionsDialog::EditOption()
+{
+ int nEntry = m_xLbSettings->get_selected_index();
+ if (nEntry == -1)
+ return;
+ ScSolverOptionsString* pStringItem = weld::fromId<ScSolverOptionsString*>(m_xLbSettings->get_id(nEntry));
+ if (!pStringItem)
+ return;
+
+ if (pStringItem->IsDouble())
+ {
+ m_xValDialog = std::make_shared<ScSolverValueDialog>(m_xDialog.get());
+ m_xValDialog->SetOptionName(pStringItem->GetText());
+ if (maProperties[nEntry].Name == "DECR")
+ m_xValDialog->SetMax(1.0);
+ else if (maProperties[nEntry].Name == "DEFactorMax")
+ m_xValDialog->SetMax(1.2);
+ else if (maProperties[nEntry].Name == "DEFactorMin")
+ m_xValDialog->SetMax(1.2);
+ else if (maProperties[nEntry].Name == "PSCL")
+ m_xValDialog->SetMax(0.005);
+ m_xValDialog->SetValue(pStringItem->GetDoubleValue());
+ weld::DialogController::runAsync(m_xValDialog, [nEntry, pStringItem, this](sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ pStringItem->SetDoubleValue(m_xValDialog->GetValue());
+
+ OUString sTxt(pStringItem->GetText() + ": ");
+ sTxt += rtl::math::doubleToUString(pStringItem->GetDoubleValue(),
+ rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
+ ScGlobal::getLocaleData().getNumDecimalSep()[0], true );
+
+ m_xLbSettings->set_text(nEntry, sTxt, 0);
+ }
+ m_xValDialog.reset();
+ });
+ }
+ else
+ {
+ m_xIntDialog = std::make_shared<ScSolverIntegerDialog>(m_xDialog.get());
+ m_xIntDialog->SetOptionName( pStringItem->GetText() );
+ if (maProperties[nEntry].Name == "EpsilonLevel")
+ m_xIntDialog->SetMax(3);
+ else if (maProperties[nEntry].Name == "Algorithm")
+ m_xIntDialog->SetMax(1);
+ m_xIntDialog->SetValue( pStringItem->GetIntValue() );
+ weld::DialogController::runAsync(m_xIntDialog, [nEntry, pStringItem, this](sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ pStringItem->SetIntValue(m_xIntDialog->GetValue());
+
+ OUString sTxt(
+ pStringItem->GetText() + ": " + OUString::number(pStringItem->GetIntValue()));
+
+ m_xLbSettings->set_text(nEntry, sTxt, 0);
+ }
+ m_xIntDialog.reset();
+ });
+ }
+}
+
+IMPL_LINK( ScSolverOptionsDialog, ButtonHdl, weld::Button&, rBtn, void )
+{
+ if (&rBtn == m_xBtnEdit.get())
+ EditOption();
+}
+
+IMPL_LINK_NOARG(ScSolverOptionsDialog, SettingsDoubleClickHdl, weld::TreeView&, bool)
+{
+ EditOption();
+ return true;
+}
+
+IMPL_LINK_NOARG(ScSolverOptionsDialog, EngineSelectHdl, weld::ComboBox&, void)
+{
+ const sal_Int32 nSelectPos = m_xLbEngine->get_active();
+ if ( nSelectPos < maImplNames.getLength() )
+ {
+ OUString aNewEngine( maImplNames[nSelectPos] );
+ if ( aNewEngine != maEngine )
+ {
+ maEngine = aNewEngine;
+ ReadFromComponent(); // fill maProperties from component (using maEngine)
+ FillListBox(); // using maProperties
+ }
+ }
+}
+
+IMPL_LINK_NOARG(ScSolverOptionsDialog, SettingsSelHdl, weld::TreeView&, void)
+{
+ bool bCheckbox = false;
+
+ int nEntry = m_xLbSettings->get_selected_index();
+ if (nEntry != -1)
+ {
+ ScSolverOptionsString* pStringItem = weld::fromId<ScSolverOptionsString*>(m_xLbSettings->get_id(nEntry));
+ if (!pStringItem)
+ bCheckbox = true;
+ }
+
+ m_xBtnEdit->set_sensitive(!bCheckbox);
+}
+
+ScSolverIntegerDialog::ScSolverIntegerDialog(weld::Window * pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/integerdialog.ui", "IntegerDialog")
+ , m_xFrame(m_xBuilder->weld_frame("frame"))
+ , m_xNfValue(m_xBuilder->weld_spin_button("value"))
+{
+}
+
+ScSolverIntegerDialog::~ScSolverIntegerDialog()
+{
+}
+
+void ScSolverIntegerDialog::SetOptionName( const OUString& rName )
+{
+ m_xFrame->set_label(rName);
+}
+
+void ScSolverIntegerDialog::SetValue( sal_Int32 nValue )
+{
+ m_xNfValue->set_value( nValue );
+}
+
+void ScSolverIntegerDialog::SetMax( sal_Int32 nMax )
+{
+ m_xNfValue->set_range(0, nMax);
+}
+
+sal_Int32 ScSolverIntegerDialog::GetValue() const
+{
+ return m_xNfValue->get_value();
+}
+
+ScSolverValueDialog::ScSolverValueDialog(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/doubledialog.ui", "DoubleDialog")
+ , m_xFrame(m_xBuilder->weld_frame("frame"))
+ , m_xEdValue(m_xBuilder->weld_entry("value"))
+ , m_fMaxValue(std::numeric_limits<double>::quiet_NaN())
+{
+}
+
+ScSolverValueDialog::~ScSolverValueDialog()
+{
+}
+
+void ScSolverValueDialog::SetOptionName( const OUString& rName )
+{
+ m_xFrame->set_label(rName);
+}
+
+void ScSolverValueDialog::SetValue( double fValue )
+{
+ m_xEdValue->set_text( rtl::math::doubleToUString( fValue,
+ rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
+ ScGlobal::getLocaleData().getNumDecimalSep()[0], true ) );
+}
+
+void ScSolverValueDialog::SetMax(double fMax)
+{
+ m_fMaxValue = fMax;
+}
+
+double ScSolverValueDialog::GetValue() const
+{
+ OUString aInput = m_xEdValue->get_text();
+
+ rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
+ sal_Int32 nParseEnd = 0;
+ double fValue = ScGlobal::getLocaleData().stringToDouble( aInput, true, &eStatus, &nParseEnd);
+ /* TODO: shouldn't there be some error checking? */
+ if (!std::isnan(m_fMaxValue) && fValue > m_fMaxValue)
+ fValue = m_fMaxValue;
+ return fValue;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/solverutil.cxx b/sc/source/ui/miscdlgs/solverutil.cxx
new file mode 100644
index 000000000..6ba270786
--- /dev/null
+++ b/sc/source/ui/miscdlgs/solverutil.cxx
@@ -0,0 +1,175 @@
+/* -*- 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 <solverutil.hxx>
+
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/sheet/XSolver.hpp>
+#include <com/sun/star/sheet/XSolverDescription.hpp>
+
+#include <osl/diagnose.h>
+#include <comphelper/processfactory.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace com::sun::star;
+
+constexpr OUStringLiteral SCSOLVER_SERVICE = u"com.sun.star.sheet.Solver";
+
+void ScSolverUtil::GetImplementations( uno::Sequence<OUString>& rImplNames,
+ uno::Sequence<OUString>& rDescriptions )
+{
+ rImplNames.realloc(0); // clear
+ rDescriptions.realloc(0);
+
+ uno::Reference<uno::XComponentContext> xCtx(
+ comphelper::getProcessComponentContext() );
+
+ uno::Reference<container::XContentEnumerationAccess> xEnAc(
+ xCtx->getServiceManager(), uno::UNO_QUERY );
+ if ( !xEnAc.is() )
+ return;
+
+ uno::Reference<container::XEnumeration> xEnum =
+ xEnAc->createContentEnumeration( SCSOLVER_SERVICE );
+ if ( !xEnum.is() )
+ return;
+
+ sal_Int32 nCount = 0;
+ while ( xEnum->hasMoreElements() )
+ {
+ uno::Any aAny = xEnum->nextElement();
+ uno::Reference<lang::XServiceInfo> xInfo;
+ aAny >>= xInfo;
+ if ( xInfo.is() )
+ {
+ uno::Reference<lang::XSingleComponentFactory> xCFac( xInfo, uno::UNO_QUERY );
+ if ( xCFac.is() )
+ {
+ OUString sName = xInfo->getImplementationName();
+
+ try
+ {
+ uno::Reference<sheet::XSolver> xSolver(
+ xCFac->createInstanceWithContext(xCtx), uno::UNO_QUERY );
+ uno::Reference<sheet::XSolverDescription> xDesc( xSolver, uno::UNO_QUERY );
+ OUString sDescription;
+ if ( xDesc.is() )
+ sDescription = xDesc->getComponentDescription();
+
+ if ( sDescription.isEmpty() )
+ sDescription = sName; // use implementation name if no description available
+
+ rImplNames.realloc( nCount+1 );
+ rImplNames.getArray()[nCount] = sName;
+ rDescriptions.realloc( nCount+1 );
+ rDescriptions.getArray()[nCount] = sDescription;
+ ++nCount;
+ }
+ catch (const css::uno::Exception&)
+ {
+ TOOLS_INFO_EXCEPTION("sc.ui", "ScSolverUtil::GetImplementations: cannot instantiate: " << sName);
+ }
+ }
+ }
+ }
+}
+
+uno::Reference<sheet::XSolver> ScSolverUtil::GetSolver( std::u16string_view rImplName )
+{
+ uno::Reference<sheet::XSolver> xSolver;
+
+ uno::Reference<uno::XComponentContext> xCtx(
+ comphelper::getProcessComponentContext() );
+
+ uno::Reference<container::XContentEnumerationAccess> xEnAc(
+ xCtx->getServiceManager(), uno::UNO_QUERY );
+ if ( xEnAc.is() )
+ {
+ uno::Reference<container::XEnumeration> xEnum =
+ xEnAc->createContentEnumeration( SCSOLVER_SERVICE );
+ if ( xEnum.is() )
+ {
+ while ( xEnum->hasMoreElements() && !xSolver.is() )
+ {
+ uno::Any aAny = xEnum->nextElement();
+ uno::Reference<lang::XServiceInfo> xInfo;
+ aAny >>= xInfo;
+ if ( xInfo.is() )
+ {
+ uno::Reference<lang::XSingleComponentFactory> xCFac( xInfo, uno::UNO_QUERY );
+ if ( xCFac.is() )
+ {
+ OUString sName = xInfo->getImplementationName();
+ if ( sName == rImplName )
+ xSolver.set( xCFac->createInstanceWithContext(xCtx), uno::UNO_QUERY );
+ }
+ }
+ }
+ }
+ }
+
+ SAL_WARN_IF( !xSolver.is(), "sc.ui", "can't get solver" );
+ return xSolver;
+}
+
+uno::Sequence<beans::PropertyValue> ScSolverUtil::GetDefaults( std::u16string_view rImplName )
+{
+ uno::Sequence<beans::PropertyValue> aDefaults;
+
+ uno::Reference<sheet::XSolver> xSolver = GetSolver( rImplName );
+ uno::Reference<beans::XPropertySet> xPropSet( xSolver, uno::UNO_QUERY );
+ if ( !xPropSet.is() )
+ {
+ // no XPropertySet - no options
+ return aDefaults;
+ }
+
+ // fill maProperties
+
+ uno::Reference<beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
+ OSL_ENSURE( xInfo.is(), "can't get property set info" );
+ if ( !xInfo.is() )
+ return aDefaults;
+
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ const sal_Int32 nSize = aPropSeq.getLength();
+ aDefaults.realloc(nSize);
+ auto pDefaults = aDefaults.getArray();
+ sal_Int32 nValid = 0;
+ for (const beans::Property& rProp : aPropSeq)
+ {
+ uno::Any aValue = xPropSet->getPropertyValue( rProp.Name );
+ uno::TypeClass eClass = aValue.getValueTypeClass();
+ // only use properties of supported types
+ if ( eClass == uno::TypeClass_BOOLEAN || eClass == uno::TypeClass_LONG || eClass == uno::TypeClass_DOUBLE )
+ pDefaults[nValid++] = beans::PropertyValue( rProp.Name, -1, aValue, beans::PropertyState_DIRECT_VALUE );
+ }
+ aDefaults.realloc(nValid);
+
+ //! get user-visible names, sort by them
+
+ return aDefaults;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/solvrdlg.cxx b/sc/source/ui/miscdlgs/solvrdlg.cxx
new file mode 100644
index 000000000..f7cd8e27b
--- /dev/null
+++ b/sc/source/ui/miscdlgs/solvrdlg.cxx
@@ -0,0 +1,282 @@
+/* -*- 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 <scitems.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svl/numformat.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+#include <uiitems.hxx>
+#include <reffact.hxx>
+#include <document.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <sc.hrc>
+#include <solvrdlg.hxx>
+
+ScSolverDlg::ScSolverDlg( SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ ScDocument* pDocument,
+ const ScAddress& aCursorPos )
+
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/goalseekdlg.ui", "GoalSeekDialog")
+ , theFormulaCell(aCursorPos)
+ , theVariableCell(aCursorPos)
+ , pDoc(pDocument)
+ , nCurTab(aCursorPos.Tab())
+ , bDlgLostFocus(false)
+ , errMsgInvalidVar(ScResId(STR_INVALIDVAR))
+ , errMsgInvalidForm(ScResId(STR_INVALIDFORM))
+ , errMsgNoFormula(ScResId(STR_NOFORMULA))
+ , errMsgInvalidVal(ScResId(STR_INVALIDVAL))
+ , m_pEdActive(nullptr)
+ , m_xFtFormulaCell(m_xBuilder->weld_label("formulatext"))
+ , m_xEdFormulaCell(new formula::RefEdit(m_xBuilder->weld_entry("formulaedit")))
+ , m_xRBFormulaCell(new formula::RefButton(m_xBuilder->weld_button("formulabutton")))
+ , m_xEdTargetVal(m_xBuilder->weld_entry("target"))
+ , m_xFtVariableCell(m_xBuilder->weld_label("vartext"))
+ , m_xEdVariableCell(new formula::RefEdit(m_xBuilder->weld_entry("varedit")))
+ , m_xRBVariableCell(new formula::RefButton(m_xBuilder->weld_button("varbutton")))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+{
+ m_xEdFormulaCell->SetReferences(this, m_xFtFormulaCell.get());
+ m_xRBFormulaCell->SetReferences(this, m_xEdFormulaCell.get());
+ m_xEdVariableCell->SetReferences(this, m_xFtVariableCell.get());
+ m_xRBVariableCell->SetReferences(this, m_xEdVariableCell.get());
+ Init();
+}
+
+ScSolverDlg::~ScSolverDlg()
+{
+ if (m_xMessageBox)
+ m_xMessageBox->response(RET_CANCEL);
+ assert(!m_xMessageBox);
+}
+
+void ScSolverDlg::Init()
+{
+ m_xBtnOk->connect_clicked( LINK( this, ScSolverDlg, BtnHdl ) );
+ m_xBtnCancel->connect_clicked( LINK( this, ScSolverDlg, BtnHdl ) );
+
+ Link<formula::RefEdit&,void> aEditLink = LINK( this, ScSolverDlg, GetEditFocusHdl );
+ m_xEdFormulaCell->SetGetFocusHdl( aEditLink );
+ m_xEdVariableCell->SetGetFocusHdl( aEditLink );
+
+ Link<formula::RefButton&,void> aButtonLink = LINK( this, ScSolverDlg, GetButtonFocusHdl );
+ m_xRBFormulaCell->SetGetFocusHdl( aButtonLink );
+ m_xRBVariableCell->SetGetFocusHdl( aButtonLink );
+
+ m_xEdTargetVal->connect_focus_in(LINK(this, ScSolverDlg, GetFocusHdl));
+
+ aEditLink = LINK( this, ScSolverDlg, LoseEditFocusHdl );
+ m_xEdFormulaCell->SetLoseFocusHdl ( aEditLink );
+ m_xEdVariableCell->SetLoseFocusHdl ( aEditLink );
+
+ aButtonLink = LINK( this, ScSolverDlg, LoseButtonFocusHdl );
+ m_xRBFormulaCell->SetLoseFocusHdl ( aButtonLink );
+ m_xRBVariableCell->SetLoseFocusHdl ( aButtonLink );
+
+ OUString aStr(theFormulaCell.Format(ScRefFlags::ADDR_ABS, nullptr, pDoc->GetAddressConvention()));
+
+ m_xEdFormulaCell->SetText( aStr );
+ m_xEdFormulaCell->GrabFocus();
+ m_pEdActive = m_xEdFormulaCell.get();
+}
+
+void ScSolverDlg::Close()
+{
+ DoClose( ScSolverDlgWrapper::GetChildWindowId() );
+}
+
+void ScSolverDlg::SetActive()
+{
+ if ( bDlgLostFocus )
+ {
+ bDlgLostFocus = false;
+ if( m_pEdActive )
+ m_pEdActive->GrabFocus();
+ }
+ else
+ {
+ m_xDialog->grab_focus();
+ }
+ RefInputDone();
+}
+
+void ScSolverDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if( !m_pEdActive )
+ return;
+
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(m_pEdActive);
+
+ ScAddress aAdr = rRef.aStart;
+ ScRefFlags nFmt = ( aAdr.Tab() == nCurTab )
+ ? ScRefFlags::ADDR_ABS
+ : ScRefFlags::ADDR_ABS_3D;
+
+ OUString aStr(aAdr.Format(nFmt, &rDocP, rDocP.GetAddressConvention()));
+ m_pEdActive->SetRefString( aStr );
+
+ if (m_pEdActive == m_xEdFormulaCell.get())
+ theFormulaCell = aAdr;
+ else if (m_pEdActive == m_xEdVariableCell.get())
+ theVariableCell = aAdr;
+}
+
+void ScSolverDlg::RaiseError( ScSolverErr eError )
+{
+ OUString sMessage;
+
+ switch (eError)
+ {
+ case SOLVERR_NOFORMULA:
+ sMessage = errMsgNoFormula;
+ break;
+ case SOLVERR_INVALID_FORMULA:
+ sMessage = errMsgInvalidForm;
+ break;
+ case SOLVERR_INVALID_VARIABLE:
+ sMessage = errMsgInvalidVar;
+ break;
+ case SOLVERR_INVALID_TARGETVALUE:
+ sMessage = errMsgInvalidVal;
+ break;
+ }
+
+ m_xMessageBox.reset(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sMessage));
+ m_xMessageBox->runAsync(m_xMessageBox, [this](sal_Int32 /*nResult*/) {
+ m_xEdTargetVal->grab_focus();
+ m_xMessageBox.reset();
+ });
+}
+
+bool ScSolverDlg::IsRefInputMode() const
+{
+ return m_pEdActive != nullptr;
+}
+
+bool ScSolverDlg::CheckTargetValue( const OUString& rStrVal )
+{
+ sal_uInt32 n1 = 0;
+ double n2;
+
+ return pDoc->GetFormatTable()->IsNumberFormat( rStrVal, n1, n2 );
+}
+
+// Handler:
+
+IMPL_LINK(ScSolverDlg, BtnHdl, weld::Button&, rBtn, void)
+{
+ if (&rBtn == m_xBtnOk.get())
+ {
+ theTargetValStr = m_xEdTargetVal->get_text();
+
+ // The following code checks:
+ // 1. do the strings contain correct references / defined names?
+ // 2. does the formula coordinate refer to a cell containing a formula?
+ // 3. has a valid target value been entered?
+
+ const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
+ ScRefFlags nRes1 = theFormulaCell .Parse( m_xEdFormulaCell->GetText(), *pDoc, eConv );
+ ScRefFlags nRes2 = theVariableCell.Parse( m_xEdVariableCell->GetText(), *pDoc, eConv );
+
+ if ( (nRes1 & ScRefFlags::VALID) == ScRefFlags::VALID )
+ {
+ if ( (nRes2 & ScRefFlags::VALID) == ScRefFlags::VALID )
+ {
+ if ( CheckTargetValue( theTargetValStr ) )
+ {
+ CellType eType = pDoc->GetCellType( theFormulaCell.Col(),
+ theFormulaCell.Row(),
+ theFormulaCell.Tab());
+
+ if ( CELLTYPE_FORMULA == eType )
+ {
+ ScSolveParam aOutParam( theFormulaCell,
+ theVariableCell,
+ theTargetValStr );
+ ScSolveItem aOutItem( SCITEM_SOLVEDATA, &aOutParam );
+
+ SetDispatcherLock( false );
+
+ SwitchToDocument();
+ GetBindings().GetDispatcher()->ExecuteList(SID_SOLVE,
+ SfxCallMode::SLOT | SfxCallMode::RECORD,
+ { &aOutItem });
+ response(RET_OK);
+ }
+ else RaiseError( SOLVERR_NOFORMULA );
+ }
+ else RaiseError( SOLVERR_INVALID_TARGETVALUE );
+ }
+ else RaiseError( SOLVERR_INVALID_VARIABLE );
+ }
+ else RaiseError( SOLVERR_INVALID_FORMULA );
+ }
+ else if (&rBtn == m_xBtnCancel.get())
+ {
+ response(RET_CANCEL);
+ }
+}
+
+IMPL_LINK(ScSolverDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void)
+{
+ if (&rCtrl == m_xEdFormulaCell.get())
+ m_pEdActive = m_xEdFormulaCell.get();
+ else if (&rCtrl == m_xEdVariableCell.get())
+ m_pEdActive = m_xEdVariableCell.get();
+
+ if (m_pEdActive)
+ m_pEdActive->SelectAll();
+}
+
+IMPL_LINK_NOARG(ScSolverDlg, GetFocusHdl, weld::Widget&, void)
+{
+ m_pEdActive = nullptr;
+ m_xEdTargetVal->select_region(0, -1);
+}
+
+IMPL_LINK(ScSolverDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void)
+{
+ if (&rCtrl == m_xRBFormulaCell.get())
+ m_pEdActive = m_xEdFormulaCell.get();
+ else if (&rCtrl == m_xRBVariableCell.get())
+ m_pEdActive = m_xEdVariableCell.get();
+
+ if (m_pEdActive)
+ m_pEdActive->SelectAll();
+}
+
+IMPL_LINK_NOARG(ScSolverDlg, LoseEditFocusHdl, formula::RefEdit&, void)
+{
+ bDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(ScSolverDlg, LoseButtonFocusHdl, formula::RefButton&, void)
+{
+ bDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/strindlg.cxx b/sc/source/ui/miscdlgs/strindlg.cxx
new file mode 100644
index 000000000..61ba77534
--- /dev/null
+++ b/sc/source/ui/miscdlgs/strindlg.cxx
@@ -0,0 +1,42 @@
+/* -*- 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 <strindlg.hxx>
+
+ScStringInputDlg::ScStringInputDlg(weld::Window* pParent,
+ const OUString& rTitle,
+ const OUString& rEditTitle,
+ const OUString& rDefault,
+ const OString& rHelpId, const OString& rEditHelpId)
+ : GenericDialogController(pParent, "modules/scalc/ui/inputstringdialog.ui",
+ "InputStringDialog")
+ , m_xLabel(m_xBuilder->weld_label("description_label"))
+ , m_xEdInput(m_xBuilder->weld_entry("name_entry"))
+{
+ m_xLabel->set_label(rEditTitle);
+ m_xDialog->set_title(rTitle);
+ m_xDialog->set_help_id(rHelpId);
+ m_xEdInput->set_text(rDefault);
+ m_xEdInput->set_help_id(rEditHelpId);
+ m_xEdInput->select_region(0, -1);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/tabbgcolordlg.cxx b/sc/source/ui/miscdlgs/tabbgcolordlg.cxx
new file mode 100644
index 000000000..7a346a4e3
--- /dev/null
+++ b/sc/source/ui/miscdlgs/tabbgcolordlg.cxx
@@ -0,0 +1,141 @@
+/* -*- 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 <tabbgcolordlg.hxx>
+
+#include <tools/color.hxx>
+#include <vcl/event.hxx>
+
+#include <officecfg/Office/Common.hxx>
+
+ScTabBgColorDlg::ScTabBgColorDlg(weld::Window* pParent, const OUString& rTitle,
+ const OUString& rTabBgColorNoColorText, const Color& rDefaultColor)
+ : GenericDialogController(pParent, "modules/scalc/ui/tabcolordialog.ui", "TabColorDialog")
+ , m_aTabBgColor(rDefaultColor)
+ , m_xSelectPalette(m_xBuilder->weld_combo_box("paletteselector"))
+ , m_xTabBgColorSet(new ScTabBgColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin", true)))
+ , m_xTabBgColorSetWin(new weld::CustomWeld(*m_xBuilder, "colorset", *m_xTabBgColorSet))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+{
+ m_xTabBgColorSet->SetDialog(this);
+ m_xTabBgColorSet->SetColCount(SvxColorValueSet::getColumnCount());
+
+ m_xDialog->set_title(rTitle);
+
+ const WinBits nBits(m_xTabBgColorSet->GetStyle() | WB_NAMEFIELD | WB_ITEMBORDER | WB_NONEFIELD | WB_3DLOOK | WB_NO_DIRECTSELECT);
+ m_xTabBgColorSet->SetStyle(nBits);
+ m_xTabBgColorSet->SetText(rTabBgColorNoColorText);
+
+ const sal_uInt32 nColCount = SvxColorValueSet::getColumnCount();
+ const sal_uInt32 nRowCount(10);
+ const sal_uInt32 nLength = SvxColorValueSet::getEntryEdgeLength();
+ Size aSize(m_xTabBgColorSet->CalcWindowSizePixel(Size(nLength, nLength), nColCount, nRowCount));
+ m_xTabBgColorSetWin->set_size_request(aSize.Width() + 8, aSize.Height() + 8);
+
+ FillPaletteLB();
+
+ m_xSelectPalette->connect_changed(LINK(this, ScTabBgColorDlg, SelectPaletteLBHdl));
+ m_xTabBgColorSet->SetDoubleClickHdl(LINK(this, ScTabBgColorDlg, TabBgColorDblClickHdl_Impl));
+ m_xBtnOk->connect_clicked(LINK(this, ScTabBgColorDlg, TabBgColorOKHdl_Impl));
+}
+
+ScTabBgColorDlg::~ScTabBgColorDlg()
+{
+}
+
+void ScTabBgColorDlg::GetSelectedColor( Color& rColor ) const
+{
+ rColor = m_aTabBgColor;
+}
+
+void ScTabBgColorDlg::FillPaletteLB()
+{
+ m_xSelectPalette->clear();
+ std::vector<OUString> aPaletteList = m_aPaletteManager.GetPaletteList();
+ for (auto const& palette : aPaletteList)
+ {
+ m_xSelectPalette->append_text(palette);
+ }
+ OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() );
+ m_xSelectPalette->set_active_text(aPaletteName);
+ if (m_xSelectPalette->get_active() != -1)
+ {
+ SelectPaletteLBHdl(*m_xSelectPalette);
+ }
+}
+
+IMPL_LINK_NOARG(ScTabBgColorDlg, SelectPaletteLBHdl, weld::ComboBox&, void)
+{
+ m_xTabBgColorSet->Clear();
+ sal_Int32 nPos = m_xSelectPalette->get_active();
+ m_aPaletteManager.SetPalette( nPos );
+ m_aPaletteManager.ReloadColorSet(*m_xTabBgColorSet);
+ m_xTabBgColorSet->Resize();
+ m_xTabBgColorSet->SelectItem(0);
+}
+
+// Handler, called when color selection is changed
+IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorDblClickHdl_Impl, ValueSet*, void)
+{
+ sal_uInt16 nItemId = m_xTabBgColorSet->GetSelectedItemId();
+ Color aColor = nItemId ? ( m_xTabBgColorSet->GetItemColor( nItemId ) ) : COL_AUTO;
+ m_aTabBgColor = aColor;
+ m_xDialog->response(RET_OK);
+}
+
+// Handler, called when the OK button is pushed
+IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorOKHdl_Impl, weld::Button&, void)
+{
+ sal_uInt16 nItemId = m_xTabBgColorSet->GetSelectedItemId();
+ Color aColor = nItemId ? ( m_xTabBgColorSet->GetItemColor( nItemId ) ) : COL_AUTO;
+ m_aTabBgColor = aColor;
+ m_xDialog->response(RET_OK);
+}
+
+ScTabBgColorDlg::ScTabBgColorValueSet::ScTabBgColorValueSet(std::unique_ptr<weld::ScrolledWindow> pWindow)
+ : SvxColorValueSet(std::move(pWindow))
+ , m_pTabBgColorDlg(nullptr)
+{
+}
+
+ScTabBgColorDlg::ScTabBgColorValueSet::~ScTabBgColorValueSet()
+{
+}
+
+bool ScTabBgColorDlg::ScTabBgColorValueSet::KeyInput( const KeyEvent& rKEvt )
+{
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_SPACE:
+ case KEY_RETURN:
+ {
+ sal_uInt16 nItemId = GetSelectedItemId();
+ const Color& aColor = nItemId ? ( GetItemColor( nItemId ) ) : COL_AUTO;
+ m_pTabBgColorDlg->m_aTabBgColor = aColor;
+ m_pTabBgColorDlg->response(RET_OK);
+ return true;
+ }
+ break;
+ }
+ return SvxColorValueSet::KeyInput(rKEvt);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/tabopdlg.cxx b/sc/source/ui/miscdlgs/tabopdlg.cxx
new file mode 100644
index 000000000..7e9be6ea8
--- /dev/null
+++ b/sc/source/ui/miscdlgs/tabopdlg.cxx
@@ -0,0 +1,345 @@
+/* -*- 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 <sfx2/dispatch.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+#include <uiitems.hxx>
+#include <document.hxx>
+#include <scresid.hxx>
+#include <sc.hrc>
+#include <strings.hrc>
+#include <reffact.hxx>
+
+#include <tabopdlg.hxx>
+
+
+ScTabOpDlg::ScTabOpDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
+ ScDocument* pDocument,
+ const ScRefAddress& rCursorPos )
+ : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/multipleoperationsdialog.ui",
+ "MultipleOperationsDialog")
+ , theFormulaCell(rCursorPos)
+ , pDoc(pDocument)
+ , nCurTab(theFormulaCell.Tab())
+ , bDlgLostFocus(false)
+ , errMsgNoFormula(ScResId(STR_NOFORMULASPECIFIED))
+ , errMsgNoColRow(ScResId(STR_NOCOLROW))
+ , errMsgWrongFormula(ScResId(STR_WRONGFORMULA))
+ , errMsgWrongRowCol(ScResId(STR_WRONGROWCOL))
+ , errMsgNoColFormula(ScResId(STR_NOCOLFORMULA))
+ , errMsgNoRowFormula(ScResId(STR_NOROWFORMULA))
+ , m_pEdActive(nullptr)
+ , m_xFtFormulaRange(m_xBuilder->weld_label("formulasft"))
+ , m_xEdFormulaRange(new formula::RefEdit(m_xBuilder->weld_entry("formulas")))
+ , m_xRBFormulaRange(new formula::RefButton(m_xBuilder->weld_button("formulasref")))
+ , m_xFtRowCell(m_xBuilder->weld_label("rowft"))
+ , m_xEdRowCell(new formula::RefEdit(m_xBuilder->weld_entry("row")))
+ , m_xRBRowCell(new formula::RefButton(m_xBuilder->weld_button("rowref")))
+ , m_xFtColCell(m_xBuilder->weld_label("colft"))
+ , m_xEdColCell(new formula::RefEdit(m_xBuilder->weld_entry("col")))
+ , m_xRBColCell(new formula::RefButton(m_xBuilder->weld_button("colref")))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
+ , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
+{
+ m_xEdFormulaRange->SetReferences(this, m_xFtFormulaRange.get());
+ m_xRBFormulaRange->SetReferences(this, m_xEdFormulaRange.get());
+
+ m_xEdRowCell->SetReferences(this, m_xFtRowCell.get());
+ m_xRBRowCell->SetReferences(this, m_xEdRowCell.get());
+
+ m_xEdColCell->SetReferences(this, m_xFtColCell.get());
+ m_xRBColCell->SetReferences(this, m_xEdColCell.get());
+
+ Init();
+}
+
+ScTabOpDlg::~ScTabOpDlg()
+{
+}
+
+void ScTabOpDlg::Init()
+{
+ m_xBtnOk->connect_clicked( LINK( this, ScTabOpDlg, BtnHdl ) );
+ m_xBtnCancel->connect_clicked( LINK( this, ScTabOpDlg, BtnHdl ) );
+
+ Link<formula::RefEdit&,void> aEditLink = LINK( this, ScTabOpDlg, GetEditFocusHdl );
+ m_xEdFormulaRange->SetGetFocusHdl( aEditLink );
+ m_xEdRowCell->SetGetFocusHdl( aEditLink );
+ m_xEdColCell->SetGetFocusHdl( aEditLink );
+
+ Link<formula::RefButton&,void> aButtonLink = LINK( this, ScTabOpDlg, GetButtonFocusHdl );
+ m_xRBFormulaRange->SetGetFocusHdl( aButtonLink );
+ m_xRBRowCell->SetGetFocusHdl( aButtonLink );
+ m_xRBColCell->SetGetFocusHdl( aButtonLink );
+
+ aEditLink = LINK( this, ScTabOpDlg, LoseEditFocusHdl );
+ m_xEdFormulaRange->SetLoseFocusHdl( aEditLink );
+ m_xEdRowCell->SetLoseFocusHdl( aEditLink );
+ m_xEdColCell->SetLoseFocusHdl( aEditLink );
+
+ aButtonLink = LINK( this, ScTabOpDlg, LoseButtonFocusHdl );
+ m_xRBFormulaRange->SetLoseFocusHdl( aButtonLink );
+ m_xRBRowCell->SetLoseFocusHdl( aButtonLink );
+ m_xRBColCell->SetLoseFocusHdl( aButtonLink );
+
+ m_xEdFormulaRange->GrabFocus();
+ m_pEdActive = m_xEdFormulaRange.get();
+}
+
+void ScTabOpDlg::Close()
+{
+ DoClose( ScTabOpDlgWrapper::GetChildWindowId() );
+}
+
+void ScTabOpDlg::SetActive()
+{
+ if ( bDlgLostFocus )
+ {
+ bDlgLostFocus = false;
+ if (m_pEdActive)
+ m_pEdActive->GrabFocus();
+ }
+ else
+ m_xDialog->grab_focus();
+
+ RefInputDone();
+}
+
+void ScTabOpDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
+{
+ if (!m_pEdActive)
+ return;
+
+ ScAddress::Details aDetails(rDocP.GetAddressConvention(), 0, 0);
+
+ if ( rRef.aStart != rRef.aEnd )
+ RefInputStart(m_pEdActive);
+
+ OUString aStr;
+ ScRefFlags nFmt = ( rRef.aStart.Tab() == nCurTab )
+ ? ScRefFlags::RANGE_ABS
+ : ScRefFlags::RANGE_ABS_3D;
+
+ if (m_pEdActive == m_xEdFormulaRange.get())
+ {
+ theFormulaCell.Set( rRef.aStart, false, false, false);
+ theFormulaEnd.Set( rRef.aEnd, false, false, false);
+ aStr = rRef.Format(rDocP, nFmt, aDetails);
+ }
+ else if (m_pEdActive == m_xEdRowCell.get())
+ {
+ theRowCell.Set( rRef.aStart, false, false, false);
+ aStr = rRef.aStart.Format(nFmt, &rDocP, aDetails);
+ }
+ else if (m_pEdActive == m_xEdColCell.get())
+ {
+ theColCell.Set( rRef.aStart, false, false, false);
+ aStr = rRef.aStart.Format(nFmt, &rDocP, aDetails);
+ }
+
+ m_pEdActive->SetRefString( aStr );
+}
+
+void ScTabOpDlg::RaiseError( ScTabOpErr eError )
+{
+ const OUString* pMsg = &errMsgNoFormula;
+ formula::RefEdit* pEd = m_xEdFormulaRange.get();
+
+ switch ( eError )
+ {
+ case TABOPERR_NOFORMULA:
+ pMsg = &errMsgNoFormula;
+ pEd = m_xEdFormulaRange.get();
+ break;
+
+ case TABOPERR_NOCOLROW:
+ pMsg = &errMsgNoColRow;
+ pEd = m_xEdRowCell.get();
+ break;
+
+ case TABOPERR_WRONGFORMULA:
+ pMsg = &errMsgWrongFormula;
+ pEd = m_xEdFormulaRange.get();
+ break;
+
+ case TABOPERR_WRONGROW:
+ pMsg = &errMsgWrongRowCol;
+ pEd = m_xEdRowCell.get();
+ break;
+
+ case TABOPERR_NOCOLFORMULA:
+ pMsg = &errMsgNoColFormula;
+ pEd = m_xEdFormulaRange.get();
+ break;
+
+ case TABOPERR_WRONGCOL:
+ pMsg = &errMsgWrongRowCol;
+ pEd = m_xEdColCell.get();
+ break;
+
+ case TABOPERR_NOROWFORMULA:
+ pMsg = &errMsgNoRowFormula;
+ pEd = m_xEdFormulaRange.get();
+ break;
+ }
+
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Error, VclButtonsType::OkCancel, *pMsg));
+ xBox->run();
+ pEd->GrabFocus();
+}
+
+static bool lcl_Parse( const OUString& rString, const ScDocument& rDoc, SCTAB nCurTab,
+ ScRefAddress& rStart, ScRefAddress& rEnd )
+{
+ bool bRet = false;
+ const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
+ if ( rString.indexOf(':') != -1 )
+ bRet = ConvertDoubleRef( rDoc, rString, nCurTab, rStart, rEnd, eConv );
+ else
+ {
+ bRet = ConvertSingleRef( rDoc, rString, nCurTab, rStart, eConv );
+ rEnd = rStart;
+ }
+ return bRet;
+}
+
+// Handler:
+
+IMPL_LINK(ScTabOpDlg, BtnHdl, weld::Button&, rBtn, void)
+{
+ if (&rBtn == m_xBtnOk.get())
+ {
+ ScTabOpParam::Mode eMode = ScTabOpParam::Column;
+ sal_uInt16 nError = 0;
+
+ // The following code checks:
+ // 1. do the strings contain correct cell references / defined names?
+ // 2. is formula range row if row is empty or column if column is empty
+ // or single reference if both?
+ // 3. is at least one of row or column non-empty?
+
+ if (m_xEdFormulaRange->GetText().isEmpty())
+ nError = TABOPERR_NOFORMULA;
+ else if (m_xEdRowCell->GetText().isEmpty() &&
+ m_xEdColCell->GetText().isEmpty())
+ nError = TABOPERR_NOCOLROW;
+ else if ( !lcl_Parse( m_xEdFormulaRange->GetText(), *pDoc, nCurTab,
+ theFormulaCell, theFormulaEnd ) )
+ nError = TABOPERR_WRONGFORMULA;
+ else
+ {
+ const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
+ if (!m_xEdRowCell->GetText().isEmpty())
+ {
+ if (!ConvertSingleRef( *pDoc, m_xEdRowCell->GetText(), nCurTab,
+ theRowCell, eConv ))
+ nError = TABOPERR_WRONGROW;
+ else
+ {
+ if (m_xEdColCell->GetText().isEmpty() &&
+ theFormulaCell.Col() != theFormulaEnd.Col())
+ nError = TABOPERR_NOCOLFORMULA;
+ else
+ eMode = ScTabOpParam::Row;
+ }
+ }
+ if (!m_xEdColCell->GetText().isEmpty())
+ {
+ if (!ConvertSingleRef( *pDoc, m_xEdColCell->GetText(), nCurTab,
+ theColCell, eConv ))
+ nError = TABOPERR_WRONGCOL;
+ else
+ {
+ if (eMode == ScTabOpParam::Row) // both
+ {
+ eMode = ScTabOpParam::Both;
+ ConvertSingleRef( *pDoc, m_xEdFormulaRange->GetText(), nCurTab,
+ theFormulaCell, eConv );
+ }
+ else if (theFormulaCell.Row() != theFormulaEnd.Row())
+ nError = TABOPERR_NOROWFORMULA;
+ else
+ eMode = ScTabOpParam::Column;
+ }
+ }
+ }
+
+ if (nError)
+ RaiseError( static_cast<ScTabOpErr>(nError) );
+ else
+ {
+ ScTabOpParam aOutParam(theFormulaCell, theFormulaEnd, theRowCell, theColCell, eMode);
+ ScTabOpItem aOutItem( SID_TABOP, &aOutParam );
+
+ SetDispatcherLock( false );
+ SwitchToDocument();
+ GetBindings().GetDispatcher()->ExecuteList(SID_TABOP,
+ SfxCallMode::SLOT | SfxCallMode::RECORD,
+ { &aOutItem });
+ response(RET_OK);
+ }
+ }
+ else if (&rBtn == m_xBtnCancel.get())
+ response(RET_CANCEL);
+}
+
+IMPL_LINK( ScTabOpDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
+{
+ if (&rCtrl == m_xEdFormulaRange.get())
+ m_pEdActive = m_xEdFormulaRange.get();
+ else if (&rCtrl == m_xEdRowCell.get())
+ m_pEdActive = m_xEdRowCell.get();
+ else if (&rCtrl == m_xEdColCell.get())
+ m_pEdActive = m_xEdColCell.get();
+ else
+ m_pEdActive = nullptr;
+
+ if( m_pEdActive )
+ m_pEdActive->SelectAll();
+}
+
+IMPL_LINK( ScTabOpDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
+{
+ if (&rCtrl == m_xRBFormulaRange.get())
+ m_pEdActive = m_xEdFormulaRange.get();
+ else if (&rCtrl == m_xRBRowCell.get())
+ m_pEdActive = m_xEdRowCell.get();
+ else if (&rCtrl == m_xRBColCell.get())
+ m_pEdActive = m_xEdColCell.get();
+ else
+ m_pEdActive = nullptr;
+
+ if( m_pEdActive )
+ m_pEdActive->SelectAll();
+}
+
+IMPL_LINK_NOARG(ScTabOpDlg, LoseEditFocusHdl, formula::RefEdit&, void)
+{
+ bDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(ScTabOpDlg, LoseButtonFocusHdl, formula::RefButton&, void)
+{
+ bDlgLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/textdlgs.cxx b/sc/source/ui/miscdlgs/textdlgs.cxx
new file mode 100644
index 000000000..40a84a626
--- /dev/null
+++ b/sc/source/ui/miscdlgs/textdlgs.cxx
@@ -0,0 +1,94 @@
+/* -*- 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 <svx/svxids.hrc>
+#include <svx/dialogs.hrc>
+
+#include <editeng/flstitem.hxx>
+#include <sfx2/objsh.hxx>
+#include <svl/cjkoptions.hxx>
+
+#include <textdlgs.hxx>
+#include <svl/intitem.hxx>
+#include <svx/flagsdef.hxx>
+
+ScCharDlg::ScCharDlg(weld::Window* pParent, const SfxItemSet* pAttr, const SfxObjectShell* pDocShell, bool bDrawText)
+ : SfxTabDialogController(pParent, "modules/scalc/ui/chardialog.ui", "CharDialog", pAttr)
+ , rDocShell(*pDocShell)
+{
+ AddTabPage("font", RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("fonteffects", RID_SVXPAGE_CHAR_EFFECTS);
+ AddTabPage("position", RID_SVXPAGE_CHAR_POSITION);
+
+ if (bDrawText)
+ AddTabPage("background", RID_SVXPAGE_BKG);
+ else
+ RemoveTabPage("background");
+}
+
+void ScCharDlg::PageCreated(const OString& rId, SfxTabPage &rPage)
+{
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ if (rId == "font")
+ {
+ SvxFontListItem aItem(*static_cast<const SvxFontListItem*>(
+ ( rDocShell.GetItem( SID_ATTR_CHAR_FONTLIST) ) ) );
+
+ aSet.Put (SvxFontListItem( aItem.GetFontList(), SID_ATTR_CHAR_FONTLIST));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "fonteffects")
+ {
+ aSet.Put (SfxUInt16Item(SID_DISABLE_CTL,DISABLE_CASEMAP));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "background")
+ {
+ aSet.Put (SfxUInt32Item(SID_FLAG_TYPE, static_cast<sal_uInt32>(SvxBackgroundTabFlags::SHOW_CHAR_BKGCOLOR)));
+ rPage.PageCreated(aSet);
+ }
+}
+
+ScParagraphDlg::ScParagraphDlg(weld::Window* pParent, const SfxItemSet* pAttr)
+ : SfxTabDialogController(pParent, "modules/scalc/ui/paradialog.ui", "ParagraphDialog", pAttr)
+{
+ AddTabPage("labelTP_PARA_STD", RID_SVXPAGE_STD_PARAGRAPH);
+ AddTabPage("labelTP_PARA_ALIGN", RID_SVXPAGE_ALIGN_PARAGRAPH);
+ if (SvtCJKOptions::IsAsianTypographyEnabled() )
+ AddTabPage("labelTP_PARA_ASIAN", RID_SVXPAGE_PARA_ASIAN);
+ else
+ RemoveTabPage("labelTP_PARA_ASIAN");
+ AddTabPage("labelTP_TABULATOR", RID_SVXPAGE_TABULATOR);
+}
+
+void ScParagraphDlg::PageCreated(const OString& rId, SfxTabPage &rPage)
+{
+ if (rId == "labelTP_TABULATOR")
+ {
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ TabulatorDisableFlags const nFlags((TabulatorDisableFlags::TypeMask &~TabulatorDisableFlags::TypeLeft) |
+ (TabulatorDisableFlags::FillMask &~TabulatorDisableFlags::FillNone));
+ aSet.Put(SfxUInt16Item(SID_SVXTABULATORTABPAGE_DISABLEFLAGS, static_cast<sal_uInt16>(nFlags)));
+ rPage.PageCreated(aSet);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/warnbox.cxx b/sc/source/ui/miscdlgs/warnbox.cxx
new file mode 100644
index 000000000..8bb0a37d1
--- /dev/null
+++ b/sc/source/ui/miscdlgs/warnbox.cxx
@@ -0,0 +1,52 @@
+/* -*- 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 <warnbox.hxx>
+
+#include <scmod.hxx>
+#include <inputopt.hxx>
+
+ScReplaceWarnBox::ScReplaceWarnBox(weld::Window* pParent)
+ : MessageDialogController(pParent, "modules/scalc/ui/checkwarningdialog.ui",
+ "CheckWarningDialog", "ask")
+ // By default, the check box is ON, and the user needs to un-check it to
+ // disable all future warnings.
+ , m_xWarningOnBox(m_xBuilder->weld_check_button("ask"))
+{
+ m_xDialog->set_default_response(RET_YES);
+}
+
+short ScReplaceWarnBox::run()
+{
+ short nRet = RET_YES;
+ if (SC_MOD()->GetInputOptions().GetReplaceCellsWarn())
+ {
+ nRet = MessageDialogController::run();
+ if (!m_xWarningOnBox->get_active())
+ {
+ ScModule* pScMod = SC_MOD();
+ ScInputOptions aInputOpt(pScMod->GetInputOptions());
+ aInputOpt.SetReplaceCellsWarn(false);
+ pScMod->SetInputOptions(aInputOpt);
+ }
+ }
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */