tdf#168196 sw: copy header properties to all (first, even, odd)

Although a page style can have different CONTENTS
on left, right, and first pages,
the other header properties are the same/duplicated.

This patch tries to set up the plumbing,
and implements it for both the Borders and Background context dialog
as well as for the general Page Style dialog.

Unfortunately, our current implementation
does not use an actual shared format,
so the properties must be duplicated 4 times,
and yet sadly I couldn't find any existing mechanism
that attempted to keep them in sync.

Doing it properly doesn't sound like copy/paste,
so not something that I would attempt.

I don't see any interoperability reasons in DOC/DOCX
that would force the properties to be kept separate.
Certainly for ODF, it appears that only Master is exported
(in terms of the header and footer properties).

tdf#144448 was a nice duplicate report that pointed out the need
for FillHdFt to be used in order for Height/Spacing
to also be affected.
Otherwise SID_ATTR_PAGE_SIZE and SID_ATTR_PAGE_DYNAMIC
were just ignored as !GetRanges().doesContainWhich(nWhich)

Change-Id: I94f8cdf8bc6006dbea80941a2d6756e162f82411
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190420
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
This commit is contained in:
Justin Luth
2025-09-11 01:41:13 +02:00
parent 9064363550
commit 7d6bdb4e2a
7 changed files with 94 additions and 19 deletions
+3
View File
@@ -244,6 +244,9 @@ public:
const SwFrameFormat &GetFirstMaster() const { return m_FirstMaster; }
const SwFrameFormat &GetFirstLeft() const { return m_FirstLeft; }
/// Set format properties on all non-shared odd/even/first headers (or footers)
bool SetFormatAttrOnAll(const SfxItemSet& rSet, const bool bHeader);
/** Reset all attrs of the format but keep the ones a pagedesc
cannot live without. */
inline void ResetAllMasterAttr();
+54
View File
@@ -28,6 +28,7 @@
#include <sal/log.hxx>
#include <fmtclds.hxx>
#include <fmtfsize.hxx>
#include <fmthdft.hxx>
#include <pagefrm.hxx>
#include <pagedesc.hxx>
#include <swtable.hxx>
@@ -423,6 +424,59 @@ void SwPageDesc::ChgFirstShare( bool bNew )
m_eUse &= UseOnPage::NoFirstShare;
}
bool SwPageDesc::SetFormatAttrOnAll(const SfxItemSet& rSet, const bool bHeader)
{
if( !rSet.Count() )
return false;
// Warning: no attempt is made here to limit rSet to properties that are "safe"
// to duplicate to all of the different headers/footers.
assert(!rSet.HasItem(RES_CNTNT) && "unexpected use of SwPageDesc::SetFormatAttrOnAll");
bool bRet = false;
if (bHeader)
{
auto pHF = const_cast<SwFrameFormat*>(GetMaster().GetHeader().GetHeaderFormat());
bRet = pHF && pHF->SetFormatAttr(rSet);
if (bRet && !IsFirstShared())
{
pHF = const_cast<SwFrameFormat*>(GetFirstMaster().GetHeader().GetHeaderFormat());
pHF && pHF->SetFormatAttr(rSet);
}
if (bRet && !IsHeaderShared())
{
pHF = const_cast<SwFrameFormat*>(GetLeft().GetHeader().GetHeaderFormat());
pHF && pHF->SetFormatAttr(rSet);
if (!IsFirstShared())
{
pHF = const_cast<SwFrameFormat*>(GetFirstLeft().GetHeader().GetHeaderFormat());
pHF && pHF->SetFormatAttr(rSet);
}
}
}
else // footer
{
auto pHF = const_cast<SwFrameFormat*>(GetMaster().GetFooter().GetFooterFormat());
bRet = pHF && pHF->SetFormatAttr(rSet);
if (bRet && !IsFirstShared())
{
pHF = const_cast<SwFrameFormat*>(GetFirstMaster().GetFooter().GetFooterFormat());
pHF && pHF->SetFormatAttr(rSet);
}
if (bRet && !IsFooterShared())
{
pHF = const_cast<SwFrameFormat*>(GetLeft().GetFooter().GetFooterFormat());
pHF && pHF->SetFormatAttr(rSet);
if (bRet && !IsFirstShared())
{
pHF= const_cast<SwFrameFormat*>(GetFirstLeft().GetFooter().GetFooterFormat());
pHF && pHF->SetFormatAttr(rSet);
}
}
}
return bRet;
}
void SwPageDesc::StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bool bLeft, bool bFirst)
{
assert(rFormat.GetRegisteredIn());
+2 -1
View File
@@ -657,7 +657,8 @@ IMPL_LINK_NOARG(ApplyStyle, ApplyHdl, LinkParamNone*, void)
::ConvertAttrGenToChar(aTmpSet, m_xTmp->GetItemSet());
}
m_xTmp->SetItemSet( aTmpSet, false );
bool bParam1 = SfxStyleFamily::Page == m_nFamily; // bApplyToAllFormatFrames
m_xTmp->SetItemSet(aTmpSet, /*bBroadcast=*/ false, bParam1);
if( SfxStyleFamily::Page == m_nFamily && SvtCTLOptions::IsCTLFontEnabled() )
{
+4 -3
View File
@@ -1622,8 +1622,7 @@ void SwDocStyleSheet::MergeIndentAttrsOfListStyle( SfxItemSet& rSet )
}
// handling of parameter <bResetIndentAttrsAtParagraphStyle>
void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, const bool bBroadcast,
const bool bResetIndentAttrsAtParagraphStyle )
void SwDocStyleSheet::SetItemSet(const SfxItemSet& rSet, const bool bBroadcast, const bool bParam1)
{
// if applicable determine format first
if(!m_bPhysical)
@@ -1715,6 +1714,7 @@ void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, const bool bBroadcast,
m_rDoc.DelTextFormatColl( m_pColl );
m_pColl = pCColl;
}
const bool bResetIndentAttrsAtParagraphStyle = bParam1;
if ( bResetIndentAttrsAtParagraphStyle &&
rSet.GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET &&
rSet.GetItemState(RES_MARGIN_FIRSTLINE, false) != SfxItemState::SET &&
@@ -1892,7 +1892,8 @@ void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, const bool bBroadcast,
if( pNewDsc )
{
::ItemSetToPageDesc( aSet, *pNewDsc );
const bool bApplyToAllFormatFrames = bParam1;
::ItemSetToPageDesc(aSet, *pNewDsc, bApplyToAllFormatFrames);
m_rDoc.ChgPageDesc( nPgDscPos, *pNewDsc );
m_pDesc = &m_rDoc.GetPageDesc( nPgDscPos );
m_rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983#
+5 -3
View File
@@ -488,8 +488,8 @@ void SwHeaderFooterWin::ExecuteCommand(std::u16string_view rIdent)
}
else if (rIdent == u"borderback")
{
const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
const SwFrameFormat& rMaster = pDesc->GetMaster();
SwPageDesc& rPageDesc = const_cast<SwPageDesc&>(*pPageFrame->GetPageDesc());
SwFrameFormat& rMaster = rPageDesc.GetMaster();
SwFrameFormat* pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetFooter().GetFooterFormat() );
if ( m_bIsHeader )
pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetHeader().GetHeaderFormat() );
@@ -517,7 +517,9 @@ void SwHeaderFooterWin::ExecuteCommand(std::u16string_view rIdent)
if (svx::ShowBorderBackgroundDlg( GetFrameWeld(), &aSet ) )
{
pHFFormat->SetFormatAttr( aSet );
// Apply the modified format to all (first, even, odd) of the page style's FrameFormats
aSet.DisableItem(RES_CNTNT); // don't duplicate the content though...
rPageDesc.SetFormatAttrOnAll(aSet, m_bIsHeader);
rView.GetDocShell()->SetModified();
}
}
+2 -1
View File
@@ -69,7 +69,8 @@ SW_DLLPUBLIC void ConvertAttrGenToChar(SfxItemSet& rSet, const SfxItemSet& rOrig
void ApplyCharBackground(Color const& rBackgroundColor, model::ComplexColor const& rComplexColor, SwWrtShell& rShell);
// SfxItemSets <-> PageDesc
void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc );
void ItemSetToPageDesc(const SfxItemSet& rSet, SwPageDesc& rPageDesc,
bool bApplyToAllFormatFrames = false);
void PageDescToItemSet( const SwPageDesc& rPageDesc, SfxItemSet& rSet);
// fill tabs with default tabs
+24 -11
View File
@@ -225,8 +225,20 @@ void ApplyCharBackground(Color const& rBackgroundColor, model::ComplexColor cons
// Fill header footer
static void FillHdFt(SwFrameFormat* pFormat, const SfxItemSet& rSet)
static void FillHdFt(SfxPoolItem& rFormat, const SfxItemSet& rSet, SwPageDesc& rPageDesc,
bool bApplyToAllFormatFrames)
{
auto pHeader = dynamic_cast<SwFormatHeader*>(&rFormat);
auto pFooter = dynamic_cast<SwFormatFooter*>(&rFormat);
assert(pHeader || pFooter);
SwFrameFormat* pFormat;
if (pHeader)
pFormat = pHeader->GetHeaderFormat();
else
pFormat = pFooter->GetFooterFormat();
OSL_ENSURE(pFormat != nullptr, "no header or footer format");
SwAttrSet aSet(pFormat->GetAttrSet());
aSet.Put(rSet);
@@ -238,7 +250,14 @@ static void FillHdFt(SwFrameFormat* pFormat, const SfxItemSet& rSet)
rSize.GetSize().Width(),
rSize.GetSize().Height());
aSet.Put(aFrameSize);
pFormat->SetFormatAttr(aSet);
if (bApplyToAllFormatFrames)
{
// Apply the modified format to all (first, even, odd) of the page style's FrameFormats
aSet.DisableItem(RES_CNTNT); // don't duplicate the content though...
rPageDesc.SetFormatAttrOnAll(aSet, bool(pHeader));
}
else
pFormat->SetFormatAttr(aSet);
}
/// Convert from UseOnPage to SvxPageUsage.
@@ -273,7 +292,7 @@ static UseOnPage lcl_convertUseFromSvx(SvxPageUsage nUse)
// PageDesc <-> convert into sets and back
void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc )
void ItemSetToPageDesc(const SfxItemSet& rSet, SwPageDesc& rPageDesc, bool bApplyToAllFormatFrames)
{
SwFrameFormat& rMaster = rPageDesc.GetMaster();
bool bFirstShare = false;
@@ -364,10 +383,7 @@ void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc )
// Pick out everything and adapt the header format
SwFormatHeader aHeaderFormat(rMaster.GetHeader());
SwFrameFormat *pHeaderFormat = aHeaderFormat.GetHeaderFormat();
OSL_ENSURE(pHeaderFormat != nullptr, "no header format");
::FillHdFt(pHeaderFormat, rHeaderSet);
::FillHdFt(aHeaderFormat, rHeaderSet, rPageDesc, bApplyToAllFormatFrames);
rPageDesc.ChgHeaderShare(rHeaderSet.Get(SID_ATTR_PAGE_SHARED).GetValue());
rPageDesc.ChgFirstShare(static_cast<const SfxBoolItem&>(
@@ -400,10 +416,7 @@ void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc )
// Pick out everything and adapt the footer format
SwFormatFooter aFooterFormat(rMaster.GetFooter());
SwFrameFormat *pFooterFormat = aFooterFormat.GetFooterFormat();
OSL_ENSURE(pFooterFormat != nullptr, "no footer format");
::FillHdFt(pFooterFormat, rFooterSet);
::FillHdFt(aFooterFormat, rFooterSet, rPageDesc, bApplyToAllFormatFrames);
rPageDesc.ChgFooterShare(rFooterSet.Get(SID_ATTR_PAGE_SHARED).GetValue());
if (!bFirstShare)