File: ContactWindow.cs

package info (click to toggle)
beagle 0.2.12-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 12,204 kB
  • ctags: 16,188
  • sloc: cs: 91,628; sh: 27,627; ansic: 10,646; makefile: 2,248; xml: 15
file content (446 lines) | stat: -rw-r--r-- 14,249 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
//
// ContactWindow.cs
//
// Copyright (C) 2006 Pierre Östlund
//

//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

using Gtk;
using Glade;
using System;
using System.Collections;
using System.Text.RegularExpressions;

using Beagle.Util;
using Mono.Unix;

namespace ContactViewer {

	public class ContactWindow {
		private Glade.XML gxml;
		private UIManager ui_manager;
		
		[Widget] Gtk.TreeView ContactList;
		[Widget] Gtk.ComboBox ListIdentifier;
		[Widget] Gtk.Statusbar Statusbar;
		[Widget] Gtk.Window MainWindow;
		[Widget] Gtk.EventBox MenubarHolder;
		[Widget] Gtk.EventBox ContactHolder;
	
		private ListStore contact_store;
		private ListStore contact_show_type_store;
	
		private Uri uri;
		private MorkDatabase database;
		//private ContactManager contact_manager;
		
		public ContactWindow (ContactManager contact_manager, Uri uri)
		{
			this.uri = uri;
			//this.contact_manager = contact_manager;
			
			ShowWindow ();
		}
		
		public void ShowWindow ()
		{
			Application.Init ();
			
			gxml = new Glade.XML ("contactviewer.glade", "MainWindow");
			gxml.Autoconnect (this);
			
			ActionEntry[] entries = new ActionEntry [] {
				new ActionEntry ("FileMenuAction", null, "_File", null, null, null),
				new ActionEntry ("OpenAction", Gtk.Stock.Open,
					"_Open", "<control>O", Catalog.GetString ("Open..."), new EventHandler (OnOpenDatabase)),
				new ActionEntry ("QuitAction", Gtk.Stock.Quit,
					"_Quit", "<control>Q", Catalog.GetString ("Quit"), new EventHandler (OnQuit)),
				new ActionEntry ("HelpMenuAction", null, "_Help", null, null, null),
				new ActionEntry ("AboutAction", Gnome.Stock.About,
					"_About", null, Catalog.GetString ("About"), new EventHandler (OnAbout))
			};
			
			ActionGroup grp = new ActionGroup ("MainGroup");
			grp.Add (entries);
			
			ui_manager = new UIManager ();
			ui_manager.InsertActionGroup(grp, 0);
			ui_manager.AddUiFromResource ("menu.xml");
			MenubarHolder.Add (ui_manager.GetWidget ("/MainMenu"));
			
			// Fix the TreeView that will contain all contacts
			contact_store = new ListStore (typeof (string), typeof (string));
			
			ContactList.Model = contact_store;
			ContactList.RulesHint = true;
			ContactList.AppendColumn (Catalog.GetString ("Contacts"), new CellRendererText (), "text", 1);
			ContactList.ButtonReleaseEvent += OnContactSelected;
			
			// This ListStore will let the user choose what to see in the contact list
			contact_show_type_store = new ListStore (typeof (string), typeof (string));
			contact_show_type_store.AppendValues ("DisplayName", Catalog.GetString ("Display name"));
			contact_show_type_store.AppendValues ("PrimaryEmail", Catalog.GetString ("Primary E-mail"));
			contact_show_type_store.AppendValues ("SecondEmail", Catalog.GetString ("Secondary E-mail"));
			contact_show_type_store.AppendValues ("NickName", Catalog.GetString ("Nickname"));
			
			CellRendererText cell = new CellRendererText ();
			ListIdentifier.PackStart (cell, false);
			ListIdentifier.AddAttribute (cell, "text", 1);
			ListIdentifier.Model = contact_show_type_store;
			ListIdentifier.Active = 0;
			ListIdentifier.Changed += OnContactListTypeChanged;
			
			MainWindow.Icon = Beagle.Images.GetPixbuf ("contact-icon.png");
			MainWindow.DeleteEvent += OnDeleteEvent;
			
			LoadDatabase ();
			Application.Run ();
		}

		public void LoadDatabase ()
		{
			// Load the database file
			try {
				database = new MorkDatabase (uri.AbsolutePath);
				database.Read ();
				database.EnumNamespace = "ns:addrbk:db:row:scope:card:all";
			} catch (Exception e) {
				MessageDialog dialog = new MessageDialog (
					MainWindow,
					DialogFlags.DestroyWithParent, 
					MessageType.Error, 
					ButtonsType.Ok, 
					false, 
					String.Format (Catalog.GetString ("Unable to open mork database:\n\n {0}"), e.Message));
				
				dialog.Run ();
				dialog.Destroy ();
				Environment.Exit (1);
			}
			
			// Populate the gui with nice stuff
			Clear ();
			FillContactList ();
			
			try {
				Match m = Regex.Match (uri.Query, @"\?id=(?<id>[0-9A-Fa-f]+)");	
				ShowContact (m.Result ("${id}"));
			} catch (Exception e) {
				Gtk.MessageDialog dialog = new MessageDialog (
					MainWindow,
					DialogFlags.DestroyWithParent,
					MessageType.Warning,
					ButtonsType.Ok,
					Catalog.GetString ("The specified ID does not exist in this database!"));
				
				dialog.Run ();
				dialog.Destroy ();
			}
		}
		
