[Libreoffice-commits] core.git: include/xmloff sc/inc sc/source sc/uiconfig xmloff/source

Kohei Yoshida kohei.yoshida at collabora.com
Wed May 17 03:17:25 UTC 2017


 include/xmloff/xmltoken.hxx             |    4 +
 sc/inc/document.hxx                     |    3 +
 sc/inc/global.hxx                       |   15 +++++
 sc/inc/table.hxx                        |    2 
 sc/source/core/data/document10.cxx      |   23 ++++++++
 sc/source/core/data/table7.cxx          |   82 ++++++++++++++++++++++++++++++++
 sc/source/filter/xml/xmlexprt.cxx       |   10 +++
 sc/source/filter/xml/xmlimprt.cxx       |    4 +
 sc/source/filter/xml/xmlimprt.hxx       |    6 +-
 sc/source/filter/xml/xmlsubti.cxx       |   10 +++
 sc/source/filter/xml/xmlsubti.hxx       |    4 +
 sc/source/filter/xml/xmltabi.cxx        |   24 ++++++++-
 sc/source/ui/docshell/docfunc.cxx       |   46 +++++++++++++++++
 sc/source/ui/docshell/editable.cxx      |   22 ++++++++
 sc/source/ui/inc/editable.hxx           |   14 +++++
 sc/source/ui/inc/protectiondlg.hxx      |    4 +
 sc/source/ui/miscdlgs/protectiondlg.cxx |   24 +++++++--
 sc/source/ui/view/cellsh.cxx            |   26 ++++++++++
 sc/uiconfig/scalc/ui/protectsheetdlg.ui |   48 ++++++++++++++++++
 xmloff/source/core/xmltoken.cxx         |    4 +
 xmloff/source/token/tokens.txt          |    4 +
 21 files changed, 369 insertions(+), 10 deletions(-)

New commits:
commit 034be10413ed4915090678ad4f1d48596cf5e206
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu May 11 18:07:56 2017 -0400

    tdf#43535: support additional sheet protection options.
    
    New options are:
    
    * insert columns.
    * insert rows.
    * delete columns.
    * delete rows.
    
    Change-Id: I076b0d01bee0fff0623e2f1137c09938a6110939
    Reviewed-on: https://gerrit.libreoffice.org/37695
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>

diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 9ab65abfd195..d746ae78c5d0 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -605,6 +605,8 @@ namespace xmloff { namespace token {
         XML_DEFAULT_STYLE_NAME,
         XML_DEGREE,
         XML_DELAY,
+        XML_DELETE_COLUMNS,
+        XML_DELETE_ROWS,
         XML_DELETION,
         XML_DELETIONS,
         XML_DENOMALIGN,
@@ -1037,6 +1039,8 @@ namespace xmloff { namespace token {
         XML_INFORMATION,
         XML_INITIAL_CREATOR,
         XML_INPROCEEDINGS,
+        XML_INSERT_COLUMNS,
+        XML_INSERT_ROWS,
         XML_INSERTION,
         XML_INSERTION_CUT_OFF,
         XML_INSERTION_POSITION,
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 2c0f1318fc63..87c89958acf2 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -791,6 +791,9 @@ public:
                                                     SCCOL nEndCol, SCROW nEndRow,
                                                     const ScMarkData& rMark ) const;
 
+    bool IsEditActionAllowed( sc::ColRowEditAction eAction, SCTAB nTab, SCCOLROW nStart, SCCOLROW nEnd ) const;
+    bool IsEditActionAllowed( sc::ColRowEditAction eAction, const ScMarkData& rMark, SCCOLROW nStart, SCCOLROW nEnd ) const;
+
     SC_DLLPUBLIC bool GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix );
 
     bool            IsEmbedded() const { return bIsEmbedded;}
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 1c67775099cb..7219b9bd2a04 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -428,6 +428,21 @@ enum ScDBObject
     ScDbQuery
 };
 
+namespace sc {
+
+enum class ColRowEditAction
+{
+    Unknown,
+    InsertColumnsBefore,
+    InsertColumnsAfter,
+    InsertRowsBefore,
+    InsertRowsAfter,
+    DeleteColumns,
+    DeleteRows
+};
+
+}
+
 struct ScImportParam
 {
     SCCOL           nCol1;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 87ba9c6df206..c5941b0a085f 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -350,6 +350,8 @@ public:
     void            SetProtection(const ScTableProtection* pProtect);
     ScTableProtection* GetProtection();
 
+    bool IsEditActionAllowed( sc::ColRowEditAction eAction, SCCOLROW nStart, SCCOLROW nEnd ) const;
+
     Size            GetPageSize() const;
     void            SetPageSize( const Size& rSize );
     void            SetRepeatArea( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow );
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 161729063e4b..1273a17bc87f 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -881,4 +881,27 @@ bool ScDocument::CopyAdjustRangeName( SCTAB& rSheet, sal_uInt16& rIndex, ScRange
     return true;
 }
 
+bool ScDocument::IsEditActionAllowed(
+    sc::ColRowEditAction eAction, SCTAB nTab, SCCOLROW nStart, SCCOLROW nEnd ) const
+{
+    const ScTable* pTab = FetchTable(nTab);
+    if (!pTab)
+        return false;
+
+    return pTab->IsEditActionAllowed(eAction, nStart, nEnd);
+}
+
+bool ScDocument::IsEditActionAllowed(
+    sc::ColRowEditAction eAction, const ScMarkData& rMark, SCCOLROW nStart, SCCOLROW nEnd ) const
+{
+    ScMarkData::const_iterator it = rMark.begin(), itEnd = rMark.end();
+    for (; it != itEnd; ++it)
+    {
+        if (!IsEditActionAllowed(eAction, *it, nStart, nEnd))
+            return false;
+    }
+
+    return true;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 051e57bc7609..723a3d64c3fb 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -16,6 +16,7 @@
 #include <sharedformula.hxx>
 #include <cellvalues.hxx>
 #include "olinetab.hxx"
+#include <tabprotection.hxx>
 
 bool ScTable::IsMerged( SCCOL nCol, SCROW nRow ) const
 {
@@ -310,6 +311,87 @@ void ScTable::SetNeedsListeningGroup( SCCOL nCol, SCROW nRow )
     aCol[nCol].SetNeedsListeningGroup(nRow);
 }
 
+bool ScTable::IsEditActionAllowed(
+    sc::ColRowEditAction eAction, SCCOLROW nStart, SCCOLROW nEnd ) const
+{
+    if (!IsProtected())
+    {
+        SCCOL nCol1 = 0, nCol2 = MAXCOL;
+        SCROW nRow1 = 0, nRow2 = MAXROW;
+
+        switch (eAction)
+        {
+            case sc::ColRowEditAction::InsertColumnsBefore:
+            case sc::ColRowEditAction::InsertColumnsAfter:
+            case sc::ColRowEditAction::DeleteColumns:
+            {
+                nCol1 = nStart;
+                nCol2 = nEnd;
+                break;
+            }
+            case sc::ColRowEditAction::InsertRowsBefore:
+            case sc::ColRowEditAction::InsertRowsAfter:
+            case sc::ColRowEditAction::DeleteRows:
+            {
+                nRow1 = nStart;
+                nRow2 = nEnd;
+                break;
+            }
+            default:
+                ;
+        }
+
+        return IsBlockEditable(nCol1, nRow1, nCol2, nRow2, nullptr);
+    }
+
+    if (IsScenario())
+        // TODO: I don't even know what this scenario thingie is. Perhaps we
+        // should check it against the scenario ranges?
+        return false;
+
+    assert(pTabProtection);
+
+    switch (eAction)
+    {
+        case sc::ColRowEditAction::InsertColumnsBefore:
+        case sc::ColRowEditAction::InsertColumnsAfter:
+        {
+            // TODO: improve the matrix range handling for the insert-before action.
+            if (HasBlockMatrixFragment(nStart, 0, nEnd, MAXROW))
+                return false;
+
+            return pTabProtection->isOptionEnabled(ScTableProtection::INSERT_COLUMNS);
+        }
+        case sc::ColRowEditAction::InsertRowsBefore:
+        case sc::ColRowEditAction::InsertRowsAfter:
+        {
+            // TODO: improve the matrix range handling for the insert-before action.
+            if (HasBlockMatrixFragment(0, nStart, MAXCOL, nEnd))
+                return false;
+
+            return pTabProtection->isOptionEnabled(ScTableProtection::INSERT_ROWS);
+        }
+        case sc::ColRowEditAction::DeleteColumns:
+        {
+            if (!pTabProtection->isOptionEnabled(ScTableProtection::DELETE_COLUMNS))
+                return false;
+
+            return !HasAttrib(nStart, 0, nEnd, MAXROW, HasAttrFlags::Protected);
+        }
+        case sc::ColRowEditAction::DeleteRows:
+        {
+            if (!pTabProtection->isOptionEnabled(ScTableProtection::DELETE_ROWS))
+                return false;
+
+            return !HasAttrib(0, nStart, MAXCOL, nEnd, HasAttrFlags::Protected);
+        }
+        default:
+            ;
+    }
+
+    return false;
+}
+
 void ScTable::finalizeOutlineImport()
 {
     if (pOutlineTable && pRowFlags)
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index f84eaea6488d..d7e4ef5b8ce6 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -2894,6 +2894,16 @@ void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpre
         if (pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS))
             AddAttribute(XML_NAMESPACE_LO_EXT, XML_SELECT_UNPROTECTED_CELLS, XML_TRUE);
 
+        if (pProtect->isOptionEnabled(ScTableProtection::INSERT_COLUMNS))
+            AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_COLUMNS, XML_TRUE);
+        if (pProtect->isOptionEnabled(ScTableProtection::INSERT_ROWS))
+            AddAttribute(XML_NAMESPACE_LO_EXT, XML_INSERT_ROWS, XML_TRUE);
+
+        if (pProtect->isOptionEnabled(ScTableProtection::DELETE_COLUMNS))
+            AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_COLUMNS, XML_TRUE);
+        if (pProtect->isOptionEnabled(ScTableProtection::DELETE_ROWS))
+            AddAttribute(XML_NAMESPACE_LO_EXT, XML_DELETE_ROWS, XML_TRUE);
+
         OUString aElemName = GetNamespaceMap().GetQNameByKey(
             XML_NAMESPACE_LO_EXT, GetXMLToken(XML_TABLE_PROTECTION));
 
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index c8f94d7c4096..d035e9e1cab9 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -903,6 +903,10 @@ const SvXMLTokenMap& ScXMLImport::GetTableProtectionAttrTokenMap()
             { XML_NAMESPACE_LO_EXT, XML_SELECT_PROTECTED_CELLS, XML_TOK_TABLE_SELECT_PROTECTED_CELLS_EXT    },
             { XML_NAMESPACE_OFFICE_EXT, XML_SELECT_UNPROTECTED_CELLS, XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT  },
             { XML_NAMESPACE_LO_EXT, XML_SELECT_UNPROTECTED_CELLS, XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT  },
+            { XML_NAMESPACE_LO_EXT, XML_INSERT_COLUMNS, XML_TOK_TABLE_INSERT_COLUMNS_EXT, },
+            { XML_NAMESPACE_LO_EXT, XML_INSERT_ROWS, XML_TOK_TABLE_INSERT_ROWS_EXT, },
+            { XML_NAMESPACE_LO_EXT, XML_DELETE_COLUMNS, XML_TOK_TABLE_DELETE_COLUMNS_EXT, },
+            { XML_NAMESPACE_LO_EXT, XML_DELETE_ROWS, XML_TOK_TABLE_DELETE_ROWS_EXT, },
             XML_TOKEN_MAP_END
         };
         pTableProtectionElemTokenMap = new SvXMLTokenMap(aTableProtectionTokenMap);
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index 02c2ccfb3504..84dd944fd941 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -247,7 +247,11 @@ enum ScXMLTokenProtectionTokens
     XML_TOK_TABLE_SELECT_PROTECTED_CELLS,
     XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS,
     XML_TOK_TABLE_SELECT_PROTECTED_CELLS_EXT,
