2012-12-14 47 views
11

मैं liblarch पोर्टिंग कर रहा हूं, जो पीजीजीटीके (जीटीके 2) से पीईजीओबीजेक्ट इंट्रोस्पेक्शन (जीटीके 3) तक निर्देशित विश्वकोश ग्राफ को संभालने के लिए एक लाइब्रेरी है। मैं GtkTreeView के साथ समस्या में भाग गया।GTK3 में GtkTreeView को ड्रैग-एंड-ड्रॉप और क्रमबद्ध कैसे करें?

liblarch का उपयोग करने वाले ऐप को कॉलम द्वारा GtkTreeView को सॉर्ट करने की आवश्यकता है, लेकिन साथ ही, उपयोगकर्ता पंक्तियों को खींच और छोड़ सकता है, एक पंक्ति को दूसरी पंक्ति के नीचे ले जा सकता है। इसके लिए मुझे dnd_data_get() और dnd_data_receive() मैन्युअल रूप से संसाधित करना था जो पूरी तरह से ठीक है।

जीटीके ट्री व्यू के लिए न्यूनतम सेटअप है जो पीईजीटीके के तहत काम करता है। पंक्तियों को क्रमबद्ध किया जाता है और उपयोगकर्ता पंक्तियों को चारों ओर स्थानांतरित कर सकते हैं।

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import gtk 

window = gtk.Window() 
window.set_size_request(300, 200) 
window.connect('delete_event', lambda w,e: gtk.main_quit()) 

# Define Liblarch Tree 

store = gtk.TreeStore(str, str) 
store.insert(None, -1, ["A", "Task A"]) 
store.insert(None, -1, ["B", "Task B"]) 
store.insert(None, -1, ["C", "Task C"]) 
d_parent = store.insert(None, -1, ["D", "Task D"]) 
store.insert(d_parent, -1, ["E", "Task E"]) 

# Define TreeView in similar way as it happens in GTG/Liblarch_gtk 
tv = gtk.TreeView() 

col = gtk.TreeViewColumn() 
col.set_title("Title") 
render_text = gtk.CellRendererText() 
col.pack_start(render_text, expand=True) 
col.add_attribute(render_text, 'markup', 1) 
col.set_resizable(True) 
col.set_expand(True) 
col.set_sort_column_id(0) 
tv.append_column(col) 
tv.set_property("expander-column", col) 

treemodel = store 

def _sort_func(model, iter1, iter2): 
    """ Sort two iterators by function which gets node objects. 
    This is a simple wrapper which prepares node objects and then 
    call comparing function. In other case return default value -1 
    """ 
    node_a = model.get_value(iter1, 0) 
    node_b = model.get_value(iter2, 0) 
    if node_a and node_b: 
     sort = cmp(node_a, node_b) 
    else: 
     sort = -1 
    return sort 

treemodel.set_sort_func(1, _sort_func) 
tv.set_model(treemodel) 

def on_child_toggled(treemodel2, path, iter, param=None): 
    """ Expand row """ 
    if not tv.row_expanded(path): 
     tv.expand_row(path, True) 

treemodel.connect('row-has-child-toggled', on_child_toggled) 

tv.set_search_column(1) 
tv.set_property("enable-tree-lines", False) 
tv.set_rules_hint(False) 


#### Drag and drop stuff 

dnd_internal_target = '' 
dnd_external_targets = {} 

def on_drag_fail(widget, dc, result): 
    print "Failed dragging", widget, dc, result 

def __init_dnd(): 
    """ Initialize Drag'n'Drop support 

    Firstly build list of DND targets: 
     * name 
     * scope - just the same widget/same application 
     * id 

    Enable DND by calling enable_model_drag_dest(), 
    enable_model-drag_source() 

    It didnt use support from gtk.Widget(drag_source_set(), 
    drag_dest_set()). To know difference, look in PyGTK FAQ: 
    http://faq.pygtk.org/index.py?file=faq13.033.htp&req=show 
    """ 
    #defer_select = False 

    if dnd_internal_target == '': 
     error = 'Cannot initialize DND without a valid name\n' 
     error += 'Use set_dnd_name() first' 
     raise Exception(error) 

    dnd_targets = [(dnd_internal_target, gtk.TARGET_SAME_WIDGET, 0)] 
    for target in dnd_external_targets: 
     name = dnd_external_targets[target][0] 
     dnd_targets.append((name, gtk.TARGET_SAME_APP, target)) 

    tv.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, 
     dnd_targets, gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE) 

    tv.enable_model_drag_dest(\ 
     dnd_targets, gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE) 


