1/* 2 * Copyright 2011 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 2 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, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 * MA 02110-1301, USA. 18*/ 19 20/* 21 TODO packagekit handler (GUI and stuff) ? 22 TODO Use wnck for managing launching applications ? 23*/ 24using Posix; 25 26namespace Lxsession 27{ 28 29public class AppObject: GLib.Object 30{ 31 32 /* Core App Object, all other App objects should inherent from it 33 You should not do an instance of it, use SimpleAppObject if you want 34 a usefull Object 35 */ 36 37 public Pid pid; 38 39 public string name { get; set;} 40 public string[] command { get; set;} 41 public bool guard { get; set; default = false;} 42 public string application_type { get; set;} 43 public int crash_count { get; set; default = 0;} 44 45 /* Number of time the application have to crash before stoping to reload */ 46 public int stop_reload { get; set; default = 5;} 47 48 public AppObject() 49 { 50 init(); 51 } 52 53 public void launch () 54 { 55 generic_launch (null); 56 } 57 58 public void generic_launch (string? arg1) 59 { 60 if (this.name != null) 61 { 62 if (this.name != "") 63 { 64 try 65 { 66 string[] spawn_env = Environ.get (); 67 Process.spawn_async ( 68 arg1, 69 this.command, 70 spawn_env, 71 SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, 72 null, 73 out this.pid); 74 ChildWatch.add(this.pid, callback_pid); 75 76 message ("Launching %s ", this.name); 77 78 for (int a = 0 ; a <= this.command.length ; a++) 79 { 80 GLib.stdout.printf("%s ",this.command[a]); 81 } 82 GLib.stdout.printf("\n"); 83 } 84 catch (SpawnError err) 85 { 86 warning (err.message); 87 warning ("Error when launching %s", this.name); 88 } 89 } 90 } 91 } 92 93 public virtual void read_config_settings() 94 { 95 /* Each object need to implement this, so settings will be read when process is reloaded */ 96 } 97 98 public virtual void read_settings() 99 { 100 /* Each object need to implement this, so settings will be read when process is reloaded */ 101 } 102 103 public void stop() 104 { 105 if ((int) this.pid != 0) 106 { 107 message("Stopping process with pid %d", (int) this.pid); 108 Posix.kill ((int) this.pid, 15); 109 } 110 } 111 112 public void reload() 113 { 114 message("Reloading process"); 115 this.stop(); 116 this.launch(); 117 } 118 119 public void init() 120 { 121 read_config_settings(); 122 read_settings(); 123 } 124 125 private void callback_pid(Pid pid, int status) 126 { 127 /* Help : http://en.wikipedia.org/wiki/Signal_(computing) 128 http://valadoc.org/glib-2.0/GLib.ProcessSignal.html 129 */ 130 message("%s exit with this type of exit: %i", this.name, status); 131 132 Process.close_pid (pid); 133 134 if (this.guard == true) 135 { 136 switch (status) 137 { 138 case 0: 139 message("Exit normal, don't reload"); 140 break; 141 case 15: 142 message("Exit by the user, don't reload"); 143 break; 144 case 256: 145 message("Exit normal, don't reload"); 146 break; 147 default: 148 message("Exit not normal, try to reload"); 149 this.crash_count = this.crash_count + 1; 150 if (this.crash_count <= this.stop_reload) 151 { 152 this.launch(); 153 } 154 else 155 { 156 message("Application crashed too much, stop reloading"); 157 } 158 break; 159 } 160 } 161 } 162} 163 164 165public class SimpleAppObject: AppObject 166{ 167 168 public SimpleAppObject() 169 { 170 this.name = ""; 171 this.command = {""}; 172 this.guard = false; 173 this.application_type = ""; 174 } 175} 176 177public class GenericAppObject: AppObject 178{ 179 180 public GenericAppObject(AppType app_type) 181 { 182 this.name = app_type.name; 183 this.command = app_type.command; 184 this.guard = app_type.guard; 185 this.application_type = app_type.application_type; 186 } 187} 188 189public class GenericSimpleApp: SimpleAppObject 190{ 191 public string settings_command { get; set; default = "";} 192 193 public GenericSimpleApp (string argument) 194 { 195 settings_command = argument; 196 init(); 197 } 198 199 public override void read_settings() 200 { 201 string[] create_command = settings_command.split_set(" ",0); 202 this.name = create_command[0]; 203 this.command = create_command; 204 } 205} 206 207public class WindowsManagerApp: SimpleAppObject 208{ 209 string wm_command; 210 string mode; 211 string session; 212 string extras; 213 214 public WindowsManagerApp () 215 { 216 init(); 217 } 218 219 public override void read_settings() 220 { 221 if (global_settings.get_item_string("Session", "window_manager", null) != null) 222 { 223 mode = "simple"; 224 wm_command = global_settings.get_item_string("Session", "window_manager", null); 225 session = ""; 226 extras = ""; 227 } 228 else 229 { 230 mode = "advanced"; 231 wm_command = global_settings.get_item_string("Session", "windows_manager", "command"); 232 session = global_settings.get_item_string("Session", "windows_manager", "session"); 233 extras = global_settings.get_item_string("Session", "windows_manager", "extras"); 234 } 235 236 string session_command; 237 238 if (wm_command == "wm_safe") 239 { 240 this.name = "wm_safe"; 241 this.command = {find_window_manager()}; 242 } 243 else 244 { 245 if (mode == "simple") 246 { 247 this.name = wm_command; 248 this.command = {wm_command}; 249 } 250 else 251 { 252 this.name = wm_command; 253 string create_command; 254 string xdg_config_env = Environment.get_variable("XDG_CONFIG_HOME"); 255 switch (wm_command) 256 { 257 case "openbox": 258 switch (session) 259 { 260 case "LXDE": 261 session_command = " --config-file " + xdg_config_env + "/openbox/lxde-rc.xml"; 262 break; 263 case "Lubuntu": 264 session_command = " --config-file " + xdg_config_env + "/openbox/lubuntu-rc.xml"; 265 break; 266 default: 267 session_command = " "; 268 break; 269 } 270 break; 271 272 case "openbox-custom": 273 switch (session) 274 { 275 default: 276 session_command = " --config-file " + session; 277 break; 278 } 279 break; 280 281 default: 282 session_command = null; 283 break; 284 } 285 286 switch (extras) 287 { 288 case null: 289 create_command = wm_command + session_command; 290 break; 291 case "": 292 create_command = wm_command + session_command; 293 break; 294 case " ": 295 create_command = wm_command + session_command; 296 break; 297 default: 298 create_command = wm_command + session_command + " " + extras; 299 break; 300 } 301 302 this.command = create_command.split_set(" ",0); 303 } 304 } 305 this.guard = true; 306 } 307 308 private string find_window_manager() 309 { 310 311 var wm_list = new Array<string> (); 312 313 wm_list.append_val("openbox-lxde"); 314 wm_list.append_val("openbox-lubuntu"); 315 wm_list.append_val("openbox"); 316 wm_list.append_val("compiz"); 317 wm_list.append_val("kwin"); 318 wm_list.append_val("mutter"); 319 wm_list.append_val("fluxbox"); 320 wm_list.append_val("metacity"); 321 wm_list.append_val("xfwin"); 322 wm_list.append_val("matchbox"); 323 324 string return_value = ""; 325 326 for(int i = 0; i < wm_list.length; ++i) 327 { 328 unowned string wm = wm_list.index(i); 329 string test_wm = Environment.find_program_in_path(wm); 330 if ( test_wm != null) 331 { 332 message ("Finding %s",wm); 333 return_value = wm; 334 break; 335 } 336 } 337 338 return return_value; 339 340 } 341 342 private void callback_pid(Pid pid, int status) 343 { 344 /* Help : http://en.wikipedia.org/wiki/Signal_(computing) 345 http://valadoc.org/glib-2.0/GLib.ProcessSignal.html 346 */ 347 message("%s exit with this type of exit: %i\n", this.name, status); 348 349 if (status == -1) 350 { 351 this.name = "wm_safe"; 352 this.command = {find_window_manager()}; 353 global_settings.set_generic_default("Session", "windows_manager", "command", "string", "wm_safe"); 354 } 355 356 Process.close_pid (pid); 357 358 if (this.guard == true) 359 { 360 switch (status) 361 { 362 case 0: 363 message("Exit normal, don't reload"); 364 break; 365 case 15: 366 message("Exit by the user, don't reload"); 367 break; 368 case 256: 369 message("Exit normal, don't reload"); 370 break; 371 default: 372 message("Exit not normal, try to reload"); 373 this.crash_count = this.crash_count + 1; 374 if (this.crash_count <= this.stop_reload) 375 { 376 this.launch(); 377 } 378 else 379 { 380 message("Application crashed too much, stop reloading"); 381 } 382 break; 383 } 384 } 385 } 386 387 public new void launch () 388 { 389 this.read_config_settings(); 390 this.read_settings(); 391 392 if (this.name != null) 393 { 394 try 395 { 396 string[] spawn_env = Environ.get (); 397 Process.spawn_async ( 398 null, 399 this.command, 400 spawn_env, 401 SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, 402 null, 403 out pid); 404 ChildWatch.add(pid, this.callback_pid); 405 406 for (int a = 0 ; a <= this.command.length ; a++) 407 { 408 GLib.stdout.printf("%s ",this.command[a]); 409 } 410 GLib.stdout.printf("\n"); 411 412 } 413 catch (SpawnError err) 414 { 415 warning (err.message); 416 } 417 } 418 419 } 420} 421 422public class PanelApp: SimpleAppObject 423{ 424 public string panel_command; 425 public string panel_session; 426 427 public PanelApp () 428 { 429 init(); 430 } 431 432 public override void read_config_settings() 433 { 434 panel_command = global_settings.get_item_string("Session", "panel", "command"); 435 // message("DEBUG6 : %s", global_settings.get_item_string("Session", "panel", "command")); 436 panel_session = global_settings.get_item_string("Session", "panel", "session"); 437 // message("DEBUG6 : %s", global_settings.get_item_string("Session", "panel", "session")); 438 } 439 440 public override void read_settings() 441 { 442 switch (panel_command) 443 { 444 case "lxpanel": 445 this.name = panel_command; 446 if (panel_session != null) 447 { 448 string create_command = "lxpanel --profile " + panel_session; 449 this.command = create_command.split_set(" ",0); 450 } 451 else 452 { 453 this.command = {panel_command}; 454 } 455 break; 456 case "awn": 457 this.name = panel_command; 458 string create_command = "avant-window-navigator"; 459 this.command = create_command.split_set(" ",0); 460 break; 461 default: 462 string[] create_command = panel_command.split_set(" ",0); 463 this.name = create_command[0]; 464 this.command = create_command; 465 break; 466 } 467 this.guard = true; 468 } 469} 470 471public class DockApp: PanelApp 472{ 473 public DockApp () 474 { 475 init(); 476 } 477 478 public override void read_config_settings() 479 { 480 panel_command = global_settings.get_item_string("Session", "dock", "command"); 481 panel_session = global_settings.get_item_string("Session", "dock", "session"); 482 } 483} 484 485public class ScreensaverApp: SimpleAppObject 486{ 487 string screensaver_command; 488 489 public ScreensaverApp () 490 { 491 init(); 492 } 493 494 public override void read_settings() 495 { 496 screensaver_command = global_settings.get_item_string("Session", "screensaver", "command"); 497 498 switch (screensaver_command) 499 { 500 case "xscreensaver": 501 this.name = screensaver_command; 502 string create_command = "xscreensaver -no-splash"; 503 this.command = create_command.split_set(" ",0); 504 break; 505 default: 506 string[] create_command = screensaver_command.split_set(" ",0); 507 this.name = create_command[0]; 508 this.command = create_command; 509 break; 510 } 511 this.guard = true; 512 } 513} 514 515public class PowerManagerApp: SimpleAppObject 516{ 517 string powermanager_command; 518 string laptop_mode; 519 520 public PowerManagerApp () 521 { 522 init(); 523 } 524 525 public override void read_settings() 526 { 527 powermanager_command = global_settings.get_item_string("Session", "power_manager", "command"); 528 laptop_mode = global_settings.get_item_string("State", "laptop_mode", null); 529 530 switch (powermanager_command) 531 { 532 case "auto": 533 /* If we are on a laptop, we need a power manager, try to start xfce one */ 534 /* If we are not on a laptop, assume we don't need power management */ 535 if (laptop_mode == "yes") 536 { 537 string create_command = "xfce4-power-manager"; 538 this.name = "xfce4-power-manager"; 539 this.command = create_command.split_set(" ",0); 540 } 541 542 break; 543 case "no": 544 this.name = "power_manager_off"; 545 break; 546 default: 547 string[] create_command = powermanager_command.split_set(" ",0); 548 this.name = create_command[0]; 549 this.command = create_command; 550 break; 551 } 552 this.guard = true; 553 } 554} 555 556public class FileManagerApp: SimpleAppObject 557{ 558 string filemanager_command; 559 string filemanager_session; 560 string filemanager_extras; 561 562 public FileManagerApp () 563 { 564 init(); 565 } 566 567 public override void read_settings() 568 { 569 filemanager_command = global_settings.get_item_string("Session", "file_manager", "command"); 570 filemanager_session = global_settings.get_item_string("Session", "file_manager", "session"); 571 filemanager_extras = global_settings.get_item_string("Session", "file_manager", "extras"); 572 573 switch (filemanager_command) 574 { 575 case "pcmanfm": 576 this.name = filemanager_command; 577 if (filemanager_session != null) 578 { 579 string create_command = "pcmanfm --profile " + filemanager_session + filemanager_extras; 580 this.command = create_command.split_set(" ",0); 581 } 582 else 583 { 584 this.command = {filemanager_command}; 585 } 586 break; 587 case "pcmanfm-qt": 588 this.name = filemanager_command; 589 if (filemanager_session != null) 590 { 591 string create_command = "pcmanfm-qt --profile " + filemanager_session + filemanager_extras; 592 this.command = create_command.split_set(" ",0); 593 } 594 else 595 { 596 this.command = {filemanager_command}; 597 } 598 break; 599 case "nautilus": 600 this.name = filemanager_command; 601 string create_command = "nautilus" + " -n " + filemanager_extras; 602 this.command = create_command.split_set(" ",0); 603 break; 604 default: 605 string[] create_command = filemanager_command.split_set(" ",0); 606 this.name = create_command[0]; 607 this.command = create_command; 608 break; 609 } 610 } 611} 612 613public class DesktopApp: SimpleAppObject 614{ 615 string desktop_command; 616 string desktop_wallpaper; 617 618 public DesktopApp () 619 { 620 init(); 621 } 622 623 public override void read_settings() 624 { 625 626 desktop_command = global_settings.get_item_string("Session", "desktop_manager", "command"); 627 desktop_wallpaper = global_settings.get_item_string("Session", "desktop_manager", "wallpaper"); 628 629 switch (desktop_command) 630 { 631 case "filemanager": 632 string filemanager_session = global_settings.get_item_string("Session", "file_manager", "session"); 633 string filemanager_extras = global_settings.get_item_string("Session", "file_manager", "extras"); 634 635 if (global_file_manager != null) 636 { 637 message("File manager needed for desktop manager but doesn't exist, creating it"); 638 var filemanager = new FileManagerApp(); 639 global_file_manager = filemanager; 640 } 641 642 switch (global_settings.get_item_string("Session", "file_manager", "command")) 643 { 644 case "pcmanfm": 645 this.name = global_settings.get_item_string("Session", "file_manager", "command"); 646 string create_command = "pcmanfm --desktop --profile " + filemanager_session + filemanager_extras; 647 this.command = create_command.split_set(" ",0); 648 break; 649 case "pcmanfm-qt": 650 this.name = global_settings.get_item_string("Session", "file_manager", "command"); 651 string create_command = "pcmanfm-qt --desktop --profile " + filemanager_session + filemanager_extras; 652 this.command = create_command.split_set(" ",0); 653 break; 654 case "nautilus": 655 this.name = global_settings.get_item_string("Session", "file_manager", "command"); 656 string create_command = "nautilus" + " -n " + filemanager_extras; 657 this.command = create_command.split_set(" ",0); 658 break; 659 } 660 break; 661 case "feh": 662 this.name = desktop_command; 663 string create_command = "feh" + " --bg-scale " + desktop_wallpaper; 664 this.command = create_command.split_set(" ",0); 665 break; 666 default: 667 string[] create_command = desktop_command.split_set(" ",0); 668 this.name = create_command[0]; 669 this.command = create_command; 670 break; 671 } 672 this.guard = true; 673 } 674 675 public void launch_settings() 676 { 677 string[] backup_command = this.command; 678 679 switch (this.name) 680 { 681 case "pcmanfm": 682 string create_settings_command = "pcmanfm --desktop-pref"; 683 this.command = create_settings_command.split_set(" ",0); 684 break; 685 686 default: 687 break; 688 } 689 this.launch(); 690 this.command = backup_command; 691 } 692 693} 694 695public class PolkitApp: SimpleAppObject 696{ 697 string polkit_command; 698 699 public PolkitApp () 700 { 701 init(); 702 } 703 704 public override void read_settings() 705 { 706 polkit_command = global_settings.get_item_string("Session", "polkit", "command"); 707 708 switch (polkit_command) 709 { 710 case "gnome": 711 this.name = "polkit-gnome-authentication-agent-1"; 712 string create_command = "/usr/local/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1"; 713 this.command = create_command.split_set(" ",0); 714 break; 715 case "razorqt": 716 this.name = "razor-policykit-agent"; 717 string create_command = "/usr/bin/razor-policykit-agent"; 718 this.command = create_command.split_set(" ",0); 719 break; 720 case "lxpolkit": 721 message("polkit separate"); 722 this.name = "lxpolkit"; 723 string create_command = "lxpolkit"; 724 this.command = create_command.split_set(" ",0); 725 break; 726 } 727 this.guard = true; 728 729 } 730 731#if BUILDIN_POLKIT 732 public new void launch () 733 { 734 policykit_agent_init(); 735 } 736#endif 737 738 public void deactivate () 739 { 740#if BUILDIN_POLKIT 741 policykit_agent_finalize(); 742#endif 743 } 744} 745 746public class NetworkGuiApp: SimpleAppObject 747{ 748 string network_command; 749 string laptop_mode; 750 751 public NetworkGuiApp () 752 { 753 init(); 754 } 755 756 public override void read_settings() 757 { 758 network_command = global_settings.get_item_string("Session", "network_gui", "command"); 759 laptop_mode = global_settings.get_item_string("State", "laptop_mode", null); 760 761 switch (network_command) 762 { 763 case "no": 764 /* Don't start anything */ 765 break; 766 case "auto": 767 /* If we are on a laptop, assume we need a GUI, and try to find one, starting with nm-applet */ 768 /* If you are not on a laptop, assume we don't need any GUI */ 769 if (laptop_mode == "yes") 770 { 771 string test_nm_applet = Environment.find_program_in_path("nm-applet"); 772 if (test_nm_applet != null) 773 { 774 this.name = "nm-applet"; 775 string create_command = "nm-applet"; 776 this.command = create_command.split_set(" ",0); 777 break; 778 } 779 else 780 { 781 string test_wicd = Environment.find_program_in_path("wicd"); 782 if (test_wicd != null) 783 { 784 this.name = "wicd"; 785 string create_command = "wicd"; 786 this.command = create_command.split_set(" ",0); 787 break; 788 } 789 } 790 } 791 break; 792 default: 793 string[] create_command = network_command.split_set(" ",0); 794 this.name = create_command[0]; 795 this.command = create_command; 796 break; 797 } 798 this.guard = true; 799 } 800} 801 802public class AudioManagerApp: SimpleAppObject 803{ 804 string audiomanager_command; 805 806 public AudioManagerApp () 807 { 808 init(); 809 } 810 811 public override void read_settings() 812 { 813 audiomanager_command = global_settings.get_item_string("Session", "audio_manager", "command"); 814 815 switch (audiomanager_command) 816 { 817 case "alsamixer": 818 this.name = "alsamixer"; 819 string create_command = "xterm -e alsamixer"; 820 this.command = create_command.split_set(" ",0); 821 break; 822 default: 823 string[] create_command = audiomanager_command.split_set(" ",0); 824 this.name = create_command[0]; 825 this.command = create_command; 826 break; 827 } 828 } 829} 830 831public class QuitManagerApp: SimpleAppObject 832{ 833 string quitmanager_command; 834 string quitmanager_image; 835 string quitmanager_layout; 836 837 838 public QuitManagerApp () 839 { 840 init(); 841 } 842 843 public override void read_settings() 844 { 845 quitmanager_command = global_settings.get_item_string("Session", "quit_manager", "command"); 846 quitmanager_image = global_settings.get_item_string("Session", "quit_manager", "image"); 847 quitmanager_layout = global_settings.get_item_string("Session", "quit_manager", "layout"); 848 849 switch (quitmanager_command) 850 { 851 case "lxsession-logout": 852 this.name = "lxsession-logout"; 853 string create_command = "lxsession-logout --banner " + quitmanager_image + " --side=" + quitmanager_layout; 854 this.command = create_command.split_set(" ",0); 855 break; 856 default: 857 string[] create_command = quitmanager_command.split_set(" ",0); 858 this.name = create_command[0]; 859 this.command = create_command; 860 break; 861 } 862 } 863} 864 865public class WorkspaceManagerApp: SimpleAppObject 866{ 867 string workspacemanager_command; 868 869 public WorkspaceManagerApp () 870 { 871 init(); 872 } 873 874 public override void read_settings() 875 { 876 workspacemanager_command = global_settings.get_item_string("Session", "workspace_manager", "command"); 877 878 switch (workspacemanager_command) 879 { 880 case "obconf": 881 this.name = "obconf"; 882 string create_command = "obconf --tab 6"; 883 this.command = create_command.split_set(" ",0); 884 break; 885 default: 886 string[] create_command = workspacemanager_command.split_set(" ",0); 887 this.name = create_command[0]; 888 this.command = create_command; 889 break; 890 } 891 } 892} 893 894public class LauncherManagerApp: SimpleAppObject 895{ 896 string launchermanager_command; 897 898 public LauncherManagerApp () 899 { 900 init(); 901 } 902 903 public override void read_settings() 904 { 905 launchermanager_command = global_settings.get_item_string("Session", "launcher_manager", "command"); 906 907 switch (launchermanager_command) 908 { 909 case "lxpanelctl": 910 this.name = "lxpanelctl"; 911 string create_command = "lxpanelctl run"; 912 this.command = create_command.split_set(" ",0); 913 break; 914 default: 915 string[] create_command = launchermanager_command.split_set(" ",0); 916 this.name = create_command[0]; 917 this.command = create_command; 918 break; 919 } 920 } 921 922 public void autostart_launch() 923 { 924 switch (launchermanager_command) 925 { 926 case "synapse": 927 string create_autostart_command = "synapse --startup"; 928 lxsession_spawn_command_line_async(create_autostart_command); 929 break; 930 default: 931 this.launch(); 932 break; 933 } 934 } 935} 936 937public class TerminalManagerApp: SimpleAppObject 938{ 939 string terminalmanager_command; 940 941 public TerminalManagerApp () 942 { 943 init(); 944 } 945 946 public override void read_config_settings() 947 { 948 terminalmanager_command = global_settings.get_item_string("Session", "terminal_manager", "command"); 949 } 950 951 public override void read_settings() 952 { 953 switch (terminalmanager_command) 954 { 955 case "lxterminal": 956 this.name = "lxterminal"; 957 string create_command = "lxterminal -e"; 958 this.command = create_command.split_set(" ",0); 959 break; 960 default: 961 string[] create_command = terminalmanager_command.split_set(" ",0); 962 this.name = create_command[0]; 963 this.command = create_command; 964 break; 965 } 966 } 967 968 public new void launch (string argument) 969 { 970 if (argument == "") 971 { 972 argument = null; 973 } 974 975 generic_launch (argument); 976 } 977} 978 979public class ProxyManagerApp: SimpleAppObject 980{ 981 string proxymanager_command; 982 string proxymanager_http; 983 984 public ProxyManagerApp () 985 { 986 init(); 987 } 988 989 public override void read_settings() 990 { 991 proxymanager_command = global_settings.get_item_string("Session", "proxy_manager", "command"); 992 proxymanager_http = global_settings.get_item_string("Session", "proxy_manager", "http"); 993 994 switch (proxymanager_command) 995 { 996 case "build-in": 997 switch (proxymanager_http) 998 { 999 case null: 1000 break; 1001 case "": 1002 break; 1003 case " ": 1004 break; 1005 default: 1006 Environment.set_variable("HTTP_PROXY", proxymanager_http, true); 1007 break; 1008 } 1009 break; 1010 } 1011 } 1012} 1013 1014public class A11yApp: SimpleAppObject 1015{ 1016 string a11y_command; 1017 1018 public A11yApp () 1019 { 1020 init(); 1021 } 1022 1023 public override void read_settings() 1024 { 1025 a11y_command = global_settings.get_item_string("Session", "a11y", "command"); 1026 1027 switch (a11y_command) 1028 { 1029 case null: 1030 break; 1031 case "": 1032 break; 1033 case " ": 1034 break; 1035 case "gnome": 1036 string tmp_command = "/usr/local/lib/at-spi2-core/at-spi-bus-launcher --launch-immediately"; 1037 string[] create_command = tmp_command.split_set(" ",0); 1038 this.name = create_command[0]; 1039 this.command = create_command; 1040 break; 1041 default: 1042 string[] create_command = a11y_command.split_set(" ",0); 1043 this.name = create_command[0]; 1044 this.command = create_command; 1045 break; 1046 } 1047 } 1048} 1049 1050public class XrandrApp: SimpleAppObject 1051{ 1052 /* Don't use GenericApp, we may want to implement other option than 1053 reading a xrandr command directly 1054 */ 1055 string xrandr_command; 1056 1057 public XrandrApp () 1058 { 1059 init(); 1060 } 1061 1062 public override void read_settings() 1063 { 1064 xrandr_command = global_settings.get_item_string("Session", "xrandr", "command"); 1065 1066 switch (xrandr_command) 1067 { 1068 case null: 1069 break; 1070 case "": 1071 break; 1072 case " ": 1073 break; 1074 default: 1075 string[] create_command = xrandr_command.split_set(" ",0); 1076 this.name = create_command[0]; 1077 this.command = create_command; 1078 break; 1079 } 1080 } 1081} 1082 1083public class KeyringApp: SimpleAppObject 1084{ 1085 string keyring_command; 1086 string keyring_type; 1087 1088 public KeyringApp () 1089 { 1090 init(); 1091 } 1092 1093 public override void read_settings() 1094 { 1095 keyring_command = global_settings.get_item_string("Session", "keyring", "command"); 1096 keyring_type = global_settings.get_item_string("Session", "keyring", "type"); 1097 1098 switch (keyring_command) 1099 { 1100 case "gnome-all": 1101 string tmp_command = "gnome-keyring-daemon --start --components=pkcs11,secrets,ssh,gpg"; 1102 string[] create_command = tmp_command.split_set(" ",0); 1103 this.name = create_command[0]; 1104 this.command = create_command; 1105 break; 1106 case "ssh-agent": 1107 string tmp_command = "/usr/bin/ssh-agent -s"; 1108 string[] create_command = tmp_command.split_set(" ",0); 1109 this.name = create_command[0]; 1110 this.command = create_command; 1111 break; 1112 default: 1113 string[] create_command = keyring_command.split_set(" ",0); 1114 this.name = create_command[0]; 1115 this.command = create_command; 1116 break; 1117 } 1118 } 1119} 1120 1121public class ScreenshotManagerApp: SimpleAppObject 1122{ 1123 string screenshotmanager_command; 1124 1125 public ScreenshotManagerApp () 1126 { 1127 init(); 1128 } 1129 1130 public override void read_settings() 1131 { 1132 screenshotmanager_command = global_settings.get_item_string("Session", "screenshot_manager", "command"); 1133 1134 switch (screenshotmanager_command) 1135 { 1136 default: 1137 string[] create_command = screenshotmanager_command.split_set(" ",0); 1138 this.name = create_command[0]; 1139 this.command = create_command; 1140 break; 1141 } 1142 } 1143 1144 public void window_launch() 1145 { 1146 read_settings(); 1147 1148 string[] backup_command = this.command; 1149 1150 switch (screenshotmanager_command) 1151 { 1152 case "scrot": 1153 string create_window_command = "scrot -u -b"; 1154 this.command = create_window_command.split_set(" ",0); 1155 break; 1156 1157 default: 1158 break; 1159 } 1160 1161 this.launch(); 1162 this.command = backup_command; 1163 } 1164} 1165 1166public class UpdatesManagerApp: SimpleAppObject 1167{ 1168 string updatesmanager_command; 1169 1170 IconObject updates_icon; 1171 MenuObject icon_menu; 1172 1173 IconObject language_icon; 1174 1175 IconObject reboot_icon; 1176 1177 string apt_update_path = "/var/lib/apt/periodic/update-success-stamp"; 1178 GLib.File apt_update_file ; 1179 GLib.FileMonitor apt_update_monitor ; 1180 1181 string dpkg_update_path = "/var/lib/dpkg/status"; 1182 GLib.File dpkg_update_file ; 1183 GLib.FileMonitor dpkg_update_monitor ; 1184 1185 string dpkg_run_path = "/var/lib/update-notifier/dpkg-run-stamp"; 1186 GLib.File dpkg_run_file ; 1187 GLib.FileMonitor dpkg_run_monitor ; 1188 1189 string apt_lists_update_path = "/var/lib/apt/lists"; 1190 GLib.File apt_lists_update_file ; 1191 GLib.FileMonitor apt_lists_update_monitor ; 1192 1193 string reboot_path = "/var/run/reboot-required"; 1194 GLib.File reboot_file ; 1195 GLib.FileMonitor reboot_monitor ; 1196 1197 string dpkg_lock_file = "/var/lib/dpkg/lock"; 1198 1199 int lock_check = 0; 1200 1201 public UpdatesManagerApp () 1202 { 1203 init(); 1204 } 1205 1206 public override void read_settings() 1207 { 1208 updatesmanager_command = global_settings.get_item_string("Session", "updates_manager", "command"); 1209 1210 switch (updatesmanager_command) 1211 { 1212 case null: 1213 break; 1214 case "": 1215 break; 1216 case " ": 1217 break; 1218 case "update-notifier-clone": 1219 setup_apt_config(); 1220 setup_reboot_config(); 1221 run_check(); 1222 break; 1223 default: 1224 string[] create_command = updatesmanager_command.split_set(" ",0); 1225 this.name = create_command[0]; 1226 this.command = create_command; 1227 break; 1228 } 1229 } 1230 1231 public void test_inactivate() 1232 { 1233 updates_icon.inactivate(); 1234 } 1235 1236 public void test_activate() 1237 { 1238 updates_icon.activate(); 1239 } 1240 1241 public void run_check() 1242 { 1243 if (this.lock_check == 0) 1244 { 1245 if (check_lock_file(dpkg_lock_file) == true) 1246 { 1247 this.lock_check = 1; 1248 int timeout = 60; 1249 if (global_settings.get_item_string("Session", "updates_manager", "timeout") != null) 1250 { 1251 timeout = int.parse(global_settings.get_item_string("Session", "updates_manager", "timeout")); 1252 } 1253 GLib.Timeout.add_seconds(timeout, on_apt_update_file_change); 1254 } 1255 } 1256 } 1257 1258 public void reboot_launch() 1259 { 1260 var session = new SessionObject(); 1261 session.lxsession_restart(); 1262 } 1263 1264 public void run_check_reboot() 1265 { 1266 string notification_text =""; 1267 1268 if (this.reboot_file.query_exists ()) 1269 { 1270 if (this.reboot_icon == null) 1271 { 1272 var reboot_icon_menu = new MenuObject() ; 1273 string line = _("Reboot required"); 1274 1275 try 1276 { 1277 var dis = new DataInputStream (this.reboot_file.read ()); 1278 line = dis.read_line (); 1279 } 1280 catch (GLib.Error e) 1281 { 1282 message ("Error: %s\n", e.message); 1283 } 1284 1285 if (line != null) 1286 { 1287 notification_text = line; 1288 } 1289 1290 var menu_item = new MenuItemObject(); 1291 menu_item.set_label(notification_text); 1292 menu_item.activate.connect(() => { 1293 reboot_launch(); 1294 }); 1295 menu_item.show(); 1296 reboot_icon_menu.add(menu_item); 1297 1298 this.reboot_icon = new IconObject("RebootIcon", "system-reboot", notification_text, reboot_icon_menu); 1299 this.reboot_icon.init(); 1300 this.reboot_icon.clear_actions (); 1301 this.reboot_icon.add_action ("launch_reboot", _("Reboot"), () => 1302 { 1303 reboot_launch(); 1304 }); 1305 this.reboot_icon.activate(); 1306 } 1307 } 1308 else 1309 { 1310 if (this.reboot_icon != null) 1311 { 1312 this.reboot_icon.inactivate(); 1313 } 1314 } 1315 } 1316 1317 public void language_launch() 1318 { 1319 if (this.language_icon != null) 1320 { 1321 try 1322 { 1323 Process.spawn_command_line_async("gnome-language-selector"); 1324 this.language_icon.inactivate(); 1325 } 1326 catch (SpawnError err) 1327 { 1328 warning (err.message); 1329 } 1330 } 1331 } 1332 1333 public void check_language_support() 1334 { 1335 string command = "check-language-support"; 1336 1337 string standard_output; 1338 string standard_error; 1339 int exit_status; 1340 1341 string launch_string = _("Launch language support"); 1342 1343 try 1344 { 1345 Process.spawn_command_line_sync (command, out standard_output, out standard_error, out exit_status); 1346 1347 message ("Launching %s", command); 1348 message ("Language state: %s", standard_error); 1349 message ("Language exit status: %i", exit_status); 1350 message ("Language output: %s", standard_output); 1351 1352 } 1353 catch (SpawnError err) 1354 { 1355 warning (err.message); 1356 } 1357 1358 if (standard_output != null) 1359 { 1360 if (standard_output.length >= 3) 1361 { 1362 if (this.language_icon == null) 1363 { 1364 var language_icon_menu = new MenuObject() ; 1365 1366 var menu_item = new MenuItemObject(); 1367 menu_item.set_label(launch_string); 1368 menu_item.activate.connect(() => { 1369 language_launch(); 1370 }); 1371 menu_item.show(); 1372 language_icon_menu.add(menu_item); 1373 1374 this.language_icon = new IconObject("LanguageIcon", "preferences-desktop-locale", _("Language support missing"), language_icon_menu); 1375 this.language_icon.init(); 1376 this.language_icon.clear_actions (); 1377 this.language_icon.add_action ("launch_language_support", launch_string, () => 1378 { 1379 language_launch(); 1380 }); 1381 this.language_icon.activate(); 1382 } 1383 } 1384 else if (this.language_icon != null) 1385 { 1386 this.language_icon.inactivate(); 1387 } 1388 } 1389 else if (this.language_icon != null) 1390 { 1391 this.language_icon.inactivate(); 1392 } 1393 } 1394 1395 public void upgrade_launch (string upgrade_manager_command) 1396 { 1397 try 1398 { 1399 Process.spawn_command_line_async(upgrade_manager_command); 1400 } 1401 catch (SpawnError err) 1402 { 1403 warning (err.message); 1404 } 1405 } 1406 1407 public bool on_apt_update_file_change() 1408 { 1409 /* Launch something that check if updates are available */ 1410 /* For now, use lxsession-apt-check, which is apt-check from update-notifier */ 1411 1412 string standard_output; 1413 string standard_error; 1414 int exit_status; 1415 1416 string notification_text = _("Updates available"); 1417 1418 string launch_string = _("Launch Update Manager"); 1419 string upgrade_manager_command = ""; 1420 1421 string[] updates_num; 1422 int updates_urgent = 0; 1423 int updates_normal = 0; 1424 int updates_state = 0; 1425 int number_updates = 0; 1426 1427 /* Lock the check process, to avoid launching the check many times when one is already running */ 1428 this.lock_check = 1; 1429 1430 if (this.icon_menu == null) 1431 { 1432 this.icon_menu = new MenuObject(); 1433 1434 if (global_settings.get_item_string("Session", "upgrade_manager", "command") != null) 1435 { 1436 upgrade_manager_command = global_settings.get_item_string("Session", "upgrade_manager", "command"); 1437 1438 var menu_item = new MenuItemObject(); 1439 menu_item.set_label(launch_string); 1440 menu_item.activate.connect(() => { 1441 upgrade_launch (upgrade_manager_command); 1442 }); 1443 menu_item.show(); 1444 icon_menu.add(menu_item); 1445 } 1446 } 1447 1448 string command = "/usr/bin/nice" + " " + "/usr/bin/ionice" + " " + "-c3" + " " + "/usr/local/lib/update-notifier/apt-check"; 1449 1450 string error_string = ""; 1451 1452 try 1453 { 1454 Process.spawn_command_line_sync (command, out standard_output, out standard_error, out exit_status); 1455 1456 message ("Launching %s", command); 1457 message ("Update state: %s", standard_error); 1458 message ("Update exit status: %i", exit_status); 1459 1460 } 1461 catch (SpawnError err) 1462 { 1463 warning (err.message); 1464 } 1465 1466 if (this.updates_icon == null) 1467 { 1468 this.updates_icon = new IconObject("UpdatesIcon", "software-update-available", notification_text, this.icon_menu); 1469 this.updates_icon.init(); 1470 if (global_settings.get_item_string("Session", "upgrade_manager", "command") != null) 1471 { 1472 upgrade_manager_command = global_settings.get_item_string("Session", "upgrade_manager", "command"); 1473 this.updates_icon.clear_actions (); 1474 this.updates_icon.add_action ("launch_upgrade_manager", launch_string, () => 1475 { 1476 upgrade_launch (upgrade_manager_command); 1477 }); 1478 } 1479 this.updates_icon.inactivate(); 1480 } 1481 else 1482 { 1483 this.updates_icon.inactivate(); 1484 } 1485 1486 if (standard_error != "") 1487 { 1488 if (standard_error[0:1] == "E") 1489 { 1490 updates_urgent = 0; 1491 updates_normal = 0; 1492 updates_state = 1; 1493 error_string = _("An error occurred, please run Package Manager from the left-click menu or apt-get in a terminal to see what is wrong."); 1494 if (standard_error.length > 3) 1495 { 1496 notification_text = error_string + "\n" + _("The error message was: ") + standard_error; 1497 } 1498 else 1499 { 1500 notification_text = error_string; 1501 } 1502 } 1503 else 1504 { 1505 updates_num = standard_error.split_set(";",2); 1506 message ("Number of upgrades: %s", updates_num[0]); 1507 message ("Number of security upgrades: %s", updates_num[1]); 1508 updates_num[2] = "0"; 1509 1510 updates_urgent = int.parse(updates_num[1]); 1511 updates_normal = int.parse(updates_num[0]); 1512 number_updates = updates_normal + updates_urgent; 1513 1514 if (number_updates == 1) 1515 { 1516 notification_text = number_updates.to_string() + _(" Update available"); 1517 } 1518 else if (number_updates > 1) 1519 { 1520 notification_text = number_updates.to_string() + (" ") + _("Updates available"); 1521 } 1522 } 1523 1524 } 1525 else 1526 { 1527 updates_state = 1; 1528 } 1529 1530 1531 if (number_updates > 0) 1532 { 1533 message("Activate icon because of updates available"); 1534 this.updates_icon.set_notification_body(notification_text); 1535 this.updates_icon.activate(); 1536 } 1537 1538 if (updates_urgent > 0) 1539 { 1540 message("Set urgent icon"); 1541 this.updates_icon.set_icon("software-update-urgent"); 1542 this.updates_icon.set_notification_body(notification_text); 1543 } 1544 1545 1546 if (updates_state > 0) 1547 { 1548 message("Problem in package state"); 1549 this.updates_icon.set_icon("software-update-urgent"); 1550 this.updates_icon.set_notification_body(notification_text); 1551 this.updates_icon.clear_actions (); 1552 this.updates_icon.add_action ("launch_upgrade_manager", launch_string, () => 1553 { 1554 upgrade_launch ("synaptic-pkexec"); 1555 }); 1556 var new_menu = new MenuObject(); 1557 var new_menu_item = new MenuItemObject(); 1558 new_menu_item.set_label(launch_string); 1559 new_menu_item.activate.connect(() => { 1560 upgrade_launch ("synaptic-pkexec"); 1561 }); 1562 new_menu_item.show(); 1563 new_menu.add(new_menu_item); 1564 this.updates_icon.set_menu(new_menu); 1565 this.updates_icon.activate(); 1566 } 1567 1568 /* Check if language support is complete */ 1569 check_language_support(); 1570 1571 /* Check if a reboot is requiered */ 1572 run_check_reboot(); 1573 1574 /* Unlock the check */ 1575 this.lock_check = 0; 1576 1577 return false; 1578 } 1579 1580 public void setup_apt_config () 1581 { 1582 /* Note directories monitored by update-notifier : 1583 "/var/lib/apt/lists/" ==> files of meta data of the repositories 1584 "/var/lib/apt/lists/partial/" 1585 "/var/cache/apt/archives/" ==> .deb in cache 1586 "/var/cache/apt/archives/partial/" 1587 1588 Files monitored by update-notifier : 1589 "/var/lib/dpkg/status" => big file of dpkg status 1590 "/var/lib/update-notifier/dpkg-run-stamp" update-notifier stamp for dpkg ? 1591 "/var/lib/apt/periodic/update-success-stamp" 1592 */ 1593 1594 try 1595 { 1596 this.apt_update_file = File.new_for_path(this.apt_update_path); 1597 this.apt_update_monitor = apt_update_file.monitor_file(GLib.FileMonitorFlags.NONE); 1598 this.apt_update_monitor.changed.connect(run_check); 1599 message ("Monitoring apt changes"); 1600 } 1601 catch (GLib.Error err) 1602 { 1603 message (err.message); 1604 } 1605 1606 try 1607 { 1608 this.dpkg_update_file = File.new_for_path(this.dpkg_update_path); 1609 this.dpkg_update_monitor = dpkg_update_file.monitor_file(GLib.FileMonitorFlags.NONE); 1610 this.dpkg_update_monitor.changed.connect(run_check); 1611 message ("Monitoring dpkg changes"); 1612 } 1613 catch (GLib.Error err) 1614 { 1615 message (err.message); 1616 } 1617 1618 try 1619 { 1620 this.dpkg_run_file = File.new_for_path(this.dpkg_run_path); 1621 this.dpkg_run_monitor = dpkg_run_file.monitor_file(GLib.FileMonitorFlags.NONE); 1622 this.dpkg_run_monitor.changed.connect(run_check); 1623 message ("Monitoring dpkg run changes"); 1624 } 1625 catch (GLib.Error err) 1626 { 1627 message (err.message); 1628 } 1629 1630 try 1631 { 1632 this.apt_lists_update_file = File.new_for_path(this.apt_lists_update_path); 1633 this.apt_lists_update_monitor = apt_lists_update_file.monitor_directory(GLib.FileMonitorFlags.NONE); 1634 this.apt_lists_update_monitor.changed.connect(run_check); 1635 message ("Monitoring apt_lists changes"); 1636 } 1637 catch (GLib.Error err) 1638 { 1639 message (err.message); 1640 } 1641 } 1642 1643 public void setup_reboot_config () 1644 { 1645 try 1646 { 1647 this.reboot_file = File.new_for_path(this.reboot_path); 1648 this.reboot_monitor = reboot_file.monitor_file(GLib.FileMonitorFlags.NONE); 1649 this.reboot_monitor.changed.connect(run_check_reboot); 1650 message ("Monitoring reboot changes"); 1651 } 1652 catch (GLib.Error err) 1653 { 1654 message (err.message); 1655 } 1656 } 1657 1658 /* From https://mail.gnome.org/archives/vala-list/2010-October/msg00036.html */ 1659 public bool check_lock_file(string check_file) 1660 { 1661 1662 string lock_file_name = check_file; 1663 int fd = Posix.open (lock_file_name, Posix.O_RDWR); 1664 if (fd == -1) 1665 { 1666 print ("There was an error opening the file '" 1667 + lock_file_name + " (Error number " 1668 + Posix.errno.to_string() + ")\n"); 1669 return true; 1670 } 1671 1672 // Try to get a lock 1673 Posix.Flock fl = Posix.Flock(); 1674 fl.l_type = Posix.F_WRLCK; 1675 fl.l_whence = Posix.SEEK_SET; 1676 fl.l_start = 100; 1677 fl.l_len = 0; 1678 1679 int fcntl_return = Posix.fcntl (fd, Posix.F_SETLK, fl); 1680 if (fcntl_return == -1) 1681 return true; 1682 1683 // Release the lock again 1684 fl.l_type = Posix.F_UNLCK; 1685 fl.l_whence = Posix.SEEK_SET; 1686 fl.l_start = 100; 1687 fl.l_len = 0; 1688 fcntl_return = Posix.fcntl (fd, Posix.F_SETLK, fl); 1689 1690 return false; 1691 } 1692 1693} 1694public class CrashManagerApp: SimpleAppObject 1695{ 1696 string crash_manager_command; 1697 IconObject crash_icon; 1698 1699 string crash_dir_path = "/var/crash/"; 1700 GLib.File crash_dir_file ; 1701 GLib.FileMonitor crash_dir_monitor ; 1702 1703 int lock_crash_check = 0; 1704 1705 public CrashManagerApp () 1706 { 1707 init(); 1708 } 1709 1710 public override void read_settings() 1711 { 1712 crash_manager_command = global_settings.get_item_string("Session", "crash_manager", "command"); 1713 1714 switch (crash_manager_command) 1715 { 1716 case null: 1717 break; 1718 case "": 1719 break; 1720 case " ": 1721 break; 1722 case "apport-gtk": 1723 setup_crash_log_config (); 1724 run_crash_check(); 1725 break; 1726 default: 1727 string[] create_command = crash_manager_command.split_set(" ",0); 1728 this.name = create_command[0]; 1729 this.command = create_command; 1730 break; 1731 } 1732 } 1733 1734 public void test_activate () 1735 { 1736 if (this.crash_icon != null) 1737 { 1738 this.crash_icon.activate(); 1739 } 1740 } 1741 1742 public void test_inactivate () 1743 { 1744 if (this.crash_icon != null) 1745 { 1746 this.crash_icon.inactivate(); 1747 } 1748 } 1749 1750 public void setup_crash_log_config () 1751 { 1752 try 1753 { 1754 this.crash_dir_file = File.new_for_path(this.crash_dir_path); 1755 this.crash_dir_monitor = crash_dir_file.monitor_directory(GLib.FileMonitorFlags.NONE); 1756 this.crash_dir_monitor.changed.connect(run_crash_check); 1757 message ("Monitoring crash dir changes"); 1758 } 1759 catch (GLib.Error err) 1760 { 1761 message (err.message); 1762 } 1763 } 1764 1765 public void run_crash_check() 1766 { 1767 if (this.lock_crash_check == 0) 1768 { 1769 this.lock_crash_check = 1; 1770 int timeout = 60; 1771 if (global_settings.get_item_string("Session", "crash_manager", "timeout") != null) 1772 { 1773 timeout = int.parse(global_settings.get_item_string("Session", "crash_manager", "timeout")); 1774 } 1775 GLib.Timeout.add_seconds(timeout, on_crash_file_change); 1776 } 1777 } 1778 1779 public List<string> check_crash_file() 1780 { 1781 List<string> crash_list = new List<string> (); 1782 List<string> final_crash_list = new List<string> (); 1783 string[] uploaded_list = {}; 1784 string file_name; 1785 1786 if (this.crash_dir_file != null) 1787 { 1788 try 1789 { 1790 var directory = File.new_for_path (crash_dir_path); 1791 var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME, 0); 1792 1793 FileInfo file_info; 1794 while ((file_info = enumerator.next_file ()) != null) 1795 { 1796 file_name = file_info.get_name(); 1797 if (file_name != ".lock") 1798 { 1799 if (file_name.has_suffix(".crash")) 1800 { 1801 message("Add to crash_list: %s", file_name); 1802 crash_list.append(file_name); 1803 } 1804 else if (file_name.has_suffix(".uploaded")) 1805 { 1806 uploaded_list += file_name.replace(".uploaded", ".crash"); 1807 message("Added to upload_list: %s", file_name.replace(".uploaded", ".crash")); 1808 } 1809 } 1810 } 1811 } 1812 catch (Error e) 1813 { 1814 message ("Error: %s\n", e.message); 1815 } 1816 } 1817 1818 foreach (string element in crash_list) 1819 { 1820 message("Check element in crash_list: %s", element); 1821 if (uploaded_list != null) 1822 { 1823 if (element in uploaded_list) 1824 { 1825 message("Remove element in crash_list: %s", element); 1826 } 1827 else 1828 { 1829 final_crash_list.append(element); 1830 } 1831 } 1832 else 1833 { 1834 final_crash_list.append(element); 1835 } 1836 } 1837 1838 return final_crash_list; 1839 } 1840 1841 public void crash_report_launch (string command) 1842 { 1843 try 1844 { 1845 Process.spawn_command_line_async(command); 1846 message ("Launching crash command : %s", command); 1847 } 1848 catch (SpawnError err) 1849 { 1850 warning (err.message); 1851 } 1852 } 1853 1854 public MenuObject build_menu(List<string> crash_list) 1855 { 1856 uint len = crash_list.length(); 1857 var menu = new MenuObject(); 1858 1859 if (len >= 1) 1860 { 1861 foreach (string element in crash_list) 1862 { 1863 string command = "/usr/local/bin/pkexec /usr/local/share/apport/apport-gtk" + " " + this.crash_dir_path + element; 1864 1865 var menu_item = new MenuItemObject(); 1866 menu_item.set_label(_("Report ") + element); 1867 menu_item.activate.connect(() => { 1868 crash_report_launch(command); 1869 }); 1870 menu_item.show(); 1871 menu.add(menu_item); 1872 } 1873 } 1874 1875 return menu; 1876 1877 } 1878 1879 public bool on_crash_file_change () 1880 { 1881 List<string> crash_list; 1882 uint len; 1883 MenuObject crash_menu; 1884 1885 /* Lock the check process, to avoid launching the check many times when one is already running */ 1886 this.lock_crash_check = 1; 1887 1888 crash_list = check_crash_file(); 1889 len = crash_list.length(); 1890 uint last_item = len - 1; 1891 1892 if (len >= 1) 1893 { 1894 crash_menu = build_menu(crash_list); 1895 string command = "/usr/local/bin/pkexec /usr/local/share/apport/apport-gtk" + " " + this.crash_dir_path + crash_list.nth_data(last_item) ; 1896 string remove_command = "/usr/local/bin/pkexec rm -f " + this.crash_dir_path + crash_list.nth_data(last_item); 1897 1898 string launch_string = "Report last crash"; 1899 string remove_string = "Remove last crash"; 1900 1901 if (this.crash_icon == null) 1902 { 1903 this.crash_icon = new IconObject("CrashIcon", "apport", _("Crash files available for report"), crash_menu); 1904 this.crash_icon.init(); 1905 } 1906 this.crash_icon.set_menu(crash_menu); 1907 /* TODO Make a window dialog to be able to really report bug on notification screen (and also add the remove mode) 1908 1909 this.crash_icon.clear_actions (); 1910 this.crash_icon.add_action ("launch_crash_report", launch_string, () => 1911 { 1912 crash_report_launch (command); 1913 }); 1914 */ 1915 if (global_settings.get_item_string("Session", "crash_manager", "dev_mode") == "yes") 1916 { 1917 this.crash_icon.add_action ("remove_crash_report", remove_string, () => 1918 { 1919 crash_report_launch (remove_command); 1920 }); 1921 } 1922 this.crash_icon.activate(); 1923 } 1924 /* Unlock the check */ 1925 this.lock_crash_check = 0; 1926 return false; 1927 } 1928} 1929} 1930