sc/Library_sc.mk                             |    1 
 sc/source/ui/docshell/dbdocfun.cxx           |  217 ----------------------
 sc/source/ui/inc/dbdocfun.hxx                |    1 
 sc/source/ui/inc/operation/SortOperation.hxx |   41 ++++
 sc/source/ui/operation/SortOperation.cxx     |  263 +++++++++++++++++++++++++++
 5 files changed, 310 insertions(+), 213 deletions(-)

New commits:
commit 0f38f515dea122b34bd8cf2b83e9934c9f84ddd1
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Wed Jan 28 12:22:14 2026 +0900
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Feb 10 14:52:15 2026 +0100

    sc: Introduce SortOperation and move the impl. from ScDBDocFunc
    
    Sort operation using implementation from ScDBDocFunc.
    No functional change, but logging changed to SAL_WARN.
    
    Change-Id: I6b23a3296a2bce9fdeef9c2774d6f9b34bd30da5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198732
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 652f41d9eede..74accd38dc06 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -532,6 +532,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/operation/DeleteCellOperation \
     sc/source/ui/operation/DeleteContentOperation \
     sc/source/ui/operation/Operation \
+    sc/source/ui/operation/SortOperation \
     sc/source/ui/pagedlg/areasdlg \
     sc/source/ui/pagedlg/tphfedit \
     sc/source/ui/sidebar/AlignmentPropertyPanel \
diff --git a/sc/source/ui/docshell/dbdocfun.cxx 
b/sc/source/ui/docshell/dbdocfun.cxx
index b9baf4131982..ba79111acad3 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -58,6 +58,7 @@
 #include <chartlis.hxx>
 #include <ChartTools.hxx>
 #include <SheetViewOperationsTester.hxx>
+#include <operation/SortOperation.hxx>
 
 #include <memory>
 
@@ -608,220 +609,10 @@ bool ScDBDocFunc::RepeatDB( const OUString& rDBName, 
bool bApi, bool bIsUnnamed,
     return bDone;
 }
 
