Introduction to Part 2

In part 1, we created an application that can read and write text files, and persist them in the couchdb backend. However, the application has a hideous usability flaw, in the text box for specifying titles when saving and opening files is very confusing. In part 2, we'll fix thay by adding a save and an open dialog.

Creating a Quickly Dialog

Creating the Empty Dialog

It's simple to add an empty, but working dialog to your project. Simply specify the name of the new dialog, and it will be added automatically. Assuming that you are in the jotty project directory:

This will add the dialog to your project.

Editing the New Dialog

To edit the UI for the dialog, you'll need to load it into Glade again. If you already have an instance of glade running, you might want to go ahead and close it first, as it may get confusing if you have more than one open at a time. After closing glade, simply open it again:

Then use the project menu to switch to newly created SaveDialog.ui file.

save dialog ready to edit

Then add some widgets for the UI. Start with a Vertical Box (VBox) with two items. Put label in the top, and an HBox in the bottom slot. In the HBox, add a label and an edit widget, just like you did for JottyWindow in part 1. Set the padding and expand properties as well.

save dialog all edited

Code the Dialog

You can use the "quickly edit" command to open the SaveDialoy.py file. This dialog needs very little additional code to work. Essentially, you just need a way to retrieve the string specified by the user. We'll add a qiuck accessor method for this:

We don't need to write any code for the Ok and Cancel buttons, as they were automatically hooked up by quickly when it created the dialog.

Before we go on to invoking the dialog, delete HBox from JottyWindow that holds the text entry and label, as we won't be needing those.

text entry now deleted

Calling the Save Dialog

To use the dialog in JottyWindow, we need to follow these steps:

  1. Import SaveDialog in JottyWindow
  2. In the save_file function, create an instance of SaveDialog
  3. Run the Dialog
  4. Get the String
  5. Destroy the dialog

Importing the SaveDialog

Add the SaveDialog to the list of imported modules at the top of the, so it looks like this:

Create an instance of the dialog and run it

When the user chooses Save, we want to open the SaveDialog and collect the title of the note from the user. So we need to modify our save_file function.

To create an instance of the dialog, use the NewSaveDialog() function in the SaveDialog module. It's important that you don't create an instance of SaveDialog directly, as it won't have a chance to load up it's UI that way, and it won't work. So whenever you use a quickly dialog, do it like this:

d

To make the dialog appear, simply use the run() method. However, we want to check the result, so we'll need to store that in a variable. After it runs, we want to collect the string from the user, like this:

Clean up the dialog

We need to tell the dialog to not show itself anymore. We could call saver.hide() to make it hide, but since we don't need it hanging around, we'll just destroy it. Before we go on, though, we need to ensure that the user actually wants to save, so if we didn't get the Ok result, we should just return out of the function:

Since we're now getting the title from the dialog instead of the text entry, we should delete the line of the code that sents it from entry1. So except for the addition of the dialog code, the save_file function looks pretty much the same as it did in part 1:

Now when we choose save, we get the SaveDialog instead: save file dialog works much better

Creating a Dialog with a CouchGrid

We'll use a similar approach in the Open dialog that we did with Save. However, there is one big difference, we want to provide the user with a list of documents that you could choose to open. We'll use a widget called CouchGrid, which is included in the desktopcouch api for this.

Create the Open Dialog

su

Editing the New Dialog

Start out by closing, and then reopening glade again:

Start by adding an HBox and label in the sammer manner as in the Save Dialog above. Leave an empty space in the HBox. We will use code to put the CouchGrid there.

save space for the CouchGrid

Coding the Open Dialog

Creating and Adding a CouchGrid

It just takes a little bit of code to add a CouchGrid to the dialog. We need to:

  1. Import the CouchGrid class.
  2. Create a CouchGrid pointing at the jotty database, and the desired record type.
  3. Add the CouchGrid to the dialog.

Import the CouchGrid class

CouchGrid is part of the desktopcouch records api, so we import it like this:

Create the CouchGrid

A CouchGrid needs to know three things, the name of the database, the name of the record type to, and the name of the keys to use. "keys" is a list of fields that the widget will display, and will also use the same text for the heading of any columns. This set up should be done in the OpenDialog's finish_initalizing function. All this is easily done in code like this:

Add the CouchGrid to the Dialog

When we added the HBox to the dialog, we left an open space at the bottom. We'll use this by "packing" the CouchGrid into the HBox. We need to show it as well. So add the following lines to the finish_initializing function as well:

Create the get_selection function

The dialog still needs a bit more code to work. It needs to return the user's selection, if there is one. To do this, we need to ask the CouchGrid what is selected. This is easy using the widgets selected_record_ids function. But the CouchGrid supports multiple selection, so we'll do the following:

  1. Use a decorator to define the function as a property accessor.
  2. Get all the selected record ids.
  3. If none are selected, return None.
  4. Pick the first one and return it.

So the function to add to OpenDialog looks like this:

Using the Open Dialog

Now we want to use the Open Dialog in the JottyWindow open_file function. To use it,we'll follow these steps:

  1. Import OpenDialog in JottyWindow
  2. In the open_file function, create an instance of OpenDialog
  3. Run the Dialog
  4. Get the id for the selected title.
  5. Destroy the dialog
  6. Check the response before proceeding
  7. Use the id to get the record from CouchDB
  8. Update the UI

Import OpenDialog

Just like the SaveDialog, add the import line to the list of imports:

Create an instance of the dialog and run it

So now we're ready to call the dialog from the JottyWindow's open_file function. Creating the OpenDialog is exactly the same as creating the SaveDialog, except we also want to tell it to load the titles before we run it:

Get the id for the selected title

Now use the get_selection function to retrieve the title and text from the dialog. Don't forget to check the response type before going on.

Get the ID for the selected title

This merely involves using the property that we created for th OpenDialog:

Use the id to get the record from CouchDB

If nothing was selected, we'll just return. Otherwise, we'll retrieve the record from CouchDB and pull out the text for the document:

Update the UI

Now just put the text into the texview:

That's all there is to it. So the whole open_file function looks like this:

Now users get a nice open dialog:

open dialog works much better

Finsihing the Application

Now opening a saved document is much more intuitive.

open file dialog works much better

However, the application is not complete. There are a few things left for you to do: