python drag drop init issues - python

I'm confused as to how I would implement a drag and drop ability for a window and then have the url appear in the textbox.
I've updated where I am stuck at
class controller(NSWindow):
#File to encode or decode
form_file = IBOutlet()
mainWindow = IBOutlet()
#drag and drop ability
def awakeFromNib(self):
self.registerForDraggedTypes_([NSFilenamesPboardType, None])
print 'registerd drag type'
def draggingEntered_(self, sender):
print 'dragging entered doctor who'
pboard = sender.draggingPasteboard()
types = pboard.types()
opType = NSDragOperationNone
if NSFilenamesPboardType in types:
opType = NSDragOperationCopy
return opType
def performDragOperation_(self,sender):
print 'preform drag operation'
pboard = sender.draggingPasteboard()
successful = False
if NSFilenamesPboardType in pboard.types():
print 'my actions finally working'
fileAStr = pboard.propertyListForType_(NSFilenamesPboardType)[0]
print type(fileAStr.encode('utf-8'))
successful = True
print self.form_file
return successful
I can drop the file but I am unable to refrence the form_file outlet from inside of the performDragOperation function. As you can see I am attempting to print it but it returns a NoneType error.
(reason '<type 'exceptions.TypeError'>: 'NoneType' object is not callable') was raised during a dragging session

I believe your problem here was that something earlier in the Responder Chain was handling -[draggingEntered:] and rejecting the drag, before your window could get to it.
For a typical AppKit app, before getting to the window, an action message goes to the First Responder from the NIB, and anything hooked onto the back of it, then the innermost view and its delegate, then all of its ancestor views and their delegates. So if, for example, you have a text edit view that handles drag messages, and you drag over that view, the window won't see it.
Anyway, there are lots of ways to debug this, but the simplest one is to just have each method iterate the nextResponder() chain from self, printing (or logging.logging or NSLogging) the result. Then you can see who you're blocking.
Since there were a bunch of other issues we talked about in the comments, I'm not sure if this was the one that actually solved your problem. But one thing in particular to bring up:
I don't think PyObjC was part of the problem here. When the Cocoa runtime sends an ObjC message like -[draggingEntered:] to a PyObjC object, the PyObjC runtime handles that by looking for a draggingEntered_ method and converting it magically. (Well, I say magic, but it's simple science. Also, because it's sonic, it doesn't do wood.) You need #IBAction in the same places an ObjC program would need (IBAction), which are documented pretty well in the Cocoa documentation.
Meanwhile, one general-purpose debugging tip for PyObjC code (or just about any other event-loop-based or otherwise non-linear code). When you get an error like this:
(reason '<type 'exceptions.TypeError'>: 'NoneType' object is not callable') was raised during a dragging session
It's hard to figure out what exactly went wrong. But you can handle the exception inside the function that raised, and get all the information you want. You can wrap a try/except around each line to figure out which line raised, you can print the whole traceback instead of just the summary, etc.

Related

Python Neuroglancer Getting Input

Below is a snippet of code from Google's publicly available Neuroglancer. It is from an example on their github. Could someone explain what exactly this code does and how it does it? I am having trouble understanding it, and don't know what exactly the variable s is. Thank you for the help.
def my_action(s):
print('Got my-action')
print(' Mouse position: %s' % (s.mouse_voxel_coordinates,))
print(' Layer selected values: %s' % (s.selected_values,))
viewer.actions.add('my-action', my_action)
with viewer.config_state.txn() as s:
s.input_event_bindings.viewer['keyt'] = 'my-action'
s.status_messages['hello'] = 'Welcome to this example'
This example adds a key binding to the viewer and adds a status message. When you press the t key, the my_action function will run. my_action takes the current state of the action and grabs the mouse coordinates and selected values in the layer.
The .txn() method performs a state-modification transaction on the ConfigState object. And by state-modification, I mean it changes the config. There are several default actions in the ConfigState object (defined in part here), and you are modifying that config by adding your own action.
The mouse_coordinates and selected_values objects are defined in Python here, and link to the typescript implementation here. The example also sets a status message on the config state, and that is implemented here.
It might be useful to first point to the source code for the various functions involved.
the example is available on GitHub
viewer.config_state
viewer.config_state is a "trackable" version of neuroglancer.viewer_config_state.ConfigState
viewer.config_state.txn()