-bool ScDBDocFunc::SortTab(SCTAB nTab, const ScSortParam& rSortParam, bool 
bRecord, bool bPaint, bool bApi )
+bool ScDBDocFunc::SortTab(SCTAB nTab, const ScSortParam& rSortParam, bool 
bRecord, bool bPaint, bool bApi)
 {
-    ScDocShellModificator aModificator( rDocShell );
-
-    ScDocument& rDoc = rDocShell.GetDocument();
-    if (bRecord && !rDoc.IsUndoEnabled())
-        bRecord = false;
-
-    ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rSortParam.nCol1, 
rSortParam.nRow1,
-                                                    rSortParam.nCol2, 
rSortParam.nRow2 );
-    if (!pDBData)
-    {
-        OSL_FAIL( "Sort: no DBData" );
-        return false;
-    }
-
-    bool bCopy = !rSortParam.bInplace;
-    if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
-                  rSortParam.nDestRow == rSortParam.nRow1 && 
rSortParam.nDestTab == nTab )
-        bCopy = false;
-
-    ScSortParam aLocalParam( rSortParam );
-    if ( bCopy )
-    {
-        // Copy the data range to the destination then move the sort range to 
it.
-        ScRange aSrcRange(rSortParam.nCol1, rSortParam.nRow1, nTab, 
rSortParam.nCol2, rSortParam.nRow2, nTab);
-        ScAddress 
aDestPos(rSortParam.nDestCol,rSortParam.nDestRow,rSortParam.nDestTab);
-
-        ScDocFunc& rDocFunc = rDocShell.GetDocFunc();
-        bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, bRecord, 
bPaint, bApi);
-
-        if (!bRet)
-            return false;
-
-        aLocalParam.MoveToDest();
-        nTab = aLocalParam.nDestTab;
-    }
-
-    // tdf#119804: If there is a header row/column, it won't be affected by
-    // sorting; so we can exclude it from the test.
-    SCROW nStartingRowToEdit = aLocalParam.nRow1;
-    SCCOL nStartingColToEdit = aLocalParam.nCol1;
-    if ( aLocalParam.bHasHeader )
-    {
-        if ( aLocalParam.bByRow )
-            nStartingRowToEdit++;
-        else
-            nStartingColToEdit++;
-    }
-
-    if (!CheckSheetViewProtection(sc::OperationType::Sort))
-        return false;
-
-    ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(
-            rDoc, nTab, nStartingColToEdit, nStartingRowToEdit,
-            aLocalParam.nCol2, aLocalParam.nRow2, true /*bNoMatrixAtAll*/);
-    if (!aTester.IsEditable())
-    {
-        if (!bApi)
-            rDocShell.ErrorMessage(aTester.GetMessageId());
-        return false;
-    }
-
-    const ScInputOptions aInputOption = ScModule::get()->GetInputOptions();
-    const bool bUpdateRefs = aInputOption.GetSortRefUpdate();
-
-    // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or
-    // column (depending on direction) in any case, not just if it has headers,
-    // so empty leading cells will be sorted to the end.
-    // aLocalParam.nCol/Row will encompass data content only, extras in
-    // aLocalParam.aDataAreaExtras.
-    bool bShrunk = false;
-    aLocalParam.aDataAreaExtras.resetArea();
-    rDoc.ShrinkToUsedDataArea(bShrunk, nTab, aLocalParam.nCol1, 
aLocalParam.nRow1,
-                              aLocalParam.nCol2, aLocalParam.nRow2, false, 
aLocalParam.bByRow,
-                              !aLocalParam.bByRow,
-                              (aLocalParam.aDataAreaExtras.anyExtrasWanted() ?
-                               &aLocalParam.aDataAreaExtras : nullptr));
-
-    SCROW nStartRow = aLocalParam.nRow1;
-    if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < 
aLocalParam.nRow2)
-        ++nStartRow;
-
-    SCCOL nOverallCol1 = aLocalParam.nCol1;
-    SCROW nOverallRow1 = aLocalParam.nRow1;
-    SCCOL nOverallCol2 = aLocalParam.nCol2;
-    SCROW nOverallRow2 = aLocalParam.nRow2;
-    if (aLocalParam.aDataAreaExtras.anyExtrasWanted())
-    {
-        // Trailing empty excess columns/rows are excluded from being sorted,
-        // they stick at the end. Clip them.
-        const ScDataAreaExtras::Clip eClip = (aLocalParam.bByRow ?
-                ScDataAreaExtras::Clip::Row : ScDataAreaExtras::Clip::Col);
-        aLocalParam.aDataAreaExtras.GetOverallRange( nOverallCol1, 
nOverallRow1, nOverallCol2, nOverallRow2, eClip);
-        // Make it permanent.
-        aLocalParam.aDataAreaExtras.SetOverallRange( nOverallCol1, 
nOverallRow1, nOverallCol2, nOverallRow2);
-
-        if (bUpdateRefs)
-        {
-            // With update references the entire range needs to be handled as
-            // one entity for references pointing within to be moved along,
-            // even when there's no data content. For huge ranges we may be
-            // DOOMed then.
-            aLocalParam.nCol1 = nOverallCol1;
-            aLocalParam.nRow1 = nOverallRow1;
-            aLocalParam.nCol2 = nOverallCol2;
-            aLocalParam.nRow2 = nOverallRow2;
-        }
-    }
-
-    if (aLocalParam.aDataAreaExtras.mbCellFormats
-            && rDoc.HasAttrib( nOverallCol1, nStartRow, nTab, nOverallCol2, 
nOverallRow2, nTab,
-                HasAttrFlags::Merged | HasAttrFlags::Overlapped))
-    {
-        // Merge attributes would be mixed up during sorting.
-        if (!bApi)
-            rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
-        return false;
-    }
-
-    //      execute
-
-    weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() );
-
-    // Calculate the script types for all cells in the sort range beforehand.
-    // This will speed up the row height adjustment that takes place after the
-    // sort.
-    rDoc.UpdateScriptTypes(
-        ScAddress(aLocalParam.nCol1,nStartRow,nTab),
-        aLocalParam.nCol2-aLocalParam.nCol1+1,
-        aLocalParam.nRow2-nStartRow+1);
-
-    // No point adjusting row heights after the sort when all rows have the 
same height.
-    bool bUniformRowHeight = rDoc.HasUniformRowHeight(nTab, nStartRow, 
nOverallRow2);
-
-    bool bRepeatQuery = false;                          // repeat existing 
filter?
-    ScQueryParam aQueryParam;
-    pDBData->GetQueryParam( aQueryParam );
-    if ( aQueryParam.GetEntry(0).bDoQuery )
-        bRepeatQuery = true;
-
-    sc::ReorderParam aUndoParam;
-
-    // don't call ScDocument::Sort with an empty SortParam (may be empty here 
if bCopy is set)
-    if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
-    {
-        ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, 
true);
-        if (!bRepeatQuery)
-            bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, 
aLocalParam.nRow2, nTab);
-        rDoc.Sort(nTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, 
&aUndoParam);
-    }
-
-    if (bRecord)
-    {
-        // Set up an undo object.
-        rDocShell.GetUndoManager()->AddUndoAction(
-            std::make_unique<sc::UndoSort>(&rDocShell, aUndoParam));
-    }
-
-    pDBData->SetSortParam(rSortParam);
-    // Remember additional settings on anonymous database ranges.
-    if (pDBData == rDoc.GetAnonymousDBData( nTab) || 
rDoc.GetDBCollection()->getAnonDBs().has( pDBData))
-        pDBData->UpdateFromSortParam( rSortParam);
-
-    if (SfxViewShell* pKitSomeViewForThisDoc = 
comphelper::LibreOfficeKit::isActive() ?
-                                               
rDocShell.GetBestViewShell(false) : nullptr)
-    {
-        SfxViewShell* pViewShell = SfxViewShell::GetFirst();
-        while (pViewShell)
-        {
-            ScTabViewShell* pTabViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
-            if (pTabViewShell && pTabViewShell->GetDocId() == 
pKitSomeViewForThisDoc->GetDocId())
-            {
-                if (ScPositionHelper* pPosHelper = 
pTabViewShell->GetViewData().GetLOKHeightHelper(nTab))
-                    pPosHelper->invalidateByIndex(nStartRow);
-            }
-            pViewShell = SfxViewShell::GetNext(*pViewShell);
-        }
-
-        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
-            pKitSomeViewForThisDoc, false /* bColumns */, true /* bRows */, 
true /* bSizes*/,
-            true /* bHidden */, true /* bFiltered */, true /* bGroups */, 
nTab);
-    }
-
-    if (nStartRow <= aLocalParam.nRow2)
-    {
-        ScRange aDirtyRange(
-                aLocalParam.nCol1, nStartRow, nTab,
-                aLocalParam.nCol2, aLocalParam.nRow2, nTab);
-        rDoc.SetDirty( aDirtyRange, true );
-    }
-
-    if (bPaint)
-    {
-        PaintPartFlags nPaint = PaintPartFlags::Grid;
-        SCCOL nStartX = nOverallCol1;
-        SCROW nStartY = nOverallRow1;
-        SCCOL nEndX = nOverallCol2;
-        SCROW nEndY = nOverallRow2;
-        if ( bRepeatQuery )
-        {
-            nPaint |= PaintPartFlags::Left;
-            nStartX = 0;
-            nEndX = rDoc.MaxCol();
-        }
-        rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, 
nTab), nPaint);
-    }
-
-    if (!bUniformRowHeight && nStartRow <= nOverallRow2)
-        rDocShell.AdjustRowHeight(nStartRow, nOverallRow2, nTab);
-
-    aModificator.SetDocumentModified();
-
-    return true;
+    sc::SortOperation aOperation(rDocShell, nTab, rSortParam, bRecord, bPaint, 
bApi);
+    return aOperation.run();
 }
 
 bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
