Scripting Scribus
Have you ever said, "This program is pretty nice, but I wish it would ..."? For applications that offer the capability, scripting gives users the ability to customize, extend, and tailor a program to meet their needs. Scribus, a free page layout program that runs on Linux (and Mac OS and Windows) uses the Python programming language for user scripting. Python scripting in Scribus can drastically improve your work flow, and it's relatively easy for beginners to not only use scripts, but also write them.
Scripts are useful for page layout in a few interrelated ways, including automating repetitive tasks and tasks that involve measuring, such as placing page elements and creating page guides.
Not much is required to use Python scripts in Scribus. If your distribution successfully runs Scribus, then you probably have the required Python components. For this evaluation, I downloaded, compiled, and installed the latest stable Python version (1.3.3.11). You can start a Python script from within Scribus by going to the Script menu and choosing either Execute Script..., which opens a dialog box for selecting a script to run, or Scribus Scripts, which lists the scripts in the /usr/share/scribus/scripts directory, which contains the official scripts for Scribus. Placing additional scripts in that directory (as the root user or using sudo) makes those scripts available from the menu.
Two official scripts are provided: CalendarWizard.py and FontSample.py. Both feature dialog boxes with numerous options that showcase how Python scripts can extend the functionality of Scribus. The font sample script can take a long time to run, depending on your processor speed, memory, and number of fonts, but Scribus displays a handy progress bar showing the percentage of script completion.
Additionally, the /usr/share/scribus/samples directory contains 15 scripts intended not just for immediate use, but also as samples to study when creating your own scripts. The scripts in the samples directory are varied and range from a heavily commented boilerplate script (boilerplate.py) to functional scripts that, for example, set up a layout for CD pockets (pochette_CD.py), or add legends to images (legende.py). As the titles of some of the scripts indicate, many have comments and even dialog box text written in the native languages of the script authors, but the script description is usually in English.
More Scripts
More Scribus scripts are available online at the Scribus wiki's page on scripts and plugins. I found here a script to make empty space around an image inside an image frame -- something not yet possible in Scribus. The script works by drawing a second, empty frame 10 measurement units larger than the selected image or text frame. When I first ran the script, I had my default units set to inches, and the script created a 10-inch border around the image I selected. If you want to use this script without modification, be sure that your default units are set for points.
A more comprehensive approach to manipulating images uses a series of scripts for aligning an image inside its frame, scaling an image to fill a frame proportionally (i.e., scaling the image to the largest size possible within the frame while keeping its proportions intact), and scaling and aligning an image via a wizard and an advanced wizard that build upon the first two scripts. These scripts are great examples of how Python scripting extends Scribus's capabilities.
Using scripts that others have written is as simple as copying them from the Web page, pasting them into a text editor (preferably one that is aware of Python syntax, such as Emacs, Vim, Kate, or gedit), and then saving the script to a file ending in .py. You can then run the script from the Scribus script menu. The advantage of pasting the script into a syntax-aware text editor is that white space is important in Python, and a good editor will help you check that everything is aligned correctly.
Writing a script
Prior to doing the research for this article, I had not done any programming in Python. I did, however, have extensive experience using Adobe's scripting language for PageMaker, and I found that most of the principles carried over. A wonderful resource for beginners wanting to learn more about Python is the 110-page PDF tutorial A Byte of Python by Swaroop C H. It is well-written, easy to follow, and may be the best introduction to Python programming available.
Armed with a little bit of knowledge of Python, and having the scripting application programming interface (API) available online and from Scribus's help menu, I set out to write a couple of scripts. With all the sample scripts available, I did not have to start from scratch.
I began by modifying the script for making an empty space around an image so that the space would be 10 points regardless of the default measurement unit set by the user. To do that, I needed to get the current units setting, store it in a variable, temporarily set the units to points, and then reset the units to their original setting. To accomplish those tasks, I added the following commands to the script I downloaded:
* userUnit = getUnit() -- set a variable storing the current units setting
* setUnit(0) -- sets the units to points (0). (1) is millimeters (2) is inches and (3) is picas.
* setUnit(userUnit) -- resets the units to the original setting
The script as modified appears below. Because of the way the original author set the script to make sure the script is run from within Scribus, the commands I added needed to be prefaced with scribus..
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys try: import scribus except ImportError: print "This script only works from within Scribus" sys.exit(1) def makebox(x,y,w,h): a = scribus.createImage(x, y, w, h) scribus.textFlowsAroundFrame(a, 1) def main(): if scribus.haveDoc(): scribus.setRedraw(1) userUnit = scribus.getUnit() scribus.setUnit(0) x,y = scribus.getPosition() w,h = scribus.getSize() x2 = x - border y2 = y - border w2 = w + border * 2 h2 = h + border * 2 makebox(x2,y2,w2,h2) scribus.redrawAll() scribus.setUnit(userUnit) else: result = scribus.messageBox('Error','You need a Document open, and a frame selected.') # Change the 'border' value to change the size of space around your frame border = 10 main()
When I first started working with Scribus, I missed having the ability to make a single underline of a text or image frame. This capability is particularly handy when setting up page headers. Looking at the sample scripts, I saw that legende.py did something similar to what I wanted to do. That script gets the size and location of an image frame and then places a text box a few millimeters below the lower right corner of the box. I needed to do something similar, except that I needed my script to draw the line from the lower left corner to the lower right corner without an offset. So I modified the legende.py script and saved it as underline_block.py.
The key to making the script work is realizing that the getPosition function gets the x and y page coordinates of the upper left corner of the frame. To get the positions of the other corners, I need the height and width of the frame. When that information is stored in variables, then drawing the line is a matter of specifying the x and y coordinates of the lower two corners in relation to the height and width. The command createLine(x, y+h, x+l, y+h) accomplishes drawing the line from the bottom left to the bottom right. The full script is below:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ Draws a line below the selected frame. """ import sys try: from scribus import * except ImportError: print "This script only runs from within Scribus." sys.exit(1) import os def main(): userUnit = getUnit() setUnit(1) sel_count = selectionCount() if sel_count == 0: messageBox("underline_block.py", "Please select the object to add a line to before running this script.", ICON_INFORMATION) sys.exit(1) x,y = getPosition() l,h = getSize() createLine(x, y+h, x+l, y+h) setUnit(userUnit) if __name__ == '__main__': main()
Like any other type of programming, creating scripts is an iterative process. When writing or modifying a script, it is easy to work in a cycle of edit, save, run, check, and edit. The iterative approach also applies to improving scripts. After using the underline_block.py script for a while, I may want to modify it so that I can choose to add a line above the block rather than below it. To do that, I'll need to add a dialog box so I can choose the position. If I do that, I may want to add something to the dialog so I can choose the line style too. Each of the embellishments make the script more general and more useful.
As the examples illustrate, Python scripts are a useful way to customize and extend Scribus regardless of your level of programming experience.