o
    >bê<  ã                   @   sˆ  d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlmZ ddlm	Z	 ddl
mZ dd	lmZ ze d
d¡ d dlmZ W n eyK   dZY nw eshze dd¡ d dlmZ W n eyg   dZY nw dd„ Zdd„ Zdd„ Zdd„ ZdZer’e de¡ eƒ s‹e d¡ ndZe d¡ G dd„ deƒZG dd„ deƒZG d d!„ d!eƒZG d"d#„ d#eƒZG d$d%„ d%eƒZG d&d'„ d'eƒZdS )(é    N)ÚGio)ÚGtk)Úlog)Úxmlutilé   )Úvmmenu)Ú
vmmGObject)ÚvmmConnectionManagerÚAyatanaAppIndicator3z0.1)r
   ÚAppIndicator3)r   c                  O   s>   | }|}ddl m} | d ¡}| ¡ r| ¡  d S | ¡  d S )Nr   )Ú
vmmManager)Úmanagerr   Úget_instanceÚ
is_visibleÚcloseÚshow)ÚargsÚkwargsÚignorer   r   © r   ú./usr/share/virt-manager/virtManager/systray.pyÚ_toggle_manager(   s   
r   c                 C   s*   t  ¡ }|j| }| ¡ r| ¡  d S d S ©N)r	   r   ÚconnsÚis_disconnectedÚopen©ÚsrcÚuriÚconnmanagerÚconnr   r   r   Ú_conn_connect_cb3   ó
   
ÿr!   c                 C   s*   t  ¡ }|j| }| ¡ s| ¡  d S d S r   )r	   r   r   r   r   r   r   r   r   Ú_conn_disconnect_cb:   r"   r#   c               	   C   sr   z)t  t jjd ¡} t j | dd dddd ¡}| dd¡rW dS | dd¡r'W dS W dS  ty8   t 	d	¡ Y dS w )
Nr   zorg.freedesktop.DBusz/org/freedesktop/DBusz(s)zorg.kde.StatusNotifierWatcherTz%org.freedesktop.StatusNotifierWatcherFz$Error checking for appindicator dbus)
r   Úbus_get_syncÚBusTypeÚSESSIONÚ	DBusProxyÚnew_syncÚNameHasOwnerÚ	Exceptionr   Ú	exception)ÚbusÚdbusr   r   r   Ú_has_appindicator_dbusA   s    ý
þr.   FzImported AppIndicator3=%sz=AppIndicator3 is available, but didn't find any dbus watcher.TzUsing AppIndicator3 for systrayc                   @   s,   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	S )
Ú_Systrayc                 C   ó   t ƒ ‚r   ©ÚNotImplementedError©Úselfr   r   r   Úis_embeddedb   ó   z_Systray.is_embeddedc                 C   r0   r   r1   r3   r   r   r   r   d   r6   z_Systray.showc                 C   r0   r   r1   r3   r   r   r   Úhidef   r6   z_Systray.hidec                 C   r0   r   r1   ©r4   Úmenur   r   r   Úset_menuh   r6   z_Systray.set_menuN)Ú__name__Ú
__module__Ú__qualname__r5   r   r7   r:   r   r   r   r   r/   a   s
    r/   c                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú_SystrayIndicatorz%
    UI backend for appindicator
    c                 C   s   t j ddt jj¡| _d S )Núvirt-manager)r   Ú	IndicatorÚnewÚIndicatorCategoryÚAPPLICATION_STATUSÚ_iconr3   r   r   r   Ú__init__p   s   
þz_SystrayIndicator.__init__c                 C   sX   t j tdƒ¡}| dt¡ | ¡  | |t| 	¡ ƒd ¡ | j
 |¡ | j
 |¡ d S )Nz_Show Virtual Machine ManagerÚactivater   )r   ÚMenuItemÚnew_with_mnemonicÚ_Úconnectr   r   ÚinsertÚlenÚget_childrenrD   r:   Úset_secondary_activate_target)r4   r9   Ú	hide_itemr   r   r   r:   u   s   ÿz_SystrayIndicator.set_menuc                 C   s"   | j  d¡sdS | j  ¡ tjjkS )NÚ	connectedF)rD   Úget_propertyÚ
