[Libreoffice-commits] core.git: Branch 'feature/unitver' - 3 commits - sc/inc sc/qa sc/source
Andrzej Hunt
andrzej at ahunt.org
Mon Jun 1 10:11:33 PDT 2015
Rebased ref, commits from common ancestor:
commit 77971aa38eca3a52d559bfa5b9f7344e7e710d2b
Author: Andrzej Hunt <andrzej at ahunt.org>
Date: Mon Jun 1 18:10:29 2015 +0100
Add tests for output unit verification.
Change-Id: Ia273a64fdbb5e1fe57f41679e9d77e0df78987de
diff --git a/sc/qa/unit/units.cxx b/sc/qa/unit/units.cxx
index 4e9c2f9..e2ad7cc 100644
--- a/sc/qa/unit/units.cxx
+++ b/sc/qa/unit/units.cxx
@@ -205,6 +205,14 @@ void UnitsTest::testUnitVerification() {
setNumberFormatUnit(address, "m");
mpDoc->SetValue(address, 1);
+ // 6th column: header annotation for output verification
+ address = ScAddress(5, 0, 0);
+ mpDoc->SetString(address, "foobar [cm]");
+
+ // 7th column: another header annotation
+ address = ScAddress(6, 0, 0);
+ mpDoc->SetString(address, "foobar (cm/s)");
+
ScFormulaCell* pCell;
ScTokenArray* pTokens;
@@ -359,6 +367,52 @@ void UnitsTest::testUnitVerification() {
pTokens = pCell->GetCode();
CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
}
+
+
+ // Test output unit verification (i.e. using header annotations)
+
+ // header in [cm], cell with cm
+ address = ScAddress(5, 1, 0);
+ mpDoc->SetFormula(address, "=A1");
+ pCell = mpDoc->GetFormulaCell(address);
+ pTokens = pCell->GetCode();
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+
+
+ // header in [cm], cell with 100*cm
+ address.IncRow();
+ mpDoc->SetFormula(address, "=100*A1");
+ pCell = mpDoc->GetFormulaCell(address);
+ pTokens = pCell->GetCode();
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_OUTPUT_SCALING);
+
+ // header in [cm], cell with kg
+ address.IncRow();
+ mpDoc->SetFormula(address, "=B1");
+ pCell = mpDoc->GetFormulaCell(address);
+ pTokens = pCell->GetCode();
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_OUTPUT_INCOMPATIBLE);
+
+ // header in [cm], cell with m
+ address.IncRow();
+ mpDoc->SetFormula(address, "=E1");
+ pCell = mpDoc->GetFormulaCell(address);
+ pTokens = pCell->GetCode();
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_OUTPUT_SCALING);
+
+ // header in [cm], cell with 100*m
+ address.IncRow();
+ mpDoc->SetFormula(address, "=100*E1");
+ pCell = mpDoc->GetFormulaCell(address);
+ pTokens = pCell->GetCode();
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+
+ // header in (cm/s), formula resulting in cm/s
+ address = ScAddress(6, 1, 0);
+ mpDoc->SetFormula(address, "=A1/C1");
+ pCell = mpDoc->GetFormulaCell(address);
+ pTokens = pCell->GetCode();
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
}
void UnitsTest::testUnitFromFormatStringExtraction() {
commit 80c15be131e8bcb9063fd93a5aa2d32a36c8c72b
Author: Andrzej Hunt <andrzej at ahunt.org>
Date: Mon Jun 1 17:53:48 2015 +0100
Return status for formula errors
Returning a status (instead of a boolean) means we will be able to
print better error messages for the user in future.
Change-Id: I0b08913267fedb5735112acc7427156e07e32b31
diff --git a/sc/inc/units.hxx b/sc/inc/units.hxx
index b428d40..411fb84 100644
--- a/sc/inc/units.hxx
+++ b/sc/inc/units.hxx
@@ -38,11 +38,26 @@ struct RangeUnits {
bool compatible;
};
+/**
+ * The unit correctness status for a formula.
+ * UNKNOWN denotes that the units could not be verified
+ * (this can occur if e.g. an unsupported operator or formula
+ * is used).
+ */
+enum class FormulaStatus {
+ VERIFIED,
+ UNKNOWN,
+ ERROR_INPUT_SCALING,
+ ERROR_INPUT_INCOMPATIBLE,
+ ERROR_OUTPUT_SCALING,
+ ERROR_OUTPUT_INCOMPATIBLE
+};
+
class Units {
public:
static ::boost::shared_ptr< Units > GetUnits();
- virtual bool verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) = 0;
+ virtual FormulaStatus verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) = 0;
/*
* Split the input into value and unit, where rInput == rValue + rUnit.
diff --git a/sc/qa/unit/units.cxx b/sc/qa/unit/units.cxx
index b35cd40..4e9c2f9 100644
--- a/sc/qa/unit/units.cxx
+++ b/sc/qa/unit/units.cxx
@@ -213,65 +213,65 @@ void UnitsTest::testUnitVerification() {
mpDoc->SetFormula(address, "=A1+A2");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
- // Test that addition of different units fails
+ // Test that addition of different units fails - incompatible types
address = ScAddress(0, 6, 0);
mpDoc->SetFormula(address, "=A1+B1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// Test that addition and multiplication works (i.e. kg*s+kg*s)
address = ScAddress(0, 7, 0);
mpDoc->SetFormula(address, "=A1*B1+A2*B2");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// Test another combination (i.e. cm/s+'cm/s')
address = ScAddress(0, 8, 0);
mpDoc->SetFormula(address, "=A1/C1+D1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// Test that another combination fails (cm*kg/s+'cm/s')
address = ScAddress(0, 9, 0);
mpDoc->SetFormula(address, "=A1*B1/C1+D1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// Test that addition of scaled units works (cm + 100*m)
address = ScAddress(0, 10, 0);
mpDoc->SetFormula(address, "=A1+100*E1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// 10cm + 100*1m = 110cm
- CPPUNIT_ASSERT(mpDoc->GetValue(address) == 110);
+ CPPUNIT_ASSERT_EQUAL(mpDoc->GetValue(address), 110.0);
// But addition of them unscaled fails (cm + m)
address = ScAddress(0, 11, 0);
mpDoc->SetFormula(address, "=A1+E1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_SCALING);
// As does wrong scaling (cm+m/50)
address = ScAddress(0, 12, 0);
mpDoc->SetFormula(address, "=A1+E1/50");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_SCALING);
// And scaling doesn't help when adding incompatible units (kg + 100*m)
address = ScAddress(0, 13, 0);
mpDoc->SetFormula(address, "=B1+100*E1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// Test Ranges:
// SUM("kg")
@@ -279,49 +279,49 @@ void UnitsTest::testUnitVerification() {
mpDoc->SetFormula(address, "=SUM(B1:B3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// SUM("cm"&"kg")
address.IncRow();
mpDoc->SetFormula(address, "=SUM(A1:B3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// SUM("cm"&"kg") - multiple ranges
address.IncRow();
mpDoc->SetFormula(address, "=SUM(A1:A3,B1:B3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// SUM("cm")+SUM("kg")
address.IncRow();
mpDoc->SetFormula(address, "=SUM(A1:A3)+SUM(B1:B3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// SUM("cm")/SUM("s")+SUM("cm/s")
address.IncRow();
mpDoc->SetFormula(address, "=SUM(A1:A3)/SUM(C1:C3)+SUM(D1:D3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// PRODUCT("cm/","s")+"cm"
address.IncRow();
mpDoc->SetFormula(address, "=PRODUCT(C1:D1)+A1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// PRODUCT("cm/","s")+"kg"
address.IncRow();
mpDoc->SetFormula(address, "=PRODUCT(C1:D1)+B1");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// Test that multiple arguments of mixed types work too
// Adding multiple cells from one column is ok
@@ -329,7 +329,7 @@ void UnitsTest::testUnitVerification() {
mpDoc->SetFormula(address, "=SUM(A1,A2:A3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// But mixing the columns fails because of mixed units
// (This test is primarily to ensure that we can handle arbitrary numbers
@@ -338,7 +338,7 @@ void UnitsTest::testUnitVerification() {
mpDoc->SetFormula(address, "=SUM(A1,A2:A3,B1:B3,C1,C2,C3)");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
// Do a quick sanity check for all the other supported functions
// The following all expect identically united inputs, and should
@@ -350,14 +350,14 @@ void UnitsTest::testUnitVerification() {
mpDoc->SetFormula(address, "=" + aFunc + "(A1:A2)+A3");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
// FOO(cm) + kg
address.IncRow();
mpDoc->SetFormula(address, "=" + aFunc + "(A1:A2)+B3");
pCell = mpDoc->GetFormulaCell(address);
pTokens = pCell->GetCode();
- CPPUNIT_ASSERT(!mpUnitsImpl->verifyFormula(pTokens, address, mpDoc));
+ CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_INCOMPATIBLE);
}
}
diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index 567265b..84d5c0e 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -105,7 +105,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
switch (aOpCode) {
case ocNot:
if (!pUnit.isDimensionless()) {
- return { UnitsStatus::UNITS_INVALID, boost::none };
+ return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
}
// We just keep the same unit (in this case no unit) so can
// fall through.
@@ -147,10 +147,12 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
// The two units are identical, hence we can return either.
pOut = pFirstUnit;
SAL_INFO("sc.units", "verified equality for unit " << pFirstUnit);
+ } else if (pFirstUnit.areConvertibleTo(pSecondUnit)) {
+ return { UnitsStatus::UNITS_INVALID_SCALING, boost::none };
} else {
- return { UnitsStatus::UNITS_INVALID, boost::none };
- // TODO: notify/link UI.
+ return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
}
+
break;
case ocMul:
pOut = pFirstUnit * pSecondUnit;
@@ -213,8 +215,13 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
aFirstUnit = aUnitsStack.top();
} else {
UtUnit aCurrentUnit(aUnitsStack.top());
+
if (aFirstUnit.get() != aCurrentUnit) {
- return { UnitsStatus::UNITS_INVALID, boost::none };
+ if (aFirstUnit.get().areConvertibleTo(aCurrentUnit)) {
+ return { UnitsStatus::UNITS_INVALID_SCALING, boost::none };
+ } else {
+ return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
+ }
}
}
aUnitsStack.pop();
@@ -226,8 +233,13 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
aFirstUnit = getUnitForCell(aIt.GetPos(), pDoc);
} else {
UtUnit aCurrentUnit = getUnitForCell(aIt.GetPos(), pDoc);
+
if (aFirstUnit.get() != aCurrentUnit) {
- return { UnitsStatus::UNITS_INVALID, boost::none };
+ if (aFirstUnit.get().areConvertibleTo(aCurrentUnit)) {
+ return { UnitsStatus::UNITS_INVALID_SCALING, boost::none };
+ } else {
+ return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
+ }
}
}
} while (aIt.next());
@@ -510,8 +522,7 @@ HeaderUnitDescriptor UnitsImpl::findHeaderUnitForCell(const ScAddress& rCellAddr
return { false, UtUnit(), boost::optional< ScAddress >(), "", -1 };
}
-// getUnitForRef: check format -> if not in format, use more complicated method? (Format overrides header definition)
-bool UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) {
+FormulaStatus UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) {
#if DEBUG_FORMULA_COMPILER
pArray->Dump();
#endif
@@ -532,7 +543,7 @@ bool UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAdd
// unparseable formulas?
// (or even have a "can't be verified" state too?)
// see below for more.x
- return false;
+ return FormulaStatus::UNKNOWN;
}
aStack.push( { RAUSItemType::UNITS, aUnit } );
@@ -551,11 +562,13 @@ bool UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAdd
UnitsResult aResult = getOutputUnitsForOpCode(aStack, pToken, pDoc);
switch (aResult.status) {
- case UnitsStatus::UNITS_INVALID:
- return false;
+ case UnitsStatus::UNITS_INVALID_SCALING:
+ return FormulaStatus::ERROR_INPUT_SCALING;
+ case UnitsStatus::UNITS_INVALID_INCOMPATIBLE:
+ return FormulaStatus::ERROR_INPUT_INCOMPATIBLE;
case UnitsStatus::UNITS_UNKNOWN:
// Unsupported hence we stop processing.
- return true;
+ return FormulaStatus::UNKNOWN;
case UnitsStatus::UNITS_VALID:
assert(aResult.units); // ensure that we have the optional unit
assert(aResult.units->isValid());
@@ -583,26 +596,30 @@ bool UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAdd
// was correct.
// TODO: maybe we should have a "unverified" return state instead?
SAL_WARN("sc.units", "Unrecognised token type " << pToken->GetType());
- return true;
+ return FormulaStatus::UNKNOWN;
}
}
if (aStack.size() != 1) {
SAL_WARN("sc.units", "Wrong number of units on stack, should be 1, actual number: " << aStack.size());
- return false;
+ return FormulaStatus::UNKNOWN;
} else if (aStack.top().type != RAUSItemType::UNITS) {
SAL_WARN("sc.units", "End of verification: item on stack does not contain units");
- return false;
+ return FormulaStatus::UNKNOWN;
}
HeaderUnitDescriptor aHeader = findHeaderUnitForCell(rFormulaAddress, pDoc);
UtUnit aResultUnit = boost::get< UtUnit>(aStack.top().item);
if (aHeader.valid && aHeader.unit != aResultUnit) {
- return false;
+ if (aHeader.unit.areConvertibleTo(aResultUnit)) {
+ return FormulaStatus::ERROR_OUTPUT_SCALING;
+ } else {
+ return FormulaStatus::ERROR_OUTPUT_INCOMPATIBLE;
+ }
}
- return true;
+ return FormulaStatus::VERIFIED;
}
bool IsDigit(sal_Unicode c) {
diff --git a/sc/source/core/units/unitsimpl.hxx b/sc/source/core/units/unitsimpl.hxx
index 176a34d..b0fb137 100644
--- a/sc/source/core/units/unitsimpl.hxx
+++ b/sc/source/core/units/unitsimpl.hxx
@@ -45,7 +45,8 @@ namespace test {
enum class UnitsStatus {
UNITS_VALID,
UNITS_UNKNOWN,
- UNITS_INVALID
+ UNITS_INVALID_SCALING,
+ UNITS_INVALID_INCOMPATIBLE
};
/**
@@ -91,7 +92,7 @@ public:
UnitsImpl();
virtual ~UnitsImpl();
- virtual bool verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) SAL_OVERRIDE;
+ virtual FormulaStatus verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) SAL_OVERRIDE;
virtual bool splitUnitsFromInputString(const OUString& rInput, OUString& rValue, OUString& rUnit) SAL_OVERRIDE;
virtual bool isCellConversionRecommended(const ScAddress& rCellAddress,
ScDocument* pDoc,
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index a6b36b8..5574fcf 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -58,6 +58,10 @@ namespace sc {
struct ColRowSpan;
+namespace units {
+enum class FormulaStatus;
+}
+
}
namespace com { namespace sun { namespace star { namespace datatransfer { class XTransferable; } } } }
@@ -373,7 +377,9 @@ private:
void CopyAutoSpellData( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount );
- void NotifyUnitErrorInFormula( const ScAddress& rAddress, ScDocument* pDoc );
+ void NotifyUnitErrorInFormula( const ScAddress& rAddress,
+ ScDocument* pDoc,
+ const sc::units::FormulaStatus& rStatus);
DECL_LINK( EditUnitErrorFormulaHandler, PushButton* );
void NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index b156587..b9a08c3 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -84,6 +84,8 @@
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
+using namespace sc::units;
+
static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDocShell *pDocSh )
{
if( pCondFmt )
@@ -467,8 +469,9 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
}
#ifdef ENABLE_CALC_UNITVERIFICATION
- boost::shared_ptr< sc::units::Units > pUnits = sc::units::Units::GetUnits();
- if ( pUnits->verifyFormula( pArr, aPos, pDoc ) )
+ boost::shared_ptr< Units > pUnits = Units::GetUnits();
+ FormulaStatus aStatus = pUnits->verifyFormula( pArr, aPos, pDoc );
+ if ( aStatus == FormulaStatus::VERIFIED || aStatus == FormulaStatus::UNKNOWN )
{
SAL_INFO( "sc.units", "verification successful" );
@@ -484,7 +487,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
else
{
SAL_INFO( "sc.units", "verification failed" );
- NotifyUnitErrorInFormula( aPos, pDoc );
+ NotifyUnitErrorInFormula( aPos, pDoc, aStatus );
}
#endif
} while ( bAgain );
@@ -580,7 +583,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
}
#ifdef ENABLE_CALC_UNITVERIFICATION
- boost::shared_ptr< sc::units::Units > pUnits = sc::units::Units::GetUnits();
+ boost::shared_ptr< Units > pUnits = Units::GetUnits();
OUString sHeaderUnit, sCellUnit;
ScAddress aHeaderAddress;
@@ -2838,8 +2841,10 @@ void ScViewFunc::UpdateSelectionArea( const ScMarkData& rSel, ScPatternAttr* pAt
pTabViewShell->AdjustBlockHeight(false, const_cast<ScMarkData*>(&rSel));
}
-void ScViewFunc::NotifyUnitErrorInFormula( const ScAddress& rAddress, ScDocument* pDoc )
+void ScViewFunc::NotifyUnitErrorInFormula( const ScAddress& rAddress, ScDocument* pDoc, const FormulaStatus& rStatus )
{
+ (void) rStatus;
+
SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
// We use the cell address as the infobar id to allow us to easily get back to the
@@ -2967,7 +2972,7 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
// Do conversion first, and only then remove the infobar as we need data from the infobar
// (specifically from the pushbutton) to do the conversion.
#ifdef ENABLE_CALC_UNITVERIFICATION
- boost::shared_ptr< sc::units::Units > pUnits = sc::units::Units::GetUnits();
+ boost::shared_ptr< Units > pUnits = Units::GetUnits();
ScDocShellModificator aModificator( *pButton->mpDocSh );
commit 1172fbb2707c5c9d08f4ae2dc9584000c2a13246
Author: Andrzej Hunt <andrzej at ahunt.org>
Date: Mon Jun 1 17:51:48 2015 +0100
Invalid formulas can't have unit correctness verified.
Formulas that can't be processed will already be treated as invalid,
we shouldn't additionally complain about unit verification in this case.
Change-Id: I0556bf76b6e2343cdf27ec53669e6fd78da9280b
diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index e764aad..567265b 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -95,10 +95,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
if (nOpCode >= SC_OPCODE_START_UN_OP &&
nOpCode < SC_OPCODE_STOP_UN_OP) {
- if (rStack.size() == 0) {
- SAL_WARN("sc.units", "Single item opcode failed (no stack items, or range used)");
- return { UnitsStatus::UNITS_INVALID, boost::none };
- } else if (rStack.top().type != RAUSItemType::UNITS) {
+ if ((rStack.size() == 0) || (rStack.top().type != RAUSItemType::UNITS)) {
return { UnitsStatus::UNITS_UNKNOWN, boost::none };
}
@@ -129,12 +126,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
} else if (nOpCode >= SC_OPCODE_START_BIN_OP &&
nOpCode < SC_OPCODE_STOP_BIN_OP) {
- if (rStack.size() < 2) {
- SAL_WARN("sc.units", "less than two items on stack when attempting binary operation");
- return { UnitsStatus::UNITS_INVALID, boost::none };
- }
-
- if (rStack.top().type != RAUSItemType::UNITS) {
+ if ((rStack.size() < 2) || (rStack.top().type != RAUSItemType::UNITS)) {
return { UnitsStatus::UNITS_UNKNOWN, boost::none };
}
UtUnit pSecondUnit = boost::get<UtUnit>(rStack.top().item);
More information about the Libreoffice-commits
mailing list