1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/***
3  BEGIN LICENSE
4
5  Copyright (C) 2011-2012 Giulio Collura <random.cpp@gmail.com>
6  This program is free software: you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License version 3, as published
8  by the Free Software Foundation.
9
10  This program is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranties of
12  MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13  PURPOSE.  See the GNU General Public License for more details.
14
15  You should have received a copy of the GNU General Public License along
16  with this program.  If not, see <http://www.gnu.org/licenses/>
17
18  END LICENSE
19***/
20
21using Scratch.Services;
22
23namespace Scratch.Dialogs {
24
25    public class PasteBinDialog : Granite.Dialog {
26
27        public string[,] languages = {
28            //if default, code, desc, Code-equivalent
29            {"n", "text", "None", "text"},
30            {"n", "4cs", "4CS", ""},
31            {"n", "6502acme", "6502 ACME Cross Assembler", ""},
32            {"n", "6502kickass", "6502 Kick Assembler", ""},
33            {"n", "6502tasm", "6502 TASM/64TASS", ""},
34            {"n", "abap", "ABAP", ""},
35            {"n", "actionscript", "ActionScript", ""},
36            {"n", "actionscript3", "ActionScript 3", ""},
37            {"n", "ada", "Ada", ""},
38            {"n", "algol68", "ALGOL 68", ""},
39            {"n", "apache", "Apache Log", ""},
40            {"n", "applescript", "AppleScript", ""},
41            {"n", "apt_sources", "APT Sources", ""},
42            {"n", "asm", "ASM (NASM)", ""},
43            {"n", "asp", "ASP", ""},
44            {"n", "autoconf", "autoconf", ""},
45            {"n", "autohotkey", "Autohotkey", ""},
46            {"n", "autoit", "AutoIt", ""},
47            {"n", "avisynth", "Avisynth", ""},
48            {"n", "awk", "Awk", ""},
49            {"n", "bascomavr", "BASCOM AVR", ""},
50            {"n", "bash", "Bash", "sh"},
51            {"n", "basic4gl", "Basic4GL", ""},
52            {"n", "bibtex", "BibTeX", ""},
53            {"n", "blitzbasic", "Blitz Basic", ""},
54            {"n", "bnf", "BNF", ""},
55            {"n", "boo", "BOO", ""},
56            {"n", "bf", "BrainFuck", ""},
57            {"n", "c", "C", "c"},
58            {"n", "c_mac", "C for Macs", ""},
59            {"n", "cil", "C Intermediate Language", ""},
60            {"n", "csharp", "C#", "c-sharp"},
61            {"n", "cpp", "C++", "cpp"},
62            {"n", "cpp-qt", "C++ (with QT extensions)", ""},
63            {"n", "c_loadrunner", "C: Loadrunner", ""},
64            {"n", "caddcl", "CAD DCL", ""},
65            {"n", "cadlisp", "CAD Lisp", ""},
66            {"n", "cfdg", "CFDG", ""},
67            {"n", "chaiscript", "ChaiScript", ""},
68            {"n", "clojure", "Clojure", ""},
69            {"n", "klonec", "Clone C", ""},
70            {"n", "klonecpp", "Clone C++", ""},
71            {"n", "cmake", "CMake", "cmake"},
72            {"n", "cobol", "COBOL", ""},
73            {"n", "coffeescript", "CoffeeScript", ""},
74            {"n", "cfm", "ColdFusion", ""},
75            {"n", "css", "CSS", "css"},
76            {"n", "cuesheet", "Cuesheet", ""},
77            {"n", "d", "D", ""},
78            {"n", "dcs", "DCS", ""},
79            {"n", "delphi", "Delphi", ""},
80            {"n", "oxygene", "Delphi Prism (Oxygene)", ""},
81            {"n", "diff", "Diff", "diff"},
82            {"n", "div", "DIV", ""},
83            {"n", "dos", "DOS", ""},
84            {"n", "dot", "DOT", ""},
85            {"n", "e", "E", ""},
86            {"n", "ecmascript", "ECMAScript", ""},
87            {"n", "eiffel", "Eiffel", ""},
88            {"n", "email", "Email", ""},
89            {"n", "epc", "EPC", ""},
90            {"n", "erlang", "Erlang", ""},
91            {"n", "fsharp", "F#", ""},
92            {"n", "falcon", "Falcon", ""},
93            {"n", "fo", "FO Language", ""},
94            {"n", "f1", "Formula One", ""},
95            {"n", "fortran", "Fortran", "fortran"},
96            {"n", "freebasic", "FreeBasic", ""},
97            {"n", "gambas", "GAMBAS", ""},
98            {"n", "gml", "Game Maker", ""},
99            {"n", "gdb", "GDB", ""},
100            {"n", "genero", "Genero", ""},
101            {"n", "genie", "Genie", ""},
102            {"n", "gettext", "GetText", "gettext-translation"},
103            {"n", "go", "Go", ""},
104            {"n", "groovy", "Groovy", ""},
105            {"n", "gwbasic", "GwBasic", ""},
106            {"n", "haskell", "Haskell", ""},
107            {"n", "hicest", "HicEst", ""},
108            {"n", "hq9plus", "HQ9 Plus", ""},
109            {"n", "html4strict", "HTML", "html"},
110            {"n", "html5", "HTML 5", ""},
111            {"n", "icon", "Icon", ""},
112            {"n", "idl", "IDL", ""},
113            {"n", "ini", "INI file", "ini"},
114            {"n", "inno", "Inno Script", ""},
115            {"n", "intercal", "INTERCAL", ""},
116            {"n", "io", "IO", ""},
117            {"n", "j", "J", ""},
118            {"n", "java", "Java", "java"},
119            {"n", "java5", "Java 5", ""},
120            {"n", "javascript", "JavaScript", "js"},
121            {"n", "jquery", "jQuery", ""},
122            {"n", "kixtart", "KiXtart", ""},
123            {"n", "latex", "Latex", "latex"},
124            {"n", "lb", "Liberty BASIC", ""},
125            {"n", "lsl2", "Linden Scripting", ""},
126            {"n", "lisp", "Lisp", ""},
127            {"n", "llvm", "LLVM", ""},
128            {"n", "locobasic", "Loco Basic", ""},
129            {"n", "logtalk", "Logtalk", ""},
130            {"n", "lolcode", "LOL Code", ""},
131            {"n", "lotusformulas", "Lotus Formulas", ""},
132            {"n", "lotusscript", "Lotus Script", ""},
133            {"n", "lscript", "LScript", ""},
134            {"n", "lua", "Lua", "lua"},
135            {"n", "m68k", "M68000 Assembler", ""},
136            {"n", "magiksf", "MagikSF", ""},
137            {"n", "make", "Make", "makefile"},
138            {"n", "mapbasic", "MapBasic", ""},
139            {"n", "matlab", "MatLab", ""},
140            {"n", "mirc", "mIRC", ""},
141            {"n", "mmix", "MIX Assembler", ""},
142            {"n", "modula2", "Modula 2", ""},
143            {"n", "modula3", "Modula 3", ""},
144            {"n", "68000devpac", "Motorola 68000 HiSoft Dev", ""},
145            {"n", "mpasm", "MPASM", ""},
146            {"n", "mxml", "MXML", ""},
147            {"n", "mysql", "MySQL", ""},
148            {"n", "newlisp", "newLISP", ""},
149            {"n", "nsis", "NullSoft Installer", ""},
150            {"n", "oberon2", "Oberon 2", ""},
151            {"n", "objeck", "Objeck Programming Langua", ""},
152            {"n", "objc", "Objective C", "objc"},
153            {"n", "ocaml-brief", "OCalm Brief", ""},
154            {"n", "ocaml", "OCaml", ""},
155            {"n", "pf", "OpenBSD PACKET FILTER", ""},
156            {"n", "glsl", "OpenGL Shading", ""},
157            {"n", "oobas", "Openoffice BASIC", ""},
158            {"n", "oracle11", "Oracle 11", ""},
159            {"n", "oracle8", "Oracle 8", ""},
160            {"n", "oz", "Oz", ""},
161            {"n", "pascal", "Pascal", "pascal"},
162            {"n", "pawn", "PAWN", ""},
163            {"n", "pcre", "PCRE", ""},
164            {"n", "per", "Per", ""},
165            {"n", "perl", "Perl", "perl"},
166            {"n", "perl6", "Perl 6", ""},
167            {"n", "php", "PHP", "php"},
168            {"n", "php-brief", "PHP Brief", ""},
169            {"n", "pic16", "Pic 16", ""},
170            {"n", "pike", "Pike", ""},
171            {"n", "pixelbender", "Pixel Bender", ""},
172            {"n", "plsql", "PL/SQL", ""},
173            {"n", "postgresql", "PostgreSQL", ""},
174            {"n", "povray", "POV-Ray", ""},
175            {"n", "powershell", "Power Shell", ""},
176            {"n", "powerbuilder", "PowerBuilder", ""},
177            {"n", "proftpd", "ProFTPd", ""},
178            {"n", "progress", "Progress", ""},
179            {"n", "prolog", "Prolog", ""},
180            {"n", "properties", "Properties", ""},
181            {"n", "providex", "ProvideX", ""},
182            {"n", "purebasic", "PureBasic", ""},
183            {"n", "pycon", "PyCon", ""},
184            {"n", "python", "Python", "python"},
185            {"n", "q", "q/kdb+", ""},
186            {"n", "qbasic", "QBasic", ""},
187            {"n", "rsplus", "R", ""},
188            {"n", "rails", "Rails", ""},
189            {"n", "rebol", "REBOL", ""},
190            {"n", "reg", "REG", ""},
191            {"n", "robots", "Robots", ""},
192            {"n", "rpmspec", "RPM Spec", ""},
193            {"n", "ruby", "Ruby", "ruby"},
194            {"n", "gnuplot", "Ruby Gnuplot", ""},
195            {"n", "sas", "SAS", ""},
196            {"n", "scala", "Scala", ""},
197            {"n", "scheme", "Scheme", ""},
198            {"n", "scilab", "Scilab", ""},
199            {"n", "sdlbasic", "SdlBasic", ""},
200            {"n", "smalltalk", "Smalltalk", ""},
201            {"n", "smarty", "Smarty", ""},
202            {"n", "sql", "SQL", ""},
203            {"n", "systemverilog", "SystemVerilog", ""},
204            {"n", "tsql", "T-SQL", ""},
205            {"n", "tcl", "TCL", ""},
206            {"n", "teraterm", "Tera Term", ""},
207            {"n", "thinbasic", "thinBasic", ""},
208            {"n", "typoscript", "TypoScript", ""},
209            {"n", "unicon", "Unicon", ""},
210            {"n", "uscript", "UnrealScript", ""},
211            {"n", "vala", "Vala", "vala"},
212            {"n", "vbnet", "VB.NET", ""},
213            {"n", "verilog", "VeriLog", ""},
214            {"n", "vhdl", "VHDL", ""},
215            {"n", "vim", "VIM", ""},
216            {"n", "visualprolog", "Visual Pro Log", ""},
217            {"n", "vb", "VisualBasic", ""},
218            {"n", "visualfoxpro", "VisualFoxPro", ""},
219            {"n", "whitespace", "WhiteSpace", ""},
220            {"n", "whois", "WHOIS", ""},
221            {"n", "winbatch", "Winbatch", ""},
222            {"n", "xbasic", "XBasic", ""},
223            {"n", "xml", "XML", "xml"},
224            {"n", "xorg_conf", "Xorg Config", ""},
225            {"n", "xpp", "XPP", ""},
226            {"n", "yaml", "YAML", ""},
227            {"n", "z80", "Z80 Assembler", ""},
228            {"n", "zxbasic", "ZXBasic", ""}
229        };
230
231        public Scratch.Services.Document doc { get; construct; }
232
233        private Gtk.Button close_button;
234        private Gtk.Button upload_button;
235        private Gtk.Entry name_entry;
236        private Gtk.ComboBoxText expiry_combo;
237        private Gtk.CheckButton private_check;
238        private Gtk.ComboBoxText format_combo;
239        private Granite.Dialog format_dialog;
240        private Gtk.Stack stack;
241        private Gtk.ListBox languages_listbox;
242
243        public PasteBinDialog (Gtk.Window? parent, Scratch.Services.Document doc) {
244            Object (
245                resizable: false,
246                doc: doc,
247                transient_for: parent,
248                title: _("Upload to Pastebin")
249            );
250        }
251
252        construct {
253            name_entry = new Gtk.Entry () {
254                hexpand = true
255            };
256
257            var name_entry_l = new Gtk.Label (_("Name:")) {
258                halign = Gtk.Align.END
259            };
260
261            var format_label = new Gtk.Label (_("Format:")) {
262                halign = Gtk.Align.END
263            };
264
265            format_combo = new Gtk.ComboBoxText ();
266
267            var format_button = new Gtk.Button.from_icon_name ("view-more-horizontal-symbolic") {
268                tooltip_text = _("Choose different format")
269            };
270
271            //populate combo box
272            var sel_lang = doc.get_language_id ();
273            for (var i = 0; i < languages.length[0]; i++) {
274                //insert all languages that are in the Code combo, and also those that are marked with "y"
275                if ((languages[i, 3] != "") || (languages[i, 0] == "y")) {
276                    format_combo.append (languages[i, 1], languages[i, 2]);
277                }
278
279                //if the inserted language is selected in Code combo, select it as default
280                if (languages[i, 3] == sel_lang ) {
281                    format_combo.set_active_id (languages[i, 1]);
282                }
283            }
284
285            //if no language is selected, select text as default
286            if (format_combo.get_active_id () == null) {
287                format_combo.set_active_id ("text");
288            }
289
290            var expiry_combo_l = new Gtk.Label (_("Expiration:")) {
291                halign = Gtk.Align.END
292            };
293
294            expiry_combo = new Gtk.ComboBoxText ();
295            populate_expiry_combo ();
296
297            private_check = new Gtk.CheckButton.with_label (_("Keep this paste private"));
298
299            var grid = new Gtk.Grid () {
300                column_spacing = 6,
301                row_spacing = 12
302            };
303            grid.attach (name_entry_l, 0, 0, 1, 1);
304            grid.attach (name_entry, 1, 0, 1, 1);
305            grid.attach (format_label, 0, 1, 1, 1);
306            grid.attach (format_combo, 1, 1, 1, 1);
307            grid.attach (format_button, 2, 1, 1, 1);
308            grid.attach (expiry_combo_l, 0, 2, 1, 1);
309            grid.attach (expiry_combo, 1, 2, 1, 1);
310            grid.attach (private_check, 1, 3, 1, 1);
311
312            var spinner = new Gtk.Spinner () {
313                active = true,
314                height_request = 32,
315                valign = Gtk.Align.CENTER
316            };
317
318            stack = new Gtk.Stack () {
319                margin = 12,
320                margin_top = 0
321            };
322            stack.add (grid);
323            stack.add (spinner);
324
325            get_content_area ().add (stack);
326
327            close_button = (Gtk.Button)add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
328            upload_button = (Gtk.Button)add_button (_("Upload to Pastebin"), Gtk.ResponseType.OK);
329            upload_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
330
331            read_settings ();
332
333            show_all ();
334
335            format_button.clicked.connect (format_button_clicked);
336
337            upload_button.clicked.connect (() => {
338                stack.visible_child = spinner;
339                upload_button_clicked ();
340            });
341
342            close_button.clicked.connect (() => {
343                destroy ();
344            });
345
346            this.destroy.connect (() => {
347                write_settings ();
348            });
349        }
350
351        private void format_button_clicked () {
352            format_dialog = new Granite.Dialog () {
353                resizable = false,
354                title = _("Available Formats")
355            };
356            format_dialog.set_default_size (220, 300);
357
358            languages_listbox = new Gtk.ListBox () {
359                selection_mode = Gtk.SelectionMode.SINGLE
360            };
361
362            for (var i=0; i < languages.length[0]; i++) {
363                var label = new Gtk.Label (languages[i, 2]) {
364                    halign = Gtk.Align.START,
365                    margin = 6
366                };
367
368                languages_listbox.add (label);
369            }
370
371            var languages_scrolled = new Gtk.ScrolledWindow (null, null) {
372                hscrollbar_policy = Gtk.PolicyType.NEVER,
373                height_request = 250,
374                expand = true
375            };
376            languages_scrolled.add (languages_listbox);
377
378            var cancel_button = (Gtk.Button)format_dialog.add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
379
380            var select_button = (Gtk.Button)format_dialog.add_button (_("Select Format"), Gtk.ResponseType.OK);
381            select_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
382            select_button.clicked.connect (select_button_clicked);
383
384            var frame = new Gtk.Frame (null) {
385                margin = 12,
386                margin_top = 0
387            };
388            frame.add (languages_scrolled);
389
390            format_dialog.get_content_area ().add (frame);
391            format_dialog.show_all ();
392
393            cancel_button.clicked.connect (() => {
394                format_dialog.destroy ();
395            });
396        }
397
398        private void select_button_clicked () {
399            var selection = languages_listbox.get_selected_row ();
400            if (selection != null) {
401                var label = (Gtk.Label)selection.get_child ();
402                var lang_name = label.label;
403                var lang_code = "";
404
405                for (var i=0; i < languages.length[0]; i++) {
406                    if (languages[i, 2] == lang_name) {
407                        lang_code = languages[i, 1];
408                        format_combo.append (lang_code, lang_name);
409                        format_combo.set_active_id (lang_code);
410                        break;
411                    }
412                }
413            }
414
415            format_dialog.destroy ();
416        }
417
418        private void read_settings () {
419            string paste_name = this.doc.get_basename ();
420            name_entry.text = paste_name;
421
422            expiry_combo.set_active_id (Scratch.service_settings.get_string ("expiry-time"));
423            private_check.set_active (Scratch.service_settings.get_boolean ("set-private"));
424        }
425
426        private void write_settings () {
427            Scratch.service_settings.set_string ("paste-format-code", format_combo.active_id);
428            Scratch.service_settings.set_string ("expiry-time", expiry_combo.active_id);
429            Scratch.service_settings.set_boolean ("set-private", private_check.active);
430        }
431
432        private void upload_button_clicked () {
433            upload_button.sensitive = false;
434            close_button.label = _("Close");
435
436            string link;
437            var submit_result = submit_paste (out link);
438
439            var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10);
440            stack.add (box);
441
442            if (submit_result) {
443                //paste successfully
444                var link_button = new Gtk.LinkButton (link);
445                box.pack_start (link_button, false, true, 25);
446            } else {
447                var err_label = new Gtk.Label (link);
448                box.pack_start (err_label, false, true, 0);
449            }
450
451            box.show_all ();
452            stack.visible_child = box;
453        }
454
455        private bool submit_paste (out string link) {
456            // Get the values
457            string paste_code = this.doc.get_text ();
458            string paste_name = name_entry.text;
459            string paste_format = format_combo.get_active_id ();
460            string paste_private = private_check.get_active () == true ? PasteBin.PRIVATE : PasteBin.PUBLIC;
461            string paste_expire_date = expiry_combo.get_active_id ();
462
463            return PasteBin.submit (out link, paste_code, paste_name, paste_private, paste_expire_date, paste_format);
464        }
465
466        private void populate_expiry_combo () {
467            expiry_combo.append (PasteBin.NEVER, _("Never"));
468            expiry_combo.append (PasteBin.TEN_MINUTES, _("Ten minutes"));
469            expiry_combo.append (PasteBin.HOUR, _("One hour"));
470            expiry_combo.append (PasteBin.DAY, _("One day"));
471            expiry_combo.append (PasteBin.MONTH, _("One month"));
472        }
473     }
474}
475