sc/inc/conditio.hxx | 2 sc/inc/rangelst.hxx | 8 sc/source/core/data/conditio.cxx | 22 ++ sc/source/core/data/table2.cxx | 11 + sc/source/core/tool/rangelst.cxx | 329 ++++++++++++++++++++++++++++++ sc/source/filter/oox/condformatbuffer.cxx | 1 sc/source/ui/condformat/condformatdlg.cxx | 4 7 files changed, 375 insertions(+), 2 deletions(-)
New commits: commit 10efe1bcedfa450e95cbc3f08642d239ba2ab579 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Aug 31 04:29:49 2012 +0200 handle missing cond format entries more gracefully, related fdo#52340 Change-Id: Id1cf7d99a13c04541e87ad00c5418dd4f766d268 diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 12c9212..afb9c6b 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -669,6 +669,12 @@ void ScTable::CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCRO if (aOldIdToNewId.find(nId) == aOldIdToNewId.end()) { ScConditionalFormat* pFormat = pOldCondFormatList->GetFormat(nId); + if(!pFormat) + { + // may happen in some strange circumstances where cell storage and + // cond format storage are not in sync + continue; + } ScConditionalFormat* pNewFormat = pFormat->Clone(pDocument); pNewFormat->SetKey(0); //not in list => create entries in both maps and new format commit 3cf91a21fc5089fb7f051bf8a04d2049da88179f Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Aug 31 04:25:47 2012 +0200 use Red as error color for cond format dlg Change-Id: I1526a8d1f2999742f28600e771891e1489d62f4b diff --git a/sc/source/ui/condformat/condformatdlg.cxx b/sc/source/ui/condformat/condformatdlg.cxx index a84103c..1f9d638 100644 --- a/sc/source/ui/condformat/condformatdlg.cxx +++ b/sc/source/ui/condformat/condformatdlg.cxx @@ -836,7 +836,7 @@ IMPL_LINK_NOARG(ScCondFrmtEntry, TypeListHdl) SetHeight(); return 0; } - +#include <iostream> IMPL_LINK(ScCondFrmtEntry, EdModifyHdl, Edit*, pEdit) { rtl::OUString aFormula = pEdit->GetText(); @@ -845,7 +845,7 @@ IMPL_LINK(ScCondFrmtEntry, EdModifyHdl, Edit*, pEdit) boost::scoped_ptr<ScTokenArray> mpCode(aComp.CompileString(aFormula)); if(mpCode->GetCodeError()) { - pEdit->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor()); + pEdit->SetControlBackground(COL_RED); } else { commit a3c4ee1653166ee2ac1f1b9d65ff1065b6288ebc Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Aug 31 04:02:10 2012 +0200 update cond formats for deleting, moving and cut&paste Change-Id: I52987e957918853bcd1abd1460c6166b52454d62 diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx index 4967e82..9890758 100644 --- a/sc/inc/conditio.hxx +++ b/sc/inc/conditio.hxx @@ -290,6 +290,7 @@ public: void CompileXML(); void UpdateReference( UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); + void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ); void RenameCellStyle( const String& rOld, const String& rNew ); @@ -349,6 +350,7 @@ public: const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); void RenameCellStyle( const String& rOld, const String& rNew ); void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ); + void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); void SourceChanged( const ScAddress& rAddr ); diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 4a842fb..17483c3 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -1471,6 +1471,12 @@ void ScConditionalFormat::UpdateReference( UpdateRefMode eUpdateRefMode, itr->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz); } +void ScConditionalFormat::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + SCTAB nTab = maRanges[0]->aStart.Tab(); + maRanges.DeleteArea( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); +} + void ScConditionalFormat::RenameCellStyle(const String& rOld, const String& rNew) { for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr) @@ -1626,6 +1632,22 @@ void ScConditionalFormatList::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ) itr->UpdateMoveTab( nOldPos, nNewPos ); } +void ScConditionalFormatList::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + for( iterator itr = begin(); itr != end(); ++itr) + itr->DeleteArea( nCol1, nRow1, nCol2, nRow2 ); + + // need to check which must be deleted + iterator itr = begin(); + while(itr != end()) + { + if(itr->GetRange().empty()) + maConditionalFormats.erase(itr++); + else + ++itr; + } +} + void ScConditionalFormatList::SourceChanged( const ScAddress& rAddr ) { for( iterator itr = begin(); itr != end(); ++itr) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index a2be5f5..12c9212 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -533,6 +533,8 @@ void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal aPattern.GetItemSet().Put( ScProtectionAttr( false ) ); ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern ); } + + mpCondFormatList->DeleteArea( nCol1, nRow1, nCol2, nRow2 ); } if (nDelFlag & IDF_NOTE) @@ -561,6 +563,9 @@ void ScTable::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark ) ScRange* pRange = aRangeList[i]; if (nDelFlag & IDF_NOTE && pRange) maNotes.erase(pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row(), true); + + if(pRange && pRange->aStart.Tab() == nTab) + mpCondFormatList->DeleteArea( pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row() ); } // commit 7222a571d0d458810c1b23871f8b91491db4462d Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Aug 31 03:59:51 2012 +0200 add ScRangeList::DeleteArea DeleteArea can handle ranges that are deleting parts of an existing range Currently this code only supports a 2D deletion Change-Id: I1c514437fdd09fea99f5c4dcf97b8375dcc53b40 diff --git a/sc/inc/rangelst.hxx b/sc/inc/rangelst.hxx index 0c51506..74bb7be 100644 --- a/sc/inc/rangelst.hxx +++ b/sc/inc/rangelst.hxx @@ -68,6 +68,12 @@ public: SCsTAB nDz ); + /** For now this method assumes that nTab1 == nTab2 + * The algorithm will be much more complicated if nTab1 != nTab2 + */ + void DeleteArea( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, + SCROW nRow2, SCTAB nTab2 ); + const ScRange* Find( const ScAddress& ) const; ScRange* Find( const ScAddress& ); bool operator==( const ScRangeList& ) const; @@ -93,6 +99,8 @@ public: private: ::std::vector<ScRange*> maRanges; + typedef std::vector<ScRange*>::iterator iterator; + typedef std::vector<ScRange*>::const_iterator const_iterator; }; SV_DECL_IMPL_REF( ScRangeList ); diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx index 4ff6ff0..14cf8b4 100644 --- a/sc/source/core/tool/rangelst.cxx +++ b/sc/source/core/tool/rangelst.cxx @@ -39,6 +39,8 @@ #include "compiler.hxx" #include "stlalgorithm.hxx" +#include <iostream> + using ::std::vector; using ::std::advance; using ::std::find_if; @@ -62,6 +64,20 @@ private: }; template<typename T> +class FindRangeIn : public ::std::unary_function<bool, ScRange*> +{ +public: + FindRangeIn(const T& rTest) : mrTest(rTest) {} + FindRangeIn(const FindRangeIn& r) : mrTest(r.mrTest) {} + bool operator() (const ScRange* pRange) const + { + return mrTest.In(*pRange); + } +private: + const T& mrTest; +}; + +template<typename T> class FindIntersectingRange : public ::std::unary_function<bool, ScRange*> { public: @@ -436,6 +452,319 @@ bool ScRangeList::UpdateReference( return bChanged; } +namespace { + // + // r.aStart.X() <= p.aStart.X() && r.aEnd.X() >= p.aEnd.X() + // && ( r.aStart.Y() <= p.aStart.Y() || r.aEnd.Y() >= r.aEnd.Y() ) + +template<typename X, typename Y> +bool checkForOneRange( X rStartX, X rEndX, Y rStartY, Y rEndY, + X pStartX, X pEndX, Y pStartY, Y pEndY ) +{ + if( rStartX <= pStartX && rEndX >= pEndX + && ( rStartY <= pStartY || rEndY >= pEndY ) ) + return true; + + return false; +} + +bool handleOneRange( const ScRange& rDeleteRange, ScRange* p ) +{ + ScAddress rDelStart = rDeleteRange.aStart; + ScAddress rDelEnd = rDeleteRange.aEnd; + ScAddress rPStart = p->aStart; + ScAddress rPEnd = p->aEnd; + if(checkForOneRange(rDelStart.Col(), rDelEnd.Col(), rDelStart.Row(), rDelEnd.Row(), + rPStart.Col(), rPEnd.Col(), rPStart.Row(), rPEnd.Row())) + { + // X = Col + // Y = Row + if(rDelStart.Row() <= rPStart.Row()) + { + p->aStart.SetRow(rDelEnd.Row()+1); + } + else if(rDelEnd.Row() >= rPEnd.Row()) + { + p->aEnd.SetRow(rDelStart.Row()-1); + } + + return true; + } + else if(checkForOneRange(rDelStart.Row(), rDelEnd.Row(), rDelStart.Col(), rDelEnd.Col(), + rPStart.Row(), rPEnd.Row(), rPStart.Col(), rPEnd.Col())) + { + // X = Row + // Y = Col + if(rDelStart.Col() <= rPStart.Col()) + p->aStart.SetCol(rDelEnd.Col()+1); + else if(rDelEnd.Col() >= rPEnd.Col()) + p->aEnd.SetCol(rDelStart.Col()-1); + + return true; + } + return false; +} + +template<typename X, typename Y> +bool checkForTwoRangesCase2( X rStartX, X rEndX, Y rStartY, Y rEndY, + X pStartX, X pEndX, Y pStartY, Y pEndY ) +{ + if(rStartY > pStartY && rStartX <= pStartX + && rEndY < pEndY && rEndX >= pEndX) + return true; + + return false; +} + + +bool handleTwoRanges( const ScRange& rDeleteRange, ScRange* p, std::vector<ScRange>& rNewRanges ) +{ + ScAddress rDelStart = rDeleteRange.aStart; + ScAddress rDelEnd = rDeleteRange.aEnd; + ScAddress rPStart = p->aStart; + ScAddress rPEnd = p->aEnd; + SCCOL rStartCol = rDelStart.Col(); + SCCOL rEndCol = rDelEnd.Col(); + SCCOL pStartCol = rPStart.Col(); + SCCOL pEndCol = rPEnd.Col(); + SCROW rStartRow = rDelStart.Row(); + SCROW rEndRow = rDelEnd.Row(); + SCROW pStartRow = rPStart.Row(); + SCROW pEndRow = rPEnd.Row(); + SCTAB nTab = rPStart.Tab(); + if(rStartCol > pStartCol && rStartCol < pEndCol && rEndCol >= pEndCol) + { + if(rStartRow > pStartRow && rStartRow < pEndRow && rEndRow >= pEndRow) + { + ScRange aNewRange( pStartCol, rStartRow, nTab, rStartCol-1, pEndRow, nTab ); + rNewRanges.push_back(aNewRange); + + p->aEnd.SetRow(rStartRow -1); + return true; + } + else if(rEndRow > pStartRow && rEndRow < pEndRow && rStartRow <= pStartRow) + { + ScRange aNewRange( rPStart, ScAddress( pStartCol -1, pEndRow, nTab ) ); + rNewRanges.push_back(aNewRange); + + p->aStart.SetRow(rEndRow+1); + return true; + } + } + else if(rEndCol > pStartCol && rEndCol < pEndCol && rStartCol <= pStartCol) + { + if(rStartRow > pStartRow && rStartRow < pEndRow) + { + ScRange aNewRange( ScAddress( rEndCol +1, rStartRow, nTab ), rPEnd ); + rNewRanges.push_back(aNewRange); + + p->aEnd.SetRow(rStartRow-1); + return true; + } + else if(rEndRow > pStartRow && rEndRow < pEndRow) + { + ScRange aNewRange( rEndCol +1, pStartRow, nTab, rEndCol, rEndRow, nTab ); + rNewRanges.push_back(aNewRange); + + p->aStart.SetRow(rEndRow+1); + return true; + } + } + else if(checkForTwoRangesCase2(rDelStart.Col(), rDelEnd.Col(), rDelStart.Row(), rDelEnd.Row(), + rPStart.Col(), rPEnd.Col(), rPStart.Row(), rPEnd.Row())) + { + ScRange aNewRange( rPStart, ScAddress( rPEnd.Col(), rDelStart.Row() -1, nTab ) ); + rNewRanges.push_back(aNewRange); + + p->aStart.SetRow(rEndRow+1); + return true; + } + else if(checkForTwoRangesCase2(rDelStart.Row(), rDelEnd.Row(), rDelStart.Col(), rDelEnd.Col(), + rPStart.Row(), rPEnd.Row(), rPStart.Col(), rPEnd.Col())) + { + ScRange aNewRange( rPStart, ScAddress( rDelStart.Col() -1, rPEnd.Row(), nTab ) ); + rNewRanges.push_back(aNewRange); + + p->aStart.SetCol(rEndCol+1); + return true; + } + + return false; +} + + // r.aStart.X() > p.aStart.X() && r.aEnd.X() >= p.aEnd.X() + // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y() + // or + // r.aStart.X() <= p.aStart.X() && r.aEnd.X() < p.aEnd.X() + // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y() +template<typename X, typename Y> +bool checkForThreeRanges( X rStartX, X rEndX, Y rStartY, Y rEndY, + X pStartX, X pEndX, Y pStartY, Y pEndY ) +{ + if(rStartX > pStartX && rEndX >= pEndX + && rStartY > pStartY && rEndY < pEndY ) + return true; + else if( rStartX <= pStartX && rEndX < pEndX + && rStartY > pStartY && rEndY < pEndY ) + return true; + + return false; +} + +bool handleThreeRanges( const ScRange& rDeleteRange, ScRange* p, std::vector<ScRange>& rNewRanges ) +{ + ScAddress rDelStart = rDeleteRange.aStart; + ScAddress rDelEnd = rDeleteRange.aEnd; + ScAddress rPStart = p->aStart; + ScAddress rPEnd = p->aEnd; + SCTAB nTab = rDelStart.Tab(); + if(checkForThreeRanges(rDelStart.Col(), rDelEnd.Col(), rDelStart.Row(), rDelEnd.Row(), + rPStart.Col(), rPEnd.Col(), rPStart.Row(), rPEnd.Row())) + { + if(rDelStart.Col() > rPStart.Col()) + { + SCCOL nCol1 = rDelStart.Col(); + + ScRange aNewRange( nCol1, rPStart.Row(), nTab, rPEnd.Col(), rDelStart.Row()-1, nTab); + rNewRanges.push_back(aNewRange); + + aNewRange = ScRange( ScAddress(nCol1, rDelEnd.Row()+1, nTab), rPEnd); + rNewRanges.push_back(aNewRange); + + p->aEnd.SetCol(nCol1-1); + } + else + { + SCCOL nCol1 = rDelEnd.Col(); + + ScRange aNewRange( rPStart, ScAddress( nCol1 - 1, rDelStart.Row() -1, nTab ) ); + rNewRanges.push_back(aNewRange); + + aNewRange = ScRange( rPStart.Col(), rDelEnd.Row() + 1, nTab, rDelEnd.Col() +1, rPEnd.Row(), nTab ); + rNewRanges.push_back(aNewRange); + + p->aStart.SetCol(nCol1+1); + } + return true; + } + else if(checkForThreeRanges(rDelStart.Row(), rDelEnd.Row(), rDelStart.Col(), rDelEnd.Col(), + rPStart.Row(), rPEnd.Row(), rPStart.Col(), rPEnd.Col())) + { + if(rDelStart.Row() > rPStart.Row()) + { + SCROW nRow1 = rDelStart.Row(); + + ScRange aNewRange( rPStart.Col(), nRow1, nTab, rDelStart.Col() -1, rPEnd.Row(), nTab ); + rNewRanges.push_back( aNewRange ); + + aNewRange = ScRange( ScAddress(rDelEnd.Col() +1, nRow1, nTab), rPEnd ); + rNewRanges.push_back( aNewRange ); + + p->aEnd.SetRow(nRow1-1); + } + else + { + SCROW nRow1 = rDelEnd.Row(); + + ScRange aNewRange( rPStart, ScAddress( rDelStart.Col() -1, nRow1, nTab ) ); + rNewRanges.push_back(aNewRange); + + aNewRange = ScRange( rDelEnd.Col() +1, rPStart.Col(), nTab, rPEnd.Col(), nRow1, nTab ); + rNewRanges.push_back( aNewRange ); + + p->aStart.SetRow(nRow1+1); + } + return true; + } + + return false; +} + +bool handleFourRanges( const ScRange& rDelRange, ScRange* p, std::vector<ScRange>& rNewRanges ) +{ + ScAddress rDelStart = rDelRange.aStart; + ScAddress rDelEnd = rDelRange.aEnd; + ScAddress rPStart = p->aStart; + ScAddress rPEnd = p->aEnd; + if( rDelRange.aStart.Col() > p->aStart.Col() && rDelRange.aEnd.Col() < p->aEnd.Col() + && rDelRange.aStart.Row() > p->aStart.Row() && rDelRange.aEnd.Row() < p->aEnd.Row() ) + { + SCTAB nTab = rDelStart.Tab(); + + ScRange aNewRange( ScAddress( rPStart.Col(), rDelEnd.Row(), nTab ), rDelEnd ); + rNewRanges.push_back( aNewRange ); + + aNewRange = ScRange( rPStart.Col(), rDelStart.Row(), nTab, rDelStart.Col() -1, rDelEnd.Row(), nTab ); + rNewRanges.push_back( aNewRange ); + + aNewRange = ScRange( rDelEnd.Col() +1, rDelStart.Row(), nTab, rPEnd.Col(), rDelEnd.Row(), nTab ); + rNewRanges.push_back( aNewRange ); + + rPEnd.SetRow(rDelStart.Row()-1); + p->aEnd = rPEnd; + + return true; + } + + return false; +} + +} + +void ScRangeList::DeleteArea( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) +{ + ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + iterator itrDel = std::remove_if(maRanges.begin(), maRanges.end(), FindRangeIn<ScRange>(aRange)); + for_each(itrDel, maRanges.end(), ScDeleteObjectByPtr<ScRange>()); + maRanges.erase(itrDel, maRanges.end()); + + std::vector<ScRange> aNewRanges; + + for(iterator itr = maRanges.begin(); itr != maRanges.end(); ++itr) + { + // we have two basic cases here: + // 1. Delete area and pRange intersect + // 2. Delete area and pRange are not intersecting + // checking for 2 and if true skip this range + if(!(*itr)->Intersects(aRange)) + continue; + + // We get between 1 and 4 ranges from the difference of the first with the second + + // X either Col or Row and Y then the opposite + // r = deleteRange, p = entry from ScRangeList + + // getting exactly one range is the simple case + // r.aStart.X() <= p.aStart.X() && r.aEnd.X() >= p.aEnd.X() + // && ( r.aStart.Y() <= p.aStart.Y() || r.aEnd.Y() >= r.aEnd.Y() ) + if(handleOneRange( aRange, *itr )) + std::cout << "handled 1 Range case" << std::endl; + + // getting two ranges + // r.aStart.X() + else if(handleTwoRanges( aRange, *itr, aNewRanges )) + std::cout << "handled 2 Ranges " << std::endl; + + // getting 3 ranges + // r.aStart.X() > p.aStart.X() && r.aEnd.X() >= p.aEnd.X() + // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y() + // or + // r.aStart.X() <= p.aStart.X() && r.aEnd.X() < p.aEnd.X() + // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y() + else if(handleThreeRanges( aRange, *itr, aNewRanges )) + std::cout << "handled 3 Ranges" << std::endl; + + // getting 4 ranges + // r.aStart.X() > p.aStart.X() && r.aEnd().X() < p.aEnd.X() + // && r.aStart.Y() > p.aStart.Y() && r.aEnd().Y() < p.aEnd.Y() + else if(handleFourRanges( aRange, *itr, aNewRanges )) + std::cout << "handle 4 Ranges" << std::endl; + } + for(vector<ScRange>::iterator itr = aNewRanges.begin(); itr != aNewRanges.end(); ++itr) + Join( *itr, false); +} + const ScRange* ScRangeList::Find( const ScAddress& rAdr ) const { vector<ScRange*>::const_iterator itr = find_if( commit b20e04a76ac251f782226dcf71983666d8dbe0dd Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Thu Aug 30 02:05:20 2012 +0200 also handle the cond format code for xlsb the new way, fdo#53424 Change-Id: I8d54e5fee29952635c3d4c2d5a12203668e2ff28 diff --git a/sc/source/filter/oox/condformatbuffer.cxx b/sc/source/filter/oox/condformatbuffer.cxx index 702dffb..105dc06 100644 --- a/sc/source/filter/oox/condformatbuffer.cxx +++ b/sc/source/filter/oox/condformatbuffer.cxx @@ -880,6 +880,7 @@ void CondFormat::importCondFormatting( SequenceInputStream& rStrm ) rStrm.skip( 8 ); rStrm >> aRanges; getAddressConverter().convertToCellRangeList( maModel.maRanges, aRanges, getSheetIndex(), true ); + mpFormat = new ScConditionalFormat(0, &getScDocument()); } void CondFormat::importCfRule( SequenceInputStream& rStrm ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits