1 /*
2  * Copyright (c) 2016-2021 gnome-mpv
3  *
4  * This file is part of Celluloid.
5  *
6  * Celluloid is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Celluloid is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Celluloid.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <gdk/gdk.h>
21 #include <gio/gio.h>
22 #include <glib.h>
23 #include <glib-object.h>
24 #include <glib/gi18n.h>
25 
26 #include "celluloid-plugins-manager-item.h"
27 
28 enum
29 {
30 	PROP_0,
31 	PROP_PARENT,
32 	PROP_TITLE,
33 	PROP_PATH,
34 	N_PROPERTIES
35 };
36 
37 struct _CelluloidPluginsManagerItem
38 {
39 	GtkListBoxRow parent;
40 	GtkWindow *parent_window;
41 	gchar *title;
42 	gchar *path;
43 };
44 
45 struct _CelluloidPluginsManagerItemClass
46 {
47 	GtkListBoxRowClass parent_class;
48 };
49 
50 G_DEFINE_TYPE(CelluloidPluginsManagerItem, celluloid_plugins_manager_item, GTK_TYPE_LIST_BOX_ROW)
51 
52 static void
53 celluloid_plugins_manager_item_constructed(GObject *object);
54 
55 static void
56 celluloid_plugins_manager_item_finalize(GObject *object);
57 
58 static void
59 celluloid_plugins_manager_item_set_property(	GObject *object,
60 						guint property_id,
61 						const GValue *value,
62 						GParamSpec *pspec );
63 
64 static void
65 celluloid_plugins_manager_item_get_property(	GObject *object,
66 						guint property_id,
67 						GValue *value,
68 						GParamSpec *pspec );
69 
70 static void
71 remove_response_handler(GtkDialog *dialog, gint response_id, gpointer data);
72 
73 static void
74 remove_handler(GtkButton *button, gpointer data);
75 
76 static void
celluloid_plugins_manager_item_constructed(GObject * object)77 celluloid_plugins_manager_item_constructed(GObject *object)
78 {
79 	CelluloidPluginsManagerItem *self = CELLULOID_PLUGINS_MANAGER_ITEM(object);
80 	GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
81 	GtkWidget *title_label = gtk_label_new(self->title);
82 	GtkWidget *remove_button = gtk_button_new_with_label(_("Remove"));
83 
84 	g_signal_connect(	remove_button,
85 				"clicked",
86 				G_CALLBACK(remove_handler),
87 				self );
88 
89 	gtk_widget_set_halign(title_label, GTK_ALIGN_START);
90 	gtk_widget_set_hexpand(title_label, TRUE);
91 	gtk_widget_set_margin_start(title_label, 6);
92 	gtk_label_set_ellipsize(GTK_LABEL(title_label), PANGO_ELLIPSIZE_END);
93 	gtk_list_box_row_set_selectable(GTK_LIST_BOX_ROW(self), FALSE);
94 
95 	gtk_box_append(GTK_BOX(box), title_label);
96 	gtk_box_append(GTK_BOX(box), remove_button);
97 	gtk_list_box_row_set_child(GTK_LIST_BOX_ROW(self), box);
98 
99 	G_OBJECT_CLASS(celluloid_plugins_manager_item_parent_class)
100 		->constructed(object);
101 }
102 
103 static void
celluloid_plugins_manager_item_finalize(GObject * object)104 celluloid_plugins_manager_item_finalize(GObject *object)
105 {
106 	CelluloidPluginsManagerItem *self = CELLULOID_PLUGINS_MANAGER_ITEM(object);
107 
108 	g_free(self->title);
109 	g_free(self->path);
110 
111 	G_OBJECT_CLASS(celluloid_plugins_manager_item_parent_class)
112 		->finalize(object);
113 }
114 
115 static void
celluloid_plugins_manager_item_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)116 celluloid_plugins_manager_item_set_property(	GObject *object,
117 						guint property_id,
118 						const GValue *value,
119 						GParamSpec *pspec )
120 {
121 	CelluloidPluginsManagerItem *self = CELLULOID_PLUGINS_MANAGER_ITEM(object);
122 
123 	if(property_id == PROP_PARENT)
124 	{
125 		self->parent_window = g_value_get_pointer(value);
126 	}
127 	else if(property_id == PROP_TITLE)
128 	{
129 		g_free(self->title);
130 
131 		self->title = g_value_dup_string(value);
132 	}
133 	else if(property_id == PROP_PATH)
134 	{
135 		g_free(self->path);
136 
137 		self->path = g_value_dup_string(value);
138 	}
139 	else
140 	{
141 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
142 	}
143 }
144 
145 static void
celluloid_plugins_manager_item_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)146 celluloid_plugins_manager_item_get_property(	GObject *object,
147 						guint property_id,
148 						GValue *value,
149 						GParamSpec *pspec )
150 {
151 	CelluloidPluginsManagerItem *self = CELLULOID_PLUGINS_MANAGER_ITEM(object);
152 
153 	if(property_id == PROP_PARENT)
154 	{
155 		g_value_set_pointer(value, self->parent_window);
156 	}
157 	else if(property_id == PROP_TITLE)
158 	{
159 		g_value_set_string(value, self->title);
160 	}
161 	else if(property_id == PROP_PATH)
162 	{
163 		g_value_set_string(value, self->path);
164 	}
165 	else
166 	{
167 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
168 	}
169 }
170 
171 static void
remove_response_handler(GtkDialog * dialog,gint response_id,gpointer data)172 remove_response_handler(GtkDialog *dialog, gint response_id, gpointer data)
173 {
174 	CelluloidPluginsManagerItem *item = data;
175 	GFile *file = g_file_new_for_path(item->path);
176 	GError *error = NULL;
177 
178 	if(response_id == GTK_RESPONSE_YES)
179 	{
180 		g_file_delete(file, NULL, &error);
181 	}
182 
183 	gtk_window_destroy(GTK_WINDOW(dialog));
184 
185 	if(error)
186 	{
187 		GtkWidget *error_dialog;
188 
189 		error_dialog =	gtk_message_dialog_new
190 				(	item->parent_window,
191 					GTK_DIALOG_MODAL|
192 					GTK_DIALOG_DESTROY_WITH_PARENT,
193 					GTK_MESSAGE_ERROR,
194 					GTK_BUTTONS_OK,
195 					_("Failed to delete file '%s'. "
196 					"Reason: %s"),
197 					g_file_get_uri(file),
198 					error->message );
199 
200 		g_warning(	"Failed to delete file '%s'. Reason: %s",
201 				g_file_get_uri(file),
202 				error->message );
203 
204 		gtk_window_set_modal(GTK_WINDOW(error_dialog), TRUE);
205 		gtk_widget_show(error_dialog);
206 
207 		gtk_window_destroy(GTK_WINDOW(error_dialog));
208 		g_error_free(error);
209 	}
210 
211 	g_object_unref(file);
212 }
213 
214 static void
remove_handler(GtkButton * button,gpointer data)215 remove_handler(GtkButton *button, gpointer data)
216 {
217 	CelluloidPluginsManagerItem *item = data;
218 	GtkWidget *confirm_dialog =	gtk_message_dialog_new
219 					(	item->parent_window,
220 						GTK_DIALOG_MODAL|
221 						GTK_DIALOG_DESTROY_WITH_PARENT,
222 						GTK_MESSAGE_QUESTION,
223 						GTK_BUTTONS_YES_NO,
224 						_("Are you sure you want to "
225 						"remove this script? This "
226 						"action cannot be undone."));
227 
228 	g_signal_connect(	confirm_dialog,
229 				"response",
230 				G_CALLBACK(remove_response_handler),
231 				item );
232 
233 	gtk_window_set_modal(GTK_WINDOW(confirm_dialog), TRUE);
234 	gtk_widget_show(confirm_dialog);
235 }
236 
237 static void
celluloid_plugins_manager_item_class_init(CelluloidPluginsManagerItemClass * klass)238 celluloid_plugins_manager_item_class_init(CelluloidPluginsManagerItemClass *klass)
239 {
240 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
241 	GParamSpec *pspec = NULL;
242 
243 	obj_class->constructed = celluloid_plugins_manager_item_constructed;
244 	obj_class->finalize = celluloid_plugins_manager_item_finalize;
245 	obj_class->set_property = celluloid_plugins_manager_item_set_property;
246 	obj_class->get_property = celluloid_plugins_manager_item_get_property;
247 
248 	pspec = g_param_spec_pointer
249 		(	"parent",
250 			"Parent",
251 			"Parent window for the dialogs",
252 			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
253 	g_object_class_install_property(obj_class, PROP_PARENT, pspec);
254 
255 	pspec = g_param_spec_string
256 		(	"title",
257 			"Title",
258 			"The string to display as the title of the item",
259 			"",
260 			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
261 	g_object_class_install_property(obj_class, PROP_TITLE, pspec);
262 
263 	pspec = g_param_spec_string
264 		(	"path",
265 			"Path",
266 			"The path to the file that this item references",
267 			"",
268 			G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
269 	g_object_class_install_property(obj_class, PROP_PATH, pspec);
270 }
271 
272 static void
celluloid_plugins_manager_item_init(CelluloidPluginsManagerItem * item)273 celluloid_plugins_manager_item_init(CelluloidPluginsManagerItem *item)
274 {
275 	item->parent_window = NULL;
276 	item->title = NULL;
277 	item->path = NULL;
278 }
279 
280 GtkWidget *
celluloid_plugins_manager_item_new(GtkWindow * parent,const gchar * title,const gchar * path)281 celluloid_plugins_manager_item_new(	GtkWindow *parent,
282 					const gchar *title,
283 					const gchar *path )
284 {
285 	return GTK_WIDGET(g_object_new(	celluloid_plugins_manager_item_get_type(),
286 					"parent", parent,
287 					"title", title,
288 					"path", path,
289 					NULL));
290 }
291