v 0. Pasted by Anonymous as d at 2008-08-28 11:50:18 MSK and set expiration to never.
v 1. Edited by Anonymous as d at 2008-08-28 11:58:35 MSK and set expiration to never.

Paste will expire never.

  1. module CustomList;
  2.  
  3. import glib.RandG;
  4. import gobject.Value;
  5. import gtk.TreeIter;
  6. import gtk.TreePath;
  7. import gtk.TreeModel;
  8.  
  9. struct CustomRecord
  10. {
  11.   /* data - you can extend this */
  12.   string name;
  13.   uint yearBorn;
  14.  
  15.   /* admin stuff used by the custom list model */
  16.   uint pos;   /* pos within the array */
  17. }
  18.  
  19. enum CustomListColumn
  20. {
  21.     Record = 0,
  22.     Name,
  23.     YearBorn,
  24.     NColumns,
  25. }
  26.  
  27. class CustomList : TreeModel
  28. {
  29.     uint numRows;
  30.     int nColumns;
  31.     int stamp;
  32.     GType[3] columnTypes;
  33.     CustomRecord*[] rows;
  34.  
  35.     public this()
  36.     {
  37.         nColumns = columnTypes.length;
  38.         columnTypes[0] = GType.POINTER;
  39.         columnTypes[1] = GType.STRING;
  40.         columnTypes[2] = GType.UINT;
  41.  
  42.         stamp = RandG.randomInt();
  43.     }
  44.  
  45.     override GtkTreeModelFlags getFlags()
  46.     {
  47.         return (GtkTreeModelFlags.LIST_ONLY | GtkTreeModelFlags.ITERS_PERSIST);
  48.     }
  49.  
  50.     override int getNColumns()
  51.     {
  52.         return nColumns;
  53.     }
  54.  
  55.     override GType getColumnType(int index)
  56.     {
  57.         if ( index >= nColumns || index < 0 )
  58.             return GType.INVALID;
  59.  
  60.         return columnTypes[index];
  61.     }
  62.  
  63.     int getIter(TreeIter iter, TreePath path)
  64.     {
  65.         CustomRecord* record;
  66.         int*          indices;
  67.         int           n, depth;
  68.  
  69.         indices = path.getIndices();
  70.         depth   = path.getDepth();
  71.  
  72.         /* we do not allow children */
  73.         if (depth != 1)
  74.             return false;//throw new Exception("We only except lists");
  75.  
  76.         n = indices[0]; /* the n-th top level row */
  77.  
  78.         if ( n >= numRows || n < 0 )
  79.             return false;
  80.  
  81.         record = rows[n];
  82.  
  83.         if ( record is null )
  84.             throw new Exception("Not Exsisting record requested");
  85.         if ( record.pos != n )
  86.             throw new Exception("record.pos != TreePath.getIndices()[0]");
  87.  
  88.         /* We simply store a pointer to our custom record in the iter */
  89.         auto it = iter.getTreeIterStruct();
  90.         it.stamp     = stamp;
  91.         it.userData  = record;
  92.  
  93.         return true;
  94.     }
  95.  
  96.     override TreePath getPath(TreeIter iter)
  97.     {
  98.         TreePath path;
  99.         CustomRecord* record;
  100.      
  101.         if ( iter is null || iter.getTreeIterStruct().userData is null)
  102.             return null;
  103.  
  104.         record = cast(CustomRecord*) iter.getTreeIterStruct().userData;
  105.  
  106.         path = new TreePath();
  107.         path.appendIndex(record.pos);
  108.  
  109.         return path;
  110.     }
  111.  
  112.     override void getValue(TreeIter iter, int column, Value value)
  113.     {
  114.         CustomRecord  *record;
  115.  
  116.         if ( iter is null || column >= nColumns )
  117.             return;
  118.  
  119.         value.init(columnTypes[column]);
  120.  
  121.         record = cast(CustomRecord*) iter.getTreeIterStruct().userData;
  122.  
  123.         if ( record is null || record.pos >= numRows )
  124.             return;
  125.  
  126.         switch(column)
  127.         {
  128.             case CustomListColumn.Record:
  129.                 value.setPointer(record);
  130.                 break;
  131.  
  132.             case CustomListColumn.Name:
  133.                 value.setString(record.name);
  134.                 break;
  135.  
  136.             case CustomListColumn.YearBorn:
  137.                 value.setUint(record.yearBorn);
  138.                 break;
  139.         }
  140.     }
  141.  
  142.     override int iterNext(TreeIter iter)
  143.     {
  144.         CustomRecord* record, nextrecord;
  145.      
  146.         if ( iter is null || iter.getTreeIterStruct().userData is null )
  147.             return false;
  148.  
  149.         record = cast(CustomRecord*) iter.getTreeIterStruct().userData;
  150.  
  151.         /* Is this the last record in the list? */
  152.         if ( (record.pos + 1) >= numRows)
  153.             return false;
  154.  
  155.         nextrecord = rows[(record.pos + 1)];
  156.  
  157.         if ( nextrecord is null || nextrecord.pos != record.pos + 1 )
  158.             throw new Exception("Invalid next record");
  159.  
  160.         auto it = iter.getTreeIterStruct();
  161.         it.stamp     = stamp;
  162.         it.userData  = nextrecord;
  163.  
  164.         return true;
  165.     }
  166.  
  167.     override int iterChildren(TreeIter iter, TreeIter parent)
  168.     {
  169.         /* this is a list, nodes have no children */
  170.         if ( parent !is null )
  171.             return false;
  172.  
  173.         /* No rows => no first row */
  174.         if ( numRows == 0 )
  175.             return false;
  176.  
  177.         /* Set iter to first item in list */
  178.         auto it = iter.getTreeIterStruct();
  179.         it.stamp     = stamp;
  180.         it.userData  = rows[0];
  181.  
  182.         return true;
  183.     }
  184.  
  185.     override int iterHasChild(TreeIter iter)
  186.     {
  187.         return false;
  188.     }
  189.  
  190.     override int iterNChildren(TreeIter iter)
  191.     {
  192.         /* special case: if iter == NULL, return number of top-level rows */
  193.         if ( iter is null )
  194.             return numRows;
  195.  
  196.         return 0; /* otherwise, this is easy again for a list */
  197.     }
  198.  
  199.     override int iterNthChild(TreeIter iter, TreeIter parent, int n)
  200.     {
  201.         CustomRecord  *record;
  202.  
  203.         /* a list has only top-level rows */
  204.         if( parent is null )
  205.             return false;
  206.  
  207.         if( n >= numRows )
  208.             return false;
  209.  
  210.         record = rows[n];
  211.  
  212.         if ( record == null || record.pos != n )
  213.             throw new Exception("Invalid record");
  214.  
  215.         auto it = iter.getTreeIterStruct();
  216.         it.stamp     = stamp;
  217.         it.userData  = record;
  218.  
  219.         return true;
  220.     }
  221.  
  222.     override int iterParent(TreeIter iter, TreeIter child)
  223.     {
  224.         return false;
  225.     }
  226.  
  227.     void appendRecord(string name, uint yearBorn)
  228.     {
  229.         TreeIter      iter;
  230.         TreePath      path;
  231.         CustomRecord* newrecord;
  232.         uint          pos;
  233.  
  234.         if ( name is null )
  235.             return;
  236.  
  237.         pos = numRows;
  238.         numRows++;
  239.  
  240.         newrecord = new CustomRecord;
  241.  
  242.         newrecord.name = name;
  243.         newrecord.yearBorn = yearBorn;
  244.  
  245.         rows ~= newrecord;
  246.         newrecord.pos = pos;
  247.  
  248.         path = new TreePath();
  249.         path.appendIndex(pos);
  250.  
  251.         iter = new TreeIter();
  252.         getIter(iter, path);
  253.  
  254.         rowInserted(path, iter);
  255.     }
  256. }