def on_drag_data_get(treeview, context, selection, info, timestamp): 
    """ Extract data from the source of the DnD operation. 

    Serialize iterators of selected tasks in format 
    <iter>,<iter>,...,<iter> and set it as parameter of DND """ 
    print "on_drag_data_get(", treeview, context, selection, info, timestamp 

    treeselection = treeview.get_selection() 
    model, paths = treeselection.get_selected_rows() 
    iters = [model.get_iter(path) for path in paths] 
    iter_str = ','.join([model.get_string_from_iter(iter) for iter in iters]) 
    selection.set(dnd_internal_target, 0, iter_str) 
    print "Sending", iter_str 

def on_drag_data_received(treeview, context, x, y, selection, info,\ 
          timestamp): 
    """ Handle a drop situation. 

    First of all, we need to get id of node which should accept 
    all draged nodes as their new children. If there is no node, 
    drop to root node. 

    Deserialize iterators of dragged nodes (see self.on_drag_data_get()) 
    Info parameter determines which target was used: 
     * info == 0 => internal DND within this TreeView 
     * info > 0 => external DND 

    In case of internal DND we just use Tree.move_node(). 
    In case of external DND we call function associated with that DND 
    set by self.set_dnd_external() 
    """ 
    print "on_drag_data_received", treeview, context, x, y, selection, info, timestamp 

    model = treeview.get_model() 
    destination_iter = None 
    destination_tid = None 
    drop_info = treeview.get_dest_row_at_pos(x, y) 
    if drop_info: 
     path, position = drop_info 
     destination_iter = model.get_iter(path) 
     if destination_iter: 
      destination_tid = model.get_value(destination_iter, 0) 

    # Get dragged iter as a TaskTreeModel iter 
    # If there is no selected task (empty selection.data), 
    # explictly skip handling it (set to empty list) 
    if selection.data == '': 
     iters = [] 
    else: 
     iters = selection.data.split(',') 

    dragged_iters = [] 
    for iter in iters: 
     print "Info", info 
     if info == 0: 
      try: 
       dragged_iters.append(model.get_iter_from_string(iter)) 
      except ValueError: 
       #I hate to silently fail but we have no choice. 
       #It means that the iter is not good. 
       #Thanks shitty gtk API for not allowing us to test the string 
       print "Shitty iter", iter 
       dragged_iter = None 

     elif info in dnd_external_targets and destination_tid: 
      f = dnd_external_targets[info][1] 

      src_model = context.get_source_widget().get_model() 
      dragged_iters.append(src_model.get_iter_from_string(iter)) 


    for dragged_iter in dragged_iters: 
     if info == 0: 
      if dragged_iter and model.iter_is_valid(dragged_iter): 
       dragged_tid = model.get_value(dragged_iter, 0) 
       try: 
        row = [] 
        for i in range(model.get_n_columns()): 
         row.append(model.get_value(dragged_iter, i)) 
        #tree.move_node(dragged_tid, new_parent_id=destination_tid) 
        print "move_after(%s, %s) ~ (%s, %s)" % (dragged_iter, destination_iter, dragged_tid, destination_tid) 
        #model.move_after(dragged_iter, destination_iter) 
        model.insert(destination_iter, -1, row) 
        model.remove(dragged_iter) 
       except Exception, e: 
        print 'Problem with dragging: %s' % e 
     elif info in dnd_external_targets and destination_tid:  
      source = src_model.get_value(dragged_iter,0) 
      # Handle external Drag'n'Drop 
      f(source, destination_tid) 


dnd_internal_target = 'gtg/task-iter-str' 
__init_dnd() 
tv.connect('drag_data_get', on_drag_data_get) 
tv.connect('drag_data_received', on_drag_data_received) 
tv.connect('drag_failed', on_drag_fail) 

window.add(tv) 
window.show_all() 

tv.expand_all() 
gtk.main() 

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 

मैंने इस स्क्रिप्ट को PyGObject (GTK3) में पोर्ट किया। मेरे कोड:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

from gi.repository import Gtk, Gdk 

window = Gtk.Window() 
window.set_size_request(300, 200) 
window.connect('delete_event', lambda w,e: Gtk.main_quit()) 