diff --git a/sc/source/ui/inc/dbdocfun.hxx b/sc/source/ui/inc/dbdocfun.hxx
index 3639c2d0347c..d7dd1c377573 100644
--- a/sc/source/ui/inc/dbdocfun.hxx
+++ b/sc/source/ui/inc/dbdocfun.hxx
@@ -47,6 +47,7 @@ namespace sc
 class ScDBDocFunc
 {
 friend class ScDBFunc;
+friend class SortOperation;
 
 private:
     ScDocShell&     rDocShell;
diff --git a/sc/source/ui/inc/operation/SortOperation.hxx 
b/sc/source/ui/inc/operation/SortOperation.hxx
new file mode 100644
index 000000000000..a26360254273
--- /dev/null
+++ b/sc/source/ui/inc/operation/SortOperation.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include "Operation.hxx"
+#include <sal/types.h>
+#include <address.hxx>
+
+class ScDocShell;
+class ScMarkData;
+class ScDocFunc;
+struct ScSortParam;
+enum class InsertDeleteFlags : sal_Int32;
+
+namespace sc
+{
+/** Operation which sorts cells in a sheet. */
+class SortOperation : public Operation
+{
+private:
+    ScDocShell& mrDocShell;
+    SCTAB mnTab;
+    ScSortParam const& mrSortParam;
+    bool mbPaint;
+
+    bool runImplementation() override;
+
+public:
+    SortOperation(ScDocShell& rDocShell, SCTAB nTab, ScSortParam const& 
rSortParam, bool bRecord,
+                  bool bPaint, bool bApi);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/operation/SortOperation.cxx 
b/sc/source/ui/operation/SortOperation.cxx
new file mode 100644
index 000000000000..a01af92b6025
--- /dev/null
+++ b/sc/source/ui/operation/SortOperation.cxx
@@ -0,0 +1,263 @@
+/* -*- 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 <operation/SortOperation.hxx>
+
+#include <docfuncutil.hxx>
+#include <docfunc.hxx>
+#include <editable.hxx>
+#include <markdata.hxx>
+#include <SheetViewOperationsTester.hxx>
+#include <editable.hxx>
+#include <progress.hxx>
+#include <undosort.hxx>
+#include <scresid.hxx>
+#include <scmod.hxx>
+#include <dbdata.hxx>
+#include <globstr.hrc>
+#include <globalnames.hxx>
+#include <tabvwsh.hxx>
+#include <dociter.hxx>
+#include <queryentry.hxx>
+#include <inputopt.hxx>
+
+#include <memory>
+
+namespace sc
+{
+SortOperation::SortOperation(ScDocShell& rDocShell, SCTAB nTab, const 
ScSortParam& rSortParam,
+                             bool bRecord, bool bPaint, bool bApi)
+    : Operation(OperationType::Sort, bRecord, bApi)
+    , mrDocShell(rDocShell)
+    , mnTab(nTab)
+    , mrSortParam(rSortParam)
+    , mbPaint(bPaint)
+{
+}
+
+bool SortOperation::runImplementation()
+{
+    ScDocShellModificator aModificator(mrDocShell);
+
+    ScDocument& rDoc = mrDocShell.GetDocument();
+    if (mbRecord && !rDoc.IsUndoEnabled())
+        mbRecord = false;
+
+    ScDBData* pDBData = rDoc.GetDBAtArea(mnTab, mrSortParam.nCol1, 
mrSortParam.nRow1,
+                                         mrSortParam.nCol2, mrSortParam.nRow2);
+    if (!pDBData)
+    {
+        SAL_WARN("sc", "Sort: no DBData");
+        return false;
+    }
+
+    bool bCopy = !mrSortParam.bInplace;
+    if (bCopy && mrSortParam.nDestCol == mrSortParam.nCol1
+        && mrSortParam.nDestRow == mrSortParam.nRow1 && mrSortParam.nDestTab 
== mnTab)
+        bCopy = false;
+
+    ScSortParam aLocalParam(mrSortParam);
+    if (bCopy)
+    {
+        // Copy the data range to the destination then move the sort range to 
it.
+        ScRange aSrcRange(mrSortParam.nCol1, mrSortParam.nRow1, mnTab, 
mrSortParam.nCol2,
+                          mrSortParam.nRow2, mnTab);
+        ScAddress aDestPos(mrSortParam.nDestCol, mrSortParam.nDestRow, 
mrSortParam.nDestTab);
+
+        ScDocFunc& rDocFunc = mrDocShell.GetDocFunc();
+        bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, mbRecord, 
mbPaint, mbApi);
+
+        if (!bRet)
+            return false;
+
+        aLocalParam.MoveToDest();
+        mnTab = aLocalParam.nDestTab;
+    }
+
+    // tdf#119804: If there is a header row/column, it won't be affected by
+    // sorting; so we can exclude it from the test.
+    SCROW nStartingRowToEdit = aLocalParam.nRow1;
+    SCCOL nStartingColToEdit = aLocalParam.nCol1;
+    if (aLocalParam.bHasHeader)
+    {
+        if (aLocalParam.bByRow)
+            nStartingRowToEdit++;
+        else
+            nStartingColToEdit++;
+    }
+
+    if (!checkSheetViewProtection())
+        return false;
+
+    ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(
+        rDoc, mnTab, nStartingColToEdit, nStartingRowToEdit, 
aLocalParam.nCol2, aLocalParam.nRow2,
+        true /*bNoMatrixAtAll*/);
+    if (!aTester.IsEditable())
+    {
+        if (!mbApi)
+            mrDocShell.ErrorMessage(aTester.GetMessageId());
+        return false;
+    }
+
+    const ScInputOptions aInputOption = ScModule::get()->GetInputOptions();
+    const bool bUpdateRefs = aInputOption.GetSortRefUpdate();
+
+    // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or
+    // column (depending on direction) in any case, not just if it has headers,
+    // so empty leading cells will be sorted to the end.
+    // aLocalParam.nCol/Row will encompass data content only, extras in
+    // aLocalParam.aDataAreaExtras.
+    bool bShrunk = false;
+    aLocalParam.aDataAreaExtras.resetArea();
+    rDoc.ShrinkToUsedDataArea(
+        bShrunk, mnTab, aLocalParam.nCol1, aLocalParam.nRow1, 
aLocalParam.nCol2, aLocalParam.nRow2,
+        false, aLocalParam.bByRow, !aLocalParam.bByRow,
+        (aLocalParam.aDataAreaExtras.anyExtrasWanted() ? 
&aLocalParam.aDataAreaExtras : nullptr));
+
+    SCROW nStartRow = aLocalParam.nRow1;
+    if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < 
aLocalParam.nRow2)
+        ++nStartRow;
+
+    SCCOL nOverallCol1 = aLocalParam.nCol1;
+    SCROW nOverallRow1 = aLocalParam.nRow1;
+    SCCOL nOverallCol2 = aLocalParam.nCol2;
+    SCROW nOverallRow2 = aLocalParam.nRow2;
+    if (aLocalParam.aDataAreaExtras.anyExtrasWanted())
+    {
+        // Trailing empty excess columns/rows are excluded from being sorted,
+        // they stick at the end. Clip them.
+        const ScDataAreaExtras::Clip eClip
+            = (aLocalParam.bByRow ? ScDataAreaExtras::Clip::Row : 
ScDataAreaExtras::Clip::Col);
+        aLocalParam.aDataAreaExtras.GetOverallRange(nOverallCol1, 
nOverallRow1, nOverallCol2,
+                                                    nOverallRow2, eClip);
+        // Make it permanent.
+        aLocalParam.aDataAreaExtras.SetOverallRange(nOverallCol1, 
nOverallRow1, nOverallCol2,
+                                                    nOverallRow2);
+
+        if (bUpdateRefs)
+        {
+            // With update references the entire range needs to be handled as
+            // one entity for references pointing within to be moved along,
+            // even when there's no data content. For huge ranges we may be
+            // DOOMed then.
+            aLocalParam.nCol1 = nOverallCol1;
+            aLocalParam.nRow1 = nOverallRow1;
+            aLocalParam.nCol2 = nOverallCol2;
+            aLocalParam.nRow2 = nOverallRow2;
+        }
+    }
+
+    if (aLocalParam.aDataAreaExtras.mbCellFormats
+        && rDoc.HasAttrib(nOverallCol1, nStartRow, mnTab, nOverallCol2, 
nOverallRow2, mnTab,
+                          HasAttrFlags::Merged | HasAttrFlags::Overlapped))
+    {
+        // Merge attributes would be mixed up during sorting.
+        if (!mbApi)
+            mrDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
+        return false;
+    }
+
+    //      execute
+
+    weld::WaitObject aWait(ScDocShell::GetActiveDialogParent());
+
+    // Calculate the script types for all cells in the sort range beforehand.
+    // This will speed up the row height adjustment that takes place after the
+    // sort.
+    rDoc.UpdateScriptTypes(ScAddress(aLocalParam.nCol1, nStartRow, mnTab),
+                           aLocalParam.nCol2 - aLocalParam.nCol1 + 1,
+                           aLocalParam.nRow2 - nStartRow + 1);
+
+    // No point adjusting row heights after the sort when all rows have the 
same height.
+    bool bUniformRowHeight = rDoc.HasUniformRowHeight(mnTab, nStartRow, 
nOverallRow2);
+
+    bool bRepeatQuery = false; // repeat existing filter?
+    ScQueryParam aQueryParam;
+    pDBData->GetQueryParam(aQueryParam);
+    if (aQueryParam.GetEntry(0).bDoQuery)
+        bRepeatQuery = true;
+
+    sc::ReorderParam aUndoParam;
+
+    // don't call ScDocument::Sort with an empty SortParam (may be empty here 
if bCopy is set)
+    if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
+    {
+        ScProgress aProgress(&mrDocShell, ScResId(STR_PROGRESS_SORTING), 0, 
true);
+        if (!bRepeatQuery)
+            bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, 
aLocalParam.nRow2, mnTab);
+        rDoc.Sort(mnTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, 
&aUndoParam);
+    }
+
+    if (mbRecord)
+    {
+        // Set up an undo object.
+        mrDocShell.GetUndoManager()->AddUndoAction(
+            std::make_unique<sc::UndoSort>(&mrDocShell, aUndoParam));
+    }
+
+    pDBData->SetSortParam(mrSortParam);
+    // Remember additional settings on anonymous database ranges.
+    if (pDBData == rDoc.GetAnonymousDBData(mnTab)
+        || rDoc.GetDBCollection()->getAnonDBs().has(pDBData))
+        pDBData->UpdateFromSortParam(mrSortParam);
+
+    if (SfxViewShell* pKitSomeViewForThisDoc
+        = comphelper::LibreOfficeKit::isActive() ? 
mrDocShell.GetBestViewShell(false) : nullptr)
+    {
+        SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+        while (pViewShell)
+        {
+            ScTabViewShell* pTabViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
+            if (pTabViewShell && pTabViewShell->GetDocId() == 
pKitSomeViewForThisDoc->GetDocId())
+            {
+                if (ScPositionHelper* pPosHelper
+                    = pTabViewShell->GetViewData().GetLOKHeightHelper(mnTab))
+                    pPosHelper->invalidateByIndex(nStartRow);
+            }
+            pViewShell = SfxViewShell::GetNext(*pViewShell);
+        }
+
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+            pKitSomeViewForThisDoc, false /* bColumns */, true /* bRows */, 
true /* bSizes*/,
+            true /* bHidden */, true /* bFiltered */, true /* bGroups */, 
mnTab);
+    }
+
+    if (nStartRow <= aLocalParam.nRow2)
+    {
+        ScRange aDirtyRange(aLocalParam.nCol1, nStartRow, mnTab, 
aLocalParam.nCol2,
+                            aLocalParam.nRow2, mnTab);
+        rDoc.SetDirty(aDirtyRange, true);
+    }
+
+    if (mbPaint)
+    {
+        PaintPartFlags nPaint = PaintPartFlags::Grid;
+        SCCOL nStartX = nOverallCol1;
+        SCROW nStartY = nOverallRow1;
+        SCCOL nEndX = nOverallCol2;
+        SCROW nEndY = nOverallRow2;
+        if (bRepeatQuery)
+        {
+            nPaint |= PaintPartFlags::Left;
+            nStartX = 0;
+            nEndX = rDoc.MaxCol();
+        }
+        mrDocShell.PostPaint(ScRange(nStartX, nStartY, mnTab, nEndX, nEndY, 
mnTab), nPaint);
+    }
+
+    if (!bUniformRowHeight && nStartRow <= nOverallRow2)
+        mrDocShell.AdjustRowHeight(nStartRow, nOverallRow2, mnTab);
+
+    aModificator.SetDocumentModified();
+
+    return true;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to