1 /*
2  * Smuxi - Smart MUltipleXed Irc
3  *
4  * Copyright (c) 2005-2013, 2015 Mirco Bauer <meebey@meebey.net>
5  *
6  * Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22 
23 using System;
24 using System.Collections;
25 using System.Collections.Specialized;
26 using Mono.Unix;
27 using Smuxi.Engine;
28 using Smuxi.Common;
29 
30 namespace Smuxi.Frontend.Gnome
31 {
32     public class EngineManagerDialog : Gtk.Dialog
33     {
34 #if LOG4NET
35         private static readonly log4net.ILog _Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
36 #endif
37         private Gtk.ComboBox  _ComboBox;
38         private Gtk.ListStore _ListStore;
39         private string        _SelectedEngine;
40         private EngineManager _EngineManager;
41         private Gtk.Button    _EditButton;
42         private Gtk.Button    _DeleteButton;
43         new Gtk.Window Parent { get; set; }
44 
45         public string SelectedEngine {
46             get {
47                 Gtk.TreeIter iter;
48                 if (!_ComboBox.GetActiveIter(out iter)) {
49                     return null;
50                 }
51                 return (string) _ComboBox.Model.GetValue(iter, 0);
52             } set {
53                 int i = 0;
54                 foreach (object[] row in (Gtk.ListStore) _ComboBox.Model) {
55                     if ((string) row[0] == value) {
56                         _ComboBox.Active = i;
57                         return;
58                     }
59                     i++;
60                 }
61                 throw new ArgumentException(_("Engine not found."), "value");
62             }
63         }
64 
EngineManagerDialog(Gtk.Window parent, EngineManager engineManager)65         public EngineManagerDialog(Gtk.Window parent, EngineManager engineManager) :
66                               base(null, parent, Gtk.DialogFlags.Modal)
67         {
68             Trace.Call(parent, engineManager);
69 
70             if (engineManager == null) {
71                 throw new ArgumentNullException("engineManager");
72             }
73 
74             Parent = parent;
75             _EngineManager = engineManager;
76 
77             Title = "Smuxi - " + _("Engine Manager");
78             SetPosition(Gtk.WindowPosition.CenterAlways);
79 
80             var connect_button = new Gtk.Button(Gtk.Stock.Connect);
81             AddActionWidget(connect_button, 1);
82 
83             AddActionWidget(new Gtk.Button(Gtk.Stock.New), 3);
84 
85             Gtk.Button edit_button = new Gtk.Button(Gtk.Stock.Edit);
86             _EditButton = edit_button;
87             AddActionWidget(edit_button, 2);
88 
89             _DeleteButton = new Gtk.Button(Gtk.Stock.Delete);
90             AddActionWidget(_DeleteButton, 4);
91             AddActionWidget(new Gtk.Button(Gtk.Stock.Quit), 5);
92             Response += new Gtk.ResponseHandler(_OnResponse);
93 
94             Gtk.VBox vbox = new Gtk.VBox();
95             Gtk.Label label = new Gtk.Label("<b>" +
96                                             _("Select which Smuxi engine you want to connect to") +
97                                             "</b>");
98             label.UseMarkup = true;
99             vbox.PackStart(label, false, false, 5);
100 
101             Gtk.HBox hbox = new Gtk.HBox();
102             hbox.PackStart(new Gtk.Label(_("Engine:")), false, false, 5);
103 
104             _ListStore = new Gtk.ListStore(typeof(string));
105             _ComboBox = new Gtk.ComboBox();
106             Gtk.CellRendererText cell = new Gtk.CellRendererText();
107             _ComboBox.PackStart(cell, false);
108             _ComboBox.AddAttribute(cell, "text", 0);
109             _ComboBox.Changed += new EventHandler(_OnComboBoxChanged);
110             _ComboBox.Model = _ListStore;
111             _InitEngineList();
112 
113             var lowBandWidthCheckBox = new Gtk.CheckButton(_("Use Low Bandwidth Mode"));
114             lowBandWidthCheckBox.Active = (bool) Frontend.FrontendConfig["UseLowBandwidthMode"];
115             lowBandWidthCheckBox.Clicked += delegate {
116                 Frontend.FrontendConfig["UseLowBandwidthMode"] =
117                     lowBandWidthCheckBox.Active;
118                 Frontend.FrontendConfig.Save();
119             };
120 
121             hbox.PackStart(_ComboBox, true, true, 10);
122 
123             vbox.PackStart(hbox, false, false, 10);
124             vbox.PackStart(lowBandWidthCheckBox);
125 
126             VBox.Add(vbox);
127 
128             ShowAll();
129         }
130 
_InitEngineList()131         private void _InitEngineList()
132         {
133             string[] engines = (string[])Frontend.FrontendConfig["Engines/Engines"];
134             string default_engine = (string)Frontend.FrontendConfig["Engines/Default"];
135             int item = 0;
136             _ListStore.Clear();
137             _ListStore.AppendValues("<" + _("Local Engine") + ">");
138             item++;
139             foreach (string engine in engines) {
140                 _ListStore.AppendValues(engine);
141                 if (engine == default_engine) {
142                     _ComboBox.Active = item;
143                 }
144                 item++;
145             }
146         }
147 
_OnResponse(object sender, Gtk.ResponseArgs e)148         private void _OnResponse(object sender, Gtk.ResponseArgs e)
149         {
150             Trace.Call(sender, e);
151 
152             try {
153 #if LOG4NET
154                 _Logger.Debug("_OnResponse(): ResponseId: "+e.ResponseId);
155 #endif
156                 switch ((int)e.ResponseId) {
157                     case 1:
158                         _OnConnectButtonPressed();
159                         break;
160                     case 2:
161                         _OnEditButtonPressed();
162                         break;
163                     case 3:
164                         _OnNewButtonPressed();
165                         break;
166                     case 4:
167                         _OnDeleteButtonPressed();
168                         break;
169                     case 5:
170                         _OnQuitButtonPressed();
171                         break;
172                     case (int)Gtk.ResponseType.DeleteEvent:
173                         _OnDeleteEvent();
174                         break;
175                 }
176             } catch (Exception ex) {
177 #if LOG4NET
178                 _Logger.Error(ex);
179 #endif
180                 CrashDialog.Show(this, ex);
181             }
182         }
183 
_OnConnectButtonPressed()184         private void _OnConnectButtonPressed()
185         {
186             if (_SelectedEngine == null || _SelectedEngine == String.Empty) {
187                 Gtk.MessageDialog md = new Gtk.MessageDialog(this,
188                     Gtk.DialogFlags.Modal, Gtk.MessageType.Error,
189                     Gtk.ButtonsType.Close, _("Please select an engine!"));
190                 md.Run();
191                 md.Destroy();
192                 // Re-run the Dialog
193                 Run();
194                 return;
195             }
196 
197             if (_SelectedEngine == "<" + _("Local Engine") + ">") {
198                 Frontend.InitLocalEngine();
199                 Frontend.ConnectEngineToGUI();
200                 Destroy();
201                 return;
202             }
203 
204             string engine = _SelectedEngine;
205             try {
206                 _EngineManager.Connect(engine);
207                 var engineProtocolVersion = _EngineManager.EngineProtocolVersion;
208                 var frontendProtocolVersion = new Version(0, 0);
209                 if (engineProtocolVersion.Major != frontendProtocolVersion.Major) {
210                     throw new ApplicationException(
211                         String.Format(
212                             _("Your frontend is not compatible with the engine!\n" +
213                               "Engine Version: {0} Frontend Version: {1}\n" +
214                               "Engine Protocol: {2} Frontend Protocol: {3}"),
215                             _EngineManager.EngineAssemblyVersion, Frontend.Version,
216                             engineProtocolVersion, frontendProtocolVersion
217                         )
218                     );
219                 }
220 
221                 Frontend.Session = _EngineManager.Session;
222                 Frontend.UserConfig = _EngineManager.UserConfig;
223                 Frontend.EngineAssemblyVersion = _EngineManager.EngineAssemblyVersion;
224                 Frontend.EngineProtocolVersion = _EngineManager.EngineProtocolVersion;
225                 Frontend.ConnectEngineToGUI();
226             } catch (Exception ex) {
227 #if LOG4NET
228                 _Logger.Error(ex);
229 #endif
230                 // clean-up
231                 try {
232                     _EngineManager.Disconnect();
233                 } catch (Exception disEx) {
234 #if LOG4NET
235                     _Logger.Error(disEx);
236 #endif
237                 }
238 
239                 string error_msg = ex.Message + "\n";
240                 if (ex.InnerException != null) {
241                     error_msg += " [" + ex.InnerException.Message + "]\n";
242                 }
243 
244                 string msg;
245                 msg = _("An error occurred while connecting to the engine!") + "\n\n";
246                 msg += String.Format(_("Engine URL: {0}") + "\n",
247                                      _EngineManager.EngineUrl);
248 
249                 msg += String.Format(_("Error: {0}"), error_msg);
250 
251                 Gtk.MessageDialog md = new Gtk.MessageDialog(this, Gtk.DialogFlags.Modal,
252                     Gtk.MessageType.Error, Gtk.ButtonsType.Close, msg);
253                 md.Run();
254                 md.Destroy();
255 
256                 // Re-run the Dialog
257                 Run();
258             }
259         }
260 
_OnNewButtonPressed()261         private void _OnNewButtonPressed()
262         {
263             EngineAssistant assistant = new EngineAssistant(
264                 Parent,
265                 Frontend.FrontendConfig
266             );
267             assistant.Cancel += delegate {
268                 assistant.Destroy();
269 
270                 // Restart the Dialog
271                 // HACK: holy shit, please refactor this mess!
272                 var dialog = new EngineManagerDialog(Parent, _EngineManager);
273                 dialog.Run();
274                 dialog.Destroy();
275             };
276             assistant.Close += delegate {
277                 assistant.Destroy();
278 
279                 // Restart the Dialog
280                 // HACK: holy shit, please refactor this mess!
281                 var dialog = new EngineManagerDialog(Parent, _EngineManager);
282                 dialog.Run();
283                 dialog.Destroy();
284             };
285             assistant.ShowAll();
286         }
287 
_OnEditButtonPressed()288         private void _OnEditButtonPressed()
289         {
290             EngineAssistant assistant = new EngineAssistant(
291                 Parent,
292                 Frontend.FrontendConfig,
293                 _SelectedEngine
294             );
295             assistant.Cancel += delegate {
296                 assistant.Destroy();
297 
298                 // Restart the Dialog
299                 // HACK: holy shit, please refactor this mess!
300                 var dialog = new EngineManagerDialog(Parent, _EngineManager);
301                 dialog.Run();
302                 dialog.Destroy();
303             };
304             assistant.Close += delegate {
305                 assistant.Destroy();
306 
307                 // Restart the Dialog
308                 // HACK: holy shit, please refactor this mess!
309                 var dialog = new EngineManagerDialog(Parent, _EngineManager);
310                 dialog.Run();
311                 dialog.Destroy();
312             };
313             assistant.ShowAll();
314         }
315 
_OnDeleteButtonPressed()316         private void _OnDeleteButtonPressed()
317         {
318             string msg = String.Format(
319                             _("Are you sure you want to delete the engine \"{0}\"?"),
320                             _SelectedEngine);
321             Gtk.MessageDialog md = new Gtk.MessageDialog(this, Gtk.DialogFlags.Modal,
322             Gtk.MessageType.Warning, Gtk.ButtonsType.YesNo, msg);
323             int res = md.Run();
324             md.Destroy();
325 
326             if ((Gtk.ResponseType)res == Gtk.ResponseType.Yes) {
327                 _DeleteEngine(_SelectedEngine);
328                  _InitEngineList();
329 
330                 // Re-run the Dialog
331                 Run();
332             }
333         }
334 
_DeleteEngine(string engine)335         private void _DeleteEngine(string engine)
336         {
337             StringCollection new_engines = new StringCollection();
338             string[] current_engines = (string[])Frontend.FrontendConfig["Engines/Engines"];
339             foreach (string eng in current_engines) {
340                 if (eng != engine) {
341                     new_engines.Add(eng);
342                 }
343             }
344             string[] new_engines_array = new string[new_engines.Count];
345             new_engines.CopyTo(new_engines_array, 0);
346             // UGLY: refactor this to a proper controller class, see ServerListController
347             Frontend.FrontendConfig["Engines/Engines"] = new_engines_array;
348             Frontend.FrontendConfig.Remove("Engines/"+engine+"/Username");
349             Frontend.FrontendConfig.Remove("Engines/"+engine+"/Password");
350             Frontend.FrontendConfig.Remove("Engines/"+engine+"/Hostname");
351             Frontend.FrontendConfig.Remove("Engines/"+engine+"/Port");
352             Frontend.FrontendConfig.Remove("Engines/"+engine+"/Channel");
353             Frontend.FrontendConfig.Remove("Engines/"+engine+"/Formatter");
354             Frontend.FrontendConfig.Remove("Engines/"+engine+"/UseSshTunnel");
355             Frontend.FrontendConfig.Remove("Engines/"+engine+"/SshHostname");
356             Frontend.FrontendConfig.Remove("Engines/"+engine+"/SshPort");
357             Frontend.FrontendConfig.Remove("Engines/"+engine+"/SshUsername");
358             Frontend.FrontendConfig.Remove("Engines/"+engine);
359             Frontend.FrontendConfig.Save();
360             Frontend.FrontendConfig.Load();
361         }
362 
_OnQuitButtonPressed()363         private void _OnQuitButtonPressed()
364         {
365             Frontend.Quit();
366         }
367 
_OnDeleteEvent()368         private void _OnDeleteEvent()
369         {
370             Frontend.Quit();
371         }
372 
_OnComboBoxChanged(object sender, EventArgs e)373         private void _OnComboBoxChanged(object sender, EventArgs e)
374         {
375             Trace.Call(sender, e);
376 
377             Gtk.TreeIter iter;
378             if (_ComboBox.GetActiveIter(out iter)) {
379                _SelectedEngine = (string )_ComboBox.Model.GetValue(iter, 0);
380             }
381 
382             bool isLocalEngine = _SelectedEngine == "<" + _("Local Engine") + ">";
383             _EditButton.Sensitive = !isLocalEngine;
384             _DeleteButton.Sensitive = !isLocalEngine;
385         }
386 
_(string msg)387         private static string _(string msg)
388         {
389             return Mono.Unix.Catalog.GetString(msg);
390         }
391     }
392 }
393