-    XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT
+    XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT,
+    XML_TOK_TABLE_INSERT_COLUMNS_EXT,
+    XML_TOK_TABLE_INSERT_ROWS_EXT,
+    XML_TOK_TABLE_DELETE_COLUMNS_EXT,
+    XML_TOK_TABLE_DELETE_ROWS_EXT,
 };
 
 enum ScXMLTableRowsTokens
diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx
index c44ac7e5c25e..593372406e91 100644
--- a/sc/source/filter/xml/xmlsubti.cxx
+++ b/sc/source/filter/xml/xmlsubti.cxx
@@ -51,7 +51,11 @@ ScXMLTabProtectionData::ScXMLTabProtectionData() :
     meHash2(PASSHASH_UNSPECIFIED),
     mbProtected(false),
     mbSelectProtectedCells(true),
-    mbSelectUnprotectedCells(true)
+    mbSelectUnprotectedCells(true),
+    mbInsertColumns(false),
+    mbInsertRows(false),
+    mbDeleteColumns(false),
+    mbDeleteRows(false)
 {
 }
 
@@ -203,6 +207,10 @@ void ScMyTables::DeleteTable()
         pProtect->setPasswordHash(aHash, maProtectionData.meHash1, maProtectionData.meHash2);
         pProtect->setOption(ScTableProtection::SELECT_LOCKED_CELLS,   maProtectionData.mbSelectProtectedCells);
         pProtect->setOption(ScTableProtection::SELECT_UNLOCKED_CELLS, maProtectionData.mbSelectUnprotectedCells);