get_statusr   ÚIndicatorStatusÚPASSIVEr3   r   r   r   r5      s
   ÿz_SystrayIndicator.is_embeddedc                 C   ó   | j  tjj¡ d S r   )rD   Ú
set_statusr   rS   ÚACTIVEr3   r   r   r   r   …   ó   z_SystrayIndicator.showc                 C   rU   r   )rD   rV   r   rS   rT   r3   r   r   r   r7   ‡   rX   z_SystrayIndicator.hideN)	r;   r<   r=   Ú__doc__rE   r:   r5   r   r7   r   r   r   r   r>   l   s    
r>   c                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )Ú_SystrayStatusIconz'
    UI backend for Gtk StatusIcon
    c                 C   sP   t  ¡ | _| j dd¡ | j dt¡ | j d| j¡ | j tdƒ¡ d | _	d S )Nz	icon-namer?   rF   z
popup-menuzVirtual Machine Manager)
r   Ú
StatusIconrD   Úset_propertyrJ   r   Ú	_popup_cbÚset_tooltip_textrI   Ú_menur3   r   r   r   rE      s   

z_SystrayStatusIcon.__init__c                 C   ó
   | j  ¡ S r   )rD   r5   r3   r   r   r   r5   —   ó   
z_SystrayStatusIcon.is_embeddedc                 C   ó
   || _ d S r   ©r_   r8   r   r   r   r:   š   ra   z_SystrayStatusIcon.set_menuc                 C   s,   |dkrd S | j  d d tjj| jd|¡ d S )Né   r   )r_   Úpopupr   r[   Úposition_menurD   )r4   r   ÚbuttonÚ
event_timer   r   r   r]      s   
þz_SystrayStatusIcon._popup_cbc                 C   ó   | j  d¡ d S )NT©rD   Úset_visibler3   r   r   r   r   ¥   ó   z_SystrayStatusIcon.showc                 C   ri   )NFrj   r3   r   r   r   r7   §   rl   z_SystrayStatusIcon.hideN)
r;   r<   r=   rY   rE   r5   r:   r]   r   r7   r   r   r   r   rZ   ‹   s    rZ   c                   @   sH   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )Ú_SystrayWindowzŠ
    A mock systray implementation that shows its own top level window,
    so we can test more of the infrastructure in our ui tests
    c                 C   s   d | _ d | _|  ¡  d S r   )Ú_windowr_   Ú_init_uir3   r   r   r   rE   °   s   z_SystrayWindow.__init__c                 C   sT   t j t j¡}| d| j¡ t  ¡ | _| j dd¡ | j 	¡  