FocusReason in PyQt5?

I noticed that when calling QtWidgets.setFocus, I get a warning in PyCharm saying that it expects a Qt.FocusReason rather than a Boolean. Indeed, the documentation for this method also states that it takes a Qt.FocusReason. But for the life of me, I can't find any information on this for PyQt5.
myPlainTextEdit.setFocus(True)
The method works perfectly fine by passing in a Boolean, but I'm wondering if this is perhaps some legacy from PyQt4, or just an anomaly? I noticed that on the PyQt Sourceforge Documentation, which seems to be for PyQt4, that it says to get FocusReason from QFocusEvent. In attempting to do this, I get another warning; Expected type 'FocusReason', got 'Type' instead. This raises a TypeError, as one might expect.
myPlainTextEdit.setFocus(QtGui.QFocusEvent.ActionAdded)
The PyQt5 documentation does not appear to contain a page for Qt.FocusReason. As this is extremely pedantic, I'm not overly concerned if there is no solution. I am interested to know what causes this. Is it possible to pass a Qt FocusReason to QtWidgets.setFocus in the first place?
There are 2 functions called setFocus() that every widget supports:
void QWidget::setFocus(Qt::FocusReason reason)
void QWidget::setFocus()
You are referring to the first. So let's analyze what you point out:
The method works perfectly fine by passing in a Boolean
It works but it does not imply that it is correct, first Qt::FocusReason is an enumeration, that is to say that each element that belongs is associated to a number:
Qt::MouseFocusReason 0 A mouse action occurred.
Qt::TabFocusReason 1 The Tab key was pressed.
Qt::BacktabFocusReason 2 A Backtab occurred. The input for this may include the Shift or Control keys; e.g. Shift+Tab.
Qt::ActiveWindowFocusReason 3 The window system made this window either active or inactive.
Qt::PopupFocusReason 4 The application opened/closed a pop-up that grabbed/released the keyboard focus.
Qt::ShortcutFocusReason 5 The user typed a labels buddy shortcut
Qt::MenuBarFocusReason 6 The menu bar took focus.
Qt::OtherFocusReason 7 Another reason, usually application-specific.
so when passing a Boolean it will convert it to an integer, False to 0 and True to 1, so setFocus(True) equals setFocus(QtCore.Qt.TabFocusReason).
In attempting to do this, I get another warning; Expected type 'FocusReason', got 'Type' instead. This raises a TypeError, as one might expect.
myPlainTextEdit.setFocus(QtGui.QFocusEvent.ActionAdded)
As you realize QtGui.QFocusEvent.ActionAdded does not belong to that list, so it throws the error. You have to use the values from the previous list by changing :: by . and prefixing it with QtCore since it belongs to that submodule, for example:
myPlainTextEdit.setFocus(QtCore.Qt.MouseFocusReason)
Plus:
If you just want to establish that the widget has the focus you should call the second function:
myPlainTextEdit.setFocus()
And for clean use clearFocus().

How to correctly pass (mutable) objects using ROS-SMACH FSM

