View Issue Details

IDProjectCategoryView StatusLast Update
0017887ScribusImport / Exportpublic2026-08-31 14:45
Reporterqirat Assigned Tojghali  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformLinuxOSFedora WorkstationOS Version44
Product Version1.7.4.svn 
Fixed in Version1.6.7.svn 
Summary0017887: Property changes do not affect the text imported from .odt
DescriptionWhen text is imported from an odt file, most changes made in the Paragraph Style's "Properties" tab do not work/apply.

These do not work:
- text alignment
- line spacing mode
- optical margins
- colours: background
- first line indent, left/right indent

Some work like Direction (RTL, LTR)
Steps To Reproduce- Create new doc and draw a text frame
- Right-click the text frame > Content > Get text (choose .odt file)
- Click inside a para (heading, or any para)
- In PP, click the Edit button to open Style Manager
- In Properties tab, change any of the above mentioned for not working
- Apply changes: no effect
Additional InformationTested in 1.7.2 flatpak: same issue.

Here is a patch (created with AI) that fixed it for me.
TagsNo tags attached.
Attached Files
odt-paragraph-style-inheritance-fix.patch (5,440 bytes)   
diff --git a/scribus/plugins/gettext/odt2im/importodt.cpp b/scribus/plugins/gettext/odt2im/importodt.cpp
index dacc5b21325b78cd3eafda321cd4754f54561a3d..ac20e7e3c3866880ad342f1b03687cb7a4c5e38d 100644
--- a/scribus/plugins/gettext/odt2im/importodt.cpp
+++ b/scribus/plugins/gettext/odt2im/importodt.cpp
@@ -715,6 +715,38 @@ bool ODTIm::parseDocReferenceXML(const QDomDocument &designMapDom)
 	return true;
 }
 
