cui/source/inc/paragrph.hxx             |    1 
 cui/source/tabpages/chardlg.cxx         |    2 
 cui/source/tabpages/paragrph.cxx        |    8 
 cui/source/tabpages/tptrans.cxx         |    2 
 include/sfx2/sfxdlg.hxx                 |    5 
 include/sfx2/strings.hrc                |    2 
 include/sfx2/tabdlg.hxx                 |   24 +-
 include/svl/itemset.hxx                 |    5 
 include/svl/style.hxx                   |    8 
 sc/inc/stlsheet.hxx                     |    3 
 sc/inc/strings.hrc                      |   13 +
 sc/source/core/data/stlsheet.cxx        |  189 ++++++++++++++++
 sfx2/UIConfig_sfx.mk                    |    3 
 sfx2/source/dialog/mgetempl.cxx         |  371 +++++++++++++++++++++++++++++++-
 sfx2/source/dialog/mgetempl.hxx         |   84 ++++++-
 sfx2/source/dialog/styledlg.cxx         |    7 
 sfx2/source/dialog/tabdlg.cxx           |  237 ++++++++++++++++++++
 sfx2/uiconfig/ui/managestylepage.ui     |  117 +++++++++-
 sfx2/uiconfig/ui/propertycategoryrow.ui |   42 +++
 sfx2/uiconfig/ui/propertychip.ui        |   55 ++++
 sfx2/uiconfig/ui/propertychiprow.ui     |   10 
 solenv/sanitizers/ui/sfx.suppr          |    2 
 svl/source/items/itemset.cxx            |   18 +
 svl/source/items/style.cxx              |   49 ++++
 sw/inc/docstyle.hxx                     |    3 
 sw/inc/strings.hrc                      |   14 +
 sw/qa/uitest/ui/fmtui/tdf89826.py       |   95 ++++++++
 sw/source/ui/dialog/swdlgfact.cxx       |    2 
 sw/source/ui/fmtui/tmpdlg.cxx           |    2 
 sw/source/uibase/app/docst.cxx          |    6 
 sw/source/uibase/app/docstyle.cxx       |  270 +++++++++++++++++++++++
 31 files changed, 1627 insertions(+), 22 deletions(-)

New commits:
commit 52010fde0917051e043674c8da42d9a06340b571
Author:     Paolo Benvenuto <[email protected]>
AuthorDate: Sat Feb 28 13:22:16 2026 +0100
Commit:     Heiko Tietze <[email protected]>
CommitDate: Sat Feb 28 15:52:40 2026 +0100

    tdf#89826 Add interactive property chips to style Organizer tab
    
    The Organizer tab of the style dialog now shows interactive "chips"
    for each property that differs from the parent style. Each chip
    displays the property name and value, and includes an X button to
    reset that property back to parent inheritance. All properties
    are shown full text, no ellipsis.
    
    Properties are grouped by tab page (Font, Font effects, etc.)
    and displayed in a scrollable area. A View/Edit toggle lets the
    user switch between the traditional description text and the
    interactive chip view.
    
    Implementation summary:
    
    - New PropertyChip and PropertyCategoryRow widgets (sfx2) with
      corresponding .ui files for the chip layout.
    
    - SfxStyleSheetBase::GetItemPresentation() virtual method returns
      per-property presentation strings, overridden in SwDocStyleSheet
      and ScStyleSheet for module-specific attributes.
    
    - SfxItemSet access tracker mechanism to automatically map WhichIds
      to their owning tab pages via BuildWhichToTabMap().
    
    - SfxTabDialogController::InvalidateItem() propagates chip resets
      to the output set and affected tab pages.
    
    - SwDocStyleSheet::ResetItems() uses SwDoc::ResetAttrAtFormat() to
      ensure proper undo support in Writer.
    
    - SfxStyleDialogController::Ok() clears invalidated items from the
      style's item set on dialog confirmation.
    
    - SvxAsianTabPage now calls SetExchangeSupport() and implements
      DeactivatePage() so its items are properly tracked.
    
    - Access tracker ignore guards in SvxCharBasePage::SetPrevFontWidthScale
      and SvxTransparenceTabPage::InitPreview to avoid false positives
      from preview-only item access.
    
    Includes a UITest for Writer (sw/qa/uitest/ui/fmtui/tdf89826.py)
    that creates a child style, modifies a property, removes it via
    chip, and verifies inheritance is restored including undo.
    
    A Calc UITest is not included because the style edit dialog in Calc
    is opened asynchronously (ScTabViewShell::ExecuteStyleEdit) and the
    UITest framework's execute_dialog_through_command cannot capture it.
    The Calc functionality has been verified manually. A Calc UITest can
    be added once the framework supports async style dialogs.
    
    Change-Id: Ia764405798c212fe5340bba254f2ff6ac62365f6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199318
    Reviewed-by: Heiko Tietze <[email protected]>
    Tested-by: Jenkins

diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx
index 685492aa8e61..ad4398495f3f 100644
--- a/cui/source/inc/paragrph.hxx
+++ b/cui/source/inc/paragrph.hxx
@@ -357,6 +357,7 @@ public:
 
     virtual bool        FillItemSet( SfxItemSet* rSet ) override;
     virtual void        Reset( const SfxItemSet* rSet ) override;
+    virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
     virtual void        ChangesApplied() override;
 };
 
diff --git a/cui/source/tabpages/chardlg.cxx b/cui/source/tabpages/chardlg.cxx
index a1a0130ac6c6..a92ae65f5ffa 100644
--- a/cui/source/tabpages/chardlg.cxx
+++ b/cui/source/tabpages/chardlg.cxx
@@ -154,11 +154,13 @@ void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet)
 void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet )
 {
     sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
+    rSet.SetAccessTrackerIgnore(true);
     if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT)
     {
         const SvxCharScaleWidthItem &rItem = static_cast<const 
SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
         m_aPreviewWin.SetFontWidthScale(rItem.GetValue());
     }
+    rSet.SetAccessTrackerIgnore(false);
 }
 
 void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 
nEscProp, short nEsc )
diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx
index 3e1e1aee4710..46b9a83c9690 100644
--- a/cui/source/tabpages/paragrph.cxx
+++ b/cui/source/tabpages/paragrph.cxx
@@ -3056,12 +3056,20 @@ SvxAsianTabPage::SvxAsianTabPage(weld::Container* 
pPage, weld::DialogController*
     , m_xHangingPunctCB(m_xBuilder->weld_check_button(u"checkHangPunct"_ustr))
     , 
m_xScriptSpaceCB(m_xBuilder->weld_check_button(u"checkApplySpacing"_ustr))
 {
+    SetExchangeSupport();
 }
 
 SvxAsianTabPage::~SvxAsianTabPage()
 {
 }
 
+DeactivateRC SvxAsianTabPage::DeactivatePage( SfxItemSet* pSet )
+{
+    if ( pSet )
+        FillItemSet( pSet );
+    return DeactivateRC::LeavePage;
+}
+
 std::unique_ptr<SfxTabPage> SvxAsianTabPage::Create(weld::Container* pPage, 
weld::DialogController* pController, const SfxItemSet* rSet)
 {
     return std::make_unique<SvxAsianTabPage>(pPage, pController, *rSet);
diff --git a/cui/source/tabpages/tptrans.cxx b/cui/source/tabpages/tptrans.cxx
index 06c967f7fb2e..e9e159c6713d 100644
--- a/cui/source/tabpages/tptrans.cxx
+++ b/cui/source/tabpages/tptrans.cxx
@@ -458,6 +458,7 @@ bool SvxTransparenceTabPage::InitPreview(const SfxItemSet& 
rSet)
     }
 
     // Get fillstyle for preview
+    rSet.SetAccessTrackerIgnore(true);
     rXFSet.Put ( rSet.Get(XATTR_FILLSTYLE) );
     rXFSet.Put ( rSet.Get(XATTR_FILLCOLOR) );
     rXFSet.Put ( rSet.Get(XATTR_FILLGRADIENT) );
@@ -469,6 +470,7 @@ bool SvxTransparenceTabPage::InitPreview(const SfxItemSet& 
rSet)
     m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() );
 
     bBitmap = rSet.Get(XATTR_FILLSTYLE).GetValue() == 
drawing::FillStyle_BITMAP;
+    rSet.SetAccessTrackerIgnore(false);
 
     // show the right preview window
     if ( bBitmap )
diff --git a/include/sfx2/sfxdlg.hxx b/include/sfx2/sfxdlg.hxx
index 1dedbf084496..69f0f230b45f 100644
--- a/include/sfx2/sfxdlg.hxx
+++ b/include/sfx2/sfxdlg.hxx
@@ -64,6 +64,11 @@ public:
     virtual void                SetCurPageId( const OUString &rName ) = 0;
     virtual WhichRangesContainer GetInputRanges( const SfxItemPool& ) = 0;
     virtual void                SetInputSet( const SfxItemSet* pInSet ) = 0;
+    virtual const std::set<sal_uInt16>& GetInvalidatedWhichIds() const
+    {
+        static const std::set<sal_uInt16> empty;
+        return empty;
+    }
 };
 
 class SfxAbstractApplyTabDialog : virtual public SfxAbstractTabDialog
diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc
index 88d64a425f77..573c75b0f0cc 100644
--- a/include/sfx2/strings.hrc
+++ b/include/sfx2/strings.hrc
@@ -231,6 +231,8 @@
 #define STR_TABPAGE_INVALIDNAME                 NC_("STR_TABPAGE_INVALIDNAME", 
"This name is already in use.")
 #define STR_TABPAGE_INVALIDSTYLE                
NC_("STR_TABPAGE_INVALIDSTYLE", "This Style does not exist.")
 #define STR_TABPAGE_INVALIDPARENT               
