Thread: [Pyobjc-dev] NSTableView and Drag and Drop
Brought to you by:
ronaldoussoren
From: John S. <jo...@sk...> - 2008-01-24 22:51:21
|
Hi PyObjC list, I have a table view that I'd like to add drag and drop support to. I borrowed a lot of code from the bookmarks example and some Objective-C examples I've found across the net (and I used tableView_writeRowsWithIndexes_toPasteboard_ rather than tableView_writeRows_toPasteboard_ since I read writeRows is deprecated). I've also modified it a little since my application is not document-based. Ideally the user would be able to reorder items in the table (I don't anticipate the need for copy and paste). I have it almost working--I can drag an element, but on drop, I get the following error: An unexpected error has occurred (TypeError: 'NoneType' object is not iterable) I've implemented the three methods I believe I'm supposed to implement for DND table support and I've declared a pasteboard type. I don't know if it's because the acceptDrop or validateDrop methods aren't working. Ideas? My code is below: """ ApplicationDelegate.py Controller class for the application """ from Foundation import * from AppKit import * from PyObjCTools import NibClassBuilder import objc from objc import YES, NO, IBOutlet, IBAction from ApplicationModel import * MovedRowsType = u"MOVED_ROWS_TYPE" class ApplicationDelegate(NSObject): # Outlets arrayController = objc.IBOutlet() tableView = objc.IBOutlet() # Class methods def init(self): self = NSObject.init(self) return self def awakeFromNib(self): # register for drag and drop self.tableView.registerForDraggedTypes_([MovedRowsType]) def tableView_writeRowsWithIndexes_toPasteboard_(self, tv, rowIndexes, pboard): typesArray = [MovedRowsType] data = NSKeyedArchiver.archivedDataWithRootObject_(rowIndexes) pboard.declareTypes_owner_(typesArray, self) #pboard.setData_forType_(typesArray, self) NSLog("boo-yeah") return YES def tableView_validateDrop_proposedRow_proposedDropOperation_(self, tv, info, row, op): dragOp = NSDragOperationMove tv.setDropRow_dropOperation_(row, NSTableViewDropAbove) return dragOp def tableView_acceptDrop_row_dropOperation_(self, tv, info, row, op): if row < 0: row = 0 if info.draggingSource() == self.tableView: rows = info.draggingPasteboard().propertyListForType_(MovedRowsType) indexSet = self.indexSetFromRows_(rows) self.moveObjectsInArrangedObjectsFromIndexes_toIndex_(indexSet, row) rowsAbove = self.rowsAboveRow_inIndexSet_(row, indexSet) aRange = NSMakeRange(row - rowsAbove, indexSet.count()) indexSet = NSIndexSet.indexSetWithIndexesInRange_(aRange) self.arrayController.setSelectionIndexes_(indexSet) return YES return NO def moveObjectsInArrangedObjectsFromIndexes_toIndex_(self, indexSet, insertIndex): objects = self.arrayController.arrangedObjects() index = indexSet.lastIndex() aboveInsertIndexCount = 0 removeIndex = 0 while index != NSNotFound: if index >= insertIndex: removeIndex = index + aboveInsertIndexCount aboveInsertIndexCount += 1 else: removeIndex = index insertIndex -= 1 obj = objects.objectAtIndex_(removeIndex) self.arrayController.removeObjectAtArrangedObjectIndex_(removeIndex) self.arrayController.insertObject_atArrangedObjectIndex_(obj, insertIndex) index = indexSet.indexLessThanIndex_(index) def indexSetFromRows_(self, rows): indexSet = NSMutableIndexSet.indexSet() for row in rows: indexSet.addIndex_(row) return indexSet def rowsAboveRow_inIndexSet_(self, row, indexSet): currentIndex = indexSet.firstIndex() i = 0 while currentIndex != NSNotFound: if currentIndex < row: i += 1 currentIndex = indexSet.indexGreaterThanIndex_(currentIndex) return i |
From: Michael M. <mic...@gm...> - 2008-01-25 18:26:35
|
Hi John, from a quick peek at your code, it sounds like the 'rows' argument in indexSetFromRows_ is None, since it's trying to iterate it. And it looks like in tableView_writeRowsWithIndexes_toPasteboard_, you declare the type but have commented out the setData call: def tableView_writeRowsWithIndexes_toPasteboard_(self, tv, rowIndexes, pboard): typesArray = [MovedRowsType] data = NSKeyedArchiver.archivedDataWithRootObject_(rowIndexes) pboard.declareTypes_owner_(typesArray, self) #pboard.setData_forType_(typesArray, self) NSLog("boo-yeah") return YES I'm guessing your call to setData_forType_ should look something more like this: pboard.setData_forType_(data, MovedRowsType), and then when you ask for the data later in acceptDrop: rows = info.draggingPasteboard().propertyListForType_(MovedRowsType) you should get something other than None. HTH, -mike On Jan 24, 2008 2:51 PM, John Skidgel <jo...@sk...> wrote: > > Hi PyObjC list, > > I have a table view that I'd like to add drag and drop support to. I > borrowed a lot of code from the bookmarks example and some Objective-C > examples I've found across the net (and I used > tableView_writeRowsWithIndexes_toPasteboard_ rather than > tableView_writeRows_toPasteboard_ since I read writeRows is deprecated). > I've also modified it a little since my application is not document-based. > Ideally the user would be able to reorder items in the table (I don't > anticipate the need for copy and paste). I have it almost working--I can > drag an element, but on drop, I get the following error: > > An unexpected error has occurred > (TypeError: 'NoneType' object is not iterable) > > I've implemented the three methods I believe I'm supposed to implement for > DND table support and I've declared a pasteboard type. I don't know if it's > because the acceptDrop or validateDrop methods aren't working. Ideas? > > My code is below: > > > """ > ApplicationDelegate.py > Controller class for the application > """ > > from Foundation import * > from AppKit import * > from PyObjCTools import NibClassBuilder > import objc > from objc import YES, NO, IBOutlet, IBAction > > from ApplicationModel import * > > MovedRowsType = u"MOVED_ROWS_TYPE" > > class ApplicationDelegate(NSObject): > # Outlets > arrayController = objc.IBOutlet() > tableView = objc.IBOutlet() > > # Class methods > def init(self): > self = NSObject.init(self) > return self > > def awakeFromNib(self): > # register for drag and drop > self.tableView.registerForDraggedTypes_([MovedRowsType]) > > def tableView_writeRowsWithIndexes_toPasteboard_(self, tv, rowIndexes, > pboard): > typesArray = [MovedRowsType] > data = NSKeyedArchiver.archivedDataWithRootObject_(rowIndexes) > pboard.declareTypes_owner_(typesArray, self) > #pboard.setData_forType_(typesArray, self) > NSLog("boo-yeah") > return YES > > def tableView_validateDrop_proposedRow_proposedDropOperation_(self, tv, > info, row, op): > dragOp = NSDragOperationMove > tv.setDropRow_dropOperation_(row, NSTableViewDropAbove) > return dragOp > > def tableView_acceptDrop_row_dropOperation_(self, tv, info, row, op): > if row < 0: > row = 0 > > if info.draggingSource() == self.tableView: > rows = info.draggingPasteboard().propertyListForType_(MovedRowsType) > indexSet = self.indexSetFromRows_(rows) > self.moveObjectsInArrangedObjectsFromIndexes_toIndex_(indexSet, row) > > rowsAbove = self.rowsAboveRow_inIndexSet_(row, indexSet) > aRange = NSMakeRange(row - rowsAbove, indexSet.count()) > indexSet = NSIndexSet.indexSetWithIndexesInRange_(aRange) > self.arrayController.setSelectionIndexes_(indexSet) > return YES > return NO > > def moveObjectsInArrangedObjectsFromIndexes_toIndex_(self, indexSet, > insertIndex): > objects = self.arrayController.arrangedObjects() > index = indexSet.lastIndex() > aboveInsertIndexCount = 0 > removeIndex = 0 > while index != NSNotFound: > if index >= insertIndex: > removeIndex = index + aboveInsertIndexCount > aboveInsertIndexCount += 1 > else: > removeIndex = index > insertIndex -= 1 > obj = objects.objectAtIndex_(removeIndex) > self.arrayController.removeObjectAtArrangedObjectIndex_(removeIndex) > self.arrayController.insertObject_atArrangedObjectIndex_(obj, > insertIndex) > index = indexSet.indexLessThanIndex_(index) > > def indexSetFromRows_(self, rows): > indexSet = NSMutableIndexSet.indexSet() > for row in rows: > indexSet.addIndex_(row) > return indexSet > > def rowsAboveRow_inIndexSet_(self, row, indexSet): > currentIndex = indexSet.firstIndex() > i = 0 > while currentIndex != NSNotFound: > if currentIndex < row: > i += 1 > currentIndex = indexSet.indexGreaterThanIndex_(currentIndex) > return i > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev > > -- Michael McCracken UCSD CSE PhD Candidate research: http://www.cse.ucsd.edu/~mmccrack/ misc: http://michael-mccracken.net/wp/ |