GenericTreeModel

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
grindhold
User
Beiträge: 3
Registriert: Dienstag 23. November 2010, 18:49

Tach, alle miteinander :)

Bin hier neu im Board, komme aber gleich mit einer kniffligen Fragestellung zu euch. Ich hoffe mal, dass ich mein problem praezise genug beschreiben kann, um euren anspruechen zu genuegen.
Ich versuche momentan ein gtk.GenericTreeModel zu implementieren, komme aber noch nicht soganz dahinter wie das funktioniert. Um einen kleinen Einblick zu gewaehren hab ich ein Testscript angefertigt um das Problem auf das wesentliche zu reduzieren. Im endeffekt moechte ich erreichen, dass mein TreeModel direkt mit Objekten bestueckt werden kann (im beispiel Object1 und Object2), die ein parent- und ein children-attribut besitzen um die baumstruktur auszudruecken.
Ich vermute, dass mein fehler schon allein damit beginnt, dass ich versuche einen gtk.TreeIter mit meinen Objekten zu implementieren. Von den Dokumentationen ausgehend habe ich bisher angenommen, ein gtk.TreeIter sei eine referenz auf eine bestimmte zeile im treestore.
Wie handle ich TreeIter und vor allem, wie kann ich welche erzeugen(abstrakte klasse)? Wie verknuepfe ich TreeIter und datensatz miteinander? Wieso besteht der iter, den ich aus dem model ziehe die validTreeIter pruefung nicht?

Wenn hier irgendjemand Licht ins dunkel bringen koennte, waere ich demjenigen sehr dankbar.

Code: Alles auswählen


import pygtk
pygtk.require('2.0')
import gtk

class Object1(gtk.TreeIter):
  def __init__(self):
    self.id = None
    self.name = None
    self.parent = None
    self.children = []

class Object2(gtk.TreeIter):
  def __init__(self):
    self.id = None
    self.name = None
    self.parent = None
    self.children = []

class ObjectTreeModel(gtk.GenericTreeModel):
  COLUMN_NAMES = ('ID','Name')
  COLUMN_TYPES = (int, str)
  
  
  def __init__(self):
    gtk.GenericTreeModel.__init__(self)
    
    root = Object1()
    root.id = 0
    root.name = 'root'
    
    self.items = [root]
    
  def on_get_flags(self):
    return 0
  
  def on_get_n_columns(self):
    return (len(self.COLUMN_NAMES)+1)

  def on_get_column_type(self, index):
    return self.COLUMN_TYPES[index]
  
  def on_get_iter(self,path):
    cur_element = self.items
    for number in path:
      try:
        if cur_element == self.items:
          cur_element = cur_element[number]
        else:
          cur_element = cur_element.children[number]
      except IndexError, e:
        return None
    return cur_element
    
  def on_get_path(self, rowref):
    tree = self.items
    path = {}
    treelevel = 0
    def searchSubTree(subtree,rowref, path, treelevel):
      for x in xrange(0,len(subtree)):
        path[treelevel] = x
        if subtree[x] == rowref:
          return path
        elif len(subtree[x].children)!=0:
          treelevel+=1
          searchSubTree(subtree[x].children,rowref,path,treelevel)
          treelevel-=1
        else:
          pass
    path = searchSubTree(tree,rowref,path,treelevel)
    return tuple(path.values())
    
  def on_get_value(self,rowref,column):
    assert column in (0,1)
    if column == 0:
      return rowref.id
    else:
      return rowref.name
  
  def on_iter_next(self,rowref):
    if rowref.parent!= None:
      parent = rowref.parent
      try:
        nextchild = parent.children[parent.children.index(rowref)+1]
      except IndexError,e:
        return None
      else:
        return nextchild
  
  def on_iter_children(self,rowref):
    if parent is None:
      return None
    else:
      try:
        child = rowref.children[0]
        return child
      except IndexError,e:
        return None
      
  def on_iter_has_child(self, rowref):
    return len(rowref.children) > 0
  
  def on_iter_n_children(self, rowref):
    return len(rowref.children)
    
  def on_iter_nth_child(self, parent, n):
    try:
      child = parent.children[n]
      return child
    except Exception,e:
      return None
  
  def on_iter_parent(self, child):
    return child.parent
  
class TestApp(gtk.Window):
  def __init__(self):
    gtk.Window.__init__(self)
    
    self.treeview = gtk.TreeView()
    self.model    = ObjectTreeModel()
    self.treeview.set_model(self.model)
    self.col_id = gtk.TreeViewColumn('Id')
    self.col_name = gtk.TreeViewColumn('Name')
    self.renderer_id = gtk.CellRendererText()
    self.renderer_name = gtk.CellRendererText()
    
    self.treeview.append_column(self.col_id)
    self.treeview.append_column(self.col_name)
    
    self.col_id.pack_start(self.renderer_id,False)
    self.col_name.pack_start(self.renderer_name,False)
    
    self.col_id.add_attribute(self.renderer_id,'text',0)
    self.col_name.add_attribute(self.renderer_name,'text',1)
    
    self.add(self.treeview)
    self.show_all()

win = TestApp()
gtk.main()
P.S.: falls jemand fragt warum ich das mache: ich moechte anhand meiner objekte daten aus einer DB nachladen um den speicherverbrauch gering zu halten. also sprich nur das geladen haben was wirklich angezeigt wird, haeufig benutze pfade cachen, weniger haeufig benutze, jedoch geladene pfade aus dem speicher entfernen.
dazu braeucht ich halt nur mal das grundgeruest.
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

Willkommen im Forum, ich habe zwar keine Ahnung von GTK aber ich habe folgende Unstimmigkeit gefunden:

Code: Alles auswählen

  def on_iter_children(self,rowref):
    if parent is None:
      return None
    else:
      try:
        child = rowref.children[0]
        return child
      except IndexError,e:
        return None
'parent' ist immer 'None'
grindhold
User
Beiträge: 3
Registriert: Dienstag 23. November 2010, 18:49

das stimmt natuerlich schonmal, dankeschoen. ich hab das testscript eben ziemlich fix aus meinem eigentlichen programm herausgearbeitet, kann passieren :)
Antworten