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/
|