PageRenderTime 83ms CodeModel.GetById 21ms app.highlight 54ms RepoModel.GetById 1ms app.codeStats 1ms

/SparkleShare/SparkleSetup.cs

http://github.com/hbons/SparkleShare
C# | 649 lines | 444 code | 178 blank | 27 comment | 21 complexity | 99bcbef9c10dbdcea299f37c99b46541 MD5 | raw file
  1//   SparkleShare, a collaboration and sharing tool.
  2//   Copyright (C) 2010  Hylke Bons <hylkebons@gmail.com>
  3//
  4//   This program is free software: you can redistribute it and/or modify
  5//   it under the terms of the GNU General private License as published by
  6//   the Free Software Foundation, either version 3 of the License, or
  7//   (at your option) any later version.
  8//
  9//   This program is distributed in the hope that it will be useful,
 10//   but WITHOUT ANY WARRANTY; without even the implied warranty of
 11//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 12//   GNU General private License for more details.
 13//
 14//   You should have received a copy of the GNU General private License
 15//   along with this program. If not, see <http://www.gnu.org/licenses/>.
 16
 17
 18using System;
 19using System.Diagnostics;
 20using System.IO;
 21using System.Text.RegularExpressions;
 22using System.Timers;
 23using System.Collections.Generic;
 24
 25using Gtk;
 26using Mono.Unix;
 27
 28namespace SparkleShare {
 29
 30    public class SparkleSetup : SparkleSetupWindow {
 31
 32        public SparkleSetupController Controller = new SparkleSetupController ();
 33
 34        private string SecondaryTextColor;
 35        private string SecondaryTextColorSelected;
 36
 37        private ProgressBar progress_bar = new ProgressBar ();
 38        
 39
 40        // Short alias for the translations
 41        public static string _ (string s)
 42        {
 43            return Catalog.GetString (s);
 44        }
 45
 46
 47        public SparkleSetup () : base ()
 48        {
 49            SecondaryTextColor         = SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Insensitive));
 50            SecondaryTextColorSelected =
 51                SparkleUIHelpers.GdkColorToHex (
 52                    MixColors (
 53                        new TreeView ().Style.Foreground (StateType.Selected),
 54                        new TreeView ().Style.Background (StateType.Selected),
 55                        0.15
 56                    )
 57                );
 58
 59            Controller.ChangePageEvent += delegate (PageType type, string [] warnings) {
 60                Application.Invoke (delegate {
 61                    Reset ();
 62
 63                    switch (type) {
 64                    case PageType.Setup: {
 65
 66                        Header = _("Welcome to SparkleShare!");
 67                        Description  = "We'll need some info to mark your changes in the event log. " +
 68                                       "Don't worry, this stays between you and your peers.";
 69
 70
 71                        Table table = new Table (2, 3, true) {
 72                            RowSpacing    = 6,
 73                            ColumnSpacing = 6
 74                        };
 75
 76                            Label name_label = new Label ("<b>" + _("Full Name:") + "</b>") {
 77                                UseMarkup = true,
 78                                Xalign    = 1
 79                            };
 80
 81                            Entry name_entry = new Entry (Controller.GuessedUserName) {
 82                                Xalign = 0
 83                            };
 84
 85                            Entry email_entry = new Entry (Controller.GuessedUserEmail) {
 86                                Xalign = 0
 87                            };
 88                            
 89                            name_entry.Changed += delegate {
 90                                Controller.CheckSetupPage (name_entry.Text, email_entry.Text);
 91                            };
 92                           
 93                            email_entry.Changed += delegate {
 94                                Controller.CheckSetupPage (name_entry.Text, email_entry.Text);
 95                            };
 96
 97                            Label email_label = new Label ("<b>" + _("Email:") + "</b>") {
 98                                UseMarkup = true,
 99                                Xalign    = 1
100                            };
101
102                        table.Attach (name_label, 0, 1, 0, 1);
103                        table.Attach (name_entry, 1, 2, 0, 1);
104                        table.Attach (email_label, 0, 1, 1, 2);
105                        table.Attach (email_entry, 1, 2, 1, 2);
106                        
107                        VBox wrapper = new VBox (false, 9);
108                        wrapper.PackStart (table, true, false, 0);
109
110                            Button continue_button = new Button (_("Continue")) {
111                                Sensitive = false
112                            };
113
114                            continue_button.Clicked += delegate (object o, EventArgs args) {
115                                string full_name = name_entry.Text;
116                                string email     = email_entry.Text;
117
118                                Controller.SetupPageCompleted (full_name, email);
119                            };
120
121                        AddButton (continue_button);
122                        Add (wrapper);
123
124
125                        Controller.UpdateSetupContinueButtonEvent += delegate (bool button_enabled) {
126                            Application.Invoke (delegate {
127                                continue_button.Sensitive = button_enabled;
128                            });
129                        };
130
131                        Controller.CheckSetupPage (name_entry.Text, email_entry.Text);
132
133                        break;
134                    } 
135
136                    case PageType.Add: {
137
138                        Header = _("Where's your project hosted?");
139
140                        VBox layout_vertical = new VBox (false, 12);
141                        HBox layout_fields   = new HBox (true, 12);
142                        VBox layout_address  = new VBox (true, 0);
143                        VBox layout_path     = new VBox (true, 0);
144
145
146                        ListStore store = new ListStore (typeof (Gdk.Pixbuf),
147                            typeof (string), typeof (SparklePlugin));
148
149                        SparkleTreeView tree = new SparkleTreeView (store) { HeadersVisible = false };
150                        ScrolledWindow scrolled_window = new ScrolledWindow ();
151                        scrolled_window.AddWithViewport (tree);
152
153                        // Icon column
154                        tree.AppendColumn ("Icon", new Gtk.CellRendererPixbuf (), "pixbuf", 0);
155                        tree.Columns [0].Cells [0].Xpad = 6;
156
157                        // Service column
158                        TreeViewColumn service_column = new TreeViewColumn () { Title = "Service" };
159                        CellRendererText service_cell = new CellRendererText () { Ypad = 4 };
160                        service_column.PackStart (service_cell, true);
161                        service_column.SetCellDataFunc (service_cell, new TreeCellDataFunc (RenderServiceColumn));
162
163                        foreach (SparklePlugin plugin in Controller.Plugins) {
164                            store.AppendValues (
165                                new Gdk.Pixbuf (plugin.ImagePath),
166                                "<span size=\"small\"><b>" + plugin.Name + "</b>\n" +
167                                  "<span fgcolor=\"" + SecondaryTextColorSelected + "\">" +
168                                  plugin.Description + "</span>" +
169                                "</span>",
170                                plugin);
171                        }
172
173                        tree.AppendColumn (service_column);
174
175                        SparkleEntry path_entry    = new SparkleEntry ();
176                        SparkleEntry address_entry = new SparkleEntry ();
177
178
179                        // Select the first plugin by default
180                        TreeSelection default_selection = tree.Selection;
181                        TreePath default_path = new TreePath ("0");
182                        default_selection.SelectPath (default_path);
183                        Controller.SelectedPluginChanged (0);
184
185                        Controller.ChangeAddressFieldEvent += delegate (string text,
186                            string example_text, FieldState state) {
187
188                            Application.Invoke (delegate {
189                                address_entry.Text        = text;
190                                address_entry.Sensitive   = (state == FieldState.Enabled);
191
192                                if (string.IsNullOrEmpty (example_text))
193                                    address_entry.ExampleText = null;
194                                else
195                                    address_entry.ExampleText = example_text;
196
197                                if (string.IsNullOrEmpty (text))
198                                    address_entry.ExampleTextActive = true;
199                                else
200                                    address_entry.ExampleTextActive = false;
201                            });
202                        };
203
204                        Controller.ChangePathFieldEvent += delegate (string text,
205                            string example_text, FieldState state) {
206
207                            Application.Invoke (delegate {
208                                path_entry.Text        = text;
209                                path_entry.Sensitive   = (state == FieldState.Enabled);
210
211                                if (string.IsNullOrEmpty (example_text))
212                                    path_entry.ExampleText = null;
213                                else
214                                    path_entry.ExampleText = example_text;
215
216                                if (string.IsNullOrEmpty (text))
217                                    path_entry.ExampleTextActive = true;
218                                else
219                                    path_entry.ExampleTextActive = false;
220                            });
221                        };
222
223                        // Update the address field text when the selection changes
224                        tree.CursorChanged += delegate (object sender, EventArgs e) {
225                            Controller.SelectedPluginChanged (tree.SelectedRow);
226                            // TODO: Scroll to selected row when using arrow keys
227                        };
228
229                        tree.Model.Foreach (new TreeModelForeachFunc (delegate (TreeModel model,
230                            TreePath path, TreeIter iter) {
231
232                            string address;
233
234                            try {
235                                address = (model.GetValue (iter, 2) as SparklePlugin).Address;
236
237                            } catch (NullReferenceException) {
238                                address = "";
239                            }
240
241                            if (!string.IsNullOrEmpty (address) &&
242                                address.Equals (Controller.PreviousAddress)) {
243
244                                tree.SetCursor (path, service_column, false);
245                                SparklePlugin plugin = (SparklePlugin) model.GetValue (iter, 2);
246
247                                if (plugin.Address != null) {
248                                    address_entry.Sensitive = false;}
249
250                                if (plugin.Path != null)
251                                    path_entry.Sensitive = false;
252
253                                // TODO: Scroll to the selection
254
255                                return true;
256                            } else {
257                                return false;
258                            }
259                        }));
260
261                        address_entry.Completion = new EntryCompletion();
262                        ListStore server_store = new ListStore (typeof (string));
263
264                        foreach (string host in Program.Controller.PreviousHosts)
265                            server_store.AppendValues (host);
266
267                        address_entry.Completion.Model      = server_store;
268                        address_entry.Completion.TextColumn = 0;
269
270                        address_entry.Changed += delegate {
271                            Controller.CheckAddPage (address_entry.Text, path_entry.Text, tree.SelectedRow);
272                        };
273
274                                layout_address.PackStart (new Label () {
275                                        Markup = "<b>" + _("Address") + "</b>",
276                                        Xalign = 0
277                                    }, true, true, 0);
278
279                                layout_address.PackStart (address_entry, true, true, 0);
280
281                                    path_entry.Completion  = new EntryCompletion();
282
283                                    ListStore folder_store = new ListStore (typeof (string));
284
285                                    //foreach (string host in Program.Controller.FolderPaths)
286                                    //    folder_store.AppendValues (host);
287
288                                    path_entry.Completion.Model      = folder_store;
289                                    path_entry.Completion.TextColumn = 0;
290
291                                    path_entry.Changed += delegate {
292                                        Controller.CheckAddPage (address_entry.Text, path_entry.Text, tree.SelectedRow);
293                                    };
294
295                                layout_path.PackStart (new Label () {
296                                        Markup = "<b>" + _("Remote Path") + "</b>",
297                                        Xalign = 0
298                                    }, true, true, 0);
299                                
300                                layout_path.PackStart (path_entry, true, true, 0);
301
302                            layout_fields.PackStart (layout_address);
303                            layout_fields.PackStart (layout_path);
304
305                        layout_vertical.PackStart (new Label (""), false, false, 0);
306                        layout_vertical.PackStart (scrolled_window, true, true, 0);
307                        layout_vertical.PackStart (layout_fields, false, false, 0);
308
309                        Add (layout_vertical);
310
311                            // Cancel button
312                            Button cancel_button = new Button (_("Cancel"));
313
314                            cancel_button.Clicked += delegate {
315                                Close ();
316                            };
317
318                            // Sync button
319                            Button add_button = new Button (_("Add"));
320
321                            add_button.Clicked += delegate {
322                                string server         = address_entry.Text;
323                                string folder_name    = path_entry.Text;
324
325                                Controller.AddPageCompleted (server, folder_name);
326                            };
327
328                        AddButton (cancel_button);
329                        AddButton (add_button);
330
331                        Controller.CheckAddPage (address_entry.Text, path_entry.Text, tree.SelectedRow);
332
333                        break;
334                    }
335
336                    case PageType.Syncing: {
337
338                        Header      = String.Format (_("Adding project ‘{0}’…"), Controller.SyncingFolder);
339                        Description = _("This may take a while.") + Environment.NewLine +
340                                      _("Are you sure it’s not coffee o'clock?");
341
342                        Button finish_button = new Button () {
343                            Sensitive = false,
344                            Label = _("Finish")
345                        };
346
347                        Button cancel_button = new Button () {
348                            Label = _("Cancel")
349                        };
350
351                        cancel_button.Clicked += delegate {
352                            Controller.SyncingCancelled ();
353                        };
354
355                        AddButton (cancel_button);
356                        AddButton (finish_button);
357
358                        Controller.UpdateProgressBarEvent += delegate (double percentage) {
359                            Application.Invoke (delegate {
360                                this.progress_bar.Fraction = percentage / 100;
361                            });
362                        };
363
364                        if (this.progress_bar.Parent != null)
365                           (this.progress_bar.Parent as Container).Remove (this.progress_bar);
366
367                        VBox bar_wrapper = new VBox (false , 0);
368                        bar_wrapper.PackStart (this.progress_bar, false, false, 0);
369
370                        Add (bar_wrapper);
371
372                        break;
373                    }
374
375                    case PageType.Error: {
376
377                        Header      = _("Something went wrong") + "…";
378
379						VBox points = new VBox (false, 0);
380						Image list_point_one   = new Image (SparkleUIHelpers.GetIcon ("list-point", 16)) {  };
381						Image list_point_two   = new Image (SparkleUIHelpers.GetIcon ("list-point", 16)) {  };
382						Image list_point_three = new Image (SparkleUIHelpers.GetIcon ("list-point", 16)) {  };
383
384                        Label label_one = new Label () {
385                            Text   = "First, have you tried turning it off and on again?",
386                            Wrap   = true,
387                            Xalign = 0
388                        };
389
390                        Label label_two = new Label () {
391                            Markup = "<b>" + Controller.PreviousUrl + "</b> is the address we've compiled. " +
392                                     "Does this look alright?",
393                            Wrap   = true,
394                            Xalign = 0
395                        };
396
397                        Label label_three = new Label () {
398                            Text   = "The host needs to know who you are. Did you upload the key that's in " +
399                                     "your SparkleShare folder?",
400                            Wrap   = true,
401                            Xalign = 0
402                        };
403
404						
405                        points.PackStart (new Label ("Please check the following:") { Xalign = 0 }, false, false, 6);
406
407                        HBox point_one = new HBox (false, 0);
408						point_one.PackStart (list_point_one, false, false, 0);
409						point_one.PackStart (label_one, true, true, 12);
410						points.PackStart (point_one, false, false, 12);
411						
412						HBox point_two = new HBox (false, 0);
413						point_two.PackStart (list_point_two, false, false, 0);
414						point_two.PackStart (label_two, true, true, 12);
415						points.PackStart (point_two, false, false, 12);
416                          
417                        HBox point_three = new HBox (false, 0);
418						point_three.PackStart (list_point_three, false, false, 0);
419						point_three.PackStart (label_three, true, true, 12);
420						points.PackStart (point_three, false, false, 12);
421
422                        points.PackStart (new Label (""), true, true, 0);
423
424
425                        Button try_again_button = new Button (_("Try Again…")) {
426                            Sensitive = true
427                        };
428
429                        try_again_button.Clicked += delegate {
430                            Controller.ErrorPageCompleted ();
431                        };
432
433                        AddButton (try_again_button);
434                        Add (points);
435
436                        break;
437                    }
438
439                    case PageType.Finished: {
440
441                        UrgencyHint = true;
442
443                        if (!HasToplevelFocus) {
444                            string title   = String.Format (_("‘{0}’ has been successfully added"), Controller.SyncingFolder);
445                            string subtext = "";
446
447                            SparkleUI.Bubbles.Controller.ShowBubble (title, subtext, null);
448                        }
449
450                        Header      = _("Project successfully added!");
451                        Description = _("Access the files from your SparkleShare folder.");
452
453                        // A button that opens the synced folder
454                        Button open_folder_button = new Button (_("Open Folder"));
455
456                        open_folder_button.Clicked += delegate {
457                            Program.Controller.OpenSparkleShareFolder (Controller.SyncingFolder);
458                        };
459
460                        Button finish_button = new Button (_("Finish"));
461
462                        finish_button.Clicked += delegate {
463                            Controller.FinishedPageCompleted ();
464                            Close ();
465                        };
466
467
468                        if (warnings != null) {
469                            Image warning_image = new Image (
470                                SparkleUIHelpers.GetIcon ("dialog-warning", 24)
471                            );
472
473                            Label warning_label = new Label (warnings [0]) {
474                                Xalign = 0,
475                                Wrap   = true
476                            };
477
478                            HBox warning_layout = new HBox (false, 0);
479                            warning_layout.PackStart (warning_image, false, false, 0);
480                            warning_layout.PackStart (warning_label, true, true, 15);
481                            
482                            VBox warning_wrapper = new VBox (false, 0);
483                            warning_wrapper.PackStart (warning_layout, false, false, 0);
484
485                            Add (warning_wrapper);
486
487                        } else {
488                            Add (null);
489                        }
490
491
492                        AddButton (open_folder_button);
493                        AddButton (finish_button);
494
495                        break;
496                    }
497
498
499                    case PageType.Tutorial: {
500
501                        switch (Controller.TutorialPageNumber) {
502                        case 1: {
503                            Header      = _("What's happening next?");
504                            Description = _("SparkleShare creates a special folder in your personal folder " +
505                                "that will keep track of your projects.");
506
507                            Button skip_tutorial_button = new Button (_("Skip Tutorial"));
508                            skip_tutorial_button.Clicked += delegate {
509                                Controller.TutorialSkipped ();
510                            };
511
512                            Button continue_button = new Button (_("Continue"));
513                            continue_button.Clicked += delegate {
514                                Controller.TutorialPageCompleted ();
515                            };
516
517                            Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-1.png");
518
519                            Add (slide);
520
521                            AddButton (skip_tutorial_button);
522                            AddButton (continue_button);
523
524                            break;
525                        }
526
527                        case 2: {
528                            Header      = _("Sharing files with others");
529                            Description = _("All files added to your project folders are synced with the host " +
530                                "automatically, as well as with your collaborators.");
531
532                            Button continue_button = new Button (_("Continue"));
533                            continue_button.Clicked += delegate {
534                                Controller.TutorialPageCompleted ();
535                            };
536
537                            Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-2.png");
538
539                            Add (slide);
540                            AddButton (continue_button);
541
542                            break;
543                        }
544
545                        case 3: {
546                            Header      = _("The status icon is here to help");
547                            Description = _("It shows the syncing process status, " +
548                                "and contains links to your projects and the event log.");
549
550                            Button continue_button = new Button (_("Continue"));
551                            continue_button.Clicked += delegate {
552                                Controller.TutorialPageCompleted ();
553                            };
554
555                            Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-3.png");
556
557                            Add (slide);
558                            AddButton (continue_button);
559
560                            break;
561                        }
562
563                        case 4: {
564                            Header      = _("Adding projects to SparkleShare");
565                            Description = _("Just click this button when you see it on the web, and " +
566                                "the project will be automatically added:");
567
568                            Label label = new Label (_("…or select <b>‘Add Hosted Project…’</b> from the status icon menu " +
569                                "to add one by hand.")) {
570                                Wrap   = true,
571                                Xalign = 0,
572                                UseMarkup = true
573                            };
574
575                            Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-4.png");
576
577                            Button finish_button = new Button (_("Finish"));
578                            finish_button.Clicked += delegate {
579                                Close ();
580                            };
581
582
583                            VBox box = new VBox (false, 0);
584                            box.Add (slide);
585                            box.Add (label);
586
587                            Add (box);
588                            AddButton (finish_button);
589
590                            break;
591                        }
592                        }
593
594                        break;
595                    }
596                    }
597
598                    ShowAll ();
599                });
600            };
601        }
602
603
604        private void RenderServiceColumn (TreeViewColumn column, CellRenderer cell,
605            TreeModel model, TreeIter iter)
606        {
607            string markup           = (string) model.GetValue (iter, 1);
608            TreeSelection selection = (column.TreeView as TreeView).Selection;
609
610            if (selection.IterIsSelected (iter))
611                markup = markup.Replace (SecondaryTextColor, SecondaryTextColorSelected);
612            else
613                markup = markup.Replace (SecondaryTextColorSelected, SecondaryTextColor);
614
615            (cell as CellRendererText).Markup = markup;
616        }
617
618
619        private Gdk.Color MixColors (Gdk.Color first_color, Gdk.Color second_color, double ratio)
620        {
621            return new Gdk.Color (
622                Convert.ToByte ((255 * (Math.Min (65535, first_color.Red   * (1.0 - ratio) + second_color.Red   * ratio))) / 65535),
623                Convert.ToByte ((255 * (Math.Min (65535, first_color.Green * (1.0 - ratio) + second_color.Green * ratio))) / 65535),
624                Convert.ToByte ((255 * (Math.Min (65535, first_color.Blue  * (1.0 - ratio) + second_color.Blue  * ratio))) / 65535)
625            );
626        }
627    }
628
629
630    public class SparkleTreeView : TreeView {
631
632        public int SelectedRow
633        {
634            get {
635                TreeIter iter;
636                TreeModel model;
637
638                Selection.GetSelected (out model, out iter);
639
640                return int.Parse (model.GetPath (iter).ToString ());
641            }
642        }
643
644
645        public SparkleTreeView (ListStore store) : base (store)
646        {
647        }
648    }
649}