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

« back to all changes in this revision

Viewing changes to Tomboy/Plugins/GalagoPresence.cs

Tags: upstream-0.7.2
Import upstream version 0.7.2

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