Form

A Gnome::Db::Form is in many ways similar to a Gnome::Db::Grid except that it does not show the data in a table but instead shows only one data set (usually one record) at a time using appropriate widgets. It features buttons to navigate through the data set and can also be used to edit data if modification queries were given, as stated in the Gnome::Db::Grid section.

Gnome::Db::Form reference

Example

This examples creates a read-write Form with a query from an example sqlite database.

Figure 5.2. Form

Form

Source Code

File: examplewindow.h

#include <gtkmm.h>
#include <libgdamm.h>
#include <libgdamm/datamodelquery.h>
#include <libgnomedbmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow(Glib::RefPtr<Gnome::Gda::Dict>& dict);
  ~ExampleWindow();
    
private:
  Glib::RefPtr<Gnome::Gda::DataModelQuery> m_model;
    
  Gtk::VBox m_box;
  Gtk::Label m_label;
  Gnome::Db::Form* m_form;
};

 

File: examplewindow.cc

#include "examplewindow.h" 

#include <libgdamm/query.h>
#include <libgdamm/datamodelquery.h>
#include <libgdamm/datamodel.h>
#include <iostream>

ExampleWindow::ExampleWindow(Glib::RefPtr<Gnome::Gda::Dict>& dict) :
  m_label("The following Gnome::Db::Form widget displays data from the 'products' table.\n\n"
          "Because modification queries were provided, the data is writeable\n(except for the 'price' "
          "field, because these queries voluntarily omit that field)."),
  m_form(0)
{		
  m_box.set_border_width(6);
  m_box.pack_start(m_label, Gtk::PACK_SHRINK);
		
  Glib::RefPtr<Gnome::Gda::Query> query = Gnome::Gda::Query::create(dict);
  query->set_sql_text("SELECT ref, category, name, price, wh_stored FROM products");
	
  // Create the demo widget:	
  m_model = Gnome::Gda::DataModelQuery::create(query);

  try
  {
    //TODO: Explain what these SQL queries do:
    m_model->set_modification_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*/");

    m_model->set_modification_query("DELETE FROM products WHERE ref=##/*name:'-0' type:gchararray*/");

    m_model->set_modification_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*/)");
  }
  catch(const Glib::Error& err)
  {
    std::cerr << "Exception Caught: " << err.what() << std::endl;
    exit(1);
  }

  m_form = new Gnome::Db::Form(m_model);

  m_box.pack_start(*m_form);
  add(m_box);
  show_all();
}

ExampleWindow::~ExampleWindow()
{
  delete m_form;
}

File: main.cc

#include <libgnomedbmm.h>
#include <libgdamm.h>
#include <gtkmm.h>

#include <iostream>

#include "examplewindow.h"

int main(int argc, char* argv[])
{
  Gtk::Main kit(argc, argv);
  Gnome::Db::init("Form example", "1.0", argc, argv);

  Glib::RefPtr<Gnome::Gda::Dict> dict = Gnome::Gda::Dict::create();
  try
  {
    // We use a Gda::Dict here to read the information how to map DMBS types to Gda types from an xml file.
    // A Gda::Dict is a powerful repository to store informations about the underlying database and read/write them
    // to xml in an efficient way. Besides types it can also store other informations such as functions and aggregates.
    std::string filename = Glib::build_filename(LIBGNOMEDB_DATADIR, "demo_dict.xml");
    dict->load_xml_file(filename);

    Glib::ustring connection_string = "DB_DIR=" LIBGNOMEDB_DATADIR ";DB_NAME=demo_db";

    // Create a connection to the embedded sqlite database
    Glib::RefPtr<Gnome::Gda::Client> client = Gnome::Gda::Client::create();
    Glib::RefPtr<Gnome::Gda::Connection> cnc = client->open_connection_from_string("SQLite" /* provider */, 
      connection_string, "" /* username */, "" /* password */);
    
    // Associate the connection with the edit
    dict->set_connection(cnc);
  }
  catch(const Glib::Error& err)
  {
    std::cerr << err.what() << std::endl;
    exit(1);
  }

  ExampleWindow window(dict);

  kit.run(window);
  return 0;
}

Setting fields as mandatory

Often you might have fields in your database that should never be empty. Gnome::Db::Form can support you by adding a '*' next to every field that is mandatory and showing an error message if the user leaves this field empty. Empty in this case means an empty string or an empty Gnome::Gda::Value.

To set a field as mandatory you must access the underlying Gda::Parameter of your Gda::DataModel and set the parameter to not-null:

// Configure param to be mandatory:
// Note that this must be done before the form is created.
Glib::RefPtr<Gnome::Gda::DataModelIter> iter = m_model->create_iter();
Glib::RefPtr<Gnome::Gda::Parameter> param = iter->find_param("name");
param->set_not_null();

Example