NC_("STR_TABPAGE_INVALIDPARENT", "This Style cannot be used as a base Style,
because it would result in a recursive reference.")
+#define STR_RESET_PROPERTY_TOOLTIP              
NC_("STR_RESET_PROPERTY_TOOLTIP", "Reset this property to inherit from parent 
style")
+#define STR_NO_MODIFIED_PROPERTIES              
NC_("STR_NO_MODIFIED_PROPERTIES", "All properties are inherited from parent 
style.")
 #define STR_POOL_STYLE_NAME                     NC_("STR_POOL_STYLE_NAME", 
"Name already exists as a default Style.
Please choose another name.")
 #define STR_DELETE_STYLE_USED                   NC_("STR_DELETE_STYLE_USED", 
"One or more of the selected styles is in use in this document.
If you will delete it, text or objects using these styles will revert to the 
parent style.
Do you still wish to delete these styles?
")
 #define STR_DELETE_STYLE                        NC_("STR_DELETE_STYLE", 
"Styles in use: ")
diff --git a/include/sfx2/tabdlg.hxx b/include/sfx2/tabdlg.hxx
index 9866b5d85164..6dd6155b8162 100644
--- a/include/sfx2/tabdlg.hxx
+++ b/include/sfx2/tabdlg.hxx
@@ -22,6 +22,7 @@
 #include <memory>
 #include <unordered_map>
 #include <string_view>
+#include <set>
 
 #include <sal/config.h>
 #include <sfx2/dllapi.h>
@@ -32,6 +33,7 @@
 #include <svl/itemset.hxx>
 #include <svl/setitem.hxx>
 #include <o3tl/typed_flags_set.hxx>
+#include <map>
 
 class Bitmap;
 class SfxTabPage;
@@ -80,9 +82,11 @@ private:
     std::unique_ptr<SfxItemSet>           m_pOutSet;
     std::unique_ptr<TabDlg_Impl>          m_pImpl;
     WhichRangesContainer                  m_pRanges;
+    std::map<sal_uInt16, OUString>        m_aWhichToTabMap;
     OUString             m_sAppPageId;
     bool                m_bStandardPushed;
     std::unique_ptr<SfxAllItemSet>       m_xItemSet;
+    std::map<sal_uInt16, int> m_aWhichOrderMap;
 
     DECL_DLLPRIVATE_LINK(ActivatePageHdl, const OUString&, void);
     DECL_DLLPRIVATE_LINK(DeactivatePageHdl, const OUString&, bool);
@@ -92,6 +96,7 @@ private:
 
 protected:
     virtual short               Ok();
+    std::set<sal_uInt16>        m_aInvalidatedWhichIds;
     virtual void                RefreshInputSet();
     virtual SfxItemSet*         CreateInputItemSet(const OUString& rName);
     virtual void                PageCreated(const OUString &rName, SfxTabPage 
&rPage);
@@ -161,6 +166,23 @@ public:
     void                ShowPage(const OUString& rName);  // SetCurPageId + 
call Activate on it
     OUString             GetCurPageId() const;
     SfxTabPage*         GetCurTabPage() const { return 
GetTabPage(GetCurPageId()); }
+    void                ResetTabPage(std::u16string_view rPageId);
+    void                ResetAllTabPages();
+    void                InvalidateItem(sal_uInt16 nWhich);
+    OUString            GetTabPageNameForWhich(sal_uInt16 nWhich) const;
+    void                BuildWhichToTabMap();
+    OUString            GetTabPageLabel(const OUString& rPageId) const;
+    std::vector<OUString> GetTabPageIds() const;
+    int GetWhichOrder(sal_uInt16 nWhich) const {
+        auto it = m_aWhichOrderMap.find(nWhich);
+        return it != m_aWhichOrderMap.end() ? it->second : INT_MAX;
+    }
+    const SfxItemSet* GetExampleSet() const override { return 
m_xExampleSet.get(); }
+
+    /// Subclasses can override to provide additional WhichId→tab mappings
+    /// that the access tracker cannot determine correctly.
+    virtual std::map<sal_uInt16, OUString> GetWhichToTabOverrides() const { 
return {}; }
+    const std::set<sal_uInt16>& GetInvalidatedWhichIds() const { return 
m_aInvalidatedWhichIds; }
 
     // may provide local slots converted by Map
     const WhichRangesContainer& GetInputRanges( const SfxItemPool& );
@@ -181,8 +203,6 @@ public:
     static bool runAsync(const std::shared_ptr<SfxTabDialogController>& 
rController,
                          const std::function<void(sal_Int32)>&);
 
-    virtual const SfxItemSet* GetExampleSet() const override { return 
m_xExampleSet.get(); }
-
     void                SetApplyHandler(const Link<weld::Button&,void>& _rHdl);
 
     //calls Ok without closing dialog
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 7dd32ff77791..8e5a3b63b76d 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -28,6 +28,7 @@
 #include <svl/poolitem.hxx>
 #include <svl/typedwhich.hxx>
 #include <svl/whichranges.hxx>
+#include <set>
 
 class SfxItemPool;
 
@@ -90,6 +91,8 @@ class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
     SfxItemPool*      m_pPool;         ///< pool that stores the items
     const SfxItemSet* m_pParent;       ///< derivation
     sal_uInt16        m_nRegister;     ///< number of items with 
NeedsSurrogateSupport
+    mutable std::vector<sal_uInt16>* m_pAccessTracker = nullptr;
+    mutable bool m_bAccessTrackerIgnore = false;
 
 #ifdef DBG_UTIL
     sal_uInt16          m_nRegisteredSfxItemIter;
@@ -244,6 +247,8 @@ public:
     void                        SetRanges( WhichRangesContainer&& );
     void                        MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo );
     const SfxItemSet*           GetParent() const { return m_pParent; }
+    void SetAccessTracker(std::vector<sal_uInt16>* pTracker) const { 
m_pAccessTracker = pTracker; }
+    void SetAccessTrackerIgnore(bool b) const { m_bAccessTrackerIgnore = b; }
 
     bool                        operator==(const SfxItemSet &) const;
     size_t                      GetHashCode() const;
diff --git a/include/svl/style.hxx b/include/svl/style.hxx
index 2555eda5306b..f803e710b59b 100644
--- a/include/svl/style.hxx
+++ b/include/svl/style.hxx
@@ -34,6 +34,9 @@
 #include <memory>
 #include <optional>
 
+#include <vector>
+#include <utility>
+
 // This is used as a flags enum in sw/, but only there,
 // so I don't pull in o3tl::typed_flags here
 enum class SfxStyleFamily {
@@ -164,6 +167,11 @@ public:
     virtual bool IsUsed() const;                // Default true
     virtual OUString GetDescription( MapUnit eMetric );
 
+    /// Returns individual property presentations for building UI chips
+    /// Each pair contains: WhichId and presentation string
+    virtual std::vector<std::pair<sal_uInt16, OUString>> GetItemPresentation(
+        MapUnit eMetric, const SfxItemSet* pWorkingSet = nullptr);
+
     virtual OUString GetUsedBy() { return OUString(); }
 
     SfxStyleSheetBasePool* GetPool() { return m_pPool; }
diff --git a/sc/inc/stlsheet.hxx b/sc/inc/stlsheet.hxx
index 6eab3e5a1128..1e1dfef78254 100644
--- a/sc/inc/stlsheet.hxx
+++ b/sc/inc/stlsheet.hxx
@@ -54,6 +54,9 @@ public:
 
     /// Fix for expensive dynamic_cast
     virtual bool isScStyleSheet() const override { return true; }
+
+    virtual std::vector<std::pair<sal_uInt16, OUString>> GetItemPresentation(
+            MapUnit eMetric, const SfxItemSet* pWorkingSet = nullptr) override;
 private:
     virtual             ~ScStyleSheet() override;
 
diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc
index c824785a830d..89ca3a06793a 100644
--- a/sc/inc/strings.hrc
+++ b/sc/inc/strings.hrc
@@ -445,6 +445,19 @@
 #define STR_DUPLICATERECORDS_DATACONATINSROWHEADERS    
NC_("STR_DUPLICATERECORDS_DATACONATINSROWHEADERS", "Data contains row headers")
 #define STR_DUPLICATERECORDS_DATACONATINSCOLUMNHEADERS 
NC_("STR_DUPLICATERECORDS_DATACONATINSCOLUMNHEADERS", "Data contains column 
headers")
 
+#define STR_ATTR_PROTECTION    NC_("STR_ATTR_PROTECTION", "Protection")
+#define STR_ATTR_ROTATION      NC_("STR_ATTR_ROTATION", "Rotation")
+#define STR_ATTR_ROTATION_MODE NC_("STR_ATTR_ROTATION_MODE", "Rotation Mode")
+#define STR_ATTR_TEXT_DIR      NC_("STR_ATTR_TEXT_DIR", "Text Direction")
+#define STR_ATTR_WRAP_TEXT     NC_("STR_ATTR_WRAP_TEXT", "Wrap Text")
+#define STR_ATTR_SHRINK_FIT   NC_("STR_ATTR_SHRINK_FIT", "Shrink to Fit")
+#define STR_ATTR_STACKED      NC_("STR_ATTR_STACKED", "Stacked")
+#define STR_ATTR_H_ALIGN      NC_("STR_ATTR_H_ALIGN", "Horizontal Alignment")
+#define STR_ATTR_V_ALIGN      NC_("STR_ATTR_V_ALIGN", "Vertical Alignment")
+#define STR_ATTR_INDENT       NC_("STR_ATTR_INDENT", "Indent")
+#define STR_ATTR_SPACING      NC_("STR_ATTR_SPACING", "Spacing")
+#define STR_ATTR_NUM_FORMAT   NC_("STR_ATTR_NUM_FORMAT", "Number Format")
+#define STR_ATTR_ASIAN_LAYOUT   NC_("STR_ATTR_ASIAN_LAYOUT", "Asian Layout 
Mode")
 
 #define STR_CONTENT_WITH_UNKNOWN_ENCRYPTION 
NC_("STR_CONTENT_WITH_UNKNOWN_ENCRYPTION", "Document contains DRM content that 
is encrypted with an unknown encryption method. Only the un-encrypted content 
will be shown.")
 
diff --git a/sc/source/core/data/stlsheet.cxx b/sc/source/core/data/stlsheet.cxx
index b56a6ef0c6a2..81692a994dd4 100644
--- a/sc/source/core/data/stlsheet.cxx
+++ b/sc/source/core/data/stlsheet.cxx
@@ -39,13 +39,33 @@
 #include <svl/itemset.hxx>
 #include <svl/numformat.hxx>
 #include <svl/hint.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/zformat.hxx>
 #include <o3tl/unit_conversion.hxx>
 #include <attrib.hxx>
 
 #include <globstr.hrc>
+#include <strings.hrc>
 #include <scresid.hxx>
 #include <sc.hrc>
 
+#include <svx/strarray.hxx>
+#include <svx/svxids.hrc>
+#include <svl/numformat.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/intitem.hxx>
+#include <svl/ilstitem.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/eitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <scitems.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <document.hxx>
+#include <docsh.hxx>
+#include <sfx2/objsh.hxx>
+
 constexpr auto TWO_CM = o3tl::convert(2, o3tl::Length::cm, 
o3tl::Length::twip); // 1134
 constexpr auto HFDIST_CM = o3tl::convert(250, o3tl::Length::mm100, 
o3tl::Length::twip); // 142
 
@@ -274,6 +294,175 @@ SfxItemSet& ScStyleSheet::GetItemSet()
     return *pSet;
 }
 
+std::vector<std::pair<sal_uInt16, OUString>> ScStyleSheet::GetItemPresentation(
+    MapUnit eMetric, const SfxItemSet* pWorkingSet)
+{
+    std::vector<std::pair<sal_uInt16, OUString>> aResult;
+    IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+
+    const SfxItemSet& rSet = GetItemSet();
+    const SfxItemSet* pCheckSet = pWorkingSet ? pWorkingSet : &rSet;
+
+    // Get parent item set for comparison
+    const SfxItemSet* pParentSet = nullptr;
+    SfxStyleSheetBase* pParentStyle = nullptr;
+    if (!GetParent().isEmpty())
+    {
+        pParentStyle = m_pPool->Find(GetParent(), GetFamily());
+        if (pParentStyle)
+            pParentSet = &pParentStyle->GetItemSet();
+    }
+
+    // Get the number formatter for ATTR_VALUE_FORMAT
+    SvNumberFormatter* pFormatter = nullptr;
+    if (ScDocShell* pDocSh = 
dynamic_cast<ScDocShell*>(SfxObjectShell::Current()))
+    {
+        pFormatter = pDocSh->GetDocument().GetFormatTable();
+    }
+
+    SfxItemIter aIter(rSet);
+
+    for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = 
aIter.NextItem())
+    {
+        if (IsInvalidItem(pItem))
+            continue;
+
+        sal_uInt16 nWhich = pItem->Which();
+
+        // Only show items explicitly SET in this style (not inherited)
+        if (pCheckSet->GetItemState(nWhich, false) != SfxItemState::SET)
+            continue;
+
+        // Skip items identical to parent
+        if (pParentSet)
+        {
+            const SfxPoolItem* pParentItem = nullptr;
+            if (pParentSet->GetItemState(nWhich, true, &pParentItem) == 
SfxItemState::SET
+                && pParentItem && *pParentItem == *pItem)
+                continue;
+        }
+
+        // Skip items equal to pool default
+        if (*pItem == rSet.GetPool()->GetUserOrPoolDefaultItem(nWhich))
+            continue;
+
+        // Skip internal/structural items that don't make sense as chips
+        switch (nWhich)
+        {
+            case SID_ATTR_BORDER_INNER:
+            case SID_ATTR_PARA_MODEL:
+            case SID_ATTR_PAGE_SIZE:
+            case SID_ATTR_PAGE_MAXSIZE:
+            case SID_ATTR_PAGE_PAPERBIN:
+                continue;
+            default:
+                break;
+        }
+
+        OUString aItemPresentation;
+
+        // Special handling for number format: the default GetPresentation
+        // just returns the raw format key (e.g. "10122")
+        if (nWhich == ATTR_VALUE_FORMAT && pFormatter)
+        {
+            sal_uInt32 nFormat = static_cast<const 
SfxUInt32Item*>(pItem)->GetValue();
+            const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
+            if (pEntry)
+            {
+                OUString sFormatStr = pEntry->GetFormatstring();
+                // Truncate very long format strings
+                if (sFormatStr.getLength() > 40)
+                    sFormatStr = OUString::Concat(sFormatStr.subView(0, 37)) + 
"...";
+                aItemPresentation = SvxAttrNameTable::GetString(
+                    SvxAttrNameTable::FindIndex(
+                        rSet.GetPool()->GetSlotId(nWhich)));
+                if (aItemPresentation.isEmpty())
+                    aItemPresentation = ScResId(STR_ATTR_NUM_FORMAT);
+                aItemPresentation += ": " + sFormatStr;
+            }
+            else
+            {
+                continue;  // Skip unresolvable format keys
+            }
+        }
+        else
+        {
+            // Standard presentation via pool
+            if (!m_pPool->GetPool().GetPresentation(
+                    *pItem, eMetric, aItemPresentation, aIntlWrapper))
+                continue;
+
+            if (aItemPresentation.isEmpty())
+                continue;
+
+            // Add attribute name prefix if not already present
+            if (aItemPresentation.indexOf(": ") == -1)
+            {
+                sal_uInt16 nSlotId = rSet.GetPool()->GetSlotId(nWhich);
+                sal_uInt32 nIdx = SvxAttrNameTable::FindIndex(nSlotId);
+                OUString aAttrName = SvxAttrNameTable::GetString(nIdx);
+
+                // Fallback for Calc-specific WhichIds not in SvxAttrNameTable
+                if (aAttrName.isEmpty())
+                {
+                    // You may want to add string resources in 
sc/inc/strings.hrc
+                    // for now using English fallbacks that you can later 
replace
+                    // with proper NC_ macros
+                    switch (nWhich)
+                    {
+                        case ATTR_PROTECTION:
+                            aAttrName = ScResId(STR_ATTR_PROTECTION);
+                            break;
+                        case ATTR_ROTATE_VALUE:
+                            aAttrName = ScResId(STR_ATTR_ROTATION);
+                            break;
+                        case ATTR_ROTATE_MODE:
+                            aAttrName = ScResId(STR_ATTR_ROTATION_MODE);
+                            break;
+                        case ATTR_WRITINGDIR:
+                            aAttrName = ScResId(STR_ATTR_TEXT_DIR);
+                            break;
+                        case ATTR_LINEBREAK:
+                            aAttrName = ScResId(STR_ATTR_WRAP_TEXT);
+                            break;
+                        case ATTR_SHRINKTOFIT:
+                            aAttrName = ScResId(STR_ATTR_SHRINK_FIT);
+                            break;
+                        case ATTR_STACKED:
+                            aAttrName = ScResId(STR_ATTR_STACKED);
+                            break;
+                        case ATTR_HOR_JUSTIFY:
+                            aAttrName = ScResId(STR_ATTR_H_ALIGN);
+                            break;
+                        case ATTR_VER_JUSTIFY:
+                            aAttrName = ScResId(STR_ATTR_V_ALIGN);
+                            break;
+                        case ATTR_INDENT:
+                            aAttrName = ScResId(STR_ATTR_INDENT);
+                            break;
+                        case ATTR_MARGIN:
+                            aAttrName = ScResId(STR_ATTR_SPACING);
+                            break;
+                        case ATTR_VERTICAL_ASIAN:
+                            aAttrName = ScResId(STR_ATTR_ASIAN_LAYOUT);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+
+                if (!aAttrName.isEmpty())
+                    aItemPresentation = aAttrName + ": " + aItemPresentation;
+            }
+        }
+
+        if (!aItemPresentation.isEmpty())
+            aResult.emplace_back(nWhich, aItemPresentation);
+    }
+
+    return aResult;
+}
+
 bool ScStyleSheet::IsUsed() const
 {
     switch (GetFamily())
diff --git a/sfx2/UIConfig_sfx.mk b/sfx2/UIConfig_sfx.mk
index 79bec2ca159e..87f09452e6a6 100644
--- a/sfx2/UIConfig_sfx.mk
+++ b/sfx2/UIConfig_sfx.mk
@@ -56,6 +56,9 @@ $(eval $(call gb_UIConfig_add_uifiles,sfx,\
        sfx2/uiconfig/ui/password \
        sfx2/uiconfig/ui/notebookbarpopup \
        sfx2/uiconfig/ui/printeroptionsdialog \
+       sfx2/uiconfig/ui/propertychip \
+       sfx2/uiconfig/ui/propertychiprow \
+       sfx2/uiconfig/ui/propertycategoryrow \
        sfx2/uiconfig/ui/querysavedialog \
        sfx2/uiconfig/ui/quickfind \
        sfx2/uiconfig/ui/saveastemplatedlg \
diff --git a/sfx2/source/dialog/mgetempl.cxx b/sfx2/source/dialog/mgetempl.cxx
index f29d69041e22..264981fac84e 100644
--- a/sfx2/source/dialog/mgetempl.cxx
+++ b/sfx2/source/dialog/mgetempl.cxx
@@ -45,9 +45,141 @@
 
 #include <svl/stritem.hxx>
 #include <sfx2/dispatch.hxx>
+#include <sal/log.hxx>
+
+#include <algorithm>
 
 #include "mgetempl.hxx"
 
+// PropertyChip implementation
+PropertyChip::PropertyChip(weld::Box* pParent, SfxManageStyleSheetPage* pPage,
+                           sal_uInt16 nWhich, const OUString& rText)
+    : m_xBuilder(Application::CreateBuilder(pParent, 
u"sfx/ui/propertychip.ui"_ustr))
+    , m_xContainer(m_xBuilder->weld_container(u"PropertyChip"_ustr))
+    , m_xLabel(m_xBuilder->weld_label(u"label"_ustr))
+    , m_xRemoveBtn(m_xBuilder->weld_toolbar(u"removebar"_ustr))
+    , m_pPage(pPage)
+    , m_sText(rText)
+    , m_nWhich(nWhich)
+{
+    // For texts longer than one line, insert manual newlines.
+    static constexpr int MAX_LINE_CHARS = 100;
+    if (rText.getLength() > MAX_LINE_CHARS)
+    {
+        OUStringBuffer aBuf;
+        int nLineLen = 0;
+        for (sal_Int32 i = 0; i < rText.getLength(); ++i)
+        {
+            sal_Unicode c = rText[i];
+            aBuf.append(c);
+            nLineLen++;
+            if (nLineLen >= MAX_LINE_CHARS && (c == ' ' || c == ',' || c == 
';' || c == '&'))
+            {
+                aBuf.append('
');
+                nLineLen = 0;
+            }
+        }
+        m_xLabel->set_label(aBuf.makeStringAndClear());
+    }
+    else
+    {
+        m_xLabel->set_label(rText);
+    }
+    m_xLabel->set_tooltip_text(rText);
+    m_xRemoveBtn->connect_clicked(LINK(this, PropertyChip, RemoveHdl));
+}
+
+PropertyChip::~PropertyChip()
+{
+    if (m_xContainer)
+        m_xContainer->set_visible(false);
+}
+
+IMPL_LINK_NOARG(PropertyChip, RemoveHdl, const OUString&, void)
+{
+    m_pPage->ResetPropertyToParent(m_nWhich);
+}
+
+// PropertyCategoryRow implementation
+PropertyCategoryRow::PropertyCategoryRow(weld::Box* pParentBox, 
std::u16string_view rLabel)
+    : m_xBuilder(Application::CreateBuilder(pParentBox, 
u"sfx/ui/propertycategoryrow.ui"_ustr))
+    , m_xContainer(m_xBuilder->weld_container(u"PropertyCategoryRow"_ustr))
+    , m_xLabel(m_xBuilder->weld_label(u"label"_ustr))
+    , m_xChipsBox(m_xBuilder->weld_container(u"chipsbox"_ustr))
+{
+    m_xLabel->set_label(OUString::Concat(rLabel) + ":");
+}
+
+PropertyCategoryRow::~PropertyCategoryRow()
+{
+    m_aChips.clear();
+    m_aChipRows.clear();
+    if (m_xContainer)
+        m_xContainer->set_visible(false);
+}
+
+weld::Box* PropertyCategoryRow::EnsureCurrentRow(int nChipChars)
+{
+    if (m_aChipRows.empty()
+        || (m_aChipRows.back()->nTotalChars + nChipChars > MAX_CHARS_PER_ROW
+            && m_aChipRows.back()->nTotalChars > 0))
+    {
+        auto pRow = std::make_unique<ChipRow>();
+        pRow->xBuilder = Application::CreateBuilder(
+            m_xChipsBox.get(), u"sfx/ui/propertychiprow.ui"_ustr);
+        pRow->xBox = pRow->xBuilder->weld_box(u"PropertyChipRow"_ustr);
+        pRow->xBox->show();
+        pRow->nTotalChars = 0;
+        m_aChipRows.push_back(std::move(pRow));
+    }
+    return m_aChipRows.back()->xBox.get();
+}
+
+void PropertyCategoryRow::AddChip(SfxManageStyleSheetPage* pPage, sal_uInt16 
nWhich, const OUString& rText)
+{
+    int nTextLen = rText.getLength();
+    int nChipChars = nTextLen + 3;
+    weld::Box* pCurrentRow = EnsureCurrentRow(nChipChars);
+    m_aChips.emplace_back(std::make_unique<PropertyChip>(pCurrentRow, pPage, 
nWhich, rText));
+    m_aChipRows.back()->nTotalChars += nChipChars;
+}
+
+void PropertyCategoryRow::RemoveChip(sal_uInt16 nWhich)
+{
+    struct ChipData
+    {
+        sal_uInt16 nWhich;
+        OUString sText;
+    };
+    std::vector<ChipData> aData;
+
+    SfxManageStyleSheetPage* pPage = nullptr;
+    for (const auto& pChip : m_aChips)
+    {
+        if (pChip->GetWhich() == nWhich)
+            continue;
+        if (!pPage)
+            pPage = pChip->GetPage();
+        aData.push_back({pChip->GetWhich(), pChip->GetText()});
+    }
+
+    // Hide rows before destroying
+    for (auto& pRow : m_aChipRows)
+    {
+        if (pRow->xBox)
+            pRow->xBox->set_visible(false);
+    }
+
+    m_aChips.clear();
+    m_aChipRows.clear();
+
+    if (pPage)
+    {
+        for (const auto& d : aData)
+            AddChip(pPage, d.nWhich, d.sText);
+    }
+}
+
 /*  SfxManageStyleSheetPage Constructor
  *
  *  initializes the list box with the templates
@@ -72,6 +204,10 @@ 
SfxManageStyleSheetPage::SfxManageStyleSheetPage(weld::Container* pPage, weld::D
     , m_xFilterFt(m_xBuilder->weld_label(u"categoryft"_ustr))
     , m_xFilterLb(m_xBuilder->weld_combo_box(u"category"_ustr))
     , m_xDescFt(m_xBuilder->weld_label(u"desc"_ustr))
+    , m_xEditViewBox(m_xBuilder->weld_box(u"editviewbox"_ustr))
+    , m_xEditPropsBtn(m_xBuilder->weld_toggle_button(u"editprops"_ustr))
+    , m_xViewPropsBtn(m_xBuilder->weld_toggle_button(u"viewprops"_ustr))
+    , m_xPropBox(m_xBuilder->weld_box(u"propbox"_ustr))
 {
     m_xFollowLb->make_sorted();
     // tdf#120188 like SwCharURLPage limit the width of the style combos
@@ -258,10 +394,13 @@ 
SfxManageStyleSheetPage::SfxManageStyleSheetPage(weld::Container* pPage, weld::D
     m_xBaseLb->connect_changed(LINK(this, SfxManageStyleSheetPage, 
EditLinkStyleSelectHdl_Impl));
     m_xEditStyleBtn->connect_clicked(LINK(this, SfxManageStyleSheetPage, 
EditStyleHdl_Impl));
     m_xEditLinkStyleBtn->connect_clicked(LINK(this, SfxManageStyleSheetPage, 
EditLinkStyleHdl_Impl));
+    m_xEditPropsBtn->connect_toggled(LINK(this, SfxManageStyleSheetPage, 
EditPropsHdl_Impl));
+    m_xViewPropsBtn->connect_toggled(LINK(this, SfxManageStyleSheetPage, 
ViewPropsHdl_Impl));
 }
 
 SfxManageStyleSheetPage::~SfxManageStyleSheetPage()
 {
+    m_aPropertyRows.clear();
     pItem = nullptr;
     pStyle = nullptr;
 }
@@ -299,6 +438,7 @@ void SfxManageStyleSheetPage::SetDescriptionText_Impl()
 /*  [Description]
 
     Set attribute description. Get the set metric for this.
+    Also builds property chips if the style has a parent.
 */
 
 {
@@ -325,7 +465,195 @@ void SfxManageStyleSheetPage::SetDescriptionText_Impl()
         default:
             OSL_FAIL( "non supported field unit" );
     }
-    m_xDescFt->set_label(pStyle->GetDescription(eUnit));
+
+    // If style has a parent, show description text and Edit button
+    if (pStyle->HasParentSupport() && !pStyle->GetParent().isEmpty())
+    {
+        if (m_bEditMode)
+        {
+            m_xDescFt->hide();
+            m_bInToggleHandler = true;
+            m_xEditPropsBtn->set_active(true);
+            m_xViewPropsBtn->set_active(false);
+            m_bInToggleHandler = false;
+            BuildPropertyChips_Impl();
+        }
+        else
+        {
+            m_xDescFt->set_label(pStyle->GetDescription(eUnit));
+            m_xDescFt->show();
+            m_bInToggleHandler = true;
+            m_xEditPropsBtn->set_active(false);
+            m_xViewPropsBtn->set_active(true);
+            m_bInToggleHandler = false;
+        }
+        m_xEditViewBox->show();
+    }
+    else
+    {
+        // No parent - show the full description, no Edit button
+        m_aPropertyRows.clear();
+        m_xDescFt->set_label(pStyle->GetDescription(eUnit));
+        m_xDescFt->show();
+        m_xEditPropsBtn->hide();
+        m_xEditViewBox->hide();
+    }
+}
+
+void SfxManageStyleSheetPage::BuildPropertyChips_Impl()
+
+/*  [Description]
+
+    Build property chips for all properties in this style that differ from the 
parent.
+    Each chip shows the property name/value and has an X button to reset it to 
parent.
+    Chips are grouped by tab page.
+*/
+
+{
+    m_aPropertyRows.clear();
+
+    if (!pStyle->HasParentSupport() || pStyle->GetParent().isEmpty())
+        return;
+
+    MapUnit eUnit = MapUnit::MapCM;
+    FieldUnit eFieldUnit(FieldUnit::CM);
+    SfxModule* pModule = SfxModule::GetActiveModule();
+    if (pModule)
+    {
+        eFieldUnit = pModule->GetFieldUnit();
+    }
+
+    switch (eFieldUnit)
+    {
+        case FieldUnit::MM:      eUnit = MapUnit::MapMM; break;
+        case FieldUnit::CM:
+        case FieldUnit::M:
+        case FieldUnit::KM:      eUnit = MapUnit::MapCM; break;
+        case FieldUnit::POINT:
+        case FieldUnit::PICA:    eUnit = MapUnit::MapPoint; break;
+        case FieldUnit::INCH:
+        case FieldUnit::FOOT:
+        case FieldUnit::MILE:    eUnit = MapUnit::MapInch; break;
+        default:
+            break;
+    }
+
+    // Get the dialog controller to find tab page names
+    SfxTabDialogController* pDlgController = 
static_cast<SfxTabDialogController*>(GetDialogController());
+    if (pDlgController)
+        pDlgController->BuildWhichToTabMap();
+
+    // Use the virtual method to get individual property presentations
+    const SfxItemSet* pWorkingSet = pDlgController ? 
pDlgController->GetExampleSet() : nullptr;
+    std::vector<std::pair<sal_uInt16, OUString>> aItems = 
pStyle->GetItemPresentation(eUnit, pWorkingSet);
+
+    // Group items by tab page
+    std::map<OUString, std::vector<std::pair<sal_uInt16, OUString>>> 
aGroupedItems;
+
+    for (const auto& rItem : aItems)
+    {
+        // Skip items that user has explicitly reset
+        if (m_aResetWhichIds.find(rItem.first) != m_aResetWhichIds.end())
+            continue;
+
+        OUString sTabId;
+        if (pDlgController)
+        {
+            sTabId = pDlgController->GetTabPageNameForWhich(rItem.first);
+        }
+
+        if (sTabId.isEmpty())
+        {
+            continue;  // skip unclassifiable items
+        }
+
+        aGroupedItems[sTabId].push_back(rItem);
+    }
+
+    // Create category rows in tab order (not alphabetical)
+    std::vector<OUString> aTabOrder;
+    if (pDlgController)
+    {
+        aTabOrder = pDlgController->GetTabPageIds();
+    }
+    // Add "other" at the end for items not matching any tab
+    aTabOrder.push_back("other");
+
+    for (const auto& sTabId : aTabOrder)
+    {
+        auto itGroup = aGroupedItems.find(sTabId);
+        if (itGroup == aGroupedItems.end())
+            continue;  // No items for this tab
+
+        OUString sLabel;
+        if (pDlgController && sTabId != "other")
+        {
+            sLabel = pDlgController->GetTabPageLabel(sTabId);
+        }
+        if (sLabel.isEmpty())
+            sLabel = sTabId;
+
+        auto pRow = std::make_unique<PropertyCategoryRow>(m_xPropBox.get(), 
sLabel);
+
+        auto& aItemVec = itGroup->second;
+        std::sort(aItemVec.begin(), aItemVec.end(),
+            [&](const auto& a, const auto& b) {
+                auto itA = pDlgController->GetWhichOrder(a.first);
+                auto itB = pDlgController->GetWhichOrder(b.first);
+                return itA < itB;
+            });
+
+        for (const auto& rItem : itGroup->second)
+        {
+            pRow->AddChip(this, rItem.first, rItem.second);
+        }
+
+        m_aPropertyRows[sTabId] = std::move(pRow);
+    }
+
+    for (const auto& sTabId : aTabOrder)
+    {
+        auto it = m_aPropertyRows.find(sTabId);
+        if (it != m_aPropertyRows.end())
+            it->second->Show();
+    }
+
+    if (m_aPropertyRows.empty())
+    {
+        m_xDescFt->set_label(SfxResId(STR_NO_MODIFIED_PROPERTIES));
+        m_xDescFt->show();
+    }
+}
+
+void SfxManageStyleSheetPage::ResetPropertyToParent(sal_uInt16 nWhich)
+{
+    SfxItemSet& rSet = pStyle->GetItemSet();
+
+    // Clear this item to restore inheritance
+    rSet.ClearItem(nWhich);
+
+    // Track that user has reset this property
+    m_aResetWhichIds.insert(nWhich);
+
+    bModified = true;
+
+    // Invalidate this item in the dialog's output set
+    SfxTabDialogController* pDlgController = 
static_cast<SfxTabDialogController*>(GetDialogController());
+    if (pDlgController)
+    {
+        pDlgController->InvalidateItem(nWhich);
+    }
+
+    // Rebuild all chips from scratch — this avoids FlowBox residue issues
+    m_aPropertyRows.clear();
+    BuildPropertyChips_Impl();
+
+    // If no rows left, show the "all inherited" message
+    if (m_aPropertyRows.empty())
+    {
+        m_xDescFt->set_label(SfxResId(STR_NO_MODIFIED_PROPERTIES));
+        m_xDescFt->show();
+    }
 }
 
 IMPL_LINK_NOARG(SfxManageStyleSheetPage, EditStyleSelectHdl_Impl, 
weld::ComboBox&, void)
@@ -357,6 +685,38 @@ IMPL_LINK_NOARG(SfxManageStyleSheetPage, 
EditLinkStyleHdl_Impl, weld::Button&, v
         Execute_Impl( SID_STYLE_EDIT, aTemplName, 
static_cast<sal_uInt16>(pStyle->GetFamily()) );
 }
 
+IMPL_LINK_NOARG(SfxManageStyleSheetPage, EditPropsHdl_Impl, weld::Toggleable&, 
void)
+{
+    if (m_bInToggleHandler)
+        return;
+    m_bInToggleHandler = true;
+
+    m_xEditPropsBtn->set_active(true);
+    m_xViewPropsBtn->set_active(false);
+
+    m_bEditMode = true;
+    m_xDescFt->hide();
+    BuildPropertyChips_Impl();
+
+    m_bInToggleHandler = false;
+}
+
+IMPL_LINK_NOARG(SfxManageStyleSheetPage, ViewPropsHdl_Impl, weld::Toggleable&, 
void)
+{
+    if (m_bInToggleHandler)
+        return;
+    m_bInToggleHandler = true;
+
+    m_xViewPropsBtn->set_active(true);
+    m_xEditPropsBtn->set_active(false);
+
+    m_bEditMode = false;
+    m_aPropertyRows.clear();
+    SetDescriptionText_Impl();
+
+    m_bInToggleHandler = false;
+}
+
 // Internal: Perform functions through the Dispatcher
 bool SfxManageStyleSheetPage::Execute_Impl(
     sal_uInt16 nId, const OUString &rStr, sal_uInt16 nFamily)
@@ -454,7 +814,6 @@ bool SfxManageStyleSheetPage::FillItemSet( SfxItemSet* rSet 
)
     return bModified;
 }
 
-
 void SfxManageStyleSheetPage::Reset( const SfxItemSet* /*rAttrSet*/ )
 
 /*  [Description]
@@ -555,6 +914,14 @@ void SfxManageStyleSheetPage::ActivatePage( const 
SfxItemSet& rSet)
 */
 
 {
+    // Rebuild property chips when returning to this page in edit mode,
+    // so that changes made in other tab pages are reflected immediately.
+    if (m_bEditMode)
+    {
+        m_aPropertyRows.clear();
+        BuildPropertyChips_Impl();
+    }
+
     SetDescriptionText_Impl();
 
     // It is a style with auto update? (SW only)
diff --git a/sfx2/source/dialog/mgetempl.hxx b/sfx2/source/dialog/mgetempl.hxx
index 0e59c6862ef8..f5eaa8fa5253 100644
--- a/sfx2/source/dialog/mgetempl.hxx
+++ b/sfx2/source/dialog/mgetempl.hxx
@@ -21,7 +21,12 @@
 
 #include <sfx2/styfitem.hxx>
 #include <sfx2/tabdlg.hxx>
+#include <vcl/weld/Toolbar.hxx>
 #include <memory>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <set>
 
 namespace weld { class Button; }
 namespace weld { class CheckButton; }
@@ -30,11 +35,73 @@ namespace weld { class Entry; }
 namespace weld { class Label; }
 namespace weld { class Widget; }
 
+namespace weld { class Container; }
+namespace weld { class Box; }
+
+class SfxManageStyleSheetPage;
+
+/// A "chip" widget representing a single style property that can be reset to 
parent
+class PropertyChip final
+{
+private:
+    std::unique_ptr<weld::Builder> m_xBuilder;
+    std::unique_ptr<weld::Container> m_xContainer;
+    std::unique_ptr<weld::Label> m_xLabel;
+    std::unique_ptr<weld::Toolbar> m_xRemoveBtn;;
+
+    SfxManageStyleSheetPage* m_pPage;
+    OUString m_sText;
+    sal_uInt16 m_nWhich;
+
+    DECL_LINK(RemoveHdl, const OUString&, void);
+
+public:
+    PropertyChip(weld::Box* pParent, SfxManageStyleSheetPage* pPage,
+                 sal_uInt16 nWhich, const OUString& rText);
+    ~PropertyChip();
+
+    sal_uInt16 GetWhich() const { return m_nWhich; }
+    const OUString& GetText() const { return m_sText; }
+    SfxManageStyleSheetPage* GetPage() const { return m_pPage; }
+};
 /* expected:
     SID_TEMPLATE_NAME   :   In: StringItem, Name of Template
     SID_TEMPLATE_FAMILY :   In: Family of Template
 */
 
+/// A row containing chips for a single tab/category
+class PropertyCategoryRow final
+{
+private:
+    std::unique_ptr<weld::Builder> m_xBuilder;
+    std::unique_ptr<weld::Container> m_xContainer;
+    std::unique_ptr<weld::Label> m_xLabel;
+    std::unique_ptr<weld::Container> m_xChipsBox;
+    std::vector<std::unique_ptr<PropertyChip>> m_aChips;
+
+    struct ChipRow
+    {
+        std::unique_ptr<weld::Builder> xBuilder;
+        std::unique_ptr<weld::Box> xBox;
+        int nTotalChars = 0;  // estimated total character width
+    };
+    std::vector<std::unique_ptr<ChipRow>> m_aChipRows;
+    static constexpr int MAX_CHARS_PER_ROW = 100;
+
+    weld::Box* EnsureCurrentRow(int nChipChars);
+
+public:
+    PropertyCategoryRow(weld::Box* pParentBox, std::u16string_view rLabel);
+    ~PropertyCategoryRow();
+    void AddChip(SfxManageStyleSheetPage* pPage, sal_uInt16 nWhich, const 
OUString& rText);
+    void RemoveChip(sal_uInt16 nWhich);
+    bool IsEmpty() const { return m_aChips.empty(); }
+    void Show() { if (m_xContainer) m_xContainer->set_visible(true); }
+    void Hide() { if (m_xContainer) m_xContainer->set_visible(false); }
+    OUString GetLabel() const { return m_xLabel->get_label(); }
+    int GetChipRowCount() const { return static_cast<int>(m_aChipRows.size()); 
}
+};
+
 class SfxManageStyleSheetPage final : public SfxTabPage
 {
     SfxStyleSheetBase *pStyle;
@@ -60,8 +127,17 @@ class SfxManageStyleSheetPage final : public SfxTabPage
     std::unique_ptr<weld::Label> m_xFilterFt;
     std::unique_ptr<weld::ComboBox> m_xFilterLb;
     std::unique_ptr<weld::Label> m_xDescFt;
+    std::unique_ptr<weld::Box> m_xEditViewBox;
+    std::unique_ptr<weld::Toggleable> m_xEditPropsBtn;
+    std::unique_ptr<weld::Toggleable> m_xViewPropsBtn;
+    std::unique_ptr<weld::Box> m_xPropBox;
+    std::map<OUString, std::unique_ptr<PropertyCategoryRow>> m_aPropertyRows;
+    std::set<sal_uInt16> m_aResetWhichIds;  // Track Which IDs that user has 
reset
+    bool m_bEditMode = false;               // True after user clicks Edit
+    bool m_bInToggleHandler = false;
 
     friend class SfxStyleDialogController;
+    friend class PropertyChip;
 
     DECL_LINK(GetFocusHdl, weld::Widget&, void);
     DECL_LINK(LoseFocusHdl, weld::Widget&, void);
@@ -69,18 +145,20 @@ class SfxManageStyleSheetPage final : public SfxTabPage
     DECL_LINK(EditStyleHdl_Impl, weld::Button&, void);
     DECL_LINK(EditLinkStyleSelectHdl_Impl, weld::ComboBox&, void);
     DECL_LINK(EditLinkStyleHdl_Impl, weld::Button&, void);
-
+    DECL_LINK(EditPropsHdl_Impl, weld::Toggleable&, void);
+    DECL_LINK(ViewPropsHdl_Impl, weld::Toggleable&, void);
     void    UpdateName_Impl(weld::ComboBox*, const OUString &rNew);
     void    SetDescriptionText_Impl();
 
-
+    void    BuildPropertyChips_Impl();
+    void    ResetPropertyToParent(sal_uInt16 nWhich);
+    virtual void ActivatePage(const SfxItemSet& rSet) override;
     static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, 
weld::DialogController* pController, const SfxItemSet* );
 
     virtual bool        FillItemSet(SfxItemSet *) override;
     virtual void        Reset(const SfxItemSet *) override;
 
     static bool    Execute_Impl( sal_uInt16 nId, const OUString& rStr, 
sal_uInt16 nFamily );
-    virtual void        ActivatePage(const SfxItemSet &) override;
     virtual DeactivateRC DeactivatePage(SfxItemSet *) override;
 
 public:
diff --git a/sfx2/source/dialog/styledlg.cxx b/sfx2/source/dialog/styledlg.cxx
index 850c10bf3607..489cd69a84c2 100644
--- a/sfx2/source/dialog/styledlg.cxx
+++ b/sfx2/source/dialog/styledlg.cxx
@@ -81,6 +81,13 @@ SfxStyleDialogController::~SfxStyleDialogController()
 short SfxStyleDialogController::Ok()
 {
     SfxTabDialogController::Ok();
+
+    SfxItemSet& rStyleSet = m_rStyle.GetItemSet();
+    for (sal_uInt16 nWhich : m_aInvalidatedWhichIds)
+    {
+        rStyleSet.ClearItem(nWhich);
+    }
+
     return RET_OK;
 }
 
diff --git a/sfx2/source/dialog/tabdlg.cxx b/sfx2/source/dialog/tabdlg.cxx
index efb2fba57831..c17018d48987 100644
--- a/sfx2/source/dialog/tabdlg.cxx
+++ b/sfx2/source/dialog/tabdlg.cxx
@@ -37,9 +37,15 @@
 #include <sal/log.hxx>
 #include <tools/debug.hxx>
 #include <comphelper/lok.hxx>
+#include <editeng/editids.hrc>
+#include <svx/xdef.hxx>
 
 #include <sfx2/strings.hrc>
 #include <helpids.h>
+#include <map>
+#include <set>
+
+
 
 using namespace ::com::sun::star::uno;
 
@@ -60,6 +66,7 @@ namespace {
 struct Data_Impl
 {
     OUString sId;                 // The ID
+    OUString sLabel;              // The tab label
     CreateTabPage fnCreatePage;   // Pointer to Factory
     GetTabPageRanges fnGetRanges; // Pointer to Ranges-Function
     std::unique_ptr<SfxTabPage> xTabPage;         // The TabPage itself
@@ -595,7 +602,6 @@ bool 
SfxTabDialogController::DeactivatePage(std::u16string_view aPage)
     if (m_pSet)
     {
         SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() );
-
         if (pPage->HasExchangeSupport())
             nRet = pPage->DeactivatePage(&aTmp);
         else
@@ -605,6 +611,12 @@ bool 
SfxTabDialogController::DeactivatePage(std::u16string_view aPage)
         {
             m_xExampleSet->Put( aTmp );
             m_pOutSet->Put( aTmp );
+
+            // Re-clear any items that were explicitly invalidated by user
+            for (sal_uInt16 nWhich : m_aInvalidatedWhichIds)
+            {
+                m_xExampleSet->ClearItem(nWhich);
+            }
         }
     }
     else
@@ -817,6 +829,16 @@ short SfxTabDialogController::Ok()
     if (m_bStandardPushed)
         bModified = true;
 
+    if (!m_aInvalidatedWhichIds.empty())
+            bModified = true;
+
+    // Re-apply user-requested property resets after FillItemSet
+    for (sal_uInt16 nWhich : m_aInvalidatedWhichIds)
+    {
+        if (m_pOutSet)
+            m_pOutSet->ClearItem(nWhich);
+    }
+
     return bModified ? RET_OK : RET_CANCEL;
 }
 
@@ -877,11 +899,9 @@ void SfxTabDialogController::AddTabPage(const OUString 
&rName /* Page ID */,
 }
 
 /*  [Description]
-
     Add a page to the dialog. The Rider text is passed on, the page has no
     counterpart in the TabControl in the resource of the dialogue.
 */
-
 void SfxTabDialogController::AddTabPage(const OUString &rName, /* Page ID */
                                         const OUString& rRiderText,
                                         CreateTabPage pCreateFunc, /* Pointer 
to the Factory Method */
@@ -890,6 +910,10 @@ void SfxTabDialogController::AddTabPage(const OUString 
&rName, /* Page ID */
     assert(!m_xTabCtrl->get_page(rName) && "Double Page-Ids in the Tabpage");
     AddTabPage(rName, pCreateFunc, nullptr);
     m_xTabCtrl->append_page(rName, rRiderText, pIconName);
+    // Save the label in Data_Impl
+    auto it = Find(m_pImpl->aData, rName);
+    if (it != m_pImpl->aData.end())
+        (*it)->sLabel = rRiderText;
 }
 
 void SfxTabDialogController::AddTabPage(const OUString &rName, /* Page ID */
@@ -901,6 +925,10 @@ void SfxTabDialogController::AddTabPage(const OUString 
&rName, /* Page ID */
     assert(!m_xTabCtrl->get_page(rName) && "Double Page-Ids in the Tabpage");
     AddTabPage(rName, pCreateFunc, pRangesFunc);
     m_xTabCtrl->append_page(rName, rRiderText, &rIconName);
+    // Save the label in Data_Impl
+    auto it = Find(m_pImpl->aData, rName);
+    if (it != m_pImpl->aData.end())
+        (*it)->sLabel = rRiderText;
 }
 
 void SfxTabDialogController::AddTabPage(const OUString &rName,
@@ -918,6 +946,10 @@ void SfxTabDialogController::AddTabPage(const OUString 
&rName, const OUString& r
     assert(!m_xTabCtrl->get_page(rName) && "Double Page-Ids in the Tabpage");
     AddTabPage(rName, nPageCreateId);
     m_xTabCtrl->append_page(rName, rRiderText, pIconName);
+    // Save the label in Data_Impl
+    auto it = Find(m_pImpl->aData, rName);
+    if (it != m_pImpl->aData.end())
+        (*it)->sLabel = rRiderText;
 }
 
 void SfxTabDialogController::AddTabPage(const OUString &rName, const OUString& 
rRiderText,
@@ -1036,7 +1068,6 @@ void SfxTabDialogController::RemoveTabPage(const 
OUString& rId)
 void SfxTabDialogController::Start_Impl()
 {
     CreatePages();
-
     setPreviewsToSamePlace();
 
     assert(m_pImpl->aData.size() == 
static_cast<size_t>(m_xTabCtrl->get_n_pages())
@@ -1083,6 +1114,204 @@ OUString SfxTabDialogController::GetCurPageId() const
     return m_xTabCtrl->get_current_page_ident();
 }
 
+void SfxTabDialogController::ResetTabPage(std::u16string_view rPageId)
+{
+    SfxTabPage* pPage = GetTabPage(rPageId);
+    if (pPage)
+    {
+        const SfxItemSet* pSet = m_xExampleSet ? m_xExampleSet.get() : 
m_pSet.get();
+        if (pSet)
+        {
+            pPage->Reset(pSet);
+        }
+    }
+}
+
+void SfxTabDialogController::ResetAllTabPages()
+{
+    const SfxItemSet* pSet = m_xExampleSet ? m_xExampleSet.get() : 
m_pSet.get();
+    if (!pSet)
+        return;
+
+    for (auto const& elem : m_pImpl->aData)
+    {
+        if (elem->xTabPage)
+        {
+            elem->xTabPage->Reset(pSet);
+        }
+    }
+}
+
+void SfxTabDialogController::InvalidateItem(sal_uInt16 nWhich)
+{
+    m_aInvalidatedWhichIds.insert(nWhich);
+
+    if (m_xExampleSet)
+    {
+        m_xExampleSet->ClearItem(nWhich);
+    }
+    if (m_pOutSet)
+        m_pOutSet->InvalidateItem(nWhich);
+
+    if (!m_pSet)
+        return;
+
+    const SfxItemPool* pPool = m_pSet->GetPool();
+    if (!pPool)
+        return;
+
+    sal_uInt16 nSlotId = pPool->GetSlotId(nWhich);
+
+    for (auto const& elem : m_pImpl->aData)
+    {
+        if (!elem->xTabPage)
+            continue;
+
+        bool bFound = false;
+
+        if (elem->fnGetRanges)
+        {
+            const WhichRangesContainer aRanges = elem->fnGetRanges();
+
+            for (const auto& rPair : aRanges)
+            {
+                // Check 1: via SlotId
+                if (nSlotId >= rPair.first && nSlotId <= rPair.second)
+                {
+                    bFound = true;
+                    break;
+                }
+
+                // Check 2: iterate each slot, convert to WhichId
+                for (sal_uInt16 nSlot = rPair.first; nSlot <= rPair.second; 
++nSlot)
+                {
+                    if (pPool->GetWhichIDFromSlotID(nSlot) == nWhich)
+                    {
+                        bFound = true;
+                        break;
+                    }
+                }
+                if (bFound)
+                    break;
+            }
+        }
+
+        if (bFound)
+        {
+            const SfxItemSet* pResetSet = m_xExampleSet ? m_xExampleSet.get() 
: m_pSet.get();
+            if (pResetSet)
+            {
+                elem->xTabPage->Reset(pResetSet);
+            }
+        }
+        else
+        {
+            elem->bRefresh = true;
+        }
+    }
+}
+
+void SfxTabDialogController::BuildWhichToTabMap()
+{
+    if (!m_aWhichToTabMap.empty())
+        return;
+
+    const SfxItemSet* pSet = m_xExampleSet ? m_xExampleSet.get() : 
m_pSet.get();
+    if (!pSet)
+        return;
+
+    const SfxItemPool* pPool = m_pSet ? m_pSet->GetPool() : nullptr;
+
+    // Passata 1: tracker (copre le tab che accedono via Get/GetItemState)
+    for (auto const& elem : m_pImpl->aData)
+    {
+        if (!elem->xTabPage)
+            continue;
+
+        std::vector<sal_uInt16> aAccessed;
+        pSet->SetAccessTracker(&aAccessed);
+        elem->xTabPage->Reset(pSet);
+        pSet->SetAccessTracker(nullptr);
+
+        for (int i = 0; i < static_cast<int>(aAccessed.size()); ++i)
+        {
+            sal_uInt16 nWhich = aAccessed[i];
+            if (m_aWhichToTabMap.find(nWhich) == m_aWhichToTabMap.end())
+            {
+                m_aWhichToTabMap[nWhich] = elem->sId;
+                m_aWhichOrderMap[nWhich] = i;
+            }
+        }
+    }
+
+    // Passata 2: GetRanges (copre le tab che accedono ItemSet interni)
+    if (pPool)
+    {
+        for (auto const& elem : m_pImpl->aData)
+        {
+            if (!elem->fnGetRanges)
+                continue;
+
+            const WhichRangesContainer aRanges = elem->fnGetRanges();
+            for (const auto& rPair : aRanges)
+            {
+                for (sal_uInt16 nSlot = rPair.first; nSlot <= rPair.second; 
++nSlot)
+                {
+                    sal_uInt16 nWhich = pPool->GetWhichIDFromSlotID(nSlot);
+                    // Solo se non già classificato dal tracker
+                    if (m_aWhichToTabMap.find(nWhich) == 
m_aWhichToTabMap.end())
+                        m_aWhichToTabMap[nWhich] = elem->sId;
+                }
+            }
+        }
+    }
+
+    // Restore delle tab page
+    for (auto const& elem : m_pImpl->aData)
+    {
+        if (!elem->xTabPage)
+            continue;
+        if (elem->xTabPage->DeferResetToFirstActivation())
+            elem->bRefresh = true;
+        else
+            elem->xTabPage->Reset(pSet);
+    }
+}
+
+OUString SfxTabDialogController::GetTabPageNameForWhich(sal_uInt16 nWhich) 
const
+{
+    auto it = m_aWhichToTabMap.find(nWhich);
+    if (it != m_aWhichToTabMap.end())
+        return it->second;
+    return OUString();
+}
+
+OUString SfxTabDialogController::GetTabPageLabel(const OUString& rPageId) const
+{
+    // First try to get the label from Data_Impl
+    auto it = Find(m_pImpl->aData, rPageId);
+    if (it != m_pImpl->aData.end() && !(*it)->sLabel.isEmpty())
+        return (*it)->sLabel;
+
+    // Then try from the notebook
+    OUString sLabel = m_xTabCtrl->get_tab_label_text(rPageId);
+    if (!sLabel.isEmpty())
+        return sLabel;
+
+    // Last resort: return the page ID itself
+    return rPageId;
+}
+
+std::vector<OUString> SfxTabDialogController::GetTabPageIds() const
+{
+    std::vector<OUString> aResult;
+    for (auto const& elem : m_pImpl->aData)
+    {
+        aResult.push_back(elem->sId);
+    }
+    return aResult;
+}
+
 short SfxTabDialogController::run()
 {
     Start_Impl();
diff --git a/sfx2/uiconfig/ui/managestylepage.ui 
b/sfx2/uiconfig/ui/managestylepage.ui
index 59e6e91fcfd4..42f07abad6e6 100644
--- a/sfx2/uiconfig/ui/managestylepage.ui
+++ b/sfx2/uiconfig/ui/managestylepage.ui
@@ -245,18 +245,115 @@
         <property name="label-xalign">0</property>
         <property name="shadow-type">none</property>
         <child>
-          <object class="GtkLabel" id="desc">
+          <object class="GtkBox" id="containsbox">
             <property name="visible">True</property>
             <property name="can-focus">False</property>
-            <property name="margin-start">12</property>
+            <property name="margin-start">24</property>
             <property name="margin-top">6</property>
-            <property name="wrap">True</property>
-            <property name="max-width-chars">52</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <attributes>
-              <attribute name="scale" value="0.90000000000000002"/>
-            </attributes>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="desc">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="wrap">True</property>
+                <property name="max-width-chars">52</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0</property>
+                <attributes>
+                  <attribute name="scale" value="0.90000000000000002"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="propscroll">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="hscrollbar-policy">never</property>
+                <property name="vscrollbar-policy">automatic</property>
+                <property name="shadow-type">none</property>
+                <property name="min-content-height">60</property>
+                <property name="max-content-height">200</property>
+                <child>
+                  <object class="GtkViewport" id="propviewport">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="propbox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">4</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="editviewbox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="orientation">horizontal</property>
+                <property name="spacing">0</property>
+                <property name="halign">start</property>
+                <property name="margin-top">6</property>
+                <child>
+                  <object class="GtkToggleButton" id="viewprops">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="label" translatable="yes" 
context="managestylepage|viewprops">View</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="viewprops-atkobject">
+                        <property name="AtkObject::accessible-name" 
translatable="yes" context="managestylepage|viewprops">View style properties as 
description text</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToggleButton" id="editprops">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="label" translatable="yes" 
context="managestylepage|editprops">Edit</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="editprops-atkobject">
+                        <property name="AtkObject::accessible-name" 
translatable="yes" context="managestylepage|editprops">Edit style properties as 
interactive chips</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
           </object>
         </child>
         <child type="label">
@@ -271,7 +368,7 @@
         </child>
       </object>
       <packing>
-        <property name="expand">False</property>
+        <property name="expand">True</property>
         <property name="fill">True</property>
         <property name="position">1</property>
       </packing>
diff --git a/sfx2/uiconfig/ui/propertycategoryrow.ui 
b/sfx2/uiconfig/ui/propertycategoryrow.ui
new file mode 100644
index 000000000000..08315690d9e0
--- /dev/null
+++ b/sfx2/uiconfig/ui/propertycategoryrow.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="sfx">
+  <requires lib="gtk+" version="3.24"/>
+  <object class="GtkBox" id="PropertyCategoryRow">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">0</property>
+    <property name="margin-bottom">2</property>
+    <child>
+      <object class="GtkLabel" id="label">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="halign">start</property>
+        <property name="xalign">0</property>
+        <property name="label">Category:</property>
+        <child internal-child="accessible">
+          <object class="AtkObject" id="label-atkobject">
+            <property name="AtkObject::accessible-name" translatable="yes" 
context="propertycategoryrow|label">Property category name</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="chipsbox">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">0</property>
+        <property name="margin-start">12</property>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/sfx2/uiconfig/ui/propertychip.ui b/sfx2/uiconfig/ui/propertychip.ui
new file mode 100644
index 000000000000..0628e6b066e6
--- /dev/null
+++ b/sfx2/uiconfig/ui/propertychip.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="sfx">
+  <requires lib="gtk+" version="3.24"/>
+  <object class="GtkBox" id="PropertyChip">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="orientation">horizontal</property>
+    <property name="spacing">2</property>
+    <child>
+      <object class="GtkToolbar" id="removebar">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="toolbar-style">icons</property>
+        <property name="show-arrow">False</property>
+        <property name="icon_size">2</property>
+        <property name="valign">start</property>
+        <child>
+          <object class="GtkToolButton" id="remove">
+            <property name="visible">True</property>
+            <property name="icon-name">window-close-symbolic</property>
+            <property name="tooltip-text" translatable="yes" 
context="propertychip|remove">Reset this property to inherit from parent 
style</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="homogeneous">False</property>
+          </packing>
+        </child>
+        <style>
+          <class name="small-button"/>
+        </style>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="ellipsize">none</property>
+        <property name="xalign">0</property>
+        <attributes>
+          <attribute name="scale" value="0.90000000000000002"/>
+        </attributes>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/sfx2/uiconfig/ui/propertychiprow.ui 
b/sfx2/uiconfig/ui/propertychiprow.ui
new file mode 100644
index 000000000000..e4c5438975b5
--- /dev/null
+++ b/sfx2/uiconfig/ui/propertychiprow.ui
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="sfx">
+  <requires lib="gtk+" version="3.24"/>
+  <object class="GtkBox" id="PropertyChipRow">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="orientation">horizontal</property>
+    <property name="spacing">8</property>
+  </object>
+</interface>
diff --git a/solenv/sanitizers/ui/sfx.suppr b/solenv/sanitizers/ui/sfx.suppr
index 58fcd42eb62d..0996e9dd18d3 100644
--- a/solenv/sanitizers/ui/sfx.suppr
+++ b/solenv/sanitizers/ui/sfx.suppr
@@ -55,3 +55,5 @@ sfx2/uiconfig/ui/password.ui://GtkLevelBar[@id='pass1bar'] 
no-labelled-by
 sfx2/uiconfig/ui/password.ui://GtkLabel[@id='pass1policylabel'] orphan-label
 sfx2/uiconfig/ui/password.ui://GtkLevelBar[@id='pass2bar'] no-labelled-by
 sfx2/uiconfig/ui/password.ui://GtkLabel[@id='pass2policylabel'] orphan-label
+sfx2/uiconfig/ui/propertychip.ui://GtkLabel[@id='label'] orphan-label
+sfx2/uiconfig/ui/propertycategoryrow.ui://GtkLabel[@id='label'] orphan-label
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index 1911fcb3b82c..b2a8ad0e6f24 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -496,6 +496,12 @@ SfxItemState 
SfxItemSet::GetItemState_ForIter(PoolItemMap::const_iterator aHit,
 
 SfxItemState SfxItemSet::GetItemState_ForWhichID( SfxItemState eState, 
sal_uInt16 nWhich, bool bSrchInParent, const SfxPoolItem **ppItem) const
 {
+    if (m_pAccessTracker && !m_bAccessTrackerIgnore) {
+        if (std::find(m_pAccessTracker->begin(), m_pAccessTracker->end(), 
nWhich)
+                == m_pAccessTracker->end())
+            m_pAccessTracker->push_back(nWhich);
+    }
+
     PoolItemMap::const_iterator aHit(m_aPoolItemMap.find(nWhich));
 
     if (aHit != m_aPoolItemMap.end())
@@ -519,6 +525,12 @@ SfxItemState SfxItemSet::GetItemState_ForWhichID( 
SfxItemState eState, sal_uInt1
 
 bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const
 {
+    if (m_pAccessTracker && !m_bAccessTrackerIgnore) {
+        if (std::find(m_pAccessTracker->begin(), m_pAccessTracker->end(), 
nWhich)
+                == m_pAccessTracker->end())
+            m_pAccessTracker->push_back(nWhich);
+    }
+
     const bool bRet(SfxItemState::SET == 
GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, true, ppItem));
 
     // we need to reset ppItem when it was *not* set by GetItemState_ForWhichID
@@ -921,6 +933,12 @@ const SfxPoolItem* SfxItemSet::GetItem(sal_uInt16 nId, 
bool bSearchInParent) con
 
 const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool bSrchInParent) 
const
 {
+    if (m_pAccessTracker && !m_bAccessTrackerIgnore) {
+        if (std::find(m_pAccessTracker->begin(), m_pAccessTracker->end(), 
nWhich)
+                == m_pAccessTracker->end())
+            m_pAccessTracker->push_back(nWhich);
+    }
+
     PoolItemMap::const_iterator aHit(m_aPoolItemMap.find(nWhich));
 
     if (aHit != m_aPoolItemMap.end())
diff --git a/svl/source/items/style.cxx b/svl/source/items/style.cxx
index 594736cc43b1..441d756f4beb 100644
--- a/svl/source/items/style.cxx
+++ b/svl/source/items/style.cxx
@@ -364,6 +364,55 @@ OUString SfxStyleSheetBase::GetDescription( MapUnit 
eMetric )
     return aDesc.makeStringAndClear();
 }
 
+std::vector<std::pair<sal_uInt16, OUString>> 
SfxStyleSheetBase::GetItemPresentation(MapUnit eMetric, const SfxItemSet* 
/*pWorkingSet*/)
+{
+    std::vector<std::pair<sal_uInt16, OUString>> aResult;
+    SfxItemIter aIter(GetItemSet());
+    IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+
+    // Get parent item set for comparison
+    const SfxItemSet* pParentSet = nullptr;
+    SfxStyleSheetBase* pParentStyle = nullptr;
+    if (!GetParent().isEmpty())
+    {
+        pParentStyle = m_pPool->Find(GetParent(), GetFamily());
+        if (pParentStyle)
+            pParentSet = &pParentStyle->GetItemSet();
+    }
+
+    for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = 
aIter.NextItem())
+    {
+        if (IsInvalidItem(pItem))
+            continue;
+
+        sal_uInt16 nWhich = pItem->Which();
+
+        // Only include items that are set in this style (not inherited)
+        if (GetItemSet().GetItemState(nWhich, false) != SfxItemState::SET)
+            continue;
+
+        // Skip items identical to parent
+        if (pParentSet)
+        {
+            const SfxPoolItem* pParentItem = nullptr;
+            if (pParentSet->GetItemState(nWhich, true, &pParentItem) == 
SfxItemState::SET
+                && pParentItem && *pParentItem == *pItem)
+                continue;
+        }
+
+        OUString aItemPresentation;
+        if (m_pPool->GetPool().GetPresentation(*pItem, eMetric, 
aItemPresentation, aIntlWrapper))
+        {
+            if (!aItemPresentation.isEmpty())
+            {
+
+                aResult.emplace_back(nWhich, aItemPresentation);
+            }
+        }
+    }
+    return aResult;
+}
+
 inline bool SfxStyleSheetIterator::IsTrivialSearch() const
 {
     return (( nMask & SfxStyleSearchBits::AllVisible ) == 
SfxStyleSearchBits::AllVisible) &&
diff --git a/sw/inc/docstyle.hxx b/sw/inc/docstyle.hxx
index 1f2bffef3ac7..fbc0670d7973 100644
--- a/sw/inc/docstyle.hxx
+++ b/sw/inc/docstyle.hxx
@@ -132,6 +132,9 @@ public:
     virtual bool            HasParentSupport() const override;
     virtual bool            HasClearParentSupport() const override;
     virtual OUString        GetDescription(MapUnit eUnit) override;
+    virtual std::vector<std::pair<sal_uInt16, OUString>> GetItemPresentation(
+        MapUnit eMetric, const SfxItemSet* pWorkingSet = nullptr) override;
+    void ResetItems(const std::set<sal_uInt16>& rWhichIds);
 
     virtual OUString GetUsedBy() override;
 
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 9bc2d7db19f9..cd0160b28e72 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -1555,6 +1555,20 @@
 #define STR_UNDO_MAKE_ENDNOTES_FOOTNOTES 
NC_("STR_UNDO_MAKE_ENDNOTES_FOOTNOTES", "Make all endnotes footnotes")
 #define STR_UNDO_CONVERT_FIELD_TO_TEXT NC_("STR_UNDO_CONVERT_FIELD_TO_TEXT", 
"Convert field to text")
 
+// Attribute names for style property chips in the Organizer tab.
+// These labels are shown alongside property values when a style overrides
+// a property from its parent (e.g. "Outline Level: 6", "Fill Style: 
Gradient").
+// They are needed for Writer-specific attributes not covered by 
SvxAttrNameTable.
+#define STR_ATTR_OUTLINE_LEVEL                  NC_("STR_ATTR_OUTLINE_LEVEL", 
"Outline Level")
+#define STR_ATTR_LIST_LEVEL                     NC_("STR_ATTR_LIST_LEVEL", 
"List Level")
+#define STR_ATTR_LIST_RESTART                   NC_("STR_ATTR_LIST_RESTART", 
"List Restart")
+#define STR_ATTR_LIST_RESTART_VALUE             
NC_("STR_ATTR_LIST_RESTART_VALUE", "List Restart Value")
+#define STR_ATTR_TEXT_DIRECTION                 NC_("STR_ATTR_TEXT_DIRECTION", 
"Text Direction")
+#define STR_ATTR_HIDDEN                         NC_("STR_ATTR_HIDDEN", 
"Hidden")
+#define STR_ATTR_FILL_STYLE                     NC_("STR_ATTR_FILL_STYLE", 
"Fill Style")
+#define STR_ATTR_GRADIENT                       NC_("STR_ATTR_GRADIENT", 
"Gradient")
+#define STR_ATTR_GRADIENT_STEPS                 NC_("STR_ATTR_GRADIENT_STEPS", 
"Gradient Steps")
+
 // To translators: title, text, question for confirmation whether to switch 
overwrite mode on
 #define STR_QUERY_INSMODE_TITLE NC_("STR_QUERY_INSMODE_TITLE", "You are 
switching to the overwrite mode")
 #define STR_QUERY_INSMODE_TEXT NC_("STR_QUERY_INSMODE_TEXT", "The overwrite 
mode allows to type over text. It is indicated by a block cursor and at the 
statusbar. Press Insert again to switch back.")
diff --git a/sw/qa/uitest/ui/fmtui/tdf89826.py 
b/sw/qa/uitest/ui/fmtui/tdf89826.py
new file mode 100644
index 000000000000..d6f547779555
--- /dev/null
+++ b/sw/qa/uitest/ui/fmtui/tdf89826.py
@@ -0,0 +1,95 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+"""Tests for tdf#89826 - interactive property chips on Organizer tab."""
+
+from uitest.framework import UITestCase
+from uitest.uihelper.common import select_pos
+from uitest.uihelper.common import type_text
+from libreoffice.uno.propertyvalue import mkPropertyValues
+
+
+class tdf89826(UITestCase):
+
+    def _find_and_click_first_chip(self, xDialog):
+        """Navigate into propbox and click the remove button on the first chip.
+        Returns True if a chip was found and clicked."""
+        xPropBox = xDialog.getChild("propbox")
+        for sCatName in xPropBox.getChildren():
+            xCatRow = xPropBox.getChild(sCatName)
+            if "chipsbox" not in xCatRow.getChildren():
+                continue
+            xChipsBox = xCatRow.getChild("chipsbox")
+            for sRowName in xChipsBox.getChildren():
+                xChipRow = xChipsBox.getChild(sRowName)
+                for sChipName in xChipRow.getChildren():
+                    xChip = xChipRow.getChild(sChipName)
+                    if "removebar" in xChip.getChildren():
+                        xRemoveBar = xChip.getChild("removebar")
+                        xRemoveBar.executeAction("CLICK",
+                            mkPropertyValues({"POS": "0"}))
+                        return True
+        return False
+
+    def test_property_chip_reset(self):
+        """Test that removing a property via chip resets it to parent value,
+        and that undo restores it."""
+        with self.ui_test.create_doc_in_start_center("writer"):
+            document = self.ui_test.get_component()
+
+            # Create a new style
+            with self.ui_test.execute_dialog_through_command(
+                    ".uno:StyleNewByExample") as xDialog:
+                xStyleName = xDialog.getChild("stylename")
+                type_text(xStyleName, "Test Chip Style")
+
+            # Set parent and change font size in one dialog opening
+            with self.ui_test.execute_dialog_through_command(
+                    ".uno:EditStyle") as xDialog:
+                xTabs = xDialog.getChild("tabcontrol")
+                # Tab 0 = Organizer: set parent
+                select_pos(xTabs, "0")
+                xLinkedWith = xTabs.getChild("linkedwith")
+                xLinkedWith.executeAction("SELECT",
+                    mkPropertyValues({"TEXT": "Default Paragraph Style"}))
+                # Tab 1 = Character: change font size
+                select_pos(xTabs, "1")
+                xSizeWest = xTabs.getChild("cbWestSize")
+                xSizeWest.executeAction("CLEAR", tuple())
+                type_text(xSizeWest, "20pt")
+
+            # Verify font size was applied
+            xParaStyles = document.StyleFamilies.ParagraphStyles
+            self.assertEqual(
+                xParaStyles.getByName("Test Chip Style").getPropertyValue(
+                    "CharHeight"), 20)
+
+            # Open style dialog, switch to Edit mode, remove first chip
+            with self.ui_test.execute_dialog_through_command(
+                    ".uno:EditStyle") as xDialog:
+                xTabs = xDialog.getChild("tabcontrol")
+                select_pos(xTabs, "0")
+                xEditBtn = xDialog.getChild("editprops")
+                xEditBtn.executeAction("CLICK", tuple())
+                self.assertTrue(self._find_and_click_first_chip(xDialog),
+                    "No property chip found to remove")
+
+            # Property should now be inherited from parent
+            xParent = xParaStyles.getByName("Standard")
+            self.assertEqual(
+                xParaStyles.getByName("Test Chip Style").getPropertyValue(
+                    "CharHeight"),
+                xParent.getPropertyValue("CharHeight"))
+
+            # Undo should restore the removed property
+            self.xUITest.executeCommand(".uno:Undo")
+            self.assertEqual(
+                xParaStyles.getByName("Test Chip Style").getPropertyValue(
+                    "CharHeight"), 20)
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/ui/dialog/swdlgfact.cxx 
b/sw/source/ui/dialog/swdlgfact.cxx
index 50d7567486a0..3329399de2b7 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -94,6 +94,7 @@
 #include <translatelangselect.hxx>
 #include <copyfielddlg.hxx>
 #include <SwGridTabPage.hxx>
+#include <set>
 
 using namespace css::frame;
 using namespace css::uno;
@@ -375,6 +376,7 @@ public:
         return this->m_pDlg->GetInputRanges(pItem);
     }
     void SetInputSet(const SfxItemSet* pInSet) override { 
this->m_pDlg->SetInputSet(pInSet); }
+    const std::set<sal_uInt16>& GetInvalidatedWhichIds() const override { 
return this->m_pDlg->GetInvalidatedWhichIds(); }
     // From class Window.
     void SetText(const OUString& rStr) override { 
this->m_pDlg->set_title(rStr); }
 };
diff --git a/sw/source/ui/fmtui/tmpdlg.cxx b/sw/source/ui/fmtui/tmpdlg.cxx
index a7035e3edbb1..aaf212b27223 100644
--- a/sw/source/ui/fmtui/tmpdlg.cxx
+++ b/sw/source/ui/fmtui/tmpdlg.cxx
@@ -267,7 +267,7 @@ 
SwTemplateDlgController::SwTemplateDlgController(weld::Window* pParent,
 
 short SwTemplateDlgController::Ok()
 {
-    short nRet = SfxTabDialogController::Ok();
+    short nRet = SfxStyleDialogController::Ok();
     if( RET_OK == nRet )
     {
         const SfxPoolItem *pOutItem, *pExItem;
diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx
index 577337abffa7..93b5b9d63acb 100644
--- a/sw/source/uibase/app/docst.cxx
+++ b/sw/source/uibase/app/docst.cxx
@@ -20,6 +20,7 @@
 #include <config_wasm_strip.h>
 
 #include <memory>
+#include <set>
 
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
@@ -653,6 +654,11 @@ IMPL_LINK_NOARG(ApplyStyle, ApplyHdl, LinkParamNone*, void)
         // reset indent attributes at paragraph style, if a list style
         // will be applied and no indent attributes will be applied.
         m_xTmp->SetItemSet( aSet, false, true );
+
+        // Reset properties that user explicitly removed via property chips
+        const std::set<sal_uInt16>& rInvalidated = 
m_pDlg->GetInvalidatedWhichIds();
+        if (!rInvalidated.empty())
+            m_xTmp->ResetItems(rInvalidated);
     }
     else
     {
diff --git a/sw/source/uibase/app/docstyle.cxx 
b/sw/source/uibase/app/docstyle.cxx
index 45d0d8ad3c67..159a933e6b85 100644
--- a/sw/source/uibase/app/docstyle.cxx
+++ b/sw/source/uibase/app/docstyle.cxx
@@ -69,6 +69,7 @@
 #include <svx/xfillit0.hxx>
 #include <svx/xflftrit.hxx>
 #include <svx/drawitem.hxx>
+#include <svx/strarray.hxx>
 #include <names.hxx>
 
 using namespace com::sun::star;
@@ -1203,6 +1204,275 @@ OUString  SwDocStyleSheet::GetDescription(MapUnit eUnit)
     return SfxStyleSheetBase::GetDescription(eUnit);
 }
 
+std::vector<std::pair<sal_uInt16, OUString>> 
SwDocStyleSheet::GetItemPresentation(
+    MapUnit eMetric, const SfxItemSet* pWorkingSet)
+{
+    std::vector<std::pair<sal_uInt16, OUString>> aResult;
+    IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+
+    // Get parent item set for comparison
+    const SfxItemSet* pParentSet = nullptr;
+    SfxStyleSheetBase* pParentStyle = nullptr;
+    if (!GetParent().isEmpty())
+    {
+        pParentStyle = m_pPool->Find(GetParent(), nFamily);
+        if (pParentStyle)
+            pParentSet = &pParentStyle->GetItemSet();
+    }
+
+    if (SfxStyleFamily::Page == nFamily)
+    {
+        if (!pSet)
+            GetItemSet();
+
+        SfxItemIter aIter(*pSet);
+
+        for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = 
aIter.NextItem())
+        {
+            if (!IsInvalidItem(pItem))
+            {
+                // Only show items that are explicitly SET in this style, not 
inherited from parent
+                if (pSet->GetItemState(pItem->Which(), false) != 
SfxItemState::SET)
+                    continue;
+
+                // Skip items identical to parent
+                if (pParentSet)
+                {
+                    const SfxPoolItem* pParentItem = nullptr;
+                    if (pParentSet->GetItemState(pItem->Which(), true, 
&pParentItem) == SfxItemState::SET
+                        && pParentItem && *pParentItem == *pItem)
+                        continue;
+                }
+
+                // Skip items whose value equals the pool default
+                if (*pItem == 
pSet->GetPool()->GetUserOrPoolDefaultItem(pItem->Which()))
+                    continue;
+
+                switch (pItem->Which())
+                {
+                    case RES_LR_SPACE:
+                    case SID_ATTR_PAGE_SIZE:
+                    case SID_ATTR_PAGE_MAXSIZE:
+                    case SID_ATTR_PAGE_PAPERBIN:
+                    case SID_ATTR_BORDER_INNER:
+                        break;
+                    default:
+                    {
+                        OUString aItemPresentation;
+                        if (!IsInvalidItem(pItem) &&
+                            m_pPool->GetPool().GetPresentation(
+                                *pItem, eMetric, aItemPresentation, 
aIntlWrapper))
+                        {
+                            if (!aItemPresentation.isEmpty())
+                            {
+                                // If there isn't "Name: value", try adding 
the name
+                                if (aItemPresentation.indexOf(": ") == -1)
+                                {
+                                    sal_uInt16 nSlotId = 
m_pPool->GetPool().GetSlotId(pItem->Which());
+                                    sal_uInt32 nIdx = 
SvxAttrNameTable::FindIndex(nSlotId);
+                                    OUString aAttrName = 
SvxAttrNameTable::GetString(nIdx);
+                                    if (aAttrName.isEmpty())
+                                    {
+                                        // Fallback for Writer-specific WhichId
+                                        static const std::map<sal_uInt16, 
TranslateId> aSwAttrNames = {
+                                            { 
sal_uInt16(RES_PARATR_OUTLINELEVEL),      STR_ATTR_OUTLINE_LEVEL },
+                                            { 
sal_uInt16(RES_PARATR_LIST_LEVEL),        STR_ATTR_LIST_LEVEL },
+                                            { 
sal_uInt16(RES_PARATR_LIST_ISRESTART),    STR_ATTR_LIST_RESTART },
+                                            { 
sal_uInt16(RES_PARATR_LIST_RESTARTVALUE), STR_ATTR_LIST_RESTART_VALUE },
+                                            { 
sal_uInt16(RES_PARATR_AUTOFRAMEDIR),      STR_ATTR_TEXT_DIRECTION },
+                                            { sal_uInt16(RES_CHRATR_HIDDEN),   
         STR_ATTR_HIDDEN },
+                                            { sal_uInt16(XATTR_FILLSTYLE),     
         STR_ATTR_FILL_STYLE },
+                                            { sal_uInt16(XATTR_FILLGRADIENT),  
         STR_ATTR_GRADIENT },
+                                            { 
sal_uInt16(XATTR_GRADIENTSTEPCOUNT),      STR_ATTR_GRADIENT_STEPS },
+                                        };
+                                        auto itW = 
aSwAttrNames.find(pItem->Which());
+                                        if (itW != aSwAttrNames.end())
+                                            aAttrName = SwResId(itW->second);
+                                    }
+                                    if (!aAttrName.isEmpty())
+                                        aItemPresentation = aAttrName + ": " + 
aItemPresentation;
+                                }
+                                aResult.emplace_back(pItem->Which(), 
aItemPresentation);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return aResult;
+    }
+
+    if (SfxStyleFamily::Frame == nFamily || SfxStyleFamily::Para == nFamily || 
SfxStyleFamily::Char == nFamily)
+    {
+        if (!pSet)
+            GetItemSet();
+
+        const SfxItemSet* pCheckSet = pWorkingSet ? pWorkingSet : pSet;
+
+        const drawing::FillStyle 
eFillStyle(pCheckSet->Get(XATTR_FILLSTYLE).GetValue());
+        const bool 
bUseFloatTransparence(pCheckSet->Get(XATTR_FILLFLOATTRANSPARENCE).IsEnabled());
+
+        SfxItemIter aIter(*pSet);
+
+        for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = 
aIter.NextItem())
+        {
+            if (!IsInvalidItem(pItem))
+            {
+                // Only show items that are explicitly SET in this style, not 
inherited from parent
+                if (pCheckSet->GetItemState(pItem->Which(), false) != 
SfxItemState::SET)
+                    continue;
+
+                // Skip items identical to parent
+                if (pParentSet)
+                {
+                    const SfxPoolItem* pParentItem = nullptr;
+                    if (pParentSet->GetItemState(pItem->Which(), true, 
&pParentItem) == SfxItemState::SET
+                        && pParentItem && *pParentItem == *pItem)
+                        continue;
+                }
+
+                switch (pItem->Which())
+                {
+                    case SID_ATTR_AUTO_STYLE_UPDATE:
+                    case RES_PAGEDESC:
+                    case SID_ATTR_PARA_PAGENUM:
+                    case SID_ATTR_PARA_MODEL:
+                    case RES_BREAK:
+                        // Skip these - they have special handling in 
GetDescription
+                        break;
+                    default:
+                    {
+                        OUString aItemPresentation;
+                        if (!IsInvalidItem(pItem) &&
+                            m_pPool->GetPool().GetPresentation(
+                                *pItem, eMetric, aItemPresentation, 
aIntlWrapper))
+                        {
+                            bool bIsDefault = false;
+                            switch (pItem->Which())
+                            {
+                                case XATTR_FILLCOLOR:
+                                    bIsDefault = (drawing::FillStyle_SOLID == 
eFillStyle);
+                                    break;
+                                case XATTR_FILLGRADIENT:
+                                    bIsDefault = (drawing::FillStyle_GRADIENT 
== eFillStyle);
+                                    break;
+                                case XATTR_FILLHATCH:
+                                    bIsDefault = (drawing::FillStyle_HATCH == 
eFillStyle);
+                                    break;
+                                case XATTR_FILLBITMAP:
+                                    bIsDefault = (drawing::FillStyle_BITMAP == 
eFillStyle);
+                                    break;
+                                case XATTR_FILLTRANSPARENCE:
+                                    bIsDefault = !bUseFloatTransparence;
+                                    break;
+                                case XATTR_FILLFLOATTRANSPARENCE:
+                                    bIsDefault = bUseFloatTransparence;
+                                    break;
+                                case XATTR_GRADIENTSTEPCOUNT:
+                                    bIsDefault = bUseFloatTransparence;
+                                    break;
+                                case RES_CHRATR_CJK_FONT:
+                                case RES_CHRATR_CJK_FONTSIZE:
+                                case RES_CHRATR_CJK_LANGUAGE:
+                                case RES_CHRATR_CJK_POSTURE:
+                                case RES_CHRATR_CJK_WEIGHT:
+                                    if (SvtCJKOptions::IsCJKFontEnabled())
+                                        bIsDefault = true;
+                                    aItemPresentation = SwResId(STR_CJK_FONT) 
+ aItemPresentation;
+                                        break;
+                                case RES_CHRATR_CTL_FONT:
+                                case RES_CHRATR_CTL_FONTSIZE:
+                                case RES_CHRATR_CTL_LANGUAGE:
+                                case RES_CHRATR_CTL_POSTURE:
+                                case RES_CHRATR_CTL_WEIGHT:
+                                    if (SvtCTLOptions::IsCTLFontEnabled())
+                                        bIsDefault = true;
+                                    aItemPresentation = SwResId(STR_CTL_FONT) 
+ aItemPresentation;
+                                    break;
+                                case RES_CHRATR_FONT:
+                                case RES_CHRATR_FONTSIZE:
+                                case RES_CHRATR_LANGUAGE:
+                                case RES_CHRATR_POSTURE:
+                                case RES_CHRATR_WEIGHT:
+                                    aItemPresentation = 
SwResId(STR_WESTERN_FONT) + aItemPresentation;
+                                    [[fallthrough]];
+                                default:
+                                    bIsDefault = true;
+                            }
+                            if (bIsDefault && !aItemPresentation.isEmpty())
+                            {
+                                // If there isn't "Name: value", try adding 
the name
+                                if (aItemPresentation.indexOf(": ") == -1)
+                                {
+                                    sal_uInt16 nSlotId = 
m_pPool->GetPool().GetSlotId(pItem->Which());
+                                    sal_uInt32 nIdx = 
SvxAttrNameTable::FindIndex(nSlotId);
+                                    OUString aAttrName = 
SvxAttrNameTable::GetString(nIdx);
+                                    if (aAttrName.isEmpty())
+                                    {
+                                        // Fallback for Writer-specific WhichId
+                                        static const std::map<sal_uInt16, 
TranslateId> aSwAttrNames = {
+                                            { 
sal_uInt16(RES_PARATR_OUTLINELEVEL),      STR_ATTR_OUTLINE_LEVEL },
+                                            { 
sal_uInt16(RES_PARATR_LIST_LEVEL),        STR_ATTR_LIST_LEVEL },
+                                            { 
sal_uInt16(RES_PARATR_LIST_ISRESTART),    STR_ATTR_LIST_RESTART },
+                                            { 
sal_uInt16(RES_PARATR_LIST_RESTARTVALUE), STR_ATTR_LIST_RESTART_VALUE },
+                                            { 
sal_uInt16(RES_PARATR_AUTOFRAMEDIR),      STR_ATTR_TEXT_DIRECTION },
+                                            { sal_uInt16(RES_CHRATR_HIDDEN),   
         STR_ATTR_HIDDEN },
+                                            { sal_uInt16(XATTR_FILLSTYLE),     
         STR_ATTR_FILL_STYLE },
+                                            { sal_uInt16(XATTR_FILLGRADIENT),  
         STR_ATTR_GRADIENT },
+                                            { 
sal_uInt16(XATTR_GRADIENTSTEPCOUNT),      STR_ATTR_GRADIENT_STEPS },
+                                        };
+                                        auto itW = 
aSwAttrNames.find(pItem->Which());
+                                        if (itW != aSwAttrNames.end())
+                                            aAttrName = SwResId(itW->second);
+                                    }
+                                    if (!aAttrName.isEmpty())
+                                        aItemPresentation = aAttrName + ": " + 
aItemPresentation;
+                                }
+                                aResult.emplace_back(pItem->Which(), 
aItemPresentation);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return aResult;
+    }
+
+    if (SfxStyleFamily::Pseudo == nFamily)
+    {
+        return aResult;
+    }
+
+    return SfxStyleSheetBase::GetItemPresentation(eMetric);
+}
+
+void SwDocStyleSheet::ResetItems(const std::set<sal_uInt16>& rWhichIds)
+{
+    if (rWhichIds.empty())
+        return;
+
+    std::vector<sal_uInt16> aIds(rWhichIds.begin(), rWhichIds.end());
+
+    if (nFamily == SfxStyleFamily::Para)
+    {
+        SwTextFormatColl* pColl = 
m_rDoc.FindTextFormatCollByName(UIName(aName));
+        if (pColl)
+            m_rDoc.ResetAttrAtFormat(aIds, *pColl);
+    }
+    else if (nFamily == SfxStyleFamily::Char)
+    {
+        SwCharFormat* pCharFormat = m_rDoc.FindCharFormatByName(UIName(aName));
+        if (pCharFormat)
+            m_rDoc.ResetAttrAtFormat(aIds, *pCharFormat);
+    }
+    else if (nFamily == SfxStyleFamily::Frame)
+    {
+        SwFrameFormat* pFrameFormat = 
m_rDoc.FindFrameFormatByName(UIName(aName));
+        if (pFrameFormat)
+            m_rDoc.ResetAttrAtFormat(aIds, *pFrameFormat);
+    }
+}
+
 // Set names
 bool  SwDocStyleSheet::SetName(const OUString& rStr, bool bReindexNow)
 {

Reply via email to