# Define Liblarch Tree 

store = Gtk.TreeStore(str, str) 
store.insert(None, -1, ["A", "Task A"]) 
store.insert(None, -1, ["B", "Task B"]) 
store.insert(None, -1, ["C", "Task C"]) 
d_parent = store.insert(None, -1, ["D", "Task D"]) 
store.insert(d_parent, -1, ["E", "Task E"]) 

# Define TreeView in similar way as it happens in GTG/Liblarch_gtk 
tv = Gtk.TreeView() 

col = Gtk.TreeViewColumn() 
col.set_title("Title") 
render_text = Gtk.CellRendererText() 
col.pack_start(render_text, expand=True) 
col.add_attribute(render_text, 'markup', 1) 
col.set_resizable(True) 
col.set_expand(True) 
col.set_sort_column_id(0) 
tv.append_column(col) 
tv.set_property("expander-column", col) 

treemodel = store 

def _sort_func(model, iter1, iter2): 
    """ Sort two iterators by function which gets node objects. 
    This is a simple wrapper which prepares node objects and then 
    call comparing function. In other case return default value -1 
    """ 
    node_a = model.get_value(iter1, 0) 
    node_b = model.get_value(iter2, 0) 
    if node_a and node_b: 
     sort = cmp(node_a, node_b) 
    else: 
     sort = -1 
    return sort 

treemodel.set_sort_func(1, _sort_func) 
tv.set_model(treemodel) 

def on_child_toggled(treemodel2, path, iter, param=None): 
    """ Expand row """ 
    if not tv.row_expanded(path): 
     tv.expand_row(path, True) 

treemodel.connect('row-has-child-toggled', on_child_toggled) 

tv.set_search_column(1) 
tv.set_property("enable-tree-lines", False) 
tv.set_rules_hint(False) 


#### Drag and drop stuff 

dnd_internal_target = '' 
dnd_external_targets = {} 

def on_drag_fail(widget, dc, result): 
    print "Failed dragging", widget, dc, result 

def __init_dnd(): 
    """ Initialize Drag'n'Drop support 

    Firstly build list of DND targets: 
     * name 
     * scope - just the same widget/same application 
     * id 

    Enable DND by calling enable_model_drag_dest(), 
    enable_model-drag_source() 

    It didnt use support from Gtk.Widget(drag_source_set(), 
    drag_dest_set()). To know difference, look in PyGTK FAQ: 
    http://faq.pygtk.org/index.py?file=faq13.033.htp&req=show 
    """ 
    #defer_select = False 

    if dnd_internal_target == '': 
     error = 'Cannot initialize DND without a valid name\n' 
     error += 'Use set_dnd_name() first' 
     raise Exception(error) 

    dnd_targets = [(dnd_internal_target, Gtk.TargetFlags.SAME_WIDGET, 0)] 
    for target in dnd_external_targets: 
     name = dnd_external_targets[target][0] 
     dnd_targets.append((name, Gtk.TARGET_SAME_APP, target)) 

    tv.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, 
     dnd_targets, Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE) 

    tv.enable_model_drag_dest(\ 
     dnd_targets, Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE) 


def on_drag_data_get(treeview, context, selection, info, timestamp): 
    """ Extract data from the source of the DnD operation. 

    Serialize iterators of selected tasks in format 
    <iter>,<iter>,...,<iter> and set it as parameter of DND """ 
    print "on_drag_data_get(", treeview, context, selection, info, timestamp 

    treeselection = treeview.get_selection() 
    model, paths = treeselection.get_selected_rows() 
    iters = [model.get_iter(path) for path in paths] 
    iter_str = ','.join([model.get_string_from_iter(iter) for iter in iters]) 
    selection.set(dnd_internal_target, 0, iter_str) 
    print "Sending", iter_str 

