Problem With openPanelDidEnd in PyObjC in 10.6
Asked Answered
N

2

0

The following code which worked fine under OS X 10.5 now fails on 10.6:

    @IBAction
def addButton_(self, sender):
    panel = NSOpenPanel.openPanel()
    panel.setCanChooseDirectories_(YES)
    panel.setAllowsMultipleSelection_(YES)
    try:
        panel.beginSheetForDirectory_file_modalForWindow_modalDelegate_didEndSelector_contextInfo_(self.directory, None, NSApp().mainWindow(), self, 'openPanelDidEnd:panel:returnCode:contextInfo:', None)
    except:
        pass

@AppHelper.endSheetMethod
def openPanelDidEnd_panel_returnCode_contextInfo_(self, panel, returnCode, contextInfo):

The error I get is:

objc.BadPrototypeError: Python signature doesn't match implied Objective-C signature for <unbound selector openPanelDidEnd:panel:returnCode:contextInfo: of controller at 0x6166a70>
Nowell answered 28/9, 2010 at 2:48 Comment(0)
W
1

beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:contextInfo: has been deprecated in 10.6: http://developer.apple.com/library/mac/#documentation/cocoa/reference/ApplicationKit/Classes/NSOpenPanel_Class/DeprecationAppendix/AppendixADeprecatedAPI.html

struggling on the same problem cause PyObjC has no block signature http://pyobjc.sourceforge.net/documentation/pyobjc-core/blocks.html for beginSheetModalForWindow:completionHandler: and you can only use runModal

my solution:

panel = NSOpenPanel.openPanel()
panel.setCanChooseDirectories_(NO)
panel.setAllowsMultipleSelection_(NO)

panel.setAllowedFileTypes_(self.filetypes)
panel.setDirectoryURL_(os.getcwd())

ret = panel.runModal()
if ret:
    print panel.URL()

panel.URL() returns the user selection.

Wisniewski answered 2/3, 2011 at 1:17 Comment(0)
S
1

As elv notes, beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:contextInfo: has been deprecated in 10.6, and the new method to use is beginSheetModalForWindow:completionHandler: There's no metadata for this method in the version of PyObjC that shipped with Snow Leopard, but it has since been added, and you can update the appropriate file yourself so that you can use this method. Open /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport and find the element:

<class name='NSSavePanel'>

inside this, add the following:

<method selector='beginSheetModalForWindow:completionHandler:'>
    <arg index='1' block='true' >
        <retval type='v' />
        <arg type='i' type64='q' />
    </arg>
</method>
<method selector='beginWithCompletionHandler:'>
    <arg index='0' block='true' >
        <retval type='v' />
        <arg type='i' type64='q' />
    </arg>
</method>

This is the metadata that the Python side needs in order to get and return the correct types of objects to Objective-C. You can pass any callable for the completion handler, as long as it has the correct signature (i.e., takes an integer argument and returns nothing). An example:

def showOpenPanel_(self, sender):
    openPanel = NSOpenPanel.openPanel()

    def openPanelDidClose_(result):
        if result == NSFileHandlingPanelOKButton:
            openPanel.orderOut_(self)
            image = NSImage.alloc().initWithContentsOfFile_(openPanel.filename())
            self.imgView.setImage_(image)
    openPanel.setAllowedFileTypes_(NSImage.imageFileTypes())
    openPanel.beginSheetModalForWindow_completionHandler_(self.imgView.window(), 
                                                          objc.selector(openPanelDidClose_, argumentTypes='l'))
Squill answered 11/3, 2011 at 11:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.