tags:

views:

88

answers:

1

I'm currently writing a PyGTK application and I'd like some advice as to the best way to structure my application. Basically the application will read a specific file specification and present it in a GUI for editing.

Currently I have a parser.py which handles all the low level file IO and parsing of the file. I'm displaying the contents of the file in a treeview, which means that I need to use a treestore as my data type.

The problem I've ran into is that I've only thought of two solutions to this problem. The first is that my parser could build a treestore and pass it to my ui class. That requires my parser depending on pygtk, and minimizes the potential reuse for the class. The second would be storing a reference to my ui class in parser, which would also potentially limit the reuse of my parser class as a standalone library.

To condense my question into a short one liner: Is there a way to accomplish my goals in a more pythonic or OO-friendly way?

If looking at my code would help anyone trying to answer my question: https://code.launchpad.net/~blainepace/nbtparser/trunk

Other pythonic suggestions welcome, this is my first python program and I may be stuck in a more C++ style of thinking. I plan on refactoring a lot of it.

+1  A: 

You should take a look at the tutorial "Sub-classing GObject in Python". This goes through using GObject's type system to create signals and properties, which allow you to model underlying behavior in a way that is easy to integrate with typical PyGTK semantics (connecting to signals, waiting for property notifications, etc).

Both your parser and UI should have only properties and signals to connect to. You then have a third class that connects up these signals and callbacks and starts the main loop in a if __name__ == __main__ block.

Typically, mine look something like:

class MyApp(gtk.Window):

    def __init__(self, parser, ui):
        gtk.Window.__init__(self)
        parser.connect("some-signal", ui.update_this)
        parser.connect("some-other-signal", ui.update_that, extra_params)
        ui.connect("refresh-clicked", parser.reparse_file)
        self.add(ui)

...and then in your main script:

parser = parser.Parser(...)
ui = view.ParseView(...)
app = MyApp(parser, ui)

app.show_all()

gtk.main()

Of course, this is often different depending on eg. am I using Glade? Do I subclass widgets for the main app or wrap them? etc.

The great thing about this is that you can then write, say, a test parser that does nothing but return pre-programmed responses, or uses a known test file. Swapping it in is as easy as changing one line above:

parser = parser.DummyParser(...)
detly
Thanks, you pointed me in the right direction.
sensae