novelWriter 2.6b1__py3-none-any.whl → 2.6b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/METADATA +3 -3
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/RECORD +68 -52
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +49 -10
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +2 -2
- novelwriter/assets/i18n/project_ru_RU.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +7 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
- novelwriter/assets/icons/typicons_light/icons.conf +7 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/credits_en.htm +1 -0
- novelwriter/common.py +37 -2
- novelwriter/config.py +15 -12
- novelwriter/constants.py +24 -9
- novelwriter/core/coretools.py +111 -125
- novelwriter/core/docbuild.py +3 -2
- novelwriter/core/index.py +9 -19
- novelwriter/core/item.py +39 -6
- novelwriter/core/itemmodel.py +518 -0
- novelwriter/core/project.py +67 -89
- novelwriter/core/status.py +7 -5
- novelwriter/core/tree.py +268 -287
- novelwriter/dialogs/docmerge.py +7 -17
- novelwriter/dialogs/preferences.py +3 -3
- novelwriter/dialogs/projectsettings.py +2 -2
- novelwriter/enum.py +7 -0
- novelwriter/extensions/configlayout.py +6 -4
- novelwriter/formats/todocx.py +34 -38
- novelwriter/formats/tohtml.py +14 -15
- novelwriter/formats/tokenizer.py +21 -17
- novelwriter/formats/toodt.py +53 -124
- novelwriter/formats/toqdoc.py +92 -44
- novelwriter/gui/doceditor.py +230 -219
- novelwriter/gui/docviewer.py +38 -9
- novelwriter/gui/docviewerpanel.py +14 -22
- novelwriter/gui/itemdetails.py +17 -24
- novelwriter/gui/mainmenu.py +13 -8
- novelwriter/gui/noveltree.py +12 -12
- novelwriter/gui/outline.py +10 -11
- novelwriter/gui/projtree.py +548 -1202
- novelwriter/gui/search.py +9 -10
- novelwriter/gui/theme.py +7 -3
- novelwriter/guimain.py +59 -43
- novelwriter/shared.py +52 -23
- novelwriter/text/patterns.py +17 -5
- novelwriter/tools/manusbuild.py +13 -11
- novelwriter/tools/manussettings.py +42 -52
- novelwriter/types.py +7 -1
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/top_level.txt +0 -0
novelwriter/formats/toodt.py
CHANGED
@@ -43,7 +43,7 @@ from novelwriter.constants import nwHeadFmt, nwStyles
|
|
43
43
|
from novelwriter.core.project import NWProject
|
44
44
|
from novelwriter.formats.shared import BlockFmt, BlockTyp, TextFmt, stripEscape
|
45
45
|
from novelwriter.formats.tokenizer import Tokenizer
|
46
|
-
from novelwriter.types import FONT_STYLE,
|
46
|
+
from novelwriter.types import FONT_STYLE, QtHexRgb
|
47
47
|
|
48
48
|
logger = logging.getLogger(__name__)
|
49
49
|
|
@@ -173,44 +173,10 @@ class ToOdt(Tokenizer):
|
|
173
173
|
self._fontStyle = "normal"
|
174
174
|
self._fontPitch = "variable"
|
175
175
|
self._fontBold = "bold"
|
176
|
-
self._fSizeTitle = "30pt"
|
177
|
-
self._fSizeHead1 = "24pt"
|
178
|
-
self._fSizeHead2 = "20pt"
|
179
|
-
self._fSizeHead3 = "16pt"
|
180
|
-
self._fSizeHead4 = "14pt"
|
181
|
-
self._fSizeHead = "14pt"
|
182
|
-
self._fSizeText = "12pt"
|
183
|
-
self._fSizeFoot = "10pt"
|
184
|
-
self._fLineHeight = "115%"
|
185
176
|
self._fBlockIndent = "1.693cm"
|
186
|
-
self._fTextIndent = "0.499cm"
|
187
177
|
self._dLanguage = "en"
|
188
178
|
self._dCountry = "GB"
|
189
179
|
|
190
|
-
# Text Margins
|
191
|
-
self._mTopTitle = "0.423cm"
|
192
|
-
self._mTopHead1 = "0.423cm"
|
193
|
-
self._mTopHead2 = "0.353cm"
|
194
|
-
self._mTopHead3 = "0.247cm"
|
195
|
-
self._mTopHead4 = "0.247cm"
|
196
|
-
self._mTopHead = "0.423cm"
|
197
|
-
self._mTopText = "0.000cm"
|
198
|
-
self._mTopMeta = "0.000cm"
|
199
|
-
self._mTopSep = "0.247cm"
|
200
|
-
|
201
|
-
self._mBotTitle = "0.212cm"
|
202
|
-
self._mBotHead1 = "0.212cm"
|
203
|
-
self._mBotHead2 = "0.212cm"
|
204
|
-
self._mBotHead3 = "0.212cm"
|
205
|
-
self._mBotHead4 = "0.212cm"
|
206
|
-
self._mBotHead = "0.212cm"
|
207
|
-
self._mBotText = "0.247cm"
|
208
|
-
self._mBotMeta = "0.106cm"
|
209
|
-
self._mBotSep = "0.247cm"
|
210
|
-
|
211
|
-
self._mBotFoot = "0.106cm"
|
212
|
-
self._mLeftFoot = "0.600cm"
|
213
|
-
|
214
180
|
# Document Size and Margins
|
215
181
|
self._mDocWidth = "21.0cm"
|
216
182
|
self._mDocHeight = "29.7cm"
|
@@ -254,60 +220,16 @@ class ToOdt(Tokenizer):
|
|
254
220
|
# Initialise Variables
|
255
221
|
# ====================
|
256
222
|
|
257
|
-
intWeight = FONT_WEIGHTS.get(self._textFont.weight(), 400)
|
258
|
-
fontWeight = str(intWeight)
|
259
|
-
fontBold = str(min(intWeight + 300, 900))
|
260
|
-
|
261
223
|
lang, _, country = self._dLocale.name().partition("_")
|
262
224
|
self._dLanguage = lang or self._dLanguage
|
263
225
|
self._dCountry = country or self._dCountry
|
264
226
|
|
265
|
-
self._fontFamily
|
266
|
-
self._fontSize
|
267
|
-
self.
|
268
|
-
self.
|
269
|
-
self.
|
270
|
-
self._fontBold = FONT_WEIGHT_MAP.get(fontBold, fontBold)
|
271
|
-
self._headWeight = self._fontBold if self._boldHeads else None
|
272
|
-
|
273
|
-
hScale = self._scaleHeads
|
274
|
-
self._fSizeTitle = self._emToPt(nwStyles.H_SIZES[0] if hScale else 1.0) # Was 2.50
|
275
|
-
self._fSizeHead1 = self._emToPt(nwStyles.H_SIZES[1] if hScale else 1.0) # Was 2.00
|
276
|
-
self._fSizeHead2 = self._emToPt(nwStyles.H_SIZES[2] if hScale else 1.0) # Was 1.60
|
277
|
-
self._fSizeHead3 = self._emToPt(nwStyles.H_SIZES[3] if hScale else 1.0) # Was 1.30
|
278
|
-
self._fSizeHead4 = self._emToPt(nwStyles.H_SIZES[4] if hScale else 1.0) # Was 1.15
|
279
|
-
self._fSizeHead = self._emToPt(nwStyles.H_SIZES[4] if hScale else 1.0) # Was 1.15
|
280
|
-
self._fSizeText = self._emToPt(1.0)
|
281
|
-
self._fSizeFoot = self._emToPt(0.8)
|
282
|
-
|
283
|
-
mScale = self._lineHeight/1.15
|
284
|
-
|
285
|
-
self._mTopTitle = self._emToCm(mScale * self._marginTitle[0])
|
286
|
-
self._mTopHead1 = self._emToCm(mScale * self._marginHead1[0])
|
287
|
-
self._mTopHead2 = self._emToCm(mScale * self._marginHead2[0])
|
288
|
-
self._mTopHead3 = self._emToCm(mScale * self._marginHead3[0])
|
289
|
-
self._mTopHead4 = self._emToCm(mScale * self._marginHead4[0])
|
290
|
-
self._mTopHead = self._emToCm(mScale * self._marginHead4[0])
|
291
|
-
self._mTopText = self._emToCm(mScale * self._marginText[0])
|
292
|
-
self._mTopMeta = self._emToCm(mScale * self._marginMeta[0])
|
293
|
-
self._mTopSep = self._emToCm(mScale * self._marginSep[0])
|
294
|
-
|
295
|
-
self._mBotTitle = self._emToCm(mScale * self._marginTitle[1])
|
296
|
-
self._mBotHead1 = self._emToCm(mScale * self._marginHead1[1])
|
297
|
-
self._mBotHead2 = self._emToCm(mScale * self._marginHead2[1])
|
298
|
-
self._mBotHead3 = self._emToCm(mScale * self._marginHead3[1])
|
299
|
-
self._mBotHead4 = self._emToCm(mScale * self._marginHead4[1])
|
300
|
-
self._mBotHead = self._emToCm(mScale * self._marginHead4[1])
|
301
|
-
self._mBotText = self._emToCm(mScale * self._marginText[1])
|
302
|
-
self._mBotMeta = self._emToCm(mScale * self._marginMeta[1])
|
303
|
-
self._mBotSep = self._emToCm(mScale * self._marginSep[1])
|
304
|
-
|
305
|
-
self._mLeftFoot = self._emToCm(self._marginFoot[0])
|
306
|
-
self._mBotFoot = self._emToCm(self._marginFoot[1])
|
307
|
-
|
308
|
-
self._fLineHeight = f"{round(100 * self._lineHeight):d}%"
|
227
|
+
self._fontFamily = self._textFont.family()
|
228
|
+
self._fontSize = self._textFont.pointSize()
|
229
|
+
self._fontStyle = FONT_STYLE.get(self._textFont.style(), "normal")
|
230
|
+
self._fontPitch = "fixed" if self._textFont.fixedPitch() else "variable"
|
231
|
+
self._headWeight = self._fontBold if self._boldHeads else None
|
309
232
|
self._fBlockIndent = self._emToCm(self._blockIndent)
|
310
|
-
self._fTextIndent = self._emToCm(self._firstWidth)
|
311
233
|
|
312
234
|
# Clear Errors
|
313
235
|
self._errData = []
|
@@ -744,7 +666,7 @@ class ToOdt(Tokenizer):
|
|
744
666
|
|
745
667
|
def _emToCm(self, value: float) -> str:
|
746
668
|
"""Converts an em value to centimetres."""
|
747
|
-
return f"{value*2.54/72
|
669
|
+
return f"{value*self._fontSize*2.54/72.0:.3f}cm"
|
748
670
|
|
749
671
|
def _emToPt(self, scale: float) -> str:
|
750
672
|
"""Compute relative font size in points."""
|
@@ -772,16 +694,19 @@ class ToOdt(Tokenizer):
|
|
772
694
|
|
773
695
|
xHead = ET.SubElement(xPage, _mkTag("style", "header-style"))
|
774
696
|
ET.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib={
|
775
|
-
_mkTag("fo", "min-height"):
|
697
|
+
_mkTag("fo", "min-height"): self._emToCm(1.5),
|
776
698
|
_mkTag("fo", "margin-left"): "0.000cm",
|
777
699
|
_mkTag("fo", "margin-right"): "0.000cm",
|
778
|
-
_mkTag("fo", "margin-bottom"):
|
700
|
+
_mkTag("fo", "margin-bottom"): self._emToCm(0.5),
|
779
701
|
})
|
780
702
|
|
781
703
|
return
|
782
704
|
|
783
705
|
def _defaultStyles(self) -> None:
|
784
706
|
"""Set the default styles."""
|
707
|
+
hScale = self._scaleHeads
|
708
|
+
textSize = self._emToPt(nwStyles.T_NORMAL)
|
709
|
+
|
785
710
|
# Add Paragraph Family Style
|
786
711
|
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib={
|
787
712
|
_mkTag("style", "family"): "paragraph",
|
@@ -796,7 +721,7 @@ class ToOdt(Tokenizer):
|
|
796
721
|
_mkTag("fo", "font-family"): self._fontFamily,
|
797
722
|
_mkTag("fo", "font-weight"): self._fontWeight,
|
798
723
|
_mkTag("fo", "font-style"): self._fontStyle,
|
799
|
-
_mkTag("fo", "font-size"):
|
724
|
+
_mkTag("fo", "font-size"): textSize,
|
800
725
|
_mkTag("fo", "language"): self._dLanguage,
|
801
726
|
_mkTag("fo", "country"): self._dCountry,
|
802
727
|
})
|
@@ -812,7 +737,7 @@ class ToOdt(Tokenizer):
|
|
812
737
|
_mkTag("fo", "font-family"): self._fontFamily,
|
813
738
|
_mkTag("fo", "font-weight"): self._fontWeight,
|
814
739
|
_mkTag("fo", "font-style"): self._fontStyle,
|
815
|
-
_mkTag("fo", "font-size"):
|
740
|
+
_mkTag("fo", "font-size"): textSize,
|
816
741
|
})
|
817
742
|
|
818
743
|
# Add Default Heading Style
|
@@ -824,8 +749,8 @@ class ToOdt(Tokenizer):
|
|
824
749
|
_mkTag("style", "class"): "text",
|
825
750
|
})
|
826
751
|
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib={
|
827
|
-
_mkTag("fo", "margin-top"): self.
|
828
|
-
_mkTag("fo", "margin-bottom"): self.
|
752
|
+
_mkTag("fo", "margin-top"): self._emToCm(self._marginHead4[0]),
|
753
|
+
_mkTag("fo", "margin-bottom"): self._emToCm(self._marginHead4[1]),
|
829
754
|
_mkTag("fo", "keep-with-next"): "always",
|
830
755
|
})
|
831
756
|
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
@@ -833,7 +758,7 @@ class ToOdt(Tokenizer):
|
|
833
758
|
_mkTag("fo", "font-family"): self._fontFamily,
|
834
759
|
_mkTag("fo", "font-weight"): self._fontWeight,
|
835
760
|
_mkTag("fo", "font-style"): self._fontStyle,
|
836
|
-
_mkTag("fo", "font-size"): self.
|
761
|
+
_mkTag("fo", "font-size"): self._emToPt(nwStyles.H_SIZES[4] if hScale else 1.0),
|
837
762
|
})
|
838
763
|
|
839
764
|
# Add Header and Footer Styles
|
@@ -857,20 +782,24 @@ class ToOdt(Tokenizer):
|
|
857
782
|
|
858
783
|
def _useableStyles(self) -> None:
|
859
784
|
"""Set the usable styles."""
|
785
|
+
hScale = self._scaleHeads
|
860
786
|
hColor = self._theme.head if self._colorHeads else None
|
861
787
|
|
788
|
+
textSize = self._emToPt(nwStyles.T_NORMAL)
|
789
|
+
lineHeight = f"{round(100 * self._lineHeight):d}%"
|
790
|
+
|
862
791
|
# Add Text Body Style
|
863
792
|
style = ODTParagraphStyle(S_TEXT)
|
864
793
|
style.setDisplayName("Text body")
|
865
794
|
style.setParentStyleName("Standard")
|
866
795
|
style.setClass("text")
|
867
|
-
style.setMarginTop(self.
|
868
|
-
style.setMarginBottom(self.
|
869
|
-
style.setLineHeight(
|
796
|
+
style.setMarginTop(self._emToCm(self._marginText[0]))
|
797
|
+
style.setMarginBottom(self._emToCm(self._marginText[1]))
|
798
|
+
style.setLineHeight(lineHeight)
|
870
799
|
style.setTextAlign(self._defaultAlign)
|
871
800
|
style.setFontName(self._fontFamily)
|
872
801
|
style.setFontFamily(self._fontFamily)
|
873
|
-
style.setFontSize(
|
802
|
+
style.setFontSize(textSize)
|
874
803
|
style.setFontWeight(self._fontWeight)
|
875
804
|
style.packXML(self._xStyl)
|
876
805
|
self._mainPara[style.name] = style
|
@@ -880,7 +809,7 @@ class ToOdt(Tokenizer):
|
|
880
809
|
style.setDisplayName("First line indent")
|
881
810
|
style.setParentStyleName(S_TEXT)
|
882
811
|
style.setClass("text")
|
883
|
-
style.setTextIndent(self.
|
812
|
+
style.setTextIndent(self._emToCm(self._firstWidth))
|
884
813
|
style.packXML(self._xStyl)
|
885
814
|
self._mainPara[style.name] = style
|
886
815
|
|
@@ -889,12 +818,12 @@ class ToOdt(Tokenizer):
|
|
889
818
|
style.setDisplayName("Text Meta")
|
890
819
|
style.setParentStyleName("Standard")
|
891
820
|
style.setClass("text")
|
892
|
-
style.setMarginTop(self.
|
893
|
-
style.setMarginBottom(self.
|
894
|
-
style.setLineHeight(
|
821
|
+
style.setMarginTop(self._emToCm(self._marginMeta[0]))
|
822
|
+
style.setMarginBottom(self._emToCm(self._marginMeta[1]))
|
823
|
+
style.setLineHeight(lineHeight)
|
895
824
|
style.setFontName(self._fontFamily)
|
896
825
|
style.setFontFamily(self._fontFamily)
|
897
|
-
style.setFontSize(
|
826
|
+
style.setFontSize(textSize)
|
898
827
|
style.setFontWeight(self._fontWeight)
|
899
828
|
style.packXML(self._xStyl)
|
900
829
|
self._mainPara[style.name] = style
|
@@ -905,12 +834,12 @@ class ToOdt(Tokenizer):
|
|
905
834
|
style.setParentStyleName("Heading")
|
906
835
|
style.setNextStyleName(S_TEXT)
|
907
836
|
style.setClass("chapter")
|
908
|
-
style.setMarginTop(self.
|
909
|
-
style.setMarginBottom(self.
|
837
|
+
style.setMarginTop(self._emToCm(self._marginTitle[0]))
|
838
|
+
style.setMarginBottom(self._emToCm(self._marginTitle[1]))
|
910
839
|
style.setTextAlign("center")
|
911
840
|
style.setFontName(self._fontFamily)
|
912
841
|
style.setFontFamily(self._fontFamily)
|
913
|
-
style.setFontSize(self.
|
842
|
+
style.setFontSize(self._emToPt(nwStyles.H_SIZES[0] if hScale else 1.0))
|
914
843
|
style.setFontWeight(self._headWeight)
|
915
844
|
style.packXML(self._xStyl)
|
916
845
|
self._mainPara[style.name] = style
|
@@ -921,13 +850,13 @@ class ToOdt(Tokenizer):
|
|
921
850
|
style.setParentStyleName("Standard")
|
922
851
|
style.setNextStyleName(S_TEXT)
|
923
852
|
style.setClass("text")
|
924
|
-
style.setMarginTop(self.
|
925
|
-
style.setMarginBottom(self.
|
926
|
-
style.setLineHeight(
|
853
|
+
style.setMarginTop(self._emToCm(self._marginSep[0]))
|
854
|
+
style.setMarginBottom(self._emToCm(self._marginSep[1]))
|
855
|
+
style.setLineHeight(lineHeight)
|
927
856
|
style.setTextAlign("center")
|
928
857
|
style.setFontName(self._fontFamily)
|
929
858
|
style.setFontFamily(self._fontFamily)
|
930
|
-
style.setFontSize(
|
859
|
+
style.setFontSize(textSize)
|
931
860
|
style.setFontWeight(self._fontWeight)
|
932
861
|
style.packXML(self._xStyl)
|
933
862
|
self._mainPara[style.name] = style
|
@@ -939,11 +868,11 @@ class ToOdt(Tokenizer):
|
|
939
868
|
style.setNextStyleName(S_TEXT)
|
940
869
|
style.setOutlineLevel("1")
|
941
870
|
style.setClass("text")
|
942
|
-
style.setMarginTop(self.
|
943
|
-
style.setMarginBottom(self.
|
871
|
+
style.setMarginTop(self._emToCm(self._marginHead1[0]))
|
872
|
+
style.setMarginBottom(self._emToCm(self._marginHead1[1]))
|
944
873
|
style.setFontName(self._fontFamily)
|
945
874
|
style.setFontFamily(self._fontFamily)
|
946
|
-
style.setFontSize(self.
|
875
|
+
style.setFontSize(self._emToPt(nwStyles.H_SIZES[1] if hScale else 1.0))
|
947
876
|
style.setFontWeight(self._headWeight)
|
948
877
|
style.setColor(hColor)
|
949
878
|
style.packXML(self._xStyl)
|
@@ -956,11 +885,11 @@ class ToOdt(Tokenizer):
|
|
956
885
|
style.setNextStyleName(S_TEXT)
|
957
886
|
style.setOutlineLevel("2")
|
958
887
|
style.setClass("text")
|
959
|
-
style.setMarginTop(self.
|
960
|
-
style.setMarginBottom(self.
|
888
|
+
style.setMarginTop(self._emToCm(self._marginHead2[0]))
|
889
|
+
style.setMarginBottom(self._emToCm(self._marginHead2[1]))
|
961
890
|
style.setFontName(self._fontFamily)
|
962
891
|
style.setFontFamily(self._fontFamily)
|
963
|
-
style.setFontSize(self.
|
892
|
+
style.setFontSize(self._emToPt(nwStyles.H_SIZES[2] if hScale else 1.0))
|
964
893
|
style.setFontWeight(self._headWeight)
|
965
894
|
style.setColor(hColor)
|
966
895
|
style.packXML(self._xStyl)
|
@@ -973,11 +902,11 @@ class ToOdt(Tokenizer):
|
|
973
902
|
style.setNextStyleName(S_TEXT)
|
974
903
|
style.setOutlineLevel("3")
|
975
904
|
style.setClass("text")
|
976
|
-
style.setMarginTop(self.
|
977
|
-
style.setMarginBottom(self.
|
905
|
+
style.setMarginTop(self._emToCm(self._marginHead3[0]))
|
906
|
+
style.setMarginBottom(self._emToCm(self._marginHead3[1]))
|
978
907
|
style.setFontName(self._fontFamily)
|
979
908
|
style.setFontFamily(self._fontFamily)
|
980
|
-
style.setFontSize(self.
|
909
|
+
style.setFontSize(self._emToPt(nwStyles.H_SIZES[3] if hScale else 1.0))
|
981
910
|
style.setFontWeight(self._headWeight)
|
982
911
|
style.setColor(hColor)
|
983
912
|
style.packXML(self._xStyl)
|
@@ -990,11 +919,11 @@ class ToOdt(Tokenizer):
|
|
990
919
|
style.setNextStyleName(S_TEXT)
|
991
920
|
style.setOutlineLevel("4")
|
992
921
|
style.setClass("text")
|
993
|
-
style.setMarginTop(self.
|
994
|
-
style.setMarginBottom(self.
|
922
|
+
style.setMarginTop(self._emToCm(self._marginHead4[0]))
|
923
|
+
style.setMarginBottom(self._emToCm(self._marginHead4[1]))
|
995
924
|
style.setFontName(self._fontFamily)
|
996
925
|
style.setFontFamily(self._fontFamily)
|
997
|
-
style.setFontSize(self.
|
926
|
+
style.setFontSize(self._emToPt(nwStyles.H_SIZES[4] if hScale else 1.0))
|
998
927
|
style.setFontWeight(self._headWeight)
|
999
928
|
style.setColor(hColor)
|
1000
929
|
style.packXML(self._xStyl)
|
@@ -1013,10 +942,10 @@ class ToOdt(Tokenizer):
|
|
1013
942
|
style.setDisplayName("Footnote")
|
1014
943
|
style.setParentStyleName("Standard")
|
1015
944
|
style.setClass("extra")
|
1016
|
-
style.setMarginLeft(self.
|
1017
|
-
style.setMarginBottom(self.
|
1018
|
-
style.setTextIndent("-"+self.
|
1019
|
-
style.setFontSize(self.
|
945
|
+
style.setMarginLeft(self._emToCm(self._marginFoot[0]))
|
946
|
+
style.setMarginBottom(self._emToCm(self._marginFoot[1]))
|
947
|
+
style.setTextIndent("-"+self._emToCm(self._marginFoot[0]))
|
948
|
+
style.setFontSize(self._emToPt(nwStyles.T_SMALL))
|
1020
949
|
style.packXML(self._xStyl)
|
1021
950
|
self._mainPara[style.name] = style
|
1022
951
|
|
novelwriter/formats/toqdoc.py
CHANGED
@@ -29,11 +29,12 @@ from pathlib import Path
|
|
29
29
|
|
30
30
|
from PyQt5.QtCore import QMarginsF, QSizeF
|
31
31
|
from PyQt5.QtGui import (
|
32
|
-
QColor, QFont,
|
33
|
-
QTextCursor, QTextDocument
|
32
|
+
QColor, QFont, QFontDatabase, QPageSize, QTextBlockFormat, QTextCharFormat,
|
33
|
+
QTextCursor, QTextDocument, QTextFrameFormat
|
34
34
|
)
|
35
35
|
from PyQt5.QtPrintSupport import QPrinter
|
36
36
|
|
37
|
+
from novelwriter import __version__
|
37
38
|
from novelwriter.constants import nwStyles, nwUnicode
|
38
39
|
from novelwriter.core.project import NWProject
|
39
40
|
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt
|
@@ -67,16 +68,22 @@ class ToQTextDocument(Tokenizer):
|
|
67
68
|
super().__init__(project)
|
68
69
|
self._document = QTextDocument()
|
69
70
|
self._document.setUndoRedoEnabled(False)
|
70
|
-
self._document.setDocumentMargin(0)
|
71
|
+
self._document.setDocumentMargin(0.0)
|
71
72
|
|
72
73
|
self._usedNotes: dict[str, int] = {}
|
73
74
|
self._usedFields: list[tuple[int, str]] = []
|
74
75
|
|
75
76
|
self._init = False
|
76
|
-
self._bold = QFont.Weight.Bold
|
77
|
-
self._normal = QFont.Weight.Normal
|
78
77
|
self._newPage = False
|
78
|
+
self._anchors = True
|
79
79
|
|
80
|
+
self._hWeight = QFont.Weight.Bold
|
81
|
+
self._dWeight = QFont.Weight.Normal
|
82
|
+
self._dItalic = False
|
83
|
+
self._dStrike = False
|
84
|
+
self._dUnderline = False
|
85
|
+
|
86
|
+
self._dpi = 96
|
80
87
|
self._pageSize = QPageSize(QPageSize.PageSizeId.A4)
|
81
88
|
self._pageMargins = QMarginsF(20.0, 20.0, 20.0, 20.0)
|
82
89
|
|
@@ -108,32 +115,52 @@ class ToQTextDocument(Tokenizer):
|
|
108
115
|
self._newPage = state
|
109
116
|
return
|
110
117
|
|
118
|
+
def disableAnchors(self) -> None:
|
119
|
+
"""Disable anchors for when writing to file."""
|
120
|
+
self._anchors = False
|
121
|
+
return
|
122
|
+
|
111
123
|
##
|
112
124
|
# Class Methods
|
113
125
|
##
|
114
126
|
|
115
|
-
def initDocument(self) -> None:
|
127
|
+
def initDocument(self, pdf: bool = False) -> None:
|
116
128
|
"""Initialise all computed values of the document."""
|
117
129
|
super().initDocument()
|
118
130
|
|
131
|
+
if pdf:
|
132
|
+
fontDB = QFontDatabase()
|
133
|
+
family = self._textFont.family()
|
134
|
+
style = self._textFont.styleName()
|
135
|
+
self._dpi = 1200 if fontDB.isScalable(family, style) else 72
|
136
|
+
|
119
137
|
self._document.setUndoRedoEnabled(False)
|
120
138
|
self._document.blockSignals(True)
|
121
139
|
self._document.clear()
|
122
140
|
self._document.setDefaultFont(self._textFont)
|
123
141
|
|
124
|
-
|
125
|
-
|
126
|
-
|
142
|
+
# Default Styles
|
143
|
+
self._dWeight = self._textFont.weight()
|
144
|
+
self._dItalic = self._textFont.italic()
|
145
|
+
self._dStrike = self._textFont.strikeOut()
|
146
|
+
self._dUnderline = self._textFont.underline()
|
147
|
+
|
148
|
+
# Header Weight
|
149
|
+
self._hWeight = QFont.Weight.Bold if self._boldHeads else self._dWeight
|
127
150
|
|
128
151
|
# Scaled Sizes
|
129
152
|
# ============
|
130
153
|
|
154
|
+
fPt = self._textFont.pointSizeF()
|
155
|
+
fPx = fPt*96.0/72.0 # 1 em in pixels
|
156
|
+
mPx = fPx * self._dpi/96.0
|
157
|
+
|
131
158
|
self._mHead = {
|
132
|
-
BlockTyp.TITLE: (
|
133
|
-
BlockTyp.HEAD1: (
|
134
|
-
BlockTyp.HEAD2: (
|
135
|
-
BlockTyp.HEAD3: (
|
136
|
-
BlockTyp.HEAD4: (
|
159
|
+
BlockTyp.TITLE: (fPx * self._marginTitle[0], fPx * self._marginTitle[1]),
|
160
|
+
BlockTyp.HEAD1: (fPx * self._marginHead1[0], fPx * self._marginHead1[1]),
|
161
|
+
BlockTyp.HEAD2: (fPx * self._marginHead2[0], fPx * self._marginHead2[1]),
|
162
|
+
BlockTyp.HEAD3: (fPx * self._marginHead3[0], fPx * self._marginHead3[1]),
|
163
|
+
BlockTyp.HEAD4: (fPx * self._marginHead4[0], fPx * self._marginHead4[1]),
|
137
164
|
}
|
138
165
|
|
139
166
|
hScale = self._scaleHeads
|
@@ -145,9 +172,9 @@ class ToQTextDocument(Tokenizer):
|
|
145
172
|
BlockTyp.HEAD4: (nwStyles.H_SIZES.get(4, 1.0) * fPt) if hScale else fPt,
|
146
173
|
}
|
147
174
|
|
148
|
-
self._mText = (
|
149
|
-
self._mMeta = (
|
150
|
-
self._mSep = (
|
175
|
+
self._mText = (fPx * self._marginText[0], fPx * self._marginText[1])
|
176
|
+
self._mMeta = (fPx * self._marginMeta[0], fPx * self._marginMeta[1])
|
177
|
+
self._mSep = (fPx * self._marginSep[0], fPx * self._marginSep[1])
|
151
178
|
|
152
179
|
self._mIndent = mPx * 2.0
|
153
180
|
self._tIndent = mPx * self._firstWidth
|
@@ -242,14 +269,19 @@ class ToQTextDocument(Tokenizer):
|
|
242
269
|
def saveDocument(self, path: Path) -> None:
|
243
270
|
"""Save the document as a PDF file."""
|
244
271
|
m = self._pageMargins
|
272
|
+
logger.info("Writing PDF at %d DPI", self._dpi)
|
245
273
|
|
246
|
-
printer = QPrinter(QPrinter.PrinterMode.
|
274
|
+
printer = QPrinter(QPrinter.PrinterMode.HighResolution)
|
275
|
+
printer.setDocName(self._project.data.name)
|
276
|
+
printer.setCreator(f"novelWriter/{__version__}")
|
277
|
+
printer.setResolution(self._dpi)
|
247
278
|
printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat)
|
248
279
|
printer.setPageSize(self._pageSize)
|
249
280
|
printer.setPageMargins(m.left(), m.top(), m.right(), m.bottom(), QPrinter.Unit.Millimeter)
|
250
281
|
printer.setOutputFileName(str(path))
|
251
282
|
|
252
|
-
self._document.
|
283
|
+
self._document.documentLayout().setPaintDevice(printer)
|
284
|
+
self._document.setPageSize(QSizeF(printer.pageRect().size()))
|
253
285
|
self._document.print(printer)
|
254
286
|
|
255
287
|
return
|
@@ -309,21 +341,21 @@ class ToQTextDocument(Tokenizer):
|
|
309
341
|
|
310
342
|
# Construct next format
|
311
343
|
if fmt == TextFmt.B_B:
|
312
|
-
cFmt.setFontWeight(
|
344
|
+
cFmt.setFontWeight(QFont.Weight.Bold)
|
313
345
|
elif fmt == TextFmt.B_E:
|
314
|
-
cFmt.setFontWeight(self.
|
346
|
+
cFmt.setFontWeight(self._dWeight)
|
315
347
|
elif fmt == TextFmt.I_B:
|
316
348
|
cFmt.setFontItalic(True)
|
317
349
|
elif fmt == TextFmt.I_E:
|
318
|
-
cFmt.setFontItalic(
|
350
|
+
cFmt.setFontItalic(self._dItalic)
|
319
351
|
elif fmt == TextFmt.D_B:
|
320
352
|
cFmt.setFontStrikeOut(True)
|
321
353
|
elif fmt == TextFmt.D_E:
|
322
|
-
cFmt.setFontStrikeOut(
|
354
|
+
cFmt.setFontStrikeOut(self._dStrike)
|
323
355
|
elif fmt == TextFmt.U_B:
|
324
356
|
cFmt.setFontUnderline(True)
|
325
357
|
elif fmt == TextFmt.U_E:
|
326
|
-
cFmt.setFontUnderline(
|
358
|
+
cFmt.setFontUnderline(self._dUnderline)
|
327
359
|
elif fmt == TextFmt.M_B:
|
328
360
|
cFmt.setBackground(self._theme.highlight)
|
329
361
|
elif fmt == TextFmt.M_E:
|
@@ -344,18 +376,22 @@ class ToQTextDocument(Tokenizer):
|
|
344
376
|
cFmt.setForeground(self._theme.text)
|
345
377
|
primary = None
|
346
378
|
elif fmt == TextFmt.ANM_B:
|
347
|
-
|
348
|
-
|
379
|
+
if self._anchors:
|
380
|
+
cFmt.setAnchor(True)
|
381
|
+
cFmt.setAnchorNames([data])
|
349
382
|
elif fmt == TextFmt.ANM_E:
|
350
|
-
|
383
|
+
if self._anchors:
|
384
|
+
cFmt.setAnchor(False)
|
351
385
|
elif fmt == TextFmt.ARF_B:
|
352
|
-
|
353
|
-
|
354
|
-
|
386
|
+
if self._anchors:
|
387
|
+
cFmt.setFontUnderline(True)
|
388
|
+
cFmt.setAnchor(True)
|
389
|
+
cFmt.setAnchorHref(data)
|
355
390
|
elif fmt == TextFmt.ARF_E:
|
356
|
-
|
357
|
-
|
358
|
-
|
391
|
+
if self._anchors:
|
392
|
+
cFmt.setFontUnderline(False)
|
393
|
+
cFmt.setAnchor(False)
|
394
|
+
cFmt.setAnchorHref("")
|
359
395
|
elif fmt == TextFmt.HRF_B:
|
360
396
|
cFmt.setForeground(self._theme.link)
|
361
397
|
cFmt.setFontUnderline(True)
|
@@ -363,7 +399,7 @@ class ToQTextDocument(Tokenizer):
|
|
363
399
|
cFmt.setAnchorHref(data)
|
364
400
|
elif fmt == TextFmt.HRF_E:
|
365
401
|
cFmt.setForeground(primary or self._theme.text)
|
366
|
-
cFmt.setFontUnderline(
|
402
|
+
cFmt.setFontUnderline(self._dUnderline)
|
367
403
|
cFmt.setAnchor(False)
|
368
404
|
cFmt.setAnchorHref("")
|
369
405
|
elif fmt == TextFmt.FNOTE:
|
@@ -396,24 +432,36 @@ class ToQTextDocument(Tokenizer):
|
|
396
432
|
def _insertNewPageMarker(self, cursor: QTextCursor) -> None:
|
397
433
|
"""Insert a new page marker."""
|
398
434
|
if self._newPage:
|
399
|
-
|
435
|
+
bgCol = QColor(self._theme.text)
|
436
|
+
bgCol.setAlphaF(0.1)
|
437
|
+
fgCol = QColor(self._theme.text)
|
438
|
+
fgCol.setAlphaF(0.8)
|
400
439
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
440
|
+
fFmt = QTextFrameFormat()
|
441
|
+
fFmt.setBorderStyle(QTextFrameFormat.BorderStyle.BorderStyle_None)
|
442
|
+
fFmt.setBackground(bgCol)
|
443
|
+
fFmt.setTopMargin(self._mSep[0])
|
444
|
+
fFmt.setBottomMargin(self._mSep[1])
|
405
445
|
|
406
446
|
bFmt = QTextBlockFormat(self._blockFmt)
|
407
447
|
bFmt.setAlignment(QtAlignCenter)
|
408
448
|
bFmt.setTopMargin(0.0)
|
409
|
-
bFmt.
|
449
|
+
bFmt.setBottomMargin(0.0)
|
450
|
+
bFmt.setLineHeight(100.0, QtPropLineHeight)
|
410
451
|
|
411
452
|
cFmt = QTextCharFormat(self._charFmt)
|
453
|
+
cFmt.setFontItalic(False)
|
454
|
+
cFmt.setFontUnderline(False)
|
455
|
+
cFmt.setFontStrikeOut(False)
|
456
|
+
cFmt.setFontWeight(QFont.Weight.Normal)
|
412
457
|
cFmt.setFontPointSize(0.75*self._textFont.pointSizeF())
|
413
|
-
cFmt.setForeground(
|
458
|
+
cFmt.setForeground(fgCol)
|
414
459
|
|
415
|
-
|
460
|
+
cursor.insertFrame(fFmt)
|
461
|
+
cursor.setBlockFormat(bFmt)
|
416
462
|
cursor.insertText(self._project.localLookup("New Page"), cFmt)
|
463
|
+
cursor.swap(self._document.rootFrame().lastCursorPosition())
|
464
|
+
|
417
465
|
return
|
418
466
|
|
419
467
|
def _genHeadStyle(self, hType: BlockTyp, hKey: str, rFmt: QTextBlockFormat) -> T_TextStyle:
|
@@ -427,9 +475,9 @@ class ToQTextDocument(Tokenizer):
|
|
427
475
|
hCol = self._colorHeads and hType != BlockTyp.TITLE
|
428
476
|
cFmt = QTextCharFormat(self._charFmt)
|
429
477
|
cFmt.setForeground(self._theme.head if hCol else self._theme.text)
|
430
|
-
cFmt.setFontWeight(self.
|
478
|
+
cFmt.setFontWeight(self._hWeight)
|
431
479
|
cFmt.setFontPointSize(self._sHead.get(hType, 1.0))
|
432
|
-
if hKey:
|
480
|
+
if hKey and self._anchors:
|
433
481
|
cFmt.setAnchorNames([hKey])
|
434
482
|
cFmt.setAnchor(True)
|
435
483
|
|