FLOSS Manuals

 English |  Español |  Français |  Italiano |  Português |  Русский |  Shqip

Python Scripting with Scribus

A real script: bcaption.py

# -*- coding: utf-8  -*-

"""

bcaption.py

Creates a text frame (caption) below one or more selected frames.

"""

try:
    import scribus
except ImportError:
    print "Unable to import the 'scribus' module. This script will only run within"
    print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
    sys.exit(1)

numselect = scribus.selectionCount()
count = 0
frames = []

if numselect == 0:
    scribus.messageBox('Selection Count', "You must have at least one image frame selected",
                       scribus.ICON_WARNING, scribus.BUTTON_OK)
    sys.exit(2)
pageunits = scribus.getUnit()
scribus.setUnit(scribus.UNIT_POINTS)

while count < numselect:
    frames.append(scribus.getSelectedObject(count))
    count += 1
    
for frame in frames:
    fwidth, fheight = scribus.getSize(frame)
    fx, fy = scribus.getPosition(frame)
    textf = scribus.createText(fx, fy+fheight, fwidth, 24)
    
scribus.setUnit(pageunits)

scribus.setRedraw(True)

This is an early form of a script, caption.py, which was later included with Scribus. The idea is to automatically create a small frame underneath another frame, in which a caption might be entered. While this might most commonly be used for image frames, I didn't see any reason to restrict its use to that. Another feature is that one can do multiple frame captions at once, simply by selecting a number of them. You do this on the main canvas by holding down the SHIFT key while clicking them sequentially, and they can be on more than one page. After the initial check to see if the script is running under Scribus, a count of the number of frames selected is taken, a counter is indexed to zero, and an empty Python list is created (frames). In case the user forgot to select any frames, there is a check for this.

Next comes a step which is a good idea any time you are using and changing object measurements in absolute numbers. Personally, I prefer to work in points, because of the precision you can easily achieve. We first use the command getUnit() to make note of the user's page units, then setUnit() to change to points. UNIT_POINTS is a built-in Scribus variable that is handier to use than looking up what that constant is. Notice that when we use a built-in variable it requires this scribus. prefix, so that Python knows where to find it. After we finish whatever we need to do in the script, it's important that we set the units back to what they originally were with setUnit(pageunits).

The next little clause after setting the units to points is to fill in our list of selected objects by using the append list function of Python. Once this is done, one by one we first get the dimensions of the object with getSize() and then its position on the page with getPosition(). Notice how each of these assigns two variables, since each command returns two variables. In Python lingo, this is called a tuple. Something else to notice is how we create variable names that have some meaning, like fwidth and fheight so that we're less likely to make mistakes later, and also so that someone else reading the script can easily understand what these represent. We're also helping ourselves, since if we save this file and then open it years later, we can more easily understand our own work, with the added benefit that we can also understand what these Scribus commands return.

Finally, the real point of the script, creating the caption frame at the bottom of the original frame, with the same width, and a height of 24 points. The last command, setRedraw(True) is there to ask Scribus to redraw the document after everything is finished. I probably should have (and usually do) put in a line saying scribus.setRedraw(False) somewhere early in the script, which is supposed to suppress any redrawing of the document while the script runs, theoretically slowing it down. I'm not really sure how effective the setRedraw() command is, though. Later we'll see what I mean in the centervert.py script. Something else to mention is that we do not need to say scribus.True or scribus.False since these are recognized by Python for boolean operations.

Caption.py

Here is the version which is included with Scribus.

#!/usr/bin/env python
# -*- coding: utf-8  -*-

"""

caption.py

Creates a text frame (caption) in selected location relative to
one or more selected frames.

USAGE

Select one or more object (can be any kind of frame, or even imported vector graphics),

run script. Dialog appears for choosing placement of all caption frames

B/T/R/L (Bottom/Top/Right/Left).

Bottom and Top caption frames are sized to width of parent object and height

of 24 points. Right and Left caption frames sized to 150 points width and

40 points height.

"""

try:
    import scribus
except ImportError:
    print "Unable to import the 'scribus' module. This script will only run within"
    print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
    sys.exit(1)

numselect = scribus.selectionCount()
count = 0
frames = []

if numselect == 0:
    scribus.messageBox('Selection Count', "You must have at least one object selected",
                       scribus.ICON_WARNING, scribus.BUTTON_OK)
    sys.exit(2)

captionloc = scribus.valueDialog("Caption Location","Where to put the caption(s) -\n B/T/R/L?", "b")
captionloc = captionloc[0]
location = captionloc.upper()

pageunits = scribus.getUnit()
scribus.setUnit(scribus.UNIT_POINTS)

while count < numselect:
    frames.append(scribus.getSelectedObject(count))
    count += 1
    
for frame in frames:
    fwidth, fheight = scribus.getSize(frame)
    fx, fy = scribus.getPosition(frame)
    if location == "B":
        textf = scribus.createText(fx, fy+fheight, fwidth, 24)
    elif location == "T":
        textf = scribus.createText(fx, fy-24, fwidth, 24)
    elif location == "R":
        textf = scribus.createText(fx + fwidth, fy, 150, 40)
    elif location == "L":
        textf = scribus.createText(fx-150, fy + fheight - 40, 150, 40)
scribus.setUnit(pageunits)

scribus.setRedraw(True)

 

I've highlighted the parts that differ in bold. The idea behind these changes was to allow for the possibility of having a caption frame not just at the bottom of the selected object, but perhaps at the top, or to the left or right. We use this valueDialog() to allow for user input. As you can see, there are three elements between the parentheses of this command. The first gives a title to the dialog, the next is a little message telling the user what this input is about, in this case asking for a single letter to use for Bottom, Top, Right, or Left location for the caption frame, and lastly the default value is b. These are all strings, thus the enclosing quotation marks. I purposely but a lower case b for the default so that the user would hopefully understand that he can enter either an upper or lower case letter. Afterward, I use the upper() string method to make the result only upper case.

In the lower bolded text we see how we put this into action. If I hadn't converted the valueDialog() entry to upper case, I would have had to have, for example

if ((location == "b") or (location == "B")):

So some extra typing is saved. For the bottom location, you can see we do exactly what was done in the bcaption.py script, and for the other choices we change the math and settings as needed.

This is also a good time to add a comment about multiline comments. For individual lines you enter '#' and then what follows is your comment. For a multiple line comment, you can enter 3 double quotes on a line, then on following lines type your extended comment, after which to type 3 double quotes to end the comment. Scribus uses this block of comment when, from the menu, you select Scripter > About Script..., after which you find the script of interest with a file dialog. A window then displays the text between the sets of quotes.

There has been error in communication with Booktype server. Not sure right now where is the problem.

You should refresh this page.