Wednesday, July 30, 2008

Checking with CoreData

I wrote an application about two years ago called "SmartChecking" to act as my checkbook. I talked about it here and it's still available in my Public Folder. I still like it very much. Key features are: auto-dating of new items, auto-detection of checks (deposits are recognized by keywords). Checks are auto-dated and converted to negative values for computing the balance. The best thing is a balance column with two modes, one mode only counts items that have cleared the bank. I never have any trouble balancing my checkbook.

While playing with CoreData I realized that the checking app is a perfect test case for learning more. So, in about 3 hours, I produced a skeleton that works (sort of) and, until the last two features, it had absolutely no code! (I've spent most of the time tweaking the User Interface). Here is a screenshot:



The data model is a single entity (Transaction) with attributes: amount, date, identifier, isCheck, isClear, and number. These are wired up using a single controller in the standard way for table views. The box at the bottom of the window gives details on the selected item. I changed a couple of things that did require some code. First, the date for a new transaction is set to the current date (exactly as described in the Apple tutorial and my last post).

Also, I wanted the + button to not only add a new item, but also switch focus to the name text field. I tried sending the action to my document and then relaying it to the array controller, but that screws up Undo. So I just wrote a new controller that inherits from NSArrayController and notifies my text field to selectText when the add returns. Hillegass has a much more complicated solution. (And I should probably be using a Category, or something). Anyway, here's the code:

class NotifyingArrayController(NSArrayController):
myAppDelegate = objc.IBOutlet()

def init(self):
self = super(NotifyingArrayController,self).init()
return self

def add_(self,sender):
print 'add_'
super(NotifyingArrayController,self).add_(sender)
self.myAppDelegate.myTextField.selectText_(self)

class TransactionMO(NSManagedObject):
def init(self):
self = super(CommitMessageMO,self).init()
return self

def awakeFromInsert(self):
self.setValue_forKey_(NSDate.date(),u"date")


There is still a lot to do, however:

• bind the text color of the amount to check v. deposit 
(How to specify the alternate color?)
• make Return key to bring up a new item,
but only if we are not currently editing.
• do the balance computation using bindings
• implement insert as well as add
• If I use a currency formatter,
it requires me to type the $ sign and
complete the cents. I want it to be smarter.
• implement auto-check numbering

But undo, save and open recent work. Oops, print does not work yet. I should add a toolbar too, for fun.