Advertisement
lpugoy

Insync GNOME Shell applet

Feb 19th, 2013
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Insync Gnome3 and Cinnamon Desktop Applet
  3. by brett@insynchq.com | Copyright Insynchq Pte. Ltd., ("Insync") | http://www.insynchq.com
  4.  
  5. Hacking Notes:
  6.     . St.Icon can not be shared, each bin needs a unique instance of St.Icon
  7.     . Gnome3 has a bug with shell escape in Main.Util.spawnCommandLine,
  8.       these examples will fail: "nautilus ~/Insync" or "nautilus $HOME/Insync"
  9. */
  10.  
  11. const Lang = imports.lang;
  12. const Main = imports.ui.main;
  13. const GLib = imports.gi.GLib;
  14. const Gio = imports.gi.Gio;
  15. const PopupMenu = imports.ui.popupMenu;
  16. const Gtk = imports.gi.Gtk;
  17. const DBus = imports.dbus;
  18. const St = imports.gi.St;       // Gnome3 ShellToolkit
  19. const Gettext = imports.gettext;
  20. const text = Gettext.gettext;
  21.  
  22. const ICON_SIZE  = 13;
  23. const SUB_ICON_SIZE = 12;
  24.  
  25. const STATUS_ICON_LOOKUP = {
  26.     'UNLINKED' : 'insync-idle',
  27.     'SYNCED' : 'insync-synced',
  28.     'SYNCING' : 'insync-syncing',
  29.     'OFFLINE' : 'insync-offline',
  30.     'ERROR' : 'insync-error',
  31.     'WARNING' : 'insync-partial-error'
  32. };
  33.  
  34. //////////////////////////// Helper Functions ///////////////////////////////////
  35.  
  36. function dir( object ) {
  37.     global.log( object );
  38.     for (let name in object) { global.log(name); }
  39. }
  40.  
  41. function load_icon( icon_file, width, height ) {
  42.     try {                   // this can fail without any warning if the file is missing!
  43.         let file = Gio.file_new_for_path(icon_file);
  44.         let icon_uri = file.get_uri();
  45.         let icon = St.TextureCache.get_default().load_uri_sync(1, icon_uri, width, height);
  46.         let iconBox = new St.Bin();
  47.         iconBox.child = icon;
  48.         return iconBox;
  49.     } catch(e) {
  50.         return undefined;
  51.     }
  52. }
  53.  
  54. function get_file_name( uri ) {
  55.     let a = uri.split('/');
  56.     return a[ a.length-1 ];
  57. }
  58.  
  59. //for debugging: alt-F2, "lg"   # looking glass #
  60. function debug(a){
  61.     global.log('<insync>'+a);
  62. }
  63.  
  64.  
  65. function launch() {}
  66. launch.prototype = {
  67.     file: function(file) {
  68.         Gio.app_info_launch_default_for_uri(file, global.create_app_launch_context());
  69.     },
  70.     command: function(location) {
  71.         debug( location );
  72.         Main.Util.spawnCommandLine(location);
  73.     }
  74. }
  75.  
  76. //////////////////////////////// MenuItem Subclass /////////////////////////////////
  77. function MenuItem() { this._init.apply(this, arguments); }
  78. MenuItem.prototype = {
  79.     __proto__: PopupMenu.PopupBaseMenuItem.prototype,    
  80.     _init: function(icon, text, params) {
  81.         PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
  82.         this.box = new St.BoxLayout({ style_class: 'popup-combobox-item' });
  83.         this.icon = icon;
  84.         if (icon) {
  85.             this.box.add(this.icon);
  86.             this.label = new St.Label({ text: ' '+text });
  87.         } else {
  88.             this.label = new St.Label({ text: text });
  89.         }
  90.         this.box.add(this.label);
  91.         this.addActor(this.box);
  92.     }
  93. };
  94. //////////////////////////////// ButtonItem Subclass /////////////////////////////////
  95. function ButtonItem() { this._init.apply(this, arguments); }
  96. ButtonItem.prototype = {
  97.     __proto__: PopupMenu.PopupBaseMenuItem.prototype,    
  98.     _init: function(icon, text, params) {
  99.         PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
  100.         this.box = new St.BoxLayout({ style_class: 'popup-combobox-item', vertical:false });
  101.         if (icon) {
  102.             this.button = new St.Button({ style_class: 'sound-button', toggle_mode: true });
  103.             this.button.set_child( icon );
  104.             this.box.add( this.button );
  105.             this.box.add( new St.Label({ text:text}) );
  106.  
  107.         } else {
  108.             this.button = new St.Button({ toggle_mode: true });
  109.             this.button.set_label( text );
  110.             //this.box.add( new St.Label({ text: '    ' }) );
  111.             this.box.add( this.button );
  112.         }
  113.  
  114.         this.addActor(this.box);
  115.     }
  116. };
  117.  
  118.  
  119. /////////////////////////////////// Applet ///////////////////////////////////////
  120. //const EXTENSION_PATH = '/org/cinnamon/insync';
  121. //const EXTENSION_IFACE = 'org.cinnamon.insync';
  122. const EXTENSION_PATH = '/';
  123. const EXTENSION_IFACE = 'insync.dbus';
  124.  
  125.  
  126. const AppInterface = {
  127.     name : EXTENSION_IFACE,
  128.     methods: [
  129.         {name: 'hello_world', inSignature: 's', outSignature: ''},          // just for testing
  130.         {name: 'toggle_applet', inSignature: 's', outSignature: ''},        // toggle applet on/off
  131.         {name: 'update_status', inSignature: 's', outSignature: ''}     // updates systray icon
  132.     ]
  133. };
  134.  
  135. ///////////////////// TODO - why can't this be upgraded to newer Gdbus API ? //////////////////
  136. /*
  137. const AppInterface = <interface name="org.cinnamon.insync">
  138. <method name="hello_world">
  139.     <arg type="s" direction="in" />
  140.     <arg type="" direction="out" />
  141. </method>
  142. <method name="toggle_applet">
  143.     <arg type="s" direction="in" />
  144.     <arg type="" direction="out" />
  145. </method>
  146. <method name="update_status">
  147.     <arg type="s" direction="in" />
  148.     <arg type="" direction="out" />
  149. </method>
  150. </interface>;
  151. */
  152.  
  153. debug('APPINTERFACE defined');
  154.  
  155. function proxify_object( self ) {
  156.     debug('DBus.session.exports[\'-impl-\'] = ' + DBus.session.exports['-impl-']);
  157.     if ( typeof DBus.session.exports['-impl-'] != 'undefined' ) {
  158.         DBus.session.unexportObject(DBus.session.exports['-impl-']);
  159.     }
  160.     DBus.session.proxifyObject(self, EXTENSION_IFACE, EXTENSION_PATH);
  161.     DBus.session.exportObject(EXTENSION_PATH, self);
  162.     DBus.session.acquire_name(EXTENSION_IFACE, 0, null, null);
  163.     // newer Gdbus API //
  164.     //self._dbus_impl = Gio.DBusExportedObject.wrapJSObject(AppInterface, self);
  165.     //self._dbus_impl.export( Gio.DBus.session, EXTENSION_PATH );
  166. }
  167.  
  168. function rebuild_widget( self ) {
  169.     let active = self._insync_active;
  170.     debug('trying to rebuild widget');
  171.  
  172.     if ( active ) {
  173.         //make_insync_menu(self);
  174.         // first get state from insync process //
  175.         try {
  176.             debug('trying to contact insync process...');
  177.             let proxy = get_insync_proxy()
  178.             proxy.callRemote(
  179.                 'GET-STATE',
  180.                 Lang.bind(self, self.rebuild_insync_menu)       // callback,
  181.             );
  182.         } catch(e) {
  183.             debug('failed to contact insync process!');
  184.             debug(e);
  185.             self._insync_active = false;
  186.  
  187.             let icon = new St.Icon(
  188.                 {
  189.                     icon_name: "error",
  190.                     icon_size: 32
  191.                 }
  192.             );
  193.             let item = new MenuItem(icon, "ERROR: failed to contact insync process");
  194.             self.menu.addMenuItem( item );
  195.         }
  196.  
  197.  
  198.     } else {
  199.         debug('insync not running, falling back to startup UI');
  200.         self.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
  201.         let icon = load_icon( "/usr/share/icons/insync/icons/insync-app.svg", 100, 100 );
  202.         let item = new MenuItem(icon, text("Start Insync"));
  203.         item.connect('activate',
  204.             function(actor, event) {
  205.                 debug('running new insync process');
  206.                 //new launch().command("xterm -e insync --gnome");
  207.                 new launch().command("insync --gnome");
  208.             }
  209.         );
  210.         self.menu.addMenuItem(item);
  211.     }
  212.  
  213. }
  214.  
  215.  
  216. function make_insync_menu(self, data) {
  217.     self._insync_active = true;
  218.     //debug(data);
  219.     let state = JSON.parse( data );
  220.     //debug( state );
  221.  
  222.     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  223.     //self.menu.removeAll();
  224.     //self.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
  225.  
  226.     ///////////////////////////////////// shared folder //////////////////////////////////
  227.     let icon = new St.Icon(
  228.         {
  229.             icon_name: "user-home-symbolic",
  230.             icon_size: ICON_SIZE
  231.         }
  232.     );
  233.     self.homeItem = new MenuItem(icon, text("Open Insync Folder"));
  234.     self.homeItem.connect('activate',
  235.         function(actor, event) {
  236.             get_insync_proxy().callRemote( 'OPEN-INSYNC-FOLDER' ); 
  237.         }
  238.     );
  239.     self.menu.addMenuItem(self.homeItem);
  240.  
  241.     ////////////////////////////////// go to insynchq.com //////////////////////////
  242.     let icon = new St.Icon(
  243.         {
  244.             icon_name: "folder-remote-symbolic",
  245.             icon_size: ICON_SIZE
  246.         }
  247.     );
  248.     let item = new MenuItem(icon, text("Go to Insync Web"));
  249.     item.connect('activate',
  250.         function(actor, event) {
  251.             get_insync_proxy().callRemote( 'http://wwww.insynchq.com' );
  252.         }
  253.     );
  254.     self.menu.addMenuItem(item);
  255.  
  256.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  257.     self.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
  258.  
  259.     let item = new PopupMenu.PopupSubMenuMenuItem(text("Recent Changes"));
  260.     self.menu.addMenuItem( item );
  261.     let item_recent = item;
  262.  
  263.     let item = new PopupMenu.PopupSubMenuMenuItem(text("Actions Required"));
  264.     self.menu.addMenuItem(item);
  265.     let item_actions = item;
  266.  
  267.     let item = new PopupMenu.PopupSubMenuMenuItem(text("Error Messages"));
  268.     self.menu.addMenuItem(item);
  269.     let item_errors = item;
  270.  
  271.     self.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
  272.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  273.  
  274.     //let button = new ButtonItem( undefined, 'Pause Syncing');
  275.     //self.menu.addMenuItem(button);
  276.  
  277.     if (state.paused) {
  278.         let item = new MenuItem(undefined, text("Resume Syncing"));
  279.         self.menu.addMenuItem(item);
  280.         item.connect('activate',
  281.             function(actor,event) {
  282.                 get_insync_proxy().callRemote( "RESUME" );
  283.             }
  284.         );
  285.     } else {
  286.         let item = new MenuItem(undefined, text("Pause Syncing"));
  287.         self.menu.addMenuItem(item);
  288.         item.connect('activate',
  289.             function(actor,event) {
  290.                 get_insync_proxy().callRemote( "PAUSE" );
  291.             }
  292.         );
  293.     }
  294.  
  295.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  296.     self.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
  297.  
  298.     let item = new PopupMenu.PopupSubMenuMenuItem(text("Account Information"));
  299.     self.menu.addMenuItem(item);
  300.     let item_account = item;
  301.  
  302.  
  303.     //let item = new MenuItem(icon, text("Settings"));      // TODO enable this
  304.     //self.menu.addMenuItem(item);
  305.  
  306.     let item = new MenuItem(undefined, text("Support"));
  307.     self.menu.addMenuItem(item);
  308.     item.connect('activate',
  309.         function(actor, event) {
  310.             get_insync_proxy().callRemote( 'http://forums.insynchq.com' );
  311.         }
  312.     );
  313.  
  314.  
  315.     ////////////////////////////////////////////////
  316.     let item = new MenuItem(undefined, text("Quit"), {});
  317.     self.menu.addMenuItem(item);
  318.     item.connect('activate',
  319.         function(actor,event) {
  320.             get_insync_proxy().callRemote( "EXIT" );
  321.             self.shutdown();
  322.         }
  323.     );
  324.     debug('setup UI layout...');
  325.     ////////////////////////////////////////////////////////////////////////////////////////////////
  326.     if (state.recent.length == 0) {
  327.         let icon = new St.Icon({icon_name: 'object-select-symbolic', icon_size: SUB_ICON_SIZE });
  328.         let sub = new MenuItem( icon, "(no recent updates)" );
  329.         item_recent.menu.addMenuItem( sub );
  330.     }
  331.     if (state.actions.length == 0) {
  332.         let icon = new St.Icon({icon_name: 'object-select-symbolic', icon_size: SUB_ICON_SIZE });
  333.         let sub = new MenuItem( icon, "(no actions required)" );
  334.         item_actions.menu.addMenuItem( sub );
  335.     }
  336.     if (state.errors.length == 0) {
  337.         let icon = new St.Icon({icon_name: 'object-select-symbolic', icon_size: SUB_ICON_SIZE });
  338.         let sub = new MenuItem( icon, "(no errors)" );
  339.         item_errors.menu.addMenuItem( sub );
  340.     }
  341.  
  342.  
  343.     let keys = ['recent', 'actions', 'account'];
  344.     for (var h=0; h < keys.length; h++) {
  345.         let key = keys[ h ];
  346.         let list = state[ key ];
  347.  
  348.         for (var i=0; i< list.length; i++) {
  349.             let info_txt = list[i][0];
  350.             let method = list[i][1];
  351.             let item = undefined;
  352.             let icon = undefined;
  353.             switch (key) {
  354.                 case 'recent':
  355.                     item = item_recent;
  356.                     icon = new St.Icon( {icon_name: "edit-select-all-symbolic", icon_size: SUB_ICON_SIZE} );
  357.                     break;
  358.                 case 'actions':
  359.                     item = item_actions;
  360.                     icon = new St.Icon( {icon_name: "document-page-setup-symbolic", icon_size: SUB_ICON_SIZE} );
  361.                     break;
  362.  
  363.                 case 'account':
  364.                     item = item_account;
  365.                     icon = new St.Icon( {icon_name: "weather-overcast-symbolic", icon_size: SUB_ICON_SIZE} );
  366.                     break;
  367.  
  368.                 default:
  369.                     item = undefined; icon = undefined;
  370.                     break;
  371.             }
  372.             var sub = new MenuItem( icon, info_txt );
  373.             item.menu.addMenuItem( sub );
  374.             sub.connect('activate',
  375.                 function(actor,event) {
  376.                     get_insync_proxy().callRemote( method );    // fire and forget
  377.                 }
  378.             );
  379.         }
  380.     }
  381.     //////////////////////////////////////////////
  382.     let icon = new St.Icon( {icon_name: "list-add-symbolic", icon_size: SUB_ICON_SIZE} );
  383.     let sub = new MenuItem( icon, "Connect another Google account" )
  384.     item_account.menu.addMenuItem( sub );
  385.     sub.connect('activate',
  386.         function(actor,event) {
  387.             get_insync_proxy().callRemote( 'ADD-ACCOUNT' ); // fire and forget
  388.         }
  389.     );
  390.     /////////////////////////////////////////////
  391.     if (state.errors.length == 3) {
  392.         let item = item_errors;
  393.         var retry = state.errors[0];  // tuple
  394.         var errors = state.errors[1]; // list of tuples
  395.         var other = state.errors[2];  // null
  396.  
  397.         if (retry.length) {
  398.             let icon = new St.Icon( {icon_name: "view-refresh-symbolic", icon_size: SUB_ICON_SIZE} );
  399.             let info_txt = retry[0];
  400.             let method = retry[1];
  401.             let sub = new MenuItem( icon, info_txt );
  402.             item.menu.addMenuItem( sub );
  403.             sub.connect('activate',
  404.                 function(actor,event) {
  405.                     get_insync_proxy().callRemote( method );    // fire and forget
  406.                 }
  407.             );
  408.             item.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
  409.         }
  410.  
  411.         let list = errors;
  412.         for (var i=0; i< list.length; i++) {
  413.             let icon = new St.Icon( {icon_name: "action-unavailable-symbolic", icon_size: SUB_ICON_SIZE} );
  414.             let info_txt = list[i][0];
  415.             let method = list[i][1];
  416.             let sub = new MenuItem( icon, info_txt );
  417.             item.menu.addMenuItem( sub );
  418.             sub.connect('activate',
  419.                 function(actor,event) {
  420.                     get_insync_proxy().callRemote( method );    // fire and forget
  421.                 }
  422.             );
  423.         }
  424.         if (other) {
  425.             let icon = new St.Icon( {icon_name: "edit-select-symbolic", icon_size: SUB_ICON_SIZE} );
  426.             let sub = new MenuItem( icon, other );
  427.             item.menu.addMenuItem( sub );
  428.         }
  429.     }
  430. }
  431.  
  432.  
  433.  
  434.  
  435. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  436.  
  437. // (Keeping older DBus API instead of the new Gio.DBus to stay compatible with older Cinnamon)
  438. // this should be safer anyways because we still use the older API above.
  439.  
  440. const InsyncRemoteInterface = {
  441.     name: 'insync.rpc', //interface name
  442.     methods: [
  443.         {    //method name and signature
  444.             name: 'call',       // becomes: callRemote
  445.             inSignature: 's',
  446.             outSignature: 's'
  447.         }
  448.     ]
  449. };
  450. /*
  451. const InsyncRemoteInterface = <interface name="insync.rpc">
  452. <method name="call">
  453.     <arg type="s" direction="in" />
  454.     <arg type="s" direction="out" />
  455. </method>
  456. </interface>;
  457. */
  458.  
  459.  
  460. debug('REMOTE-INTERFACE defined');
  461.  
  462. let InsyncProxyClass = DBus.makeProxyClass( InsyncRemoteInterface );
  463. //var InsyncProxyClass = Gio.DBusProxy.makeProxyWrapper( InsyncRemoteInterface );
  464.  
  465. function get_insync_proxy() {
  466.     let proxy = new InsyncProxyClass(
  467.         DBus.session, //Gio.DBus.session,
  468.         'insync.rpc',
  469.         '/'
  470.     );
  471.     return proxy;
  472. }
  473.  
  474. debug('Cinnamon/Gnome3 common API defined');
  475.  
  476. const PanelMenu = imports.ui.panelMenu;
  477.  
  478. let _app;
  479. let SCRIPT_PATH;
  480.  
  481.  
  482. const GnomeApp = new Lang.Class({
  483.     Name: 'InsyncApp.InsyncApp',
  484.     Extends: PanelMenu.SystemStatusButton,
  485.  
  486.     destroy: function() { this.parent(); },
  487.  
  488.     _init: function() {
  489.         this.parent('insync-offline-symbolic', 'Insync');
  490.         proxify_object( this ); // common.js
  491.  
  492.         // this is required for on_button_press to work properly
  493.         let item = new PopupMenu.PopupSubMenuMenuItem("hello world");
  494.         this.menu.addMenuItem( item );
  495.  
  496.         this.actor.connect('button-press-event', Lang.bind(this, this.on_button_press));
  497.         this.start_insync_if_inactive();
  498.  
  499.     },
  500.  
  501.     start_insync_if_inactive: function() {
  502.         // parses /proc to see if insync is running for the logged in user
  503.         // if for some reason /proc is inaccessible, looks for the insync socket file
  504.         this._insync_active = false;
  505.         let read_attr = Gio.FILE_ATTRIBUTE_ACCESS_CAN_READ;
  506.         let home_dir = Gio.file_new_for_path(GLib.get_home_dir());
  507.         let home_dir_info = home_dir.query_info(Gio.FILE_ATTRIBUTE_UNIX_UID, 0, null);
  508.         let uid = home_dir_info.get_attribute_as_string(Gio.FILE_ATTRIBUTE_UNIX_UID);
  509.         let proc = Gio.file_new_for_path('/proc');
  510.         let proc_info = proc.query_info(read_attr, 0, null);
  511.         let proc_access = proc_info.get_attribute_as_string(read_attr, null);
  512.         if ( proc_access == 'TRUE' ) {
  513.             let processes = proc.enumerate_children(Gio.FILE_ATTRIBUTE_STANDARD_NAME, 0, null);
  514.             let process;
  515.             while ( (process = processes.next_file(null)) != null ) {
  516.                 let pid = process.get_name();
  517.                 if ( isNaN(pid) ) {
  518.                     continue;
  519.                 }
  520.                 let status_file = Gio.file_new_for_path('/proc/' + pid + '/status');
  521.                 if ( !status_file.query_exists(null) ) {
  522.                     debug('apparently this sometimes happens: ' + status_file + ' not found');
  523.                     continue;
  524.                 }
  525.                 let status_file_info = status_file.query_info(read_attr, 0, null);
  526.                 let status_file_access = status_file_info.get_attribute_as_string(read_attr, null);
  527.                 if ( status_file_access != 'TRUE' ) {
  528.                     continue;
  529.                 }
  530.                 let status_file_dict = this.parse_status_file(String(status_file.load_contents(null)[1]));
  531.                 let process_real_uid = status_file_dict['Uid'].split(' ')[0];
  532.                 //debug('name: ' + status_file_dict['Name']);
  533.                 //debug('process_real_uid: ' + process_real_uid);
  534.                 if ( status_file_dict['Name'] == 'insync' &&
  535.                      process_real_uid == uid &&
  536.                      status_file_dict['State'] != 'Z (zombie)' ) {
  537.                     this._insync_active = true;
  538.                     break;
  539.                 }
  540.             }
  541.             if ( !this._insync_active ) {
  542.                 debug('running insync process');
  543.                 Main.Util.spawnCommandLine('insync --gnome');
  544.             }
  545.         } else {
  546.             // no access to /proc; check using existence of insync socket
  547.             debug('no access to /proc; really?');
  548.             let insync_socket = Gio.file_new_for_path('/tmp/insync' + uid + '.sock')
  549.             if ( !insync_socket.query_exists(null) ) {
  550.                 debug('running insync process');
  551.                 Main.Util.spawnCommandLine('insync --gnome');
  552.             }
  553.         }
  554.         this._insync_active = true;
  555.     },
  556.  
  557.     parse_status_file: function( status_file_contents ) {
  558.         let split_strings = status_file_contents.replace(/\t/g, ' ').trim().split('\n');
  559.         let status_file_dict = new Object();
  560.         for (let i = 0; i < split_strings.length; i++) {
  561.             let kv_pair = split_strings[i].split(':', 2);
  562.             status_file_dict[kv_pair[0].trim()] = kv_pair[1].trim();
  563.         }
  564.         return status_file_dict;
  565.     },
  566.  
  567.     on_button_press: function( actor, event ) {
  568.         debug('on_button_press');
  569.         debug( this.menu );
  570.         this.menu.removeAll();
  571.         rebuild_widget(this);
  572.         //this.menu.toggle();       // DO NOT call this.menu.toggle()
  573.         debug('on_button_press OK');
  574.     },
  575.  
  576.     shutdown: function() {
  577.         this._insync_active = false;
  578.         this.setIcon( 'insync-offline-symbolic' );
  579.     },
  580.  
  581.     // dbus callback - proxy.callRemote(..., callback) //
  582.     rebuild_insync_menu: function( data ) {
  583.         debug('calling rebuild-insync-menu');
  584.         //debug( data );
  585.         make_insync_menu(this, data);
  586.     },
  587.  
  588.  
  589.     ///////////////////////////// dbus methods ///////////////////////////
  590.     hello_world: function( string ) {
  591.         debug('calling hello_world');
  592.     },
  593.     toggle_applet: function( string ) {
  594.         if ( string=='ON' ) {
  595.             this._insync_active = true;
  596.         } else {
  597.             this._insync_active = false;
  598.             this.shutdown();
  599.         }
  600.     },
  601.  
  602.     update_status: function( state ) {
  603.         debug('calling update_status');
  604.         this._insync_active = true;
  605.         let icon = STATUS_ICON_LOOKUP[ state ];
  606.         this.setIcon( icon+"-symbolic" );       // Hadim
  607.         //let gicon = Gio.icon_new_for_string( SCRIPT_PATH + '/' + icon + '.svg' );
  608.         //this.setGIcon( gicon );
  609.         debug('icon set!');
  610.     }
  611.  
  612. });
  613.  
  614.  
  615. function init(metadata) {
  616.     debug( 'insync gnome applet init' );
  617.     debug( metadata.path );
  618.     SCRIPT_PATH = metadata.path;
  619.     Gtk.IconTheme.get_default().append_search_path(metadata.path);
  620. }
  621.  
  622.  
  623. function enable() {
  624.     _app = new GnomeApp;
  625.     Main.panel.addToStatusArea('places-menu-insync', _app);
  626. }
  627.  
  628. function disable() {
  629.     _app.destroy();
  630. }
  631.  
  632. DBus.conformExport(GnomeApp.prototype, AppInterface);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement