Hi,
I am trying to implement a template mechanism in a script. The idea is to have a text containing placeholders like ${date}, $[title}, ${name}, plus a data set containing dates, titles and names, and create for each data a copy of the text with the placeholders replaced by the actual data. The trick is now that the text features such as font, font size, text color, line spacing, tabs etc. shall be preserved as faithfully as possible. My current findings are, that this is not possible in general, but that we can come close. The main obstacle is that there is not enough functionality in the script API (at least I was unable to find it). For example, there is no function getCharacterStyle. Or you can get style names (getAllStyles), but you cannot get style details. Only today I found a getStyle() in 1.5.6, which did not yet exist in 1.5.2, but which returns only paragraph styles.
So far I came up with this code:
textlen = scribus.getTextLength(textbox)
scribus.selectText(0, 1, textbox)
last_style = scribus.getStyle(textbox)
last_fontname = scribus.getFont(textbox)
last_fontsize = scribus.getFontSize(textbox)
last_textcolor = scribus.getTextColor(textbox)
last_textshade = scribus.getTextShade(textbox)
text = ""
pos = textlen
changed = False
for c in range(0, textlen):
scribus.selectText(c, 1, textbox)
char = scribus.getText(textbox)
style = scribus.getStyle(textbox)
if style != last_style:
changed = True
fontname = scribus.getFont(textbox)
if fontname != last_fontname:
changed = True
fontsize = scribus.getFontSize(textbox)
if fontsize != last_fontsize:
changed = True
textcolor = scribus.getTextColor(textbox)
if textcolor != last_textcolor:
changed = True
textshade = scribus.getTextShade(textbox)
if textshade != last_textshade:
changed = True
if changed:
scribus.insertText(text, pos, textbox)
tlen = scribus.getTextLength(textbox)
scribus.selectText(pos, tlen - pos, textbox)
scribus.setStyle(noStyle if last_style is None else last_style, textbox)
scribus.selectText(pos, tlen - pos, textbox)
scribus.setFont(last_fontname, textbox)
scribus.selectText(pos, tlen - pos, textbox)
scribus.setFontSize(last_fontsize, textbox)
scribus.selectText(pos, tlen - pos, textbox)
scribus.setTextColor(last_textcolor, textbox)
scribus.selectText(pos, tlen - pos, textbox)
scribus.setTextShade(last_textshade, textbox)
pos = tlen
text = ""
last_fontname = fontname
last_fontsize = fontsize
last_textcolor = textcolor
last_textshade = textshade
last_style = style
changed = False
text = text + char
As you can see, I go through the text one character at a time, collecting all characters with the same formatting, as far as I can determine it, then insert the text at the end, and applying the formatting as much as possible.
Some remarks:
- I had to repeat the selectText before each set..., apparently the set...-functions unselect the current selection
- I had to specify the second parameter textbox to avoid error messages
- The template contains special characters. Adding len(text) to pos did not work, because Scribus character count is not the same as Python character len. So, because a getCurrentPos() is missing, and insertText does not return the last pos, I use getTextLength to go to the end of the inserted text. This works of course only if you do not start with a position in the middle of text.
- I found no way to getText text that I had inserted with insertText. The text length is increased luckily, and you can selectText the new text, but you cannot getText it. getText returns only an empty string for the new text.
- We can obtain font, font size, color, shade, and paragraph style. But when you look at the story editor, you can do more to text, e.g. underline it. You can also apply a character style to piece of text (select in the main window, F3). But I could not find out (yet) how to get at these properties. So the replicated text looses e.g. underlining. It does not loose font or font size, if the character style changed that from the paragraph style.