4 // Copyright (C) 2006 Pierre Östlund
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 using System
.Collections
;
31 using System
.Text
.RegularExpressions
;
36 namespace ContactViewer
{
38 public class ContactWindow
{
39 private Glade
.XML gxml
;
40 private UIManager ui_manager
;
42 [Widget
] Gtk
.TreeView ContactList
;
43 [Widget
] Gtk
.ComboBox ListIdentifier
;
44 [Widget
] Gtk
.Statusbar Statusbar
;
45 [Widget
] Gtk
.Window MainWindow
;
46 [Widget
] Gtk
.EventBox MenubarHolder
;
47 [Widget
] Gtk
.EventBox ContactHolder
;
49 private ListStore contact_store
;
50 private ListStore contact_show_type_store
;
53 private MorkDatabase database
;
54 //private ContactManager contact_manager;
56 public ContactWindow (ContactManager contact_manager
, Uri uri
)
59 //this.contact_manager = contact_manager;
64 public void ShowWindow ()
68 gxml
= new Glade
.XML ("contactviewer.glade", "MainWindow");
69 gxml
.Autoconnect (this);
71 ActionEntry
[] entries
= new ActionEntry
[] {
72 new ActionEntry ("FileMenuAction", null, "_File", null, null, null),
73 new ActionEntry ("OpenAction", Gtk
.Stock
.Open
,
74 "_Open", "<control>O", Catalog
.GetString ("Open..."), new EventHandler (OnOpenDatabase
)),
75 new ActionEntry ("QuitAction", Gtk
.Stock
.Quit
,
76 "_Quit", "<control>Q", Catalog
.GetString ("Quit"), new EventHandler (OnQuit
)),
77 new ActionEntry ("HelpMenuAction", null, "_Help", null, null, null),
78 new ActionEntry ("AboutAction", Gnome
.Stock
.About
,
79 "_About", null, Catalog
.GetString ("About"), new EventHandler (OnAbout
))
82 ActionGroup grp
= new ActionGroup ("MainGroup");
85 ui_manager
= new UIManager ();
86 ui_manager
.InsertActionGroup(grp
, 0);
87 ui_manager
.AddUiFromResource ("menu.xml");
88 MenubarHolder
.Add (ui_manager
.GetWidget ("/MainMenu"));
90 // Fix the TreeView that will contain all contacts
91 contact_store
= new ListStore (typeof (string), typeof (string));
93 ContactList
.Model
= contact_store
;
94 ContactList
.RulesHint
= true;
95 ContactList
.AppendColumn (Catalog
.GetString ("Contacts"), new CellRendererText (), "text", 1);
96 ContactList
.ButtonReleaseEvent
+= OnContactSelected
;
98 // This ListStore will let the user choose what to see in the contact list
99 contact_show_type_store
= new ListStore (typeof (string), typeof (string));
100 contact_show_type_store
.AppendValues ("DisplayName", Catalog
.GetString ("Display name"));
101 contact_show_type_store
.AppendValues ("PrimaryEmail", Catalog
.GetString ("Primary E-mail"));
102 contact_show_type_store
.AppendValues ("SecondEmail", Catalog
.GetString ("Secondary E-mail"));
103 contact_show_type_store
.AppendValues ("NickName", Catalog
.GetString ("Nickname"));
105 CellRendererText cell
= new CellRendererText ();
106 ListIdentifier
.PackStart (cell
, false);
107 ListIdentifier
.AddAttribute (cell
, "text", 1);
108 ListIdentifier
.Model
= contact_show_type_store
;
109 ListIdentifier
.Active
= 0;
110 ListIdentifier
.Changed
+= OnContactListTypeChanged
;
112 MainWindow
.Icon
= Beagle
.Images
.GetPixbuf ("contact-icon.png");
113 MainWindow
.DeleteEvent
+= OnDeleteEvent
;
119 public void LoadDatabase ()
121 // Load the database file
123 database
= new MorkDatabase (uri
.AbsolutePath
);
125 database
.EnumNamespace
= "ns:addrbk:db:row:scope:card:all";
126 } catch (Exception e
) {
127 MessageDialog dialog
= new MessageDialog (
129 DialogFlags
.DestroyWithParent
,
133 String
.Format (Catalog
.GetString ("Unable to open mork database:\n\n {0}"), e
.Message
));
137 Environment
.Exit (1);
140 // Populate the gui with nice stuff
145 Match m
= Regex
.Match (uri
.Query
, @"\?id=(?<id>[0-9A-Fa-f]+)");
146 ShowContact (m
.Result ("${id}"));
148 Gtk
.MessageDialog dialog
= new MessageDialog (
150 DialogFlags
.DestroyWithParent
,
153 Catalog
.GetString ("The specified ID does not exist in this database!"));
160 public void FillContactList ()
165 if (!ListIdentifier
.GetActiveIter (out iter
))
168 contact_store
.Clear ();
170 // Add contacts to treeview
171 foreach (string id
in database
) {
172 Hashtable tbl
= database
.Compile (id
, database
.EnumNamespace
);
174 if (tbl
["table"] != null && tbl
["table"] as string == "BF") {
175 contact_store
.AppendValues (tbl
["id"], tbl
[contact_show_type_store
.GetValue (iter
, 0)]);
180 SetStatusMessage (String
.Format (Catalog
.GetPluralString ("Added {0} contact", "Added {0} contacts", count
), count
));
183 public void ShowContact (string id
)
186 Hashtable tbl
= database
.Compile (id
, database
.EnumNamespace
);
188 if (ContactHolder
.Child
!= null)
189 ContactHolder
.Remove (ContactHolder
.Child
);
191 ContactHolder
.Add (new Contact (tbl
));
192 MainWindow
.ShowAll ();
194 // Update selection in the contact list as well
195 if (contact_store
.GetIterFirst (out iter
)) {
197 if (contact_store
.GetValue (iter
, 0) as string == id
) {
198 ContactList
.Selection
.SelectIter (iter
);
201 } while (contact_store
.IterNext (ref iter
));
204 SetStatusMessage (String
.Format (Catalog
.GetString ("Viewing {0}"),
205 (ContactHolder
.Child
as Contact
).GetString ("DisplayName")));
210 if (ContactHolder
.Child
!= null)
211 ContactHolder
.Remove (ContactHolder
.Child
);
213 contact_store
.Clear ();
216 public void SetStatusMessage (string message
)
219 Statusbar
.Push (0, message
);
222 protected virtual void OnContactSelected (object o
, ButtonReleaseEventArgs args
)
227 if (!ContactList
.Selection
.GetSelected (out model
, out iter
))
230 ShowContact ((string) model
.GetValue (iter
, 0));
233 protected virtual void OnContactListTypeChanged (object o
, EventArgs args
)
238 protected virtual void OnOpenDatabase (object o
, EventArgs args
)
241 ResponseType response
;
242 FileChooserDialog chooser
;
244 chooser
= new FileChooserDialog (Catalog
.GetString ("Select a mork database file"),
245 MainWindow
, FileChooserAction
.Open
);
246 chooser
.LocalOnly
= true;
247 chooser
.AddButton (Gtk
.Stock
.Cancel
, ResponseType
.Cancel
);
248 chooser
.AddButton (Gtk
.Stock
.Ok
, ResponseType
.Ok
);
250 response
= (ResponseType
) chooser
.Run ();
251 uri
= new Uri (chooser
.Uri
);
254 if (response
== ResponseType
.Ok
) {
260 protected virtual void OnAbout (object o
, EventArgs args
)
262 #pragma warning disable 612 // don't warn that Gnome.About is deprecated.
263 Gnome
.About about
= new Gnome
.About ("Contact Viewer",
264 ExternalStringsHack
.Version
,
265 "Copyright (C) 2006 Pierre \u00D6stlund",
266 null, new string [] { "Pierre \u00D6stlund" }
,
267 null, null, Beagle
.Images
.GetPixbuf ("system-search.png"));
271 #pragma warning restore 612
274 protected virtual void OnQuit (object o
, EventArgs args
)
279 protected virtual void OnDeleteEvent (object o
, DeleteEventArgs args
)
285 public class Contact
: VBox
{
286 private Hashtable contact
;
288 public Contact (Hashtable contact
) :
294 HButtonBox hbuttonbox
;
296 this.contact
= contact
;
298 // Create header containing an icon and display name
301 hbox
.PackStart (Beagle
.Images
.GetWidget ("person.png"), false, false, 0);
302 hbox
.PackStart (new VLabel (String
.Format ("<b><span size='large'>{0} \"{1}\" {2}</span></b>",
303 GetString ("FirstName"), GetString ("NickName"), GetString ("LastName")), false));
304 PackStart (hbox
, false, false, 0);
305 PackStart (new HSeparator (), false, false, 0);
307 // Create a table containing some user information
308 table
= new Table (5, 2, false);
309 PackStart (table
, false, false, 0);
311 table
.Attach (new VLabel (String
.Format ("<b>{0}</b>", Catalog
.GetString ("Primary E-Mail:")), false),
312 0, 1, 0, 1, AttachOptions
.Shrink
| AttachOptions
.Fill
, AttachOptions
.Shrink
, 10, 0);
313 table
.Attach (new VLabel (GetString ("PrimaryEmail"), true), 1, 2, 0, 1);
315 table
.Attach (new VLabel (String
.Format ("<b>{0}</b>", Catalog
.GetString ("Screen name:")), false),
316 0, 1, 1, 2, AttachOptions
.Shrink
| AttachOptions
.Fill
, AttachOptions
.Shrink
, 10, 0);
317 table
.Attach (new VLabel (GetString ("_AimScreenName"), true), 1, 2, 1, 2);
319 table
.Attach (new VLabel (String
.Format ("<b>{0}</b>", Catalog
.GetString ("Home phone:")), false),
320 0, 1, 2, 3, AttachOptions
.Shrink
| AttachOptions
.Fill
, AttachOptions
.Shrink
, 10, 0);
321 table
.Attach (new VLabel (GetString ("HomePhone"), true), 1, 2, 2, 3);
323 table
.Attach (new VLabel (String
.Format ("<b>{0}</b>", Catalog
.GetString ("Mobile phone:")), false),
324 0, 1, 3, 4, AttachOptions
.Shrink
| AttachOptions
.Fill
, AttachOptions
.Shrink
, 10, 0);
325 table
.Attach (new VLabel (GetString ("CellularNumber"), true), 1, 2, 3, 4);
327 table
.Attach (new VLabel (String
.Format ("<b>{0}</b>", Catalog
.GetString ("Web page:")), false),
328 0, 1, 4, 5, AttachOptions
.Shrink
| AttachOptions
.Fill
, AttachOptions
.Shrink
, 10, 0);
329 table
.Attach (new VLabel (GetString ("WebPage2"), true), 1, 2, 4, 5);
331 // Add a button row with some informational buttons
332 hbuttonbox
= new HButtonBox ();
333 hbuttonbox
.Layout
= ButtonBoxStyle
.End
;
334 PackEnd (hbuttonbox
, false, false, 0);
336 button
= new Button (Catalog
.GetString ("Send E-Mail"));
337 button
.Clicked
+= OnSendEmail
;
338 hbuttonbox
.Add (button
);
340 button
= new Button (Catalog
.GetString ("Details..."));
341 button
.Clicked
+= OnDetails
;
342 hbuttonbox
.Add (button
);
345 public string GetString (string str
)
347 if (!contact
.ContainsKey (str
))
350 return contact
[str
] as string;
353 protected virtual void OnSendEmail (object o
, EventArgs args
)
358 if (contact
["PrimaryEmail"] != null)
359 mail
= contact
["PrimaryEmail"] as string;
360 else if (contact
["SecondEmail"] != null)
361 mail
= contact
["SecondMail"] as string;
363 MessageDialog dialog
= new MessageDialog (
365 DialogFlags
.DestroyWithParent
,
368 Catalog
.GetString ("Could not find a valid E-mail address!"));
375 process
= new SafeProcess ();
376 process
.Arguments
= new string [2];
377 process
.Arguments
[0] = Thunderbird
.ExecutableName
;
378 process
.Arguments
[1] = String
.Format ("mailto:{0}", mail
);
382 protected virtual void OnDetails (object o
, EventArgs args
)
384 new DetailedWindow (contact
);
387 public class VLabel
: Label
{
389 public VLabel (string label
, bool selectable
) :
394 Selectable
= selectable
;
400 public class DetailedWindow
{
401 private Glade
.XML gxml
;
403 [Widget
] Gtk
.Button Close
;
404 [Widget ("DetailedWindow")] Gtk
.Window Window
;
405 [Widget
] Gtk
.TextView Notes
;
406 [Widget
] Gtk
.ComboBox PreferredType
;
408 string[] widget_names
= new string[] {"FirstName", "LastName", "DisplayName",
409 "NickName", "PrimaryEmail", "SecondEmail", "_AimScreenName", "WorkPhone",
410 "HomePhone", "FaxNumber", "PagerNumber", "CellularNumber", "HomeAddress",
411 "HomeAddress2", "HomeCity", "HomeCountry", "WebPage2", "HomeZipCode",
412 "HomeState", "WorkState", "WorkZipCode", "JobTitle", "Department", "Company",
413 "WorkAddress", "WorkAddress2", "WorkCity", "WorkCountry", "WebPage1",
414 "Custom1", "Custom2", "Custom3", "Custom4"};
416 public DetailedWindow (Hashtable contact
)
418 gxml
= new Glade
.XML (null, "contactviewer.glade", "DetailedWindow", null);
419 gxml
.Autoconnect (this);
421 // Fill all Entry-boxes with information
422 foreach (string name
in widget_names
)
423 (gxml
.GetWidget (name
) as Gtk
.Entry
).Text
= (contact
[name
] != null ? (contact
[name
] as string) : "");;
425 // Also fill the special cases
426 Notes
.Buffer
.Text
= (contact
["Notes"] != null ? (contact
["Notes"] as string) : "");
429 int tmp
= Convert
.ToInt32 (contact
["PreferMailFormat"]);
430 PreferredType
.Active
= (tmp
>= 0 && tmp
<= 2 ? tmp
: 0);
432 PreferredType
.Active
= 0;
435 Close
.Clicked
+= OnClose
;
437 Window
.Icon
= Beagle
.Images
.GetPixbuf ("contact-icon.png");
441 protected virtual void OnClose (object o
, EventArgs args
)