Introduction to Part 1

This part 1 of th Quickly tutorial. This part is will introduce some key quickly commands, editing a user interface in Glade, and editing code in Gedit. This part of the tutorial will familiarize you with these three tools, and how they work together with python and pygtk so that you can quickly build applications.

Creating a Quickly Project

Creating the Empty Project

Creating an empty but working program couldn't be simpler. First, open a terminal window to type commands into. When it's open, type the command:

type 'quickly new ubuntu-project super_text' into terminal

This will create a super_text sub directory containing a complete directory tree and files for an empty python appliction. The command finishes by running the newly created empty application.

The command finishes by running the empty application.

Testing the Empty Application

They are populated and set up, and you can resize the window. Notice that quickly interfered that the application title is "Super Text". Only a few of menu items do anything in the empty application, Help->About, Edit->Preferences, and File->Quit.

The menus are populated and set up.

Running the Application

Close the application by closing the window or using the Quit command. Since the empty application isn't installed into Ubuntu yet, you can't start the application from the application menu yet. To start the applicaton, use the terminal to first cd into the new subdirectory, and then issue the command to start the program.

run the empty application from the terminal

Editing an Application

Edit the User Interface in Glade

Quickly programs use Glade to edit the user interface. Start Glade with quickly in order to set up Glade for editing the empty applicaton. Don't start glade directly, or it won't load the necessary catalogue files for editing the classes that were automaticaly generated by quickly.

start glade with the 'quickly glade' command

Glade will open with the project loaded up and ready to edit.

glade loads the project

Use the Project Menu to choose "SuperTextWindow.ui" for editing.

choose SuperTextWindow.ui from the project menu

We want to create a text area for typing into. There are some default Widgets added to the Window. We won't need these so we'll start with deleting them. Click on the label, and press delete, and it will disappear from the window.

select the label delete the label from the window

Do the same with the image widget. This leave us two free slots.

two empty slots in the window

We'll use the bottom slot to add a TextView widget for the user to type into. In the toolbox, click on the TextView widget. Then click in the empty slot.

click on the text view widget

Make sure you save the file in Glade, or your changes won't take! Then run the application from terminal again. The window now has a place where the user can type.

the applicaton permits typing

Now we'll add the entry field for the title, and also a label for it. We'll use the top empty slot for that. First, click on Horizontal Box (HBox) from the "Containers" section of the pallette, and then click on the top slot. A dialog box will open, tell it that you want two items.

tell the hbox you want two items

The HBox is a container that arranges it's children horizontally. Add a label to the empty left hand box, and a Text Entry to the right hand one.

text entry is added

Before going on, let's clean up the UI just a tad here. Select the new HBox from the treeview in the inspector window. Then go to the Packing tab, and set Expand and Fill to "No".

no expand and fill

Go to the General tab, and set spacing to 5.

spacing is 5

Set expand and fill to "no" for the label, but keep it "yes" for the entry. Set the padding for both to 5 (also on the Packing tab).

glade all cleaned up

Add the Save, Open, and New Features

After the user types something, they may want to save it. A File->Save menu item was automatically created when the empty applicaton was created, but it's not hooked up to any code. To make Save work, we need tell the menu item what function to call, and then create a function to actually do the saving.

Set the Signal Handler in Glade

To tell the menu item what function to call. If glade is not still open, open up the appliction in glade:

Click on the file menu, and the menu opens as if the application were running.

choose the menu item

Choose the Save menu item, and it will be selected in Glade.

the menu item is selcted in glade

Then choose the "Signals" tab of the properties window.

signals tab in glade

In pygtk, menu items are "activated" when a user chooses the item from the menu. Since we want a function to run when the user chooses Save, we want to specify a function to respond to the activate signal from the menu item. We'll call the function "save_file". Simply type the function name into the box for the activate signal. Make sure to save the glade file.

activate signal set to 'save_file'

Edit the Code in Gedit

Create the Save File Signal Handler

Of course, this won't make the file actually save, because we haven't created the "save_file" function yet. So it's time to write a little code. The code for SuperTextWindow is stored in the file SuperTextWindow.py.

Notice the relationship, SuperTextWindow.ui and SuperTextWindow.py. These two files always work tog.ether to make your program work. The .ui file stores the presentation of the window, while the .py file stores the behavior.

Use the quickly edit command to start editing your code files:

This will open the default Ubuntu text editor "Gedit" with any python files in the python directory.

python files ready to edit

