1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gtk.ListStore; 26 27 private import glib.ConstructionException; 28 private import glib.MemorySlice; 29 private import gobject.ObjectG; 30 private import gobject.Value; 31 private import gtk.BuildableIF; 32 private import gtk.BuildableT; 33 private import gtk.TreeDragDestIF; 34 private import gtk.TreeDragDestT; 35 private import gtk.TreeDragSourceIF; 36 private import gtk.TreeDragSourceT; 37 private import gtk.TreeIter; 38 private import gtk.TreeModelIF; 39 private import gtk.TreeModelT; 40 private import gtk.TreeSortableIF; 41 private import gtk.TreeSortableT; 42 private import gtk.c.functions; 43 public import gtk.c.types; 44 45 46 /** 47 * A list-like data structure that can be used with the GtkTreeView 48 * 49 * The #GtkListStore object is a list model for use with a #GtkTreeView 50 * widget. It implements the #GtkTreeModel interface, and consequentialy, 51 * can use all of the methods available there. It also implements the 52 * #GtkTreeSortable interface so it can be sorted by the view. 53 * Finally, it also implements the tree 54 * [drag and drop][gtk4-GtkTreeView-drag-and-drop] 55 * interfaces. 56 * 57 * The #GtkListStore can accept most GObject types as a column type, though 58 * it can’t accept all custom types. Internally, it will keep a copy of 59 * data passed in (such as a string or a boxed pointer). Columns that 60 * accept #GObjects are handled a little differently. The 61 * #GtkListStore will keep a reference to the object instead of copying the 62 * value. As a result, if the object is modified, it is up to the 63 * application writer to call gtk_tree_model_row_changed() to emit the 64 * #GtkTreeModel::row_changed signal. This most commonly affects lists with 65 * #GdkTextures stored. 66 * 67 * An example for creating a simple list store: 68 * |[<!-- language="C" --> 69 * enum { 70 * COLUMN_STRING, 71 * COLUMN_INT, 72 * COLUMN_BOOLEAN, 73 * N_COLUMNS 74 * }; 75 * 76 * { 77 * GtkListStore *list_store; 78 * GtkTreePath *path; 79 * GtkTreeIter iter; 80 * int i; 81 * 82 * list_store = gtk_list_store_new (N_COLUMNS, 83 * G_TYPE_STRING, 84 * G_TYPE_INT, 85 * G_TYPE_BOOLEAN); 86 * 87 * for (i = 0; i < 10; i++) 88 * { 89 * char *some_data; 90 * 91 * some_data = get_some_data (i); 92 * 93 * // Add a new row to the model 94 * gtk_list_store_append (list_store, &iter); 95 * gtk_list_store_set (list_store, &iter, 96 * COLUMN_STRING, some_data, 97 * COLUMN_INT, i, 98 * COLUMN_BOOLEAN, FALSE, 99 * -1); 100 * 101 * // As the store will keep a copy of the string internally, 102 * // we free some_data. 103 * g_free (some_data); 104 * } 105 * 106 * // Modify a particular row 107 * path = gtk_tree_path_new_from_string ("4"); 108 * gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), 109 * &iter, 110 * path); 111 * gtk_tree_path_free (path); 112 * gtk_list_store_set (list_store, &iter, 113 * COLUMN_BOOLEAN, TRUE, 114 * -1); 115 * } 116 * ]| 117 * 118 * # Performance Considerations 119 * 120 * Internally, the #GtkListStore was originally implemented with a linked list 121 * with a tail pointer. As a result, it was fast at data insertion and deletion, 122 * and not fast at random data access. The #GtkListStore sets the 123 * #GTK_TREE_MODEL_ITERS_PERSIST flag, which means that #GtkTreeIters can be 124 * cached while the row exists. Thus, if access to a particular row is needed 125 * often and your code is expected to run on older versions of GTK, it is worth 126 * keeping the iter around. 127 * 128 * # Atomic Operations 129 * 130 * It is important to note that only the methods 131 * gtk_list_store_insert_with_values() and gtk_list_store_insert_with_valuesv() 132 * are atomic, in the sense that the row is being appended to the store and the 133 * values filled in in a single operation with regard to #GtkTreeModel signaling. 134 * In contrast, using e.g. gtk_list_store_append() and then gtk_list_store_set() 135 * will first create a row, which triggers the #GtkTreeModel::row-inserted signal 136 * on #GtkListStore. The row, however, is still empty, and any signal handler 137 * connecting to #GtkTreeModel::row-inserted on this particular store should be prepared 138 * for the situation that the row might be empty. This is especially important 139 * if you are wrapping the #GtkListStore inside a #GtkTreeModelFilter and are 140 * using a #GtkTreeModelFilterVisibleFunc. Using any of the non-atomic operations 141 * to append rows to the #GtkListStore will cause the 142 * #GtkTreeModelFilterVisibleFunc to be visited with an empty row first; the 143 * function must be prepared for that. 144 * 145 * # GtkListStore as GtkBuildable 146 * 147 * The GtkListStore implementation of the GtkBuildable interface allows 148 * to specify the model columns with a <columns> element that may contain 149 * multiple <column> elements, each specifying one model column. The “type” 150 * attribute specifies the data type for the column. 151 * 152 * Additionally, it is possible to specify content for the list store 153 * in the UI definition, with the <data> element. It can contain multiple 154 * <row> elements, each specifying to content for one row of the list model. 155 * Inside a <row>, the <col> elements specify the content for individual cells. 156 * 157 * Note that it is probably more common to define your models in the code, 158 * and one might consider it a layering violation to specify the content of 159 * a list store in a UI definition, data, not presentation, and common wisdom 160 * is to separate the two, as far as possible. 161 * 162 * An example of a UI Definition fragment for a list store: 163 * |[<!-- language="C" --> 164 * <object class="GtkListStore"> 165 * <columns> 166 * <column type="gchararray"/> 167 * <column type="gchararray"/> 168 * <column type="gint"/> 169 * </columns> 170 * <data> 171 * <row> 172 * <col id="0">John</col> 173 * <col id="1">Doe</col> 174 * <col id="2">25</col> 175 * </row> 176 * <row> 177 * <col id="0">Johan</col> 178 * <col id="1">Dahlin</col> 179 * <col id="2">50</col> 180 * </row> 181 * </data> 182 * </object> 183 * ]| 184 */ 185 public class ListStore : ObjectG, BuildableIF, TreeDragDestIF, TreeDragSourceIF, TreeModelIF, TreeSortableIF 186 { 187 /** the main Gtk struct */ 188 protected GtkListStore* gtkListStore; 189 190 /** Get the main Gtk struct */ 191 public GtkListStore* getListStoreStruct(bool transferOwnership = false) 192 { 193 if (transferOwnership) 194 ownedRef = false; 195 return gtkListStore; 196 } 197 198 /** the main Gtk struct as a void* */ 199 protected override void* getStruct() 200 { 201 return cast(void*)gtkListStore; 202 } 203 204 /** 205 * Sets our main struct and passes it to the parent class. 206 */ 207 public this (GtkListStore* gtkListStore, bool ownedRef = false) 208 { 209 this.gtkListStore = gtkListStore; 210 super(cast(GObject*)gtkListStore, ownedRef); 211 } 212 213 // add the Buildable capabilities 214 mixin BuildableT!(GtkListStore); 215 216 // add the TreeDragDest capabilities 217 mixin TreeDragDestT!(GtkListStore); 218 219 // add the TreeDragSource capabilities 220 mixin TreeDragSourceT!(GtkListStore); 221 222 // add the TreeModel capabilities 223 mixin TreeModelT!(GtkListStore); 224 225 // add the TreeSortable capabilities 226 mixin TreeSortableT!(GtkListStore); 227 228 /** 229 * Creates a top level iteractor. 230 * I don't think lists have but the top level iteractor 231 */ 232 TreeIter createIter() 233 { 234 GtkTreeIter* iter = new GtkTreeIter; 235 gtk_list_store_append(getListStoreStruct(), iter); 236 return new TreeIter(iter); 237 } 238 239 /** */ 240 void setValue(TYPE)(TreeIter iter, int column, TYPE value) 241 { 242 Value v = new Value(value); 243 gtk_list_store_set_value(gtkListStore, iter.getTreeIterStruct(), column, v.getValueStruct()); 244 } 245 246 /** 247 */ 248 249 /** */ 250 public static GType getType() 251 { 252 return gtk_list_store_get_type(); 253 } 254 255 /** 256 * Non-vararg creation function. Used primarily by language bindings. 257 * 258 * Params: 259 * types = an array of #GType types for the columns, from first to last 260 * 261 * Returns: a new #GtkListStore 262 * 263 * Throws: ConstructionException GTK+ fails to create the object. 264 */ 265 public this(GType[] types) 266 { 267 auto __p = gtk_list_store_newv(cast(int)types.length, types.ptr); 268 269 if(__p is null) 270 { 271 throw new ConstructionException("null returned by newv"); 272 } 273 274 this(cast(GtkListStore*) __p, true); 275 } 276 277 /** 278 * Appends a new row to @list_store. @iter will be changed to point to this new 279 * row. The row will be empty after this function is called. To fill in 280 * values, you need to call gtk_list_store_set() or gtk_list_store_set_value(). 281 * 282 * Params: 283 * iter = An unset #GtkTreeIter to set to the appended row 284 */ 285 public void append(out TreeIter iter) 286 { 287 GtkTreeIter* outiter = sliceNew!GtkTreeIter(); 288 289 gtk_list_store_append(gtkListStore, outiter); 290 291 iter = ObjectG.getDObject!(TreeIter)(outiter, true); 292 } 293 294 /** 295 * Removes all rows from the list store. 296 */ 297 public void clear() 298 { 299 gtk_list_store_clear(gtkListStore); 300 } 301 302 /** 303 * Creates a new row at @position. @iter will be changed to point to this new 304 * row. If @position is -1 or is larger than the number of rows on the list, 305 * then the new row will be appended to the list. The row will be empty after 306 * this function is called. To fill in values, you need to call 307 * gtk_list_store_set() or gtk_list_store_set_value(). 308 * 309 * Params: 310 * iter = An unset #GtkTreeIter to set to the new row 311 * position = position to insert the new row, or -1 for last 312 */ 313 public void insert(out TreeIter iter, int position) 314 { 315 GtkTreeIter* outiter = sliceNew!GtkTreeIter(); 316 317 gtk_list_store_insert(gtkListStore, outiter, position); 318 319 iter = ObjectG.getDObject!(TreeIter)(outiter, true); 320 } 321 322 /** 323 * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be 324 * prepended to the beginning of the list. @iter will be changed to point to 325 * this new row. The row will be empty after this function is called. To fill 326 * in values, you need to call gtk_list_store_set() or gtk_list_store_set_value(). 327 * 328 * Params: 329 * iter = An unset #GtkTreeIter to set to the new row 330 * sibling = A valid #GtkTreeIter, or %NULL 331 */ 332 public void insertAfter(out TreeIter iter, TreeIter sibling) 333 { 334 GtkTreeIter* outiter = sliceNew!GtkTreeIter(); 335 336 gtk_list_store_insert_after(gtkListStore, outiter, (sibling is null) ? null : sibling.getTreeIterStruct()); 337 338 iter = ObjectG.getDObject!(TreeIter)(outiter, true); 339 } 340 341 /** 342 * Inserts a new row before @sibling. If @sibling is %NULL, then the row will 343 * be appended to the end of the list. @iter will be changed to point to this 344 * new row. The row will be empty after this function is called. To fill in 345 * values, you need to call gtk_list_store_set() or gtk_list_store_set_value(). 346 * 347 * Params: 348 * iter = An unset #GtkTreeIter to set to the new row 349 * sibling = A valid #GtkTreeIter, or %NULL 350 */ 351 public void insertBefore(out TreeIter iter, TreeIter sibling) 352 { 353 GtkTreeIter* outiter = sliceNew!GtkTreeIter(); 354 355 gtk_list_store_insert_before(gtkListStore, outiter, (sibling is null) ? null : sibling.getTreeIterStruct()); 356 357 iter = ObjectG.getDObject!(TreeIter)(outiter, true); 358 } 359 360 /** 361 * A variant of gtk_list_store_insert_with_values() which 362 * takes the columns and values as two arrays, instead of 363 * varargs. 364 * 365 * This function is mainly intended for language-bindings. 366 * 367 * Params: 368 * iter = An unset #GtkTreeIter to set to the new row 369 * position = position to insert the new row, or -1 for last 370 * columns = an array of column numbers 371 * values = an array of GValues 372 */ 373 public void insertWithValuesv(out TreeIter iter, int position, int[] columns, Value[] values) 374 { 375 GtkTreeIter* outiter = sliceNew!GtkTreeIter(); 376 377 GValue[] valuesArray = new GValue[values.length]; 378 for ( int i = 0; i < values.length; i++ ) 379 { 380 valuesArray[i] = *(values[i].getValueStruct()); 381 } 382 383 gtk_list_store_insert_with_valuesv(gtkListStore, outiter, position, columns.ptr, valuesArray.ptr, cast(int)values.length); 384 385 iter = ObjectG.getDObject!(TreeIter)(outiter, true); 386 } 387 388 /** 389 * > This function is slow. Only use it for debugging and/or testing 390 * > purposes. 391 * 392 * Checks if the given iter is a valid iter for this #GtkListStore. 393 * 394 * Params: 395 * iter = A #GtkTreeIter. 396 * 397 * Returns: %TRUE if the iter is valid, %FALSE if the iter is invalid. 398 */ 399 public bool iterIsValid(TreeIter iter) 400 { 401 return gtk_list_store_iter_is_valid(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct()) != 0; 402 } 403 404 /** 405 * Moves @iter in @store to the position after @position. Note that this 406 * function only works with unsorted stores. If @position is %NULL, @iter 407 * will be moved to the start of the list. 408 * 409 * Params: 410 * iter = A #GtkTreeIter. 411 * position = A #GtkTreeIter or %NULL. 412 */ 413 public void moveAfter(TreeIter iter, TreeIter position) 414 { 415 gtk_list_store_move_after(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct(), (position is null) ? null : position.getTreeIterStruct()); 416 } 417 418 /** 419 * Moves @iter in @store to the position before @position. Note that this 420 * function only works with unsorted stores. If @position is %NULL, @iter 421 * will be moved to the end of the list. 422 * 423 * Params: 424 * iter = A #GtkTreeIter. 425 * position = A #GtkTreeIter, or %NULL. 426 */ 427 public void moveBefore(TreeIter iter, TreeIter position) 428 { 429 gtk_list_store_move_before(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct(), (position is null) ? null : position.getTreeIterStruct()); 430 } 431 432 /** 433 * Prepends a new row to @list_store. @iter will be changed to point to this new 434 * row. The row will be empty after this function is called. To fill in 435 * values, you need to call gtk_list_store_set() or gtk_list_store_set_value(). 436 * 437 * Params: 438 * iter = An unset #GtkTreeIter to set to the prepend row 439 */ 440 public void prepend(out TreeIter iter) 441 { 442 GtkTreeIter* outiter = sliceNew!GtkTreeIter(); 443 444 gtk_list_store_prepend(gtkListStore, outiter); 445 446 iter = ObjectG.getDObject!(TreeIter)(outiter, true); 447 } 448 449 /** 450 * Removes the given row from the list store. After being removed, 451 * @iter is set to be the next valid row, or invalidated if it pointed 452 * to the last row in @list_store. 453 * 454 * Params: 455 * iter = A valid #GtkTreeIter 456 * 457 * Returns: %TRUE if @iter is valid, %FALSE if not. 458 */ 459 public bool remove(TreeIter iter) 460 { 461 return gtk_list_store_remove(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct()) != 0; 462 } 463 464 /** 465 * Reorders @store to follow the order indicated by @new_order. Note that 466 * this function only works with unsorted stores. 467 * 468 * Params: 469 * newOrder = an array of integers mapping the new 470 * position of each child to its old position before the re-ordering, 471 * i.e. @new_order`[newpos] = oldpos`. It must have 472 * exactly as many items as the list store’s length. 473 */ 474 public void reorder(int[] newOrder) 475 { 476 gtk_list_store_reorder(gtkListStore, newOrder.ptr); 477 } 478 479 /** 480 * This function is meant primarily for #GObjects that inherit from #GtkListStore, 481 * and should only be used when constructing a new #GtkListStore. It will not 482 * function after a row has been added, or a method on the #GtkTreeModel 483 * interface is called. 484 * 485 * Params: 486 * types = An array length n of #GTypes 487 */ 488 public void setColumnTypes(GType[] types) 489 { 490 gtk_list_store_set_column_types(gtkListStore, cast(int)types.length, types.ptr); 491 } 492 493 /** 494 * See gtk_list_store_set(); this version takes a va_list for use by language 495 * bindings. 496 * 497 * Params: 498 * iter = A valid #GtkTreeIter for the row being modified 499 * varArgs = va_list of column/value pairs 500 */ 501 public void setValist(TreeIter iter, void* varArgs) 502 { 503 gtk_list_store_set_valist(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct(), varArgs); 504 } 505 506 /** 507 * Sets the data in the cell specified by @iter and @column. 508 * The type of @value must be convertible to the type of the 509 * column. 510 * 511 * Params: 512 * iter = A valid #GtkTreeIter for the row being modified 513 * column = column number to modify 514 * value = new value for the cell 515 */ 516 public void setValue(TreeIter iter, int column, Value value) 517 { 518 gtk_list_store_set_value(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct(), column, (value is null) ? null : value.getValueStruct()); 519 } 520 521 /** 522 * A variant of gtk_list_store_set_valist() which 523 * takes the columns and values as two arrays, instead of 524 * varargs. This function is mainly intended for 525 * language-bindings and in case the number of columns to 526 * change is not known until run-time. 527 * 528 * Params: 529 * iter = A valid #GtkTreeIter for the row being modified 530 * columns = an array of column numbers 531 * values = an array of GValues 532 */ 533 public void setValuesv(TreeIter iter, int[] columns, Value[] values) 534 { 535 GValue[] valuesArray = new GValue[values.length]; 536 for ( int i = 0; i < values.length; i++ ) 537 { 538 valuesArray[i] = *(values[i].getValueStruct()); 539 } 540 541 gtk_list_store_set_valuesv(gtkListStore, (iter is null) ? null : iter.getTreeIterStruct(), columns.ptr, valuesArray.ptr, cast(int)values.length); 542 } 543 544 /** 545 * Swaps @a and @b in @store. Note that this function only works with 546 * unsorted stores. 547 * 548 * Params: 549 * a = A #GtkTreeIter. 550 * b = Another #GtkTreeIter. 551 */ 552 public void swap(TreeIter a, TreeIter b) 553 { 554 gtk_list_store_swap(gtkListStore, (a is null) ? null : a.getTreeIterStruct(), (b is null) ? null : b.getTreeIterStruct()); 555 } 556 }