ToDos

Shows two array controllers, one to manage the contents of a table view, the other to manage a pop-up menu in a table column. Also shows two value transformers to alter the color of text.

Originally from “Cocoa Bindings Examples and Hints”, converted to PyObjC by u.fiedler.

Sources

Category.py

#
#  Category.py
#  ToDos
#
#  Converted by u.fiedler on 09.02.05.
#
#  The original version was written in Objective-C by Malcolm Crawford
#  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

from Foundation import NSObject
import objc


class Category(NSObject):
    title = objc.ivar('title')
    priority = objc.ivar('priority', objc._C_INT)

    @classmethod
    def allCategories(cls):
        """Predefined global list of categories"""
        return categories

    @classmethod
    def categoryForPriority_(cls, thePriority):
        for category in categories:
            if thePriority >= category.priority:
                return category
        return None

    @classmethod
    def categoryWithTitle_andPriority_(cls, aTitle, aValue):
        """Convenience constructor"""
        newCategory = Category.alloc().init()
        newCategory.title = aTitle
        newCategory.priority = aValue
        return newCategory


    # NSCoding methods
    # To encode, simply save 'priority'; on decode, replace self with
    # the existing instance from 'allCategories' with the same priority

    def encodeWithCoder_(self, encoder):
        if encoder.allowsKeyedCoding():
            encoder.encodeInt_forKey_(self.priority, u"priority")
        else:
            encoder.encodeObject_(self.priority)

    def initWithCoder_(self, decoder):
        if decoder.allowsKeyedCoding():
            thePriority = decoder.decodeIntForKey_(u"priority")
        else:
            thePriority = decoder.decodeObject()
        return Category.categoryForPriority_(thePriority)


categories = [
        Category.categoryWithTitle_andPriority_(u"Vital", 11),
        Category.categoryWithTitle_andPriority_(u"Very Important", 4),
        Category.categoryWithTitle_andPriority_(u"Important", 3),
        Category.categoryWithTitle_andPriority_(u"Not Important", 2),
        Category.categoryWithTitle_andPriority_(u"Whenever", 0)
]

OverdueTransformer.py

#
#  OverdueTransformer.py
#  ToDos
#
#  Converted by u.fiedler on 09.02.05.
#
#  The original version was written in Objective-C by Malcolm Crawford
#  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

from Cocoa import NSValueTransformer, NSColor

class OverdueTransformer(NSValueTransformer):

    @classmethod
    def transformedValueClass(cls):
        return NSColor

    @classmethod
    def allowsReverseTransformation(cls):
        return False

    def transformedValue_(self, aDate):
        if aDate is None:
            return None
        if aDate.timeIntervalSinceNow() < 0:
            return NSColor.redColor()
        return NSColor.blackColor()

PriorityToColourTransformer.py

#
#  PriorityToColourTransformer.py
#  ToDos
#
#  Converted by u.fiedler on 09.02.05.
#
#  The original version was written in Objective-C by Malcolm Crawford
#  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

from Cocoa import NSValueTransformer, NSColor

class PriorityToColourTransformer(NSValueTransformer):

    @classmethod
    def transformedValueClass(cls):
        return NSColor

    @classmethod
    def allowsReverseTransformation(cls):
        return False

    def transformedValue_(self, priority):
        if priority is None:
            return NSColor.blackColor()
        elif priority > 4:
            return NSColor.redColor()
        elif priority > 3:
            return NSColor.orangeColor()
        elif priority > 2:
            return NSColor.blueColor()
        elif priority > 1:
            return NSColor.greenColor()
        elif priority > 0:
            return NSColor.brownColor()
        else:
            return NSColor.blackColor()

ToDos.py

import ToDosDocument

if __name__ == '__main__':
    from PyObjCTools import AppHelper
    AppHelper.runEventLoop()

ToDosDocument.py

#
#  ToDosDocument.py
#  ToDos
#
#  Converted by u.fiedler on 09.02.05.
#
#  The original version was written in Objective-C by Malcolm Crawford
#  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

import objc
from objc import super
from Cocoa import NSDocument, NSMutableArray, NSValueTransformer
from Cocoa import NSKeyedArchiver, NSKeyedUnarchiver

from Category import Category
from PriorityToColourTransformer import PriorityToColourTransformer
from OverdueTransformer import OverdueTransformer

class ToDosDocument(NSDocument):
    nix = objc.IBOutlet()
    toDos = objc.ivar()

    def init(self):
        self = super(ToDosDocument, self).init()
        if self is None:
            return None
        self.toDos = NSMutableArray()
        return self # if this line is missing you will get the
                    # simple message: "Can't create new document"

    def categories(self):
        return Category.allCategories()

    def windowNibName(self):
        return "ToDosDocument"

    def dataRepresentationOfType_(self, aType):
        return NSKeyedArchiver.archivedDataWithRootObject_(self.toDos)

    def loadDataRepresentation_ofType_(self, data, aType):
        self.toDos = NSKeyedUnarchiver.unarchiveObjectWithData_(data)
        return True

priorityTransformer = PriorityToColourTransformer.alloc().init()
NSValueTransformer.setValueTransformer_forName_(
    priorityTransformer, "PriorityToColourTransformer")

overdueTransformer = OverdueTransformer.alloc().init()
NSValueTransformer.setValueTransformer_forName_(
    overdueTransformer, "OverdueTransformer")

setup.py

"""
Script for building the example:

Usage:
    python3 setup.py py2app
"""
from setuptools import setup

plist = dict(
    CFBundleDocumentTypes = [
        dict(
            CFBundleTypeExtensions=["ToDos", "*"],
            CFBundleTypeName="ToDos File",
            CFBundleTypeRole="Editor",
            NSDocumentClass="ToDosDocument",
        ),
    ],
)

setup(
    name="ToDos",
    app=["ToDos.py"],
    data_files=["English.lproj"],
    options=dict(py2app=dict(
        plist=plist,
    )),
    setup_requires=[
        "py2app",
        "pyobjc-framework-Cocoa",
    ]
)

Resources