d¡ | j |¡ d S )Nzbutton-press-eventéd   zvmm-fake-systray)r   ÚButtonÚnew_from_stockÚ	STOCK_ADDrJ   r]   ÚWindowrn   Úset_size_requestÚget_accessibleÚset_nameÚadd)r4   rg   r   r   r   ro   µ   s   
z_SystrayWindow._init_uic                 C   r`   r   )rn   r   r3   r   r   r   r5   ¾   ra   z_SystrayWindow.is_embeddedc                 C   rb   r   rc   r8   r   r   r   r:   Á   ra   z_SystrayWindow.set_menuc                 C   s$   |j dkr
tƒ  d S | j |¡ d S )Nr   )rg   r   r_   Úpopup_at_pointer)r4   r   Úeventr   r   r   r]   Ä   s   

z_SystrayWindow._popup_cbc                 C   ó   | j  ¡  d S r   )rn   Úshow_allr3   r   r   r   r   Ê   ó   z_SystrayWindow.showc                 C   r{   r   )rn   r7   r3   r   r   r   r7   Ì   r}   z_SystrayWindow.hideN)r;   r<   r=   rY   rE   ro   r5   r:   r]   r   r7   r   r   r   r   rm   «   s    	rm   c                   @   sÀ   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.S )/Ú_TrayMainMenuz[
    Helper class for maintaining the conn + VM menu list and updating
    it in place
    c                 C   s   t  | ¡ d | _|  ¡ | _d S r   )r   rE   ÚtopwinÚ_build_menur_   r3   r   r   r   rE   Õ   s   
z_TrayMainMenu.__init__c                 C   s   | j  ¡  d | _ d S r   )r_   Údestroyr3   r   r   r   Ú_cleanupÛ   s   

z_TrayMainMenu._cleanupc                 C   sX   t  ¡ }| ¡  d¡ | t  ¡ ¡ t j t jd¡}| 	d| j
¡ | |¡ | ¡  |S )zK
        Build the top level conn list menu when clicking the icon
        zvmm-systray-menuNrF   )r   ÚMenurv   rw   rx   ÚSeparatorMenuItemÚImageMenuItemrr   Ú
STOCK_QUITrJ   Ú_exit_app_cbr|   )r4   r9   Ú	exit_itemr   r   r   r€   ä   s   
z_TrayMainMenu._build_menuc                 C   ó   t |dd ƒS ©NÚ_vmlookupkey©Úgetattr©r4   Úchildr   r   r   Ú_get_lookupkeyø   ó   z_TrayMainMenu._get_lookupkeyc                 C   ó   t |d|ƒS rŠ   ©Úsetattr©r4   r   Úvalr   r   r   Ú_set_lookupkeyú   r‘   z_TrayMainMenu._set_lookupkeyc                 C   r‰   ©NÚ
_vmsortkeyrŒ   rŽ   r   r   r   Ú_get_sortkeyý   r‘   z_TrayMainMenu._get_sortkeyc                 C   r’   r˜   r“   r•   r   r   r   Ú_set_sortkeyÿ   r‘   z_TrayMainMenu._set_sortkeyc                 C   s,   |  ¡ }| | ¡ ¡ | ¡ }| |¡ d S r   )Ú	get_childÚset_textÚget_name_or_titleÚget_submenuÚupdate_widget_states)r4   Ú	menu_itemÚvmÚlabelÚvm_action_menur   r   r   Ú_set_vm_state  s   z_TrayMainMenu._set_vm_statec                    sh   t j d¡}| d¡ t | ‡ fdd„¡}| |¡ |  |ˆ ¡ |  |ˆ  	¡ ¡ |  
|ˆ ¡ | ¡  |S )z<
        Build a menu item representing a single VM
        ÚFOOFc                      s   ˆ S r   r   r   ©r¢   r   r   Ú<lambda>  s    z2_TrayMainMenu._build_vm_menuitem.<locals>.<lambda>)r   r…   Únew_with_labelÚset_use_underliner   ÚVMActionMenuÚset_submenur—   r›   rž   r¥   r|   )r4   r¢   r¡   r¤   r   r§   r   Ú_build_vm_menuitem  s   

z _TrayMainMenu._build_vm_menuitemc                 C   s†   |  ¡ }| ¡ r|  ¡ }dt | ¡ ¡ }| |¡ n| | ¡ ¡ |  | ¡ d¡}|  | ¡ d¡}| 	| ¡ ¡ | 	| ¡  ¡ d S )Nz	<b>%s</b>r   é   )
rœ   Ú	is_activer   Ú
xml_escapeÚget_pretty_descÚ
set_markupr   Ú_find_lookupkeyrŸ   rk   )r4   r¡   r    r£   ÚmarkupÚconnect_itemÚdisconnect_itemr   r   r   Ú_set_conn_state  s   z_TrayMainMenu._set_conn_statec                 C   sö   t j d¡}|  || ¡ ¡ ttt| ¡  ƒƒƒ}|| 	¡  
¡ 7 }|  ||¡ t  ¡ }| |¡ | t  ¡ ¡ t j t jd¡}| dt| ¡ ¡ |  |d¡ | |¡ t j t jd¡}| dt| ¡ ¡ |  |d¡ | |¡ | ¡  |  ||¡ |S )z}
        Build a menu item representing a single connection, and populate
        all its VMs as items in a sub menu
        r¦   NrF   r   r®   )r   rG   r©   r—   Úget_uriÚstrÚintÚboolr¯   r±   Úlowerr›   rƒ   r¬   rx   r„   r…   rr   ÚSTOCK_DISCONNECTrJ   r#   ÚSTOCK_CONNECTr!   r|   r·   )r4   r    r¡   Úsortkeyr9   Úcitem1Úcitem2r   r   r   Ú_build_conn_menuitem%  s&   


z"_TrayMainMenu._build_conn_menuitemc                 C   s(   |  ¡ D ]}|  |¡|kr|  S qd S r   )rM   r   )r4   ÚparentÚkeyr   r   r   r   r³   D  s
   ÿÿz_TrayMainMenu._find_lookupkeyc                 C   s   |   | j|¡S r   )r³   r_   )r4   r   r   r   r   Ú_find_conn_menuitemI  r}   z!_TrayMainMenu._find_conn_menuitemc                 C   s   |   |¡}|  | ¡ |¡S r   )rÅ   r³   rŸ   )r4   r   r¢   Úconnmenur   r   r   Ú_find_vm_menuitemL  s   
z_TrayMainMenu._find_vm_menuitemc                 C   s   ddl m} | ¡  ¡  d S )Nr   )Ú	vmmEngine)ÚenginerÈ   r   Úexit_app)r4   r   rÈ   r   r   r   r‡   U  s   z_TrayMainMenu._exit_app_cbc                 C   s   | j S r   rc   r3   r   r   r   Úget_menu^  r6   z_TrayMainMenu.get_menuc                 C   sd   |   |¡}|  |¡}d}tt| j ¡ ƒƒD ]\}}|  |¡}|d u s&||kr( nq| j ||¡ d S ©Nr   )rÂ   rš   Ú	enumerateÚlistr_   rM   rK   )r4   r    rÆ   r¿   Úidxr   Ú	checksortr   r   r   Úconn_adda  s   


ÿz_TrayMainMenu.conn_addc                 C   s*   |   |¡}|r| j |¡ | ¡  d S d S r   )rÅ   r_   Úremover   )r4   r   rÆ   r   r   r   Úconn_removem  s
   
þz_TrayMainMenu.conn_removec                 C   s   |   | ¡ ¡}|  ||¡ d S r   )rÅ   r¸   r·   )r4   r    rÆ   r   r   r   Úconn_changes  ó   z_TrayMainMenu.conn_changec           	      C   sx   |   |j ¡ ¡}|  |¡}|  |¡}| ¡ }d}tt| ¡ ƒƒD ]\}}|  |¡}|d u s1||kr3 nq | 	||¡ d S rÌ   )
rÅ   r    r¸   r­   rš   rŸ   rÍ   rÎ   rM   rK   )	r4   r¢   rÆ   r¡   r¿   Ú	vmsubmenurÏ   r   rÐ   r   r   r   Úvm_addw  s   


ÿz_TrayMainMenu.vm_addc                 C   s>   |j }|  | ¡ ¡}|  | ¡ |¡}| ¡  |¡ | ¡  d S r   )r    rÅ   r¸   rÇ   rŸ   rÒ   r   )r4   r¢   r    rÆ   Úvmitemr   r   r   Ú	vm_remove…  s
   z_TrayMainMenu.vm_removec                 C   s"   |   |j ¡ |¡}|  ||¡ d S r   )rÇ   r    r¸   r¥   )r4   r¢   rØ   r   r   r   Ú	vm_changeŒ  s   z_TrayMainMenu.vm_changeN)r;   r<   r=   rY   rE   r‚   r€   r   r—   rš   r›   r¥   r­   r·   rÂ   r³   rÅ   rÇ   r‡   rË   rÑ   rÓ   rÔ   r×   rÙ   rÚ   r   r   r   r   r~   Ð   s0    			r~   c                   @   s˜   e Zd ZdZedd„ ƒZedd„ ƒZdd„ Zdd	„ Z	d
d„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"S )#Ú
vmmSystrayz`
    API class representing a systray icon. May use StatusIcon or appindicator
    backends
    c                 C   s   | j stƒ | _ | j S r   )Ú	_instancerÛ   )Úclsr   r   r   r   –  s   zvmmSystray.get_instancec                   C   s   dt jvrd S trd S dS )NÚWAYLAND_DISPLAYz=No appindicator listener found, which is required on wayland.)ÚosÚenvironÚ_USING_APPINDICATORr   r   r   r   Úsystray_disabled_messageœ  s
   