I've been struggling with this question for a while now. My question is very specific so please don't post a link to the ROS-tutorial page with the "!Note:" paragraph showing how to pass mutable objects (unless you show me something I have missed). I would like to know if anyone has been able to correctly pass mutable objects back and forth in SMACH states, without encountering any errors.
I wrote a particularly simple and useless program to explain what I am attempting to do. I could post the code of this example (unfortunately however, not surprisingly to those that have used SMACH before, it is a long piece of code). So for now I will just try my best to explain it and include a [link] to an image of my example. I created two python scripts. Each script contains a single class and object of that class (with some basic methods). I create a publisher and subscriber in each script, one of the scripts sends messages (talks) while the other script listens to (hears) the messages. At the end the talker flags both FSMs to shutdown. If anyone would like the full code example let me know...
Code snippet below showing smach states and transitions:
# begin sm
with sm:
smach.StateMachine.add('LOAD', loadFSM(),
transitions={'LOADED':'SENDMSG'})
smach.StateMachine.add('SENDMSG', startMSG(),
transitions={'SENT':'SENDMSG',
'ENDING':'END'})
smach.StateMachine.add('END', stopFSM(),
transitions={'DONE':'complete',
'ERRED':'incomplete'})
Code snippet below showing a smach state (loadFSM):
class loadFSM(smach.State):
def __init__(self):
smach.State.__init__(self, outcomes=['LOADED'],
output_keys=['talker_obj'],
input_keys=['talker_obj'])
# Initialise our talker object
self.talker = Talk()
def execute(self, userdata):
rospy.loginfo("talker state: Loading fsm")
self.talker.init_publish()
self.talker.init_subscribe()
userdata.talker_obj = self.talker
return 'LOADED'
The errors I receive (using Ubuntu 14.04, ROS indigo and python 2.7, not too sure but I believe the same errors occur in kinetic as well) only occur during state transitions and of course the introspective server does not work (does not show state transitions). The errors are;
1. "Exception in thread sm_introViewer:status_publisher:"
2. "Could not execute transition callback: Traceback (most recent call
last): File
"/opt/ros/indigo/lib/python2.7/dist-packages/smach/container.py",
line 175, in call_transition_cbs cb(self.userdata,
self.get_active_states(), *args)"
I also need to add, that my simple finite state machine example actually works and completes successfully, even my project's 2 larger FSMs complete. However, when the FSM has many states like in my project, sometimes my simulations fail. I would like to know from anyone who has used SMACH extensively if they think these errors are the cause or if they know for a fact that I am not passing the object correctly between states.
Thanks in Advance,
Tiz
I had similar problems in the past. If I remember correctly, userdata can only handle basic types (int, string, list, dict, ...) but not arbitrary objects.
I solved it by passing the objects to the constructor of state classes, instead of using the userdata, i.e. something like:
class myState(smach.State):
def __init__(self, obj):
smach.State.__init__(self, outcomes=['foo'], ...)
self.obj = obj
...
and then initialize like follows:
obj = SomeClass()
with sm:
smach.StateMachine.add('MY_STATE', myState(obj),
transitions={'foo':'bar'})
It is not so nice as it circumvents the userdata concept but it works.

Pygtk object uninitialized

