When invalid regex is enter, show an error icon and tooltip with error message

This commit is contained in:
Yevgen Muntyan 2011-01-19 01:38:24 -08:00
parent ea7ca1b365
commit cbd0d33735
5 changed files with 221 additions and 55 deletions

View File

@ -131,7 +131,7 @@ moo_edit_action_set_file_filter (MooEditAction *action,
_moo_edit_filter_free (action->priv->file_filter);
if (string && string[0])
action->priv->file_filter = _moo_edit_filter_new (string);
action->priv->file_filter = _moo_edit_filter_new (string, MOO_EDIT_FILTER_ACTION);
else
action->priv->file_filter = NULL;

View File

@ -36,7 +36,8 @@ MOO_DEBUG_INIT(filters, FALSE)
typedef enum {
MOO_EDIT_FILTER_LANGS,
MOO_EDIT_FILTER_GLOBS,
MOO_EDIT_FILTER_REGEX
MOO_EDIT_FILTER_REGEX,
MOO_EDIT_FILTER_INVALID
} MooEditFilterType;
struct MooEditFilter {
@ -45,6 +46,7 @@ struct MooEditFilter {
GSList *langs;
GSList *globs;
GRegex *regex;
char *string;
} u;
};
@ -60,8 +62,15 @@ typedef struct {
static FilterSettingsStore *settings_store;
static char *filter_settings_store_get_setting (FilterSettingsStore *store,
MooEdit *doc);
static char *filter_settings_store_get_setting (FilterSettingsStore *store,
MooEdit *doc);
static MooEditFilter *moo_edit_filter_new_langs (const char *string,
GError **error);
static MooEditFilter *moo_edit_filter_new_regex (const char *string,
GError **error);
static MooEditFilter *moo_edit_filter_new_globs (const char *string,
GError **error);
static char *
moo_edit_filter_get_string (MooEditFilter *filter,
@ -87,6 +96,8 @@ moo_edit_filter_get_string (MooEditFilter *filter,
case MOO_EDIT_FILTER_REGEX:
g_string_append (str, "regex:");
break;
case MOO_EDIT_FILTER_INVALID:
break;
}
}
@ -104,34 +115,57 @@ moo_edit_filter_get_string (MooEditFilter *filter,
case MOO_EDIT_FILTER_REGEX:
g_string_append (str, g_regex_get_pattern (filter->u.regex));
break;
case MOO_EDIT_FILTER_INVALID:
g_string_append (str, filter->u.string);
break;
}
return g_string_free (str, FALSE);
}
static MooEditFilter *
_moo_edit_filter_new_full (const char *string,
gboolean default_regex)
MooEditFilter *
_moo_edit_filter_new_full (const char *string,
MooEditFilterKind kind,
GError **error)
{
g_return_val_if_fail (string && string[0], NULL);
if (!strncmp (string, "langs:", strlen ("langs:")))
return _moo_edit_filter_new_langs (string + strlen ("langs:"));
return moo_edit_filter_new_langs (string + strlen ("langs:"), error);
if (!strncmp (string, "globs:", strlen ("globs:")))
return _moo_edit_filter_new_globs (string + strlen ("globs:"));
return moo_edit_filter_new_globs (string + strlen ("globs:"), error);
if (!strncmp (string, "regex:", strlen ("regex:")))
return _moo_edit_filter_new_regex (string + strlen ("regex:"));
return moo_edit_filter_new_regex (string + strlen ("regex:"), error);
if (default_regex)
return _moo_edit_filter_new_regex (string);
else
return _moo_edit_filter_new_globs (string);
switch (kind)
{
case MOO_EDIT_FILTER_CONFIG:
return moo_edit_filter_new_regex (string, error);
case MOO_EDIT_FILTER_ACTION:
return moo_edit_filter_new_globs (string, error);
}
g_return_val_if_reached (NULL);
}
MooEditFilter *
_moo_edit_filter_new (const char *string)
_moo_edit_filter_new (const char *string,
MooEditFilterKind kind)
{
return _moo_edit_filter_new_full (string, FALSE);
GError *error = NULL;
MooEditFilter *filter;
g_return_val_if_fail (string != NULL, NULL);
filter = _moo_edit_filter_new_full (string, kind, &error);
if (error)
{
g_warning ("could not parse filter '%s': %s", string, error->message);
g_error_free (error);
}
return filter;
}
static GSList *
@ -160,12 +194,13 @@ _moo_edit_parse_langs (const char *string)
return g_slist_reverse (list);
}
MooEditFilter *
_moo_edit_filter_new_langs (const char *string)
static MooEditFilter *
moo_edit_filter_new_langs (const char *string,
GError **error)
{
MooEditFilter *filt;
g_return_val_if_fail (string != NULL, NULL);
moo_return_error_if_fail_p (string != NULL);
filt = g_new0 (MooEditFilter, 1);
filt->type = MOO_EDIT_FILTER_LANGS;
@ -174,28 +209,38 @@ _moo_edit_filter_new_langs (const char *string)
return filt;
}
MooEditFilter *
_moo_edit_filter_new_regex (const char *string)
static MooEditFilter *
moo_edit_regex_new_invalid (const char *string,
GError **error)
{
MooEditFilter *filt;
moo_return_error_if_fail_p (string != NULL);
filt = g_new0 (MooEditFilter, 1);
filt->type = MOO_EDIT_FILTER_INVALID;
filt->u.string = g_strdup (string);
return filt;
}
static MooEditFilter *
moo_edit_filter_new_regex (const char *string,
GError **error)
{
MooEditFilter *filt;
GRegex *regex;
GError *error = NULL;
g_return_val_if_fail (string != NULL, NULL);
moo_return_error_if_fail_p (string != NULL);
regex = g_regex_new (string, G_REGEX_OPTIMIZE
#ifdef __WIN32__
| G_REGEX_CASELESS
#endif
, 0, &error);
, 0, error);
if (!regex)
{
g_warning ("%s: invalid regex '%s': %s", G_STRFUNC,
string, error->message);
g_error_free (NULL);
return NULL;
}
return moo_edit_regex_new_invalid (string, NULL);
filt = g_new0 (MooEditFilter, 1);
filt->type = MOO_EDIT_FILTER_REGEX;
@ -230,12 +275,13 @@ parse_globs (const char *string)
return g_slist_reverse (list);
}
MooEditFilter *
_moo_edit_filter_new_globs (const char *string)
static MooEditFilter *
moo_edit_filter_new_globs (const char *string,
GError **error)
{
MooEditFilter *filt;
g_return_val_if_fail (string != NULL, NULL);
moo_return_error_if_fail_p (string != NULL);
filt = g_new0 (MooEditFilter, 1);
filt->type = MOO_EDIT_FILTER_GLOBS;
@ -244,6 +290,13 @@ _moo_edit_filter_new_globs (const char *string)
return filt;
}
gboolean
_moo_edit_filter_valid (MooEditFilter *filter)
{
g_return_val_if_fail (filter != NULL, FALSE);
return filter->type != MOO_EDIT_FILTER_INVALID;
}
void
_moo_edit_filter_free (MooEditFilter *filter)
{
@ -260,6 +313,9 @@ _moo_edit_filter_free (MooEditFilter *filter)
if (filter->u.regex)
g_regex_unref (filter->u.regex);
break;
case MOO_EDIT_FILTER_INVALID:
g_free (filter->u.string);
break;
}
g_free (filter);
@ -334,6 +390,8 @@ _moo_edit_filter_match (MooEditFilter *filter,
return moo_edit_filter_check_langs (filter->u.langs, doc);
case MOO_EDIT_FILTER_REGEX:
return moo_edit_filter_check_regex (filter->u.regex, doc);
case MOO_EDIT_FILTER_INVALID:
return FALSE;
}
g_return_val_if_reached (FALSE);
@ -362,7 +420,7 @@ filter_setting_new (const char *filter,
g_return_val_if_fail (config != NULL, NULL);
setting = g_new0 (FilterSetting, 1);
setting->filter = _moo_edit_filter_new_full (filter, TRUE);
setting->filter = _moo_edit_filter_new (filter, MOO_EDIT_FILTER_CONFIG);
setting->config = g_strdup (config);
if (!setting->filter)

View File

@ -27,20 +27,27 @@ G_BEGIN_DECLS
typedef struct MooEditFilter MooEditFilter;
MooEditFilter *_moo_edit_filter_new (const char *string);
MooEditFilter *_moo_edit_filter_new_langs (const char *string);
MooEditFilter *_moo_edit_filter_new_regex (const char *string);
MooEditFilter *_moo_edit_filter_new_globs (const char *string);
void _moo_edit_filter_free (MooEditFilter *filter);
gboolean _moo_edit_filter_match (MooEditFilter *filter,
MooEdit *doc);
typedef enum {
MOO_EDIT_FILTER_CONFIG,
MOO_EDIT_FILTER_ACTION
} MooEditFilterKind;
MooEditFilter *_moo_edit_filter_new (const char *string,
MooEditFilterKind kind);
MooEditFilter *_moo_edit_filter_new_full (const char *string,
MooEditFilterKind kind,
GError **error);
gboolean _moo_edit_filter_valid (MooEditFilter *filter);
void _moo_edit_filter_free (MooEditFilter *filter);
gboolean _moo_edit_filter_match (MooEditFilter *filter,
MooEdit *doc);
void _moo_edit_filter_settings_load (void);
GSList *_moo_edit_filter_settings_get_strings (void);
void _moo_edit_filter_settings_set_strings (GSList *strings);
void _moo_edit_filter_settings_set_strings (GSList *strings);
char *_moo_edit_filter_settings_get_for_doc (MooEdit *doc);
char *_moo_edit_filter_settings_get_for_doc (MooEdit *doc);
G_END_DECLS

View File

@ -796,6 +796,8 @@ prefs_page_apply_lang_prefs (MooPrefsPage *page)
*/
enum {
FILTER_COLUMN_INVALID,
FILTER_COLUMN_INVALID_TOOLTIP,
FILTER_COLUMN_FILTER,
FILTER_COLUMN_CONFIG,
FILTER_NUM_COLUMNS
@ -820,6 +822,65 @@ filter_store_get_modified (gpointer store)
_moo_tree_helper_get_modified (g_object_get_data (store, "tree-helper"));
}
static gboolean
check_filter (const char *string,
char **message)
{
gboolean result;
MooEditFilter *filter;
GError *error = NULL;
if (message)
*message = NULL;
if (!string || !string[0])
return TRUE;
filter = _moo_edit_filter_new_full (string, MOO_EDIT_FILTER_CONFIG, &error);
g_return_val_if_fail (filter != NULL, FALSE);
result = _moo_edit_filter_valid (filter);
if (error && message)
*message = g_strdup (error->message);
if (error)
g_error_free (error);
_moo_edit_filter_free (filter);
return result;
}
static void
check_filter_row (GtkListStore *store,
GtkTreeIter *iter)
{
gboolean invalid;
char *filter = NULL;
char *message = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
FILTER_COLUMN_FILTER, &filter,
-1);
g_return_if_fail (filter != NULL);
invalid = !check_filter (filter, &message);
if (invalid)
gtk_list_store_set (store, iter,
FILTER_COLUMN_INVALID, TRUE,
FILTER_COLUMN_INVALID_TOOLTIP, message,
-1);
else
gtk_list_store_set (store, iter,
FILTER_COLUMN_INVALID, FALSE,
FILTER_COLUMN_INVALID_TOOLTIP, NULL,
-1);
g_free (message);
g_free (filter);
}
static void
populate_filter_settings_store (GtkListStore *store)
{
@ -832,15 +893,27 @@ populate_filter_settings_store (GtkListStore *store)
while (l)
{
GtkTreeIter iter;
const char *filter;
const char *config;
gboolean valid;
char *message = NULL;
g_return_if_fail (l->next != NULL);
filter = l->data;
config = l->next->data;
valid = check_filter (filter, &message);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
FILTER_COLUMN_FILTER, l->data,
FILTER_COLUMN_CONFIG, l->next->data,
FILTER_COLUMN_INVALID, !valid,
FILTER_COLUMN_INVALID_TOOLTIP, message,
FILTER_COLUMN_FILTER, filter,
FILTER_COLUMN_CONFIG, config,
-1);
g_free (message);
l = l->next->next;
}
@ -879,6 +952,7 @@ filter_cell_edited (GtkCellRendererText *cell,
{
gtk_list_store_set (store, &iter, column, text, -1);
filter_store_set_modified (store, TRUE);
check_filter_row (store, &iter);
}
g_free (old_text);
@ -887,18 +961,43 @@ filter_cell_edited (GtkCellRendererText *cell,
static void
create_filter_cell (GtkTreeView *treeview,
GtkListStore *store,
const char *title,
int column_id)
filter_icon_data_func (G_GNUC_UNUSED GtkTreeViewColumn *column,
GtkCellRenderer *cell,
GtkTreeModel *model,
GtkTreeIter *iter)
{
gboolean invalid;
gtk_tree_model_get (model, iter, FILTER_COLUMN_INVALID, &invalid, -1);
g_object_set (cell, "visible", invalid, NULL);
}
static void
create_filter_column (GtkTreeView *treeview,
GtkListStore *store,
const char *title,
int column_id)
{
GtkTreeViewColumn *column;
GtkCellRenderer *cell;
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (title, cell, "text", column_id, NULL);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, title);
gtk_tree_view_append_column (treeview, column);
if (column_id == FILTER_COLUMN_FILTER)
{
cell = gtk_cell_renderer_pixbuf_new ();
g_object_set (cell, "stock-id", GTK_STOCK_DIALOG_ERROR, NULL);
gtk_tree_view_column_pack_start (column, cell, FALSE);
gtk_tree_view_column_set_cell_data_func (column, cell,
(GtkTreeCellDataFunc) filter_icon_data_func,
NULL, NULL);
}
cell = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, cell, TRUE);
gtk_tree_view_column_set_attributes (column, cell, "text", column_id, NULL);
g_object_set (cell, "editable", TRUE, NULL);
g_object_set_data (G_OBJECT (cell), "filter-store-column-id", GINT_TO_POINTER (column_id));
g_signal_connect (cell, "edited", G_CALLBACK (filter_cell_edited), store);
@ -911,14 +1010,16 @@ filter_treeview_init (PrefsFiltersXml *gxml)
GtkListStore *store;
MooTreeHelper *helper;
store = gtk_list_store_new (FILTER_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
store = gtk_list_store_new (FILTER_NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
populate_filter_settings_store (store);
gtk_tree_view_set_model (gxml->filter_treeview, GTK_TREE_MODEL (store));
/* Column label on File Filters prefs page */
create_filter_cell (gxml->filter_treeview, store, C_("filter-prefs-column", "Filter"), FILTER_COLUMN_FILTER);
create_filter_column (gxml->filter_treeview, store, C_("filter-prefs-column", "Filter"), FILTER_COLUMN_FILTER);
/* Column label on File Filters prefs page */
create_filter_cell (gxml->filter_treeview, store, C_("filter-prefs-column", "Options"), FILTER_COLUMN_CONFIG);
create_filter_column (gxml->filter_treeview, store, C_("filter-prefs-column", "Options"), FILTER_COLUMN_CONFIG);
gtk_tree_view_set_tooltip_column (gxml->filter_treeview, FILTER_COLUMN_INVALID_TOOLTIP);
helper = _moo_tree_helper_new (GTK_WIDGET (gxml->filter_treeview),
GTK_WIDGET (gxml->new_filter_setting),

View File

@ -4038,7 +4038,7 @@ moo_edit_window_set_action_filter (const char *action_id,
g_return_if_fail (type < N_ACTION_CHECKS);
if (filter_string && filter_string[0])
filter = _moo_edit_filter_new (filter_string);
filter = _moo_edit_filter_new (filter_string, MOO_EDIT_FILTER_ACTION);
if (filter)
moo_edit_window_set_action_check (action_id, type,