Problem
This is in response to Kovu's post titled "Dynamic Define Columns With GtkListStore".
He has some flat file databases, each containing differing number of columns.
He would like to be able to read in any of these flat file database, define the GtkListStore columns dynamically, and populate the data in a treeview as shown below:
Solution
- You can create GtkListStore dynamically with GtkTreeStore::set_column_types().
- To illustrate this, I use the familiar treeview example: How to display a 2D array in GtkTreeView - Part 5 - get user selection? so that you can compare the two methods of creating the data model statically and dynamically.
- Instead of storing the rows information in array, in this example, we store them in a plain text file, with the columns delimited by tabs as shown below:
Row # Description Qty Price row0 item 42 2 3.1 row1 item 36 20 6.21 row2 item 21 8 9.36 row3 item 10 11 12.4 row4 item 7 5 15.5 row5 item 4 17 18.6 row6 item 3 20 21.73
Sample Code
The following data file is required by the sample code below. Please save a copy of the data file and put them in the same directory where you store the sample code.
Please right click on the link and choose "Save As": flat_file_db.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 50 51 52 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 73 74 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | <?php $window = new GtkWindow(); $window->set_size_request(400, 200); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Display a flat file DB in GtkTreeView - Part 1"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 40); $vbox->pack_start($title, 0, 0); $vbox->pack_start(new GtkLabel(), 0, 0); // the 2D table $flat_file_db = 'flat_file_db.txt'; // note 1 $data = file($flat_file_db); // note 2 display_table($vbox, $data); $window->show_all(); Gtk::main(); function display_table($vbox, $data) { // Set up a scroll window $scrolled_win = new GtkScrolledWindow(); $scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); $vbox->pack_start($scrolled_win); // Creates the list store // Create the model $headers = explode("\t", trim($data[0])); // note 3 $model_def = array(); foreach($headers as $header) { if (defined("GObject::TYPE_STRING")) { $model_def[] = "GObject::TYPE_STRING"; // note 4 } else { $model_def[] = "Gtk::TYPE_STRING"; // note 4 } } $model = new GtkListStore(); // note 5 $model->set_column_types($model_def); // note 6 // Creates the view to display the list store $view = new GtkTreeView($model); $scrolled_win->add($view); // Creates the columns for ($col=0; $col<count($headers); ++$col) { $cell_renderer = new GtkCellRendererText(); $column = new GtkTreeViewColumn($headers[$col], $cell_renderer, 'text', $col); $column->set_sort_column_id($col); // set the header font and color $label = new GtkLabel($headers[$col]); $label->modify_font(new PangoFontDescription("Arial Bold")); $label->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000FF")); $column->set_widget($label); $label->show(); // setup self-defined function to display alternate row color $column->set_cell_data_func($cell_renderer, "format_col", $col); $view->append_column($column); } // pupulates the data for ($row=1; $row<count($data); ++$row) { // note 7 $columns = explode("\t", trim($data[$row])); $values = array(); for ($col=0; $col<count($columns); ++$col) { $values[] = $columns[$col]; } $model->append($values); } $selection = $view->get_selection(); $selection->connect('changed', 'on_selection'); } // self-defined function to format the price column function format_col($column, $cell, $model, $iter, $col_num) { $path = $model->get_path($iter); // get the current path $row_num = $path[0]; // get the row number if ($col_num==3) { $amt = $model->get_value($iter, 3); $cell->set_property('text', '$'.number_format($amt,2)); } $row_color = ($row_num%2==1) ? '#dddddd' : '#ffffff'; $cell->set_property('cell-background', $row_color); } // the function that is called when user selects a row function on_selection($selection) { list($model, $iter) = $selection->get_selected(); $desc = $model->get_value($iter, 1); $qty = $model->get_value($iter, 2); $price = $model->get_value($iter, 3); print "You have selected $desc: $qty ($price)\n"; } ?> |
Output
As shown above.
Explanation
We make use of the code from How to display a 2D array in GtkTreeView - Part 5 - get user selection?
What's new here:
- Specify the filename of your flat file database here.
- Read the entire flat file db into array.
- Grab the header info, which is the first row of the flat file. Note that in this example, the columns are tab delimited.
- Iterate through each column header and set up the corresponding column types in the array
$model_def
. Note that since there's no data type information stored in the flat file, we just set up all columns to useGtk::TYPE_STRING
. - Create an empty GtkListStore.
- Now set up the columns with the array
$model_def
. - Populate the data. Note that we now start with row 1, since row 0 is header information.
Note
- Since there is no data type information, all columns are of data type
Gtk::TYPE_STRING
. - Since there is no alignment information, all columns are left-aligned.
Read more...