Figure 5.3. Mandatory fields in form

Mandatory fields in form

Source Code

File: examplewindow.h

#include <gtkmm.h>
#include <libgdamm.h>
#include <libgdamm/datamodelquery.h>
#include <libgnomedbmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow(Glib::RefPtr<Gnome::Gda::Dict>& dict);
  ~ExampleWindow();
    
private:
  Glib::RefPtr<Gnome::Gda::DataModelQuery> m_model;
  
  Gtk::VBox m_box;
  Gtk::Label m_label;
  Gnome::Db::Form* m_form;
};

 

File: examplewindow.cc

#include "examplewindow.h" 

#include <libgdamm/query.h>
#include <libgdamm/datamodelquery.h>
#include <libgdamm/datamodel.h>
#include <iostream>

ExampleWindow::ExampleWindow(Glib::RefPtr<Gnome::Gda::Dict>& dict) :
  m_label("The following Gnome::Db::Form widget displays data from the 'products' table.\n\n"
          "Because modification queries were provided, the data is writeable\n(except for the 'price' "
          "field, because these queries voluntarily omit that field)."),
  m_form(0)
{		
  m_box.set_border_width(6);
  m_box.pack_start(m_label, Gtk::PACK_SHRINK);
		
  Glib::RefPtr<Gnome::Gda::Query> query = Gnome::Gda::Query::create(dict);
  query->set_sql_text("SELECT id, name, country, city FROM warehouses");
	
  // Create the demo widget:	
  m_model = Gnome::Gda::DataModelQuery::create(query);

  try
  {
       //TODO: Explain what these SQL queries do:
    m_model->set_modification_query("UPDATE warehouses set "
                                    "id=##/*name:'+0' type:gint*/, "
                                    "name=##/*name:'+1' type:gchararray*/,"
                                    "country=##/*name:'+2' type:gchararray*/, "
                                    "city=##/*name:'+3' type:gchararray*/ "
                                    "WHERE id=##/*name:'-0' type:gint*/");

    m_model->set_modification_query("DELETE FROM warehouses WHERE id=##/*name:'-0' type:gint*/");

    m_model->set_modification_query("INSERT INTO warehouses (id, name, country, city) "
                                     "VALUES (##/*name:'+0' type:gint*/, "
                                     "##/*name:'+1' type:gchararray*/, "
                                     "##/*name:'+2' type:gchararray*/, "
                                     "##/*name:'+3' type:gchararray*/)");
  }
  catch(const Glib::Error& err)
  {
    std::cerr << "Exception Caught: " << err.what() << std::endl;
    exit(1);
  }

  // Configure param to be mandatory
  // Note that this has to be done before the form is created
  Glib::RefPtr<Gnome::Gda::DataModelIter> iter = m_model->create_iter();
  Glib::RefPtr<Gnome::Gda::Parameter> param = iter->find_param("city");
  if (param)
  {
    param->set_not_null();
  }
  else
  {
    std::cerr << "Param not found" << std::endl;
    exit(1);
  }
  m_form = new Gnome::Db::Form(m_model);
  
  
  m_box.pack_start(*m_form);
  add(m_box);
  show_all();
}

ExampleWindow::~ExampleWindow()
{
  delete m_form;
}

File: main.cc

#include <libgnomedbmm.h>
#include <libgdamm.h>
#include <gtkmm.h>

#include <iostream>

#include "examplewindow.h"

int main(int argc, char* argv[])
{
  Gtk::Main kit(argc, argv);
  Gnome::Db::init("Mandatory example", "1.0", argc, argv);

  Glib::RefPtr<Gnome::Gda::Dict> dict = Gnome::Gda::Dict::create();
  try
  {
    // We use a Gda::Dict here to read the information how to map DMBS types to Gda types from an xml file.
    // A Gda::Dict is a powerful repository to store informations about the underlying database and read/write them
    // to xml in an efficient way. Besides types it can also store other informations such as functions and aggregates.
    std::string filename = Glib::build_filename(LIBGNOMEDB_DATADIR, "demo_dict.xml");
    dict->load_xml_file(filename);

    Glib::ustring connection_string = "DB_DIR=" LIBGNOMEDB_DATADIR ";DB_NAME=demo_db";

    // Create a connection to the embedded sqlite database
    Glib::RefPtr<Gnome::Gda::Client> client = Gnome::Gda::Client::create();
    Glib::RefPtr<Gnome::Gda::Connection> cnc = client->open_connection_from_string("SQLite" /* provider */, 
      connection_string, "" /* username */, "" /* password */);
    
    // Associate the connection with the edit
    dict->set_connection(cnc);
  }
  catch(const Glib::Error& err)
  {
    std::cerr << err.what() << std::endl;
    exit(1);
  }

  ExampleWindow window(dict);

  kit.run(window);
  return 0;
}