

Today I have spent the whole morning playing with Cocoa-Python. When I upgraded to Leopard and XCode 3.0 back in December, I discovered the new Cocoa-Python and Cocoa-ruby projects (later I learned Pyobjc has been around for a few years now).
At first I though it was cool to have alternatives to Objective-C when developing software for Macs with the Cocoa library. But then I thought why would you want to use something else, when ObjC works so great.
So it has been now that I have started playing with Python when I realized that I was looking at it the wrong way: Cocoa-Python is not intended to replace ObjectiveC in any way, but intended to bring to you Python scripts the most beautiful user interface available: the Cocoa framework.
One of the first things I wanted to know is if all the scripts I have created lately, which use different libraries like htmllib, urllib2, cookielib or sqlite3 would work on my XCode project. And the answer is yes, everything seems to work! All Python libraries are available :)
The script I have been using today is a script to dump cookies from the sqlite database which Firefox 3 uses for storage to a plain text file (actually the file created is a netscape formatted cookiejar file). I created this code based on code I found on Internet:
So now let's make it work on XCode. At first, the new Cocoa-Python project will look like this:
The original script was command line driven, so it didn't require any extra user action. For the Cocoa based version, we want to use the interface, so we will load the cookies after clicking a button and we will show the cookies on a nice table (instead of saving the data to a file
At this point, the application has all the functionality we need to read cookies from Firefox, but still doesn't do anything, since it doesn't interact with the user interface yet.
When you program in Cocoa with Interface Builder, you have to define some Outlets and Actions on your AppController class. On Objective-C you do this on the header (.h) file. So I was a little bit lost, since Python doesn't have header files.
The way to do it is directly in between you class code. Outlets are varibles declared as myOutlet = objc.IBOutlet(), which will let Interface Builder know about their existence. In order to define class methods as Actions, the line @objc.IBAction has to be added before the function itself.
We want to interact with an NSArrayController, which will pass our cookies to the NSTableView. Before, our cookies will be stored on a Python list of dictionaries
The last two functions are accessors that would let us link our NSArrayController to our python's cookies list. So we are done
Our application has a very simple interface, with NSTableView to scroll through the cookies and a fieldset to show all cookie fields.

Now we need to bind the table and all fields to the array controller. Next, we need to bind the array controller to our FirefoxCookieDumperAppDelegate cookieArray accessor. Don't forget to bind the Load Cookies button and we are done!
So now you may be wondering why did we need an outlet for the NSArrayController. Well, there is a problem with our application (I'm not sure about if this is a bug or not). If we run the application and click on Load Cookies button, the screen will still empty. our cookies will be loaded, though. But the screen won't refresh.
In order to make the screen refresh properly I have used a little trick: add an object calling NSArrayController.addObject and deleting it. It's not very pretty, but it works. Please, if anyone knows how to do this better let me know :)
Here is the final capture, with all cookies dumped:

As you can see, it is very, very easy to add a Cocoa user interface to your Python scripts. It takes a while to figure it out at the beginning, but soon everything starts making sense :)
Hope you enjoyed the post!
PS: I have let the Clear button implementation for you :)
Post new comment