/* * Copyright (C) 2012 - Juan Ferrer Toribio * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "vn-combo.h" #include "../vn-model.h" #include /** * SECTION:vn-combo * @Short_description: a combo box widget * @Title: VnCombo * @See_also: #VnField * @Image: combo.png * * A combo box widget to select from a list of items, selected from a * database. */ G_DEFINE_TYPE (VnCombo, vn_combo, VN_TYPE_FIELD); /** * vn_combo_new: * @model: the model used by combo box * * Creates a new #VnCombo * * Return value: a #VnCombo **/ VnField * vn_combo_new (DbModel * model) { return g_object_new (VN_TYPE_COMBO, "model", model, NULL); } /** * vn_combo_new_with_sql: * @conn: the connection used to create the combo model * @sql: the SQL query used to create the combo model * * Creates a new #VnCombo * * Return value: a #VnCombo **/ VnField * vn_combo_new_with_sql (DbConn * conn, const gchar * sql) { return g_object_new (VN_TYPE_COMBO, "sql", sql, "conn", conn, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private static void vn_combo_cb_changed (GtkComboBox * combo, VnCombo * obj) { GtkTreeIter iter; GValue value = {0}; if (gtk_combo_box_get_active_iter (combo, &iter)) gtk_tree_model_get_value (obj->tree, &iter, obj->index_column, &value); else g_value_init (&value, GVN_TYPE_NULL); VN_FIELD_GET_CLASS (obj)->value_changed (VN_FIELD (obj), &value); g_value_unset (&value); } static void vn_combo_on_model_ready (VnCombo * obj, const GValue * value) { DbIter iter; g_signal_handlers_block_by_func (obj->combo, vn_combo_cb_changed, obj); if (!gvn_value_is_null (value) && db_model_search_value (obj->model, obj->index_column, &iter, value)) { GtkTreeIter tree_iter; vn_gtk_tree_iter_from_db_iter (&tree_iter, &iter); gtk_combo_box_set_active_iter (obj->combo, &tree_iter); } else gtk_combo_box_set_active_iter (obj->combo, NULL); g_signal_handlers_unblock_by_func (obj->combo, vn_combo_cb_changed, obj); } static void vn_combo_set_value (VnCombo * obj, const GValue * value) { if (obj->model && db_model_get_status (obj->model) == DB_MODEL_STATUS_READY) vn_combo_on_model_ready (obj, value); } static void vn_combo_cb_status_changed (DbModel * model, DbModelStatus status, VnCombo * obj) { if (status == DB_MODEL_STATUS_READY) { gtk_combo_box_set_model (obj->combo, obj->tree); vn_combo_on_model_ready (obj, vn_field_get_value (VN_FIELD (obj))); } else gtk_combo_box_set_model (obj->combo, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public /** * vn_combo_set_conn: * @obj: a #VnCombo * @conn: the #DbConn * * Sets the connection used to create the combo model. **/ void vn_combo_set_conn (VnCombo * obj, DbConn * conn) { g_return_if_fail (VN_IS_COMBO (obj)); g_return_if_fail (DB_IS_CONN (conn)); g_return_if_fail (obj->model); db_model_set_conn (obj->model, conn); } /** * vn_combo_set_model: * @obj: a #VnCombo * @model: the #DbModel * * Sets the SQL query used to create the combo model. **/ void vn_combo_set_model (VnCombo * obj, DbModel * model) { g_return_if_fail (VN_IS_COMBO (obj)); g_return_if_fail (DB_IS_MODEL (model) || !model); if (obj->model) { g_signal_handlers_disconnect_by_func (obj->model, vn_combo_cb_status_changed, obj); g_clear_object (&obj->model); g_clear_object (&obj->tree); } if (model) { obj->tree = GTK_TREE_MODEL (vn_model_new (model)); obj->model = g_object_ref (model); g_signal_connect (model, "status-changed", G_CALLBACK (vn_combo_cb_status_changed), obj); vn_combo_cb_status_changed (model, db_model_get_status (model), obj); } } /** * vn_combo_get_index_column: * @obj: a #VnCombo * * Gets the combo column index. * * Return value: the column **/ guint vn_combo_get_index_column (VnCombo * obj) { g_return_val_if_fail (VN_IS_COMBO (obj), 0); return obj->index_column; } /** * vn_combo_set_index_column: * @obj: a #VnCombo * @column: the column * * Sets the column index used by combo. **/ void vn_combo_set_index_column (VnCombo * obj, guint column) { g_return_if_fail (VN_IS_COMBO (obj)); obj->index_column = column; vn_combo_set_value (obj, vn_field_get_value (VN_FIELD (obj))); } /** * vn_combo_get_show_column: * @obj: a #VnCombo * * Gets the column shown by combo. * * Return value: the column **/ guint vn_combo_get_show_column (VnCombo * obj) { g_return_val_if_fail (VN_IS_COMBO (obj), 0); return obj->show_column; } /** * vn_combo_set_show_column: * @obj: a #VnCombo * @column: the column * * Sets the column shown by combo. **/ void vn_combo_set_show_column (VnCombo * obj, guint column) { g_return_if_fail (VN_IS_COMBO (obj)); obj->show_column = column; gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (obj->combo), obj->cell); gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (obj->combo), obj->cell, "text", (gint) obj->show_column); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties enum { PROP_INDEX_COLUMN = 1 ,PROP_SHOW_COLUMN ,PROP_MODEL ,PROP_CONN ,PROP_SQL }; static void vn_combo_set_property (VnCombo * obj, guint property_id, const GValue * value, GParamSpec * pspec) { switch (property_id) { case PROP_INDEX_COLUMN: vn_combo_set_index_column (obj, g_value_get_uint (value)); break; case PROP_SHOW_COLUMN: vn_combo_set_show_column (obj, g_value_get_uint (value)); break; case PROP_MODEL: vn_combo_set_model (obj, g_value_get_object (value)); break; case PROP_CONN: vn_combo_set_conn (obj, g_value_get_object (value)); break; case PROP_SQL: { const gchar * sql = g_value_get_string (value); if (sql) { DbModel * model = db_model_new_with_sql (NULL, g_value_get_string (value)); vn_combo_set_model (obj, model); g_object_unref (model); } break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); } } static void vn_combo_get_property (VnCombo * obj, guint property_id, GValue * value, GParamSpec * pspec) { switch (property_id) { case PROP_INDEX_COLUMN: g_value_set_uint (value, obj->index_column); break; case PROP_SHOW_COLUMN: g_value_set_uint (value, obj->show_column); break; case PROP_MODEL: g_value_set_object (value, obj->model); break; case PROP_CONN: g_value_set_object (value, db_model_get_conn (obj->model)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class static void vn_combo_init (VnCombo * obj) { obj->tree = NULL; obj->model = NULL; obj->combo = GTK_COMBO_BOX (gtk_combo_box_new ()); g_signal_connect (obj->combo, "changed", G_CALLBACK (vn_combo_cb_changed), obj); gtk_container_add (GTK_CONTAINER (obj), GTK_WIDGET (obj->combo)); obj->cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (obj->combo), obj->cell, TRUE); VN_FIELD (obj)->field = GTK_WIDGET (obj->combo); } static void vn_combo_finalize (VnCombo * obj) { vn_combo_set_model (obj, NULL); G_OBJECT_CLASS (vn_combo_parent_class)->finalize (G_OBJECT (obj)); } static void vn_combo_class_init (VnComboClass * klass) { GObjectClass * k = G_OBJECT_CLASS (klass); k->finalize = (GObjectFinalizeFunc) vn_combo_finalize; k->set_property = (GObjectSetPropertyFunc) vn_combo_set_property; k->get_property = (GObjectGetPropertyFunc) vn_combo_get_property; VN_FIELD_CLASS (klass)->set_value = (VnFieldSetValueFunc) vn_combo_set_value; g_object_class_install_property (k, PROP_INDEX_COLUMN, g_param_spec_uint ("index-column" ,_("Index column") ,_("The column index of the model") ,0, 255, 0 ,G_PARAM_CONSTRUCT | G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_SHOW_COLUMN, g_param_spec_uint ("show-column" ,_("Show column") ,_("The column of the model shown by combo") ,0, 255, 1 ,G_PARAM_CONSTRUCT | G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_MODEL, g_param_spec_object ("model" ,_("Model") ,_("The model from which the combo takes the values shown in the list") ,DB_TYPE_MODEL ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_CONN, g_param_spec_object ("conn" ,_("Connection") ,_("The connection used by the model") ,DB_TYPE_CONN ,G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_SQL, g_param_spec_string ("sql" ,_("SQL") ,_("The SQL query used to create the model") , NULL ,G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE )); }