1/*
2 * This file is part of gitg
3 *
4 * Copyright (C) 2013 - Sindhu S
5 *
6 * gitg 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 2 of the License, or
9 * (at your option) any later version.
10 *
11 * gitg 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 gitg. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20namespace Gitg
21{
22	[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-author-details-dialog.ui")]
23	public class AuthorDetailsDialog : Gtk.Dialog
24	{
25		//Do this to pull in config.h before glib.h (for gettext)
26		private const string version = Gitg.Config.VERSION;
27
28		[GtkChild (name = "entry_name")]
29		private Gtk.Entry d_entry_name;
30
31		[GtkChild (name = "entry_email")]
32		private Gtk.Entry d_entry_email;
33
34		[GtkChild (name = "label_info")]
35		private Gtk.Label d_label_info;
36
37		[GtkChild (name = "checkbutton_override_global")]
38		private Gtk.CheckButton d_checkbutton_override_global;
39
40		private string? d_repository_name;
41
42		private Ggit.Config d_config;
43
44		public AuthorDetailsDialog (Gtk.Window? parent, Ggit.Config config, string? repository_name)
45		{
46			Object (use_header_bar: 1);
47
48			if (parent != null)
49			{
50				set_transient_for (parent);
51			}
52
53			d_repository_name = repository_name;
54			d_config = config;
55		}
56
57		public static AuthorDetailsDialog? show_global(Window window)
58		{
59			var xdg_config_path = Path.build_filename(Environment.get_user_config_dir(), "git", "config");
60			var config_path = Path.build_filename(Environment.get_home_dir(), ".gitconfig");
61
62			// If neither exists yet, create default empty one
63			if (!FileUtils.test(xdg_config_path, FileTest.EXISTS) && !FileUtils.test(config_path, FileTest.EXISTS))
64			{
65				try
66				{
67					FileUtils.set_contents(config_path, "");
68				} catch {}
69			}
70
71			var global_config_file = Ggit.Config.find_global();
72
73			if (global_config_file == null)
74			{
75				return null;
76			}
77
78			Ggit.Config? global_config;
79
80			try
81			{
82				global_config = new Ggit.Config.from_file(global_config_file);
83			}
84			catch
85			{
86				return null;
87			}
88
89			var author_details = new AuthorDetailsDialog(window, global_config, null);
90			author_details.show();
91
92			return author_details;
93		}
94
95		private void build_global()
96		{
97			title = _("Author Details");
98			d_label_info.label = _("Enter default details used for all repositories:");
99			d_label_info.show();
100		}
101
102		private bool config_is_local(string name)
103		{
104			try
105			{
106				var entry = d_config.get_entry(name);
107				return entry.get_level() == Ggit.ConfigLevel.LOCAL;
108			}
109			catch
110			{
111				return false;
112			}
113		}
114
115		private void build_repository()
116		{
117			title = "%s — %s".printf(d_repository_name, _("Author Details"));
118
119			// Translators: %s is the repository name
120			d_checkbutton_override_global.label = _("Override global details for repository “%s”:").printf(d_repository_name);
121			d_checkbutton_override_global.active = (config_is_local("user.name") || config_is_local("user.email"));
122
123			d_checkbutton_override_global.notify["active"].connect(update_sensitivity);
124			d_checkbutton_override_global.show();
125
126			update_sensitivity();
127		}
128
129		private void update_sensitivity()
130		{
131			d_entry_name.sensitive = d_checkbutton_override_global.active;
132			d_entry_email.sensitive = d_checkbutton_override_global.active;
133
134			Ggit.Config? config = null;
135
136			try
137			{
138				if (!d_checkbutton_override_global.active)
139				{
140					config = d_config.open_level(Ggit.ConfigLevel.GLOBAL);
141				}
142				else
143				{
144					config = d_config;
145				}
146			} catch {}
147
148			if (config != null)
149			{
150				update_entries(config);
151			}
152		}
153
154		public override void show()
155		{
156			base.show();
157
158			if (d_repository_name == null)
159			{
160				build_global();
161			}
162			else
163			{
164				build_repository();
165			}
166
167			update_entries(d_config);
168		}
169
170		private string read_config_string(Ggit.Config config, string name, string defval = "")
171		{
172			string? ret = null;
173
174			try
175			{
176				ret = config.snapshot().get_string(name);
177			} catch {}
178
179			return ret != null ? ret : defval;
180		}
181
182		private void update_entries(Ggit.Config config)
183		{
184			d_entry_name.set_text(read_config_string(config, "user.name").chomp());
185			d_entry_email.set_text(read_config_string(config, "user.email").chomp());
186		}
187
188		private void delete_local_entries()
189		{
190			try
191			{
192				if (d_config.get_entry("user.name").get_level() == Ggit.ConfigLevel.LOCAL)
193				{
194					d_config.delete_entry("user.name");
195				}
196			} catch {}
197
198			try
199			{
200				if (d_config.get_entry("user.email").get_level() == Ggit.ConfigLevel.LOCAL)
201				{
202					d_config.delete_entry("user.email");
203				}
204			} catch {}
205		}
206
207		public override void response(int id) {
208			if (id == Gtk.ResponseType.OK)
209			{
210				try
211				{
212					if (d_repository_name != null)
213					{
214						if (d_checkbutton_override_global.active)
215						{
216							d_config.set_string("user.name", d_entry_name.get_text());
217							d_config.set_string("user.email", d_entry_email.get_text());
218						}
219						else
220						{
221							delete_local_entries();
222						}
223					}
224					else
225					{
226						d_config.set_string("user.name", d_entry_name.get_text());
227						d_config.set_string("user.email", d_entry_email.get_text());
228					}
229				}
230				catch (Error e)
231				{
232					show_config_error(_("Failed to set Git user config."), e.message);
233					destroy();
234					return;
235				}
236			}
237
238			destroy();
239		}
240
241		private void show_config_error(string primary_message, string secondary_message)
242		{
243			var error_dialog = new Gtk.MessageDialog(this,
244			                                         Gtk.DialogFlags.DESTROY_WITH_PARENT,
245			                                         Gtk.MessageType.ERROR,
246			                                         Gtk.ButtonsType.OK,
247			                                         "%s",
248			                                         primary_message);
249
250			error_dialog.secondary_text = secondary_message;
251			error_dialog.response.connect((d, id) => {
252				error_dialog.destroy();
253			});
254
255			error_dialog.show();
256		}
257	}
258}
259
260/* vi:ts=4 */
261