Hi during the creation of multiple objects in pygtk application, calling some of these object return that they are uninitialised when passing there contents to signals (noting the value are showen correctly in the application)
sections = config.sections()
for section in sections:
box= gtk.Table (3,len(config.options(section)),False)
box.set_col_spacings(2)
box.set_row_spacings(2)
box.show()
label = gtk.Label(section)
label.show()
notebook.append_page (box,label)
for i,option in enumerate(config.options(section)):
optionlabel = gtk.Label(option)
optionvalue = gtk.Entry ()
optionvalue.set_text(config.get(section,option))
--> optionvalue.connect("activate", enter_callback,optionvalue, label, optionlabel)
box.attach(optionlabel,0,1,i,i+1,xoptions=gtk.SHRINK|gtk.FILL,yoptions=gtk.SHRINK)
box.attach(optionvalue,1,2,i,i+1,yoptions=gtk.SHRINK)
box.show_all()
at first I thought that the variables are not in scope but they were ( I've tested several objects and found them working the last 3 lines
Linuxcnc ini.py:70: GtkWarning: IA__gtk_entry_get_text: assertion "GTK_IS_ENTRY (entry) failed
print (widget.get_text())
None
<gtk.Label object at 0x9f44a54 (uninitialized at 0x0)>
<gtk.Label object at 0x9f44c0c (uninitialized at 0x0)>
0
<gtk.Label object at 0x9f4c8ec (GtkLabel at 0xa1a3350)>
<gtk.Label object at 0x9f4dc0c (GtkLabel at 0xa1a3450)>
For this one I think you may need to look in the Gtk system library itself.
(The source code that is used to produce ".so", ".dll" or ".dylib" file, that has the routines that your Python program is accessing).
You can look a the contents of such binary files with commands like "strings", "nm", and "objdump".
But based the nature of the error, it looks like the fix will be done in the source code of the library itself, not the Python program.
Sorry I cannot give more detail than that.

Registering an Object on DBus using pythons Gio-Bindings

I'm working on a Python-Clone of an existing C-Project. The C-Project Connects to a custom DBus and offers a Object there for getting Callbacks.
I tried to replicate this using Python with code that basically boils down to:
def vtable_method_call_cb(connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
print('vtable_method_call_cb: %s' % method_name)
connection = Gio.DBusConnection.new_for_address_sync(
"unix:abstract=gstswitch",
Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
None,
None)
node_info = Gio.DBusNodeInfo.new_for_xml(introspection_xml)
vtable = Gio.DBusInterfaceVTable()
vtable.method_call(vtable_method_call_cb)
vtable.get_property(None)
vtable.set_property(None)
connection.register_object(
"/info/duzy/gst/switch/SwitchUI",
node_info.interfaces[0],
vtable,
None,
None)
The code fails when creating the vtable at the vtable.method_call call (but get_property fails, too, when I comment one call out) the following log/traceback:
** (process:18062): WARNING **: Field method_call: Interface type 2 should have is_pointer set
Traceback (most recent call last):
File "moo.py", line 69, in <module>
vtable.method_call(vtable_method_call_cb)
RuntimeError: unable to get the value
I was not able to find code using register_object() in python, so I'm unsure if this part of Gio should be usable or if it's just not complete.
This certainly not what you'll want to hear, but you have hit a 4 year old bug in the GDBus Python bindings that makes it impossible to register objects on the bus. A patch had been proposed quite some time ago, but every time it looked like it was actually going to land, some GNOME developer found something he/she did not like something about it, a new patch was proposed... and nothing happend for most of the next year. This cycle has already happend 3 times and I do not know if there is much hope that it will be broken anytime soon...
Basically the GNOME developers themselves more or less suggested that people use dbus-python until this issue is finally fixed, so I guess you should be heading here instead. :-/
BTW: I think you source code is wrong (aside from the fact that it won't work either way). To create the VTable you would actually be written something like this, I think:
vtable = Gio.DBusInterfaceVTable()
vtable.method_call = vtable_method_call_cb
vtable.get_property = None
vtable.set_property = None
But since the bindings are broken you are just trading an exception with an abort() here... :-(
If the patch actually makes it into python-gi in the current form the vtable would be dumped entirely (YEAH!) and connection.register_object call would become:
connection.register_object_with_closures(
"/info/duzy/gst/switch/SwitchUI",
node_info.interfaces[0],
vtable_method_call_cb, # vtable.method_call
None, # vtable.get_property
None) # vtable.set_property
Update
It appears this has now finally been fixed! You can now export object using g_dbus_connection_register_object_with_closures:
def vtable_method_call_cb(connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
print('vtable_method_call_cb: %s' % method_name)
connection = Gio.DBusConnection.new_for_address_sync(
"unix:abstract=gstswitch",
Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
None,
None)
node_info = Gio.DBusNodeInfo.new_for_xml(introspection_xml)
connection.register_object(
"/info/duzy/gst/switch/SwitchUI",
node_info.interfaces[0],
vtable_method_call_cb,
None,
None)

Categories