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
This commit is contained in:
Kohei Yoshida
2013-01-11 12:12:09 -05:00
parent ac56d9373a
commit feef29286f
4 changed files with 145 additions and 4 deletions

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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
{

View File

@@ -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()