This sections explains the additional widgets provided by libgnomedbmm.
A Gnome::Db::Grid
is used to display and edit data in a table. In the simple read-only case it
is filled with the result of a Gda::Query
on the underlying database. A Gda::Model
must be filled with that query.
You do not need to show all fields of a table within the grid but only those will be shown that you select in your query:
/* Show all fields: */ query->set_sql_text("SELECT ref, category, name, price, wh_stored FROM products"); /* Show only some fields: */ query->set_sql_text("SELECT name, price FROM products");
The more interesting read-write case obviously requires some more work. The Gnome::Db::Grid
must know
how to modify the database if the user changes some fields. This information must be given to the model by using the set_modification_query()
method. The details of the modification query depend on your database engine and layout.
Note that the editing capabilities of the grid depend on the modification queries provided. If no delete query is given, rows cannot be deleted. If the update query does not update some field ('price' in the example), values in the corresponding column cannot be modified.
This examples creates a read-write Grid with a query from an example sqlite database.
File: examplewindow.h
#include <memory> #include <gtkmm.h> #include <libgdamm.h> #include <libgnomedbmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(const Glib::RefPtr<Gnome::Gda::Dict>& dict); private: #ifdef GLIBMM_EXCEPTIONS_ENABLED void create_model(const Glib::RefPtr<Gnome::Gda::Dict>& dict); #else void create_model(const Glib::RefPtr<Gnome::Gda::Dict>& dict, std::auto_ptr<Glib::Error>& error); #endif Glib::RefPtr<Gnome::Gda::DataModelQuery> m_model; Gtk::VBox m_box; Gtk::Label m_label; Gnome::Db::Grid* m_grid; };
File: main.cc
#include <libgnomedbmm.h> #include <libgdamm.h> #include <gtkmm.h> #include <iostream> #include "examplewindow.h" #ifdef GLIBMM_EXCEPTIONS_ENABLED Glib::RefPtr<Gnome::Gda::Dict> create_dict() #else Glib::RefPtr<Gnome::Gda::Dict> create_dict(std::auto_ptr<Glib::Error>& error) #endif { Glib::RefPtr<Gnome::Gda::Dict> dict = Gnome::Gda::Dict::create(); Glib::RefPtr<Gnome::Gda::Client> client = Gnome::Gda::Client::create(); Glib::ustring connection_string = "DB_DIR=" LIBGNOMEDB_DATADIR ";DB_NAME=demo_db"; #ifdef GLIBMM_EXCEPTIONS_ENABLED Glib::RefPtr<Gnome::Gda::Connection> cnc = client->open_connection_from_string("SQLite", connection_string, "" /* username */, "" /* password */); dict->set_connection(cnc); dict->update_dbms_meta_data(); #else Glib::RefPtr<Gnome::Gda::Connection> cnc = client->open_connection_from_string("SQLite", connection_string, "", "", Gnome::Gda::ConnectionOptions(0), error); if(error.get() == NULL) { dict->set_connection(cnc); dict->update_dbms_meta_data(error); } #endif return dict; } int main(int argc, char* argv[]) { Gtk::Main kit(argc, argv); Gnome::Db::init("Grid example", "1.0", argc, argv); Glib::RefPtr<Gnome::Gda::Dict> dict; #ifdef GLIBMM_EXCEPTIONS_ENABLED try { dict = create_dict(); } catch(const Glib::Error& err) { std::cerr << "Exception caught: " << err.what() << std::endl; return 1; } #else std::auto_ptr<Glib::Error> error; dict = create_dict(error); if(error.get() != NULL) { std::cerr << "Exception caught: " << error->what() << std::endl; return 1; } #endif ExampleWindow window(dict); kit.run(window); return 0; }
File: examplewindow.cc
#include "examplewindow.h" #include <libgdamm.h> #include <iostream> #ifdef GLIBMM_EXCEPTIONS_ENABLED void ExampleWindow::create_model(const Glib::RefPtr<Gnome::Gda::Dict>& dict) #else void ExampleWindow::create_model(const Glib::RefPtr<Gnome::Gda::Dict>& dict, std::auto_ptr<Glib::Error>& error) #endif // GLIBMM_EXCEPTIONS_ENABLED { Glib::RefPtr<Gnome::Gda::Query> query = Gnome::Gda::Query::create(dict); #ifdef GLIBMM_EXCEPTIONS_ENABLED query->set_sql_text("SELECT ref, category, name, price, wh_stored FROM products"); #else query->set_sql_text("SELECT ref, category, name, price, wh_stored FROM products", error); if(error.get() != NULL) return; #endif // GLIBMM_EXCEPTIONS_ENABLED m_model = Gnome::Gda::DataModelQuery::create(query); const Glib::ustring update_query = "UPDATE products set " "ref=##/*name:'+0' type:gchararray*/, " "category=##/*name:'+1' type:gint*/," "name=##/*name:'+2' type:gchararray*/, " "wh_stored=##/*name:'+4' type:gint*/ " "WHERE ref=##/*name:'-0' type:gchararray*/"; const Glib::ustring delete_query = "DELETE FROM products WHERE ref=##/*name:'-0' type:gchararray*/"; const Glib::ustring insert_query = "INSERT INTO products (ref, category, name, price, wh_stored) " "VALUES (##/*name:'+0' type:gchararray*/, " "##/*name:'+1' type:gint*/, " "##/*name:'+2' type:gchararray*/, " "1.0, " "##/*name:'+4' type:gint*/)"; #ifdef GLIBMM_EXCEPTIONS_ENABLED m_model->set_modification_query(update_query); m_model->set_modification_query(delete_query); m_model->set_modification_query(insert_query); #else m_model->set_modification_query(update_query, error); m_model->set_modification_query(delete_query, error); m_model->set_modification_query(insert_query, error); #endif } ExampleWindow::ExampleWindow(const Glib::RefPtr<Gnome::Gda::Dict>& dict) : m_label("The following Gnome::Db::Grid widget displays data from the 'products' table.\n\n" "As modification queries are provided, the data is read-write\n(except for the 'price' " "field as these queries voluntarily omit that field).") { m_box.set_border_width(6); m_box.pack_start(m_label, Gtk::PACK_SHRINK); #ifdef GLIBMM_EXCEPTIONS_ENABLED try { create_model(dict); } catch(const Glib::Error& err) { std::cerr << "Exception caught: " << err.what() << std::endl; exit(1); } #else std::auto_ptr<Glib::Error> error; create_model(dict, error); if(error.get() != NULL) { std::cerr << "Exception caught: " << error->what() << std::endl; exit(1); } #endif /* Create the demo widget */ m_grid = Gtk::manage(new Gnome::Db::Grid(m_model)); m_box.pack_start(*m_grid); add(m_box); set_default_size(0, 400); show_all(); }
By default, the title headers of the columns on a grid contain the name of the field. This might not always be desirable because they might not be human-readable. An easy way to specify custom headers is to adjust the SELECT query which reads the actual data:
query->set_sql_text("SELECT ref as \"ID\", category as \"Category\" FROM products");
The 'as' clause specifies the new name.
However, since Gnome::Db::Grid
is implemented as
a regular Gtk::TreeView
, the TreeView API can be used to
alter the title of the individual columns. Likewise, it is also possible
in this way to completely hide a column or manipulate it in other ways.
Gnome::Db::Grid
contains a
Gnome::Db::RawGrid
, which is a derived TreeView
which shows the data. The Gnome::Db::Grid
also provides
scrolling functionality and the toolbar at the bottom. This means that, in order to use the
TreeView API, we need the Gnome::Db::RawGrid
object from the
grid. This is available via the
Gnome::Db::Grid::get_raw_grid()
function.
The Gtk::TreeView::get_column()
function provides access
to the Gtk::TreeViewColumn
for a given column. The index
to get_column() depends on your selection query. For instance, if it was "SELECT ref, category FROM products",
then ref will be the first column (with index 0) and category will be the second (with index 1).
For instance, our code might look like this, assuming model is a valid
Gnome::Gda::DataModel
.
Gnome::Db::Grid grid(model); grid.get_raw_grid()->get_column(0)->set_title("ID"); grid.get_raw_grid()->get_column(1)->set_title("Category");
The first column's title was changed to "ID" whereas the second was changed to "Category".
File: main.cc
#include <libgnomedbmm.h> #include <gtkmm.h> int main(int argc, char* argv[]) { Gtk::Main kit(argc, argv); Gnome::Db::init("Example", "1.0", argc, argv); #ifndef GLIBMM_EXCEPTIONS_ENABLED std::auto_ptr<Glib::Error> error; #endif Glib::RefPtr<Gnome::Gda::Client> client = Gnome::Gda::Client::create(); #ifdef GLIBMM_EXCEPTIONS_ENABLED Glib::RefPtr<Gnome::Gda::Connection> connection = client->open_connection_from_string("SQLite", "DB_DIR=" LIBGNOMEDB_DATADIR ";DB_NAME=demo_db", "" /* username */, "" /* password */); #else Glib::RefPtr<Gnome::Gda::Connection> connection = client->open_connection_from_string("SQLite", "DB_DIR=" LIBGNOMEDB_DATADIR ";DB_NAME=demo_db", "" /* username */, "" /* password */, Gnome::Gda::ConnectionOptions(0), error); if(error.get() != NULL) return -1; #endif // GLIBMM_EXCEPTIONS_ENABLED #ifdef GLIBMM_EXCEPTIONS_ENABLED Glib::RefPtr<Gnome::Gda::DataModel> model = connection->execute_select_command("SELECT * FROM products"); #else Glib::RefPtr<Gnome::Gda::DataModel> model = connection->execute_select_command("SELECT * FROM products", error); if(error.get() != NULL) return -1; #endif // GLIBMM_EXCEPTIONS_ENABLED Gnome::Db::Grid grid(model); Gnome::Db::RawGrid* raw_grid = grid.get_raw_grid(); raw_grid->get_column(0)->set_title("ID"); raw_grid->get_column(1)->set_title("Category"); raw_grid->get_column(2)->set_title("Name"); raw_grid->get_column(3)->set_title("Price"); raw_grid->get_column(4)->set_title("Stored"); Gtk::Window window; window.set_title("Libgnomedbmm example window"); window.set_default_size(400, 400); window.add(grid); window.show_all(); kit.run(window); return 0; }