2018-05-01 12:51:23 +01:00
# Copyright (C) 2018 Red Hat, Inc.
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
2018-09-29 16:04:05 -04:00
from gi . repository import Gdk , Gtk
2018-05-01 12:51:23 +01:00
import virtinst
from . baseclass import vmmGObjectUI
class vmmOSList ( vmmGObjectUI ) :
__gsignals__ = {
" os-selected " : ( vmmGObjectUI . RUN_FIRST , None , [ object ] )
}
def __init__ ( self ) :
vmmGObjectUI . __init__ ( self , " oslist.ui " , " vmm-oslist " )
self . _cleanup_on_app_close ( )
self . _filter_name = None
self . _filter_eol = True
2018-09-29 16:04:05 -04:00
self . _selected_os = None
self . search_entry = self . widget ( " os-name " )
self . search_entry . set_placeholder_text ( _ ( " Type to start searching... " ) )
self . eol_text = self . widget ( " eol-warn " ) . get_text ( )
2018-05-01 12:51:23 +01:00
self . builder . connect_signals ( {
2018-09-29 16:04:05 -04:00
" on_include_eol_toggled " : self . _eol_toggled_cb ,
" on_os_name_activate " : self . _entry_activate_cb ,
" on_os_name_key_press_event " : self . _key_press_cb ,
" on_os_name_search_changed " : self . _search_changed_cb ,
" on_os_name_stop_search " : self . _stop_search_cb ,
" on_os_list_row_activated " : self . _os_selected_cb ,
2018-05-01 12:51:23 +01:00
} )
self . _init_state ( )
2018-09-29 16:04:05 -04:00
def _cleanup ( self ) :
pass
###########
# UI init #
###########
2018-05-01 12:51:23 +01:00
2018-09-29 16:04:05 -04:00
def _init_state ( self ) :
2018-05-01 12:51:23 +01:00
os_list = self . widget ( " os-list " )
# (os object, label)
os_list_model = Gtk . ListStore ( object , str )
all_os = virtinst . OSDB . list_os ( )
for os in all_os :
os_list_model . append ( [ os , " %s ( %s ) " % ( os . label , os . name ) ] )
2018-09-29 16:04:05 -04:00
model_filter = Gtk . TreeModelFilter ( child_model = os_list_model )
model_filter . set_visible_func ( self . _filter_os_cb )
2018-05-01 12:51:23 +01:00
2018-09-29 16:04:05 -04:00
os_list . set_model ( model_filter )
2018-05-01 12:51:23 +01:00
nameCol = Gtk . TreeViewColumn ( _ ( " Name " ) )
nameCol . set_spacing ( 6 )
text = Gtk . CellRendererText ( )
nameCol . pack_start ( text , True )
nameCol . add_attribute ( text , ' text ' , 1 )
os_list . append_column ( nameCol )
2018-09-29 16:04:05 -04:00
###################
# Private helpers #
###################
def _set_default_selection ( self ) :
os_list = self . widget ( " os-list " )
sel = os_list . get_selection ( )
2019-04-13 17:03:16 -04:00
if not self . is_visible ( ) :
2018-09-29 16:04:05 -04:00
return
if not len ( os_list . get_model ( ) ) :
return
sel . select_iter ( os_list . get_model ( ) [ 0 ] . iter )
def _refilter ( self ) :
os_list = self . widget ( " os-list " )
sel = os_list . get_selection ( )
sel . unselect_all ( )
os_list . get_model ( ) . refilter ( )
self . _set_default_selection ( )
def _filter_by_name ( self , partial_name ) :
self . _filter_name = partial_name . lower ( )
self . _refilter ( )
def _clear_filter ( self ) :
self . _filter_by_name ( " " )
self . widget ( " os-scroll " ) . get_vadjustment ( ) . set_value ( 0 )
def _sync_os_selection ( self ) :
model , titer = self . widget ( " os-list " ) . get_selection ( ) . get_selected ( )
self . _selected_os = None
if titer :
self . _selected_os = model [ titer ] [ 0 ]
self . search_entry . set_text ( self . _selected_os . label )
self . emit ( " os-selected " , self . _selected_os )
def _show_popover ( self ) :
2018-10-02 10:00:19 -04:00
# Match width to the search_entry width. Height is based on
# whatever we can fit into the hardcoded create wizard sizes
r = self . search_entry . get_allocation ( )
self . topwin . set_size_request ( r . width , 350 )
2018-09-29 16:04:05 -04:00
self . topwin . set_relative_to ( self . search_entry )
self . topwin . popup ( )
self . _set_default_selection ( )
################
# UI Callbacks #
################
def _entry_activate_cb ( self , src ) :
os_list = self . widget ( " os-list " )
2020-01-26 10:26:40 -05:00
if not os_list . is_visible ( ) :
return
2018-09-29 16:04:05 -04:00
sel = os_list . get_selection ( )
model , rows = sel . get_selected_rows ( )
if rows :
self . select_os ( model [ rows [ 0 ] ] [ 0 ] )
def _key_press_cb ( self , src , event ) :
if Gdk . keyval_name ( event . keyval ) != " Down " :
return
self . _show_popover ( )
self . widget ( " os-list " ) . grab_focus ( )
def _eol_toggled_cb ( self , src ) :
2018-05-01 12:51:23 +01:00
self . _filter_eol = not src . get_active ( )
self . _refilter ( )
2018-09-29 16:04:05 -04:00
def _search_changed_cb ( self , src ) :
"""
Called text in search_entry is changed
"""
searchname = src . get_text ( ) . strip ( )
selected_label = None
if self . _selected_os :
selected_label = self . _selected_os . label
if ( not src . get_sensitive ( ) or
2018-10-02 10:22:37 -04:00
not searchname or
2018-09-29 16:04:05 -04:00
selected_label == searchname ) :
self . topwin . popdown ( )
self . _clear_filter ( )
return
self . _filter_by_name ( searchname )
self . _show_popover ( )
def _stop_search_cb ( self , src ) :
"""
Called when the search window is closed , like with Escape key
"""
if self . _selected_os :
self . search_entry . set_text ( self . _selected_os . label )
2018-05-01 12:51:23 +01:00
else :
2018-09-29 16:04:05 -04:00
self . search_entry . set_text ( " " )
def _os_selected_cb ( self , src , path , column ) :
self . _sync_os_selection ( )
def _filter_os_cb ( self , model , titer , ignore1 ) :
osobj = model . get ( titer , 0 ) [ 0 ]
if osobj . is_generic ( ) :
return True
2018-05-01 12:51:23 +01:00
if self . _filter_eol :
2018-09-29 16:04:05 -04:00
if osobj . eol :
2018-05-01 12:51:23 +01:00
return False
if self . _filter_name is not None and self . _filter_name != " " :
2018-09-29 16:04:05 -04:00
label = osobj . label . lower ( )
name = osobj . name . lower ( )
2018-05-01 12:51:23 +01:00
if ( label . find ( self . _filter_name ) == - 1 and
name . find ( self . _filter_name ) == - 1 ) :
return False
return True
2018-09-29 16:04:05 -04:00
###############
# Public APIs #
###############
def reset_state ( self ) :
self . _selected_os = None
self . search_entry . set_text ( " " )
self . _clear_filter ( )
self . _sync_os_selection ( )
def select_os ( self , vmosobj ) :
self . _clear_filter ( )
2018-05-01 12:51:23 +01:00
os_list = self . widget ( " os-list " )
2018-09-29 16:04:05 -04:00
if vmosobj . eol and not self . widget ( " include-eol " ) . get_active ( ) :
self . widget ( " include-eol " ) . set_active ( True )
2018-05-01 12:51:23 +01:00
2018-09-29 16:04:05 -04:00
for row in os_list . get_model ( ) :
osobj = row [ 0 ]
if osobj . name != vmosobj . name :
continue
2018-05-01 12:51:23 +01:00
2018-09-29 16:04:05 -04:00
os_list . get_selection ( ) . select_iter ( row . iter )
self . _sync_os_selection ( )
return
2018-05-01 12:51:23 +01:00
2018-09-29 16:04:05 -04:00
def get_selected_os ( self ) :
return self . _selected_os
2018-05-01 12:51:23 +01:00
2018-09-29 16:04:05 -04:00
def set_sensitive ( self , sensitive ) :
if sensitive == self . search_entry . get_sensitive ( ) :
return
if not sensitive :
self . search_entry . set_sensitive ( False )
self . reset_state ( )
else :
if self . _selected_os :
self . select_os ( self . _selected_os )
else :
self . reset_state ( )
self . search_entry . set_sensitive ( True )