~ubuntu-branches/ubuntu/raring/blam/raring-proposed

« back to all changes in this revision

Viewing changes to src/Opml.cs

  • Committer: Bazaar Package Importer
  • Author(s): Johan Svedberg
  • Date: 2004-09-18 19:29:12 UTC
  • Revision ID: james.westby@ubuntu.com-20040918192912-rny8s6l2fuxikfr5
Tags: upstream-1.4.1
ImportĀ upstreamĀ versionĀ 1.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Author: 
 
3
//   Mikael Hallendal <micke@imendio.com>
 
4
//
 
5
// (C) 2004 Imendio HB
 
6
// 
 
7
 
 
8
using Gdk;
 
9
using Glade;
 
10
using Gtk;
 
11
using Mono.Posix;
 
12
using System;
 
13
using System.Collections;
 
14
using System.Globalization;
 
15
using System.IO;
 
16
using System.Text;
 
17
using System.Threading;
 
18
using System.Xml;
 
19
 
 
20
namespace Imendio.Blam {
 
21
 
 
22
    public class OpmlDialog {
 
23
        [Widget] Gtk.Dialog opmlDialog;
 
24
        [Widget] Gtk.Image  dialogImage;
 
25
        [Widget] Gtk.Entry  urlEntry;
 
26
        [Widget] Gtk.Button importButton;
 
27
 
 
28
        private Gtk.FileSelection fileDialog;
 
29
 
 
30
        private OpmlStatusDialog opmlStatusDialog;
 
31
 
 
32
        public event ChannelEventHandler   ChannelAdded;
 
33
        public event ActionFinishedHandler ImportFinished;
 
34
 
 
35
        Gtk.Window mParentWindow;
 
36
 
 
37
        public string Url {
 
38
            get {
 
39
                return urlEntry.Text;
 
40
            }
 
41
            set {
 
42
                urlEntry.Text = value;
 
43
            }
 
44
        }
 
45
 
 
46
        public OpmlDialog (Gtk.Window parentWindow)
 
47
        {
 
48
            Glade.XML gladeXML = Glade.XML.FromAssembly("blam.glade",
 
49
                                                        "opmlDialog",
 
50
                                                        null);
 
51
            gladeXML.Autoconnect(this);
 
52
 
 
53
            mParentWindow = parentWindow;
 
54
            opmlDialog.TransientFor = mParentWindow;
 
55
            opmlDialog.Icon = Gdk.Pixbuf.LoadFromResource("blam.png");
 
56
 
 
57
            dialogImage.Pixbuf = 
 
58
                Gdk.Pixbuf.LoadFromResource ("blam-add-news.png");
 
59
            
 
60
            Gtk.Drag.DestSet(opmlDialog, DestDefaults.All, 
 
61
                             Application.DragEntries, 
 
62
                             DragAction.Copy | DragAction.Move);
 
63
           
 
64
            opmlDialog.DragDataReceived += DragDataReceivedCb;
 
65
 
 
66
            opmlStatusDialog = new OpmlStatusDialog (parentWindow);
 
67
        }
 
68
 
 
69
        public void Show ()
 
70
        {
 
71
            urlEntry.Text = "";
 
72
            opmlDialog.ShowAll ();
 
73
        }
 
74
        
 
75
        private void DragDataReceivedCb(object o, DragDataReceivedArgs args)
 
76
        {
 
77
            SelectionData d = args.SelectionData;
 
78
            
 
79
            if (d.Length < 0 && d.Format != 8){
 
80
                Gtk.Drag.Finish(args.Context, false, false, args.Time);
 
81
                return;
 
82
            }
 
83
 
 
84
            UTF8Encoding encoding = new UTF8Encoding( );
 
85
            string text = encoding.GetString(d.Data);
 
86
           
 
87
            Url = text;
 
88
            
 
89
            Gtk.Drag.Finish(args.Context, true, true, args.Time);
 
90
        }
 
91
 
 
92
        private void FileButtonClicked(object obj, EventArgs args)
 
93
        {
 
94
            if (fileDialog == null) {
 
95
                fileDialog = new Gtk.FileSelection (Catalog.GetString ("Select OPML file"));
 
96
                fileDialog.Modal = true;
 
97
                fileDialog.ShowFileops = false;
 
98
            }
 
99
 
 
100
            fileDialog.TransientFor = this.opmlDialog;
 
101
            int result = fileDialog.Run();
 
102
            
 
103
            switch (result) {
 
104
            case (int)ResponseType.Ok: 
 
105
                urlEntry.Text = fileDialog.Filename;
 
106
                break;
 
107
            }
 
108
 
 
109
            fileDialog.Hide();
 
110
        }
 
111
 
 
112
        private int nrChannels;
 
113
 
 
114
        private void ChannelReadCb (Channel channel)
 
115
        {
 
116
            ++nrChannels;
 
117
 
 
118
            string status = String.Format (Catalog.GetString ("Imported {0} channels"), nrChannels);
 
119
 
 
120
            if (ChannelAdded != null) {
 
121
                ChannelAdded (channel);
 
122
            }
 
123
        }
 
124
 
 
125
        private void ImportFinishedCb ()
 
126
        {
 
127
            // FIXME: Signal this to application
 
128
            opmlStatusDialog.Hide ();
 
129
 
 
130
            if (ImportFinished != null) {
 
131
                ImportFinished (String.Format (Catalog.GetString ("Imported {0} channels from OPML file"), nrChannels));
 
132
            }
 
133
        }
 
134
 
 
135
        private void ImportErrorCb (string errorMsg)
 
136
        {
 
137
            opmlStatusDialog.Hide ();
 
138
 
 
139
            ShowErrorDialog (Url, errorMsg);
 
140
        }
 
141
 
 
142
        public void ShowErrorDialog (string url, string errorMsg)
 
143
        {
 
144
            string str = String.Format (Catalog.GetString ("Failed to import {0}"), url);
 
145
 
 
146
            Gtk.Dialog dialog = new HigDialog (mParentWindow,
 
147
                                               DialogFlags.Modal | DialogFlags.DestroyWithParent, 
 
148
                                               MessageType.Error,
 
149
                                               ButtonsType.Ok,
 
150
                                               str,
 
151
                                               errorMsg);
 
152
            dialog.Run ();
 
153
            dialog.Destroy ();
 
154
        }
 
155
        
 
156
        public static string GetXmlExceptionString ()
 
157
        {
 
158
            return Catalog.GetString ("Not a valid OPML file");
 
159
        }
 
160
 
 
161
        public static string GetFileNotFoundExceptionString ()
 
162
        {
 
163
            return Catalog.GetString ("File not found");
 
164
        }
 
165
 
 
166
        public static string GetUriFormatExceptionString ()
 
167
        {
 
168
            return Catalog.GetString ("Invalid file name");
 
169
        }
 
170
        
 
171
        public static string GetWebExceptionString ()
 
172
        {
 
173
            return Catalog.GetString ("Could not find OPML file");
 
174
        }
 
175
        
 
176
        public static string GetUnknownExceptionString ()
 
177
        {
 
178
            return Catalog.GetString ("Unknown error");
 
179
        }
 
180
        
 
181
        private void ImportButtonClicked (object obj, EventArgs args)
 
182
        {
 
183
            bool success = true;
 
184
            string errorMsg = "";
 
185
            
 
186
            try {
 
187
                Uri uri = new Uri (Url);
 
188
                OpmlReader reader = new OpmlReader (uri);
 
189
                reader.ChannelRead += ChannelReadCb;
 
190
                reader.ImportFinished += ImportFinishedCb;
 
191
                reader.ErrorEvent += ImportErrorCb;
 
192
 
 
193
                nrChannels = 0;
 
194
                opmlDialog.Hide ();
 
195
                if (!uri.IsFile) {
 
196
                    opmlStatusDialog.Show (Catalog.GetString ("Opening OPML file"));
 
197
                    reader.ReadChannelsAsync ();
 
198
                    return;
 
199
                } else {
 
200
                    reader.ReadChannels ();
 
201
                }
 
202
            }
 
203
            catch (XmlException) {
 
204
                errorMsg = GetXmlExceptionString ();
 
205
            }
 
206
            catch (FileNotFoundException) {
 
207
                errorMsg = GetFileNotFoundExceptionString ();
 
208
            }
 
209
            catch (UriFormatException) {
 
210
                errorMsg = GetUriFormatExceptionString ();
 
211
            }
 
212
            catch {
 
213
                errorMsg = GetUnknownExceptionString ();
 
214
            }
 
215
            
 
216
            opmlDialog.Hide ();
 
217
            ShowErrorDialog (Url, errorMsg);
 
218
        }
 
219
 
 
220
        private void CancelButtonClicked (object obj, EventArgs args)
 
221
        {
 
222
            opmlDialog.Hide ();
 
223
        }
 
224
 
 
225
        private void UrlEntryChanged (object obj, EventArgs args)
 
226
        {
 
227
            if (urlEntry.Text == "") {
 
228
                importButton.Sensitive = false;
 
229
            } else {
 
230
                importButton.Sensitive = true;
 
231
            }
 
232
        }
 
233
 
 
234
        private void UrlEntryActivated (object obj, EventArgs args)
 
235
        {
 
236
            if (urlEntry.Text == "") {
 
237
                return;
 
238
            }
 
239
 
 
240
            importButton.Click ();
 
241
        }
 
242
        
 
243
        public class OpmlStatusDialog {
 
244
            [Widget] Gtk.Dialog opmlStatusDialog;
 
245
            [Widget] Gtk.ProgressBar progressBar;
 
246
 
 
247
            private uint timeoutId;
 
248
            
 
249
            public OpmlStatusDialog (Gtk.Window parentWindow)
 
250
            {
 
251
                Glade.XML gladeXML = Glade.XML.FromAssembly("blam.glade",
 
252
                                                            "opmlStatusDialog",
 
253
                                                            null);
 
254
                gladeXML.Autoconnect(this);
 
255
                opmlStatusDialog.TransientFor = parentWindow;
 
256
                opmlStatusDialog.Icon = Gdk.Pixbuf.LoadFromResource("blam.png");
 
257
            }
 
258
 
 
259
            public void Show (string initialStatus)
 
260
            {
 
261
                timeoutId = GLib.Timeout.Add (100, new GLib.TimeoutHandler (UpdateProgress));
 
262
                opmlStatusDialog.ShowAll ();
 
263
            }
 
264
 
 
265
            public void Hide ()
 
266
            {
 
267
                opmlStatusDialog.Hide ();
 
268
                if (timeoutId > 0) {
 
269
                    GLib.Source.Remove (timeoutId);
 
270
                    timeoutId = 0;
 
271
                }
 
272
            }
 
273
 
 
274
            private void CancelButtonClicked (object obj, EventArgs args)
 
275
            {
 
276
                System.Console.WriteLine ("Cancel");
 
277
                opmlStatusDialog.Hide ();
 
278
            }
 
279
 
 
280
            private bool UpdateProgress ()
 
281
            {
 
282
                progressBar.Pulse ();
 
283
                return true;
 
284
            }
 
285
        }
 
286
    }
 
287
 
 
288
 
 
289
    public class OpmlReader {
 
290
 
 
291
        public delegate void ImportFinishedHandler ();
 
292
        public delegate void ErrorHandler (string errorMsg);
 
293
        
 
294
        public event ChannelEventHandler   ChannelRead;
 
295
        public event ImportFinishedHandler ImportFinished;
 
296
        public event ErrorHandler          ErrorEvent;
 
297
 
 
298
        private Uri           mUri;
 
299
 
 
300
        private string        mErrorMsg;
 
301
 
 
302
        private IList         mChannels;
 
303
        protected IList ReadList {
 
304
            get {
 
305
                return mChannels;
 
306
            }
 
307
        }
 
308
        
 
309
        public OpmlReader (Uri uri)
 
310
        {
 
311
            mUri = uri;
 
312
            mChannels = ArrayList.Synchronized (new ArrayList ());
 
313
        }
 
314
 
 
315
        public void ReadChannels ()
 
316
        {
 
317
            DoRead ();
 
318
        }
 
319
 
 
320
        public void ReadChannelsAsync ()
 
321
        {
 
322
            Thread thread = new Thread (new ThreadStart (ReadThread));
 
323
            thread.Start ();
 
324
        }
 
325
 
 
326
        private void DoRead ()
 
327
        {
 
328
            XmlTextReader reader = new XmlTextReader (mUri.ToString ());
 
329
        
 
330
            while (reader.Read ()) {
 
331
                string nodeName = reader.Name;
 
332
                string name;
 
333
                string url;
 
334
 
 
335
                // Ignore all other nodes
 
336
                if (nodeName == "outline") {
 
337
                    name = reader.GetAttribute ("text");
 
338
                    url = reader.GetAttribute ("xmlUrl");
 
339
 
 
340
                    if (name == null || url == null) {
 
341
                        continue;
 
342
                    }
 
343
 
 
344
                    Channel channel = new Channel (name, url);
 
345
                    new MainloopEmitter (this.ChannelRead, channel).Emit ();
 
346
                }
 
347
            }
 
348
            GLib.Idle.Add (new GLib.IdleHandler (EmitImportFinished));
 
349
        }
 
350
 
 
351
        private void ReadThread ()
 
352
        {
 
353
            try {
 
354
                XmlTextReader reader = new XmlTextReader (mUri.ToString ());
 
355
        
 
356
                while (reader.Read ()) {
 
357
                    string nodeName = reader.Name;
 
358
                    string name;
 
359
                    string url;
 
360
                    
 
361
                    // Ignore all other nodes
 
362
                    if (nodeName == "outline") {
 
363
                        name = reader.GetAttribute ("text");
 
364
                        url = reader.GetAttribute ("xmlUrl");
 
365
 
 
366
                        if (name == null || url == null) {
 
367
                            continue;
 
368
                        }
 
369
 
 
370
                        Channel channel = new Channel (name, url);
 
371
                        new MainloopEmitter (this.ChannelRead, channel).Emit ();
 
372
                    }
 
373
                }
 
374
                GLib.Idle.Add (new GLib.IdleHandler (EmitImportFinished));
 
375
                return;
 
376
            } 
 
377
            catch (XmlException) {
 
378
                mErrorMsg = OpmlDialog.GetXmlExceptionString ();
 
379
            }
 
380
            catch (FileNotFoundException) {
 
381
                mErrorMsg = OpmlDialog.GetFileNotFoundExceptionString ();
 
382
            }
 
383
            catch (UriFormatException) {
 
384
                mErrorMsg = OpmlDialog.GetUriFormatExceptionString ();
 
385
            }
 
386
            catch (System.Net.WebException) {
 
387
                mErrorMsg = OpmlDialog.GetWebExceptionString ();
 
388
            }
 
389
            catch {
 
390
                mErrorMsg = OpmlDialog.GetUnknownExceptionString ();
 
391
            }
 
392
 
 
393
            GLib.Idle.Add (new GLib.IdleHandler (EmitErrorEvent));
 
394
        }
 
395
 
 
396
        private bool EmitImportFinished ()
 
397
        {
 
398
            if (ImportFinished != null) {
 
399
                ImportFinished ();
 
400
            }
 
401
 
 
402
            return false;
 
403
        }
 
404
 
 
405
        private bool EmitErrorEvent ()
 
406
        {
 
407
            if (ErrorEvent != null) {
 
408
                ErrorEvent (mErrorMsg);
 
409
            }
 
410
 
 
411
            return false;
 
412
        }
 
413
    }
 
414
 
 
415
    public class OpmlWriter {
 
416
        public static void Write (ChannelCollection collection, string fileName)
 
417
        {
 
418
            XmlTextWriter xtw = new XmlTextWriter (fileName, null);
 
419
            
 
420
            xtw.Formatting = Formatting.Indented;
 
421
            xtw.Indentation = 2;
 
422
 
 
423
            xtw.WriteStartDocument ();
 
424
            xtw.WriteStartElement ("opml");
 
425
            xtw.WriteAttributeString ("version", "1.0");
 
426
            
 
427
            WriteHeader (xtw);
 
428
 
 
429
            WriteBody (xtw, collection);
 
430
 
 
431
            xtw.WriteEndElement ();
 
432
 
 
433
            xtw.Flush ();
 
434
            xtw.Close ();
 
435
        }
 
436
 
 
437
        private static void WriteHeader (XmlTextWriter xtw)
 
438
        {
 
439
            xtw.WriteStartElement ("head");
 
440
            
 
441
            xtw.WriteElementString ("dateCreated", DateTime.Now.ToString ("r"));
 
442
            
 
443
            xtw.WriteEndElement ();
 
444
        }
 
445
 
 
446
        private static void WriteBody (XmlTextWriter xtw, ChannelCollection collection)
 
447
        {
 
448
            xtw.WriteStartElement ("body");
 
449
 
 
450
            foreach (Channel channel in collection.Channels) {
 
451
                xtw.WriteStartElement ("outline");
 
452
                xtw.WriteAttributeString ("text", channel.Name);
 
453
                xtw.WriteAttributeString ("xmlUrl", channel.Url);
 
454
                xtw.WriteEndElement ();
 
455
            }
 
456
            
 
457
            xtw.WriteEndElement ();
 
458
        }
 
459
    }
 
460
}