sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls |binary
 sc/qa/unit/subsequent_filters_test4.cxx        |   20 ++++++++
 sc/source/filter/excel/xiescher.cxx            |   60 +++++++++++++++++++++++++
 sc/source/filter/inc/xiescher.hxx              |    6 ++
 4 files changed, 86 insertions(+)

New commits:
commit 25fed4ae027b9680597ea498c25acc3f854db4bf
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Thu Aug 4 19:52:23 2022 -0400
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Tue May 16 01:01:27 2023 +0200

    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 <jl...@mail.com>

diff --git a/sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls 
b/sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls
new file mode 100644
index 000000000000..1861913020d3
Binary files /dev/null and b/sc/qa/unit/data/xls/tdf79542_radioGroupBox.xls 
differ
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. */

Reply via email to