497. How to display a flat file database in treeview with dynamically created GtkListStore model - Part 1?

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:

How to display a flat file database in treeview with dynamically created GtkListStore model - Part 1?


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
    
  • Note that the header information is contained in the first row of the data file.

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:

  1. Specify the filename of your flat file database here.
  2. Read the entire flat file db into array.
  3. Grab the header info, which is the first row of the flat file. Note that in this example, the columns are tab delimited.
  4. 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 use Gtk::TYPE_STRING.
  5. Create an empty GtkListStore.
  6. Now set up the columns with the array $model_def.
  7. 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.

Related Links

Add comment


Security code
Refresh