SuperTextWindow.ui is now expecting to find a function SuperTextWindow.save_file(), so we simply add one to the SuperTextWindow class:

This will print the word "save" to the terminal when run. The method signature is the standard signature expected in a signal handler. If you are new to python, be sure to copy the indentations exactly, as the indentation level is very important in python.

Save the file, and run it again:

Choose "File->Save" from the menu, and you'll see the word "save" printing out interminal. That's all there is to hookig up the functions!

'save' gets printed to the terminal

Implementing Save

Now we'll write a little code in the signal handler to actually save the text. Because we want it to be easy for users to do things like syncronize their Super Text documents between computers, back it up, etc... we'll use couchdb as our backend. Note that if you are not interested in learning about how to save to and read from couchdb, you can just snipe the code. First, you may need to install couchdb and python-couchdb. The fastest way to do this is from ther terminal:

After couchdb and python-couchdb is installed, you can write the code. The code will do the following:

  1. Import the stuff you'll need from python-couchdb.
  2. Specify the database location.
  3. Get a reference to the couchdb database to save into.
  4. Get the title of the document and the text from the user interface.
  5. Check if there is already a document with the same title, and if so overwrite it.
  6. If there is not a document already, create one.

Import the stuff you'll need from python-couchdb.

Add these import statements along with the other imports to the top of SuperTextWindow.py:

Specify the database location

We'll just hard code a reference to the database on the user's computer. If we want to point to a couchdb instance somewhere else later, it will be easy to change. We also want to name the datbase something reasonably unique, we'll use "super_text". Since we want these lines to run every time the Super Text window is created, put these at the end of the finish_initializing function:

Get a reference to the database

Now in our save_file function, we want to get a reference to the database. However, if this is the first time that the application is run, the database may not have been created yet. Fortunately, it's an easy matter to check for the database, and if it's not there to create it.

Here's the code to pull the title out of the title entry:

Here's the code to get pull the text out of the TextView:

In pygtk, TextView widgets have a text buffer that stores the text. So you ask the TextView for it's TextBuffer, and then you ask the TextBuffer for the text. You use iters to determine from which part of the text buffer you want text. Since we want all the text, it's easy to just get the start and end iters.

Saving a document to Couchdb

A document in couch is essentially a python dictionary. So we can save the document to couch like this:

The "record_type" field is not really required, but among other things, it makes it easy to fetch the documents later. By convention, we use a url to specify the record type. This provides a place for other developers to go to read about the record type. The description only needs to be human readable. Couchdb is not a typed database, so don't expect that the url will have any kind of schema definition or anything. You can use whatever url you want, and put whatever you want at that URL.

Check for a pre-existing note with the same title

Before we just write the new document though, we have to take note of the fact that couch will allow you to create as many documents as you want with the same title. We probably don't want this, so we we'll have to write a little code to check if there is already a document in couch with the same title, and if there is, update that document rather than create a new one.

To do this:

  1. Write a filtering function in javascript.
  2. Query the database with this function.
  3. Get the id for the first returned document
  4. Use that id to get a reference to the docuemnt.
  5. Change the text in the document.
  6. Overwrite the document in the database with the one you just created.

This all may sound very weird, but in code, it's not quite so complicated:

So the whole function should look like this:

Couchdb makes it really easy to see if your save function is working. You can just point your web browser at it and explore the database:

http://localhost:5984/_utils/
open couchdb in a browser

Implementing Open and New

To open a saved document, the user will type the title of the document that they want to open in the text entry, and choose "Open" from the main menu. If there is no matching document there, it will just clear out the text view, ready for input. This is probably not too intuitive, so we'll add a dialog box for prompting the user for the title, but that's for later in the tutorial. For now, we'll just use the same text entry field.

Implementing Open is essentially the reverse of Save:

Follow these steps:

  1. Check if the database has been created, or if this is a first run.
  2. Get the title the user is looking for from the text entry
  3. Query the database, and pull out the text matching the title, if any
  4. Set the text view to display the new text

So the open_file function looks like so:

To implement New, we'll just clear out the text, like this:

To make them work, add these functions to the SuperTextWindow class, and save. Then go back and connect the functions to the activate signals for the Open and New menu items.

Saving Your Work

When Quickly created your application, it automatically added it to Bazaar, a source code versioning system. You can use Bazaar to roll back mistake, see code history, compare versions, etc... Quickly has a convenience function for backing up your work:

This will call "$bzr add" and then "$bzr commit -m [your meesage]" for you.