def on_drag_data_received(treeview, context, x, y, selection, info,\ 
          timestamp): 
    """ Handle a drop situation. 

    First of all, we need to get id of node which should accept 
    all draged nodes as their new children. If there is no node, 
    drop to root node. 

    Deserialize iterators of dragged nodes (see self.on_drag_data_get()) 
    Info parameter determines which target was used: 
     * info == 0 => internal DND within this TreeView 
     * info > 0 => external DND 

    In case of internal DND we just use Tree.move_node(). 
    In case of external DND we call function associated with that DND 
    set by self.set_dnd_external() 
    """ 
    print "on_drag_data_received", treeview, context, x, y, selection, info, timestamp 

    model = treeview.get_model() 
    destination_iter = None 
    destination_tid = None 
    drop_info = treeview.get_dest_row_at_pos(x, y) 
    if drop_info: 
     path, position = drop_info 
     destination_iter = model.get_iter(path) 
     if destination_iter: 
      destination_tid = model.get_value(destination_iter, 0) 

    # Get dragged iter as a TaskTreeModel iter 
    # If there is no selected task (empty selection.data), 
    # explictly skip handling it (set to empty list) 
    if selection.data == '': 
     iters = [] 
    else: 
     iters = selection.data.split(',') 

    dragged_iters = [] 
    for iter in iters: 
     print "Info", info 
     if info == 0: 
      try: 
       dragged_iters.append(model.get_iter_from_string(iter)) 
      except ValueError: 
       #I hate to silently fail but we have no choice. 
       #It means that the iter is not good. 
       #Thanks shitty Gtk API for not allowing us to test the string 
       print "Shitty iter", iter 
       dragged_iter = None 

     elif info in dnd_external_targets and destination_tid: 
      f = dnd_external_targets[info][1] 

      src_model = context.get_source_widget().get_model() 
      dragged_iters.append(src_model.get_iter_from_string(iter)) 


    for dragged_iter in dragged_iters: 
     if info == 0: 
      if dragged_iter and model.iter_is_valid(dragged_iter): 
       dragged_tid = model.get_value(dragged_iter, 0) 
       try: 
        row = [] 
        for i in range(model.get_n_columns()): 
         row.append(model.get_value(dragged_iter, i)) 
        #tree.move_node(dragged_tid, new_parent_id=destination_tid) 
        print "move_after(%s, %s) ~ (%s, %s)" % (dragged_iter, destination_iter, dragged_tid, destination_tid) 
        #model.move_after(dragged_iter, destination_iter) 
        model.insert(destination_iter, -1, row) 
        model.remove(dragged_iter) 
       except Exception, e: 
        print 'Problem with dragging: %s' % e 
     elif info in dnd_external_targets and destination_tid:  
      source = src_model.get_value(dragged_iter,0) 
      # Handle external Drag'n'Drop 
      f(source, destination_tid) 


dnd_internal_target = 'gtg/task-iter-str' 
__init_dnd() 
tv.connect('drag_data_get', on_drag_data_get) 
tv.connect('drag_data_received', on_drag_data_received) 
tv.connect('drag_failed', on_drag_fail) 

window.add(tv) 
window.show_all() 

tv.expand_all() 
Gtk.main() 

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 

मैं सही ढंग से dnd_data_receive() को संभालने के लिए जहां या तो इसे पैदा नहीं कर रहा है या कोई डेटा प्राप्त कर रहे हैं पा रहा हूँ।

Failed dragging <TreeView object at 0xeb4370 (GtkTreeView at 0xf742a0)> <gtk.gdk.X11DragContext object at 0xf351e0 (GdkX11DragContext at 0xf96ca0)> <enum GTK_DRAG_RESULT_NO_TARGET of type GtkDragResult> 

मेरा प्रश्न: कैसे PyGObject (GTK3) के लिए बंदरगाह पहले स्क्रिप्ट के लिए इतना GtkTreeView छाँटा जा सकता है और एक ही समय पंक्तियों में हो सकता है खींचें-और-यह हमेशा निम्नलिखित कॉलबैक + अपने मानकों के साथ विफल रहता है गिरा दिया? ड्रैग-एंड-ड्रॉप कॉलबैक को सही तरीके से ड्रैग-एंड-ड्रॉप को संसाधित करने के लिए कैसे बदलें?

+0

liblarch के लिए गिटहब लिंक टूटा हुआ है। – rvighne

उत्तर

5

