I#2215 - Notify user when sending a mail to an external contact
Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/2215
This commit is contained in:
@ -5,5 +5,10 @@
|
||||
<_summary>List of assignments for recipient and the address to be used with it</_summary>
|
||||
<_description>The list is of format 'recipient<tab>sender', where the recipient can be part of the address only and the sender is a full email address, which should match the From address precisely.</_description>
|
||||
</key>
|
||||
<key name="account-for-recipients" type="as">
|
||||
<_default>[]</_default>
|
||||
<_summary>List of assignments for an account, which recipients it accepts</_summary>
|
||||
<_description>The list is of format 'recipient<tab>sender', where the recipient can be part of the address only and the sender is a full email address, which should match the From address precisely.</_description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
||||
@ -3,7 +3,13 @@
|
||||
<error-list domain="org.gnome.evolution.plugins.sender-validation" default="GTK_RESPONSE_YES">
|
||||
<error id="sender-validation" type="info">
|
||||
<_primary>Confirm sender address</_primary>
|
||||
<_secondary>The message contains recipient “{0}” for which it is set up to use sender account “{1}”, but the account “{2}” is used instead.</_secondary>
|
||||
<_secondary>The message contains recipient “{0}” for which it is set to use sender account “{1}”, but the account “{2}” is used instead.</_secondary>
|
||||
<button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL" _label="_Edit Message"/>
|
||||
<button response="GTK_RESPONSE_YES" _label="_Send Anyway"></button>
|
||||
</error>
|
||||
<error id="sender-validation-ar" type="info">
|
||||
<_primary>Confirm recipient address</_primary>
|
||||
<_secondary>The message contains recipient “{0}”, which does not match recipient pattern “{1}” for the account “{2}”.</_secondary>
|
||||
<button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL" _label="_Edit Message"/>
|
||||
<button response="GTK_RESPONSE_YES" _label="_Send Anyway"></button>
|
||||
</error>
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
#include "mail/em-event.h"
|
||||
#include "shell/e-shell.h"
|
||||
|
||||
#define CONF_KEY_NAME "assignments"
|
||||
#define RA_CONF_KEY_NAME "assignments"
|
||||
#define AR_CONF_KEY_NAME "account-for-recipients"
|
||||
|
||||
gint e_plugin_lib_enable (EPlugin *ep,
|
||||
gint enable);
|
||||
@ -95,10 +96,10 @@ e_sender_validation_parse_assignments (gchar **in_assignments)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
e_sender_validation_ask (GtkWindow *window,
|
||||
const gchar *recipient,
|
||||
const gchar *expected_account,
|
||||
const gchar *used_account)
|
||||
e_sender_validation_ask_ra (GtkWindow *window,
|
||||
const gchar *recipient,
|
||||
const gchar *expected_account,
|
||||
const gchar *used_account)
|
||||
{
|
||||
gint response;
|
||||
|
||||
@ -110,6 +111,22 @@ e_sender_validation_ask (GtkWindow *window,
|
||||
return response == GTK_RESPONSE_YES;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
e_sender_validation_ask_ar (GtkWindow *window,
|
||||
const gchar *recipient,
|
||||
const gchar *expected_recipient,
|
||||
const gchar *used_account)
|
||||
{
|
||||
gint response;
|
||||
|
||||
response = e_alert_run_dialog_for_args (window,
|
||||
"org.gnome.evolution.plugins.sender-validation:sender-validation-ar",
|
||||
recipient, expected_recipient, used_account,
|
||||
NULL);
|
||||
|
||||
return response == GTK_RESPONSE_YES;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
e_sender_validation_check (EMsgComposer *composer)
|
||||
{
|
||||
@ -121,9 +138,8 @@ e_sender_validation_check (EMsgComposer *composer)
|
||||
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
|
||||
|
||||
settings = e_util_ref_settings ("org.gnome.evolution.plugin.sender-validation");
|
||||
strv = g_settings_get_strv (settings, CONF_KEY_NAME);
|
||||
g_clear_object (&settings);
|
||||
|
||||
strv = g_settings_get_strv (settings, RA_CONF_KEY_NAME);
|
||||
assignments = e_sender_validation_parse_assignments (strv);
|
||||
|
||||
if (assignments) {
|
||||
@ -163,7 +179,7 @@ e_sender_validation_check (EMsgComposer *composer)
|
||||
}
|
||||
|
||||
if (!has_match && has_mismatch) {
|
||||
can_send = e_sender_validation_ask (GTK_WINDOW (composer), recipient, has_mismatch->account, from_address);
|
||||
can_send = e_sender_validation_ask_ra (GTK_WINDOW (composer), recipient, has_mismatch->account, from_address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -177,6 +193,76 @@ e_sender_validation_check (EMsgComposer *composer)
|
||||
/* Can free 'strv' only after 'assignments', because 'assignments' is using the memory from 'strv' */
|
||||
g_strfreev (strv);
|
||||
|
||||
if (!can_send) {
|
||||
g_clear_object (&settings);
|
||||
return can_send;
|
||||
}
|
||||
|
||||
strv = g_settings_get_strv (settings, AR_CONF_KEY_NAME);
|
||||
assignments = e_sender_validation_parse_assignments (strv);
|
||||
|
||||
if (assignments) {
|
||||
EComposerHeaderTable *header_table;
|
||||
const gchar *from_address;
|
||||
|
||||
header_table = e_msg_composer_get_header_table (composer);
|
||||
from_address = e_composer_header_table_get_from_address (header_table);
|
||||
|
||||
if (from_address && *from_address) {
|
||||
GSList *link, *usable_assignments = NULL;
|
||||
|
||||
for (link = assignments; link; link = g_slist_next (link)) {
|
||||
const Assignment *assignment = link->data;
|
||||
|
||||
/* one account can be in the list multiple times */
|
||||
if (camel_strstrcase (from_address, assignment->account))
|
||||
usable_assignments = g_slist_prepend (usable_assignments, (gpointer) assignment);
|
||||
}
|
||||
|
||||
usable_assignments = g_slist_reverse (usable_assignments);
|
||||
|
||||
if (usable_assignments) {
|
||||
EDestination **destinations;
|
||||
guint ii;
|
||||
|
||||
destinations = e_composer_header_table_get_destinations (header_table);
|
||||
|
||||
for (ii = 0; destinations && destinations[ii]; ii++) {
|
||||
EDestination *dest = destinations[ii];
|
||||
const gchar *recipient;
|
||||
|
||||
recipient = e_destination_get_address (dest);
|
||||
|
||||
if (recipient && *recipient) {
|
||||
const Assignment *has_mismatch = NULL;
|
||||
gboolean has_match = FALSE;
|
||||
|
||||
for (link = usable_assignments; link && !has_match; link = g_slist_next (link)) {
|
||||
const Assignment *assignment = link->data;
|
||||
|
||||
if (camel_strstrcase (recipient, assignment->recipient))
|
||||
has_match = TRUE;
|
||||
else if (!has_mismatch)
|
||||
has_mismatch = assignment;
|
||||
}
|
||||
|
||||
if (!has_match && has_mismatch) {
|
||||
can_send = e_sender_validation_ask_ar (GTK_WINDOW (composer), recipient, has_mismatch->recipient, from_address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e_destination_freev (destinations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free_full (assignments, e_sender_validation_free_assignment);
|
||||
/* Can free 'strv' only after 'assignments', because 'assignments' is using the memory from 'strv' */
|
||||
g_strfreev (strv);
|
||||
g_clear_object (&settings);
|
||||
|
||||
return can_send;
|
||||
}
|
||||
|
||||
@ -197,15 +283,25 @@ enum {
|
||||
|
||||
typedef struct {
|
||||
GSettings *settings;
|
||||
GtkWidget *treeview;
|
||||
GtkWidget *button_add;
|
||||
GtkWidget *button_edit;
|
||||
GtkWidget *button_remove;
|
||||
GtkListStore *store;
|
||||
/* 'ra' for Recipients~>Account */
|
||||
GtkWidget *ra_tree_view;
|
||||
GtkWidget *ra_button_add;
|
||||
GtkWidget *ra_button_edit;
|
||||
GtkWidget *ra_button_remove;
|
||||
GtkListStore *ra_store;
|
||||
|
||||
/* 'ar' for Account~>Recipients */
|
||||
GtkWidget *ar_tree_view;
|
||||
GtkWidget *ar_button_add;
|
||||
GtkWidget *ar_button_edit;
|
||||
GtkWidget *ar_button_remove;
|
||||
GtkListStore *ar_store;
|
||||
} UIData;
|
||||
|
||||
static void
|
||||
commit_changes (UIData *ui)
|
||||
commit_changes (UIData *ui,
|
||||
GtkWidget *tree_view,
|
||||
const gchar *conf_key)
|
||||
{
|
||||
GtkTreeModel *model = NULL;
|
||||
GVariantBuilder builder;
|
||||
@ -213,7 +309,7 @@ commit_changes (UIData *ui)
|
||||
GtkTreeIter iter;
|
||||
gboolean valid;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (ui->treeview));
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
|
||||
valid = gtk_tree_model_get_iter_first (model, &iter);
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
|
||||
@ -245,66 +341,103 @@ commit_changes (UIData *ui)
|
||||
|
||||
/* A floating GVariant is returned, which is consumed by the g_settings_set_value() */
|
||||
var = g_variant_builder_end (&builder);
|
||||
g_settings_set_value (ui->settings, CONF_KEY_NAME, var);
|
||||
g_settings_set_value (ui->settings, conf_key, var);
|
||||
}
|
||||
|
||||
static void
|
||||
column_edited (UIData *ui,
|
||||
gint column,
|
||||
gint column_index,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text)
|
||||
const gchar *new_text,
|
||||
GtkWidget *tree_view,
|
||||
const gchar *conf_key)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
|
||||
gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ui->store), &iter, path_string);
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
|
||||
gtk_tree_model_get_iter_from_string (model, &iter, path_string);
|
||||
|
||||
gtk_list_store_set (ui->store, &iter, column, new_text, -1);
|
||||
commit_changes (ui);
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter, column_index, new_text, -1);
|
||||
commit_changes (ui, tree_view, conf_key);
|
||||
}
|
||||
|
||||
static void
|
||||
recipient_edited_cb (GtkCellRendererText *cell,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text,
|
||||
UIData *ui)
|
||||
ra_recipient_edited_cb (GtkCellRendererText *cell,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text,
|
||||
UIData *ui)
|
||||
{
|
||||
column_edited (ui, RECIPIENT_COLUMN, path_string, new_text);
|
||||
column_edited (ui, RECIPIENT_COLUMN, path_string, new_text, ui->ra_tree_view, RA_CONF_KEY_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
account_edited_cb (GtkCellRendererText *cell,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text,
|
||||
UIData *ui)
|
||||
ra_account_edited_cb (GtkCellRendererText *cell,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text,
|
||||
UIData *ui)
|
||||
{
|
||||
column_edited (ui, ACCOUNT_COLUMN, path_string, new_text);
|
||||
column_edited (ui, ACCOUNT_COLUMN, path_string, new_text, ui->ra_tree_view, RA_CONF_KEY_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
button_add_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
ar_recipient_edited_cb (GtkCellRendererText *cell,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text,
|
||||
UIData *ui)
|
||||
{
|
||||
column_edited (ui, RECIPIENT_COLUMN, path_string, new_text, ui->ar_tree_view, AR_CONF_KEY_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_account_edited_cb (GtkCellRendererText *cell,
|
||||
const gchar *path_string,
|
||||
const gchar *new_text,
|
||||
UIData *ui)
|
||||
{
|
||||
column_edited (ui, ACCOUNT_COLUMN, path_string, new_text, ui->ar_tree_view, AR_CONF_KEY_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
add_clicked (GtkTreeView *tree_view,
|
||||
gint column_index)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
tree_view = GTK_TREE_VIEW (ui->treeview);
|
||||
model = gtk_tree_view_get_model (tree_view);
|
||||
|
||||
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
||||
|
||||
path = gtk_tree_model_get_path (model, &iter);
|
||||
column = gtk_tree_view_get_column (tree_view, RECIPIENT_COLUMN);
|
||||
column = gtk_tree_view_get_column (tree_view, column_index);
|
||||
gtk_tree_view_set_cursor (tree_view, path, column, TRUE);
|
||||
gtk_tree_view_row_activated (tree_view, path, column);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
button_remove_clicked (GtkButton *button,
|
||||
ra_button_add_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
{
|
||||
add_clicked (GTK_TREE_VIEW (ui->ra_tree_view), RECIPIENT_COLUMN);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_button_add_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
{
|
||||
add_clicked (GTK_TREE_VIEW (ui->ar_tree_view), ACCOUNT_COLUMN);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_clicked (UIData *ui,
|
||||
GtkTreeView *tree_view,
|
||||
GtkWidget *button_edit,
|
||||
GtkWidget *button_remove,
|
||||
const gchar *conf_key)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
@ -314,7 +447,7 @@ button_remove_clicked (GtkButton *button,
|
||||
gint len;
|
||||
|
||||
valid = FALSE;
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
|
||||
selection = gtk_tree_view_get_selection (tree_view);
|
||||
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
return;
|
||||
|
||||
@ -336,19 +469,34 @@ button_remove_clicked (GtkButton *button,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gtk_widget_set_sensitive (ui->button_edit, FALSE);
|
||||
gtk_widget_set_sensitive (ui->button_remove, FALSE);
|
||||
gtk_widget_set_sensitive (button_edit, FALSE);
|
||||
gtk_widget_set_sensitive (button_remove, FALSE);
|
||||
}
|
||||
|
||||
gtk_widget_grab_focus (ui->treeview);
|
||||
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
commit_changes (ui);
|
||||
commit_changes (ui, GTK_WIDGET (tree_view), conf_key);
|
||||
}
|
||||
|
||||
static void
|
||||
button_edit_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
ra_button_remove_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
{
|
||||
remove_clicked (ui, GTK_TREE_VIEW (ui->ra_tree_view), ui->ra_button_edit, ui->ra_button_remove, RA_CONF_KEY_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_button_remove_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
{
|
||||
remove_clicked (ui, GTK_TREE_VIEW (ui->ar_tree_view), ui->ar_button_edit, ui->ar_button_remove, AR_CONF_KEY_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
edit_clicked (UIData *ui,
|
||||
GtkTreeView *tree_view,
|
||||
gint column_index)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
@ -356,35 +504,63 @@ button_edit_clicked (GtkButton *button,
|
||||
GtkTreeIter iter;
|
||||
GtkTreeViewColumn *focus_col;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
|
||||
selection = gtk_tree_view_get_selection (tree_view);
|
||||
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
return;
|
||||
|
||||
focus_col = gtk_tree_view_get_column (GTK_TREE_VIEW (ui->treeview), RECIPIENT_COLUMN);
|
||||
focus_col = gtk_tree_view_get_column (tree_view, column_index);
|
||||
path = gtk_tree_model_get_path (model, &iter);
|
||||
|
||||
if (path) {
|
||||
gtk_tree_view_set_cursor (GTK_TREE_VIEW (ui->treeview), path, focus_col, TRUE);
|
||||
gtk_tree_view_set_cursor (tree_view, path, focus_col, TRUE);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
selection_changed_cb (GtkTreeSelection *selection,
|
||||
UIData *ui)
|
||||
ra_button_edit_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
{
|
||||
edit_clicked (ui, GTK_TREE_VIEW (ui->ra_tree_view), RECIPIENT_COLUMN);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_button_edit_clicked (GtkButton *button,
|
||||
UIData *ui)
|
||||
{
|
||||
edit_clicked (ui, GTK_TREE_VIEW (ui->ar_tree_view), ACCOUNT_COLUMN);
|
||||
}
|
||||
|
||||
static void
|
||||
selection_changed (GtkTreeSelection *selection,
|
||||
GtkWidget *button_edit,
|
||||
GtkWidget *button_remove)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
|
||||
gtk_widget_set_sensitive (ui->button_edit, TRUE);
|
||||
gtk_widget_set_sensitive (ui->button_remove, TRUE);
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
|
||||
gtk_widget_set_sensitive (button_edit, TRUE);
|
||||
gtk_widget_set_sensitive (button_remove, TRUE);
|
||||
} else {
|
||||
gtk_widget_set_sensitive (ui->button_edit, FALSE);
|
||||
gtk_widget_set_sensitive (ui->button_remove, FALSE);
|
||||
gtk_widget_set_sensitive (button_edit, FALSE);
|
||||
gtk_widget_set_sensitive (button_remove, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ra_selection_changed_cb (GtkTreeSelection *selection,
|
||||
UIData *ui)
|
||||
{
|
||||
selection_changed (selection, ui->ra_button_edit, ui->ra_button_remove);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_selection_changed_cb (GtkTreeSelection *selection,
|
||||
UIData *ui)
|
||||
{
|
||||
selection_changed (selection, ui->ar_button_edit, ui->ar_button_remove);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_ui_data (gpointer data)
|
||||
{
|
||||
@ -460,6 +636,7 @@ e_plugin_lib_get_configure_widget (EPlugin *plugin)
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *container;
|
||||
GtkWidget *scrolledwindow;
|
||||
GtkWidget *vbuttonbox;
|
||||
@ -473,6 +650,20 @@ e_plugin_lib_get_configure_widget (EPlugin *plugin)
|
||||
gtk_widget_show (vbox);
|
||||
gtk_widget_set_size_request (vbox, 385, 189);
|
||||
|
||||
label = gtk_label_new (_("Set which account should be used for certain recipient patterns.\n"
|
||||
"For example, setting recipient as “@company.org” for account “me@company.org” will warn when a recipient containing “@company.org” is not used with the “me@company.org” account."));
|
||||
g_object_set (label,
|
||||
"halign", GTK_ALIGN_START,
|
||||
"hexpand", TRUE,
|
||||
"valign", GTK_ALIGN_START,
|
||||
"vexpand", FALSE,
|
||||
"wrap", TRUE,
|
||||
"wrap-mode", PANGO_WRAP_WORD,
|
||||
"max-width-chars", 80,
|
||||
NULL);
|
||||
gtk_widget_show (label);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 6);
|
||||
|
||||
container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_widget_show (container);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), container, TRUE, TRUE, 0);
|
||||
@ -482,12 +673,12 @@ e_plugin_lib_get_configure_widget (EPlugin *plugin)
|
||||
gtk_box_pack_start (GTK_BOX (container), scrolledwindow, TRUE, TRUE, 0);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
ui->treeview = gtk_tree_view_new ();
|
||||
gtk_widget_show (ui->treeview);
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), ui->treeview);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (ui->treeview), 1);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->treeview), TRUE);
|
||||
gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (ui->treeview), FALSE);
|
||||
ui->ra_tree_view = gtk_tree_view_new ();
|
||||
gtk_widget_show (ui->ra_tree_view);
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), ui->ra_tree_view);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (ui->ra_tree_view), 1);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->ra_tree_view), TRUE);
|
||||
gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (ui->ra_tree_view), FALSE);
|
||||
|
||||
vbuttonbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
|
||||
gtk_widget_show (vbuttonbox);
|
||||
@ -495,74 +686,184 @@ e_plugin_lib_get_configure_widget (EPlugin *plugin)
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox), GTK_BUTTONBOX_START);
|
||||
gtk_box_set_spacing (GTK_BOX (vbuttonbox), 6);
|
||||
|
||||
ui->button_add = e_dialog_button_new_with_icon ("list-add", _("_Add"));
|
||||
gtk_widget_show (ui->button_add);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->button_add);
|
||||
gtk_widget_set_can_default (ui->button_add, TRUE);
|
||||
ui->ra_button_add = e_dialog_button_new_with_icon ("list-add", _("_Add"));
|
||||
gtk_widget_show (ui->ra_button_add);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->ra_button_add);
|
||||
gtk_widget_set_can_default (ui->ra_button_add, TRUE);
|
||||
|
||||
ui->button_edit = gtk_button_new_with_mnemonic (_("_Edit"));
|
||||
gtk_widget_show (ui->button_edit);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->button_edit);
|
||||
gtk_widget_set_can_default (ui->button_edit, TRUE);
|
||||
ui->ra_button_edit = gtk_button_new_with_mnemonic (_("_Edit"));
|
||||
gtk_widget_show (ui->ra_button_edit);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->ra_button_edit);
|
||||
gtk_widget_set_can_default (ui->ra_button_edit, TRUE);
|
||||
|
||||
ui->button_remove = e_dialog_button_new_with_icon ("list-remove", _("_Remove"));
|
||||
gtk_widget_show (ui->button_remove);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->button_remove);
|
||||
gtk_widget_set_can_default (ui->button_remove, TRUE);
|
||||
ui->ra_button_remove = e_dialog_button_new_with_icon ("list-remove", _("_Remove"));
|
||||
gtk_widget_show (ui->ra_button_remove);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->ra_button_remove);
|
||||
gtk_widget_set_can_default (ui->ra_button_remove, TRUE);
|
||||
|
||||
ui->settings = e_util_ref_settings ("org.gnome.evolution.plugin.sender-validation");
|
||||
ui->store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
|
||||
ui->ra_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (ui->treeview), GTK_TREE_MODEL (ui->store));
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (ui->ra_tree_view), GTK_TREE_MODEL (ui->ra_store));
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_insert_column_with_attributes (
|
||||
GTK_TREE_VIEW (ui->treeview), -1, _("Recipient Contains"),
|
||||
GTK_TREE_VIEW (ui->ra_tree_view), -1, _("Recipient Contains"),
|
||||
renderer, "text", RECIPIENT_COLUMN, NULL);
|
||||
g_object_set (renderer, "editable", TRUE, NULL);
|
||||
g_signal_connect (
|
||||
renderer, "edited",
|
||||
G_CALLBACK (recipient_edited_cb), ui);
|
||||
G_CALLBACK (ra_recipient_edited_cb), ui);
|
||||
|
||||
renderer = gtk_cell_renderer_combo_new ();
|
||||
e_sender_validation_fill_accounts (GTK_CELL_RENDERER_COMBO (renderer));
|
||||
gtk_tree_view_insert_column_with_attributes (
|
||||
GTK_TREE_VIEW (ui->treeview), -1, _("Account to Use"),
|
||||
GTK_TREE_VIEW (ui->ra_tree_view), -1, _("Account to Use"),
|
||||
renderer, "text", ACCOUNT_COLUMN, NULL);
|
||||
g_object_set (renderer, "editable", TRUE, NULL);
|
||||
g_signal_connect (
|
||||
renderer, "edited",
|
||||
G_CALLBACK (account_edited_cb), ui);
|
||||
G_CALLBACK (ra_account_edited_cb), ui);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->ra_tree_view));
|
||||
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
|
||||
g_signal_connect (
|
||||
selection, "changed",
|
||||
G_CALLBACK (selection_changed_cb), ui);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->treeview), TRUE);
|
||||
G_CALLBACK (ra_selection_changed_cb), ui);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->ra_tree_view), TRUE);
|
||||
|
||||
g_signal_connect (
|
||||
ui->button_add, "clicked",
|
||||
G_CALLBACK (button_add_clicked), ui);
|
||||
ui->ra_button_add, "clicked",
|
||||
G_CALLBACK (ra_button_add_clicked), ui);
|
||||
|
||||
g_signal_connect (
|
||||
ui->button_remove, "clicked",
|
||||
G_CALLBACK (button_remove_clicked), ui);
|
||||
gtk_widget_set_sensitive (ui->button_remove, FALSE);
|
||||
ui->ra_button_remove, "clicked",
|
||||
G_CALLBACK (ra_button_remove_clicked), ui);
|
||||
gtk_widget_set_sensitive (ui->ra_button_remove, FALSE);
|
||||
|
||||
g_signal_connect (
|
||||
ui->button_edit, "clicked",
|
||||
G_CALLBACK (button_edit_clicked), ui);
|
||||
gtk_widget_set_sensitive (ui->button_edit, FALSE);
|
||||
ui->ra_button_edit, "clicked",
|
||||
G_CALLBACK (ra_button_edit_clicked), ui);
|
||||
gtk_widget_set_sensitive (ui->ra_button_edit, FALSE);
|
||||
|
||||
strv = g_settings_get_strv (ui->settings, CONF_KEY_NAME);
|
||||
strv = g_settings_get_strv (ui->settings, RA_CONF_KEY_NAME);
|
||||
assignments = e_sender_validation_parse_assignments (strv);
|
||||
|
||||
for (link = assignments; link; link = g_slist_next (link)) {
|
||||
const Assignment *assignment = link->data;
|
||||
|
||||
gtk_list_store_append (ui->store, &iter);
|
||||
gtk_list_store_set (ui->store, &iter,
|
||||
gtk_list_store_append (ui->ra_store, &iter);
|
||||
gtk_list_store_set (ui->ra_store, &iter,
|
||||
RECIPIENT_COLUMN, assignment->recipient,
|
||||
ACCOUNT_COLUMN, assignment->account,
|
||||
-1);
|
||||
}
|
||||
|
||||
g_slist_free_full (assignments, e_sender_validation_free_assignment);
|
||||
g_strfreev (strv);
|
||||
|
||||
label = gtk_label_new (_("Set which recipient patterns can be used for certain account.\n"
|
||||
"For example, setting account “me@company.org” for recipients “@company.org” will warn when any of the recipients does not contain “@company.org” when sending with the “me@company.org” account."));
|
||||
g_object_set (label,
|
||||
"halign", GTK_ALIGN_START,
|
||||
"hexpand", TRUE,
|
||||
"valign", GTK_ALIGN_START,
|
||||
"vexpand", FALSE,
|
||||
"wrap", TRUE,
|
||||
"wrap-mode", PANGO_WRAP_WORD,
|
||||
"max-width-chars", 80,
|
||||
NULL);
|
||||
gtk_widget_show (label);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 6);
|
||||
|
||||
container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_widget_show (container);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), container, TRUE, TRUE, 0);
|
||||
|
||||
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_widget_show (scrolledwindow);
|
||||
gtk_box_pack_start (GTK_BOX (container), scrolledwindow, TRUE, TRUE, 0);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
ui->ar_tree_view = gtk_tree_view_new ();
|
||||
gtk_widget_show (ui->ar_tree_view);
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), ui->ar_tree_view);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (ui->ar_tree_view), 1);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->ar_tree_view), TRUE);
|
||||
gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (ui->ar_tree_view), FALSE);
|
||||
|
||||
vbuttonbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
|
||||
gtk_widget_show (vbuttonbox);
|
||||
gtk_box_pack_start (GTK_BOX (container), vbuttonbox, FALSE, TRUE, 0);
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox), GTK_BUTTONBOX_START);
|
||||
gtk_box_set_spacing (GTK_BOX (vbuttonbox), 6);
|
||||
|
||||
ui->ar_button_add = e_dialog_button_new_with_icon ("list-add", _("_Add"));
|
||||
gtk_widget_show (ui->ar_button_add);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->ar_button_add);
|
||||
|
||||
ui->ar_button_edit = gtk_button_new_with_mnemonic (_("_Edit"));
|
||||
gtk_widget_show (ui->ar_button_edit);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->ar_button_edit);
|
||||
gtk_widget_set_can_default (ui->ar_button_edit, TRUE);
|
||||
|
||||
ui->ar_button_remove = e_dialog_button_new_with_icon ("list-remove", _("_Remove"));
|
||||
gtk_widget_show (ui->ar_button_remove);
|
||||
gtk_container_add (GTK_CONTAINER (vbuttonbox), ui->ar_button_remove);
|
||||
gtk_widget_set_can_default (ui->ar_button_remove, TRUE);
|
||||
|
||||
ui->ar_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (ui->ar_tree_view), GTK_TREE_MODEL (ui->ar_store));
|
||||
|
||||
renderer = gtk_cell_renderer_combo_new ();
|
||||
e_sender_validation_fill_accounts (GTK_CELL_RENDERER_COMBO (renderer));
|
||||
gtk_tree_view_insert_column_with_attributes (
|
||||
GTK_TREE_VIEW (ui->ar_tree_view), -1, _("Account"),
|
||||
renderer, "text", ACCOUNT_COLUMN, NULL);
|
||||
g_object_set (renderer, "editable", TRUE, NULL);
|
||||
g_signal_connect (
|
||||
renderer, "edited",
|
||||
G_CALLBACK (ar_account_edited_cb), ui);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_insert_column_with_attributes (
|
||||
GTK_TREE_VIEW (ui->ar_tree_view), -1, _("Allow Recipients Which Contain"),
|
||||
renderer, "text", RECIPIENT_COLUMN, NULL);
|
||||
g_object_set (renderer, "editable", TRUE, NULL);
|
||||
g_signal_connect (
|
||||
renderer, "edited",
|
||||
G_CALLBACK (ar_recipient_edited_cb), ui);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->ar_tree_view));
|
||||
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
|
||||
g_signal_connect (
|
||||
selection, "changed",
|
||||
G_CALLBACK (ar_selection_changed_cb), ui);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->ar_tree_view), TRUE);
|
||||
|
||||
g_signal_connect (
|
||||
ui->ar_button_add, "clicked",
|
||||
G_CALLBACK (ar_button_add_clicked), ui);
|
||||
|
||||
g_signal_connect (
|
||||
ui->ar_button_remove, "clicked",
|
||||
G_CALLBACK (ar_button_remove_clicked), ui);
|
||||
gtk_widget_set_sensitive (ui->ar_button_remove, FALSE);
|
||||
|
||||
g_signal_connect (
|
||||
ui->ar_button_edit, "clicked",
|
||||
G_CALLBACK (ar_button_edit_clicked), ui);
|
||||
gtk_widget_set_sensitive (ui->ar_button_edit, FALSE);
|
||||
|
||||
strv = g_settings_get_strv (ui->settings, AR_CONF_KEY_NAME);
|
||||
assignments = e_sender_validation_parse_assignments (strv);
|
||||
|
||||
for (link = assignments; link; link = g_slist_next (link)) {
|
||||
const Assignment *assignment = link->data;
|
||||
|
||||
gtk_list_store_append (ui->ar_store, &iter);
|
||||
gtk_list_store_set (ui->ar_store, &iter,
|
||||
RECIPIENT_COLUMN, assignment->recipient,
|
||||
ACCOUNT_COLUMN, assignment->account,
|
||||
-1);
|
||||
|
||||
Reference in New Issue
Block a user