diff options
author | Justin Luth <jluth@mail.com> | 2022-08-04 19:52:23 -0400 |
---|---|---|
committer | Justin Luth <jluth@mail.com> | 2023-05-16 01:01:27 +0200 |
commit | 25fed4ae027b9680597ea498c25acc3f854db4bf (patch) | |
tree | 4b8a94073a0c6896ec875a6839ffdb1b04c55cce /sc | |
parent | 67d4fe32713070be5688eef2da9377a91e2f6b81 (diff) |
tdf#79542 xls: applyGroupBox to radiobutton groups
A group box control links radiobuttons together,
and so does a sheet.
No matching unit tests were found.
make CppunitTest_sc_subsequent_filters_test4 \
CPPUNIT_TEST_NAME=testLegacyOptionButtonGroupBox
Change-Id: Ib5b03c68b5218649268f283d11981cc03fe4850a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137838
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls | bin | 0 -> 37376 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_filters_test4.cxx | 20 | ||||
-rw-r--r-- | sc/source/filter/excel/xiescher.cxx | 60 | ||||
-rw-r--r-- | sc/source/filter/inc/xiescher.hxx | 6 |
4 files changed, 86 insertions, 0 deletions
diff --git a/sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls b/sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls Binary files differnew file mode 100644 index 000000000000..1861913020d3 --- /dev/null +++ b/sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls diff --git a/sc/qa/unit/subsequent_filters_test4.cxx b/sc/qa/unit/subsequent_filters_test4.cxx index fcbc02ebe0a3..d6b853607e51 100644 --- a/sc/qa/unit/subsequent_filters_test4.cxx +++ b/sc/qa/unit/subsequent_filters_test4.cxx @@ -116,6 +116,26 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testControlImport) UNO_QUERY_THROW); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testLegacyOptionButtonGroupBox) +{ + createScDoc("xls/tdf79542_radioGroupBox.xls"); + uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xIA->getByIndex(0), + UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xIA_DrawPage(xDrawPageSupplier->getDrawPage(), + UNO_QUERY_THROW); + + OUString sGroupName; + uno::Reference<drawing::XControlShape> xControlShape(xIA_DrawPage->getByIndex(1), + UNO_QUERY_THROW); + uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), + uno::UNO_QUERY_THROW); + // The radio buttons are grouped by GroupBoxes - so the name comes from the group shape name + xPropertySet->getPropertyValue("GroupName") >>= sGroupName; + CPPUNIT_ASSERT_EQUAL(OUString("Casella di gruppo 1"), sGroupName); +} + CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testActiveXOptionButtonGroup) { createScDoc("xlsx/tdf111980_radioButtons.xlsx"); diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index e9a47fada31c..1805b7a26312 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -378,6 +378,11 @@ void XclImpDrawObjBase::SetAnchor( const XclObjAnchor& rAnchor ) mbHasAnchor = true; } +const tools::Rectangle& XclImpDrawObjBase::GetDffRect() const +{ + return maDffRect; +} + void XclImpDrawObjBase::SetDffData( const DffObjData& rDffObjData, const OUString& rObjName, const OUString& rHyperlink, bool bVisible, bool bAutoMargin ) @@ -388,6 +393,7 @@ void XclImpDrawObjBase::SetDffData( maHyperlink = rHyperlink; mbVisible = bVisible; mbAutoMargin = bAutoMargin; + maDffRect = rDffObjData.aChildAnchor; } OUString XclImpDrawObjBase::GetObjName() const @@ -2086,6 +2092,16 @@ void XclImpTbxObjBase::SetDffProperties( const DffPropSet& rDffPropSet ) ::set_flag( maLineData.mnAuto, EXC_OBJ_FILL_AUTO, false ); } +void XclImpControlHelper::SetStringProperty(const OUString& sName, const OUString& sVal) +{ + Reference<XControlModel> xCtrlModel = XclControlHelper::GetControlModel(mxShape); + if (!xCtrlModel.is()) + return; + + ScfPropertySet aProps(xCtrlModel); + aProps.SetStringProperty(sName, sVal); +} + bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const { return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName(), GetDocShell() ); @@ -2393,6 +2409,11 @@ XclTbxEventType XclImpOptionButtonObj::DoGetEventType() const return EXC_TBX_EVENT_ACTION; } +bool XclImpOptionButtonObj::IsInGroup() const +{ + return mnNextInGroup; +} + XclImpLabelObj::XclImpLabelObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ) { @@ -4070,6 +4091,43 @@ const XclImpObjTextData* XclImpDrawing::FindTextData( const DffRecordHeader& rHe return nullptr; } +void XclImpDrawing::ApplyGroupBoxes() +{ + // sorted: smallest to largest - looking for smallest contained-in GroupBox + // multimap: allows duplicate key values - may have identical areas. + std::multimap<double, XclImpDrawObjRef> aGroupBoxAreaMap; + for (auto& rGroupBox : maObjMapId) + { + if (rGroupBox.second->GetObjType() != EXC_OBJTYPE_GROUPBOX) + continue; + const tools::Rectangle& rRect = rGroupBox.second->GetDffRect(); + const double fArea = double(rRect.GetWidth()) * rRect.GetHeight(); + aGroupBoxAreaMap.insert(std::pair<double, XclImpDrawObjRef>(fArea, rGroupBox.second)); + } + + for (auto& rGroupedObj : maObjMapId) + { + auto pRadioButton = dynamic_cast<XclImpOptionButtonObj*>(rGroupedObj.second.get()); + if (!pRadioButton || pRadioButton->IsInGroup()) + continue; + + OUString sGroupName("autoGroup_"); + for (auto& rGroupBox : aGroupBoxAreaMap) + { + assert(pRadioButton->GetTab() == rGroupBox.second->GetTab() && "impossible right?"); + if (!rGroupBox.second->GetDffRect().Contains(pRadioButton->GetDffRect())) + continue; + + sGroupName = rGroupBox.second->GetObjName(); + if (sGroupName.isEmpty()) + sGroupName += "autoGroup_" + OUString::number(rGroupBox.second->GetObjId()); + // I ASSUME the smallest box wins in MS Word. (otherwise first? last?) + break; + } + pRadioButton->SetStringProperty("GroupName", sGroupName); + } +} + void XclImpDrawing::SetSkipObj( sal_uInt16 nObjId ) { maSkipObjs.push_back( nObjId ); @@ -4097,6 +4155,8 @@ void XclImpDrawing::ImplConvertObjects( XclImpDffConverter& rDffConv, SdrModel& rDffConv.ProcessDrawing( maRawObjs ); // process all objects in the DFF stream rDffConv.ProcessDrawing( maDffStrm ); + // assign groups based on being contained in the same GroupBox/sheet + ApplyGroupBoxes(); // unregister this drawing manager at the passed (global) DFF manager rDffConv.FinalizeDrawing(); rSdrModel.EnableUndo(bOrigUndoStatus); diff --git a/sc/source/filter/inc/xiescher.hxx b/sc/source/filter/inc/xiescher.hxx index 2079d68f11c1..cf09c161fe11 100644 --- a/sc/source/filter/inc/xiescher.hxx +++ b/sc/source/filter/inc/xiescher.hxx @@ -98,6 +98,7 @@ public: sal_uInt32 GetDffShapeId() const { return mnDffShapeId; } /** Returns the shape flags from the DFF stream. */ ShapeFlag GetDffFlags() const { return mnDffFlags; } + const tools::Rectangle& GetDffRect() const; /** Returns true, if the object is hidden. */ bool IsHidden() const { return mbHidden; } @@ -191,6 +192,7 @@ private: sal_uInt16 mnObjType; /// The Excel object type from OBJ record. sal_uInt32 mnDffShapeId; /// Shape ID from DFF stream. ShapeFlag mnDffFlags; /// Shape flags from DFF stream. + tools::Rectangle maDffRect; OUString maObjName; /// Name of the object. OUString maMacroName; /// Name of an attached macro. OUString maHyperlink; /// On-click hyperlink URL. @@ -470,6 +472,7 @@ public: /** Sets additional properties to the form control model, calls virtual DoProcessControl(). */ void ProcessControl( const XclImpDrawObjBase& rDrawObj ) const; + void SetStringProperty(const OUString& sName, const OUString& sVal); protected: /** Reads the formula for the linked cell from the current position of the stream. */ @@ -571,6 +574,7 @@ class XclImpOptionButtonObj final : public XclImpCheckBoxObj { public: explicit XclImpOptionButtonObj( const XclImpRoot& rRoot ); + bool IsInGroup() const; private: /** Reads the contents of the a BIFF5 OBJ record from the passed stream. */ @@ -1062,6 +1066,8 @@ public: /** Finds the textbox data related to the DFF shape at the passed position. */ const XclImpObjTextData* FindTextData( const DffRecordHeader& rHeader ) const; + void ApplyGroupBoxes(); + /** Sets the object with the passed identification to be skipped on import. */ void SetSkipObj( sal_uInt16 nObjId ); /** Returns the size of the progress bar shown while processing all objects. */ |