+        pProtect->setOption(ScTableProtection::INSERT_COLUMNS, maProtectionData.mbInsertColumns);
+        pProtect->setOption(ScTableProtection::INSERT_ROWS,    maProtectionData.mbInsertRows);
+        pProtect->setOption(ScTableProtection::DELETE_COLUMNS, maProtectionData.mbDeleteColumns);
+        pProtect->setOption(ScTableProtection::DELETE_ROWS,    maProtectionData.mbDeleteRows);
         rImport.GetDocument()->SetTabProtection(maCurrentCellPos.Tab(), pProtect.get());
     }
 }
diff --git a/sc/source/filter/xml/xmlsubti.hxx b/sc/source/filter/xml/xmlsubti.hxx
index 48f7a92fbbd6..fc1be1654401 100644
--- a/sc/source/filter/xml/xmlsubti.hxx
+++ b/sc/source/filter/xml/xmlsubti.hxx
@@ -40,6 +40,10 @@ struct ScXMLTabProtectionData
     bool            mbProtected;
     bool            mbSelectProtectedCells;
     bool            mbSelectUnprotectedCells;
+    bool            mbInsertColumns;
+    bool            mbInsertRows;
+    bool            mbDeleteColumns;
+    bool            mbDeleteRows;
 
     ScXMLTabProtectionData();
 };
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
index 3c1a89cac4da..793416ba0e93 100644
--- a/sc/source/filter/xml/xmltabi.cxx
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -442,6 +442,10 @@ ScXMLTableProtectionContext::ScXMLTableProtectionContext(
     const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableProtectionAttrTokenMap();
     bool bSelectProtectedCells = false;
     bool bSelectUnprotectedCells = false;
+    bool bInsertColumns = false;
+    bool bInsertRows = false;
+    bool bDeleteColumns = false;
+    bool bDeleteRows = false;
 
     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
 
@@ -459,11 +463,23 @@ ScXMLTableProtectionContext::ScXMLTableProtectionContext(
             case XML_TOK_TABLE_SELECT_PROTECTED_CELLS:
             case XML_TOK_TABLE_SELECT_PROTECTED_CELLS_EXT:
                 bSelectProtectedCells = IsXMLToken(aValue, XML_TRUE);
-            break;
+                break;
             case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS:
             case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT:
                 bSelectUnprotectedCells = IsXMLToken(aValue, XML_TRUE);
-            break;
+                break;
+            case XML_TOK_TABLE_INSERT_COLUMNS_EXT:
+                bInsertColumns = IsXMLToken(aValue, XML_TRUE);
+                break;
+            case XML_TOK_TABLE_INSERT_ROWS_EXT:
+                bInsertRows = IsXMLToken(aValue, XML_TRUE);
+                break;
+            case XML_TOK_TABLE_DELETE_COLUMNS_EXT:
+                bDeleteColumns = IsXMLToken(aValue, XML_TRUE);
+                break;
+            case XML_TOK_TABLE_DELETE_ROWS_EXT:
+                bDeleteRows = IsXMLToken(aValue, XML_TRUE);
+                break;
             default:
                 SAL_WARN("sc", "unknown attribute: " << aAttrName);
         }
@@ -472,6 +488,10 @@ ScXMLTableProtectionContext::ScXMLTableProtectionContext(
     ScXMLTabProtectionData& rProtectData = GetScImport().GetTables().GetCurrentProtectionData();
     rProtectData.mbSelectProtectedCells   = bSelectProtectedCells;
     rProtectData.mbSelectUnprotectedCells = bSelectUnprotectedCells;
+    rProtectData.mbInsertColumns = bInsertColumns;
+    rProtectData.mbInsertRows = bInsertRows;
+    rProtectData.mbDeleteColumns = bDeleteColumns;
+    rProtectData.mbDeleteRows = bDeleteRows;
 }
 
 ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 5e686ca56a90..13d4baa795e8 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -1761,7 +1761,32 @@ bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark,
 
     SCCOL nEditTestEndCol = (eCmd==INS_INSCOLS_BEFORE || eCmd==INS_INSCOLS_AFTER) ? MAXCOL : nMergeTestEndCol;
     SCROW nEditTestEndRow = (eCmd==INS_INSROWS_BEFORE || eCmd==INS_INSROWS_AFTER) ? MAXROW : nMergeTestEndRow;
-    ScEditableTester aTester( &rDoc, nMergeTestStartCol, nMergeTestStartRow, nEditTestEndCol, nEditTestEndRow, aMark );
+
+    ScEditableTester aTester;
+
+    switch (eCmd)
+    {
+        case INS_INSCOLS_BEFORE:
+            aTester = ScEditableTester(
+                rDoc, sc::ColRowEditAction::InsertColumnsBefore, nMergeTestStartCol, nMergeTestEndCol, aMark);
+            break;
+        case INS_INSCOLS_AFTER:
+            aTester = ScEditableTester(
+                rDoc, sc::ColRowEditAction::InsertColumnsAfter, nMergeTestStartCol, nMergeTestEndCol, aMark);
+            break;
+        case INS_INSROWS_BEFORE:
+            aTester = ScEditableTester(
+                rDoc, sc::ColRowEditAction::InsertRowsBefore, nMergeTestStartRow, nMergeTestEndRow, aMark);
+            break;
+        case INS_INSROWS_AFTER:
+            aTester = ScEditableTester(
+                rDoc, sc::ColRowEditAction::InsertRowsAfter, nMergeTestStartRow, nMergeTestEndRow, aMark);
+            break;
+        default:
+            aTester = ScEditableTester(
+                &rDoc, nMergeTestStartCol, nMergeTestStartRow, nEditTestEndCol, nEditTestEndRow, aMark);
+    }
+
     if (!aTester.IsEditable())
     {
         if (!bApi)
@@ -2217,7 +2242,24 @@ bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
     SCROW nEditTestEndY = nUndoEndRow;
     if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
         nEditTestEndY = MAXROW;
-    ScEditableTester aTester( &rDoc, nUndoStartCol, nUndoStartRow, nEditTestEndX, nEditTestEndY, aMark );
+
+    ScEditableTester aTester;
+
+    switch (eCmd)
+    {
+        case DEL_DELCOLS:
+            aTester = ScEditableTester(
+                rDoc, sc::ColRowEditAction::DeleteColumns, nUndoStartCol, nUndoEndCol, aMark);
+            break;
+        case DEL_DELROWS:
+            aTester = ScEditableTester(
+                rDoc, sc::ColRowEditAction::DeleteRows, nUndoStartRow, nUndoEndRow, aMark);
+            break;
+        default:
+            aTester = ScEditableTester(
+                &rDoc, nUndoStartCol, nUndoStartRow, nEditTestEndX, nEditTestEndY, aMark);
+    }
+
     if (!aTester.IsEditable())
     {
         if (!bApi)
diff --git a/sc/source/ui/docshell/editable.cxx b/sc/source/ui/docshell/editable.cxx
index 05d4f19ebc89..2a06c82dc322 100644
--- a/sc/source/ui/docshell/editable.cxx
+++ b/sc/source/ui/docshell/editable.cxx
@@ -73,6 +73,13 @@ ScEditableTester::ScEditableTester( ScViewFunc* pView ) :
     }
 }
 
+ScEditableTester::ScEditableTester(
+    const ScDocument& rDoc, sc::ColRowEditAction eAction, SCCOLROW nStart, SCCOLROW nEnd, const ScMarkData& rMark ) :
+    ScEditableTester()
+{
+    TestBlockForAction(rDoc, eAction, nStart, nEnd, rMark);
+}
+
 void ScEditableTester::TestBlock( ScDocument* pDoc, SCTAB nTab,
                         SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
 {
@@ -124,6 +131,21 @@ void ScEditableTester::TestSelection( ScDocument* pDoc, const ScMarkData& rMark
     }
 }
 
+void ScEditableTester::TestBlockForAction(
+    const ScDocument& rDoc, sc::ColRowEditAction eAction, SCCOLROW nStart, SCCOLROW nEnd,
+    const ScMarkData& rMark )
+{
+    mbOnlyMatrix = false;
+
+    for (ScMarkData::const_iterator it = rMark.begin(), itEnd = rMark.end(); it != itEnd; ++it)
+    {
+        if (!mbIsEditable)
+            return;
+
+        mbIsEditable = rDoc.IsEditActionAllowed(eAction, *it, nStart, nEnd);
+    }
+}
+
 sal_uInt16 ScEditableTester::GetMessageId() const
 {
     if (mbIsEditable)
diff --git a/sc/source/ui/inc/editable.hxx b/sc/source/ui/inc/editable.hxx
index 10a03032c5ac..e47e2d473060 100644
--- a/sc/source/ui/inc/editable.hxx
+++ b/sc/source/ui/inc/editable.hxx
@@ -27,6 +27,12 @@ class ScViewFunc;
 class ScMarkData;
 class ScRange;
 
+namespace sc {
+
+enum class ColRowEditAction;
+
+}
+
 class ScEditableTester
 {
     bool mbIsEditable;
@@ -53,6 +59,10 @@ public:
             // calls TestView
             ScEditableTester( ScViewFunc* pView );
 
+    ScEditableTester(
+        const ScDocument& rDoc, sc::ColRowEditAction eAction, SCCOLROW nStart, SCCOLROW nEnd,
+        const ScMarkData& rMark );
+
             // Several calls to the Test... methods check if *all* of the ranges
             // are editable. For several independent checks, Reset() has to be used.
     void    TestBlock( ScDocument* pDoc, SCTAB nTab,
@@ -63,6 +73,10 @@ public:
     void    TestRange( ScDocument* pDoc, const ScRange& rRange );
     void    TestSelection( ScDocument* pDoc, const ScMarkData& rMark );
 
+    void TestBlockForAction(
+        const ScDocument& rDoc, sc::ColRowEditAction eAction, SCCOLROW nStart, SCCOLROW nEnd,
+        const ScMarkData& rMark );
+
     bool IsEditable() const { return mbIsEditable; }
     bool IsFormatEditable() const { return mbIsEditable || mbOnlyMatrix; }
     sal_uInt16  GetMessageId() const;
diff --git a/sc/source/ui/inc/protectiondlg.hxx b/sc/source/ui/inc/protectiondlg.hxx
index 752fee048706..351a733e31d0 100644
--- a/sc/source/ui/inc/protectiondlg.hxx
+++ b/sc/source/ui/inc/protectiondlg.hxx
@@ -62,6 +62,10 @@ private:
 
     OUString         m_aSelectLockedCells;
     OUString         m_aSelectUnlockedCells;
+    OUString         m_aInsertColumns;
+    OUString         m_aInsertRows;
+    OUString         m_aDeleteColumns;
+    OUString         m_aDeleteRows;
 
     DECL_LINK( OKHdl, Button*, void );
     DECL_LINK( CheckBoxHdl, Button*, void );
diff --git a/sc/source/ui/miscdlgs/protectiondlg.cxx b/sc/source/ui/miscdlgs/protectiondlg.cxx
index ddfd337a220b..082aec5a87c6 100644
--- a/sc/source/ui/miscdlgs/protectiondlg.cxx
+++ b/sc/source/ui/miscdlgs/protectiondlg.cxx
@@ -23,13 +23,21 @@
 
 #include <sal/macros.h>
 #include <vcl/msgbox.hxx>
+#include <vector>
+
+namespace {
 
 // The order must match that of the list box.
-static const ScTableProtection::Option aOptions[] = {
+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,
 };
-static const sal_uInt16 nOptionCount = SAL_N_ELEMENTS(aOptions);
+
+}
 
 ScTableProtectionDlg::ScTableProtectionDlg(vcl::Window* pParent)
     : ModalDialog( pParent, "ProtectSheetDialog", "modules/scalc/ui/protectsheetdlg.ui" )
@@ -44,6 +52,10 @@ ScTableProtectionDlg::ScTableProtectionDlg(vcl::Window* pParent)
 
     m_aSelectLockedCells = get<FixedText>("protected")->GetText();
     m_aSelectUnlockedCells = get<FixedText>("unprotected")->GetText();
+    m_aInsertColumns = get<FixedText>("insert-columns")->GetText();
+    m_aInsertRows = get<FixedText>("insert-rows")->GetText();
+    m_aDeleteColumns = get<FixedText>("delete-columns")->GetText();
+    m_aDeleteRows = get<FixedText>("delete-rows")->GetText();
 
     Init();
 }
@@ -67,7 +79,7 @@ void ScTableProtectionDlg::dispose()
 
 void ScTableProtectionDlg::SetDialogData(const ScTableProtection& rData)
 {
-    for (sal_uInt16 i = 0; i < nOptionCount; ++i)
+    for (size_t i = 0; i < aOptions.size(); ++i)
         m_pOptionsListBox->CheckEntryPos(i, rData.isOptionEnabled(aOptions[i]));
 }
 
@@ -78,7 +90,7 @@ void ScTableProtectionDlg::WriteData(ScTableProtection& rData) const
     // We assume that the two password texts match.
     rData.setPassword(m_pPassword1Edit->GetText());
 
-    for (sal_uInt16 i = 0; i < nOptionCount; ++i)
+    for (size_t i = 0; i < aOptions.size(); ++i)
         rData.setOption(aOptions[i], m_pOptionsListBox->IsChecked(i));
 }
 
@@ -97,6 +109,10 @@ void ScTableProtectionDlg::Init()
 
     m_pOptionsListBox->InsertEntry(m_aSelectLockedCells);
     m_pOptionsListBox->InsertEntry(m_aSelectUnlockedCells);
+    m_pOptionsListBox->InsertEntry(m_aInsertColumns);
+    m_pOptionsListBox->InsertEntry(m_aInsertRows);
+    m_pOptionsListBox->InsertEntry(m_aDeleteColumns);
+    m_pOptionsListBox->InsertEntry(m_aDeleteRows);
 
     m_pOptionsListBox->CheckEntryPos(0);
     m_pOptionsListBox->CheckEntryPos(1);
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 79d356e1a86f..52785f4fc883 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -231,6 +231,19 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
             case FID_INS_ROW:
             case FID_INS_ROWS_BEFORE:           // insert rows
             case FID_INS_ROWS_AFTER:
+            {
+                sc::ColRowEditAction eAction = sc::ColRowEditAction::InsertRowsBefore;
+                if (nWhich == FID_INS_ROWS_AFTER)
+                    eAction = sc::ColRowEditAction::InsertRowsAfter;
+
+                bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked();
+                if (!bEditable && nCol1 == 0 && nCol2 == MAXCOL)
+                {
+                    // See if row insertions are allowed.
+                    bEditable = pDoc->IsEditActionAllowed(eAction, rMark, nRow1, nRow2);
+                }
+                break;
+            }
             case FID_INS_CELLSDOWN:
             case SID_ROW_OPERATIONS:
                 bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked();
@@ -239,6 +252,19 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
             case FID_INS_COLUMN:
             case FID_INS_COLUMNS_BEFORE:        // insert columns
             case FID_INS_COLUMNS_AFTER:
+            {
+                sc::ColRowEditAction eAction = sc::ColRowEditAction::InsertColumnsBefore;
+                if (nWhich == FID_INS_COLUMNS_AFTER)
+                    eAction = sc::ColRowEditAction::InsertColumnsAfter;
+
+                bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
+                if (!bEditable && nRow1 == 0 && nRow2 == MAXROW)
+                {
+                    // See if row insertions are allowed.
+                    bEditable = pDoc->IsEditActionAllowed(eAction, rMark, nCol1, nCol2);
+                }
+                break;
+            }
             case FID_INS_CELLSRIGHT:
             case SID_COLUMN_OPERATIONS:
                 bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
diff --git a/sc/uiconfig/scalc/ui/protectsheetdlg.ui b/sc/uiconfig/scalc/ui/protectsheetdlg.ui
index 63f35c1f5dfa..0b520b9752ae 100644
--- a/sc/uiconfig/scalc/ui/protectsheetdlg.ui
+++ b/sc/uiconfig/scalc/ui/protectsheetdlg.ui
@@ -248,6 +248,54 @@
                         <property name="position">1</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkLabel" id="insert-columns">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Insert columns</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="insert-rows">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Insert rows</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="delete-columns">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Delete columns</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="delete-rows">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Delete rows</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index c22e32173314..a7d242b366dd 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -606,6 +606,8 @@ namespace xmloff { namespace token {
         TOKEN( "default-style-name",              XML_DEFAULT_STYLE_NAME ),
         TOKEN( "degree",                          XML_DEGREE ),
         TOKEN( "delay",                           XML_DELAY ),
+        TOKEN( "delete-columns",                  XML_DELETE_COLUMNS ),
+        TOKEN( "delete-rows",                     XML_DELETE_ROWS ),
         TOKEN( "deletion",                        XML_DELETION ),
         TOKEN( "deletions",                       XML_DELETIONS ),
         TOKEN( "denomalign"       ,               XML_DENOMALIGN ),
@@ -1039,6 +1041,8 @@ namespace xmloff { namespace token {
         TOKEN( "information",                     XML_INFORMATION ),
         TOKEN( "initial-creator",                 XML_INITIAL_CREATOR ),
         TOKEN( "inproceedings",                   XML_INPROCEEDINGS ),
+        TOKEN( "insert-columns",                  XML_INSERT_COLUMNS ),
+        TOKEN( "insert-rows",                     XML_INSERT_ROWS ),
         TOKEN( "insertion",                       XML_INSERTION ),
         TOKEN( "insertion-cut-off",               XML_INSERTION_CUT_OFF ),
         TOKEN( "insertion-position",              XML_INSERTION_POSITION ),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 70386737e4ed..e874670378bb 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -529,6 +529,8 @@ default-style
 default-style-name
 degree
 delay
+delete-columns
+delete-rows
 deletion
 deletions
 denomalign
@@ -957,6 +959,8 @@ index-title-template
 information
 initial-creator
 inproceedings
+insert-columns
+insert-rows
 insertion
 insertion-cut-off
 insertion-position


More information about the Libreoffice-commits mailing list