aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schaarschmidt <schaarsc@gmx.de>2014-03-24 23:29:31 +0800
committerMilan Crha <mcrha@redhat.com>2014-03-24 23:29:31 +0800
commit2263c3c6049be334e48c650e06332e18ca5af7d2 (patch)
tree984167a9b6c1845bc60819c5ad498ed2e9b74cf5
parentec1862c1497ac44f89c1fe3d92d922b525da96d9 (diff)
downloadgsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.tar
gsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.tar.gz
gsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.tar.bz2
gsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.tar.lz
gsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.tar.xz
gsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.tar.zst
gsoc2013-evolution-2263c3c6049be334e48c650e06332e18ca5af7d2.zip
Bug #724059 - Allow arbitrary number of phone entries in the contact editor
-rw-r--r--addressbook/gui/contact-editor/Makefile.am4
-rw-r--r--addressbook/gui/contact-editor/contact-editor.ui220
-rw-r--r--addressbook/gui/contact-editor/e-contact-editor-dyntable.c738
-rw-r--r--addressbook/gui/contact-editor/e-contact-editor-dyntable.h126
-rw-r--r--addressbook/gui/contact-editor/e-contact-editor.c372
5 files changed, 1026 insertions, 434 deletions
diff --git a/addressbook/gui/contact-editor/Makefile.am b/addressbook/gui/contact-editor/Makefile.am
index 4e5d0b7111..c8499b7da4 100644
--- a/addressbook/gui/contact-editor/Makefile.am
+++ b/addressbook/gui/contact-editor/Makefile.am
@@ -21,7 +21,9 @@ libecontacteditor_la_SOURCES = \
e-contact-editor.c \
e-contact-editor.h \
e-contact-quick-add.c \
- e-contact-quick-add.h
+ e-contact-quick-add.h \
+ e-contact-editor-dyntable.h \
+ e-contact-editor-dyntable.c
libecontacteditor_la_LDFLAGS = -avoid-version $(NO_UNDEFINED)
diff --git a/addressbook/gui/contact-editor/contact-editor.ui b/addressbook/gui/contact-editor/contact-editor.ui
index 7e48bc5443..9b7e94ea1e 100644
--- a/addressbook/gui/contact-editor/contact-editor.ui
+++ b/addressbook/gui/contact-editor/contact-editor.ui
@@ -528,215 +528,17 @@
<property name="border_width">12</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
- <child>
- <object class="GtkTable" id="table84">
- <property name="visible">True</property>
- <property name="n_rows">2</property>
- <property name="n_columns">4</property>
- <property name="column_spacing">6</property>
- <property name="row_spacing">6</property>
- <child>
- <object class="GtkEntry" id="entry-phone-1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry-phone-3">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry-phone-4">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry-phone-2">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-1">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-3">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-2">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-4">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkTable" id="table-phone-extended">
- <property name="n_rows">2</property>
- <property name="n_columns">4</property>
- <property name="column_spacing">6</property>
- <property name="row_spacing">6</property>
- <child>
- <object class="GtkEntry" id="entry-phone-5">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry-phone-7">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry-phone-6">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry-phone-8">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-5">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-7">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-6">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="combobox-phone-8">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
+
+ <child>
+ <object class="EContactEditorDynTable" type-func="e_contact_editor_dyntable_get_type" id="phone-dyntable">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+
+
</object>
</child>
<child type="label">
diff --git a/addressbook/gui/contact-editor/e-contact-editor-dyntable.c b/addressbook/gui/contact-editor/e-contact-editor-dyntable.c
new file mode 100644
index 0000000000..4706d5b1f9
--- /dev/null
+++ b/addressbook/gui/contact-editor/e-contact-editor-dyntable.c
@@ -0,0 +1,738 @@
+/*
+ * e-contact-editor-dyntable.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "e-contact-editor-dyntable.h"
+
+G_DEFINE_TYPE(EContactEditorDynTable, e_contact_editor_dyntable, GTK_TYPE_GRID)
+
+/* one position is occupied by two widgets: combo+entry */
+#define ENTRY_SIZE 2
+#define MAX_CAPACITY 100
+
+enum {
+ CHANGED_SIGNAL,
+ ACTIVATE_SIGNAL,
+ ROW_ADDED_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint dyntable_signals[LAST_SIGNAL];
+
+struct _EContactEditorDynTablePrivate {
+
+ /* absolute max, dyntable will ignore the rest */
+ guint max_entries;
+
+ /* current number of entries with text or requested by user*/
+ guint curr_entries;
+
+ /* minimum to show, with or without text */
+ guint show_min_entries;
+
+ /* no matter how much data, show only */
+ guint show_max_entries;
+
+ /* number of entries (combo/text) per row */
+ guint columns;
+
+ /* if true, fill line with empty slots*/
+ gboolean justified;
+
+ GtkWidget *add_button;
+ GtkListStore *combo_store;
+ GtkListStore *data_store;
+
+ /* array of default values for combo box */
+ const gint *combo_defaults;
+
+ /* number of elements in the array */
+ size_t combo_defaults_n;
+};
+
+GtkWidget*
+e_contact_editor_dyntable_new (void)
+{
+ GtkWidget* widget;
+ widget = GTK_WIDGET (g_object_new (e_contact_editor_dyntable_get_type (), NULL));
+ return widget;
+}
+
+static void
+set_combo_box_active (EContactEditorDynTable *dyntable,
+ GtkComboBox *combo_box,
+ gint active)
+{
+ g_signal_handlers_block_matched (combo_box,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL,
+ NULL, dyntable);
+ gtk_combo_box_set_active (combo_box, active);
+ g_signal_handlers_unblock_matched (combo_box,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL,
+ NULL, dyntable);
+}
+
+/* translate position into column/row */
+static void
+position_to_grid (EContactEditorDynTable *dyntable,
+ guint pos,
+ guint *col,
+ guint *row)
+{
+ *row = pos / dyntable->priv->columns;
+ *col = pos % dyntable->priv->columns * ENTRY_SIZE;
+}
+
+static void
+move_widget (GtkGrid *grid, GtkWidget *w, guint col, guint row)
+{
+ GValue rowValue = G_VALUE_INIT, colValue = G_VALUE_INIT;
+
+ g_value_init (&rowValue, G_TYPE_UINT);
+ g_value_init (&colValue, G_TYPE_UINT);
+
+ g_value_set_uint (&rowValue, row);
+ g_value_set_uint (&colValue, col);
+
+ gtk_container_child_set_property (GTK_CONTAINER (grid), w,
+ "left-attach", &colValue);
+ gtk_container_child_set_property (GTK_CONTAINER (grid), w,
+ "top-attach", &rowValue);
+}
+
+static gboolean
+is_button_required (EContactEditorDynTable *dyntable)
+{
+ if (dyntable->priv->curr_entries >= dyntable->priv->max_entries)
+ return FALSE;
+ if (dyntable->priv->curr_entries <= dyntable->priv->show_max_entries)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+sensitize_button (EContactEditorDynTable *dyntable)
+{
+ guint row, col, current_entries;
+ GtkWidget *w;
+ GtkGrid *grid;
+ EContactEditorDynTableClass *class;
+ gboolean enabled;
+
+ grid = GTK_GRID (dyntable);
+ class = E_CONTACT_EDITOR_DYNTABLE_GET_CLASS (dyntable);
+
+ current_entries = dyntable->priv->curr_entries;
+ enabled = TRUE;
+ if (current_entries > 0) {
+ /* last entry */
+ current_entries--;
+ position_to_grid (dyntable, current_entries, &col, &row);
+ w = gtk_grid_get_child_at (grid, col + 1, row);
+
+ enabled = !class->widget_is_empty (dyntable, w);
+ }
+
+ gtk_widget_set_sensitive (dyntable->priv->add_button, enabled);
+}
+
+static void
+show_button (EContactEditorDynTable *dyntable)
+{
+ guint col,row, pos;
+ gboolean visible = FALSE;
+ GtkGrid *grid;
+
+ grid = GTK_GRID (dyntable);
+
+ /* move button to end of current line */
+ pos = dyntable->priv->curr_entries;
+ if (pos > 0)
+ pos--;
+ position_to_grid(dyntable, pos, &col, &row);
+ move_widget (grid, dyntable->priv->add_button,
+ dyntable->priv->columns*ENTRY_SIZE+1, row);
+
+ /* set visibility */
+ if (is_button_required (dyntable))
+ visible = TRUE;
+
+ gtk_widget_set_visible (dyntable->priv->add_button, visible);
+
+ sensitize_button (dyntable);
+}
+
+static void
+increment_counter (EContactEditorDynTable *dyntable)
+{
+ dyntable->priv->curr_entries++;
+ show_button (dyntable);
+}
+
+static void
+decrement_counter (EContactEditorDynTable *dyntable)
+{
+ dyntable->priv->curr_entries--;
+ show_button (dyntable);
+}
+
+static gint
+get_next_combo_index (EContactEditorDynTable *dyntable)
+{
+ size_t array_size = dyntable->priv->combo_defaults_n;
+ gint idx = 0;
+
+ if (dyntable->priv->combo_defaults != NULL) {
+ idx = dyntable->priv->combo_defaults[dyntable->priv->curr_entries % array_size];
+ }
+
+ return idx;
+}
+
+static GtkWidget*
+combo_box_create (EContactEditorDynTable *dyntable)
+{
+ GtkWidget *w;
+ GtkComboBox *combo;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+
+ w = gtk_combo_box_new ();
+ combo = GTK_COMBO_BOX (w);
+ store = dyntable->priv->combo_store;
+
+ gtk_combo_box_set_model (combo, GTK_TREE_MODEL(store));
+
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo));
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
+ "text", DYNTABLE_COMBO_COLUMN_TEXT,
+ "sensitive", DYNTABLE_COMBO_COLUMN_SENSITIVE,
+ NULL);
+
+ gtk_combo_box_set_active (combo, get_next_combo_index (dyntable));
+
+ return w;
+}
+
+static void
+emit_changed (EContactEditorDynTable *dyntable)
+{
+ g_signal_emit (dyntable, dyntable_signals[CHANGED_SIGNAL], 0);
+}
+
+static void
+emit_activated (EContactEditorDynTable *dyntable)
+{
+ g_signal_emit (dyntable, dyntable_signals[ACTIVATE_SIGNAL], 0);
+}
+
+static void
+emit_row_added (EContactEditorDynTable *dyntable)
+{
+ g_signal_emit (dyntable, dyntable_signals[ROW_ADDED_SIGNAL], 0);
+}
+
+static void
+add_empty_entry (EContactEditorDynTable *dyntable)
+{
+ GtkGrid *grid;
+ guint row, col;
+ GtkWidget *box, *entry;
+ EContactEditorDynTableClass *class;
+
+ grid = GTK_GRID (dyntable);
+ position_to_grid (dyntable, dyntable->priv->curr_entries, &col, &row);
+
+ /* create new entry at last position */
+ class = E_CONTACT_EDITOR_DYNTABLE_GET_CLASS (dyntable);
+ box = combo_box_create (dyntable);
+ gtk_grid_attach (grid, box, col, row, 1, 1);
+ gtk_widget_show (box);
+
+ entry = class->widget_create (dyntable);
+ g_object_set (entry, "margin-left", 2, NULL);
+ g_object_set (entry, "margin-right", 5, NULL);
+ gtk_widget_set_hexpand (entry, GTK_EXPAND);
+ gtk_grid_attach (grid, entry, col + 1, row, 1, 1);
+ gtk_widget_show (entry);
+
+ g_signal_connect_swapped(box, "changed",
+ G_CALLBACK (gtk_widget_grab_focus), entry);
+ g_signal_connect_swapped(box, "changed",
+ G_CALLBACK (emit_changed), dyntable);
+ g_signal_connect_swapped(entry, "changed",
+ G_CALLBACK (emit_changed), dyntable);
+ g_signal_connect_swapped(entry, "changed",
+ G_CALLBACK (sensitize_button), dyntable);
+ g_signal_connect_swapped(entry, "activate",
+ G_CALLBACK (emit_activated), dyntable);
+
+ increment_counter (dyntable);
+
+ if ( (dyntable->priv->justified && col < dyntable->priv->columns-1) ||
+ (dyntable->priv->curr_entries < dyntable->priv->show_min_entries) )
+ add_empty_entry (dyntable);
+
+ gtk_widget_grab_focus (entry);
+}
+
+static void
+remove_empty_entries (EContactEditorDynTable *dyntable, gboolean fillup)
+{
+ guint row, col, pos;
+ GtkGrid* grid;
+ GtkWidget* w;
+ EContactEditorDynTableClass *class;
+
+ grid = GTK_GRID (dyntable);
+ class = E_CONTACT_EDITOR_DYNTABLE_GET_CLASS (dyntable);
+
+ for (pos = 0; pos < dyntable->priv->curr_entries; pos++) {
+ position_to_grid (dyntable, pos, &col, &row);
+ w = gtk_grid_get_child_at (grid, col + 1, row);
+
+ if (w != NULL && class->widget_is_empty (dyntable, w)) {
+ guint pos2, next_col, next_row;
+
+ gtk_widget_destroy (w);
+ w = gtk_grid_get_child_at (grid, col, row);
+ gtk_widget_destroy (w);
+
+ /* now fill gap */
+ for (pos2 = pos + 1; pos2 < dyntable->priv->curr_entries; pos2++) {
+ position_to_grid (dyntable, pos2, &next_col, &next_row);
+ w = gtk_grid_get_child_at (grid, next_col, next_row);
+ move_widget (grid, w, col, row);
+ w = gtk_grid_get_child_at (grid, next_col + 1, next_row);
+ move_widget (grid, w, col + 1, row);
+ col = next_col;
+ row = next_row;
+ }
+ decrement_counter (dyntable);
+ pos--; /* check the new widget on our current position */
+ }
+
+ }
+
+ if (fillup && dyntable->priv->curr_entries < dyntable->priv->show_min_entries)
+ add_empty_entry (dyntable);
+
+}
+
+/* clears data, not the combo box list store */
+void
+e_contact_editor_dyntable_clear_data (EContactEditorDynTable *dyntable)
+{
+ guint i, col, row;
+ GtkGrid *grid;
+ GtkWidget *w;
+ EContactEditorDynTableClass *class;
+
+ grid = GTK_GRID(dyntable);
+ class = E_CONTACT_EDITOR_DYNTABLE_GET_CLASS(dyntable);
+
+ for (i = 0; i < dyntable->priv->curr_entries; i++) {
+ position_to_grid (dyntable, i, &col, &row);
+ w = gtk_grid_get_child_at (grid, col + 1, row);
+ class->widget_clear (dyntable, w);
+ }
+ remove_empty_entries (dyntable, TRUE);
+
+ gtk_list_store_clear (dyntable->priv->data_store);
+}
+
+static void
+adjust_visibility_of_widgets (EContactEditorDynTable *dyntable)
+{
+ guint pos, col, row;
+ GtkGrid *grid;
+ GtkWidget *w;
+
+ grid = GTK_GRID (dyntable);
+ for (pos = 0; pos < dyntable->priv->curr_entries; pos++) {
+ gboolean visible = FALSE;
+
+ if (pos < dyntable->priv->show_max_entries)
+ visible = TRUE;
+
+ position_to_grid (dyntable, pos, &col, &row);
+ w = gtk_grid_get_child_at (grid, col, row);
+ gtk_widget_set_visible (w, visible);
+ w = gtk_grid_get_child_at (grid, col + 1, row);
+ gtk_widget_set_visible (w, visible);
+ }
+
+ show_button (dyntable);
+}
+
+/* number of columns can only be set before any data is added to this dyntable */
+void e_contact_editor_dyntable_set_num_columns (EContactEditorDynTable *dyntable,
+ guint number_of_columns,
+ gboolean justified)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *store;
+ gboolean holds_data;
+
+ g_return_if_fail (number_of_columns > 0);
+
+ store = GTK_TREE_MODEL (dyntable->priv->data_store);
+ holds_data = gtk_tree_model_get_iter_first (store, &iter);
+ g_return_if_fail (!holds_data);
+
+ remove_empty_entries(dyntable, FALSE);
+
+ dyntable->priv->columns = number_of_columns;
+ dyntable->priv->justified = justified;
+
+ remove_empty_entries(dyntable, TRUE);
+}
+
+void
+e_contact_editor_dyntable_set_max_entries (EContactEditorDynTable *dyntable,
+ guint max)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *store;
+ gboolean holds_data;
+
+ g_return_if_fail (max > 0);
+
+ store = GTK_TREE_MODEL (dyntable->priv->data_store);
+ holds_data = gtk_tree_model_get_iter_first (store, &iter);
+ g_return_if_fail (!holds_data);
+
+ dyntable->priv->max_entries = max;
+ if (dyntable->priv->show_max_entries>max)
+ dyntable->priv->show_max_entries = max;
+ if (dyntable->priv->show_min_entries>max)
+ dyntable->priv->show_min_entries = max;
+}
+
+/* show at least number_of_entries, with or without data */
+void
+e_contact_editor_dyntable_set_show_min (EContactEditorDynTable *dyntable,
+ guint number_of_entries)
+{
+ if (number_of_entries > dyntable->priv->show_max_entries)
+ dyntable->priv->show_min_entries = dyntable->priv->show_max_entries;
+ else
+ dyntable->priv->show_min_entries = number_of_entries;
+
+ if (dyntable->priv->curr_entries < dyntable->priv->show_min_entries)
+ add_empty_entry (dyntable);
+
+ adjust_visibility_of_widgets (dyntable);
+}
+
+/* show no more than number_of_entries, hide the rest */
+void
+e_contact_editor_dyntable_set_show_max (EContactEditorDynTable *dyntable,
+ guint number_of_entries)
+{
+ if (number_of_entries > dyntable->priv->max_entries) {
+ dyntable->priv->show_max_entries = dyntable->priv->max_entries;
+ } else if (number_of_entries < dyntable->priv->show_min_entries) {
+ dyntable->priv->show_max_entries = dyntable->priv->show_min_entries;
+ } else {
+ dyntable->priv->show_max_entries = number_of_entries;
+ }
+
+ adjust_visibility_of_widgets (dyntable);
+}
+
+/* use data_store to fill data into widgets */
+void
+e_contact_editor_dyntable_fill_in_data (EContactEditorDynTable *dyntable)
+{
+ guint pos = 0, col, row;
+ EContactEditorDynTableClass *class;
+ GtkGrid *grid;
+ GtkTreeIter iter;
+ GtkTreeModel *store;
+ GtkWidget *w;
+ gboolean valid;
+ gchar *str_data;
+ gint int_data;
+
+ class = E_CONTACT_EDITOR_DYNTABLE_GET_CLASS (dyntable);
+ grid = GTK_GRID (dyntable);
+ store = GTK_TREE_MODEL (dyntable->priv->data_store);
+
+ valid = gtk_tree_model_get_iter_first (store, &iter);
+ while (valid) {
+ gtk_tree_model_get (store, &iter,
+ DYNTABLE_STORE_COLUMN_ENTRY_STRING, &str_data,
+ DYNTABLE_STORE_COLUMN_SELECTED_ITEM, &int_data,
+ -1);
+
+ if (pos >= dyntable->priv->curr_entries)
+ add_empty_entry (dyntable);
+
+ position_to_grid (dyntable, pos++, &col, &row);
+ w = gtk_grid_get_child_at (grid, col, row);
+ set_combo_box_active (dyntable, GTK_COMBO_BOX(w), int_data);
+ w = gtk_grid_get_child_at (grid, col + 1, row);
+ class->widget_fill (dyntable, w, str_data);
+
+ g_return_if_fail(pos < dyntable->priv->max_entries);
+ valid = gtk_tree_model_iter_next (store, &iter);
+ }
+
+ /* fix visibility of added items */
+ adjust_visibility_of_widgets (dyntable);
+}
+
+/* the model returned has 3 columns
+ *
+ * UINT: sort order
+ * UINT: active combo item
+ * STRING: data extracted with widget_extract()
+ */
+GtkListStore*
+e_contact_editor_dyntable_extract_data (EContactEditorDynTable *dyntable)
+{
+ EContactEditorDynTableClass *class;
+ GtkGrid *grid;
+ GtkListStore *data_store;
+ GtkWidget *w;
+ guint pos, col, row;
+
+ grid = GTK_GRID(dyntable);
+ class = E_CONTACT_EDITOR_DYNTABLE_GET_CLASS(dyntable);
+ data_store = dyntable->priv->data_store;
+
+ gtk_list_store_clear (data_store);
+
+ for (pos = 0; pos < dyntable->priv->curr_entries; pos++) {
+
+ position_to_grid (dyntable, pos, &col, &row);
+ w = gtk_grid_get_child_at (grid, col + 1, row);
+
+ if (!class->widget_is_empty (dyntable, w)) {
+ GtkTreeIter iter;
+ gchar *dup;
+ gint combo_item;
+ const gchar *data;
+
+ data = class->widget_extract (dyntable, w);
+ w = gtk_grid_get_child_at (grid, col, row);
+ combo_item = gtk_combo_box_get_active (GTK_COMBO_BOX(w));
+
+ dup = g_strdup (data);
+ g_strstrip(dup);
+
+ gtk_list_store_append (data_store, &iter);
+ gtk_list_store_set (data_store, &iter,
+ DYNTABLE_STORE_COLUMN_SORTORDER, pos,
+ DYNTABLE_STORE_COLUMN_SELECTED_ITEM, combo_item,
+ DYNTABLE_STORE_COLUMN_ENTRY_STRING, dup,
+ -1);
+
+ g_free (dup);
+ }
+ }
+
+ return dyntable->priv->data_store;
+}
+
+/* the model returned has two columns
+ *
+ * STRING: bound to attribute "text"
+ * BOOLEAN: bound to attribute "sensitive"
+ */
+GtkListStore*
+e_contact_editor_dyntable_get_combo_store (EContactEditorDynTable *dyntable)
+{
+ return dyntable->priv->combo_store;
+}
+
+void
+e_contact_editor_dyntable_set_combo_defaults (EContactEditorDynTable *dyntable,
+ const gint *defaults,
+ size_t defaults_n)
+{
+ dyntable->priv->combo_defaults = defaults;
+ dyntable->priv->combo_defaults_n = defaults_n;
+}
+
+static void
+dispose_impl (GObject *object)
+{
+ GtkListStore *store;
+ EContactEditorDynTable *dyntable;
+
+ dyntable = E_CONTACT_EDITOR_DYNTABLE(object);
+
+ store = dyntable->priv->data_store;
+ if (store) {
+ gtk_list_store_clear (store);
+ g_object_unref (store);
+ dyntable->priv->data_store = NULL;
+ }
+
+ store = dyntable->priv->combo_store;
+ if (store) {
+ g_object_unref (store);
+ dyntable->priv->combo_store = NULL;
+ }
+
+ G_OBJECT_CLASS(e_contact_editor_dyntable_parent_class)->dispose (object);
+}
+
+static GtkWidget*
+default_impl_widget_create (EContactEditorDynTable *dyntable)
+{
+ return gtk_entry_new ();
+}
+
+static void
+default_impl_widget_clear (EContactEditorDynTable *dyntable,
+ GtkWidget *w)
+{
+ GtkEntry *e;
+ e = GTK_ENTRY(w);
+ gtk_entry_set_text (e, "");
+}
+
+static const gchar*
+default_impl_widget_extract (EContactEditorDynTable *dyntable,
+ GtkWidget *w)
+{
+ GtkEntry *e;
+
+ e = GTK_ENTRY(w);
+ return gtk_entry_get_text (e);
+}
+
+static void
+default_impl_widget_fill (EContactEditorDynTable *dyntable,
+ GtkWidget *w,
+ const gchar *value)
+{
+ GtkEntry *e;
+
+ e = GTK_ENTRY(w);
+ gtk_entry_set_text (e, value);
+}
+
+static gboolean
+default_impl_widget_is_empty (EContactEditorDynTable *dyntable,
+ GtkWidget *w)
+{
+ GtkEntry *e;
+ const gchar *data;
+ gchar * dup;
+ size_t len = -1;
+
+ e = GTK_ENTRY(w);
+ if (0 == gtk_entry_get_text_length (e))
+ return TRUE;
+
+ data = gtk_entry_get_text (e);
+
+ dup = g_strdup (data);
+ g_strchug (dup);
+ len = strlen (dup);
+ g_free (dup);
+
+ return len <= 0;
+}
+
+static void
+e_contact_editor_dyntable_init (EContactEditorDynTable *dyntable)
+{
+ GtkGrid *grid;
+
+ dyntable->priv = G_TYPE_INSTANCE_GET_PRIVATE(dyntable,
+ E_TYPE_CONTACT_EDITOR_DYNTABLE,
+ EContactEditorDynTablePrivate);
+
+ /* fill in defaults */
+ dyntable->priv->max_entries = MAX_CAPACITY;
+ dyntable->priv->curr_entries = 0;
+ dyntable->priv->show_min_entries = 0;
+ dyntable->priv->show_max_entries = dyntable->priv->max_entries;
+ dyntable->priv->columns = 2;
+ dyntable->priv->justified = FALSE;
+ dyntable->priv->combo_defaults = NULL;
+
+ dyntable->priv->combo_store = gtk_list_store_new (DYNTABLE_COBMO_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING, G_TYPE_BOOLEAN);
+ dyntable->priv->data_store = gtk_list_store_new (DYNTABLE_STORE_COLUMN_NUM_COLUMNS,
+ G_TYPE_UINT, G_TYPE_INT, G_TYPE_STRING);
+ gtk_tree_sortable_set_sort_column_id (
+ GTK_TREE_SORTABLE (dyntable->priv->data_store),
+ DYNTABLE_STORE_COLUMN_SORTORDER,
+ GTK_SORT_ASCENDING);
+
+ dyntable->priv->add_button = gtk_button_new_with_label ("+");
+ g_signal_connect_swapped (dyntable->priv->add_button, "clicked",
+ G_CALLBACK (add_empty_entry), dyntable);
+ g_signal_connect_swapped(dyntable->priv->add_button, "clicked",
+ G_CALLBACK (emit_row_added), dyntable);
+
+ grid = GTK_GRID (dyntable);
+
+ gtk_grid_attach (grid, dyntable->priv->add_button, 0, 0, 1, 1);
+ gtk_widget_set_valign (dyntable->priv->add_button, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (dyntable->priv->add_button, GTK_ALIGN_START);
+ gtk_widget_show (dyntable->priv->add_button);
+
+ if (dyntable->priv->curr_entries < dyntable->priv->show_min_entries)
+ add_empty_entry (dyntable);
+}
+
+static void
+e_contact_editor_dyntable_class_init (EContactEditorDynTableClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof(EContactEditorDynTablePrivate));
+
+ dyntable_signals[CHANGED_SIGNAL] = g_signal_new ("changed",
+ G_TYPE_FROM_CLASS(class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET(EContactEditorDynTableClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ dyntable_signals[ACTIVATE_SIGNAL] = g_signal_new ("activate",
+ G_TYPE_FROM_CLASS(class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET(EContactEditorDynTableClass, activate),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ dyntable_signals[ROW_ADDED_SIGNAL] = g_signal_new ("row-added",
+ G_TYPE_FROM_CLASS(class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET(EContactEditorDynTableClass, row_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = dispose_impl;
+
+ /* virtual functions */
+ class->widget_create = default_impl_widget_create;
+ class->widget_is_empty = default_impl_widget_is_empty;
+ class->widget_clear = default_impl_widget_clear;
+ class->widget_extract = default_impl_widget_extract;
+ class->widget_fill = default_impl_widget_fill;
+}
diff --git a/addressbook/gui/contact-editor/e-contact-editor-dyntable.h b/addressbook/gui/contact-editor/e-contact-editor-dyntable.h
new file mode 100644
index 0000000000..c5c9238d56
--- /dev/null
+++ b/addressbook/gui/contact-editor/e-contact-editor-dyntable.h
@@ -0,0 +1,126 @@
+/*
+ * e-contact-editor-dyntable.h
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef E_CONTACT_EDITOR_DYNTABLE_H_
+#define E_CONTACT_EDITOR_DYNTABLE_H_
+
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define E_TYPE_CONTACT_EDITOR_DYNTABLE \
+ (e_contact_editor_dyntable_get_type ())
+#define E_CONTACT_EDITOR_DYNTABLE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CONTACT_EDITOR_DYNTABLE, EContactEditorDynTable))
+#define E_CONTACT_EDITOR_DYNTABLE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), E_TYPE_CONTACT_EDITOR_DYNTABLE, EContactEditorDynTableClass))
+#define E_IS_CONTACT_EDITOR_DYNTABLE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CONTACT_EDITOR_DYNTABLE))
+#define E_IS_CONTACT_EDITOR_DYNTABLE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((obj), E_TYPE_CONTACT_EDITOR_DYNTABLE))
+#define E_CONTACT_EDITOR_DYNTABLE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ (obj,E_TYPE_CONTACT_EDITOR_DYNTABLE, EContactEditorDynTableClass))
+
+G_BEGIN_DECLS
+
+typedef enum {
+ DYNTABLE_STORE_COLUMN_SORTORDER,
+ DYNTABLE_STORE_COLUMN_SELECTED_ITEM,
+ DYNTABLE_STORE_COLUMN_ENTRY_STRING,
+ DYNTABLE_STORE_COLUMN_NUM_COLUMNS
+} EContactEditorDynTableStoreColumns;
+
+typedef enum {
+ DYNTABLE_COMBO_COLUMN_TEXT,
+ DYNTABLE_COMBO_COLUMN_SENSITIVE,
+ DYNTABLE_COBMO_COLUMN_NUM_COLUMNS
+} EContactEditorDynTableComboColumns;
+
+typedef struct _EContactEditorDynTable EContactEditorDynTable;
+typedef struct _EContactEditorDynTableClass EContactEditorDynTableClass;
+typedef struct _EContactEditorDynTablePrivate EContactEditorDynTablePrivate;
+
+struct _EContactEditorDynTableClass {
+ GtkGridClass parent_class;
+
+ /* Signals */
+ void (*changed) (EContactEditorDynTable* dyntable);
+ void (*activate) (EContactEditorDynTable* dyntable);
+ void (*row_added) (EContactEditorDynTable* dyntable);
+
+ /* virtual */
+
+ /* defaults to GtkEntiy */
+ GtkWidget* (*widget_create) (EContactEditorDynTable *dyntable);
+
+ /* defaults to string_is_empty(txt) */
+ gboolean (*widget_is_empty) (EContactEditorDynTable *dyntable,
+ GtkWidget *w);
+
+ /* defaults to entry_set_text("") */
+ void (*widget_clear) (EContactEditorDynTable *dyntable,
+ GtkWidget *w);
+
+ /* default impl gtk_entry_set_text
+ * other widgets may need to "parse" value before usage.
+ */
+ void (*widget_fill) (EContactEditorDynTable *dyntable,
+ GtkWidget *w,
+ const gchar *value);
+
+ /* default impl returns gtk_entry_get_text
+ * other widget may require some kind of "encoding"
+ */
+ const gchar* (*widget_extract) (EContactEditorDynTable *dyntable,
+ GtkWidget *w);
+
+};
+
+struct _EContactEditorDynTable {
+ GtkGrid parent;
+
+ EContactEditorDynTablePrivate* priv;
+};
+
+GtkWidget* e_contact_editor_dyntable_new (void);
+GType e_contact_editor_dyntable_get_type (void) G_GNUC_CONST;
+void e_contact_editor_dyntable_set_show_min (EContactEditorDynTable *dyntable,
+ guint number_of_entries);
+void e_contact_editor_dyntable_set_show_max (EContactEditorDynTable *dyntable,
+ guint number_of_entries);
+void e_contact_editor_dyntable_set_num_columns (EContactEditorDynTable *dyntable,
+ guint number_of_columns,
+ gboolean justified);
+void e_contact_editor_dyntable_set_max_entries (EContactEditorDynTable *dyntable,
+ guint max);
+
+GtkListStore* e_contact_editor_dyntable_get_combo_store (EContactEditorDynTable* dyntable);
+void e_contact_editor_dyntable_set_combo_defaults (EContactEditorDynTable* dyntable,
+ const gint *defaults,
+ size_t defaults_n);
+void e_contact_editor_dyntable_clear_data (EContactEditorDynTable *dyntable);
+void e_contact_editor_dyntable_fill_in_data (EContactEditorDynTable *dyntable);
+GtkListStore* e_contact_editor_dyntable_extract_data (EContactEditorDynTable *dyntable);
+
+G_END_DECLS
+
+#endif /* E_CONTACT_EDITOR_DYNTABLE_H_ */
diff --git a/addressbook/gui/contact-editor/e-contact-editor.c b/addressbook/gui/contact-editor/e-contact-editor.c
index aa02ab0eb6..a27f8cdb57 100644
--- a/addressbook/gui/contact-editor/e-contact-editor.c
+++ b/addressbook/gui/contact-editor/e-contact-editor.c
@@ -44,9 +44,12 @@
#include "eab-contact-merging.h"
#include "e-contact-editor-fullname.h"
+#include "e-contact-editor-dyntable.h"
+#define SLOTS_PER_LINE 2
+#define SLOTS_IN_COLLAPSED_STATE SLOTS_PER_LINE
#define EMAIL_SLOTS 4
-#define PHONE_SLOTS 8
+#define PHONE_SLOTS 50
#define IM_SLOTS 4
#define ADDRESS_SLOTS 3
@@ -1316,52 +1319,6 @@ init_item_sensitiveable_combo_box (GtkComboBox *combo)
"text", 0, "sensitive", 1, NULL);
}
-/* EContact can get attributes by field ID only,
- * and there is none for TEL, so we need this */
-static GList *
-get_attributes_named (EVCard *vcard,
- const gchar *attr_name)
-{
- GList *attr_list_in;
- GList *attr_list_out = NULL;
- GList *l;
-
- attr_list_in = e_vcard_get_attributes (vcard);
-
- for (l = attr_list_in; l; l = g_list_next (l)) {
- EVCardAttribute *attr = l->data;
- const gchar *name;
-
- name = e_vcard_attribute_get_name (attr);
-
- if (!g_ascii_strcasecmp (attr_name, name)) {
- attr_list_out = g_list_append (
- attr_list_out,
- e_vcard_attribute_copy (attr));
- }
- }
-
- return attr_list_out;
-}
-
-/* EContact can set attributes by field ID only,
- * and there is none for TEL, so we need this */
-static void
-set_attributes_named (EVCard *vcard,
- const gchar *attr_name,
- GList *attr_list)
-{
- GList *l;
-
- e_vcard_remove_attributes (vcard, NULL, attr_name);
-
- for (l = attr_list; l; l = g_list_next (l)) {
- EVCardAttribute *attr = l->data;
-
- e_vcard_add_attribute (vcard, e_vcard_attribute_copy (attr));
- }
-}
-
static void
set_arrow_image (EContactEditor *editor,
const gchar *arrow_widget,
@@ -1378,6 +1335,22 @@ set_arrow_image (EContactEditor *editor,
GTK_ARROW (arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
}
+static gboolean
+is_arrow_image_arrow_down (EContactEditor *editor,
+ const gchar *arrow_widget)
+{
+ GtkWidget *arrow;
+ gint value;
+
+ arrow = e_builder_get_widget (editor->priv->builder, arrow_widget);
+ g_object_get (arrow, "arrow-type", &value, NULL);
+
+ if (value == GTK_ARROW_DOWN)
+ return TRUE;
+
+ return FALSE;
+}
+
static void
expand_widget_list (EContactEditor *editor,
const gchar **widget_names,
@@ -1407,13 +1380,18 @@ static void
expand_phone (EContactEditor *editor,
gboolean expanded)
{
- const gchar *names[] = {
- "entry-phone-3", "combobox-phone-3",
- "entry-phone-4", "combobox-phone-4",
- "table-phone-extended", NULL
- };
+ GtkWidget *w;
+ EContactEditorDynTable *dyntable;
+
set_arrow_image (editor, "arrow-phone-expand", expanded);
- expand_widget_list (editor, names, expanded);
+
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
+ dyntable = E_CONTACT_EDITOR_DYNTABLE (w);
+
+ if (expanded)
+ e_contact_editor_dyntable_set_show_max (dyntable, PHONE_SLOTS);
+ else
+ e_contact_editor_dyntable_set_show_max (dyntable, SLOTS_IN_COLLAPSED_STATE);
}
static void
@@ -1460,89 +1438,51 @@ init_email (EContactEditor *editor)
}
static void
-fill_in_phone_record (EContactEditor *editor,
- gint record,
- const gchar *phone,
- gint phone_type)
-{
- GtkWidget *phone_type_combo_box;
- GtkWidget *phone_entry;
- gchar *widget_name;
-
- widget_name = g_strdup_printf ("combobox-phone-%d", record);
- phone_type_combo_box = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- widget_name = g_strdup_printf ("entry-phone-%d", record);
- phone_entry = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- set_combo_box_active (
- editor, GTK_COMBO_BOX (phone_type_combo_box),
- phone_type >= 0 ? phone_type : phones_default[record - 1]);
- set_entry_text (editor, GTK_ENTRY (phone_entry), phone ? phone : "");
-
- if (phone && *phone && record >= 3)
- expand_phone (editor, TRUE);
-}
-
-static void
-extract_phone_record (EContactEditor *editor,
- gint record,
- gchar **phone,
- gint *phone_type)
-{
- GtkWidget *phone_type_combo_box;
- GtkWidget *phone_entry;
- gchar *widget_name;
-
- widget_name = g_strdup_printf ("combobox-phone-%d", record);
- phone_type_combo_box = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- widget_name = g_strdup_printf ("entry-phone-%d", record);
- phone_entry = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- *phone = g_strdup (gtk_entry_get_text (GTK_ENTRY (phone_entry)));
- *phone_type = gtk_combo_box_get_active (GTK_COMBO_BOX (phone_type_combo_box));
-}
-
-static void
fill_in_phone (EContactEditor *editor)
{
GList *phone_attr_list;
GList *l;
- gint record_n;
+ GtkWidget *w;
+ EContactEditorDynTable *dyntable;
+ GtkListStore *data_store;
+ GtkTreeIter iter;
+
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
+ dyntable = E_CONTACT_EDITOR_DYNTABLE (w);
/* Clear */
- for (record_n = 1; record_n <= PHONE_SLOTS; record_n++) {
- fill_in_phone_record (editor, record_n, NULL, -1);
- }
+ e_contact_editor_dyntable_clear_data (dyntable);
/* Fill in */
- phone_attr_list = get_attributes_named (E_VCARD (editor->priv->contact), "TEL");
+ phone_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_TEL);
+ data_store = e_contact_editor_dyntable_extract_data (dyntable);
- for (record_n = 1, l = phone_attr_list;
- l && record_n <= PHONE_SLOTS; l = g_list_next (l)) {
+ for (l = phone_attr_list;l ; l = g_list_next (l)) {
EVCardAttribute *attr = l->data;
gchar *phone;
gint slot;
+ gint phone_type;
+ slot = get_ui_slot (attr);
+ phone_type = get_phone_type (attr);
phone = e_vcard_attribute_get_value (attr);
- slot = alloc_ui_slot (editor, "entry-phone", get_ui_slot (attr), PHONE_SLOTS);
- if (slot < 1)
- break;
- fill_in_phone_record (
- editor, slot, phone, get_phone_type (attr));
-
- record_n++;
+ gtk_list_store_append (data_store, &iter);
+ gtk_list_store_set (data_store,&iter,
+ DYNTABLE_STORE_COLUMN_SORTORDER, slot,
+ DYNTABLE_STORE_COLUMN_SELECTED_ITEM, phone_type,
+ DYNTABLE_STORE_COLUMN_ENTRY_STRING, phone,
+ -1);
g_free (phone);
}
+
+ e_contact_editor_dyntable_fill_in_data (dyntable);
+ g_list_free_full (phone_attr_list, (GDestroyNotify) e_vcard_attribute_free);
+
+ expand_phone (editor, TRUE);
}
static void
@@ -1552,45 +1492,54 @@ extract_phone (EContactEditor *editor)
GList *old_attr_list;
GList *ll;
gint i;
+ GtkWidget *w;
+ EContactEditorDynTable *dyntable;
+ GtkListStore *data_store;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ gboolean valid;
- for (i = 1; i <= PHONE_SLOTS; i++) {
- gchar *phone;
- gint phone_type;
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
+ dyntable = E_CONTACT_EDITOR_DYNTABLE (w);
+ data_store = e_contact_editor_dyntable_extract_data (dyntable);
+ tree_model = GTK_TREE_MODEL (data_store);
- extract_phone_record (editor, i, &phone, &phone_type);
+ valid = gtk_tree_model_get_iter_first (tree_model, &iter);
+ while (valid){
+ gint phone_type;
+ gchar *phone;
+ EVCardAttribute *attr;
- if (!STRING_IS_EMPTY (phone)) {
- EVCardAttribute *attr;
+ attr = e_vcard_attribute_new ("", "TEL");
+ gtk_tree_model_get (tree_model,&iter,
+ DYNTABLE_STORE_COLUMN_SELECTED_ITEM, &phone_type,
+ DYNTABLE_STORE_COLUMN_ENTRY_STRING, &phone,
+ -1);
- attr = e_vcard_attribute_new ("", "TEL");
+ if (phone_type >= 0) {
+ const gchar *type_1;
+ const gchar *type_2;
- if (phone_type >= 0) {
- const gchar *type_1;
- const gchar *type_2;
+ phone_index_to_type (phone_type, &type_1, &type_2);
- phone_index_to_type (phone_type, &type_1, &type_2);
+ e_vcard_attribute_add_param_with_value (
+ attr, e_vcard_attribute_param_new (EVC_TYPE), type_1);
+ if (type_2)
e_vcard_attribute_add_param_with_value (
- attr, e_vcard_attribute_param_new (EVC_TYPE), type_1);
+ attr, e_vcard_attribute_param_new (EVC_TYPE), type_2);
+ }
- if (type_2)
- e_vcard_attribute_add_param_with_value (
- attr, e_vcard_attribute_param_new (EVC_TYPE), type_2);
+ e_vcard_attribute_add_value (attr, phone);
- }
-
- e_vcard_attribute_add_value (attr, phone);
- set_ui_slot (attr, i);
+ attr_list = g_list_append (attr_list, attr);
- attr_list = g_list_append (attr_list, attr);
- }
-
- g_free (phone);
+ valid = gtk_tree_model_iter_next (tree_model, &iter);
}
/* Splice in the old attributes, minus the PHONE_SLOTS first */
- old_attr_list = get_attributes_named (E_VCARD (editor->priv->contact), "TEL");
+ old_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_TEL);
for (ll = old_attr_list, i = 1; ll && i <= PHONE_SLOTS; i++) {
e_vcard_attribute_free (ll->data);
ll = g_list_delete_link (ll, ll);
@@ -1599,81 +1548,82 @@ extract_phone (EContactEditor *editor)
old_attr_list = ll;
attr_list = g_list_concat (attr_list, old_attr_list);
- set_attributes_named (E_VCARD (editor->priv->contact), "TEL", attr_list);
+ e_contact_set_attributes (editor->priv->contact, E_CONTACT_TEL, attr_list);
- free_attr_list (attr_list);
+ g_list_free_full (attr_list, (GDestroyNotify) e_vcard_attribute_free);
}
static void
-init_phone_record_type (EContactEditor *editor,
- gint record)
+init_phone_record_type (EContactEditor *editor)
{
- GtkWidget *phone_type_combo_box;
- GtkWidget *phone_entry;
- gchar *widget_name;
- gint i;
+ GtkWidget *w;
GtkListStore *store;
+ gint i;
+ EContactEditorDynTable *dyntable;
- widget_name = g_strdup_printf ("entry-phone-%d", record);
- phone_entry = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- widget_name = g_strdup_printf ("combobox-phone-%d", record);
- phone_type_combo_box = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- init_item_sensitiveable_combo_box (GTK_COMBO_BOX (phone_type_combo_box));
-
- store = GTK_LIST_STORE (
- gtk_combo_box_get_model (
- GTK_COMBO_BOX (phone_type_combo_box)));
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
+ dyntable = E_CONTACT_EDITOR_DYNTABLE (w);
+ store = e_contact_editor_dyntable_get_combo_store (dyntable);
for (i = 0; i < G_N_ELEMENTS (phones); i++) {
GtkTreeIter iter;
gtk_list_store_append (store, &iter);
- gtk_list_store_set (
- store, &iter,
- 0, e_contact_pretty_name (phones[i].field_id),
- 1, TRUE,
- -1);
+ gtk_list_store_set (store, &iter,
+ DYNTABLE_COMBO_COLUMN_TEXT, e_contact_pretty_name (phones[i].field_id),
+ DYNTABLE_COMBO_COLUMN_SENSITIVE, TRUE,
+ -1);
}
- g_signal_connect_swapped (
- phone_type_combo_box, "changed",
- G_CALLBACK (gtk_widget_grab_focus), phone_entry);
- g_signal_connect (
- phone_type_combo_box, "changed",
- G_CALLBACK (object_changed), editor);
- g_signal_connect (
- phone_entry, "changed",
- G_CALLBACK (object_changed), editor);
- g_signal_connect_swapped (
- phone_entry, "activate",
- G_CALLBACK (entry_activated), editor);
+ e_contact_editor_dyntable_set_combo_defaults (dyntable, phones_default, G_N_ELEMENTS (phones_default));
+}
+
+static void
+row_added_phone (EContactEditorDynTable *dyntable, EContactEditor *editor)
+{
+ expand_phone (editor, TRUE);
}
static void
init_phone (EContactEditor *editor)
{
- gint i;
+ GtkWidget *w;
+ EContactEditorDynTable *dyntable;
+
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
+ dyntable = E_CONTACT_EDITOR_DYNTABLE (w);
- expand_phone (editor, FALSE);
+ e_contact_editor_dyntable_set_max_entries (dyntable, PHONE_SLOTS);
+ e_contact_editor_dyntable_set_num_columns (dyntable, SLOTS_PER_LINE, TRUE);
+ e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_PER_LINE);
- for (i = 1; i <= PHONE_SLOTS; i++)
- init_phone_record_type (editor, i);
+ g_signal_connect (
+ w, "changed",
+ G_CALLBACK (object_changed), editor);
+ g_signal_connect_swapped (
+ w, "activate",
+ G_CALLBACK (entry_activated), editor);
+ g_signal_connect (
+ w, "row-added",
+ G_CALLBACK (row_added_phone), editor);
+
+ init_phone_record_type (editor);
}
static void
-sensitize_phone_types (EContactEditor *editor,
- GtkWidget *combo_box)
+sensitize_phone_types (EContactEditor *editor)
{
+ GtkWidget *w;
+ GtkListStore *listStore;
GtkTreeModel *model;
GtkTreeIter iter;
gint i;
gboolean valid;
- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
+ listStore = e_contact_editor_dyntable_get_combo_store (E_CONTACT_EDITOR_DYNTABLE (w));
+ model = GTK_TREE_MODEL (listStore);
+
valid = gtk_tree_model_get_iter_first (model, &iter);
for (i = 0; i < G_N_ELEMENTS (phones); i++) {
@@ -1682,51 +1632,29 @@ sensitize_phone_types (EContactEditor *editor,
return;
}
- gtk_list_store_set (
- GTK_LIST_STORE (model), &iter,
- 1, is_field_supported (editor, phones[i].field_id),
- -1);
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ DYNTABLE_COMBO_COLUMN_SENSITIVE,
+ is_field_supported (editor, phones[i].field_id),
+ -1);
valid = gtk_tree_model_iter_next (model, &iter);
}
}
static void
-sensitize_phone_record (EContactEditor *editor,
- gint record,
- gboolean enabled)
-{
- GtkWidget *phone_type_combo_box;
- GtkWidget *phone_entry;
- gchar *widget_name;
-
- widget_name = g_strdup_printf ("combobox-phone-%d", record);
- phone_type_combo_box = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- widget_name = g_strdup_printf ("entry-phone-%d", record);
- phone_entry = e_builder_get_widget (editor->priv->builder, widget_name);
- g_free (widget_name);
-
- gtk_widget_set_sensitive (phone_type_combo_box, enabled);
- gtk_editable_set_editable (GTK_EDITABLE (phone_entry), enabled);
-
- sensitize_phone_types (editor, phone_type_combo_box);
-}
-
-static void
sensitize_phone (EContactEditor *editor)
{
- gint i;
+ GtkWidget *w;
+ gboolean enabled = TRUE;
- for (i = 1; i <= PHONE_SLOTS; i++) {
- gboolean enabled = TRUE;
+ w = e_builder_get_widget (editor->priv->builder, "phone-dyntable");
- if (!editor->priv->target_editable)
- enabled = FALSE;
+ if (!editor->priv->target_editable)
+ enabled = FALSE;
- sensitize_phone_record (editor, i, enabled);
- }
+ gtk_widget_set_sensitive (w, enabled);
+
+ sensitize_phone_types (editor);
}
static void
@@ -4159,11 +4087,7 @@ expand_web_toggle (EContactEditor *ce)
static void
expand_phone_toggle (EContactEditor *ce)
{
- GtkWidget *phone_ext_table;
-
- phone_ext_table = e_builder_get_widget (
- ce->priv->builder, "table-phone-extended");
- expand_phone (ce, !gtk_widget_get_visible (phone_ext_table));
+ expand_phone (ce, !is_arrow_image_arrow_down (ce, "arrow-phone-expand"));
}
static void