Commit eac54d80 authored by Murray Cumming's avatar Murray Cumming Committed by Murray Cumming

Explain how to use glom as an Operator and as a Developer.

2004-07-18  Murray Cumming  <murrayc@murrayc.com>

        * docs/user-guide/C/glom.xml: Explain how to use glom as an Operator
        and as a Developer.

2004-07-13  Murray Cumming  <murrayc@murrayc.com>

        * glom/data_structure/field.cc: sql(): Create sql text representation
        depending on the expected value type rather than the actual value
        type, to prevent SQL errors when using relationships between fields of
        different types.
parent fdb92da0
Murray Cumming <murrayc@murrayc.com>
Please see http://www.glom.org and use the mailing list instead of emailng me directly.
\ No newline at end of file
Please see http://www.glom.org and use the mailing list instead of emailing me directly.
\ No newline at end of file
2004-07-18 Murray Cumming <murrayc@murrayc.com>
* docs/user-guide/C/glom.xml: Explain how to use glom as an Operator
and as a Developer.
2004-07-13 Murray Cumming <murrayc@murrayc.com>
* glom/data_structure/field.cc: sql(): Create sql text representation
depending on the expected value type rather than the actual value
type, to prevent SQL errors when using relationships between fields of
different types.
2004-07-13 Murray Cumming <murrayc@murrayc.com>
* glom/mode_design/tables_relationships.[h|cc]: Actually delete
......
Glom is an easy-to-use database designer and user interface. See http://www.glom.org
Glom is an easy-to-use database designer and user interface.
See http://www.glom.org
......@@ -10,3 +10,20 @@ dist-hook: app-dist-hook
# Build a local copy (yelp normally transforms+renders it at runtime)
DOCBOOK_STYLESHEET ?= http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl
html/index.html: glom.xml
-rm -rf html
$(mkinstalldirs) html
xsltproc -o html/ --xinclude --catalogs $(DOCBOOK_STYLESHEET) $<
validate_original: glom.xml
xmllint --xinclude --valid --noout --catalogs $<
validate: glom.xml
xmllint --xinclude --valid --noout --catalogs $<
docs/user-guide/C/figures/start.png

33.3 KB | W: | H:

docs/user-guide/C/figures/start.png

18.9 KB | W: | H:

