1"""TableModel.py -- Minimal example showing how to use an NSTableView. 2 3To build the demo program, run this line in Terminal.app: 4 5 $ python setup.py py2app -A 6 7This creates a directory "dist" containing TableModel.app. (The 8-A option causes the files to be symlinked to the .app bundle instead 9of copied. This means you don't have to rebuild the app if you edit the 10sources or nibs.) 11""" 12 13# Or rather, this app shows how to create an object conforming to the 14# NSTableDataSource protocol. The model object is connected to the table view 15# in the nib, both as the delegate and the data source. The table view will 16# ask our object for data; it controls us, not the other way around. 17 18from PyObjCTools import AppHelper 19from Cocoa import * 20import pkg_resources 21 22ROWCOUNT = 200 23 24# class defined in MainMenu.nib 25class TableModel(NSObject): 26 label = objc.IBOutlet() 27 tableView = objc.IBOutlet() 28 29 # An instance of this class is connected to the 'datasource' and 30 # the 'delegate' outlet of the table view in the nib. 31 32 def awakeFromNib(self): 33 self.editedFields = {} 34 self.rowcount = ROWCOUNT 35 # tableView is an outlet set in Interface Builder 36 self.tableView.setAutosaveName_("TableView") 37 self.tableView.setAutosaveTableColumns_(1) 38 self.tableView.setTarget_(self) 39 self.tableView.setDoubleAction_("doubleClick:") 40 self.tableView.window().setDelegate_(self) 41 42 def init(self): 43 self.rowcount = ROWCOUNT 44 return self 45 46 @objc.IBAction 47 def doubleClick_(self, sender): 48 # double-clicking a column header causes clickedRow() to return -1 49 print "doubleClick!", sender.clickedColumn(), sender.clickedRow() 50 51 # data source methods 52 def numberOfRowsInTableView_(self, aTableView): 53 return self.rowcount 54 55 def tableView_objectValueForTableColumn_row_( 56 self, aTableView, aTableColumn, rowIndex): 57 col = aTableColumn.identifier() 58 return self.editedFields.get((aTableColumn, rowIndex), 59 "{%s, %d}" % (col, rowIndex)) 60 61 def tableView_setObjectValue_forTableColumn_row_( 62 self, aTableView, anObject, aTableColumn, rowIndex): 63 self.editedFields[(aTableColumn, rowIndex)] = anObject 64 65 # delegate methods 66 def tableView_shouldSelectRow_(self, aTableView, rowIndex): 67 # only allow odd rows to be selected 68 return rowIndex % 2 69 70 def tableView_shouldEditTableColumn_row_(self, aTableView, aTableColumn, rowIndex): 71 # only allow cells in the second column in odd rows to be edited 72 return (rowIndex % 2) and aTableColumn.identifier() == "col_2" 73 74 def tableViewSelectionDidChange_(self, notification): 75 # Always use this delegate method instead of using the action to do something 76 # when the selection changed: the action method is only called when the selection 77 # changed by means of a mouse click; this method is also called when the 78 # user uses the arrow keys. 79 if self.tableView.numberOfSelectedRows() == 0: 80 if self.tableView.numberOfSelectedColumns() == 0: 81 self.label.setStringValue_("") 82 else: 83 items = list(self.tableView.selectedColumnEnumerator()) 84 word = "Column" 85 else: 86 items = list(self.tableView.selectedRowEnumerator()) 87 word = "Row" 88 label = "%s%s: %s" % (word, ("s", "")[len(items) == 1], ", ".join([str(x) for x in items])) 89 self.label.setStringValue_(label) 90 91 def windowShouldClose_(self, sender): 92 print "Should Close?" 93 return 0 94 95 96AppHelper.runEventLoop() 97