2013-10-27 21:59:46 +01:00
# Copyright (C) 2009, 2013 Red Hat, Inc.
2009-07-27 22:30:01 -04:00
# Copyright (C) 2009 Cole Robinson <crobinso@redhat.com>
#
2018-04-04 14:35:41 +01:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 15:00:02 -04:00
# See the COPYING file in the top-level directory.
2009-07-27 22:30:01 -04:00
2012-01-31 18:16:54 -05:00
import logging
2012-05-14 14:24:56 +01:00
from gi . repository import Gtk
2009-07-27 22:30:01 -04:00
2014-09-12 16:10:45 -04:00
from . import vmmenu
from . baseclass import vmmGObject
2018-03-14 13:13:22 -04:00
from . connmanager import vmmConnectionManager
2010-11-23 20:13:50 -05:00
2013-04-13 14:34:52 -04:00
2010-12-09 14:06:00 -05:00
class vmmSystray ( vmmGObject ) :
2018-03-15 05:53:58 -04:00
@classmethod
def get_instance ( cls ) :
if not cls . _instance :
2018-03-17 16:08:20 -04:00
cls . _instance = vmmSystray ( )
2018-03-15 05:53:58 -04:00
return cls . _instance
2012-05-14 14:24:56 +01:00
2018-03-14 13:13:22 -04:00
def __init__ ( self ) :
2010-12-09 14:06:00 -05:00
vmmGObject . __init__ ( self )
2018-03-15 07:43:56 -04:00
self . _cleanup_on_app_close ( )
2009-07-27 22:30:01 -04:00
2010-11-23 20:13:50 -05:00
self . topwin = None
2009-07-27 22:30:01 -04:00
self . conn_menuitems = { }
self . conn_vm_menuitems = { }
self . vm_action_dict = { }
2018-03-15 05:53:58 -04:00
2009-07-27 22:30:01 -04:00
self . systray_menu = None
self . systray_icon = None
2018-03-15 05:53:58 -04:00
self . _init_ui ( )
2009-07-27 22:30:01 -04:00
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2018-03-15 05:53:58 -04:00
self . config . on_view_system_tray_changed (
self . _show_systray_changed_cb ) )
self . _show_systray_changed_cb ( )
2009-07-27 22:30:01 -04:00
2018-03-14 13:13:22 -04:00
connmanager = vmmConnectionManager . get_instance ( )
connmanager . connect ( " conn-added " , self . _conn_added )
connmanager . connect ( " conn-removed " , self . _conn_removed )
for conn in connmanager . conns . values ( ) :
self . _conn_added ( connmanager , conn )
2018-03-14 10:29:20 -04:00
2018-03-17 11:46:38 -04:00
def is_embedded ( self ) :
2018-03-17 11:37:58 -04:00
return ( self . systray_icon and
2018-03-08 13:01:23 -05:00
self . systray_icon . is_embedded ( ) )
2009-11-10 11:56:15 -05:00
2011-07-23 21:16:54 -04:00
def _cleanup ( self ) :
if self . systray_menu :
self . systray_menu . destroy ( )
self . systray_menu = None
2011-04-13 09:27:02 -04:00
2018-03-17 11:37:58 -04:00
self . _hide ( )
2015-09-20 14:20:50 -04:00
self . conn_menuitems = None
self . conn_vm_menuitems = None
self . vm_action_dict = None
2011-04-13 09:27:02 -04:00
2015-09-20 14:20:50 -04:00
###########################
# Initialization routines #
###########################
2009-07-27 22:30:01 -04:00
2018-03-15 05:53:58 -04:00
def _init_ui ( self ) :
2012-05-14 14:24:56 +01:00
self . systray_menu = Gtk . Menu ( )
self . systray_menu . add ( Gtk . SeparatorMenuItem ( ) )
2010-02-28 20:28:51 -05:00
2012-05-14 14:24:56 +01:00
exit_item = Gtk . ImageMenuItem . new_from_stock ( Gtk . STOCK_QUIT , None )
2009-07-27 22:30:01 -04:00
exit_item . connect ( " activate " , self . exit_app )
self . systray_menu . add ( exit_item )
self . systray_menu . show_all ( )
2018-03-17 11:37:58 -04:00
def _show ( self ) :
if self . systray_icon :
return
2018-03-08 13:01:23 -05:00
self . systray_icon = Gtk . StatusIcon ( )
2018-03-17 11:37:58 -04:00
self . systray_icon . set_visible ( True )
2018-03-08 13:01:23 -05:00
self . systray_icon . set_property ( " icon-name " , " virt-manager " )
self . systray_icon . connect ( " activate " , self . systray_activate )
self . systray_icon . connect ( " popup-menu " , self . systray_popup )
self . systray_icon . set_tooltip_text ( _ ( " Virtual Machine Manager " ) )
2018-03-17 11:37:58 -04:00
def _hide ( self ) :
if not self . systray_icon :
return
self . systray_icon . set_visible ( False )
self . systray_icon = None
2009-07-27 22:30:01 -04:00
2018-03-15 05:53:58 -04:00
def _show_systray_changed_cb ( self ) :
2009-07-27 22:30:01 -04:00
do_show = self . config . get_view_system_tray ( )
2012-01-31 18:16:54 -05:00
logging . debug ( " Showing systray: %s " , do_show )
2009-07-27 22:30:01 -04:00
2018-03-15 05:53:58 -04:00
if do_show :
2018-03-17 11:37:58 -04:00
self . _show ( )
2009-07-27 22:30:01 -04:00
else :
2018-03-17 11:37:58 -04:00
self . _hide ( )
2009-07-27 22:30:01 -04:00
# Helper functions
def _get_vm_menu_item ( self , vm ) :
2014-06-02 17:17:47 -04:00
connkey = vm . get_connkey ( )
2011-07-22 16:43:26 -04:00
uri = vm . conn . get_uri ( )
2009-07-27 22:30:01 -04:00
2010-12-10 11:47:07 -05:00
if uri in self . conn_vm_menuitems :
2014-06-02 17:17:47 -04:00
if connkey in self . conn_vm_menuitems [ uri ] :
return self . conn_vm_menuitems [ uri ] [ connkey ]
2009-07-27 22:30:01 -04:00
return None
def _set_vm_status_icon ( self , vm , menu_item ) :
2012-05-14 14:24:56 +01:00
image = Gtk . Image ( )
2011-07-12 11:50:11 -04:00
image . set_from_icon_name ( vm . run_status_icon_name ( ) ,
2012-05-14 14:24:56 +01:00
Gtk . IconSize . MENU )
2009-07-27 22:30:01 -04:00
image . set_sensitive ( vm . is_active ( ) )
menu_item . set_image ( image )
# Listeners
2018-03-15 05:53:58 -04:00
def systray_activate ( self , _src ) :
from . manager import vmmManager
manager = vmmManager . get_instance ( self )
if manager . is_visible ( ) :
manager . close ( )
else :
manager . show ( )
2009-07-27 22:30:01 -04:00
2010-12-09 11:22:35 -05:00
def systray_popup ( self , widget_ignore , button , event_time ) :
2009-07-27 22:30:01 -04:00
if button != 3 :
return
2012-05-14 14:24:56 +01:00
self . systray_menu . popup ( None , None , Gtk . StatusIcon . position_menu ,
self . systray_icon , 0 , event_time )
2009-07-27 22:30:01 -04:00
2010-03-24 10:58:17 -04:00
def repopulate_menu_list ( self ) :
# Build sorted connection list
2017-10-11 12:35:46 +01:00
connsort = list ( self . conn_menuitems . keys ( ) )
2010-03-24 10:58:17 -04:00
connsort . sort ( )
connsort . reverse ( )
# Empty conn list
for child in self . systray_menu . get_children ( ) :
2017-10-11 12:35:46 +01:00
if child in list ( self . conn_menuitems . values ( ) ) :
2010-03-24 10:58:17 -04:00
self . systray_menu . remove ( child )
# Build sorted conn list
for uri in connsort :
self . systray_menu . insert ( self . conn_menuitems [ uri ] , 0 )
2018-03-14 10:29:20 -04:00
def _conn_added ( self , _engine , conn ) :
2009-07-27 22:30:01 -04:00
conn . connect ( " vm-added " , self . vm_added )
conn . connect ( " vm-removed " , self . vm_removed )
conn . connect ( " state-changed " , self . conn_state_changed )
2010-12-10 11:47:07 -05:00
if conn . get_uri ( ) in self . conn_menuitems :
2009-07-27 22:30:01 -04:00
return
2014-07-04 18:20:08 -04:00
menu_item = Gtk . MenuItem . new_with_label ( conn . get_pretty_desc ( ) )
2009-07-27 22:30:01 -04:00
menu_item . show ( )
2012-05-14 14:24:56 +01:00
vm_submenu = Gtk . Menu ( )
2009-07-27 22:30:01 -04:00
vm_submenu . show ( )
menu_item . set_submenu ( vm_submenu )
self . conn_menuitems [ conn . get_uri ( ) ] = menu_item
self . conn_vm_menuitems [ conn . get_uri ( ) ] = { }
2010-03-24 10:58:17 -04:00
self . repopulate_menu_list ( )
2009-07-27 22:30:01 -04:00
self . conn_state_changed ( conn )
self . populate_vm_list ( conn )
2018-03-14 10:29:20 -04:00
def _conn_removed ( self , _engine , uri ) :
2014-05-02 10:20:59 -04:00
if uri not in self . conn_menuitems :
2009-07-27 22:30:01 -04:00
return
2011-04-12 11:50:10 -04:00
menu_item = self . conn_menuitems [ uri ]
2009-07-27 22:30:01 -04:00
self . systray_menu . remove ( menu_item )
2011-04-14 13:26:44 -04:00
menu_item . destroy ( )
2011-04-12 11:50:10 -04:00
del ( self . conn_menuitems [ uri ] )
self . conn_vm_menuitems [ uri ] = { }
2009-07-27 22:30:01 -04:00
2010-03-24 10:58:17 -04:00
self . repopulate_menu_list ( )
2009-07-27 22:30:01 -04:00
def conn_state_changed ( self , conn ) :
sensitive = conn . is_active ( )
menu_item = self . conn_menuitems [ conn . get_uri ( ) ]
menu_item . set_sensitive ( sensitive )
def populate_vm_list ( self , conn ) :
uri = conn . get_uri ( )
conn_menu_item = self . conn_menuitems [ uri ]
vm_submenu = conn_menu_item . get_submenu ( )
# Empty conn menu
for c in vm_submenu . get_children ( ) :
vm_submenu . remove ( c )
vm_mappings = { }
2014-06-02 17:17:47 -04:00
for vm in conn . list_vms ( ) :
vm_mappings [ vm . get_name ( ) ] = vm . get_connkey ( )
2009-07-27 22:30:01 -04:00
2017-10-11 12:35:46 +01:00
vm_names = list ( vm_mappings . keys ( ) )
2009-07-27 22:30:01 -04:00
vm_names . sort ( )
if len ( vm_names ) == 0 :
2014-02-25 15:57:38 -05:00
menu_item = Gtk . MenuItem . new_with_label ( _ ( " No virtual machines " ) )
2009-07-27 22:30:01 -04:00
menu_item . set_sensitive ( False )
vm_submenu . insert ( menu_item , 0 )
return
2017-10-11 12:36:03 +01:00
for i , name in enumerate ( vm_names ) :
2014-06-02 17:17:47 -04:00
connkey = vm_mappings [ name ]
if connkey in self . conn_vm_menuitems [ uri ] :
vm_item = self . conn_vm_menuitems [ uri ] [ connkey ]
2009-07-27 22:30:01 -04:00
vm_submenu . insert ( vm_item , i )
2014-06-02 17:17:47 -04:00
def vm_added ( self , conn , connkey ) :
2011-07-22 13:54:40 -04:00
uri = conn . get_uri ( )
2014-06-02 17:17:47 -04:00
vm = conn . get_vm ( connkey )
2009-07-27 22:30:01 -04:00
if not vm :
return
2015-04-09 18:02:42 -04:00
vm . connect ( " state-changed " , self . vm_state_changed )
2009-07-27 22:30:01 -04:00
vm_mappings = self . conn_vm_menuitems [ uri ]
2014-06-02 17:17:47 -04:00
if connkey in vm_mappings :
2009-07-27 22:30:01 -04:00
return
# Build VM list entry
2014-02-25 15:57:38 -05:00
menu_item = Gtk . ImageMenuItem . new_with_label ( vm . get_name ( ) )
menu_item . set_use_underline ( False )
2014-06-02 17:17:47 -04:00
vm_mappings [ connkey ] = menu_item
2014-01-28 18:04:46 -05:00
vm_action_menu = vmmenu . VMActionMenu ( self , lambda : vm )
2009-07-27 22:30:01 -04:00
menu_item . set_submenu ( vm_action_menu )
2014-06-02 17:17:47 -04:00
self . vm_action_dict [ connkey ] = vm_action_menu
2009-07-27 22:30:01 -04:00
# Add VM to menu list
self . populate_vm_list ( conn )
# Update state
self . vm_state_changed ( vm )
menu_item . show ( )
2014-06-02 17:17:47 -04:00
def vm_removed ( self , conn , connkey ) :
2011-07-22 13:54:40 -04:00
uri = conn . get_uri ( )
2009-07-27 22:30:01 -04:00
vm_mappings = self . conn_vm_menuitems [ uri ]
if not vm_mappings :
return
2014-06-02 17:17:47 -04:00
if connkey not in vm_mappings :
return
conn_item = self . conn_menuitems [ uri ]
vm_menu_item = vm_mappings [ connkey ]
vm_menu = conn_item . get_submenu ( )
vm_menu . remove ( vm_menu_item )
vm_menu_item . destroy ( )
2018-03-12 18:18:09 -04:00
vm_mappings . pop ( connkey )
self . vm_action_dict . pop ( connkey )
2014-06-02 17:17:47 -04:00
if len ( vm_menu . get_children ( ) ) == 0 :
placeholder = Gtk . MenuItem . new_with_label (
_ ( " No virtual machines " ) )
placeholder . show ( )
placeholder . set_sensitive ( False )
vm_menu . add ( placeholder )
2009-07-27 22:30:01 -04:00
2015-04-09 16:07:09 -04:00
def vm_state_changed ( self , vm ) :
2009-07-27 22:30:01 -04:00
menu_item = self . _get_vm_menu_item ( vm )
if not menu_item :
return
self . _set_vm_status_icon ( vm , menu_item )
# Update action widget states
2014-06-02 17:17:47 -04:00
menu = self . vm_action_dict [ vm . get_connkey ( ) ]
2013-09-22 15:13:41 -04:00
menu . update_widget_states ( vm )
2009-07-27 22:30:01 -04:00
2018-03-14 18:58:22 -04:00
def exit_app ( self , _src ) :
2018-03-17 11:46:38 -04:00
from . engine import vmmEngine
2018-03-14 18:58:22 -04:00
vmmEngine . get_instance ( ) . exit_app ( )