सबसे पहले, आपको जो त्रुटि मिलती है वह PyGObject के संस्करण से संबंधित प्रतीत होती है। मैं नवीनतम उबंटू 13.04 बीटा के साथ अपने लैपटॉप को पुनर्स्थापित करने से पहले समान त्रुटि जानकारी पुन: उत्पन्न करता हूं।

  • SelectionData.set के पहले पैरामीटर() केवल हो सकता है लगता है Gtk.gdk.Atom: लेकिन उन्नयन के बाद, त्रुटि कॉलबैक की तरह

    on_drag_data_get(<TreeView object at 0x1765870 (GtkTreeView at 0x19120a0)> <gtk.gdk.X11DragContext object at 0x1765aa0 (GdkX11DragContext at 0x1988820)> <GtkSelectionData at 0x7fffb106b760> 0 21962912 
    Traceback (most recent call last): 
        File "dnd_gtk3_org.py", line 116, in on_drag_data_get 
        selection.set(dnd_internal_target, 0, iter_str) 
        File "/usr/lib/python2.7/dist-packages/gi/types.py", line 113, in function 
        return info.invoke(*args, **kwargs) 
    TypeError: argument type: Expected Gdk.Atom, but got str 
    on_drag_data_received <TreeView object at 0x1765870 (GtkTreeView at 0x19120a0)> <gtk.gdk.X11DragContext object at 0x1765be0 (GdkX11DragContext at 0x1988940)> 45 77 <GtkSelectionData at 0x7fffb106b6e0> 0 21962912 
    Traceback (most recent call last): 
        File "dnd_gtk3_org.py", line 151, in on_drag_data_received 
        if selection.data == '': 
    AttributeError: 'SelectionData' object has no attribute 'data' 
    

    वहाँ केवल दो छोटे समस्याएं हैं कुछ करने के लिए बदल जाता है लेकिन एक स्ट्रिंग नहीं है जो निर्दिष्ट करता है कि pygtk में।

  • चयन डेटा में कोई 'डेटा' विशेषता नहीं है लेकिन इसके बजाय get_data() विधि है।

एक काम कर कोड अपने प्रश्न में से एक के साथ ऊपर नीचे

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

from gi.repository import Gtk, Gdk 

window = Gtk.Window() 
window.set_size_request(300, 200) 
window.connect('delete_event', Gtk.main_quit) 

# Define Liblarch Tree 

store = Gtk.TreeStore(str, str) 
store.insert(None, -1, ["A", "Task A"]) 
store.insert(None, -1, ["B", "Task B"]) 
store.insert(None, -1, ["C", "Task C"]) 
d_parent = store.insert(None, -1, ["D", "Task D"]) 
store.insert(d_parent, -1, ["E", "Task E"]) 

# Define TreeView in similar way as it happens in GTG/Liblarch_gtk 
tv = Gtk.TreeView() 

col = Gtk.TreeViewColumn() 
col.set_title("Title") 
render_text = Gtk.CellRendererText() 
col.pack_start(render_text, expand=True) 
col.add_attribute(render_text, 'markup', 1) 
col.set_resizable(True) 
col.set_expand(True) 
col.set_sort_column_id(0) 
tv.append_column(col) 
tv.set_property("expander-column", col) 

treemodel = store 

def _sort_func(model, iter1, iter2): 
    """ Sort two iterators by function which gets node objects. 
    This is a simple wrapper which prepares node objects and then 
    call comparing function. In other case return default value -1 
    """ 
    node_a = model.get_value(iter1, 0) 
    node_b = model.get_value(iter2, 0) 
    if node_a and node_b: 
     sort = cmp(node_a, node_b) 
    else: 
     sort = -1 
    return sort 

treemodel.set_sort_func(1, _sort_func) 
tv.set_model(treemodel) 

def on_child_toggled(treemodel2, path, iter, param=None): 
    """ Expand row """ 
    if not tv.row_expanded(path): 
     tv.expand_row(path, True) 

treemodel.connect('row-has-child-toggled', on_child_toggled) 

tv.set_search_column(1) 
tv.set_property("enable-tree-lines", False) 
tv.set_rules_hint(False) 


#### Drag and drop stuff 

dnd_internal_target = '' 
dnd_external_targets = {} 

def on_drag_fail(widget, dc, result): 
    print "Failed dragging", widget, dc, result 

def __init_dnd(): 
    """ Initialize Drag'n'Drop support 

    Firstly build list of DND targets: 
     * name 
     * scope - just the same widget/same application 
     * id 

    Enable DND by calling enable_model_drag_dest(), 
    enable_model-drag_source() 

    It didnt use support from Gtk.Widget(drag_source_set(), 
    drag_dest_set()). To know difference, look in PyGTK FAQ: 
    http://faq.pygtk.org/index.py?file=faq13.033.htp&req=show 
    """ 
    #defer_select = False 

    if dnd_internal_target == '': 
     error = 'Cannot initialize DND without a valid name\n' 
     error += 'Use set_dnd_name() first' 
     raise Exception(error) 

    dnd_targets = [(dnd_internal_target, Gtk.TargetFlags.SAME_WIDGET, 0)] 
    for target in dnd_external_targets: 
     name = dnd_external_targets[target][0] 
     dnd_targets.append((name, Gtk.TARGET_SAME_APP, target)) 

    tv.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, 
     dnd_targets, Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE) 

    tv.enable_model_drag_dest(\ 
     dnd_targets, Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE) 


