When we clean, don't clean the model's last element. This helps keep

2001-12-27  Jon Trowbridge  <trow@ximian.com>

	* gui/component/select-names/e-select-names.c
	(real_add_address_cb): When we clean, don't clean the model's last
	element.  This helps keep things working properly when we have
	signal-character separators.
	(section_right_click_cb): Changed to work properly with our
	EText-emitted popup signal.
	(e_select_names_add_section): Use ETexts for the recipient
	sections, rather than tables.  This lets us make them directly
	editable. (Bug #1721)

	* gui/component/select-names/e-select-names-popup.c
	(popup_info_new): Pass in a ESelectNamesTextModel, not a
	ESelectNamesModel.
	(e_select_names_popup): Adjust for the new signature for
	e_select_names_model_text_pos.

	* gui/component/select-names/e-select-names-manager.c
	(focus_out_cb): Schedule a cleaning when we focus out.
	(focus_in_cb): Cancel pending cleaning when we get focus.  This
	helps us avoid bad things happening during the fast focus out/ins
	that happen when the completion dropdown appears.
	(completion_handler): Adjust for new signatures of
	e_select_names_model_text_pos and e_select_names_model_name_pos.
	(e_select_names_manager_entry_new): Pass in our
	ESelectNamesTextModel when constructing the
	ESelectNamesCompletion.
	(e_select_names_manager_entry_free): Cancel any pending clean-ups.

	* gui/component/select-names/e-select-names-bonobo.c
	(entry_get_property_fn): Get the text off of the text model.
	Which is the only way that really makes sense when you think about
	it.

	* gui/component/select-names/e-select-names-completion.c: Added a
	copy of the associated ESelectNamesTextModel to
	ESelectNamesCompletionPrivate.  This replaces the
	ESelectNamesModel.
	(e_select_names_completion_destroy): Unref ->text_model.
	(e_select_names_completion_handle_request): Pass in our text
	model's separator info when calling e_select_names_model_text_pos.
	(e_select_names_completion_new): Pass in the text model as an arg
	instead of the model, and ref it as needed.

	* gui/component/select-names/e-select-names-text-model.c
	(e_select_names_text_model_init): Set separator as either ", " or
	",", depending on the value of the EVOLUTION_DISABLE_MAGIC_COMMA
	environment variable.
	(e_select_names_text_model_destroy): Free the separator.
	(changed_cb): Flush our cached text on changed.
	(e_select_names_text_model_set_source): Use our own changed_cb
	callback on changed, rather than just connecting up
	e_text_model_changed.
	(e_select_names_text_model_set_separator): Added.  Lets the
	separator between recipients be specified.
	(e_select_names_text_model_get_text): Cache the text we get from
	calling e_select_names_model_get_textification.
	(e_select_names_text_model_insert_length): A bunch of small
	changes to properly support generic separators, rather than
	(implicit and explicitly) assuming ", ".
	(e_select_names_text_model_delete): More small tweaks to handle
	generic separators.
	(e_select_names_text_model_get_nth_obj): Use new signature when
	calling e_select_names_model_name_pos, and use our cached text.

	* gui/component/select-names/e-select-names-model.c
	(e_select_names_model_destroy): We don't cache the text or
	addr_text anymore, so no need to free them here.
	(e_select_names_model_changed): ...and no need to reset our text
	and addr_text caches here.
	(e_select_names_model_get_textification): Take a separator as an
	arg, rather than just using ", ".  Also, no caching.
	(e_select_names_model_get_address_text): Take a separator as an
	arg, rather than just using ", ".  And no caching here either.
	(e_select_names_model_clean): Add arg that give us control over
	whether or not the last entry should get cleaned.  We need this
	when using a one-character separator, so that new destinations
	that get tacked onto the end don't get immediately cleaned away
	for being empty.
	(e_select_names_model_name_pos): Take the separator length as an
	argument, remove implicit assumption of length 2.
	(e_select_names_model_text_pos): Take the separator length as an
	argument, remove implicit assumption of length 2.CVS: ----------------------------------------------------------------------

svn path=/trunk/; revision=15221
This commit is contained in:
Jon Trowbridge
2001-12-28 03:08:27 +00:00
committed by Jon Trowbridge
parent b054d4b4e6
commit 2786536d7f
11 changed files with 290 additions and 202 deletions

View File

@ -75,11 +75,11 @@ entry_get_property_fn (BonoboPropertyBag *bag,
switch (arg_id) {
case ENTRY_PROPERTY_ID_TEXT:
{
ESelectNamesModel *model;
model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (w), "select_names_model"));
g_assert (model != NULL);
ETextModel *text_model;
text_model = E_TEXT_MODEL (gtk_object_get_data (GTK_OBJECT (w), "select_names_text_model"));
g_assert (text_model != NULL);
BONOBO_ARG_SET_STRING (arg, e_select_names_model_get_textification (model));
BONOBO_ARG_SET_STRING (arg, e_text_model_get_text (text_model));
break;
}

View File

@ -55,7 +55,7 @@ typedef struct {
struct _ESelectNamesCompletionPrivate {
ESelectNamesModel *model;
ESelectNamesTextModel *text_model;
GList *book_data;
gint books_not_ready;
@ -739,8 +739,8 @@ e_select_names_completion_destroy (GtkObject *object)
ESelectNamesCompletion *comp = E_SELECT_NAMES_COMPLETION (object);
GList *l;
if (comp->priv->model)
gtk_object_unref (GTK_OBJECT (comp->priv->model));
if (comp->priv->text_model)
gtk_object_unref (GTK_OBJECT (comp->priv->text_model));
for (l = comp->priv->book_data; l; l = l->next) {
ESelectNamesCompletionBookData *book_data = l->data;
@ -1142,8 +1142,10 @@ e_select_names_completion_handle_request (ECompletion *comp, const gchar *text,
fprintf (out, "text=\"%s\" pos=%d limit=%d\n", text, pos, limit);
}
e_select_names_model_text_pos (selcomp->priv->model, pos, &index, NULL, NULL);
str = index >= 0 ? e_select_names_model_get_string (selcomp->priv->model, index) : NULL;
e_select_names_model_text_pos (selcomp->priv->text_model->source,
selcomp->priv->text_model->seplen,
pos, &index, NULL, NULL);
str = index >= 0 ? e_select_names_model_get_string (selcomp->priv->text_model->source, index) : NULL;
if (out)
fprintf (out, "index=%d str=\"%s\"\n", index, str);
@ -1225,13 +1227,12 @@ e_select_names_completion_book_ready (EBook *book, EBookStatus status, ESelectNa
*/
ECompletion *
e_select_names_completion_new (EBook *book, ESelectNamesModel *model)
e_select_names_completion_new (EBook *book, ESelectNamesTextModel *text_model)
{
ESelectNamesCompletion *comp;
g_return_val_if_fail (book == NULL || E_IS_BOOK (book), NULL);
g_return_val_if_fail (model, NULL);
g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL);
g_return_val_if_fail (E_IS_SELECT_NAMES_TEXT_MODEL (text_model), NULL);
comp = (ESelectNamesCompletion *) gtk_type_new (e_select_names_completion_get_type ());
@ -1253,8 +1254,8 @@ e_select_names_completion_new (EBook *book, ESelectNamesModel *model)
e_select_names_completion_add_book (comp, book);
}
comp->priv->model = model;
gtk_object_ref (GTK_OBJECT (model));
comp->priv->text_model = text_model;
gtk_object_ref (GTK_OBJECT (text_model));
return E_COMPLETION (comp);
}

View File

@ -29,7 +29,7 @@
#include <gal/e-text/e-completion.h>
#include <addressbook/backend/ebook/e-book.h>
#include "e-select-names-model.h"
#include "e-select-names-text-model.h"
BEGIN_GNOME_DECLS
@ -54,12 +54,12 @@ struct _ESelectNamesCompletionClass {
};
GtkType e_select_names_completion_get_type (void);
GtkType e_select_names_completion_get_type (void);
ECompletion *e_select_names_completion_new (EBook *, ESelectNamesModel *);
void e_select_names_completion_add_book (ESelectNamesCompletion *, EBook *);
gboolean e_select_names_completion_get_match_contact_lists (ESelectNamesCompletion *);
void e_select_names_completion_set_match_contact_lists (ESelectNamesCompletion *, gboolean);
ECompletion *e_select_names_completion_new (EBook *, ESelectNamesTextModel *);
void e_select_names_completion_add_book (ESelectNamesCompletion *, EBook *);
gboolean e_select_names_completion_get_match_contact_lists (ESelectNamesCompletion *);
void e_select_names_completion_set_match_contact_lists (ESelectNamesCompletion *, gboolean);
END_GNOME_DECLS

View File

@ -51,6 +51,7 @@ typedef struct {
EEntry *entry;
ESelectNamesManager *manager;
ESelectNamesModel *model;
guint cleaning_tag;
} ESelectNamesManagerEntry;
static void e_select_names_manager_init (ESelectNamesManager *manager);
@ -136,9 +137,24 @@ get_entry_info (EEntry *entry)
static void
popup_cb (EEntry *eentry, GdkEventButton *ev, gint pos, gpointer user_data)
{
ESelectNamesManagerEntry *entry = user_data;
ESelectNamesTextModel *text_model;
e_select_names_popup (entry->model, ev, pos);
gtk_object_get (GTK_OBJECT (eentry),
"model", &text_model,
NULL);
g_assert (E_IS_SELECT_NAMES_TEXT_MODEL (text_model));
e_select_names_popup (text_model, ev, pos);
}
static gboolean
clean_cb (gpointer ptr)
{
ESelectNamesManagerEntry *entry = ptr;
e_select_names_model_clean (entry->model, TRUE);
entry->cleaning_tag = 0;
return FALSE;
}
static gint
@ -146,6 +162,11 @@ focus_in_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
{
ESelectNamesManagerEntry *entry = user_data;
if (entry->cleaning_tag) {
gtk_timeout_remove (entry->cleaning_tag);
entry->cleaning_tag = 0;
}
e_select_names_model_cancel_cardify_all (entry->model);
return FALSE;
@ -155,11 +176,13 @@ static gint
focus_out_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
{
ESelectNamesManagerEntry *entry = user_data;
gboolean visible = e_entry_completion_popup_is_visible (entry->entry);
e_select_names_model_clean (entry->model);
if (!e_entry_completion_popup_is_visible (entry->entry))
if (! visible) {
e_select_names_model_cardify_all (entry->model, entry->manager->completion_book, 100);
if (entry->cleaning_tag == 0)
entry->cleaning_tag = gtk_timeout_add (100, clean_cb, entry);
}
return FALSE;
}
@ -177,6 +200,7 @@ static void
completion_handler (EEntry *entry, ECompletionMatch *match)
{
ESelectNamesManagerEntry *mgr_entry;
ESelectNamesTextModel *text_model;
EDestination *dest;
gint i, pos, start_pos, len;
@ -191,10 +215,15 @@ completion_handler (EEntry *entry, ECompletionMatch *match)
bitch. */
gtk_object_ref (GTK_OBJECT (dest));
gtk_object_get (GTK_OBJECT (entry),
"model", &text_model,
NULL);
g_assert (E_IS_SELECT_NAMES_TEXT_MODEL (text_model));
pos = e_entry_get_position (entry);
e_select_names_model_text_pos (mgr_entry->model, pos, &i, NULL, NULL);
e_select_names_model_text_pos (mgr_entry->model, text_model->seplen, pos, &i, NULL, NULL);
e_select_names_model_replace (mgr_entry->model, i, dest);
e_select_names_model_name_pos (mgr_entry->model, i, &start_pos, &len);
e_select_names_model_name_pos (mgr_entry->model, text_model->seplen, i, &start_pos, &len);
e_entry_set_position (entry, start_pos+len);
}
@ -223,7 +252,7 @@ e_select_names_manager_entry_new (ESelectNamesManager *manager, ESelectNamesMode
gtk_object_ref (GTK_OBJECT (entry->entry));
comp = e_select_names_completion_new (NULL, model);
comp = e_select_names_completion_new (NULL, E_SELECT_NAMES_TEXT_MODEL (text_model));
if (manager->completion_book)
e_select_names_completion_add_book (E_SELECT_NAMES_COMPLETION (comp),
manager->completion_book);
@ -257,6 +286,7 @@ e_select_names_manager_entry_new (ESelectNamesManager *manager, ESelectNamesMode
gtk_object_set_data (GTK_OBJECT (entry->entry), "entry_info", entry);
gtk_object_set_data (GTK_OBJECT (entry->entry), "select_names_model", model);
gtk_object_set_data (GTK_OBJECT (entry->entry), "select_names_text_model", text_model);
gtk_object_set_data (GTK_OBJECT (entry->entry), "completion_handler", comp);
return entry;
@ -272,6 +302,9 @@ e_select_names_manager_entry_free (ESelectNamesManagerEntry *entry)
gtk_object_unref (GTK_OBJECT (entry->model));
gtk_object_unref (GTK_OBJECT (entry->entry));
if (entry->cleaning_tag)
gtk_timeout_remove (entry->cleaning_tag);
g_free (entry);
}

View File

@ -20,9 +20,6 @@
#include "e-select-names-model.h"
#include "addressbook/backend/ebook/e-card-simple.h"
#define SEPARATOR ", "
#define SEPLEN (strlen(SEPARATOR))
#define MAX_LENGTH 2047
@ -56,8 +53,6 @@ struct _ESelectNamesModelPrivate {
gchar *title;
GList *data; /* of EDestination */
gchar *text;
gchar *addr_text;
gint limit;
@ -170,9 +165,6 @@ e_select_names_model_destroy (GtkObject *object)
g_list_foreach (model->priv->data, (GFunc) gtk_object_unref, NULL);
g_list_free (model->priv->data);
g_free (model->priv->text);
g_free (model->priv->addr_text);
g_free (model->priv);
}
@ -215,12 +207,6 @@ e_select_names_model_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
static void
e_select_names_model_changed (ESelectNamesModel *model)
{
g_free (model->priv->text);
model->priv->text = NULL;
g_free (model->priv->addr_text);
model->priv->addr_text = NULL;
if (model->priv->freeze_count > 0) {
model->priv->pending_changed = TRUE;
} else {
@ -264,76 +250,78 @@ e_select_names_model_duplicate (ESelectNamesModel *old)
return model;
}
const gchar *
e_select_names_model_get_textification (ESelectNamesModel *model)
gchar *
e_select_names_model_get_textification (ESelectNamesModel *model, const char *separator)
{
gchar *text;
g_return_val_if_fail (model != NULL, NULL);
g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL);
g_return_val_if_fail (separator && *separator, NULL);
if (model->priv->text == NULL) {
if (model->priv->data == NULL) {
text = g_strdup ("");
if (model->priv->data == NULL) {
model->priv->text = g_strdup ("");
} else {
gchar **strv = g_new0 (gchar *, g_list_length (model->priv->data)+1);
gint i = 0;
GList *iter = model->priv->data;
while (iter) {
EDestination *dest = E_DESTINATION (iter->data);
strv[i] = (gchar *) e_destination_get_textrep (dest);
++i;
iter = g_list_next (iter);
}
model->priv->text = g_strjoinv (SEPARATOR, strv);
if (strlen(model->priv->text) > MAX_LENGTH) {
model->priv->text[MAX_LENGTH] = 0;
g_realloc (model->priv->text, MAX_LENGTH + 1);
}
g_free (strv);
} else {
gchar **strv = g_new0 (gchar *, g_list_length (model->priv->data)+1);
gint i = 0;
GList *iter = model->priv->data;
while (iter) {
EDestination *dest = E_DESTINATION (iter->data);
strv[i] = (gchar *) e_destination_get_textrep (dest);
++i;
iter = g_list_next (iter);
}
text = g_strjoinv (separator, strv);
if (strlen(text) > MAX_LENGTH) {
text[MAX_LENGTH] = '\0';
text = g_realloc (text, MAX_LENGTH + 1);
}
g_free (strv);
}
return model->priv->text;
return text;
}
const gchar *
e_select_names_model_get_address_text (ESelectNamesModel *model)
gchar *
e_select_names_model_get_address_text (ESelectNamesModel *model, const char *separator)
{
gchar *addr_text;
g_return_val_if_fail (model != NULL, NULL);
g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL);
g_return_val_if_fail (separator && *separator, NULL);
if (model->priv->addr_text == NULL) {
if (model->priv->data == NULL) {
if (model->priv->data == NULL) {
addr_text = g_strdup ("");
} else {
gchar **strv = g_new0 (gchar *, g_list_length (model->priv->data)+1);
gint i = 0;
GList *iter = model->priv->data;
model->priv->addr_text = g_strdup ("");
} else {
gchar **strv = g_new0 (gchar *, g_list_length (model->priv->data)+1);
gint i = 0;
GList *iter = model->priv->data;
while (iter) {
EDestination *dest = E_DESTINATION (iter->data);
strv[i] = (gchar *) e_destination_get_address (dest);
if (strv[i])
++i;
iter = g_list_next (iter);
}
model->priv->addr_text = g_strjoinv (SEPARATOR, strv);
g_free (strv);
while (iter) {
EDestination *dest = E_DESTINATION (iter->data);
strv[i] = (gchar *) e_destination_get_address (dest);
if (strv[i])
++i;
iter = g_list_next (iter);
}
addr_text = g_strjoinv (separator, strv);
g_free (strv);
}
return model->priv->addr_text;
return addr_text;
}
gint
@ -614,7 +602,7 @@ e_select_names_model_delete (ESelectNamesModel *model, gint index)
}
void
e_select_names_model_clean (ESelectNamesModel *model)
e_select_names_model_clean (ESelectNamesModel *model, gboolean clean_last_entry)
{
GList *iter, *next;
gboolean changed = FALSE;
@ -627,6 +615,10 @@ e_select_names_model_clean (ESelectNamesModel *model)
EDestination *dest;
next = g_list_next (iter);
if (next == NULL && !clean_last_entry)
break;
dest = iter->data ? E_DESTINATION (iter->data) : NULL;
if (dest == NULL || e_destination_is_empty (dest)) {
@ -705,19 +697,19 @@ e_select_names_model_merge (ESelectNamesModel *dest, ESelectNamesModel *src)
}
void
e_select_names_model_name_pos (ESelectNamesModel *model, gint index, gint *pos, gint *length)
e_select_names_model_name_pos (ESelectNamesModel *model, gint seplen, gint index, gint *pos, gint *length)
{
gint rp = 0, i, len = 0;
GList *iter;
const gchar *str;
g_return_if_fail (model != NULL);
g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model));
g_return_if_fail (seplen > 0);
i = 0;
iter = model->priv->data;
while (iter && i <= index) {
rp += len + (i > 0 ? SEPLEN : 0);
rp += len + (i > 0 ? seplen : 0);
str = e_destination_get_textrep (E_DESTINATION (iter->data));
len = str ? strlen (str) : 0;
++i;
@ -736,14 +728,14 @@ e_select_names_model_name_pos (ESelectNamesModel *model, gint index, gint *pos,
}
void
e_select_names_model_text_pos (ESelectNamesModel *model, gint pos, gint *index, gint *start_pos, gint *length)
e_select_names_model_text_pos (ESelectNamesModel *model, gint seplen, gint pos, gint *index, gint *start_pos, gint *length)
{
GList *iter;
const gchar *str;
gint len = 0, i = 0, sp = 0, adj = 0;
g_return_if_fail (model != NULL);
g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model));
g_return_if_fail (seplen > 0);
iter = model->priv->data;
@ -756,14 +748,14 @@ e_select_names_model_text_pos (ESelectNamesModel *model, gint pos, gint *index,
}
sp += len + adj + 1;
adj = 1;
adj = seplen-1;
++i;
iter = g_list_next (iter);
}
if (i != 0)
++sp; /* skip past "magic space" */
sp += seplen-1; /* skip past "magic space" */
if (iter == NULL) {
#if 0

View File

@ -46,8 +46,8 @@ GtkType e_select_names_model_get_type (void);
ESelectNamesModel *e_select_names_model_new (void);
ESelectNamesModel *e_select_names_model_duplicate (ESelectNamesModel *old);
const gchar *e_select_names_model_get_textification (ESelectNamesModel *model);
const gchar *e_select_names_model_get_address_text (ESelectNamesModel *model);
gchar *e_select_names_model_get_textification (ESelectNamesModel *model, const char *separator);
gchar *e_select_names_model_get_address_text (ESelectNamesModel *model, const char *separator);
gint e_select_names_model_count (ESelectNamesModel *model);
gint e_select_names_model_get_limit (ESelectNamesModel *model);
@ -71,10 +71,10 @@ void e_select_names_model_delete_all (ESelectNamesModel *model);
void e_select_names_model_overwrite_copy (ESelectNamesModel *dest, ESelectNamesModel *src);
void e_select_names_model_merge (ESelectNamesModel *dest, ESelectNamesModel *src);
void e_select_names_model_clean (ESelectNamesModel *model);
void e_select_names_model_clean (ESelectNamesModel *model, gboolean clean_last_entry);
void e_select_names_model_name_pos (ESelectNamesModel *model, gint index, gint *pos, gint *length);
void e_select_names_model_text_pos (ESelectNamesModel *model, gint pos, gint *index, gint *start_pos, gint *length);
void e_select_names_model_name_pos (ESelectNamesModel *model, gint seplen, gint index, gint *pos, gint *length);
void e_select_names_model_text_pos (ESelectNamesModel *model, gint seplen, gint pos, gint *index, gint *start_pos, gint *length);
void e_select_names_model_cardify (ESelectNamesModel *model, EBook *book, gint index, gint delay);
gboolean e_select_names_model_uncardify (ESelectNamesModel *model, gint index);

View File

@ -46,23 +46,23 @@
typedef struct _PopupInfo PopupInfo;
struct _PopupInfo {
ESelectNamesModel *model;
ESelectNamesTextModel *text_model;
const EDestination *dest;
gint pos;
gint index;
};
static PopupInfo *
popup_info_new (ESelectNamesModel *model, const EDestination *dest, gint pos, gint index)
popup_info_new (ESelectNamesTextModel *text_model, const EDestination *dest, gint pos, gint index)
{
PopupInfo *info = g_new0 (PopupInfo, 1);
info->model = model;
info->text_model = text_model;
info->dest = dest;
info->pos = pos;
info->index = index;
if (model)
gtk_object_ref (GTK_OBJECT (model));
if (text_model)
gtk_object_ref (GTK_OBJECT (text_model));
if (dest)
gtk_object_ref (GTK_OBJECT (dest));
@ -75,8 +75,8 @@ popup_info_free (PopupInfo *info)
{
if (info) {
if (info->model)
gtk_object_unref (GTK_OBJECT (info->model));
if (info->text_model)
gtk_object_unref (GTK_OBJECT (info->text_model));
if (info->dest)
gtk_object_unref (GTK_OBJECT (info->dest));
@ -144,7 +144,7 @@ change_email_num_cb (GtkWidget *w, gpointer user_data)
if (n != e_destination_get_email_num (info->dest)) {
dest = e_destination_new ();
e_destination_set_card (dest, e_destination_get_card (info->dest), n);
e_select_names_model_replace (info->model, info->index, dest);
e_select_names_model_replace (info->text_model->source, info->index, dest);
}
}
@ -153,7 +153,7 @@ static void
remove_recipient_cb (GtkWidget *w, gpointer user_data)
{
PopupInfo *info = (PopupInfo *) user_data;
e_select_names_model_delete (info->model, info->index);
e_select_names_model_delete (info->text_model->source, info->index);
}
static void
@ -168,7 +168,7 @@ static void
remove_all_recipients_cb (GtkWidget *w, gpointer user_data)
{
PopupInfo *info = (PopupInfo *) user_data;
e_select_names_model_delete_all (info->model);
e_select_names_model_delete_all (info->text_model->source);
}
static void
@ -511,19 +511,22 @@ popup_menu_nocard (PopupInfo *info)
}
void
e_select_names_popup (ESelectNamesModel *model, GdkEventButton *ev, gint pos)
e_select_names_popup (ESelectNamesTextModel *text_model, GdkEventButton *ev, gint pos)
{
ESelectNamesModel *model;
GtkWidget *popup;
PopupInfo *info;
const EDestination *dest;
ECard *card;
gint index;
g_return_if_fail (model && E_IS_SELECT_NAMES_MODEL (model));
g_return_if_fail (E_IS_SELECT_NAMES_TEXT_MODEL (text_model));
g_return_if_fail (ev);
g_return_if_fail (0 <= pos);
e_select_names_model_text_pos (model, pos, &index, NULL, NULL);
model = text_model->source;
e_select_names_model_text_pos (model, text_model->seplen, pos, &index, NULL, NULL);
if (index < 0 || index >= e_select_names_model_count (model))
return;
@ -533,7 +536,7 @@ e_select_names_popup (ESelectNamesModel *model, GdkEventButton *ev, gint pos)
card = e_destination_get_card (dest);
info = popup_info_new (model, dest, pos, index);
info = popup_info_new (text_model, dest, pos, index);
if (e_destination_contains_card (dest)) {
if (e_destination_is_evolution_list (dest))

View File

@ -27,9 +27,9 @@
#ifndef __E_SELECT_NAMES_POPUP_H__
#define __E_SELECT_NAMES_POPUP_H__
#include "e-select-names-model.h"
#include "e-select-names-text-model.h"
void e_select_names_popup (ESelectNamesModel *model, GdkEventButton *ev, gint pos);
void e_select_names_popup (ESelectNamesTextModel *text_model, GdkEventButton *ev, gint pos);
#endif /* __E_SELECT_NAMES_POPUP_H__ */

View File

@ -22,8 +22,6 @@
static FILE *out = NULL; /* stream for debugging spew */
#define SEPLEN 2
/* Object argument IDs */
enum {
ARG_0,
@ -140,7 +138,16 @@ dump_model (ESelectNamesTextModel *text_model)
static void
e_select_names_text_model_init (ESelectNamesTextModel *model)
{
const gchar *default_sep;
model->last_magic_comma_pos = -1;
if (getenv ("EVOLUTION_DISABLE_MAGIC_COMMA"))
default_sep = ",";
else
default_sep = ", ";
e_select_names_text_model_set_separator (model, default_sep);
}
static void
@ -149,6 +156,9 @@ e_select_names_text_model_destroy (GtkObject *object)
ESelectNamesTextModel *model;
model = E_SELECT_NAMES_TEXT_MODEL (object);
g_free (model->text);
g_free (model->sep);
e_select_names_text_model_set_source (model, NULL);
@ -195,8 +205,9 @@ resize_cb (ESelectNamesModel *source, gint index, gint old_len, gint new_len, ET
EReposDeleteShift repos_del;
EReposInsertShift repos_ins;
gint pos;
gint seplen = E_SELECT_NAMES_TEXT_MODEL (model)->seplen;
e_select_names_model_name_pos (source, index, &pos, NULL);
e_select_names_model_name_pos (source, seplen, index, &pos, NULL);
if (new_len < old_len) {
@ -215,6 +226,17 @@ resize_cb (ESelectNamesModel *source, gint index, gint old_len, gint new_len, ET
}
}
static void
changed_cb (ETextModel *model)
{
ESelectNamesTextModel *text_model = E_SELECT_NAMES_TEXT_MODEL (model);
g_free (text_model->text);
text_model->text = NULL;
e_text_model_changed (model);
}
static void
e_select_names_text_model_set_source (ESelectNamesTextModel *model,
@ -235,7 +257,7 @@ e_select_names_text_model_set_source (ESelectNamesTextModel *model,
gtk_object_ref (GTK_OBJECT (model->source));
model->source_changed_id = gtk_signal_connect_object (GTK_OBJECT(model->source),
"changed",
GTK_SIGNAL_FUNC (e_text_model_changed),
GTK_SIGNAL_FUNC (changed_cb),
GTK_OBJECT (model));
model->source_resize_id = gtk_signal_connect (GTK_OBJECT(model->source),
"resized",
@ -252,12 +274,28 @@ e_select_names_text_model_new (ESelectNamesModel *source)
return model;
}
void
e_select_names_text_model_set_separator (ESelectNamesTextModel *model, const char *sep)
{
g_return_if_fail (E_IS_SELECT_NAMES_TEXT_MODEL (model));
g_return_if_fail (sep && *sep);
g_free (model->sep);
model->sep = g_strdup (sep);
model->seplen = strlen (sep);
}
static const gchar *
e_select_names_text_model_get_text (ETextModel *model)
{
ESelectNamesTextModel *snm = E_SELECT_NAMES_TEXT_MODEL(model);
return snm ? e_select_names_model_get_textification (snm->source) : "";
if (snm == NULL)
return "";
else if (snm->text == NULL)
snm->text = e_select_names_model_get_textification (snm->source, snm->sep);
return snm->text;
}
static void
@ -278,11 +316,10 @@ e_select_names_text_model_insert (ETextModel *model, gint position, const gchar
static void
e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gchar *text, gint length)
{
ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL (model)->source;
gint i;
ESelectNamesTextModel *text_model = E_SELECT_NAMES_TEXT_MODEL (model);
ESelectNamesModel *source = text_model->source;
g_return_if_fail (model != NULL);
g_return_if_fail (E_IS_SELECT_NAMES_TEXT_MODEL (model));
gint i;
if (out) {
gchar *tmp = g_strndup (text, length);
@ -290,11 +327,11 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
g_free (tmp);
}
pos = CLAMP (pos, 0, strlen (e_select_names_model_get_textification (source)));
pos = CLAMP (pos, 0, strlen (e_select_names_model_get_textification (source, text_model->sep)));
/* We want to control all cursor motions ourselves, rather than taking hints
from the ESelectNamesModel. */
gtk_signal_handler_block (GTK_OBJECT (source), E_SELECT_NAMES_TEXT_MODEL (model)->source_resize_id);
gtk_signal_handler_block (GTK_OBJECT (source), text_model->source_resize_id);
/* We handle this one character at a time. */
@ -302,17 +339,17 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
gint index, start_pos, text_len;
gboolean inside_quote = FALSE;
E_SELECT_NAMES_TEXT_MODEL (model)->last_magic_comma_pos = -1;
text_model->last_magic_comma_pos = -1;
if (out)
fprintf (out, "processing [%c]\n", text[i]);
e_select_names_model_text_pos (source, pos, &index, &start_pos, &text_len);
e_select_names_model_text_pos (source, text_model->seplen, pos, &index, &start_pos, &text_len);
if (out)
fprintf (out, "index=%d start_pos=%d text_len=%d\n", index, start_pos, text_len);
if (text[i] == ',' && index >= 0) { /* Is this a quoted or an unquoted comma we are dealing with? */
if (text[i] == *text_model->sep && index >= 0) { /* Is this a quoted or an unquoted separator we are dealing with? */
const EDestination *dest = e_select_names_model_get_destination (source, index);
if (dest) {
const gchar *str = e_destination_get_textrep (dest);
@ -331,7 +368,7 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
}
if (text[i] == ',' && !inside_quote) {
if (text[i] == *text_model->sep && !inside_quote) {
/* This is the case of hitting , first thing in an empty entry */
if (index == -1) {
@ -361,9 +398,9 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
repos.model = model;
repos.pos = pos;
repos.len = SEPLEN;
repos.len = text_model->seplen;
e_text_model_reposition (model, e_repos_insert_shift, &repos);
pos += SEPLEN;
pos += text_model->seplen;
}
} else {
@ -385,12 +422,13 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
repos.model = model;
repos.pos = pos;
repos.len = SEPLEN;
repos.len = text_model->seplen;
e_text_model_reposition (model, e_repos_insert_shift, &repos);
pos += SEPLEN;
pos += text_model->seplen;
}
E_SELECT_NAMES_TEXT_MODEL (model)->last_magic_comma_pos = pos;
if (text_model->seplen > 1)
text_model->last_magic_comma_pos = pos;
} else {
EReposInsertShift repos;
@ -408,6 +446,7 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
this_length = 0;
} else {
/* Adjust for our "magic white space" */
/* FIXME: This code does the wrong thing if seplen > 2 */
new_str = g_strdup_printf("%c%s%s", text[i], pos < start_pos ? " " : "", str);
if (pos < start_pos)
++this_length;
@ -447,20 +486,21 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
}
}
dump_model (E_SELECT_NAMES_TEXT_MODEL (model));
dump_model (text_model);
gtk_signal_handler_unblock (GTK_OBJECT (source), E_SELECT_NAMES_TEXT_MODEL (model)->source_resize_id);
gtk_signal_handler_unblock (GTK_OBJECT (source), text_model->source_resize_id);
}
static void
e_select_names_text_model_delete (ETextModel *model, gint pos, gint length)
{
ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL (model)->source;
ESelectNamesTextModel *text_model = E_SELECT_NAMES_TEXT_MODEL (model);
ESelectNamesModel *source = text_model->source;
gint index, start_pos, text_len, offset;
if (out) {
const gchar *str = e_select_names_model_get_textification (source);
const gchar *str = e_select_names_model_get_textification (source, text_model->sep);
gint i, len;
fprintf (out, ">> delete %d at pos %d\n", length, pos);
@ -480,15 +520,14 @@ e_select_names_text_model_delete (ETextModel *model, gint pos, gint length)
if (length < 0)
return;
if (E_SELECT_NAMES_TEXT_MODEL (model)->last_magic_comma_pos == pos+1
&& length == 1) {
--pos;
if (text_model->last_magic_comma_pos == pos+1 && length == 1) {
pos -= text_model->seplen-1;
if (pos >= 0)
++length;
E_SELECT_NAMES_TEXT_MODEL (model)->last_magic_comma_pos = -1;
length = text_model->seplen;
text_model->last_magic_comma_pos = -1;
}
e_select_names_model_text_pos (source, pos, &index, &start_pos, &text_len);
e_select_names_model_text_pos (source, text_model->seplen, pos, &index, &start_pos, &text_len);
if (out)
fprintf (out, "index=%d, start_pos=%d, text_len=%d\n", index, start_pos, text_len);
@ -529,7 +568,7 @@ e_select_names_text_model_delete (ETextModel *model, gint pos, gint length)
++str2;
if (str1 && str2)
new_str = g_strdup_printf ("%s %s", str1, str2);
new_str = g_strdup_printf ("%s%s%s", str1, text_model->sep+1, str2);
else if (str1)
new_str = g_strdup (str1);
else if (str2)
@ -549,7 +588,7 @@ e_select_names_text_model_delete (ETextModel *model, gint pos, gint length)
repos.model = model;
repos.pos = pos;
repos.len = SEPLEN - 1;
repos.len = text_model->seplen;
e_text_model_reposition (model, e_repos_delete_shift, &repos);
@ -577,11 +616,11 @@ e_select_names_text_model_delete (ETextModel *model, gint pos, gint length)
repos.model = model;
repos.pos = pos;
repos.len = text_len + SEPLEN;
repos.len = text_len + text_model->seplen;
e_text_model_reposition (model, e_repos_delete_shift, &repos);
length -= text_len + SEPLEN;
length -= text_len + text_model->seplen;
if (length > 0)
e_select_names_text_model_delete (model, pos, length);
@ -644,7 +683,7 @@ e_select_names_text_model_delete (ETextModel *model, gint pos, gint length)
repos.model = model;
repos.pos = pos;
repos.len = SEPLEN;
repos.len = text_model->seplen;
e_text_model_reposition (model, e_repos_delete_shift, &repos);
}
@ -700,7 +739,8 @@ nth_obj_index (ESelectNamesModel *source, gint n)
static const gchar *
e_select_names_text_model_get_nth_obj (ETextModel *model, gint n, gint *len)
{
ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL (model)->source;
ESelectNamesTextModel *text_model = E_SELECT_NAMES_TEXT_MODEL (model);
ESelectNamesModel *source = text_model->source;
const gchar *txt;
gint i, pos;
@ -708,12 +748,13 @@ e_select_names_text_model_get_nth_obj (ETextModel *model, gint n, gint *len)
if (i < 0)
return NULL;
e_select_names_model_name_pos (source, i, &pos, len);
e_select_names_model_name_pos (source, text_model->seplen, i, &pos, len);
if (pos < 0)
return NULL;
txt = e_select_names_model_get_textification (source);
return txt + pos;
if (text_model->text == NULL)
text_model->text = e_select_names_model_get_textification (source, text_model->sep);
return text_model->text + pos;
}
static void

View File

@ -32,6 +32,11 @@ struct _ESelectNamesTextModel {
gint source_changed_id;
gint source_resize_id;
gchar *text;
gchar *sep;
gint seplen;
gint last_magic_comma_pos;
};
@ -39,7 +44,8 @@ struct _ESelectNamesTextModelClass {
ETextModelClass parent_class;
};
ETextModel *e_select_names_text_model_new (ESelectNamesModel *source);
ETextModel *e_select_names_text_model_new (ESelectNamesModel *source);
void e_select_names_text_model_set_separator (ESelectNamesTextModel *model, const char *sep);
/* Standard Gtk function */
GtkType e_select_names_text_model_get_type (void);

View File

@ -42,7 +42,7 @@
#include "e-select-names.h"
#include <addressbook/backend/ebook/e-card-simple.h>
#include "e-select-names-table-model.h"
#include "e-select-names-text-model.h"
#include <gal/widgets/e-categories-master-list-combo.h>
#include <gal/widgets/e-unicode.h>
#include <gal/e-text/e-entry.h>
@ -63,11 +63,12 @@ enum {
};
typedef struct {
char *title;
ETableModel *model;
ESelectNamesModel *source;
ESelectNames *names;
GtkWidget *label;
char *title;
ETableModel *model;
ESelectNamesModel *source;
ESelectNamesTextModel *text_model;
ESelectNames *names;
GtkWidget *label;
} ESelectNamesChild;
GtkType
@ -215,7 +216,7 @@ real_add_address_cb (int model_row, gpointer closure)
e_destination_set_card (dest, card, 0);
e_select_names_model_append (child->source, dest);
e_select_names_model_clean (child->source);
e_select_names_model_clean (child->source, FALSE);
gtk_object_unref(GTK_OBJECT(card));
}
@ -513,10 +514,11 @@ add_additional_select_names_uris (ESelectNames *e_select_names, CORBA_Environmen
Bonobo_ConfigDatabase config_db;
guint32 num_additional_uris;
int i;
gboolean flag;
config_db = addressbook_config_database (ev);
num_additional_uris = bonobo_config_get_ulong_with_default (config_db, "/Addressbook/additional_select_names_folders/num", 0, ev);
num_additional_uris = bonobo_config_get_ulong_with_default (config_db, "/Addressbook/additional_select_names_folders/num", 0, &flag);
for (i = 0; i < num_additional_uris; i ++) {
ESelectNamesFolder *e_folder;
char *config_path;
@ -775,18 +777,21 @@ button_clicked(GtkWidget *button, ESelectNamesChild *child)
real_add_address(child->names, child);
}
#if 0
static void
remove_address(ETable *table, int row, int col, GdkEvent *event, ESelectNamesChild *child)
{
e_select_names_model_delete (child->source, row);
}
#endif
struct _RightClickData {
ETable *table;
ESelectNamesChild *child;
int index;
};
typedef struct _RightClickData RightClickData;
#if 0
static GSList *selected_rows = NULL;
static void
@ -805,47 +810,38 @@ selected_rows_foreach_cb (void *row, void *data)
remove_address (NULL, GPOINTER_TO_INT (row), 0, NULL, child);
}
#endif
static void
remove_cb (GtkWidget *widget, void *data)
{
RightClickData *rcdata = (RightClickData *)data;
e_select_names_model_freeze (rcdata->child->source);
/* Build a list of selected rows */
e_table_selected_row_foreach (rcdata->table,
etable_selection_foreach_cb,
rcdata->child);
/* Now process the list we made, removing each selected row */
g_slist_foreach (selected_rows,
(GFunc)selected_rows_foreach_cb,
rcdata->child);
e_select_names_model_thaw (rcdata->child->source);
e_select_names_model_delete (rcdata->child->source, rcdata->index);
/* Free everything we've created */
g_free (rcdata);
g_slist_free (selected_rows);
selected_rows = NULL;
}
static void
section_right_click_cb (ETable *table, gint row, gint col, GdkEvent *event, ESelectNamesChild *child)
section_right_click_cb (EText *text, GdkEventButton *ev, gint pos, ESelectNamesChild *child)
{
EPopupMenu right_click_menu[] = {
{ N_("Remove"), NULL,
GTK_SIGNAL_FUNC (remove_cb), NULL, 0 },
{ NULL, NULL, NULL, 0 }
};
gint index;
RightClickData *rcdata = g_new0 (RightClickData, 1);
rcdata->table = table;
rcdata->child = child;
e_select_names_model_text_pos (child->source, child->text_model->seplen, pos, &index, NULL, NULL);
e_popup_menu_run (right_click_menu, event, 0, 0,
rcdata);
if (index != -1) {
RightClickData *rcdata = g_new0 (RightClickData, 1);
rcdata->index = index;
rcdata->child = child;
e_popup_menu_run (right_click_menu, (GdkEvent *)ev, 0, 0, rcdata);
}
}
void
@ -858,8 +854,8 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E
GtkTable *table;
char *label_text;
ETableModel *model;
GtkWidget *etable;
GtkWidget *sw;
GtkWidget *recipient_table;
if (g_hash_table_lookup(e_select_names->children, id)) {
return;
@ -872,6 +868,12 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E
child->names = e_select_names;
child->title = e_utf8_from_locale_string(_(name));
child->text_model = (ESelectNamesTextModel *) e_select_names_text_model_new (source);
e_select_names_text_model_set_separator (child->text_model, "\n");
child->source = source;
gtk_object_ref(GTK_OBJECT(child->source));
e_select_names->child_count++;
alignment = gtk_alignment_new(0, 0, 1, 0);
@ -909,27 +911,37 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E
GTK_FILL, GTK_FILL,
0, 0);
model = e_select_names_table_model_new(source);
etable = e_table_scrolled_new (model, NULL, SPEC2, NULL);
sw = gtk_scrolled_window_new (NULL, NULL);
recipient_table = e_entry_new ();
gtk_object_set (GTK_OBJECT (recipient_table),
"model", child->text_model,
"allow_newlines", TRUE,
NULL);
gtk_signal_connect (GTK_OBJECT (recipient_table),
"popup",
GTK_SIGNAL_FUNC (section_right_click_cb),
child);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), recipient_table);
#if 0
gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(etable))), "right_click",
GTK_SIGNAL_FUNC(section_right_click_cb), child);
gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(etable))), "double_click",
GTK_SIGNAL_FUNC(remove_address), child);
#endif
child->model = model;
child->source = source;
gtk_object_ref(GTK_OBJECT(child->model));
gtk_object_ref(GTK_OBJECT(child->source));
gtk_signal_connect (GTK_OBJECT (child->source),
"changed",
GTK_SIGNAL_FUNC (sync_table_and_models),
e_select_names);
gtk_widget_show(etable);
gtk_widget_show_all (sw);
gtk_table_attach(table, etable,
gtk_table_attach(table, sw,
1, 2,
e_select_names->child_count,
e_select_names->child_count + 1,