Drag-and-drop saving tutorial

This tutorial shows how to write a simple Lorem Ipsum generator, with drag-and-drop saving. It also shows how to add extra widgets to the savebox.

You should have already read the first tutorial, as this one assumes you already have the application directory and other files set up.

ROX style saveboxes are unusual, because you can drag the icon in the savebox to a file manager or to another application.

Aim

Lorem Ipsum is nonsense text used in DTP packages to check layouts. If you've just set out some frames and you need some dummy text, you'll be able to drag from our generator into the frame (well, if you've got a decent DTP package, anyway ;-)

The code

Python is an object-oriented language, and you should have an object representing the data that you want to save. We will create a SaveBox widget, and tell it to use this object to get the actual data. We'll start with a complete program, as it's rather simple:

#!/usr/bin/env python
import findrox; findrox.version(1, 9, 8)
import rox
from rox import saving
 
text = """Lorem ipsum dolor sit amet, consectetaur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum."""
 
class Lipsum(saving.Saveable):
        def save_to_stream(self, stream):
                print >>stream, text
 
box = saving.SaveBox(Lipsum(), 'Lipsum', 'text/plain')
box.show()
 
rox.mainloop()

Well, that was pretty short -- most of it's the text to save! The three arguments to SaveBox's constructor are:

  • The object to save (we create an instance of the Lipsum class)
  • The default filename.
  • The MIME type.

Note that the SaveBox widget is automatically reference-counted by ROX-Lib, so the program will terminate correctly.
For more complicated tasks, you might want to look at the full saving API.

Adding widgets to the savebox

You may have spotted that our program is pretty pointless as it stands. We could have just put that text into a file and dragged the file in! So, now we're going to let the user specify how many repetitions they want. To do that, we'll create a subclass of the
SaveBox widget:

from rox import g, TRUE, FALSE
 
class LipsumBox(saving.SaveBox):
        def build_main_area(self):
                self.vbox.pack_start(self.save_area, 
                                expand = TRUE, fill = TRUE, padding = 0)
 
                hbox = g.HBox(FALSE, 0)
                hbox.pack_start(g.Label('Repetitions:'), FALSE, TRUE, 0)
 
                self.repetitions = g.Adjustment(1, lower = 1, upper = 100,
                                                step_incr = 1)
                spinner = g.SpinButton(self.repetitions, 1, 0)
                hbox.pack_start(spinner)
 
                self.vbox.pack_start(hbox, FALSE, TRUE, 0)
                hbox.show_all()

The build_main_area method is used to place the save_area (the bit with the icon and the text field) into the savebox. We can override this method to place it somewhere else or, as in this case, put it in the same place but add other widgets at the same time.

The HBox contains a label ('Repetitions:') and a SpinButton (a widget for entering numbers). We add this to the dialog's vbox area. Don't forget to show the new widgets! The Adjustment object stores the current number, the allowed limits and how much it increases by when you click on the arrows.

Now, we'll use this widget instead of the normal SaveBox:

box = LipsumBox(Lipsum(), 'Lipsum', 'text/plain')

In the Lipsum object (the object which actually generates the text), we can read the value of the adjustment to decide how many
times to write the text:

      def save_to_stream(self, stream):
                for x in range(box.repetitions.value):
                        print >>stream, text

And we're done! One handy Lorem Ipsum generator! Of course, there are better ways of generating additional text than by just repeating, so feel free to improve it!

Note: Normally, the Saveable will also be a Window and will store the SaveBox widget in an attribute, eg in a text editor. You can inherit from multiple classes easily in python, like this:

class Lipsum(rox.Window, saving.Saveable):
        def __init__(self):
                rox.Window.__init__(self)
                # (Saveable has no __init__ method)
                ...