diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-01-11 12:12:09 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-01-11 12:53:22 -0500 |
commit | feef29286f0a7c6abd512a07fce9ef48327e0a78 (patch) | |
tree | fa8d667cfed7c86583062f37a20f02f907866c82 /sc | |
parent | ac56d9373a66378a04048993ed5aec65cf39f149 (diff) |
Create a self-update variant of DataPilotUpdate().
DataPilotUpdate() is getting more and more complicated, with so many
branches. Since self-updating a pivot table object is common, let's
create a variant just for that. This variant has much less branching.
Change-Id: I75b0512258a09961ef13516d8d9bc8a2939287e1
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/ui/docshell/dbdocfun.cxx | 143 | ||||
-rw-r--r-- | sc/source/ui/inc/dbdocfun.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/dbfunc3.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin2.cxx | 2 |
4 files changed, 145 insertions, 4 deletions
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 3b1db2f05e7a..403ecd3a94df 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -50,6 +50,7 @@ #include "progress.hxx" #include <set> +#include <memory> using namespace ::com::sun::star; @@ -1448,6 +1449,144 @@ bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb return bDone; } +bool ScDBDocFunc::UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi) +{ + ScDocShellModificator aModificator( rDocShell ); + WaitObject aWait( rDocShell.GetActiveDialogParent() ); + + std::auto_ptr<ScDocument> pOldUndoDoc; + std::auto_ptr<ScDocument> pNewUndoDoc; + + ScDPObject aUndoDPObj(rDPObj); // For undo or revert on failure. + + ScDocument* pDoc = rDocShell.GetDocument(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = false; + + if (!rDocShell.IsEditable() || pDoc->GetChangeTrack()) + { + // not recorded -> disallow + //! different error messages? + if (!bApi) + rDocShell.ErrorMessage(STR_PROTECTIONERR); + + return false; + } + + { + ScEditableTester aTester(pDoc, rDPObj.GetOutRange()); + if (!aTester.IsEditable()) + { + if (!bApi) + rDocShell.ErrorMessage(aTester.GetMessageId()); + + return false; + } + } + + if (bRecord) + { + ScRange aRange = rDPObj.GetOutRange(); + SCTAB nTab = aRange.aStart.Tab(); + pOldUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pOldUndoDoc->InitUndo( pDoc, nTab, nTab ); + pDoc->CopyToDocument(aRange, IDF_ALL, false, pOldUndoDoc.get()); + } + + rDPObj.SetAllowMove(false); + rDPObj.ReloadGroupTableData(); + if (!rDPObj.SyncAllDimensionMembers()) + return false; + + rDPObj.InvalidateData(); // before getting the new output area + + // make sure the table has a name (not set by dialog) + if (rDPObj.GetName().isEmpty()) + rDPObj.SetName( pDoc->GetDPCollection()->CreateNewName() ); + + bool bOverflow = false; + ScRange aNewOut = rDPObj.GetNewOutputRange(bOverflow); + + //! test for overlap with other data pilot tables + const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc(); + if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(aNewOut)) + { + ScRange aOldRange = rDPObj.GetOutRange(); + SCsROW nDiff = aOldRange.aStart.Row()-aNewOut.aStart.Row(); + aNewOut.aStart.SetRow( aOldRange.aStart.Row() ); + aNewOut.aEnd.SetRow( aNewOut.aEnd.Row()+nDiff ); + if (!ValidRow(aNewOut.aStart.Row()) || !ValidRow(aNewOut.aEnd.Row())) + bOverflow = true; + } + + if (bOverflow) + { + // like with STR_PROTECTIONERR, use undo to reverse everything + OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" ); + + if (!bApi) + rDocShell.ErrorMessage(STR_PIVOT_ERROR); + + rDPObj = aUndoDPObj; + return false; + } + + { + ScEditableTester aTester(pDoc, aNewOut); + if (!aTester.IsEditable()) + { + // destination area isn't editable + //! reverse everything done so far, don't proceed + + if (!bApi) + rDocShell.ErrorMessage(aTester.GetMessageId()); + + rDPObj = aUndoDPObj; + return false; + } + } + + // test if new output area is empty except for old area + if (!bApi) + { + if (!lcl_EmptyExcept(pDoc, aNewOut, rDPObj.GetOutRange())) + { + QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) ); + if (aBox.Execute() == RET_NO) + { + rDPObj = aUndoDPObj; + return false; + } + } + } + + if (bRecord) + { + SCTAB nTab = aNewOut.aStart.Tab(); + pNewUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pNewUndoDoc->InitUndo( pDoc, nTab, nTab ); + pDoc->CopyToDocument(aNewOut, IDF_ALL, false, pNewUndoDoc.get()); + } + + rDPObj.Output(aNewOut.aStart); + rDocShell.PostPaintGridAll(); //! only necessary parts + + if (bRecord) + { + std::auto_ptr<SfxUndoAction> pAction( + new ScUndoDataPilot( + &rDocShell, pOldUndoDoc.release(), pNewUndoDoc.release(), &aUndoDPObj, &rDPObj, false)); + + rDocShell.GetUndoManager()->AddUndoAction(pAction.release()); + } + + // notify API objects + pDoc->BroadcastUno( ScDataPilotModifiedHint(rDPObj.GetName()) ); + aModificator.SetDocumentModified(); + return true; +} + sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi) { ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection(); @@ -1465,7 +1604,7 @@ sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi) ScDPObject* pObj = *it; // This action is intentionally not undoable since it modifies cache. - DataPilotUpdate(pObj, pObj, false, bApi); + UpdatePivotTable(*pObj, false, bApi); } return 0; @@ -1502,7 +1641,7 @@ void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj) } // This action is intentionally not undoable since it modifies cache. - DataPilotUpdate(pObj, pObj, false, false); + UpdatePivotTable(*pObj, false, false); } } diff --git a/sc/source/ui/inc/dbdocfun.hxx b/sc/source/ui/inc/dbdocfun.hxx index 3cf22427a90e..c302d5c532ce 100644 --- a/sc/source/ui/inc/dbdocfun.hxx +++ b/sc/source/ui/inc/dbdocfun.hxx @@ -92,6 +92,8 @@ public: bool DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj, bool bRecord, bool bApi, bool bAllowMove = false ); + bool UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi); + /** * Reload the referenced pivot cache, and refresh all pivot tables that * reference the cache. diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 84754c2c94cc..ff768cf501eb 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -1596,7 +1596,7 @@ void ScDBFunc::DataPilotInput( const ScAddress& rPos, const rtl::OUString& rStri // apply changes ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); pDPObj->SetSaveData( aData ); - aFunc.DataPilotUpdate( pDPObj, pDPObj, true, false ); + aFunc.UpdatePivotTable(*pDPObj, true, false); } else { diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx index 3ec36a25cef9..94ed3e7b23c1 100644 --- a/sc/source/ui/view/gridwin2.cxx +++ b/sc/source/ui/view/gridwin2.cxx @@ -591,7 +591,7 @@ void ScGridWindow::UpdateDPFromFieldPopupMenu() pDim->UpdateMemberVisibility(aResult); ScDBDocFunc aFunc(*pViewData->GetDocShell()); - aFunc.DataPilotUpdate(pDPObj, pDPObj, true, false); + aFunc.UpdatePivotTable(*pDPObj, true, false); } void ScGridWindow::UpdateVisibleRange() |