		public void FillContactList ()
		{
			TreeIter iter;
			int count = 0;
			
			if (!ListIdentifier.GetActiveIter (out iter)) 
				return;
			
			contact_store.Clear ();
			
			// Add contacts to treeview
			foreach (string id in database) {
				Hashtable tbl = database.Compile (id, database.EnumNamespace);
				
				if (tbl ["table"] != null && tbl ["table"] as string == "BF") {
					contact_store.AppendValues (tbl ["id"], tbl [contact_show_type_store.GetValue (iter, 0)]);
					count++;
				}
			}
			
			SetStatusMessage (String.Format (Catalog.GetPluralString ("Added {0} contact", "Added {0} contacts", count), count));
		}
		
		public void ShowContact (string id)
		{
			TreeIter iter;
			Hashtable tbl = database.Compile (id, database.EnumNamespace);
			
			if (ContactHolder.Child != null)
				ContactHolder.Remove (ContactHolder.Child);
			
			ContactHolder.Add (new Contact (tbl));
			MainWindow.ShowAll ();
			
			// Update selection in the contact list as well
			if (contact_store.GetIterFirst (out iter)) {
				do {
					if (contact_store.GetValue (iter, 0) as string == id) {
						ContactList.Selection.SelectIter (iter);
						break;
					}	
				} while (contact_store.IterNext (ref iter));
			}
			
			SetStatusMessage (String.Format (Catalog.GetString ("Viewing {0}"), 
				(ContactHolder.Child as Contact).GetString ("DisplayName")));
		}
		
		public void Clear ()
		{
			if (ContactHolder.Child != null)
				ContactHolder.Remove (ContactHolder.Child);
			
			contact_store.Clear ();
		}
		
		public void SetStatusMessage (string message)
		{
			Statusbar.Pop (0);
			Statusbar.Push (0, message);
		}

		protected virtual void OnContactSelected (object o, ButtonReleaseEventArgs args)
		{
			TreeIter iter;
			TreeModel model;
			
			if (!ContactList.Selection.GetSelected (out model, out iter))
				return;
			
			ShowContact ((string) model.GetValue (iter, 0));
		}
		
		protected virtual void OnContactListTypeChanged (object o, EventArgs args)
		{
			FillContactList ();
		}
		
		protected virtual void OnOpenDatabase (object o, EventArgs args)
		{
			Uri uri;
			ResponseType response;
			FileChooserDialog chooser;
			
			chooser = new FileChooserDialog (Catalog.GetString ("Select a mork database file"), 
				MainWindow, FileChooserAction.Open);
			chooser.LocalOnly = true;
			chooser.AddButton (Gtk.Stock.Cancel, ResponseType.Cancel);
			chooser.AddButton (Gtk.Stock.Ok, ResponseType.Ok);
			
			response = (ResponseType) chooser.Run ();
			uri = new Uri (chooser.Uri);
			chooser.Destroy ();
			
			if (response == ResponseType.Ok) {
				this.uri = uri;
				LoadDatabase ();
			}
		}
		
		protected virtual void OnAbout (object o, EventArgs args)
		{
#pragma warning disable 612 // don't warn that Gnome.About is deprecated.
			Gnome.About about = new Gnome.About ("Contact Viewer",
							     ExternalStringsHack.Version,
							     "Copyright (C) 2006 Pierre \u00D6stlund",
							     null, new string [] { "Pierre \u00D6stlund" },
							     null, null, Beagle.Images.GetPixbuf ("system-search.png"));
			
			about.Run ();
			about.Dispose ();
#pragma warning restore 612
		}
		
		protected virtual void OnQuit (object o, EventArgs args)
		{
			Application.Quit ();
		}
		
		protected virtual void OnDeleteEvent (object o, DeleteEventArgs args)
		{
			Application.Quit ();
		}
	}
	
	public class Contact : VBox {
		private Hashtable contact;
	
