2010-12-08 17:26:19 -05:00
#
# Copyright (C) 2010 Red Hat, Inc.
# Copyright (C) 2010 Cole Robinson <crobinso@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
import os
2011-04-11 11:00:57 -04:00
import sys
import logging
2010-12-08 17:26:19 -05:00
2011-04-18 13:19:39 -04:00
import virtManager
2011-05-31 16:10:34 -04:00
import virtManager . guidiff
2011-04-28 17:13:05 -04:00
2013-04-11 17:16:33 -04:00
# pylint: disable=E0611
2013-02-16 14:03:30 -05:00
from gi . repository import GLib
2012-05-14 14:24:56 +01:00
from gi . repository import GObject
if virtManager . guidiff . is_gui ( ) :
from gi . repository import Gtk
from gi . repository import Gdk
2013-04-11 17:16:33 -04:00
# pylint: enable=E0611
2010-12-08 17:26:19 -05:00
2011-04-18 12:39:53 -04:00
2013-02-16 14:03:30 -05:00
class vmmGObject ( GObject . GObject ) :
2011-04-28 17:13:05 -04:00
_leak_check = True
2010-12-08 17:26:19 -05:00
def __init__ ( self ) :
2012-05-14 14:24:56 +01:00
GObject . GObject . __init__ ( self )
self . config = virtManager . guidiff . get_running_config ( )
2010-12-08 17:26:19 -05:00
2011-04-11 11:00:57 -04:00
self . _gobject_handles = [ ]
self . _gobject_timeouts = [ ]
self . _gconf_handles = [ ]
2011-07-22 18:07:57 -04:00
self . _signal_id_map = { }
self . _next_signal_id = 1
2011-04-13 09:27:02 -04:00
self . object_key = str ( self )
2011-04-15 18:38:29 -04:00
# Config might not be available if we error early in startup
2011-04-28 17:03:22 -04:00
if self . config and self . _leak_check :
2011-04-15 18:38:29 -04:00
self . config . add_object ( self . object_key )
2011-04-11 12:54:47 -04:00
2011-04-11 11:00:57 -04:00
def cleanup ( self ) :
# Do any cleanup required to drop reference counts so object is
# actually reaped by python. Usually means unregistering callbacks
try :
for h in self . _gconf_handles [ : ] :
self . remove_gconf_handle ( h )
for h in self . _gobject_handles [ : ] :
2011-04-11 13:06:59 -04:00
self . disconnect ( h )
2011-04-11 11:00:57 -04:00
for h in self . _gobject_timeouts [ : ] :
self . remove_gobject_timeout ( h )
2011-07-23 21:16:54 -04:00
self . _cleanup ( )
2011-04-11 11:00:57 -04:00
except :
2012-01-16 22:04:40 -05:00
logging . exception ( " Error cleaning up %s " , self )
2011-04-11 11:00:57 -04:00
2011-07-23 21:16:54 -04:00
def _cleanup ( self ) :
raise NotImplementedError ( " _cleanup must be implemented in subclass " )
2011-04-11 13:06:59 -04:00
def connect ( self , name , callback , * args ) :
2012-05-14 14:24:56 +01:00
ret = GObject . GObject . connect ( self , name , callback , * args )
self . _gobject_handles . append ( ret )
return ret
2011-07-22 18:07:57 -04:00
2011-04-11 13:06:59 -04:00
def disconnect ( self , handle ) :
2012-05-14 14:24:56 +01:00
ret = GObject . GObject . disconnect ( self , handle )
self . _gobject_handles . remove ( handle )
return ret
2011-04-11 13:06:59 -04:00
2011-04-11 11:00:57 -04:00
def add_gconf_handle ( self , handle ) :
self . _gconf_handles . append ( handle )
def remove_gconf_handle ( self , handle ) :
self . config . remove_notifier ( handle )
self . _gconf_handles . remove ( handle )
def add_gobject_timeout ( self , handle ) :
self . _gobject_timeouts . append ( handle )
def remove_gobject_timeout ( self , handle ) :
2013-02-16 14:03:30 -05:00
GLib . source_remove ( handle )
2011-04-11 11:00:57 -04:00
self . _gobject_timeouts . remove ( handle )
2013-01-11 16:15:06 -05:00
def _logtrace ( self , msg = " " ) :
2011-04-13 09:27:02 -04:00
import traceback
2013-01-11 16:15:06 -05:00
if msg :
msg + = " "
logging . debug ( " %s ( %s %s ) \n : %s " ,
2012-01-16 22:04:40 -05:00
msg , self . object_key , self . refcount ( ) ,
" " . join ( traceback . format_stack ( ) ) )
2011-04-13 09:27:02 -04:00
2011-04-11 11:00:57 -04:00
def refcount ( self ) :
# Function generates 2 temporary refs, so adjust total accordingly
return ( sys . getrefcount ( self ) - 2 )
2011-06-01 16:09:48 -04:00
def get_hal_helper ( self , init = True ) :
2010-12-09 14:06:00 -05:00
from virtManager import halhelper
2011-06-01 16:09:48 -04:00
return halhelper . get_hal_helper ( init = init )
2010-12-09 14:06:00 -05:00
2011-04-17 18:27:41 -04:00
def connect_once ( self , signal , func , * args ) :
id_list = [ ]
def wrap_func ( * wrapargs ) :
if id_list :
self . disconnect ( id_list [ 0 ] )
return func ( * wrapargs )
conn_id = self . connect ( signal , wrap_func , * args )
id_list . append ( conn_id )
return conn_id
def connect_opt_out ( self , signal , func , * args ) :
id_list = [ ]
def wrap_func ( * wrapargs ) :
ret = func ( * wrapargs )
if ret and id_list :
self . disconnect ( id_list [ 0 ] )
conn_id = self . connect ( signal , wrap_func , * args )
id_list . append ( conn_id )
return conn_id
2011-04-18 11:12:36 -04:00
def idle_emit ( self , signal , * args ) :
"""
2013-02-16 14:03:30 -05:00
Safe wrapper for using ' self.emit ' with GLib . idle_add
2011-04-18 11:12:36 -04:00
"""
def emitwrap ( _s , * _a ) :
self . emit ( _s , * _a )
return False
2012-02-10 14:07:51 -05:00
self . idle_add ( emitwrap , signal , * args )
2011-04-18 11:12:36 -04:00
2012-02-10 14:07:51 -05:00
def idle_add ( self , func , * args ) :
2011-04-18 11:12:36 -04:00
"""
Make sure idle functions are run thread safe
"""
2013-02-16 14:03:30 -05:00
return GLib . idle_add ( func , * args )
2011-04-18 11:12:36 -04:00
2012-02-10 14:07:51 -05:00
def timeout_add ( self , timeout , func , * args ) :
2011-04-18 11:12:36 -04:00
"""
Make sure timeout functions are run thread safe
"""
2013-02-16 14:03:30 -05:00
return GLib . timeout_add ( timeout , func , * args )
2011-04-18 11:12:36 -04:00
2011-07-22 18:07:57 -04:00
def emit ( self , signal_name , * args ) :
2012-05-14 14:24:56 +01:00
return GObject . GObject . emit ( self , signal_name , * args )
2011-04-28 17:13:05 -04:00
2011-04-11 12:54:47 -04:00
def __del__ ( self ) :
2012-05-14 14:24:56 +01:00
# XXX
2013-04-13 14:34:52 -04:00
# GObject.GObject.__del__(self)
2011-04-11 12:54:47 -04:00
try :
2011-07-22 19:12:31 -04:00
if self . config and self . _leak_check :
2011-04-15 18:38:29 -04:00
self . config . remove_object ( self . object_key )
2011-04-11 12:54:47 -04:00
except :
2012-01-16 22:04:40 -05:00
logging . exception ( " Error removing %s " , self . object_key )
2011-04-11 11:00:57 -04:00
2013-04-13 14:34:52 -04:00
2010-12-08 17:26:19 -05:00
class vmmGObjectUI ( vmmGObject ) :
def __init__ ( self , filename , windowname ) :
vmmGObject . __init__ ( self )
self . windowname = windowname
2013-02-16 13:31:46 -05:00
self . builder = None
2010-12-08 17:26:19 -05:00
self . topwin = None
2012-02-01 17:26:46 -05:00
self . uifile = None
2011-04-11 13:06:59 -04:00
self . err = None
2010-12-08 17:26:19 -05:00
if filename :
2012-02-01 17:26:46 -05:00
self . uifile = os . path . join ( self . config . get_ui_dir ( ) , filename )
2013-02-16 13:31:46 -05:00
self . builder = Gtk . Builder ( )
self . builder . set_translation_domain ( " virt-manager " )
self . builder . add_from_string (
2012-05-14 14:24:56 +01:00
file ( self . uifile ) . read ( ) )
2012-02-01 17:26:46 -05:00
2011-07-14 13:13:13 -04:00
self . topwin = self . widget ( self . windowname )
2010-12-08 17:26:19 -05:00
self . topwin . hide ( )
2011-04-11 16:26:41 -04:00
self . err = virtManager . error . vmmErrorDialog ( self . topwin )
2011-04-11 13:06:59 -04:00
2011-07-14 13:13:13 -04:00
def widget ( self , name ) :
2013-02-16 13:31:46 -05:00
return self . builder . get_object ( name )
2011-07-14 13:13:13 -04:00
2011-04-11 13:06:59 -04:00
def cleanup ( self ) :
2012-07-08 20:56:36 -04:00
self . close ( )
2011-04-11 13:06:59 -04:00
vmmGObject . cleanup ( self )
2013-02-16 13:31:46 -05:00
self . builder = None
2011-04-11 18:35:21 -04:00
self . topwin . destroy ( )
2011-04-11 13:06:59 -04:00
self . topwin = None
2012-02-01 17:26:46 -05:00
self . uifile = None
2011-04-11 13:06:59 -04:00
self . err = None
2011-04-18 11:25:28 -04:00
2011-07-23 21:16:54 -04:00
def _cleanup ( self ) :
raise NotImplementedError ( " _cleanup must be implemented in subclass " )
2011-04-28 14:38:16 -04:00
def close ( self , ignore1 = None , ignore2 = None ) :
pass
2011-04-18 11:25:28 -04:00
def bind_escape_key_close ( self ) :
def close_on_escape ( src_ignore , event ) :
2012-05-14 14:24:56 +01:00
if Gdk . keyval_name ( event . keyval ) == " Escape " :
2011-04-18 11:25:28 -04:00
self . close ( )
self . topwin . connect ( " key-press-event " , close_on_escape )