+bool ODTIm::findNamedParagraphStyle(const QString& styleName, QString& sourceStyleName, QString& importedStyleName) const
+{
+	sourceStyleName.clear();
+	importedStyleName.clear();
+
+	QString currentName = styleName;
+	for (auto remaining = m_Styles.size(); remaining > 0 && !currentName.isEmpty(); --remaining)
+	{
+		auto styleIt = m_Styles.constFind(currentName);
+		if (styleIt == m_Styles.constEnd())
+			break;
+
+		const DrawStyle& style = styleIt.value();
+		if (style.styleOrigin.valid && style.styleType.valid
+			&& style.styleOrigin.value == "styles"
+			&& style.styleType.value == "paragraph")
+		{
+			sourceStyleName = currentName;
+			importedStyleName = style.displayName.valid ? style.displayName.value : currentName;
+			if (m_prefixName)
+				importedStyleName.prepend(m_item->itemName() + "_");
+			return true;
+		}
+
+		if (!style.parentStyle.valid)
+			break;
+		currentName = style.parentStyle.value;
+	}
+
+	return false;
+}
+
 void ODTIm::parseTextSpan(const QDomElement &elem, PageItem* item, const ParagraphStyle &tmpStyle, const CharStyle &tmpCStyle, const ObjStyleODT &tmpOStyle, int &posC)
 {
 	if (!elem.hasChildNodes())
@@ -869,35 +901,20 @@ void ODTIm::parseTextList(const QDomNode& elem, PageItem* item, const ParagraphS
 void ODTIm::parseTextParagraph(const QDomNode &elem, PageItem* item, const ParagraphStyle &newStyle, const ObjStyleODT &tmpOStyle, int &posC)
 {
 	ParagraphStyle tmpStyle = newStyle;
-	CharStyle tmpCStyle = tmpStyle.charStyle();
 	ObjStyleODT pStyle = tmpOStyle;
 	QString parStyleName;
+	QString namedOdtStyleName;
+	bool hasNamedParagraphStyle = false;
 
 	QString pStyleName = elem.toElement().attribute("text:style-name");
 	if (!pStyleName.isEmpty())
 	{
 		resolveStyle(pStyle, pStyleName);
-		if (m_Styles.contains(pStyleName))
-		{
-			DrawStyle currStyle = m_Styles[pStyleName];
-			if (currStyle.styleOrigin.value == "styles")
-			{
-				if (m_prefixName)
-				{
-					parStyleName = m_item->itemName() + "_" + pStyleName;
-					if (currStyle.displayName.valid)
-						parStyleName = m_item->itemName() + "_" + currStyle.displayName.value;
-				}
-				else
-				{
-					parStyleName = pStyleName;
-					if (currStyle.displayName.valid)
-						parStyleName = currStyle.displayName.value;
-				}
-			}
-		}
+		hasNamedParagraphStyle = findNamedParagraphStyle(pStyleName, namedOdtStyleName, parStyleName);
 		m_textStylesStack.push(pStyleName);
 	}
+
+	CharStyle tmpCStyle = tmpStyle.charStyle();
 	if ((pStyle.breakBefore == "column") && (item->itemText.isNotEmpty()))
 	{
 		QString txt = SpecialChars::COLBREAK;
@@ -908,24 +925,36 @@ void ODTIm::parseTextParagraph(const QDomNode &elem, PageItem* item, const Parag
 		QString txt = SpecialChars::FRAMEBREAK;
 		insertChars(item, txt, tmpStyle, tmpCStyle, posC);
 	}
+
+	if (hasNamedParagraphStyle)
+	{
+		// A paragraph assigned to a named style should not retain the importer's
+		// default paragraph values as local overrides.
+		tmpStyle.erase();
+		tmpStyle.setParent(parStyleName);
+	}
 	applyParagraphStyle(tmpStyle, pStyle);
 
+	if (hasNamedParagraphStyle)
+	{
+		ObjStyleODT inheritedStyle = tmpOStyle;
+		resolveStyle(inheritedStyle, namedOdtStyleName);
+
+		ParagraphStyle inheritedParagraphStyle;
+		inheritedParagraphStyle.erase();
+		applyParagraphStyle(inheritedParagraphStyle, inheritedStyle);
+
+		// Keep the named Scribus style as the paragraph base and retain only
+		// paragraph properties introduced by an ODT automatic style.
+		tmpStyle.eraseStyle(inheritedParagraphStyle);
+		tmpStyle.setParent(parStyleName);
+	}
+
+	tmpCStyle = tmpStyle.charStyle();
+	applyCharacterStyle(tmpCStyle, pStyle);
+
 	for (QDomNode spn = elem.firstChild(); !spn.isNull(); spn = spn.nextSibling())
 	{
-		if (!parStyleName.isEmpty())
-		{
-			tmpStyle.setParent(parStyleName);
-			applyParagraphStyle(tmpStyle, pStyle);
-			tmpCStyle = tmpStyle.charStyle();
-			applyCharacterStyle(tmpCStyle, pStyle);
-		}
-		else
-		{
-			tmpStyle = newStyle;
-			applyParagraphStyle(tmpStyle, pStyle);
-			tmpCStyle = tmpStyle.charStyle();
-			applyCharacterStyle(tmpCStyle, pStyle);
-		}
 		QString txt;
 		ObjStyleODT cStyle = pStyle;
 		QDomElement spEl = spn.toElement();
diff --git a/scribus/plugins/gettext/odt2im/importodt.h b/scribus/plugins/gettext/odt2im/importodt.h
index 9102e76dc833c225273e2d1d6d559d78f127c9a3..eac03e3236e936c13932f66bdfbd8cb9476ee9aa 100644
--- a/scribus/plugins/gettext/odt2im/importodt.h
+++ b/scribus/plugins/gettext/odt2im/importodt.h
@@ -138,6 +138,7 @@ private:
 	void applyCharacterStyle(CharStyle &tmpCStyle, const ObjStyleODT &oStyle);
 	void applyParagraphStyle(ParagraphStyle &tmpStyle, const ObjStyleODT &oStyle);
 	void resolveStyle(ObjStyleODT &tmpOStyle, const QString& pAttrs);
+	bool findNamedParagraphStyle(const QString& styleName, QString& sourceStyleName, QString& importedStyleName) const;
 	double parseUnit(const QString &unit) const;
 	QString parseColor( const QString &s );
 	QString constructFontName(const QString& fontBaseName, const QString& fontStyle);
sample_test_file.odt (42,264 bytes)
PatchYes

Activities

jghali

2026-08-31 10:49

administrator   ~0054386

I applied your patch to both trunk and 1.6.x branches, thanks!

qirat

2026-08-31 14:45

reporter   ~0054387

Thanks, @jghali. Glad it helped. :)

Issue History

Date Modified Username Field Change
2026-07-12 12:22 qirat New Issue
2026-07-12 12:22 qirat File Added: odt-paragraph-style-inheritance-fix.patch
2026-07-12 12:22 qirat File Added: sample_test_file.odt
2026-08-31 10:01 jghali Summary Property changes do not affect the text imported from. odt => Property changes do not affect the text imported from .odt
2026-08-31 10:49 jghali Assigned To => jghali
2026-08-31 10:49 jghali Status new => resolved
2026-08-31 10:49 jghali Resolution open => fixed
2026-08-31 10:49 jghali Fixed in Version => 1.6.7.svn
2026-08-31 10:49 jghali Note Added: 0054386
2026-08-31 14:45 qirat Note Added: 0054387