1/* 2 Copyright 2013 Julien Lavergne <gilir@ubuntu.com> 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public 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 Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17using Gtk; 18 19namespace LDefaultApps 20{ 21 void init_application( Builder builder, 22 KeyFile kf, 23 DbusBackend dbus_backend, 24 string key1, 25 string key2, 26 string message_help, 27 string[] more_list, 28 string more_help, 29 string? generic_item) 30 { 31 init_entry(builder, dbus_backend, key1); 32 init_reload_button(builder, dbus_backend, key1, key2); 33 init_help_message(builder, key1, message_help); 34 init_more_button(builder, dbus_backend, kf, key1, more_list, more_help, generic_item); 35 } 36 37 void init_application_combobox ( Gtk.Builder builder, 38 KeyFile kf, 39 DbusBackend dbus_backend, 40 string key1, 41 string key2, 42 string message_help, 43 string[] more_list, 44 string more_help, 45 string? generic_item) 46 { 47 init_combobox(builder, dbus_backend, kf, key1 + "_combobox", key1, dbus_backend.Get(key1, "command"), generic_item); 48 init_reload_button(builder, dbus_backend, key1, key2); 49 init_help_message(builder, key1, message_help); 50 init_more_button(builder, dbus_backend, kf, key1, more_list, more_help, generic_item); 51 } 52 53 void init_entry(Builder builder, DbusBackend dbus_backend, string key1) 54 { 55 string default_text = dbus_backend.Get(key1, "command"); 56 string entry_name = key1 + "_entry"; 57 var entry = builder.get_object (entry_name) as Entry; 58 entry.set_text(default_text); 59 entry.changed.connect(() => { 60 if (entry.get_text() != null) 61 { 62 dbus_backend.Set(key1, "command", entry.get_text()); 63 } 64 }); 65 entry.show_all(); 66 } 67 68 void init_reload_button(Builder builder, DbusBackend dbus_backend, string key1, string key2) 69 { 70 var button = builder.get_object(key1 + "_reload") as Gtk.Button; 71 button.clicked.connect (() => { 72 dbus_backend.Launch(key1, key2); 73 }); 74 } 75 76 void init_help_message(Builder builder, string item, string message_label) 77 { 78 var help_button = builder.get_object(item + "_help_button") as Gtk.Button; 79 help_button.clicked.connect (() => { 80 var help_window = new Window(); 81 help_window.window_position = Gtk.WindowPosition.CENTER; 82 help_window.set_default_size (350, 70); 83 help_window.set_skip_taskbar_hint(true); 84 try 85 { 86 help_window.icon = IconTheme.get_default ().load_icon ("preferences-desktop", 48, 0); 87 } 88 catch (Error e) 89 { 90 message ("Could not load application icon: %s\n", e.message); 91 } 92 93 var help_label = new Label(message_label); 94 help_window.add(help_label); 95 help_window.show_all(); 96 }); 97 } 98 99 void init_more_button(Builder builder, DbusBackend dbus_backend, KeyFile kf, string item, string[] more_list, string more_help, string generic_item) 100 { 101 /* Copy the array, it doesn't seem to like to be passed directly */ 102 string[] more_list_copy = more_list; 103 var button = builder.get_object(item + "_more") as Gtk.Button; 104 button.clicked.connect (() => { 105 init_windows_more(builder, dbus_backend, kf, item, more_list_copy, more_help, generic_item); 106 }); 107 } 108 109 void init_windows_more (Builder builder, DbusBackend dbus_backend, KeyFile kf, string item, string[] more_list, string message_help, string generic_item) 110 { 111 var window = new Gtk.Window(); 112 window.window_position = Gtk.WindowPosition.CENTER; 113 window.set_default_size (300, 500); 114 try 115 { 116 window.icon = IconTheme.get_default ().load_icon ("preferences-desktop", 48, 0); 117 } 118 catch (Error e) 119 { 120 message ("Could not load application icon: %s\n", e.message); 121 } 122 123 124 // The ScrolledWindow: 125 Gtk.ScrolledWindow more_scrolled = new Gtk.ScrolledWindow (null, null); 126 more_scrolled.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC); 127 window.add (more_scrolled); 128 129 var more_view_port = new Gtk.Viewport(null, null); 130 more_scrolled.add(more_view_port); 131 132 var master_vbox = new Gtk.VBox(false, 0); 133 more_view_port.add(master_vbox); 134 135 var help_message = new Label(message_help); 136 master_vbox.add(help_message); 137 for (int a = 0 ; a < more_list.length ; a++) 138 { 139 switch (more_list[a]) 140 { 141 case "combobox_manual": 142 var box = new Gtk.HBox(false, 0); 143 master_vbox.add(box); 144 145 var label = new Label(_("Manual setting")); 146 box.add(label); 147 148 string default_text = dbus_backend.Get(item, "command"); 149 var manual_entry = new Gtk.Entry(); 150 manual_entry.set_text(default_text); 151 manual_entry.changed.connect(() => { 152 if (manual_entry.get_text() != null) 153 { 154 dbus_backend.Set(item, "command", manual_entry.get_text()); 155 /* TODO update the main combobox */ 156 } 157 }); 158 box.add(manual_entry); 159 break; 160 161 case "mime_association": 162 var box = new Gtk.HBox(false, 0); 163 master_vbox.add(box); 164 165 var label = new Label(_("Mime Association")); 166 box.add(label); 167 168 var button = new Gtk.Button.with_label(_("Apply")); 169 170 button.clicked.connect(() => { 171 string[] combobox_list; 172 combobox_list = get_mime_list(kf, item, "installed"); 173 string default_path = ""; 174 string default_exec = ""; 175 176 for (int b = 0 ; b < combobox_list.length ; b++) 177 { 178 string item_list = combobox_list[b]; 179 ComboItemObject combo_item = new ComboItemObject (item_list); 180 if (item == combo_item.exec) 181 { 182 default_path = combo_item.desktop_path; 183 default_exec = combo_item.exec; 184 } 185 } 186 create_mime_associate_window(dbus_backend, kf, item, default_exec); 187 }); 188 box.add(button); 189 break; 190 case "mime_available": 191 var box = new Gtk.VBox(false, 0); 192 master_vbox.add(box); 193 194 var label = new Label(_("Available applications")); 195 box.add(label); 196 197 Gtk.ListStore list_store = new Gtk.ListStore (3, typeof(string), typeof(string), typeof(string)); 198 Gtk.TreeIter iter; 199 200 string[] list ; 201 if (generic_item != null) 202 { 203 list = get_mime_list(kf, generic_item, "available"); 204 } 205 else 206 { 207 list = get_mime_list(kf, item, "available"); 208 } 209 210 for (int c = 0 ; c < list.length ; c++) 211 { 212 string item_list = list[c]; 213 ComboItemObject combo_item = new ComboItemObject (item_list); 214 215 list_store.append (out iter); 216 list_store.set (iter, 0, combo_item.icon_name , 1, combo_item.name, 2, "gtk-apply"); 217 } 218 219 var return_treeview = new Gtk.TreeView.with_model(list_store); 220 221 Gtk.CellRendererPixbuf renderer_image = new Gtk.CellRendererPixbuf (); 222 return_treeview.insert_column_with_attributes (-1, "Icon", renderer_image, "icon-name", 0); 223 224 Gtk.CellRendererText renderer = new Gtk.CellRendererText (); 225 return_treeview.insert_column_with_attributes (-1, "Name", renderer, "text", 1); 226 227 Gtk.CellRendererPixbuf renderer_apply = new Gtk.CellRendererPixbuf (); 228 return_treeview.insert_column_with_attributes (-1, "", renderer_apply, "icon-name", 2); 229 230 /* TODO callback the install button */ 231 232 box.add(return_treeview); 233 234 break; 235 case "autostart": 236 var hbox = new Gtk.HBox(false, 0); 237 master_vbox.add(hbox); 238 239 var check_button = new Gtk.CheckButton(); 240 check_button.set_label(_("Autostart the application ?")); 241 string default_text = dbus_backend.Get(item, "autostart"); 242 if (default_text == "true") 243 { 244 check_button.set_active(true); 245 } 246 else 247 { 248 check_button.set_active(false); 249 } 250 check_button.clicked.connect(() => { 251 dbus_backend.Set(item, "autostart", "true"); 252 }); 253 hbox.add(check_button); 254 break; 255 256 case "handle_desktop": 257 var hbox = new Gtk.HBox(false, 0); 258 master_vbox.add(hbox); 259 260 var check_button = new Gtk.CheckButton(); 261 check_button.set_label(_("Handle the desktop with it ?")); 262 string default_text = dbus_backend.Get("desktop_manager", "command"); 263 if (default_text == "filemanager") 264 { 265 check_button.set_active(true); 266 } 267 else 268 { 269 check_button.set_active(false); 270 } 271 check_button.clicked.connect(() => { 272 dbus_backend.Set("desktop_manager", "command", "filemanager"); 273 }); 274 hbox.add(check_button); 275 break; 276 277 case "debian_default": 278 var box = new Gtk.HBox(false, 0); 279 master_vbox.add(box); 280 281 var label = new Label(_("Set debian default programs")); 282 box.add(label); 283 284 var button = new Gtk.Button.with_label(_("Apply")); 285 286 button.clicked.connect(() => { 287 288 string default_text = dbus_backend.Get(item, "command"); 289 290 string default_command; 291 292 if (default_text[0:1] == "/") 293 { 294 default_command = default_text; 295 } 296 else 297 { 298 default_command = "/usr/bin/" + default_text; 299 } 300 switch (item) 301 { 302 case "webbrowser": 303 try 304 { 305 Process.spawn_command_line_async( "gksu \"update-alternatives --set x-www-browser " 306 + default_command + "\""); 307 } 308 catch (GLib.SpawnError err) 309 { 310 warning (err.message); 311 } 312 break; 313 314 case "terminal_manager": 315 try 316 { 317 Process.spawn_command_line_async( "gksu \"update-alternatives --set x-terminal-emulator " 318 + default_command + "\""); 319 } 320 catch (GLib.SpawnError err) 321 { 322 warning (err.message); 323 } 324 break; 325 } 326 }); 327 box.add(button); 328 break; 329 default: 330 if (more_list[a] != null) 331 { 332 var hbox = new Gtk.HBox(false, 0); 333 master_vbox.add(hbox); 334 var label = new Label(more_list[a]); 335 hbox.add(label); 336 var entry = new Entry(); 337 string default_text = dbus_backend.Get(item, more_list[a]); 338 entry.set_text(default_text); 339 entry.changed.connect(() => { 340 if (entry.get_text() != null) 341 { 342 dbus_backend.Set(item, more_list[a], entry.get_text()); 343 } 344 }); 345 entry.show_all(); 346 hbox.add(entry); 347 } 348 break; 349 } 350 } 351 window.show_all(); 352 } 353 354 public class ComboItemObject: GLib.Object 355 { 356 public string name { get; set;} 357 public string exec { get; set;} 358 public Gtk.Image icon { get; set;} 359 public string icon_name { get; set;} 360 public string desktop_path { get; set;} 361 public string install_package { get; set;} 362 363 public string[] tmp_item_array; 364 365 public ComboItemObject(string item) 366 { 367 this.tmp_item_array = item.split_set(",",0); 368 this.name = tmp_item_array[0]; 369 this.exec = tmp_item_array[1]; 370 this.icon = create_image(tmp_item_array[2]); 371 this.icon_name = tmp_item_array[2]; 372 this.desktop_path = tmp_item_array[3]; 373 this.install_package = tmp_item_array[4]; 374 } 375 376 public Gtk.Image create_image (string item_image_string) 377 { 378 Gtk.Image image = new Gtk.Image (); 379 380 if (item_image_string[0:1] == "/") 381 { 382 /* Absolute path for the icon, load it directly */ 383 image.set_from_file(item_image_string); 384 } 385 else 386 { 387 /* Name icon, load it by the name */ 388 image.set_from_icon_name(item_image_string, Gtk.IconSize.MENU); 389 } 390 391 return image; 392 393 } 394 } 395 396 Gtk.ComboBox init_combobox ( Gtk.Builder builder, 397 DbusBackend dbus_backend, 398 KeyFile kf, 399 string combobox_name, 400 string combobox_list_name, 401 string by_default, 402 string? generic_item) 403 { 404 405 var return_combobox = builder.get_object (combobox_name) as Gtk.ComboBox; 406 407 Gtk.ListStore list_store = new Gtk.ListStore (4, typeof(string), typeof (string), typeof (int) , typeof(string)); 408 Gtk.TreeIter iter; 409 int default_index = -1; 410 bool default_set = false; 411 412 string[] combobox_list; 413 414 if (generic_item != null) 415 { 416 combobox_list = get_mime_list(kf, generic_item, "installed"); 417 } 418 else 419 { 420 combobox_list = get_mime_list(kf, combobox_list_name, "installed"); 421 } 422 423 /* First row, empty for not selected and for unselect */ 424 list_store.append (out iter); 425 list_store.set (iter, 0, "window-close" , 1, _("Disable"), 2, 0, 3,""); 426 427 for (int a = 0 ; a < combobox_list.length ; a++) 428 { 429 string item_list = combobox_list[a]; 430 ComboItemObject combo_item = new ComboItemObject (item_list); 431 432 list_store.append (out iter); 433 434 list_store.set (iter, 0, combo_item.icon_name , 1, combo_item.name, 2, a, 3, combo_item.exec ); 435 if (combo_item.exec == by_default) 436 { 437 /* move +1, because 1st row is Disable */ 438 default_index = a + 1; 439 default_set = true; 440 } 441 } 442 443 message ("Default = %s", by_default); 444 445 if (by_default == "" ) 446 { 447 default_index = 0; 448 default_set = true; 449 } 450 if (default_set == false) 451 { 452 Value val; 453 int last_position; 454 list_store.append (out iter); 455 list_store.get_value (iter, 2, out val); 456 last_position = val.get_int() + 1; 457 list_store.set (iter, 0, "" , 1, by_default, 2, last_position, 3,by_default); 458 } 459 460 return_combobox.set_model (list_store); 461 462 Gtk.CellRendererPixbuf renderer_image = new Gtk.CellRendererPixbuf (); 463 return_combobox.pack_start (renderer_image, false); 464 return_combobox.add_attribute (renderer_image, "icon-name", 0); 465 466 Gtk.CellRendererText renderer = new Gtk.CellRendererText (); 467 return_combobox.pack_start (renderer, false); 468 return_combobox.add_attribute (renderer, "text", 1); 469 470/* 471 Debug Exec name 472 473 Gtk.CellRendererText renderer_exec = new Gtk.CellRendererText (); 474 return_combobox.pack_start (renderer_exec, true); 475 return_combobox.add_attribute (renderer_exec, "text", 3); 476*/ 477 478 479 return_combobox.active = 0; 480 481 /* Set default */ 482 if (default_index == -1) 483 { 484 message ("Iter == -1"); 485 switch (by_default) 486 { 487 case (null): 488 return_combobox.set_active(0); 489 break; 490 case (""): 491 return_combobox.set_active(0); 492 break; 493 case (" "): 494 return_combobox.set_active(0); 495 break; 496 default: 497 return_combobox.set_active_iter(iter); 498 break; 499 } 500 } 501 else 502 { 503 message ("Iter == %d", default_index); 504 return_combobox.set_active(default_index); 505 } 506 507 return_combobox.changed.connect (() => { 508 Value val1; 509 Value val2; 510 511 return_combobox.get_active_iter (out iter); 512 list_store.get_value (iter, 2, out val1); 513 list_store.get_value (iter, 3, out val2); 514 515 message ("Selection: %d, %s\n", (int) val1, (string) val2); 516 517 if (val2.get_string() != null) 518 { 519 dbus_backend.Set(combobox_list_name, "command", val2.get_string()); 520 message ("Setting %s: %d, %s\n", combobox_list_name, (int) val1, (string) val2); 521 } 522 523 create_mime_associate_window(dbus_backend, kf, combobox_list_name, val2.get_string()); 524 525 }); 526 527 /* Disconnect scroll event, to avoid changing item when we are scrolling the windows */ 528 return_combobox.scroll_event.connect (() => { 529 530 return true; 531 532 }); 533 534 return return_combobox; 535 } 536 537 void create_mime_associate_window(DbusBackend dbus_backend, KeyFile kf, string combobox_list_name, string command) 538 { 539 var window_mime = new Window(); 540 window_mime.window_position = Gtk.WindowPosition.CENTER; 541 window_mime.set_default_size (400, 200); 542 window_mime.set_skip_taskbar_hint(true); 543 try 544 { 545 window_mime.icon = IconTheme.get_default ().load_icon ("preferences-desktop", 48, 0); 546 } 547 catch (Error e) 548 { 549 message ("Could not load application icon: %s\n", e.message); 550 } 551 552 // The ScrolledWindow: 553 Gtk.ScrolledWindow scrolled = new Gtk.ScrolledWindow (null, null); 554 scrolled.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC); 555 window_mime.add (scrolled); 556 557 var mime_view_port = new Gtk.Viewport(null, null); 558 mime_view_port.set_size_request (200, 200); 559 scrolled.add(mime_view_port); 560 561 var mime_vbox = new Gtk.VBox(false, 0); 562 mime_view_port.add(mime_vbox); 563 564 var info_label = new Label(_("Do you want to assiociate the following Mimetype ?\n")); 565 mime_vbox.add(info_label); 566 567 string[] mime_combobox_list; 568 mime_combobox_list = get_mime_list(kf, combobox_list_name, "installed"); 569 string default_path = ""; 570 571 for (int b = 0 ; b < mime_combobox_list.length ; b++) 572 { 573 string item_list = mime_combobox_list[b]; 574 ComboItemObject combo_item = new ComboItemObject (item_list); 575 message("combo_item.desktop_path: %s", combo_item.desktop_path); 576 message("combobox_list_name: %s", combobox_list_name); 577 message("combo_item.exec: %s", combo_item.exec); 578 579 if (command == combo_item.exec) 580 { 581 default_path = combo_item.desktop_path; 582 } 583 } 584 585 message("Look at default_path: %s", default_path); 586 587 if (default_path != "") 588 { 589 KeyFile kf_mime = new KeyFile(); 590 string[] mime_list; 591 try 592 { 593 kf_mime.load_from_file(default_path, KeyFileFlags.NONE); 594 } 595 catch (KeyFileError err) 596 { 597 warning (err.message); 598 } 599 catch (FileError err) 600 { 601 warning (err.message); 602 } 603 604 try 605 { 606 mime_list = kf_mime.get_string_list("Desktop Entry", "MimeType"); 607 if (mime_list.length >= 1) 608 { 609 string base_name = Path.get_basename(default_path); 610 var hbox_buttons = new Gtk.HBox(false, 0); 611 var ok_button = new Gtk.Button.with_label("OK"); 612 var cancel_button = new Gtk.Button.with_label(_("Cancel")); 613 mime_vbox.add(hbox_buttons); 614 hbox_buttons.add(ok_button); 615 hbox_buttons.add(cancel_button); 616 message("Enter mime try"); 617 for (int i = 0 ; i < mime_list.length ; i++) 618 { 619 string message_mime = mime_list[i] + "\n"; 620 message("Look at message_mime: %s", message_mime); 621 var label_mime = new Label(message_mime); 622 mime_vbox.add(label_mime); 623 } 624 625 ok_button.clicked.connect(() => { 626 save_mime_type(mime_list, base_name); 627 window_mime.destroy(); 628 }); 629 630 cancel_button.clicked.connect(() => { 631 window_mime.destroy(); 632 }); 633 634 window_mime.show_all(); 635 } 636 else 637 { 638 window_mime.destroy(); 639 } 640 } 641 catch (KeyFileError err) 642 { 643 warning (err.message); 644 } 645 } 646 } 647 648 void save_mime_type(string[] mime_list, string base_name) 649 { 650 string mimeapps_list_directory = Path.build_filename(Environment.get_home_dir (),".local", "share", "applications"); 651 KeyFile kf_mimeapps = load_key_conf(mimeapps_list_directory, "mimeapps.list"); 652 string mimeapps_list_path = Path.build_filename(mimeapps_list_directory, "mimeapps.list"); 653 654 if (mime_list != null) 655 { 656 for (int i = 0 ; i < mime_list.length ; i++) 657 { 658 kf_mimeapps.set_string("Added Associations", mime_list[i], base_name); 659 kf_mimeapps.set_string("Default Applications", mime_list[i], base_name); 660 } 661 } 662 663 var str = kf_mimeapps.to_data (null); 664 try 665 { 666 FileUtils.set_contents (mimeapps_list_path, str, str.length); 667 } 668 catch (FileError err) 669 { 670 warning (err.message); 671 } 672 } 673 674 string return_combobox_text(Gtk.ComboBox combo) 675 { 676 Gtk.TreeIter iter; 677 Gtk.ListStore model; 678 GLib.Value value1; 679 680 combo.get_active_iter (out iter); 681 model = (Gtk.ListStore) combo.get_model (); 682 model.get_value (iter, 0, out value1); 683 684 message (" Return value for %s", (string) value1); 685 686 return (string) value1; 687 } 688 689 690 string[] get_mime_list (KeyFile kf, string key1, string mode) 691 { 692 string keys = key1 + "/" + mode; 693 string[] return_value = {}; 694 try 695 { 696 return_value = kf.get_string_list("Mime", keys); 697 } 698 catch (GLib.KeyFileError err) 699 { 700 warning (err.message); 701 } 702 return return_value; 703 } 704 705 public Gtk.ComboBox ui_combobox_init ( Gtk.Builder builder, 706 string combobox_name, 707 string[] combobox_list, 708 string? entry_name, 709 string by_default) 710 { 711 Gtk.ListStore list_store = new Gtk.ListStore (2, typeof (string), typeof (int)); 712 Gtk.TreeIter iter; 713 int default_index = -1; 714 715 for (int a = 0 ; a < combobox_list.length ; a++) 716 { 717 list_store.append (out iter); 718 list_store.set (iter, 0, combobox_list[a], 1, a); 719 if (combobox_list[a] == by_default) 720 { 721 default_index = a; 722 } 723 } 724 725 list_store.append (out iter); 726 list_store.set (iter, 0, "Other", 1, 99); 727 728 message ("Default = %s", by_default); 729 730 var return_combobox = builder.get_object (combobox_name) as Gtk.ComboBox; 731 return_combobox.set_model (list_store); 732 733 Gtk.CellRendererText renderer = new Gtk.CellRendererText (); 734 return_combobox.pack_start (renderer, true); 735 return_combobox.add_attribute (renderer, "text", 0); 736 return_combobox.active = 0; 737 738 /* Set default */ 739 if (default_index == -1) 740 { 741 switch (by_default) 742 { 743 case (null): 744 return_combobox.set_active(0); 745 break; 746 case (""): 747 return_combobox.set_active(0); 748 break; 749 case (" "): 750 return_combobox.set_active(0); 751 break; 752 default: 753 return_combobox.set_active_iter(iter); 754 if (entry_name != null) 755 { 756 var entry_default = builder.get_object (entry_name) as Entry; 757 entry_default.set_text(by_default); 758 entry_default.show_all(); 759 } 760 break; 761 } 762 } 763 else 764 { 765 message ("Iter == %d", default_index); 766 return_combobox.set_active(default_index); 767 if (entry_name != null) 768 { 769 var entry_default = builder.get_object (entry_name) as Entry; 770#if USE_GTK2 771 entry_default.hide_all(); 772#endif 773#if USE_GTK3 774 entry_default.hide(); 775#endif 776 777 } 778 } 779 780 return_combobox.changed.connect (() => { 781 Value val1; 782 Value val2; 783 784 return_combobox.get_active_iter (out iter); 785 list_store.get_value (iter, 0, out val1); 786 list_store.get_value (iter, 1, out val2); 787 788 message ("Selection: %s, %d\n", (string) val1, (int) val2); 789 790 if (entry_name != null) 791 { 792 var entry = builder.get_object (entry_name) as Entry; 793 794 if (val2 == 99) 795 { 796 entry.show_all(); 797 } 798 else 799 { 800#if USE_GTK2 801 entry.hide_all(); 802#endif 803#if USE_GTK3 804 entry.hide(); 805#endif 806 } 807 } 808 }); 809 810 return return_combobox; 811 } 812} 813