OutlineEdit
===========

* :download:`Download example <PyObjCExample-OutlineEdit.zip>`

A python version of the OutlineEdit example that's included with Xcode 2.0.


.. rst-class:: tabber

Sources
-------

.. rst-class:: tabbertab

MyDocument.py
.............

.. sourcecode:: python

    import Cocoa
    import CoreData
    import objc
    from objc import super  # noqa: A004
    
    prioritySortDescriptions = Cocoa.NSArray.arrayWithObject_(
        Cocoa.NSSortDescriptor.alloc().initWithKey_ascending_("value", True)
    )
    
    
    class MyDocument(CoreData.NSPersistentDocument):
        outlineTreeController = objc.IBOutlet()
    
        def initWithType_error_(self, tp, error):
            self, error = super().initWithType_error_(tp, error)
            if self is None:
                return (None, error)
    
            managedObjectContext = self.managedObjectContext()
    
            for aPriorityValue in range(5):
                aPriority = CoreData.NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext_(  # noqa:  B950
                    "Priority", managedObjectContext
                )
                aPriority.setValue_forKey_(aPriorityValue + 1, "value")
    
            CoreData.NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext_(
                "Note", managedObjectContext
            )
    
            managedObjectContext.processPendingChanges()
            managedObjectContext.undoManager().removeAllActions()
            self.updateChangeCount_(Cocoa.NSChangeCleared)
    
            return (self, None)
    
        def windowNibName(self):
            return "MyDocument"
    
        def prioritySortDescriptions(self):
            return prioritySortDescriptions
    
        def createNote_(self, sender):
            self.outlineTreeController.add_(sender)
    
        def createChildNote_(self, sender):
            self.outlineTreeController.addChild_(sender)
    
        def indentNote_(self, sender):
            selectionPath = self.outlineTreeController.selectionIndexPath()
            if not selectionPath:
                Cocoa.NSBeep()
                return
    
            selection = self.outlineTreeController.selection()
    
            parentNote = selection.valueForKeyPath_("parent")
            if parentNote is None:
                children = self.outlineTreeController.content()
            else:
                children = parentNote.valueForKeyPath_("children").allObjects()
    
            children = children.sortedArrayUsingDescriptors_(
                self.outlineTreeController.sortDescriptors()
            )
    
            index = selectionPath.indexAtPosition_(selectionPath.length() - 1)
            if index == 0:
                Cocoa.NSBeep()
            else:
                sibling = children.objectAtIndex_(index - 1)
                selection.setValue_forKeyPath_(sibling, "parent")
    
        def dedentNote_(self, sender):
            selection = self.outlineTreeController.selection()
            parent = selection.valueForKeyPath_("parent")
    
            if parent in (
                None,
                Cocoa.NSMultipleValuesMarker,
                Cocoa.NSNoSelectionMarker,
                Cocoa.NSNotApplicableMarker,
            ):
                Cocoa.NSBeep()
                return
    
            parent = parent.valueForKeyPath_("parent")
            selection.setValue_forKeyPath_(parent, "parent")

.. rst-class:: tabbertab

Note.py
.......

.. sourcecode:: python

    import CoreData
    
    noteCount = 1
    
    
    class Note(CoreData.NSManagedObject):
        def awakeFromInsert(self):
            global noteCount
    
            contents = "Note #%d" % (noteCount,)
            noteCount += 1
            self.setValue_forKey_(contents, "contents")

.. rst-class:: tabbertab

main.py
.......

.. sourcecode:: python

    import MyDocument  # noqa: F401
    import Note  # noqa: F401
    from PyObjCTools import AppHelper
    
    if __name__ == "__main__":
        AppHelper.runEventLoop()

.. rst-class:: tabbertab

setup.py
........

.. sourcecode:: python

    """
    Script for building the example.
    
    Usage:
        python3 setup.py py2app
    """
    
    from setuptools import setup
    
    plist = {
        "NSMainNibFile": "MainMenu",
        "CFBundleDocumentTypes": [
            {
                "CFBundleTypeExtensions": ["binary"],
                "CFBundleTypeMIMETypes": ["application/octect-stream"],
                "CFBundleTypeName": "Binary",
                "CFBundleTypeRole": "Editor",
                "LSTypeIsPackage": False,
                "NSDocumentClass": "MyDocument",
                "NSPersistentStoreTypeKey": "Binary",
            },
            {
                "CFBundleTypeExtensions": ["sql"],
                "CFBundleTypeMIMETypes": ["application/octect-stream"],
                "CFBundleTypeName": "SQL",
                "CFBundleTypeRole": "Editor",
                "LSTypeIsPackage": False,
                "NSDocumentClass": "MyDocument",
                "NSPersistentStoreTypeKey": "SQLite",
            },
            {
                "CFBundleTypeExtensions": ["xml"],
                "CFBundleTypeMIMETypes": ["text/xml"],
                "CFBundleTypeName": "XML",
                "CFBundleOSTypes": ["????"],
                "CFBundleTypeRole": "Editor",
                "LSTypeIsPackage": False,
                "NSDocumentClass": "MyDocument",
                "NSPersistentStoreTypeKey": "XML",
            },
        ],
    }
    
    setup(
        name="PyOutlineEdit",
        app=["main.py"],
        data_files=["English.lproj"],
        options={"py2app": {"plist": plist, "datamodels": ["MyDocument"]}},
        setup_requires=["py2app", "pyobjc-framework-Cocoa", "pyobjc-framework-CoreData"],
    )

