1
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
3
/*This file is part of GNU MlView
5
*GNU MlView is free software;
6
*you can redistribute it and/or modify it under the terms of
7
*the GNU General Public License as
8
*published by the Free Software Foundation; either version 2,
9
*or (at your option) any later version.
11
*GNU MlView is distributed in the hope
12
*that it will be useful, but WITHOUT ANY WARRANTY;
13
*without even the implied warranty of
14
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
*See the GNU General Public License for more details.
17
*You should have received a copy of the
18
*GNU General Public License along with MlView;
19
*see the file COPYING.
20
*If not, write to the Free Software Foundation,
21
*Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
*See COPYRIGHT file for copyright information.
27
#include <glade/glade.h>
29
#include "mlview-validator-window.h"
30
#include "mlview-validator.h"
32
struct _MlViewValidatorWindow {
33
MlViewXMLDocument *document;
35
GtkWidget *validation_report;
36
GtkWidget *document_label;
37
GtkWidget *status_label;
42
MlViewValidationOutput *data;
43
struct MlViewTypeIcons *icons;
49
GHashTable *references;
53
typedef struct _MlViewValidatorWindow MlViewValidatorWindow;
55
enum SchemasModelColumns {
59
SCHEMAS_MODEL_NB_COLUMNS
62
enum OutputModelColumns {
68
OUTPUT_MODEL_NB_COLUMNS
72
add_schema_to_list_store_func (MlViewSchema *a_schema,
73
MlViewValidatorWindow *a_window)
75
GtkTreeIter iter = { 0 };
76
gchar *url = NULL, *type = NULL;
77
GtkTreePath *path = NULL;
78
GtkTreeRowReference *ref = NULL;
79
enum MlViewSchemaType schema_type = SCHEMA_TYPE_UNDEF ;
80
enum MlViewStatus status = MLVIEW_OK ;
82
g_return_if_fail (a_schema);
83
g_return_if_fail (a_window);
84
g_return_if_fail (a_window->schemas.store);
85
g_return_if_fail (a_window->schemas.references);
87
url = mlview_schema_get_url (a_schema);
89
g_return_if_fail (url);
91
gtk_list_store_append (a_window->schemas.store, &iter);
93
path = gtk_tree_model_get_path
94
(GTK_TREE_MODEL (a_window->schemas.store), &iter);
97
gtk_list_store_remove (a_window->schemas.store, &iter);
102
ref = gtk_tree_row_reference_new
103
(GTK_TREE_MODEL (a_window->schemas.store), path);
105
gtk_tree_path_free (path);
109
gtk_list_store_remove (a_window->schemas.store, &iter);
114
g_hash_table_insert (a_window->schemas.references, url, ref);
116
status = mlview_schema_get_type (a_schema, &schema_type) ;
117
g_return_if_fail (status == MLVIEW_OK
118
&& schema_type != SCHEMA_TYPE_UNDEF) ;
119
switch (schema_type) {
120
case SCHEMA_TYPE_DTD:
121
type = (gchar*) "(DTD)";
123
case SCHEMA_TYPE_RNG:
124
type = (gchar*) "(RNG)";
126
case SCHEMA_TYPE_XSD:
127
type = (gchar*) "(XSD)";
130
g_assert_not_reached () ;
133
gtk_list_store_set (a_window->schemas.store, &iter, URL_COLUMN, url,
134
TYPE_COLUMN, type, SCHEMA_COLUMN, a_schema, -1);
138
document_changed_cb (MlViewValidatorWindow *a_window)
140
g_return_if_fail (a_window);
141
g_return_if_fail (a_window->status_label);
143
gtk_label_set_text (GTK_LABEL (a_window->status_label),
144
_("Document changed ; press 'Refresh'"));
148
schema_associated_cb (MlViewSchemaList *a_list, MlViewSchema *a_schema,
149
MlViewValidatorWindow *a_window)
153
g_return_if_fail (a_schema);
154
g_return_if_fail (a_window);
155
g_return_if_fail (a_window->schemas.combo);
157
add_schema_to_list_store_func (a_schema, a_window);
159
active = gtk_combo_box_get_active (GTK_COMBO_BOX
160
(a_window->schemas.combo));
163
gtk_combo_box_set_active (GTK_COMBO_BOX
164
(a_window->schemas.combo), 0);
168
schema_unassociated_cb (MlViewSchemaList *a_list, MlViewSchema *a_schema,
169
MlViewValidatorWindow *a_window)
171
GtkTreeRowReference *ref = NULL;
173
GtkTreePath *path = NULL;
174
gboolean res = FALSE;
175
GtkTreeIter iter = { 0 };
177
g_return_if_fail (a_schema);
178
g_return_if_fail (a_window);
179
g_return_if_fail (a_window->schemas.references);
180
g_return_if_fail (a_window->schemas.store);
182
url = mlview_schema_get_url (a_schema);
184
g_return_if_fail (url);
186
ref = g_hash_table_lookup (a_window->schemas.references,
189
g_return_if_fail (ref);
191
path = gtk_tree_row_reference_get_path (ref);
193
g_return_if_fail (path);
195
res = gtk_tree_model_get_iter
196
(GTK_TREE_MODEL (a_window->schemas.store), &iter, path);
198
gtk_tree_path_free (path);
201
g_return_if_fail (res);
203
res = g_hash_table_remove (a_window->schemas.references, url);
205
g_return_if_fail (res);
207
gtk_list_store_remove (a_window->schemas.store, &iter);
211
validation_report_destroy_cb (GtkWidget *a_validation_report,
212
MlViewValidatorWindow *a_window)
214
MlViewSchemaList *list = NULL;
215
MlViewAppContext *ctxt = NULL;
217
g_return_if_fail (a_window);
219
if (a_window->document) {
220
if (a_window->output.icons) {
221
ctxt = mlview_xml_document_get_app_context
222
(a_window->document);
225
mlview_app_context_type_icons_unref
229
g_signal_handlers_disconnect_by_func
230
(G_OBJECT (a_window->document),
231
G_CALLBACK (document_changed_cb),
234
list = mlview_xml_document_get_schema_list
235
(a_window->document);
238
g_signal_handlers_disconnect_by_func
240
G_CALLBACK (schema_associated_cb),
243
g_signal_handlers_disconnect_by_func
245
G_CALLBACK (schema_unassociated_cb),
250
if (a_window->schemas.references)
251
g_hash_table_destroy (a_window->schemas.references);
253
if (a_window->output.data)
254
mlview_validation_output_free (a_window->output.data);
256
memset (a_window, 0, sizeof (MlViewValidatorWindow));
263
close_button_clicked_cb (GtkWidget *a_button,
264
MlViewValidatorWindow *a_window)
266
g_return_if_fail (a_window);
267
g_return_if_fail (a_window->validation_report);
269
gtk_widget_destroy (a_window->validation_report);
273
validate_button_clicked_cb (GtkWidget *a_button,
274
MlViewValidatorWindow *a_window)
276
GtkTreeIter iter = { 0 };
277
gboolean res = FALSE;
278
GtkWidget *dialog = NULL,
280
MlViewSchema *schema = NULL;
281
MlViewValidatorStatus status = VALIDATOR_ERROR;
283
MlViewValidationMessage *message = NULL;
284
MlViewAppContext *ctxt = NULL;
285
GdkPixbuf *pix = NULL;
286
gchar *priority = NULL;
288
g_return_if_fail (a_window);
289
g_return_if_fail (a_window->document);
290
g_return_if_fail (a_window->schemas.combo);
291
g_return_if_fail (a_window->schemas.store);
292
g_return_if_fail (a_window->output.view);
293
g_return_if_fail (a_window->validation_report);
294
g_return_if_fail (a_window->status_label);
296
res = gtk_combo_box_get_active_iter
297
(GTK_COMBO_BOX (a_window->schemas.combo), &iter);
300
dialog = gtk_dialog_new_with_buttons (_("No schema selected"),
301
GTK_WINDOW (a_window->validation_report),
310
label = gtk_label_new
311
(_("You must associate a schema with your document in order to validate it."));
316
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), label);
318
g_signal_connect (G_OBJECT (dialog), "response",
319
G_CALLBACK (gtk_widget_destroy), NULL);
321
gtk_widget_show_all (dialog);
329
if (!a_window->output.icons) {
330
ctxt = mlview_xml_document_get_app_context (a_window->document);
332
g_return_if_fail (ctxt);
334
a_window->output.icons = mlview_app_context_type_icons_ref (ctxt);
337
gtk_tree_model_get (GTK_TREE_MODEL (a_window->schemas.store), &iter,
338
SCHEMA_COLUMN, &schema, -1);
340
g_return_if_fail (schema);
342
if (a_window->output.data) {
343
mlview_validation_output_free (a_window->output.data);
344
a_window->output.data = NULL;
347
a_window->output.data = mlview_validator_validate_with_schema
348
(a_window->document, schema, &status);
350
g_return_if_fail (a_window->output.data);
353
case VALIDATOR_ERROR:
354
gtk_label_set_text (GTK_LABEL (a_window->status_label),
355
_("Validation error"));
357
case VALIDATOR_VALID_DOC:
358
gtk_label_set_text (GTK_LABEL (a_window->status_label),
359
_("Valid document"));
361
case VALIDATOR_INVALID_DOC:
362
gtk_label_set_text (GTK_LABEL (a_window->status_label),
363
_("Invalid document"));
367
a_window->output.store = gtk_list_store_new
368
(OUTPUT_MODEL_NB_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
369
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
371
g_return_if_fail (a_window->output.store);
373
for (i = 0 ; i < a_window->output.data->messages->len ; i++) {
374
message = g_array_index (a_window->output.data->messages,
375
MlViewValidationMessage*, i);
378
g_object_unref (G_OBJECT (a_window->output.store));
379
a_window->output.store = NULL;
381
mlview_utils_trace_info ("validate_button_clicked_cb failed.");
386
gtk_list_store_append (a_window->output.store, &iter);
388
if (a_window->output.icons)
389
switch (message->type) {
390
case XML_ELEMENT_NODE:
391
pix = a_window->output.icons->element;
394
pix = a_window->output.icons->text;
396
case XML_COMMENT_NODE:
397
pix = a_window->output.icons->comment;
400
pix = a_window->output.icons->pi;
402
case XML_ENTITY_REF_NODE:
403
pix = a_window->output.icons->entity_ref;
410
switch (message->priority) {
412
priority = _("Message");
414
case XML_ERR_WARNING:
415
priority = _("Warning");
418
priority = _("Error");
421
priority = _("Fatal");
428
gtk_list_store_set (a_window->output.store, &iter,
430
LEVEL_COLUMN, priority,
431
NODE_COLUMN, message->node->name,
432
ERROR_COLUMN, message->message,
433
MESSAGE_COLUMN, message, -1);
436
gtk_tree_view_set_model (GTK_TREE_VIEW (a_window->output.view),
437
GTK_TREE_MODEL (a_window->output.store));
443
gtk_widget_destroy (label);
448
gtk_widget_destroy (dialog);
452
mlview_utils_trace_info ("validate_button_clicked_cb failed.");
456
row_activated_cb (GtkTreeView *a_view,
458
GtkTreeViewColumn *a_column,
459
MlViewValidatorWindow *a_win)
461
GtkTreeIter iter = { 0 };
462
gboolean res = FALSE;
463
MlViewValidationMessage *message = NULL;
464
GtkWidget *dialog = NULL, *label = NULL;
466
g_return_if_fail (a_win);
467
g_return_if_fail (a_path);
468
g_return_if_fail (a_win->output.store);
469
g_return_if_fail (GTK_IS_TREE_MODEL (a_win->output.store));
470
g_return_if_fail (a_win->document);
471
g_return_if_fail (a_win->validation_report);
473
res = gtk_tree_model_get_iter (GTK_TREE_MODEL (a_win->output.store),
476
g_return_if_fail (res);
478
gtk_tree_model_get (GTK_TREE_MODEL (a_win->output.store), &iter,
479
MESSAGE_COLUMN, &message, -1);
481
g_return_if_fail (message);
484
mlview_xml_document_select_node (a_win->document,
487
dialog = gtk_dialog_new_with_buttons
488
(_("No node for message"),
489
GTK_WINDOW (a_win->validation_report),
495
g_return_if_fail (dialog);
497
label = gtk_label_new
498
(_("No existing node is associated with this message."));
503
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
506
gtk_widget_show (label);
508
gtk_dialog_run (GTK_DIALOG (dialog));
512
gtk_widget_destroy (dialog);
519
mlview_validator_window_new (MlViewXMLDocument *a_doc)
521
gchar *file = NULL, *uri = NULL;
522
GladeXML *xml = NULL;
523
MlViewValidatorWindow *win = NULL;
524
MlViewSchemaList *list = NULL;
525
GtkCellRenderer *renderer = NULL;
526
GtkTreeIter iter = { 0 };
527
gboolean res = FALSE;
528
GtkTreeViewColumn *column = NULL;
530
g_return_val_if_fail (a_doc && MLVIEW_IS_XML_DOCUMENT (a_doc), NULL);
532
list = mlview_xml_document_get_schema_list (a_doc);
534
g_return_val_if_fail (list, NULL);
538
win = g_try_malloc (sizeof (MlViewValidatorWindow));
543
memset (win, 0, sizeof (MlViewValidatorWindow));
545
win->document = a_doc;
549
file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_DATADIR,
550
PACKAGE "/mlview-validation-report.glade",
556
xml = glade_xml_new (file, NULL, NULL);
566
win->validation_report = glade_xml_get_widget (xml, "ValidationReport");
568
if (!(win->validation_report && GTK_IS_WINDOW (win->validation_report)))
571
win->document_label = glade_xml_get_widget (xml, "DocumentLabel");
573
if (!(win->document_label && GTK_IS_LABEL (win->document_label)))
576
uri = mlview_xml_document_get_uri (a_doc);
579
gtk_label_set_text (GTK_LABEL (win->document_label), uri);
584
win->schemas.combo = glade_xml_get_widget (xml, "SchemasCombo");
586
if (!(win->schemas.combo && GTK_IS_COMBO_BOX (win->schemas.combo)))
589
win->status_label = glade_xml_get_widget (xml, "StatusLabel");
591
if (!(win->status_label && GTK_IS_LABEL (win->status_label)))
596
win->output.view = glade_xml_get_widget (xml, "OutputView");
598
if (!(win->output.view && GTK_IS_TREE_VIEW (win->output.view)))
601
g_signal_connect (G_OBJECT (win->output.view), "row-activated",
602
G_CALLBACK (row_activated_cb), win);
604
win->output.store = gtk_list_store_new
605
(OUTPUT_MODEL_NB_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
606
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
608
if (!win->output.store)
611
gtk_tree_view_set_model (GTK_TREE_VIEW (win->output.view),
612
GTK_TREE_MODEL (win->output.store));
614
g_object_unref (G_OBJECT (win->output.store));
616
column = gtk_tree_view_column_new ();
621
gtk_tree_view_column_set_title (column, _("Node"));
623
renderer = gtk_cell_renderer_pixbuf_new ();
628
gtk_tree_view_column_pack_start (column, renderer, FALSE);
630
gtk_tree_view_column_set_attributes (column, renderer, "pixbuf",
635
renderer = gtk_cell_renderer_text_new ();
637
gtk_tree_view_column_pack_start (column, renderer, FALSE);
639
gtk_tree_view_column_set_attributes (column, renderer, "text",
644
gtk_tree_view_append_column (GTK_TREE_VIEW (win->output.view),
649
column = gtk_tree_view_column_new ();
654
gtk_tree_view_column_set_title (column, _("Priority"));
656
renderer = gtk_cell_renderer_text_new ();
661
gtk_tree_view_column_pack_start (column, renderer, FALSE);
663
gtk_tree_view_column_set_attributes (column, renderer, "text",
668
gtk_tree_view_append_column (GTK_TREE_VIEW (win->output.view),
673
column = gtk_tree_view_column_new ();
678
gtk_tree_view_column_set_title (column, _("Message"));
680
renderer = gtk_cell_renderer_text_new ();
685
gtk_tree_view_column_pack_start (column, renderer, FALSE);
687
gtk_tree_view_column_set_attributes (column, renderer, "text",
692
gtk_tree_view_append_column (GTK_TREE_VIEW (win->output.view),
699
glade_xml_signal_connect_data (xml, "validate_button_clicked_cb",
700
G_CALLBACK (validate_button_clicked_cb),
703
glade_xml_signal_connect_data (xml, "close_button_clicked_cb",
704
G_CALLBACK (close_button_clicked_cb),
707
g_signal_connect (G_OBJECT (win->validation_report), "destroy",
708
G_CALLBACK (validation_report_destroy_cb), win);
712
win->schemas.references = g_hash_table_new_full
713
(g_str_hash, g_str_equal, NULL, (GDestroyNotify) gtk_tree_row_reference_free);
715
if (!win->schemas.references)
718
win->schemas.store = gtk_list_store_new (SCHEMAS_MODEL_NB_COLUMNS, G_TYPE_STRING,
719
G_TYPE_STRING, G_TYPE_POINTER);
721
if (!win->schemas.store)
724
mlview_schema_list_foreach (list, (MlViewSchemaListFunc) add_schema_to_list_store_func,
727
gtk_combo_box_set_model (GTK_COMBO_BOX (win->schemas.combo),
728
GTK_TREE_MODEL (win->schemas.store));
730
g_object_unref (G_OBJECT (win->schemas.store));
732
res = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (win->schemas.store), &iter);
735
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (win->schemas.combo), &iter);
737
renderer = gtk_cell_renderer_text_new ();
742
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (win->schemas.combo), renderer, TRUE);
744
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->schemas.combo), renderer,
745
"text", URL_COLUMN, NULL);
747
renderer = gtk_cell_renderer_text_new ();
752
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (win->schemas.combo), renderer, FALSE);
754
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->schemas.combo), renderer,
755
"text", TYPE_COLUMN, NULL);
759
g_signal_connect (G_OBJECT (list), "schema-associated",
760
G_CALLBACK (schema_associated_cb), win);
762
g_signal_connect (G_OBJECT (list), "schema-unassociated",
763
G_CALLBACK (schema_unassociated_cb), win);
767
g_signal_connect_swapped (G_OBJECT (a_doc), "node-changed",
768
G_CALLBACK (document_changed_cb), win);
770
g_signal_connect_swapped (G_OBJECT (a_doc), "document-changed",
771
G_CALLBACK (document_changed_cb), win);
773
/* Return, cleanup */
775
return win->validation_report;
779
gtk_object_destroy (GTK_OBJECT (renderer));
784
gtk_object_destroy (GTK_OBJECT (column));
794
g_object_unref (xml);
799
if (win->validation_report) {
800
gtk_widget_destroy (win->validation_report);
802
memset (win, 0, sizeof (MlViewValidatorWindow));
805
if (win->schemas.references) {
806
g_hash_table_destroy (win->schemas.references);
807
win->schemas.references = NULL;