I’m converted some tree controls in my application to DataViewTreeCtrl for performance reasons. After getting everything working, I discovered that drag/drop doesn’t appear to function with custom data objects. I haven’t been able to track down any examples for drag/drop with this control but it appears the only unique requirement to get dragging functional is to call EnableDragSource, which I’m doing. In Linux, the dragging event fires but it seems incapable of finding valid drop targets. In Windows, everything does work. Not able to test on OS X.
I’m attaching a small example that instantiates a standard TreeCtrl and a DataViewTreeCtrl. There is a text ctrl that is a drop target. You should be able to drag the items in the trees to the text ctrl, if it’s working. Does anyone have any idea what could be causing it to fail in Linux?
I'm converted some tree controls in my application to DataViewTreeCtrl
for performance reasons. After getting everything working, I discovered
that drag/drop doesn't appear to function with custom data objects. I
haven't been able to track down any examples for drag/drop with this
control but it appears the only unique requirement to get dragging
functional is to call EnableDragSource, which I'm doing. In Linux, the
dragging event fires but it seems incapable of finding valid drop
targets. In Windows, everything does work. Not able to test on OS X.
I'm attaching a small example that instantiates a standard TreeCtrl and
a DataViewTreeCtrl. There is a text ctrl that is a drop target. You
should be able to drag the items in the trees to the text ctrl, if it's
working. Does anyone have any idea what could be causing it to fail in
Linux?
Please ask about this on wx-dev and/or create a Trac ticket for it.
I spent the better part of the day troubleshooting this and made a bit of headway. I was able to get an example working in plain wxWidgets. It turns out that the DataViewCtrl family doesn’t seem to support the standard mechanism (wxDropSource) for handling drag/drop. Instead the DataViewEvents are setup to accept drop objects. When I switched to that approach, I was golden in C++. When I revisited WxPython and updated my code to pass the drop data via the event, WxPython would crash after the data object was free’d twice. I’m hoping there is some trick I can use to prevent the extra deletion since the drop actually works.
I spent the better part of the day troubleshooting this and made a bit
of headway. I was able to get an example working in plain wxWidgets. It
turns out that the DataViewCtrl family doesn't seem to support the
standard mechanism (wxDropSource) for handling drag/drop. Instead the
DataViewEvents are setup to accept drop objects. When I switched to that
approach, I was golden in C++. When I revisited WxPython and updated my
code to pass the drop data via the event, WxPython would crash after the
data object was free'd twice. I'm hoping there is some trick I can use
to prevent the extra deletion since the drop actually works.
Robin, thanks for checking. You should just need to drag and drop a tree item from the bottom left tree (DVC Tree) to the main text pane. It will either crash upon dropping or if you exit the application immediately following the drop. I just tested on a different Linux box (Mageia 2 x64), which has a bit newer GTK than my work machine (RHEL6). Are you testing in Linux or OS X? It may be a GTK only problem or perhaps is masked in other platforms.
The code in question is here:
def _onDragDvText(self, event):
print “Starting to drag dataview text”
dataObject = wx.PyTextDataObject("Hi Mom")
#AttributeError: 'DataViewEvent' object has no attribute 'SetDragFlags'
#event.SetDragFlags(wx.Drag_DefaultMove)
event.SetDataObject(dataObject)
The variable dataObject gets deleted twice. I tried to create a new class derived from PyTextDataObject and RefCounter, and incremented the ref count prior to assigning the data object to the event, but that had no effect.
Program terminated with signal 6, Aborted. #0 0x00007f2e08a49245 in raise () from /lib64/libc.so.6
t(gdb) bt #0 0x00007f2e08a49245 in raise () from /lib64/libc.so.6 #1 0x00007f2e08a4a7cb in abort () from /lib64/libc.so.6 #2 0x00007f2e08a825be in __libc_message () from /lib64/libc.so.6 #3 0x00007f2e08a88476 in malloc_printerr () from /lib64/libc.so.6 #4 0x00007f2dfc51f497 in _M_dispose (__a=…, this=)
at /usr/lib/gcc/x86_64-mageia-linux-gnu/4.6.3/…/…/…/…/include/c++/4.6.3/bits/basic_string.h:244 #5 ~basic_string (this=0x140bba8, __in_chrg=)
at /usr/lib/gcc/x86_64-mageia-linux-gnu/4.6.3/…/…/…/…/include/c++/4.6.3/bits/basic_string.h:534 #6 wxString::~wxString (this=0x140bba8, __in_chrg=) at /usr/local/include/wx-2.9/wx/string.h:441 #7 0x00007f2dfc521f4c in ~wxTextDataObject (this=0x140bb90, __in_chrg=) at /usr/local/include/wx-2.9/wx/dataobj.h:376 #8 ~wxPyTextDataObject (this=0x140bb90, __in_chrg=) at src/gtk/_misc_wrap.cpp:4069 #9 wxPyTextDataObject::~wxPyTextDataObject (this=0x140bb90, __in_chrg=) at src/gtk/_misc_wrap.cpp:4069 #10 0x00007f2e078561b0 in wxDataViewCtrlInternal::~wxDataViewCtrlInternal() () from /usr/local/lib/libwx_gtk2u_adv-2.9.so.4 #11 0x00007f2e0785632d in wxDataViewCtrl::~wxDataViewCtrl() () from /usr/local/lib/libwx_gtk2u_adv-2.9.so.4 #12 0x00007f2e077c5cdd in wxDataViewTreeCtrl::~wxDataViewTreeCtrl() () from /usr/local/lib/libwx_gtk2u_adv-2.9.so.4 #13 0x00007f2e07307553 in wxWindowBase::Destroy() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #14 0x00007f2e07307585 in wxWindowBase::DestroyChildren() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #15 0x00007f2e07187e46 in wxWindow::~wxWindow() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #16 0x00007f2e0783a595 in wxPanel::~wxPanel() () from /usr/local/lib/libwx_gtk2u_adv-2.9.so.4 #17 0x00007f2e07307553 in wxWindowBase::Destroy() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #18 0x00007f2e07307585 in wxWindowBase::DestroyChildren() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #19 0x00007f2e07187e46 in wxWindow::~wxWindow() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #20 0x00007f2e0717be9e in wxTopLevelWindowGTK::~wxTopLevelWindowGTK() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #21 0x00007f2e0726f55c in wxFrameBase::~wxFrameBase() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #22 0x00007f2e071d9b59 in wxFrame::~wxFrame() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #23 0x00007f2e0688d6d2 in wxAppConsoleBase::DeletePendingObjects() () from /usr/local/lib/libwx_baseu-2.9.so.4 #24 0x00007f2e0688d73d in wxAppConsoleBase::ProcessIdle() () from /usr/local/lib/libwx_baseu-2.9.so.4 #25 0x00007f2e072142f3 in wxAppBase::ProcessIdle() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #26 0x00007f2e071553d5 in wxApp::DoIdle() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #27 0x00007f2e071554f3 in wxapp_idle_callback () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #28 0x00007f2e0399abc3 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0 #29 0x00007f2e0399af10 in ?? () from /lib64/libglib-2.0.so.0 #30 0x00007f2e0399b30a in g_main_loop_run () from /lib64/libglib-2.0.so.0 #31 0x00007f2e05e0ad57 in gtk_main () from /usr/lib64/libgtk-x11-2.0.so.0 #32 0x00007f2e0716c26a in wxGUIEventLoop::Run() () from /usr/local/lib/libwx_gtk2u_core-2.9.so.4 #33 0x00007f2e068912e1 in wxAppConsoleBase::MainLoop() () from /usr/local/lib/libwx_baseu-2.9.so.4 #34 0x00007f2e07b19c37 in MainLoop (this=0xee8020) at src/helpers.cpp:215 #35 wxPyApp::MainLoop (this=0xee8020) at src/helpers.cpp:200 #36 0x00007f2e07ba952f in _wrap_PyApp_MainLoop (args=) at src/gtk/_core_wrap.cpp:34291 #37 0x00007f2e0909dc06 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0 #38 0x00007f2e0909f40f in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0 #39 0x00007f2e0902ba4c in ?? () from /usr/lib64/libpython2.7.so.1.0 #40 0x00007f2e09006de3 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0 #41 0x00007f2e09015a5f in ?? () from /usr/lib64/libpython2.7.so.1.0 #42 0x00007f2e09006de3 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0 #43 0x00007f2e0909c762 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0 #44 0x00007f2e0909e383 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0 #45 0x00007f2e0909f40f in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0 #46 0x00007f2e0909f542 in PyEval_EvalCode () from /usr/lib64/libpython2.7.so.1.0 #47 0x00007f2e090b988c in ?? () from /usr/lib64/libpython2.7.so.1.0 #48 0x00007f2e090ba690 in PyRun_FileExFlags () from /usr/lib64/libpython2.7.so.1.0 #49 0x00007f2e090bb10f in PyRun_SimpleFileExFlags () from /usr/lib64/libpython2.7.so.1.0 #50 0x00007f2e090ccd35 in Py_Main () from /usr/lib64/libpython2.7.so.1.0 #51 0x00007f2e08a3632d in __libc_start_main () from /lib64/libc.so.6 #52 0x00000000004006a1 in _start ()
Robin, thanks for checking. You should just need to drag and drop a tree
item from the bottom left tree (DVC Tree) to the main text pane. It will
either crash upon dropping or if you exit the application immediately
following the drop. I just tested on a different Linux box (Mageia 2
x64), which has a bit newer GTK than my work machine (RHEL6). Are you
testing in Linux or OS X? It may be a GTK only problem or perhaps is
masked in other platforms.
All 3. I guess I'm just lucky and the uninitialized garbage in those memory locations are not causing troubles here.
The variable dataObject gets deleted twice. I tried to create a new
class derived from PyTextDataObject and RefCounter, and incremented the
ref count prior to assigning the data object to the event, but that had
no effect.
Try adding dataObject.this.disown() to the code above. That will tell the runtime that the ownership of the C++ object has been transferred and it will not try to delete it when the Python object is deleted. I'll add the code needed to do that automatically.
Adding a manual disown works. Thank you so much! One other minor thing I noticed is that SetDragFlags isn’t part of the bindings for DataViewEvent.
···
On Monday, May 27, 2013 2:13:21 PM UTC-6, Robin Dunn wrote:
Try adding dataObject.this.disown() to the code above. That will tell
the runtime that the ownership of the C++ object has been transferred
and it will not try to delete it when the Python object is deleted.
I’ll add the code needed to do that automatically.