def on_drag_data_get(treeview, context, selection, info, timestamp): 
    """ Extract data from the source of the DnD operation. 

    Serialize iterators of selected tasks in format 
    <iter>,<iter>,...,<iter> and set it as parameter of DND """ 
    print "on_drag_data_get(", treeview, context, selection, info, timestamp 

    treeselection = treeview.get_selection() 
    model, paths = treeselection.get_selected_rows() 
    iters = [model.get_iter(path) for path in paths] 
    iter_str = ','.join([model.get_string_from_iter(iter) for iter in iters]) 
    selection.set(selection.get_target(), 0, iter_str) 
    print "Sending", iter_str 

def on_drag_data_received(treeview, context, x, y, selection, info,\ 
          timestamp): 
    """ Handle a drop situation. 

    First of all, we need to get id of node which should accept 
    all draged nodes as their new children. If there is no node, 
    drop to root node. 

    Deserialize iterators of dragged nodes (see self.on_drag_data_get()) 
    Info parameter determines which target was used: 
     * info == 0 => internal DND within this TreeView 
     * info > 0 => external DND 

    In case of internal DND we just use Tree.move_node(). 
    In case of external DND we call function associated with that DND 
    set by self.set_dnd_external() 
    """ 
    print "on_drag_data_received", treeview, context, x, y, selection, info, timestamp 

    model = treeview.get_model() 
    destination_iter = None 
    destination_tid = None 
    drop_info = treeview.get_dest_row_at_pos(x, y) 
    if drop_info: 
     path, position = drop_info 
     destination_iter = model.get_iter(path) 
     if destination_iter: 
      destination_tid = model.get_value(destination_iter, 0) 

    # Get dragged iter as a TaskTreeModel iter 
    # If there is no selected task (empty selection.data), 
    # explictly skip handling it (set to empty list) 
    data = selection.get_data() 
    if data == '': 
     iters = [] 
    else: 
     iters = data.split(',') 

    dragged_iters = [] 
    for iter in iters: 
     print "Info", info 
     if info == 0: 
      try: 
       dragged_iters.append(model.get_iter_from_string(iter)) 
      except ValueError: 
       #I hate to silently fail but we have no choice. 
       #It means that the iter is not good. 
       #Thanks shitty Gtk API for not allowing us to test the string 
       print "Shitty iter", iter 
       dragged_iter = None 

     elif info in dnd_external_targets and destination_tid: 
      f = dnd_external_targets[info][1] 

      src_model = context.get_source_widget().get_model() 
      dragged_iters.append(src_model.get_iter_from_string(iter)) 


    for dragged_iter in dragged_iters: 
     if info == 0: 
      if dragged_iter and model.iter_is_valid(dragged_iter): 
       dragged_tid = model.get_value(dragged_iter, 0) 
       try: 
        row = [] 
        for i in range(model.get_n_columns()): 
         row.append(model.get_value(dragged_iter, i)) 
        #tree.move_node(dragged_tid, new_parent_id=destination_tid) 
        print "move_after(%s, %s) ~ (%s, %s)" % (dragged_iter, destination_iter, dragged_tid, destination_tid) 
        #model.move_after(dragged_iter, destination_iter) 
        model.insert(destination_iter, -1, row) 
        model.remove(dragged_iter) 
       except Exception, e: 
        print 'Problem with dragging: %s' % e 
     elif info in dnd_external_targets and destination_tid:  
      source = src_model.get_value(dragged_iter,0) 
      # Handle external Drag'n'Drop 
      f(source, destination_tid) 


dnd_internal_target = 'gtg/task-iter-str' 
__init_dnd() 
tv.connect('drag_data_get', on_drag_data_get) 
tv.connect('drag_data_received', on_drag_data_received) 
tv.connect('drag_failed', on_drag_fail) 

window.add(tv) 
window.show_all() 

