2010-12-09 01:26:19 +03: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.
#
2013-06-18 16:46:24 +04:00
import logging
2010-12-09 01:26:19 +03:00
import os
2011-04-11 19:00:57 +04:00
import sys
2013-06-18 16:46:24 +04:00
import traceback
2010-12-09 01:26:19 +03:00
2013-08-09 17:23:01 +04:00
from virtManager import config
2011-04-29 01:13:05 +04:00
2013-04-12 01:16:33 +04:00
# pylint: disable=E0611
2013-04-19 00:03:43 +04:00
from gi . repository import Gdk
2013-02-16 23:03:30 +04:00
from gi . repository import GLib
2012-05-14 17:24:56 +04:00
from gi . repository import GObject
2013-04-19 00:03:43 +04:00
from gi . repository import Gtk
2013-04-12 01:16:33 +04:00
# pylint: enable=E0611
2010-12-09 01:26:19 +03:00
2011-04-18 20:39:53 +04:00
2013-02-16 23:03:30 +04:00
class vmmGObject ( GObject . GObject ) :
2011-04-29 01:13:05 +04:00
_leak_check = True
2010-12-09 01:26:19 +03:00
def __init__ ( self ) :
2012-05-14 17:24:56 +04:00
GObject . GObject . __init__ ( self )
2013-08-09 17:23:01 +04:00
self . config = config . running_config
2010-12-09 01:26:19 +03:00
2011-04-11 19:00:57 +04:00
self . _gobject_handles = [ ]
self . _gobject_timeouts = [ ]
self . _gconf_handles = [ ]
2011-07-23 02:07:57 +04:00
self . _signal_id_map = { }
self . _next_signal_id = 1
2011-04-13 17:27:02 +04:00
self . object_key = str ( self )
2011-04-16 02:38:29 +04:00
# Config might not be available if we error early in startup
2011-04-29 01:03:22 +04:00
if self . config and self . _leak_check :
2011-04-16 02:38:29 +04:00
self . config . add_object ( self . object_key )
2011-04-11 20:54:47 +04:00
2011-04-11 19: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 21:06:59 +04:00
self . disconnect ( h )
2011-04-11 19:00:57 +04:00
for h in self . _gobject_timeouts [ : ] :
self . remove_gobject_timeout ( h )
2011-07-24 05:16:54 +04:00
self . _cleanup ( )
2011-04-11 19:00:57 +04:00
except :
2012-01-17 07:04:40 +04:00
logging . exception ( " Error cleaning up %s " , self )
2011-04-11 19:00:57 +04:00
2011-07-24 05:16:54 +04:00
def _cleanup ( self ) :
raise NotImplementedError ( " _cleanup must be implemented in subclass " )
2011-04-11 21:06:59 +04:00
def connect ( self , name , callback , * args ) :
2012-05-14 17:24:56 +04:00
ret = GObject . GObject . connect ( self , name , callback , * args )
self . _gobject_handles . append ( ret )
return ret
2011-07-23 02:07:57 +04:00
2011-04-11 21:06:59 +04:00
def disconnect ( self , handle ) :
2012-05-14 17:24:56 +04:00
ret = GObject . GObject . disconnect ( self , handle )
self . _gobject_handles . remove ( handle )
return ret
2011-04-11 21:06:59 +04:00
2011-04-11 19: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 23:03:30 +04:00
GLib . source_remove ( handle )
2011-04-11 19:00:57 +04:00
self . _gobject_timeouts . remove ( handle )
2013-01-12 01:15:06 +04:00
def _logtrace ( self , msg = " " ) :
if msg :
msg + = " "
logging . debug ( " %s ( %s %s ) \n : %s " ,
2013-04-25 20:07:57 +04:00
msg , self . object_key , self . _refcount ( ) ,
2012-01-17 07:04:40 +04:00
" " . join ( traceback . format_stack ( ) ) )
2011-04-13 17:27:02 +04:00
2013-04-25 20:07:57 +04:00
def _refcount ( self ) :
2011-04-11 19:00:57 +04:00
# Function generates 2 temporary refs, so adjust total accordingly
return ( sys . getrefcount ( self ) - 2 )
2011-04-18 02: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 19:12:36 +04:00
def idle_emit ( self , signal , * args ) :
"""
2013-02-16 23:03:30 +04:00
Safe wrapper for using ' self.emit ' with GLib . idle_add
2011-04-18 19:12:36 +04:00
"""
def emitwrap ( _s , * _a ) :
self . emit ( _s , * _a )
return False
2012-02-10 23:07:51 +04:00
self . idle_add ( emitwrap , signal , * args )
2011-04-18 19:12:36 +04:00
2013-07-13 06:10:16 +04:00
def idle_add ( self , func , * args , * * kwargs ) :
2011-04-18 19:12:36 +04:00
"""
Make sure idle functions are run thread safe
"""
2013-06-18 16:46:24 +04:00
def cb ( ) :
try :
2013-07-13 06:10:16 +04:00
return func ( * args , * * kwargs )
2013-06-18 16:46:24 +04:00
except :
print traceback . format_exc ( )
return False
return GLib . idle_add ( cb )
2011-04-18 19:12:36 +04:00
2012-02-10 23:07:51 +04:00
def timeout_add ( self , timeout , func , * args ) :
2011-04-18 19:12:36 +04:00
"""
Make sure timeout functions are run thread safe
"""
2013-06-18 16:46:24 +04:00
def cb ( ) :
try :
return func ( * args )
except :
print traceback . format_exc ( )
return False
ret = GLib . timeout_add ( timeout , cb )
2013-06-15 00:22:33 +04:00
self . add_gobject_timeout ( ret )
2013-06-15 00:32:48 +04:00
return ret
2011-04-18 19:12:36 +04:00
2011-07-23 02:07:57 +04:00
def emit ( self , signal_name , * args ) :
2012-05-14 17:24:56 +04:00
return GObject . GObject . emit ( self , signal_name , * args )
2011-04-29 01:13:05 +04:00
2011-04-11 20:54:47 +04:00
def __del__ ( self ) :
try :
2011-07-23 03:12:31 +04:00
if self . config and self . _leak_check :
2011-04-16 02:38:29 +04:00
self . config . remove_object ( self . object_key )
2011-04-11 20:54:47 +04:00
except :
2012-01-17 07:04:40 +04:00
logging . exception ( " Error removing %s " , self . object_key )
2011-04-11 19:00:57 +04:00
2013-04-13 22:34:52 +04:00
2010-12-09 01:26:19 +03:00
class vmmGObjectUI ( vmmGObject ) :
2013-06-09 03:25:36 +04:00
def __init__ ( self , filename , windowname , builder = None , topwin = None ) :
2010-12-09 01:26:19 +03:00
vmmGObject . __init__ ( self )
if filename :
2013-06-09 03:25:36 +04:00
uifile = os . path . join ( self . config . get_ui_dir ( ) , filename )
2012-02-02 02:26:46 +04:00
2013-02-16 22:31:46 +04:00
self . builder = Gtk . Builder ( )
self . builder . set_translation_domain ( " virt-manager " )
2013-06-09 03:25:36 +04:00
self . builder . add_from_string ( file ( uifile ) . read ( ) )
2012-02-02 02:26:46 +04:00
2013-06-09 03:25:36 +04:00
self . topwin = self . widget ( windowname )
2010-12-09 01:26:19 +03:00
self . topwin . hide ( )
2013-06-09 03:25:36 +04:00
else :
self . builder = builder
self . topwin = topwin
2010-12-09 01:26:19 +03:00
2013-08-09 17:23:01 +04:00
from virtManager import error
self . err = error . vmmErrorDialog ( self . topwin )
2011-04-11 21:06:59 +04:00
2011-07-14 21:13:13 +04:00
def widget ( self , name ) :
2013-02-16 22:31:46 +04:00
return self . builder . get_object ( name )
2011-07-14 21:13:13 +04:00
2011-04-11 21:06:59 +04:00
def cleanup ( self ) :
2012-07-09 04:56:36 +04:00
self . close ( )
2011-04-11 21:06:59 +04:00
vmmGObject . cleanup ( self )
2013-02-16 22:31:46 +04:00
self . builder = None
2011-04-12 02:35:21 +04:00
self . topwin . destroy ( )
2011-04-11 21:06:59 +04:00
self . topwin = None
self . err = None
2011-04-18 19:25:28 +04:00
2011-07-24 05:16:54 +04:00
def _cleanup ( self ) :
raise NotImplementedError ( " _cleanup must be implemented in subclass " )
2011-04-28 22:38:16 +04:00
def close ( self , ignore1 = None , ignore2 = None ) :
pass
2011-04-18 19:25:28 +04:00
def bind_escape_key_close ( self ) :
def close_on_escape ( src_ignore , event ) :
2012-05-14 17:24:56 +04:00
if Gdk . keyval_name ( event . keyval ) == " Escape " :
2011-04-18 19:25:28 +04:00
self . close ( )
self . topwin . connect ( " key-press-event " , close_on_escape )