z#vmmSystray.systray_disabled_messagec                 C   s>   t  | ¡ |  ¡  d | _d | _|  | j | j¡¡ |  	¡  d S r   )
r   rE   Ú_cleanup_on_app_closeÚ_systrayÚ	_mainmenuÚadd_gsettings_handleÚconfigÚon_view_system_tray_changedÚ_show_systray_changed_cbÚ_startupr3   r   r   r   rE   ¥  s   
ÿÿzvmmSystray.__init__c                 C   s   | j o| j  ¡ S r   )rä   r5   r3   r   r   r   r5   ²  rl   zvmmSystray.is_embeddedc                 C   s,   |   ¡  d | _| jr| j ¡  d | _d S d S r   )Ú_hide_systrayrä   rå   Úcleanupr3   r   r   r   r‚   µ  s   

þzvmmSystray._cleanupc                 C   sL   t ƒ | _t ¡ }| d| j¡ | d| j¡ |j ¡ D ]}|  ||¡ qd S )Nz
conn-addedzconn-removed)	r~   rå   r	   r   rJ   Ú_conn_added_cbÚ_conn_removed_cbr   Úvalues)r4   r   r    r   r   r   Ú_init_mainmenuÁ  s   ÿzvmmSystray._init_mainmenuc                 C   sX   | j s%| jjjrtƒ | _ ntrtƒ | _ ntƒ | _ |  ¡  | j  	| j
 ¡ ¡ | j  ¡  d S r   )rä   rç   ÚCLITestOptionsÚfake_systrayrm   rá   r>   rZ   rð   r:   rå   rË   r   r3   r   r   r   Ú_show_systrayÉ  s   


