~ted/ubuntu/lucid/tomboy/with-patch

« back to all changes in this revision

Viewing changes to Tomboy/Addins/GalagoPresence/GalagoPresenceNoteAddin.cs

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2007-07-16 10:26:35 UTC
  • mfrom: (1.1.21 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20070716102635-0wzk26jo50csob7b
Tags: 0.7.2-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
using System;
 
3
using System.Collections;
 
4
using System.Runtime.InteropServices;
 
5
using System.Diagnostics;
 
6
using Mono.Unix;
 
7
 
 
8
using Gtk;
 
9
using Galago;
 
10
 
 
11
using Tomboy;
 
12
 
 
13
// TODO: Indent everything in this namespace in a seperate commit
 
14
namespace Tomboy.GalagoPresence
 
15
{
 
16
 
 
17
class GalagoManager
 
18
{
 
19
        TrieTree trie;
 
20
 
 
21
        public GalagoManager ()
 
22
        {
 
23
                Galago.Global.Init ("tomboy", Galago.InitFlags.Client);
 
24
 
 
25
                ///// 
 
26
                ///// Connecting these cause crashes with the current 0.3.2 bindings...
 
27
                /////
 
28
                //Galago.Core.OnPersonAdded += OnPersonAdded;
 
29
                //Galago.Core.OnPersonRemoved += OnPersonRemoved;
 
30
                // This is just property change
 
31
                //Galago.Core.OnUpdated += OnUpdated;
 
32
 
 
33
                UpdateTrie (true);
 
34
        }
 
35
 
 
36
        public TrieTree Trie 
 
37
        {
 
38
                get { return trie; }
 
39
        }
 
40
 
 
41
        public event EventHandler PeopleChanged;
 
42
        public event EventHandler PresenceChanged;
 
43
 
 
44
        void OnUpdated (object sender, EventArgs args)
 
45
        {
 
46
                Logger.Log ("Got Presence Updated!");
 
47
                if (PresenceChanged != null)
 
48
                        PresenceChanged (this, args);
 
49
        }
 
50
 
 
51
        void OnPersonAdded (object sender, Galago.PersonAddedArgs args)
 
52
        {
 
53
                Logger.Log ("Person Added!");
 
54
 
 
55
                UpdateTrie (false);
 
56
                if (PeopleChanged != null)
 
57
                        PeopleChanged (this, args);
 
58
        }
 
59
 
 
60
        void OnPersonRemoved (object sender, Galago.PersonRemovedArgs args)
 
61
        {
 
62
                Logger.Log ("Person Removed!");
 
63
 
 
64
                UpdateTrie (false);
 
65
                if (PeopleChanged != null)
 
66
                        PeopleChanged (this, args);
 
67
        }
 
68
 
 
69
        void UpdateTrie (bool refresh_query)
 
70
        {
 
71
                trie = new TrieTree (false /* !case_sensitive */);
 
72
                ArrayList people = new ArrayList ();
 
73
 
 
74
                Logger.Log ("Loading up the person trie, Part 1...");
 
75
 
 
76
                foreach (Person person in Galago.Global.GetPeople (Galago.Origin.Remote, 
 
77
                                                                   refresh_query)) {
 
78
                        string name = person.DisplayName;
 
79
 
 
80
                        if (name != null) {
 
81
                                people.Add (new PersonLink (LinkType.PersonDisplayName, person));
 
82
                        }
 
83
 
 
84
                        foreach (Account account in person.GetAccounts(true)) {
 
85
                                if (account.DisplayName != null) {
 
86
                                        people.Add (new PersonLink (LinkType.AccountDisplayName, 
 
87
                                                                    account));
 
88
                                }
 
89
 
 
90
                                if (account.Username != null &&
 
91
                                    account.Username != account.DisplayName) {
 
92
                                        people.Add (new PersonLink (LinkType.AccountUserName, 
 
93
                                                                    account));
 
94
                                }
 
95
                        }
 
96
                }
 
97
 
 
98
                Logger.Log ("Loading up the person trie, Part 2...");
 
99
 
 
100
                foreach (PersonLink plink in people) {
 
101
                        trie.AddKeyword (plink.LinkText, plink);
 
102
                }
 
103
 
 
104
                Logger.Log ("Done.");
 
105
        }
 
106
}
 
107
 
 
108
enum LinkType
 
109
{
 
110
        PersonDisplayName,
 
111
        AccountUserName,
 
112
        AccountDisplayName,
 
113
}
 
114
 
 
115
class PersonLink
 
116
{
 
117
        LinkType link_type;
 
118
        Person   person;
 
119
        Account  account;
 
120
 
 
121
        public PersonLink (LinkType type, Person person)
 
122
        {
 
123
                this.link_type = type;
 
124
                this.person = person;
 
125
                this.account = null;
 
126
 
 
127
                Logger.Log ("Added person {0}: {1}", link_type, LinkText);
 
128
        }
 
129
 
 
130
        public PersonLink (LinkType type, Account account)
 
131
        {
 
132
                this.link_type = type;
 
133
                this.person = account.Person;
 
134
                this.account = account;         
 
135
 
 
136
                Logger.Log ("Added account {0}: {1}", link_type, LinkText);
 
137
        }
 
138
 
 
139
        public string LinkText
 
140
        {
 
141
                get {
 
142
                        
 
143
                        switch (link_type) {
 
144
                        case LinkType.PersonDisplayName:
 
145
                                return person.DisplayName;
 
146
                        case LinkType.AccountUserName:
 
147
                                return account.Username;
 
148
                        case LinkType.AccountDisplayName:
 
149
                                return account.DisplayName;
 
150
                        }
 
151
                        return null;
 
152
                }
 
153
        }
 
154
 
 
155
        Account GetBestAccount ()
 
156
        {
 
157
                if (account != null)
 
158
                        return account;
 
159
 
 
160
                if (person != null) {
 
161
                        Account best = person.PriorityAccount;
 
162
                        
 
163
                        Logger.Log ("Using priority account '{0}' for {1}", 
 
164
                                    best.Username, 
 
165
                                    LinkText);
 
166
 
 
167
                        return best;
 
168
                }
 
169
                return null;
 
170
        }
 
171
 
 
172
        public void SendMessage ()
 
173
        {
 
174
                Account best = GetBestAccount ();
 
175
                if (best == null)
 
176
                        throw new Exception ("No accounts associated with this person");
 
177
 
 
178
                Process p = new Process ();
 
179
                p.StartInfo.FileName = "gaim-remote";
 
180
                p.StartInfo.Arguments = 
 
181
                        "uri " + 
 
182
                        best.Service.Id + ":goim?screenname=" + best.Username;
 
183
                p.StartInfo.UseShellExecute = false;
 
184
 
 
185
                p.Start ();
 
186
        }
 
187
 
 
188
        [DllImport("libgalago-gtk")]
 
189
        static extern IntPtr galago_gdk_pixbuf_new_from_presence (IntPtr presence,
 
190
                                                                  int width,
 
191
                                                                  int height,
 
192
                                                                  int precedence);
 
193
 
 
194
        public Gdk.Pixbuf GetPresenceIcon ()
 
195
        {
 
196
                Account best = GetBestAccount ();
 
197
                if (best != null &&
 
198
                    best.Presence != null) {
 
199
                        IntPtr icon = galago_gdk_pixbuf_new_from_presence (best.Presence.Handle,
 
200
                                                                           16, 16,
 
201
                                                                           4);
 
202
                        if (icon != IntPtr.Zero)
 
203
                                return new Gdk.Pixbuf (icon);
 
204
                }
 
205
                return null;
 
206
        }
 
207
}
 
208
 
 
209
class PersonTag : NoteTag
 
210
{
 
211
        GalagoManager galago;
 
212
 
 
213
        public PersonTag (string tag_name, GalagoManager galago)
 
214
                : base (tag_name)
 
215
        {
 
216
                this.galago = galago;
 
217
        }
 
218
 
 
219
        public override void Initialize (string element_name)
 
220
        {
 
221
                base.Initialize (element_name);
 
222
 
 
223
                Underline = Pango.Underline.Single;
 
224
                Foreground = "blue";
 
225
                CanSerialize = false;
 
226
                CanActivate = true;
 
227
        }
 
228
        
 
229
        protected override bool OnActivate (NoteEditor editor,
 
230
                                            Gtk.TextIter start, 
 
231
                                            Gtk.TextIter end)
 
232
        {
 
233
                string persona = start.GetText (end);
 
234
                PersonLink plink = (PersonLink) galago.Trie.Lookup (persona);
 
235
 
 
236
                try {
 
237
                        plink.SendMessage ();
 
238
                } catch (Exception e) {
 
239
                        string title = Catalog.GetString ("Cannot contact '{0}'");
 
240
                        title = String.Format (title, persona);
 
241
 
 
242
                        string message = Catalog.GetString ("Error running gaim-remote: {0}");
 
243
                        message = String.Format (message, e.Message);
 
244
 
 
245
                        Logger.Log (message);
 
246
 
 
247
                        HIGMessageDialog dialog = 
 
248
                                new HIGMessageDialog (editor.Toplevel as Gtk.Window,
 
249
                                                      Gtk.DialogFlags.DestroyWithParent,
 
250
                                                      Gtk.MessageType.Info,
 
251
                                                      Gtk.ButtonsType.Ok,
 
252
                                                      title,
 
253
                                                      message);
 
254
                        dialog.Run ();
 
255
                        dialog.Destroy ();
 
256
                }
 
257
 
 
258
                return true;
 
259
        }
 
260
}
 
261
 
 
262
        
 
263
public class GalagoPresenceNoteAddin : NoteAddin
 
264
{
 
265
        static GalagoManager galago;
 
266
        Gtk.TextTag person_tag;
 
267
        Gtk.TextTag link_tag;
 
268
        Gtk.TextTag url_tag;
 
269
 
 
270
        static GalagoPresenceNoteAddin ()
 
271
        {
 
272
                galago = new GalagoManager ();
 
273
        }
 
274
 
 
275
        public GalagoPresenceNoteAddin ()
 
276
        {
 
277
                // Do nothing.
 
278
        }
 
279
 
 
280
        public override void Initialize ()
 
281
        {
 
282
                person_tag = Note.TagTable.Lookup ("link:person");
 
283
                if (person_tag == null) {
 
284
                        person_tag = new PersonTag ("link:person", galago);
 
285
 
 
286
                        Logger.Log ("Adding link:person tag...");
 
287
                        Note.TagTable.Add (person_tag);
 
288
                }
 
289
 
 
290
                link_tag = Note.TagTable.Lookup ("link:internal");
 
291
                url_tag = Note.TagTable.Lookup ("link:url");
 
292
        }
 
293
 
 
294
        public override void Shutdown ()
 
295
        {
 
296
                galago.PeopleChanged -= OnPeopleChanged;
 
297
                galago.PresenceChanged -= OnPresenceChanged;
 
298
        }
 
299
 
 
300
        public override void OnNoteOpened () 
 
301
        {
 
302
                galago.PeopleChanged += OnPeopleChanged;
 
303
                galago.PresenceChanged += OnPresenceChanged;
 
304
 
 
305
                Buffer.InsertText += OnInsertText;
 
306
                Buffer.DeleteRange += OnDeleteRange;
 
307
 
 
308
                // Highlight existing people in note
 
309
                HighlightInBlock (Buffer.StartIter, Buffer.EndIter);
 
310
        }
 
311
 
 
312
        void OnPeopleChanged (object sender, EventArgs args)
 
313
        {
 
314
                // Highlight people in note
 
315
                UnhighlightInBlock (Buffer.StartIter, Buffer.EndIter);
 
316
                HighlightInBlock (Buffer.StartIter, Buffer.EndIter);
 
317
        }
 
318
 
 
319
        void OnPresenceChanged (object sender, EventArgs args)
 
320
        {
 
321
                // Highlight people in note
 
322
                UnhighlightInBlock (Buffer.StartIter, Buffer.EndIter);
 
323
                HighlightInBlock (Buffer.StartIter, Buffer.EndIter);
 
324
        }
 
325
 
 
326
        void HighlightInBlock (Gtk.TextIter start, Gtk.TextIter end) 
 
327
        {
 
328
                foreach (TrieHit hit in galago.Trie.FindMatches (start.GetText (end))) {
 
329
                        Gtk.TextIter match_start = 
 
330
                                Buffer.GetIterAtOffset(start.Offset + hit.Start);
 
331
                        
 
332
                        // Don't create links inside note or URL links
 
333
                        if (match_start.HasTag (url_tag) ||
 
334
                            match_start.HasTag (link_tag))
 
335
                                continue;
 
336
                        
 
337
                        Gtk.TextIter match_end = match_start;
 
338
                        match_end.ForwardChars (hit.End - hit.Start);
 
339
 
 
340
                        Logger.Log ("Matching Person '{0}' at {1}-{2}...", 
 
341
                                    hit.Key, 
 
342
                                    hit.Start, 
 
343
                                    hit.End);
 
344
                        Buffer.ApplyTag (person_tag, match_start, match_end);
 
345
                }
 
346
        }
 
347
 
 
348
        void UnhighlightInBlock (Gtk.TextIter start, Gtk.TextIter end) 
 
349
        {
 
350
                Buffer.RemoveTag (person_tag, start, end);
 
351
        }
 
352
 
 
353
        void GetBlockExtents (ref Gtk.TextIter start, ref Gtk.TextIter end) 
 
354
        {
 
355
                // FIXME: Should only be processing the largest match string
 
356
                // size, so we don't slow down for large paragraphs 
 
357
                
 
358
                start.LineOffset = 0;
 
359
                end.ForwardToLineEnd ();
 
360
        }
 
361
 
 
362
        void OnDeleteRange (object sender, Gtk.DeleteRangeArgs args)
 
363
        {
 
364
                Gtk.TextIter start = args.Start;
 
365
                Gtk.TextIter end = args.End;
 
366
 
 
367
                GetBlockExtents (ref start, ref end);
 
368
                
 
369
                UnhighlightInBlock (start, end);
 
370
                HighlightInBlock (start, end);
 
371
        }
 
372
 
 
373
        void OnInsertText (object sender, Gtk.InsertTextArgs args)
 
374
        {
 
375
                Gtk.TextIter start = args.Pos;
 
376
                start.BackwardChars (args.Length);
 
377
 
 
378
                Gtk.TextIter end = args.Pos;
 
379
 
 
380
                GetBlockExtents (ref start, ref end);
 
381
 
 
382
                UnhighlightInBlock (start, end);
 
383
                HighlightInBlock (start, end);
 
384
        }
 
385
}
 
386
 
 
387
}