		public Contact (Hashtable contact) :
			base (false, 10)
		{
			HBox hbox;
			Table table;
			Button button;
			HButtonBox hbuttonbox;
			
			this.contact = contact;
			
			// Create header containing an icon and display name
			hbox = new HBox ();
			hbox.Spacing = 10;
			hbox.PackStart (Beagle.Images.GetWidget ("person.png"), false, false, 0);
			hbox.PackStart (new VLabel (String.Format ("<b><span size='large'>{0} \"{1}\" {2}</span></b>", 
				GetString ("FirstName"), GetString ("NickName"), GetString ("LastName")), false));
			PackStart (hbox, false, false, 0);
			PackStart (new HSeparator (), false, false, 0);
			
			// Create a table containing some user information
			table = new Table (5, 2, false);
			PackStart (table, false, false, 0);
			
			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Primary E-Mail:")), false), 
				0, 1, 0, 1, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
			table.Attach (new VLabel (GetString ("PrimaryEmail"), true), 1, 2, 0, 1);
				
			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Screen name:")), false), 
				0, 1, 1, 2, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
			table.Attach (new VLabel (GetString ("_AimScreenName"), true), 1, 2, 1, 2);
				
			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Home phone:")), false), 
				0, 1, 2, 3, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
			table.Attach (new VLabel (GetString ("HomePhone"), true), 1, 2, 2, 3);
				
			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Mobile phone:")), false), 
				0, 1, 3, 4, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
			table.Attach (new VLabel (GetString ("CellularNumber"), true), 1, 2, 3, 4);
				
			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Web page:")), false), 
				0, 1, 4, 5, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
			table.Attach (new VLabel (GetString ("WebPage2"), true), 1, 2, 4, 5);
					
			// Add a button row with some informational buttons
			hbuttonbox = new HButtonBox ();
			hbuttonbox.Layout = ButtonBoxStyle.End;
			PackEnd (hbuttonbox, false, false, 0);
			
			button = new Button (Catalog.GetString ("Send E-Mail"));
			button.Clicked += OnSendEmail;
			hbuttonbox.Add (button);
			
			button = new Button (Catalog.GetString ("Details..."));
			button.Clicked += OnDetails;
			hbuttonbox.Add (button);
		}
		
		public string GetString (string str)
		{
			if (!contact.ContainsKey (str))
				return "N/A";
			
			return contact [str] as string;
		}
		
		protected virtual void OnSendEmail (object o, EventArgs args)
		{
			string mail = null;
			SafeProcess process;
			
			if (contact ["PrimaryEmail"] != null)
				mail = contact ["PrimaryEmail"] as string;
			else if (contact ["SecondEmail"] != null)
				mail = contact ["SecondMail"] as string;
			else {
				MessageDialog dialog = new MessageDialog (
					null,
					DialogFlags.DestroyWithParent, 
					MessageType.Warning,
					ButtonsType.Ok, 
					Catalog.GetString ("Could not find a valid E-mail address!"));
				
				dialog.Run ();
				dialog.Destroy ();
				return;
			}
			
			process = new SafeProcess ();
			process.Arguments = new string [2];
			process.Arguments [0] = Thunderbird.ExecutableName;
			process.Arguments [1] = String.Format ("mailto:{0}", mail);
			process.Start ();
		}
		
		protected virtual void OnDetails (object o, EventArgs args)
		{
			new DetailedWindow (contact);
		}

		public class VLabel : Label {
			
			public VLabel (string label, bool selectable) :
				base (label)
			{
				Xalign = 0.0f;
				UseMarkup = true;
				Selectable = selectable;
			}
		}
		
	}
	
	public class DetailedWindow {
		private Glade.XML gxml;
		
		[Widget] Gtk.Button Close;
		[Widget ("DetailedWindow")] Gtk.Window Window;
		[Widget] Gtk.TextView Notes;
		[Widget] Gtk.ComboBox PreferredType;
		
		string[] widget_names = new string[] {"FirstName", "LastName", "DisplayName", 
			"NickName", "PrimaryEmail", "SecondEmail", "_AimScreenName", "WorkPhone",
			"HomePhone", "FaxNumber", "PagerNumber", "CellularNumber", "HomeAddress",
			"HomeAddress2", "HomeCity", "HomeCountry", "WebPage2", "HomeZipCode",
			"HomeState", "WorkState", "WorkZipCode", "JobTitle", "Department", "Company",
			"WorkAddress", "WorkAddress2", "WorkCity", "WorkCountry", "WebPage1",
			"Custom1", "Custom2", "Custom3", "Custom4"};
		
		public DetailedWindow (Hashtable contact)
		{
			gxml = new Glade.XML (null, "contactviewer.glade", "DetailedWindow", null);
			gxml.Autoconnect (this);
			
			// Fill all Entry-boxes with information
			foreach (string name in widget_names)
				(gxml.GetWidget (name) as Gtk.Entry).Text = (contact [name] != null ? (contact [name] as string) : "");;
			
			// Also fill the special cases
			Notes.Buffer.Text = (contact ["Notes"] != null ? (contact ["Notes"] as string) : "");
			
			try {
				int tmp = Convert.ToInt32 (contact ["PreferMailFormat"]);
				PreferredType.Active = (tmp >= 0 && tmp <= 2 ? tmp : 0);
			} catch (Exception e) {
				PreferredType.Active = 0;
			}
			
			Close.Clicked += OnClose;
			
			Window.Icon = Beagle.Images.GetPixbuf ("contact-icon.png");
			Window.Show ();
		}
		
		protected virtual void OnClose (object o, EventArgs args)
		{
			Window.Hide ();
		}
	}
}