zvmmSystray._show_systrayc                 C   s   | j sd S | j  ¡  d S r   )rä   r7   r3   r   r   r   rë   Õ  s   zvmmSystray._hide_systrayc                 C   s2   | j  ¡ }t d|¡ |r|  ¡  d S |  ¡  d S )NzShowing systray: %s)rç   Úget_view_system_trayr   Údebugró   rë   )r4   Údo_showr   r   r   ré   Ú  s
   
z#vmmSystray._show_systray_changed_cbc                 C   s   |   ¡  d S r   )ré   r3   r   r   r   rê   ã  s   zvmmSystray._startupc                 C   sT   |  d| j¡ |  d| j¡ |  d| j¡ | j |¡ | ¡ D ]}|  ||¡ qd S )Nzvm-addedz
vm-removedústate-changed)rJ   Ú_vm_added_cbÚ_vm_removed_cbÚ_conn_state_changed_cbrå   rÑ   Úlist_vms)r4   r   r    r¢   r   r   r   rí   ì  s   ÿzvmmSystray._conn_added_cbc                 C   ó   | j  |¡ d S r   )rå   rÓ   )r4   r   r    r   r   r   rî   ô  rl   zvmmSystray._conn_removed_cbc                 C   ó   | j  |¡ d S r   )rå   rÔ   )r4   r    r   r   r   rú   ÷  rl   z!vmmSystray._conn_state_changed_cbc                 C   s   |  d| j¡ | j |¡ d S )Nr÷   )rJ   Ú_vm_state_changed_cbrå   r×   ©r4   r    r¢   r   r   r   rø   ú  rÕ   zvmmSystray._vm_added_cbc                 C   rü   r   )rå   rÙ   rÿ   r   r   r   rù   þ  rl   zvmmSystray._vm_removed_cbc                 C   rý   r   )rå   rÚ   )r4   r¢   r   r   r   rþ     rl   zvmmSystray._vm_state_changed_cbN)r;   r<   r=   rY   Úclassmethodr   Ústaticmethodrâ   rE   r5   r‚   rð   ró   rë   ré   rê   rí   rî   rú   rø   rù   rþ   r   r   r   r   rÛ   ‘  s(    

		rÛ   )rß   ÚgiÚgi.repositoryr   r   Úvirtinstr   r   Ú r   Ú	baseclassr   r   r	   Úrequire_versionr
   r   r*   r   r!   r#   r.   rá   rõ   Úobjectr/   r>   rZ   rm   r~   rÛ   r   r   r   r   Ú<module>   sP   ÿÿ
 % B