docs/user-guide/C/figures/start.png
docs/user-guide/C/figures/start.png
docs/user-guide/C/figures/start.png
docs/user-guide/C/figures/start.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -2,7 +2,7 @@
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY legal SYSTEM "legal.xml">
<!ENTITY appversion "0,8">
<!ENTITY appversion "0.8">
<!ENTITY manrevision "0.1">
<!ENTITY date "20 June 2004">
<!ENTITY app "Glom">
......@@ -181,9 +181,7 @@
fileref="figures/start.png" format="PNG"/>
</imageobject>
<textobject>
<phrase>Shows &app; main window. Contains titlebar, menubar,
toolbar, display area, and
scrollbars. Menubar contains File, Edit, View, and Help menus.
<phrase>Shows &app; main window.
</phrase>
</textobject>
</mediaobject>
......@@ -195,10 +193,128 @@
<!-- ================ Usage ================================ -->
<!-- Use this section to describe how to use the application to perform the tasks for
which the application is designed. -->
<sect1 id="glom-usage">
<title>Usage</title>
<para></para>
<sect1>
<title>Using Glom as an Operator</title>
<para>To open an existing glom document, either open that document from the File Manager, or choose Glom from the Applications menu, and then choose the document when asked. Glom will ask you for a user name and password to access the database. Your administrator will provide your user name and password.</para>
<para>When you open an existing document, Glom will be in <literal>Operator</literal> <literal>user level</literal>. This user level allows you to find and edit records, but does not allow you to change the fundamental structure of the database.</para>
<sect2>
<title>Navigation</title>
<para>Each database has several tables. To look at a different table, choose <literal>Table</literal> from the <literal>Navigate</literal> menu. Then double-click on the table, or select it and click the <literal>Open</literal> button.</para>
</sect2>
<sect2>
<title>Entering Data</title>
<para>When in <literal>Data Mode</literal>, you can enter information into either the <literal>List</literal> or <literal>Details</literal> view. The List view shows many records at once, but does not show every field. The details view shows only one record, and shows all the fields arranged suitably.</para>
<para>When you enter data into a field it will be saved into the database immediately after you finish editing the field. If it is a date or time field then the data format will be checked for you.</para>
<para>To create a new record just click the <literal>New</literal> button. A new record will be created with blank fields for you to fill in.</para>
</sect2>
<sect2>
<title>Finding Data</title>
<para>Choose <literal>Find Mode</literal> from the Mode menu. The fields in the List and Details views will now be empty, and a Find button will appear at the bottom of the window.</para>
<para>Enter information, or part of the information, into a field to find records with that information in that field. For instance, enter Jim into a name field to find records with &quot;Jim&quot; or &quot;Jimmy&quot; in the name.</para>
<para>When you press the <literal>Find</literal> button, glom will search for records and then display them. If only one record is found then it will show you that record in the Details view. If several records are found then it will show you those records in the List view.</para>
</sect2>
</sect1>
<sect1>
<title>Using Glom as a Developer</title>
<para>When you create a new document, Glom will be in the <literal>Developer</literal> <literal>user level</literal>. You can also change to the Developer user level after opening an existing document, with the <literal>User Level</literal> menu. Glom will only allow this if the administrator has allowed it.</para>
<sect2>
<title>Adding Tables</title>
<para>You can see the list of existing tables by choosing <literal>Table</literal> from the <literal>Navigate</literal> menu. You will also see this window after connecting to a database server, after creating a new document. To create a new table, click the <literal>Add</literal> button and enter the name for the new table. This name should not contain any spaces or special characters. Glom will suggest a human-readable title for this table. <literal>Operators</literal> will see this title instead of the actual table name. You can also marka a tables as <literal>hidden</literal> from Operators. For instance, Operators should see &quot;Invoice Lines&quot; as related records from the &quot;Invoices&quot; table, but they should never be able to navigate directly to the &quot;Invoice Lines&quot; table.</para>
<para>You can also specify one table as the <literal>default table</literal>. This table will be shown whenever an operator opens an existing document, without asking him to select a table from the list.</para>
<para>You can also use this window to rename an existing table.</para>
<para>Click the <literal>Open</literal> button to look at the selected table.</para>
</sect2>
<sect2>
<title>Editing Fields</title>
<para>Choose <literal>Fields</literal> from the <literal>Developer</literal> menu. This shows the list of fields in the table. New tables automatically have a primary key field, but you can change this field if necessary.</para>
<para>Click the <literal>Add</literal> button to add a new field, then enter the name of the new field. The name should not contain spaces or special characters. Glom will guess an appropriate human-readable title for this field, but you can edit this. <literal>Operators</literal> will see this title instead of the actual field name.</para>
<para>To specify more field details, select the field and click the <literal>Details</literal> button.</para>
<figure id="developer-editing-fields">
<title>Editing Fields</title>
<screenshot>
<mediaobject>
<imageobject><imagedata
fileref="figures/glom_design_fields.png" format="PNG"/>
</imageobject>
<textobject>
<phrase>Editing the table's fields.
</phrase>
</textobject>
</mediaobject>
</screenshot>
</figure>
<sect3>
<title>Primary Keys</title>
<para>Each table must have one, and only one, <literal>Primary Key</literal>. The value in this field will be unique, meaning that each value in this field will appear in only one record in the table. For instance, each record in a &quot;Customers&quot; table would have a &quot;Customer ID&quot;. This value will be used to refer to that customer from other tables, such as &quot;Projects&quot; and &quot;Invoices&quot; records. See the <link linkend="sec-developer-relationships">Creating Relationships</link> section to see how you can relate tables together.</para>
</sect3>
<sect3>
<title>Field Types</title>
<para>Glom offers a few simple field types:
<orderedlist>
<listitem><simpara>Number</simpara></listitem>
<listitem><simpara>Text</simpara></listitem>
<listitem><simpara>Date</simpara></listitem>
<listitem><simpara>Time</simpara></listitem>
<listitem><simpara>Boolean - either true or false</simpara></listitem>
</orderedlist>
</para>
</sect3>
<sect3>
<title>Calculated Fields</title>
<para>Field values can be calculated in terms of other fields, using the Python programming language. This calculation should be the implementation of a python function, which should return a value. The return value will be used as the value of the field. This value will be recalculated every time one of the source fields changes. TODO: This only works for default values at the moment, and you can not use field values in the calculation yet.</para>
<para>You can also use calculations to specify a default value for fields, by selecting the <literal>Default Value</literal> tab in the <literal>Field Details</literal> window, clicking on the <literal>Calculate Value</literal> check box, and then entering a Python calculation. You can test this calculation in the <literal>Edit</literal> window.</para>
</sect3>
</sect2>
<sect2>
<title>Arranging Layouts</title>
<para>Each table has <literal>List</literal> and <literal>Details</literal> views, and by default these show all fields in the table, in order of creation. You can edit the layout by choosing <literal>Layout</literal> from the <literal>Developer</literal> menu.</para>
<para>For the <literal>List</literal> view, you can specify the sequence of field columns, and whether some fields are hidden.</para>
<para>For the <literal>Details</literal> view, you can create groups of fields, and give these groups titles. You can then place fields in these groups and specify the sequence fo fields in these groups. You can also specify the sequence of these groups. For instance, in a &quot;Contacts&quot; table, you might create a &quot;Name&quot; group, and place the &quot;title&quot;, &quot;first_name&quot; and &quot;last_name&quot; fields in that group. You might have other groups for the &quot;Address&quot; fields.</para>
<para>Date and Time fields will be displayed, and entered, in the correct format according to the user's locale, but stored in the database in a canonical form. Therefore, a German user can enter a date in the German format, but this will later be displayed to a U.S. user in the U.S. format.</para>
</sect2>
<sect2 id="sec-developer-relationships">
<title>Creating Relationships</title>
<para>Tables in the Database are often related together. For instance, an &quot;Invoices&quot; table might have a &quot;Customer ID&quot; field. A value in this field would specify a record in the &quot;Customers&quot; table with the same value. Glom can show extra information, such as the customer name, from that related record. Or it can show a list of several related records - for instance, several related &quot;Invoice Lines&quot; that are related to a record in the &quot;Invoice&quot; record.</para>
<para>To create relationships, choose <literal>Relationships</literal> from the <literal>Developer</literal> menu. This will show the list of existing relationships. Click the <literal>Add</literal> button to create a new relationship, and enter a name for it. You should then choose a field in the current table, and a field in another table to which it should be related. This relationship will find any records in the other table for which the values in both fields are equal.</para>
<para>You can use the relationship in the following places.
<orderedlist>
<listitem><simpara>To show a related field on the List or Details view.</simpara></listitem>
<listitem><simpara>To show a list of related records on the Details view.</simpara></listitem>
<listitem><simpara>To lookup a value from a field in a related record. For instance, to copy the current price of a &quot;Product&quot; into the &quot;Price&quot; field of an &quot;Invoice Line&quot; record.</simpara></listitem>
<listitem><simpara>To calculate a field value.</simpara></listitem>
</orderedlist>
</para>
</sect2>
<sect2>
<title>Users Administration</title>
<para>To define the <literal>Operators</literal> who can use your database, and to specify what access they have to the various tables, choose <literal>Users</literal> from the <literal>Developer</literal> menu. TODO: Implement the User adminstration.</para>
</sect2>
</sect1>
<!-- Customization/Settings not yet implemented...
<- ============= Customization ============================= ->
<- Use this section to describe how to customize the application. ->
......@@ -603,6 +719,20 @@
any later version. A copy of this license can be found at this
<ulink url="ghelp:gpl" type="help">link</ulink>, or in the file
COPYING included with the source code of this program. </para>
</sect1>
</sect1>
<appendix id="sec-concepts">
<title>Concepts</title>
<para>Glom is easy to use, but you must understand the following basic concepts.
<orderedlist>
<listitem><simpara><literal>Database</literal>: Each glom document allows access to one database.</simpara></listitem>
<listitem><simpara><literal>Table</literal>: Each database contains several tables, such as &quot;Customers&quot; and &quot;Invoices&quot; tables.</simpara></listitem>
<listitem><simpara><literal>Field</literal>: Each table has several fields, such as &quot;Customer ID&quot;, &quot;First Name&quot;, and &quot;Date of Birth&quot; fields. In other documents and applications, fields are sometimes called &quot;Columns&quot;</simpara></listitem>
<listitem><simpara><literal>Records</literal>: Each table contains several records, each of which has values for each of the fields. For instance, the &quot;Customers&quot; table will have a record for each customer. In other documents and applications, records are sometimes called <literal>Rows</literal>.</simpara></listitem>
<listitem><simpara><literal>Relationships</literal>: Each table might be related to other tables, via fields in both tables. For instance, a &quot;Customers&quot; table could have a relationship to the &quot;Invoices&quot; table, so that people could see all the invoices for that customer. Only developers need to understand this concept. In other documents and applications, relationships are sometimes called &quot;Joins&quot;.</simpara></listitem>
</orderedlist>
</para>
</appendix>
</article>
......@@ -162,14 +162,18 @@ Glib::ustring Field::get_title_or_name() const
Glib::ustring Field::sql(const Gnome::Gda::Value& value) const
{
Glib::ustring str;
switch(value.get_value_type())
switch(get_glom_type())
{
case(Gnome::Gda::VALUE_TYPE_STRING):
case(TYPE_TEXT):
{
str = "'" + value.to_string() + "'"; //Add single-quotes. Actually escape it.
if(value.is_null())
return "''"; //We want to ignore the concept of NULL strings, and deal only with empty strings.
else
str = "'" + value.to_string() + "'"; //Add single-quotes. Actually escape it.
}
case(Gnome::Gda::VALUE_TYPE_DATE):
case(Gnome::Gda::VALUE_TYPE_TIME):
case(TYPE_DATE):
case(TYPE_TIME):
{
str = GlomConversions::get_text_for_gda_value(m_glom_type, value, std::locale() /* SQL uses the C locale */, true /* ISO standard */);
if(str != "NULL")
......@@ -177,14 +181,18 @@ Glib::ustring Field::sql(const Gnome::Gda::Value& value) const
break;
}
case(Gnome::Gda::VALUE_TYPE_NUMERIC):
case(TYPE_NUMERIC):
{
str = GlomConversions::get_text_for_gda_value(m_glom_type, value, std::locale() /* SQL uses the C locale */); //No quotes for numbers.
break;
}
case(Gnome::Gda::VALUE_TYPE_BOOLEAN):
case(TYPE_BOOLEAN):
{
str = ( value.get_bool() ? "TRUE" : "FALSE" );
if(value.get_value_type() == Gnome::Gda::VALUE_TYPE_BOOLEAN)
str = ( value.get_bool() ? "TRUE" : "FALSE" );
else
str = "FALSE";
break;
}
default:
......
......@@ -24,8 +24,7 @@
#include <libintl.h>
Box_Data_List::Box_Data_List()
: m_has_one_or_more_records(false),
m_first_col(0)
: m_has_one_or_more_records(false)
{
m_layout_name = "list";
......@@ -112,6 +111,7 @@ void Box_Data_List::fill_from_database()
{
for(guint result_row = 0; result_row < rows_count; result_row++)
{
Gnome::Gda::Value value = result->get_value_at(primary_key_field_index, result_row);
Glib::ustring key = value.to_string(); //It is actually an integer, but that should not matter.
if(key.empty())
......@@ -120,12 +120,21 @@ void Box_Data_List::fill_from_database()
{
Gtk::TreeModel::iterator tree_iter = m_AddDel.add_item(key);
type_vecFields::const_iterator iterFields = listFieldsToShow.begin();
//each field:
guint cols_count = result->get_n_columns();
for(guint uiCol = 0; uiCol < cols_count; uiCol++)
{
Gnome::Gda::Value value = result->get_value_at(uiCol, result_row);
m_AddDel.set_value(tree_iter, m_first_col + uiCol, value);
guint index = 0;
//TODO_Performance: This searches m_Fields again each time:
bool test = get_field_column_index(iterFields->get_name(), index);
++iterFields;
if(test)
m_AddDel.set_value(tree_iter, index, value);
}
}
}
......@@ -143,7 +152,7 @@ void Box_Data_List::fill_from_database()
//Select first record:
Glib::RefPtr<Gtk::TreeModel> refModel = m_AddDel.get_model();
if(refModel)
m_AddDel.select_item(refModel->children().begin(), m_first_col);
m_AddDel.select_item(refModel->children().begin());
fill_end();
}
......@@ -155,21 +164,28 @@ void Box_Data_List::on_adddel_user_requested_add()
//Start editing in the primary key or the first cell if the primary key is auto-incremented (because there is no point in editing an auto-generated value)..
guint index_primary_key = 0;
bool bPresent = get_field_primary_key(index_primary_key); //If there is no primary key then the default of 0 is OK.
guint index_field_to_edit = 0;
if(bPresent)
{
index_field_to_edit = index_primary_key;
Field fieldPrimaryKey = m_Fields[index_primary_key];
if(fieldPrimaryKey.get_field_info().get_auto_increment())
{
//Start editing in the first cell that is not the primary key:
if(index_primary_key == 0)
{
index_primary_key += 1; //TODO: Check that there is > 1 column.
index_field_to_edit += 1; //TODO: Check that there is > 1 column.
}
else
index_field_to_edit = 0;
}
}
const guint treemodel_column = m_first_col + index_primary_key;
m_AddDel.select_item(iter, treemodel_column, true /* start_editing */);
guint treemodel_column = 0;
bool test = get_field_column_index(m_Fields[index_field_to_edit].get_name(), treemodel_column);
if(test)
m_AddDel.select_item(iter, treemodel_column, true /* start_editing */);
}
void Box_Data_List::on_adddel_user_requested_edit(const Gtk::TreeModel::iterator& row)
......@@ -218,13 +234,11 @@ void Box_Data_List::on_adddel_user_added(const Gtk::TreeModel::iterator& row)
Glib::RefPtr<Gnome::Gda::DataModel> data_model = record_new(true /* use entered field data*/, primary_key_value);
if(data_model)
{
guint primary_key_field_index = 0;
bool test = get_field_primary_key(primary_key_field_index);
guint primary_key_model_col_index = 0;
bool test = get_field_column_index(field.get_name(), primary_key_model_col_index);
if(test)
{
guint primary_key_model_col_index = m_first_col + primary_key_field_index;
Gnome::Gda::FieldAttributes fieldInfo = field.get_field_info();
const Gnome::Gda::FieldAttributes fieldInfo = field.get_field_info();
//If it's an auto-increment, then get the value and show it:
if(fieldInfo.get_auto_increment())
{
......@@ -289,13 +303,13 @@ void Box_Data_List::on_adddel_user_changed(const Gtk::TreeModel::iterator& row,
{
Field field_primary_key = m_Fields[primary_key_field_index];
if(col >= m_first_col)
{
const guint changed_field_col_index = col - m_first_col;
const Field field = m_Fields[changed_field_col_index];
const Gnome::Gda::Value field_value = m_AddDel.get_value_as_value(row, col);
const Glib::ustring field_name = m_AddDel.get_column_field(col);
Field field;
bool test = get_fields_for_table_one_field(m_strTableName, field_name, field);
if(test)
{
const Gnome::Gda::Value field_value = m_AddDel.get_value_as_value(row, col);
Glib::ustring strQuery = "UPDATE " + m_strTableName;
strQuery += " SET " + field.get_name() + " = " + field.sql(field_value);
......@@ -372,7 +386,7 @@ void Box_Data_List::do_lookups(const Gtk::TreeModel::iterator& row, const Field&
void Box_Data_List::on_details_nav_first()
{
m_AddDel.select_item(m_AddDel.get_model()->children().begin(), m_first_col);
m_AddDel.select_item(m_AddDel.get_model()->children().begin());
signal_user_requested_details().emit(m_AddDel.get_value_key_selected_as_value());
}
......@@ -387,7 +401,7 @@ void Box_Data_List::on_details_nav_previous()
{
iter--;
m_AddDel.select_item(iter, m_first_col);
m_AddDel.select_item(iter);
signal_user_requested_details().emit(m_AddDel.get_value_key_selected_as_value());
}
}
......@@ -402,7 +416,7 @@ void Box_Data_List::on_details_nav_next()
if( !m_AddDel.get_is_last_row(iter) )
{
iter++;
m_AddDel.select_item(iter, m_first_col);
m_AddDel.select_item(iter);
signal_user_requested_details().emit(m_AddDel.get_value_key_selected_as_value());
}
......@@ -414,7 +428,7 @@ void Box_Data_List::on_details_nav_last()
Gtk::TreeModel::iterator iter = m_AddDel.get_last_row();
if(iter)
{
m_AddDel.select_item(iter, m_first_col);
m_AddDel.select_item(iter);
signal_user_requested_details().emit(m_AddDel.get_value_key_selected_as_value());
}
}
......@@ -511,15 +525,9 @@ void Box_Data_List::fill_column_titles()
type_vecFields listFieldsToShow = get_fields_to_show();
//Add a column for each table field:
bool first_col_added = false;
for(type_vecFields::const_iterator iter = listFieldsToShow.begin(); iter != listFieldsToShow.end(); ++iter)
{
guint col = m_AddDel.add_column(*iter);
if(!first_col_added)
{
m_first_col = col; //Remember for later.
first_col_added = true;
}
m_AddDel.add_column(*iter);
if(iter->get_field_info().get_primary_key())
m_AddDel.set_key_type(*iter);
......@@ -556,5 +564,6 @@ bool Box_Data_List::get_field_column_index(const Glib::ustring& field_name, guin
++i;
}
g_warning("Box_Data_List::get_field_column_index(): field not found.");
return false; //failure.
}
......@@ -71,7 +71,6 @@ protected:
mutable AddDel_WithButtons m_AddDel; //mutable because its get_ methods aren't const.
bool m_has_one_or_more_records;
guint m_first_col;
type_signal_user_requested_details m_signal_user_requested_details;
};
......
......@@ -32,17 +32,19 @@ Box_Data_List_Related::~Box_Data_List_Related()
void Box_Data_List_Related::init_db_details(const Glib::ustring& strDatabaseName, const Relationship& relationship, const Gnome::Gda::Value& foreign_key_value, const Gnome::Gda::Value& /* from_table_primary_key_value */)
{
m_strKeyField = relationship.get_to_field();
m_key_value = foreign_key_value;
//TODO:
//At the moment strForeignKeyValue must be SQLized already.
Glib::ustring strWhereClause;
if(!m_strKeyField.empty() && !GlomConversions::value_is_empty(m_key_value))
strWhereClause = m_strKeyField + " = " + m_key_value.to_string(); //TODO: Use field.sql().
bool found = get_fields_for_table_one_field(relationship.get_to_table(), relationship.get_to_field(), m_key_field);
if(found)
{
if(!GlomConversions::value_is_empty(m_key_value))
{
Glib::ustring strWhereClause = m_key_field.get_name() + " = " + m_key_field.sql(m_key_value);
Box_Data_List::init_db_details(strDatabaseName, relationship.get_to_table(), strWhereClause);
Box_Data_List::init_db_details(strDatabaseName, relationship.get_to_table(), strWhereClause);
}
//TODO: Clear the list if there is no key value?
}
}
void Box_Data_List_Related::fill_from_database()
......@@ -58,13 +60,8 @@ void Box_Data_List_Related::fill_from_database()
if(m_has_one_or_more_records) //This was set by Box_Data_List::fill_from_database().
{
//Is the to_field unique? If so, there can not be more than one.
Field field_to;
bool test = get_fields_for_table_one_field(m_strTableName, m_strKeyField, field_to);
if(test)
{
if(field_to.get_field_info().get_unique_key()) //automatically true if it is a primary key
allow_add = false;
}
if(m_key_field.get_field_info().get_unique_key()) //automatically true if it is a primary key
allow_add = false;
}
//TODO: Disable add if the from_field already has a value and the to_field is auto-incrementing because
......@@ -92,14 +89,13 @@ void Box_Data_List_Related::on_record_added(const Gnome::Gda::Value& primary_key
if(iter)
{
guint iKey = 0;
bool bTest = get_field_index(m_strKeyField, iKey);
bool bTest = get_field_column_index(m_key_field.get_name(), iKey);
if(!bTest)
std::cout << "Box_Data_List_Related::on_record_added() field not found: " << m_strKeyField << std::endl;
std::cout << "Box_Data_List_Related::on_record_added() field not found: " << m_key_field.get_name() << std::endl;
Gnome::Gda::Value key_value = m_AddDel.get_value_as_value(iter, m_first_col + iKey);
Gnome::Gda::Value key_value = m_AddDel.get_value_as_value(iter, iKey);
Box_Data_List::on_record_added(key_value); //adds blank row.
//Make sure that the new related record is related,
//by setting the foreign key:
//If it's not auto-generated.
......@@ -111,16 +107,16 @@ void Box_Data_List_Related::on_record_added(const Gnome::Gda::Value& primary_key
else
{
//Create the link by setting the foreign key:
m_AddDel.set_value(iter, m_first_col + iKey, key_value);
m_AddDel.set_value(iter, iKey, key_value);
on_adddel_user_changed(iter, m_first_col + iKey); //Update the database.
on_adddel_user_changed(iter, iKey); //Update the database.
}
}
}
Glib::ustring Box_Data_List_Related::get_KeyField() const
Field Box_Data_List_Related::get_key_field() const
{
return m_strKeyField;
return m_key_field;
}
void Box_Data_List_Related::on_adddel_user_added(const Gtk::TreeModel::iterator& row)
......@@ -131,31 +127,26 @@ void Box_Data_List_Related::on_adddel_user_added(const Gtk::TreeModel::iterator&
bool bAllowAdd = true;
Field field;
bool test = get_field(m_strKeyField, field);
if(test)
const Gnome::Gda::FieldAttributes fieldInfo = m_key_field.get_field_info();
if(fieldInfo.get_unique_key() || fieldInfo.get_primary_key())
{
Gnome::Gda::FieldAttributes fieldInfo = field.get_field_info();
if(fieldInfo.get_unique_key() || fieldInfo.get_primary_key())
{
if(m_AddDel.get_count() > 0) //If there is already 1 record
bAllowAdd = false;
}
if(m_AddDel.get_count() > 0) //If there is already 1 record
bAllowAdd = false;
}
if(bAllowAdd)
{
Box_Data_List::on_adddel_user_added(row);
}
else
{
//Tell user that they can't do that:
Gtk::MessageDialog dialog(gettext("You attempted to add a new related record, \nbut there can only be one related record, \nbecause the relationship uses a unique key."),
Gtk::MESSAGE_WARNING);
dialog.run();
if(bAllowAdd)
{
Box_Data_List::on_adddel_user_added(row);
}
else
{
//Tell user that they can't do that:
Gtk::MessageDialog dialog(gettext("You attempted to add a new related record, \nbut there can only be one related record, \nbecause the relationship uses a unique key."),
Gtk::MESSAGE_WARNING);
dialog.run();
//Replace with correct values:
fill_from_database();
}
//Replace with correct values:
fill_from_database();
}
}
......
......@@ -31,7 +31,7 @@ public:
virtual void init_db_details(const Glib::ustring& strDatabaseName, const Relationship& relationship, const Gnome::Gda::Value& foreign_key_value, const Gnome::Gda::Value& from_table_primary_key_value);
virtual Glib::ustring get_KeyField() const;
virtual Field get_key_field() const;
sigc::signal<void, Gnome::Gda::Value> signal_record_added;
......@@ -44,7 +44,7 @@ protected:
virtual void enable_buttons();
protected:
Glib::ustring m_strKeyField;
Field m_key_field;
Gnome::Gda::Value m_key_value;
};
......
......@@ -379,6 +379,13 @@ Gtk::TreeModel::iterator AddDel::get_row(const Glib::ustring& key)
return m_refListStore->children().end();
}
bool AddDel::select_item(const Gtk::TreeModel::iterator& iter)
{
guint col_first = 0;
get_model_column_index(0, col_first);
return select_item(iter, col_first);
}
bool AddDel::select_item(const Gtk::TreeModel::iterator& iter, guint column, bool start_editing)
{
if(!m_refListStore)
......@@ -852,6 +859,15 @@ guint AddDel::add_column(const Glib::ustring& strTitle, const Glib::ustring& col
return add_column(column_info);
}
Glib::ustring AddDel::get_column_field(guint column_index) const
{
Glib::ustring result;
if(column_index < m_ColumnTypes.size())
result = m_ColumnTypes[column_index].m_name;
return result;
}
bool AddDel::get_prevent_user_signals() const
{
return m_bPreventUserSignals;
......
......@@ -110,7 +110,8 @@ public:
virtual Gtk::TreeModel::iterator get_item_selected();
virtual bool select_item(const Gtk::TreeModel::iterator& iter, guint column, bool start_editing = false); //bool indicates success.
virtual bool select_item(const Gtk::TreeModel::iterator& iter);
//Select row with this key value:
virtual bool select_item(const Glib::ustring& strItemText, guint column, bool start_editing = false);
......@@ -143,6 +144,8 @@ public:
virtual guint get_columns_count() const;
virtual Glib::ustring get_column_field(guint column_index) const;
typedef AddDelColumnInfo::type_vecStrings type_vecStrings;
/** Retrieves the column order, even after they have been reordered by the user.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment