1 /*
2  * Copyright (C) 2010 Stefan Walter
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation; either version 2.1 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include "gcr/gcr-icons.h"
21 #include "gcr/gcr-parser.h"
22 
23 #include "gcr-display-view.h"
24 #include "gcr-failure-renderer.h"
25 #include "gcr-secure-entry-buffer.h"
26 
27 #include <gdk/gdk.h>
28 #include <glib/gi18n-lib.h>
29 
30 enum {
31 	PROP_0,
32 	PROP_LABEL,
33 	PROP_ATTRIBUTES
34 };
35 
36 struct _GcrFailureRendererPrivate {
37 	gchar *label;
38 	GError *error;
39 };
40 
41 static void gcr_renderer_iface_init (GcrRendererIface *iface);
42 
43 G_DEFINE_TYPE_WITH_CODE (GcrFailureRenderer, gcr_failure_renderer, G_TYPE_OBJECT,
44 	G_ADD_PRIVATE (GcrFailureRenderer);
45 	G_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, gcr_renderer_iface_init);
46 );
47 
48 static void
gcr_failure_renderer_init(GcrFailureRenderer * self)49 gcr_failure_renderer_init (GcrFailureRenderer *self)
50 {
51 	self->pv = gcr_failure_renderer_get_instance_private (self);
52 }
53 
54 static void
gcr_failure_renderer_finalize(GObject * obj)55 gcr_failure_renderer_finalize (GObject *obj)
56 {
57 	GcrFailureRenderer *self = GCR_FAILURE_RENDERER (obj);
58 
59 	g_error_free (self->pv->error);
60 	g_free (self->pv->label);
61 
62 	G_OBJECT_CLASS (gcr_failure_renderer_parent_class)->finalize (obj);
63 }
64 
65 static void
gcr_failure_renderer_set_property(GObject * obj,guint prop_id,const GValue * value,GParamSpec * pspec)66 gcr_failure_renderer_set_property (GObject *obj,
67                                    guint prop_id,
68                                    const GValue *value,
69                                    GParamSpec *pspec)
70 {
71 	GcrFailureRenderer *self = GCR_FAILURE_RENDERER (obj);
72 
73 	switch (prop_id) {
74 	case PROP_LABEL:
75 		g_free (self->pv->label);
76 		self->pv->label = g_value_dup_string (value);
77 		g_object_notify (obj, "label");
78 		gcr_renderer_emit_data_changed (GCR_RENDERER (self));
79 		break;
80 	case PROP_ATTRIBUTES:
81 		break;
82 	default:
83 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
84 		break;
85 	}
86 }
87 
88 static void
gcr_failure_renderer_get_property(GObject * obj,guint prop_id,GValue * value,GParamSpec * pspec)89 gcr_failure_renderer_get_property (GObject *obj,
90                                    guint prop_id,
91                                    GValue *value,
92                                    GParamSpec *pspec)
93 {
94 	GcrFailureRenderer *self = GCR_FAILURE_RENDERER (obj);
95 
96 	switch (prop_id) {
97 	case PROP_LABEL:
98 		g_value_take_string (value, self->pv->label);
99 		break;
100 	case PROP_ATTRIBUTES:
101 		g_value_set_boxed (value, NULL);
102 		break;
103 	default:
104 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
105 		break;
106 	}
107 }
108 
109 static void
gcr_failure_renderer_class_init(GcrFailureRendererClass * klass)110 gcr_failure_renderer_class_init (GcrFailureRendererClass *klass)
111 {
112 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
113 
114 	gobject_class->finalize = gcr_failure_renderer_finalize;
115 	gobject_class->set_property = gcr_failure_renderer_set_property;
116 	gobject_class->get_property = gcr_failure_renderer_get_property;
117 
118 	g_object_class_install_property (gobject_class, PROP_LABEL,
119 	           g_param_spec_string ("label", "Label", "Failure Label",
120 	                                "",
121 	                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
122 
123 	g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
124 	           g_param_spec_boxed ("attributes", "Attributes", "Renderer attributes",
125 	                               GCK_TYPE_ATTRIBUTES,
126 	                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
127 }
128 
129 static void
gcr_failure_renderer_render(GcrRenderer * renderer,GcrViewer * viewer)130 gcr_failure_renderer_render (GcrRenderer *renderer,
131                              GcrViewer *viewer)
132 {
133 	GcrFailureRenderer *self = GCR_FAILURE_RENDERER (renderer);
134 	GcrDisplayView *view;
135 	gchar *display;
136 	GIcon *icon;
137 
138 	if (GCR_IS_DISPLAY_VIEW (viewer)) {
139 		view = GCR_DISPLAY_VIEW (viewer);
140 
141 	} else {
142 		g_warning ("GcrFailureRenderer only works with internal specific "
143 		           "GcrViewer returned by gcr_viewer_new().");
144 		return;
145 	}
146 
147 	_gcr_display_view_begin (view, renderer);
148 
149 	if (g_error_matches (self->pv->error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED))
150 		icon = g_themed_icon_new ("dialog-warning");
151 	else
152 		icon = g_themed_icon_new ("dialog-error");
153 	_gcr_display_view_set_icon (view, renderer, icon);
154 	g_object_unref (icon);
155 
156 	_gcr_display_view_append_title (view, renderer, self->pv->label);
157 
158 	if (self->pv->label)
159 		display = g_strdup_printf (_("Could not display “%s”"), self->pv->label);
160 	else
161 		display = g_strdup (_("Could not display file"));
162 	_gcr_display_view_append_content (view, renderer, display, NULL);
163 	g_free (display);
164 
165 	if (self->pv->error->message)
166 		_gcr_display_view_append_value (view, renderer, _("Reason"),
167 		                                self->pv->error->message, FALSE);
168 
169 	_gcr_display_view_end (view, renderer);
170 }
171 
172 static void
gcr_renderer_iface_init(GcrRendererIface * iface)173 gcr_renderer_iface_init (GcrRendererIface *iface)
174 {
175 	iface->render_view = gcr_failure_renderer_render;
176 }
177 
178 /**
179  * gcr_failure_renderer_new:
180  * @label: (nullable): the label for the failure
181  * @error: the error to display
182  *
183  * Create a new renderer for an error.
184  *
185  * Returns: (transfer full) (type GcrUi.FailureRenderer): the new renderer
186  */
187 GcrRenderer *
gcr_failure_renderer_new(const gchar * label,GError * error)188 gcr_failure_renderer_new (const gchar *label,
189                           GError *error)
190 {
191 	GcrFailureRenderer *renderer;
192 
193 	renderer = g_object_new (GCR_TYPE_FAILURE_RENDERER,
194 	                         "label", label,
195 	                         NULL);
196 
197 	renderer->pv->error = g_error_copy (error);
198 	return GCR_RENDERER (renderer);
199 }
200 
201 /**
202  * gcr_failure_renderer_new_unsupported:
203  * @label: the label for the failure
204  *
205  * Create a new renderer for unsupported data.
206  *
207  * Returns: (transfer full): the new renderer
208  */
209 GcrRenderer *
gcr_failure_renderer_new_unsupported(const gchar * label)210 gcr_failure_renderer_new_unsupported (const gchar *label)
211 {
212 	GcrRenderer *renderer;
213 	GError *error;
214 
215 	error = g_error_new (GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
216 	                     _("Cannot display a file of this type."));
217 
218 	renderer = gcr_failure_renderer_new (label, error);
219 
220 	g_error_free (error);
221 	return renderer;
222 }
223