tv.expand_all() 
Gtk.main() 

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 

सूचीबद्ध टुकड़ा के बीच अंतर का टुकड़ा

116c116 
<  selection.set(selection.get_target(), 0, iter_str) 
--- 
>  selection.set(dnd_internal_target, 0, iter_str) 
151,152c151 
<  data = selection.get_data() 
<  if data == '': 
--- 
>  if selection.data == '': 
155c154 
<   iters = data.split(',') 
--- 
>   iters = selection.data.split(',') 

इसके अलावा है, वहाँ जीटीके + 3 संस्करण के लिए एक और उदाहरण है TreeView के ड्रैग और ड्रॉप को किसी अन्य थ्रेड में: unresponsive drag and drop in pygobject

1

जीटीजी सॉफ्टवेयर का एक बड़ा टुकड़ा है! लेकिन यह कम से कम मेरे कंप्यूटर पर बहुत धीमी है। इसलिए मैं एक सी ++ लाइब्रेरी लिख रहा हूं जो एक जीटीके :: ट्री व्यू का उपयोग करके निर्देशित विश्वकोश ग्राफ प्रदर्शित करता है, और मैंने लिबलार्च स्रोत कोड को बहुत कुछ देखा।

जहां तक ​​मुझे पता है, जीटीके की पाइथन और सी ++ बाइंडिंग जीटीके से ही एक ही सीमा साझा करती है (मैंने एक बार जीटीके स्रोत कोड को देखा कि यह ठीक तरह से क्यों काम करता है): यदि आप ड्रैग-एंड चालू करते हैं -ड्रॉप और सॉर्टिंग, ड्रैग-एंड-ड्रॉप काम नहीं करेगा। ,

  1. जो DND को सीमित करता है जब छँटाई सक्षम किया गया है जीटीके के लिए एक पैच बनाने के बजाय पूरी तरह से अवरुद्ध यह

  2. लागू खुद के द्वारा छँटाई की: मैं तीन बातें आप इसके बारे में क्या कर सकते हैं प्रदान करते हैं। यह आसान है: अपने डेटा को एक क्रमबद्ध वृक्षदृश्य में लोड करके शुरू करें। अब, हर बार उपयोगकर्ता ड्रैग और ड्रॉप करता है, ड्रैग किए गए पंक्ति को अपने सॉर्टिंग फ़ंक्शन का उपयोग करके नई स्थिति में ले जाएं। लेकिन जीटीके सॉर्टिंग बंद छोड़ दें।

  3. यह 2 के अतिरिक्त किया जा सकता है, यह एक जीयूआई डिज़ाइन मुद्दा है: GtkTreeView में आप सिब्लिंग आइटमों के बीच एक आइटम डाल सकते हैं, जो सॉर्ट किए गए पेड़ में ज्यादा समझ नहीं लेता है। यूआई के मामले में केवल उन पंक्तियों को छोड़ने की अनुमति देना बेहतर है, न कि उन्हें। उदाहरण: नॉटिलस सूची-दृश्य इस तरह काम करता है। समाधान या तो TreeView drag_data_received() डिफ़ॉल्ट हैंडलर को ओवरराइड करता है, या रखरखाव के मामले में उससे बेहतर है: मॉडल को बताते हुए मॉडल को एक संकेत दें कि ड्रॉप स्थिति चालू है या इससे पहले। स्थिति से पहले है, तो अपने पेड़ के drop_possible() आभासी ओवरराइड झूठी वापसी, इस प्रकार आप एक क्लीनर जीयूआई मिल

2, और फिर आप treeview के "तुम यहाँ छोड़ सकते हैं" didplay नहीं दिख रहा है "। और 3 मैं सी ++ में करता हूं, आपको आसानी से पाइथन में ऐसा करने में सक्षम होना चाहिए :)

इसके अलावा, विकल्प 1 के बारे में एक नोट: GtktreeView (या GtkTreeStore था? मैं भूल गया) अगर सॉर्टिंग है तो बस किसी भी बूंद को अवरुद्ध करता है सक्षम। अगर कोई बस ठीक करता है (आप ... या मैं ...), या कम से कम व्युत्पन्न व्यू क्लास लिखते हैं, हमारे पास डीएनडी समर्थन के साथ क्रमबद्ध पेड़ के लिए एक डिफ़ॉल्ट साफ जीयूआई होगा।