2007-03-22 20:59:10 -04:00
# Error dialog with extensible "details" button.
#
# Copyright (C) 2007 Red Hat, Inc.
#
# 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
2007-11-20 11:12:20 -05:00
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2007-03-22 20:59:10 -04:00
2013-04-11 17:16:33 -04:00
# pylint: disable=E0611
2012-05-14 14:24:56 +01:00
from gi . repository import Gtk
2013-04-11 17:16:33 -04:00
# pylint: enable=E0611
2007-03-22 20:59:10 -04:00
2008-09-06 13:24:47 -04:00
import logging
2011-04-06 11:22:03 -04:00
import traceback
2008-09-06 13:24:47 -04:00
2011-04-11 16:26:41 -04:00
from virtManager . baseclass import vmmGObject
2010-01-14 10:09:52 -05:00
2013-04-13 14:34:52 -04:00
2010-12-01 17:48:07 -05:00
def _launch_dialog ( dialog , primary_text , secondary_text , title ,
2013-09-06 20:16:37 -04:00
widget = None , modal = True ) :
2012-05-14 14:24:56 +01:00
dialog . set_property ( " text " , primary_text )
2010-12-01 17:48:07 -05:00
dialog . format_secondary_text ( secondary_text or None )
dialog . set_title ( title )
2013-07-01 14:33:06 -04:00
if widget :
dialog . get_content_area ( ) . add ( widget )
2010-12-01 17:48:07 -05:00
res = False
2013-09-06 20:16:37 -04:00
if modal :
2010-12-01 17:48:07 -05:00
res = dialog . run ( )
2012-05-14 14:24:56 +01:00
res = bool ( res in [ Gtk . ResponseType . YES , Gtk . ResponseType . OK ] )
2010-12-01 17:48:07 -05:00
dialog . destroy ( )
else :
def response_destroy ( src , ignore ) :
src . destroy ( )
dialog . connect ( " response " , response_destroy )
dialog . show ( )
2010-01-19 14:09:43 -05:00
2010-12-01 17:48:07 -05:00
return res
2009-01-21 16:28:54 -05:00
2013-04-12 08:26:21 -04:00
2011-04-11 16:26:41 -04:00
class vmmErrorDialog ( vmmGObject ) :
2010-12-10 11:47:07 -05:00
def __init__ ( self , parent = None ) :
2011-04-11 16:26:41 -04:00
vmmGObject . __init__ ( self )
2010-12-01 17:48:07 -05:00
self . _parent = parent
2010-12-07 15:27:10 -05:00
self . _simple = None
2008-03-14 13:18:44 -04:00
2011-07-23 21:16:54 -04:00
def _cleanup ( self ) :
pass
2009-11-20 13:11:33 -05:00
def set_parent ( self , parent ) :
2010-12-01 17:48:07 -05:00
self . _parent = parent
def get_parent ( self ) :
return self . _parent
2011-04-06 11:22:03 -04:00
def show_err ( self , summary , details = None , title = " " ,
2013-09-06 20:16:37 -04:00
modal = False , debug = True ,
2012-05-14 14:24:56 +01:00
dialog_type = Gtk . MessageType . ERROR ,
buttons = Gtk . ButtonsType . CLOSE ,
2010-12-01 17:48:07 -05:00
text2 = None ) :
2011-04-06 11:22:03 -04:00
if details is None :
2013-06-30 12:42:32 -04:00
details = summary
tb = " " . join ( traceback . format_exc ( ) ) . strip ( )
if tb != " None " :
details + = " \n \n " + tb
2011-04-06 11:52:26 -04:00
# Make sure we have consistent details for error dialogs
2013-06-13 09:23:21 -04:00
if ( dialog_type == Gtk . MessageType . ERROR and not summary in details ) :
2011-04-06 11:52:26 -04:00
details = summary + " \n \n " + details
2011-04-06 11:22:03 -04:00
2011-04-09 21:42:41 -04:00
if debug :
2013-06-13 09:23:21 -04:00
logging . debug ( " error dialog message: \n summary= %s \n details= %s " ,
summary , details )
2011-04-09 21:42:41 -04:00
2010-12-01 17:48:07 -05:00
dialog = _errorDialog ( parent = self . get_parent ( ) ,
2012-05-14 14:24:56 +01:00
flags = 0 ,
message_type = dialog_type ,
buttons = buttons )
2010-12-01 17:48:07 -05:00
return dialog . show_dialog ( primary_text = summary ,
secondary_text = text2 ,
details = details , title = title ,
2013-09-06 20:16:37 -04:00
modal = modal )
2008-03-14 13:18:44 -04:00
2010-11-30 15:37:54 -05:00
###################################
# Simple one shot message dialogs #
###################################
def _simple_dialog ( self , dialog_type , buttons , text1 ,
2013-09-06 20:16:37 -04:00
text2 , title , widget = None , modal = True ) :
2010-11-30 15:37:54 -05:00
2012-05-14 14:24:56 +01:00
dialog = Gtk . MessageDialog ( self . get_parent ( ) ,
flags = Gtk . DialogFlags . DESTROY_WITH_PARENT ,
message_type = dialog_type ,
buttons = buttons )
2010-12-07 15:27:10 -05:00
if self . _simple :
self . _simple . destroy ( )
self . _simple = dialog
2010-11-30 15:37:54 -05:00
2010-12-07 15:27:10 -05:00
return _launch_dialog ( self . _simple ,
2010-12-01 17:48:07 -05:00
text1 , text2 or " " , title or " " ,
2013-07-01 14:33:06 -04:00
widget = widget ,
2013-09-06 20:16:37 -04:00
modal = modal )
2008-03-14 13:18:44 -04:00
2013-09-06 20:16:37 -04:00
def val_err ( self , text1 , text2 = None , title = _ ( " Input Error " ) , modal = True ) :
2011-08-30 14:50:50 -04:00
logtext = " Validation Error: %s " % text1
if text2 :
logtext + = " %s " % text2
if isinstance ( text1 , Exception ) or isinstance ( text2 , Exception ) :
logging . exception ( logtext )
else :
self . _logtrace ( logtext )
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . ERROR
buttons = Gtk . ButtonsType . OK
2012-01-17 10:29:16 -05:00
self . _simple_dialog ( dtype , buttons ,
str ( text1 ) ,
text2 and str ( text2 ) or " " ,
2013-09-06 20:16:37 -04:00
str ( title ) , None , modal )
2010-11-30 15:37:54 -05:00
return False
2009-07-02 12:45:48 -04:00
2013-09-06 20:16:37 -04:00
def show_info ( self , text1 , text2 = None , title = " " , widget = None , modal = True ) :
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . INFO
buttons = Gtk . ButtonsType . OK
2013-09-06 20:16:37 -04:00
self . _simple_dialog ( dtype , buttons , text1 , text2 , title , widget , modal )
2010-11-30 15:37:54 -05:00
return False
2009-02-15 21:20:14 -05:00
2010-11-30 15:37:54 -05:00
def yes_no ( self , text1 , text2 = None , title = None ) :
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . WARNING
buttons = Gtk . ButtonsType . YES_NO
2010-11-30 15:37:54 -05:00
return self . _simple_dialog ( dtype , buttons , text1 , text2 , title )
2008-03-14 13:18:44 -04:00
2010-11-30 15:37:54 -05:00
def ok_cancel ( self , text1 , text2 = None , title = None ) :
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . WARNING
buttons = Gtk . ButtonsType . OK_CANCEL
2010-11-30 15:37:54 -05:00
return self . _simple_dialog ( dtype , buttons , text1 , text2 , title )
2009-02-15 21:20:14 -05:00
2010-11-30 15:37:54 -05:00
def ok ( self , text1 , text2 = None , title = None ) :
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . WARNING
buttons = Gtk . ButtonsType . OK
2010-11-30 15:37:54 -05:00
return self . _simple_dialog ( dtype , buttons , text1 , text2 , title )
2009-02-15 21:20:14 -05:00
2010-11-30 15:37:54 -05:00
##########################################
# One shot dialog with a checkbox prompt #
##########################################
2010-03-03 16:58:50 -05:00
2009-11-18 16:11:17 -05:00
def warn_chkbox ( self , text1 , text2 = None , chktext = None , buttons = None ) :
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . WARNING
buttons = buttons or Gtk . ButtonsType . OK_CANCEL
2010-12-01 17:48:07 -05:00
chkbox = _errorDialog ( parent = self . get_parent ( ) ,
2012-05-14 14:24:56 +01:00
flags = 0 ,
message_type = dtype ,
2010-12-01 17:48:07 -05:00
buttons = buttons )
return chkbox . show_dialog ( primary_text = text1 ,
secondary_text = text2 ,
chktext = chktext )
2009-09-23 16:42:56 -04:00
2009-11-18 16:11:17 -05:00
def err_chkbox ( self , text1 , text2 = None , chktext = None , buttons = None ) :
2012-05-14 14:24:56 +01:00
dtype = Gtk . MessageType . ERROR
buttons = buttons or Gtk . ButtonsType . OK
2010-12-01 17:48:07 -05:00
chkbox = _errorDialog ( parent = self . get_parent ( ) ,
2012-05-14 14:24:56 +01:00
flags = 0 ,
message_type = dtype ,
2010-12-01 17:48:07 -05:00
buttons = buttons )
return chkbox . show_dialog ( primary_text = text1 ,
secondary_text = text2 ,
chktext = chktext )
2012-05-14 14:24:56 +01:00
class _errorDialog ( Gtk . MessageDialog ) :
2010-12-01 17:48:07 -05:00
"""
Custom error dialog with optional check boxes or details drop down
"""
2013-04-12 08:26:21 -04:00
# pylint: disable=E1101
# pylint can't detect functions we inheirit from Gtk, ex:
# Instance of '_errorDialog' has no 'set_title' member
2010-12-10 11:47:07 -05:00
def __init__ ( self , * args , * * kwargs ) :
2012-05-14 14:24:56 +01:00
Gtk . MessageDialog . __init__ ( self , * args , * * kwargs )
2010-12-01 17:48:07 -05:00
self . set_title ( " " )
2009-09-23 16:42:56 -04:00
2010-12-01 17:48:07 -05:00
self . chk_vbox = None
self . chk_align = None
self . init_chkbox ( )
2009-09-23 16:42:56 -04:00
2010-12-01 17:48:07 -05:00
self . buffer = None
self . buf_expander = None
self . init_details ( )
2009-09-23 16:42:56 -04:00
2010-12-01 17:48:07 -05:00
def init_chkbox ( self ) :
# Init check items
2012-05-14 14:24:56 +01:00
self . chk_vbox = Gtk . VBox ( False , False )
2009-09-23 16:42:56 -04:00
self . chk_vbox . set_spacing ( 0 )
2012-05-14 14:24:56 +01:00
self . chk_align = Gtk . Alignment ( )
2013-09-27 13:43:43 -04:00
self . chk_align . set_padding ( 0 , 0 , 0 , 0 )
2009-09-23 16:42:56 -04:00
self . chk_align . add ( self . chk_vbox )
self . chk_align . show_all ( )
2012-05-14 14:24:56 +01:00
self . vbox . pack_start ( self . chk_align , False , False , 0 )
2009-09-23 16:42:56 -04:00
2010-12-01 17:48:07 -05:00
def init_details ( self ) :
# Init details buffer
2012-05-14 14:24:56 +01:00
self . buffer = Gtk . TextBuffer ( )
self . buf_expander = Gtk . Expander . new ( _ ( " Details " ) )
sw = Gtk . ScrolledWindow ( )
sw . set_shadow_type ( Gtk . ShadowType . IN )
2010-12-10 11:47:07 -05:00
sw . set_size_request ( 400 , 240 )
2012-05-14 14:24:56 +01:00
sw . set_policy ( Gtk . PolicyType . AUTOMATIC , Gtk . PolicyType . AUTOMATIC )
details = Gtk . TextView . new_with_buffer ( self . buffer )
2010-12-10 11:47:07 -05:00
details . set_editable ( False )
details . set_overwrite ( False )
details . set_cursor_visible ( False )
2012-05-14 14:24:56 +01:00
details . set_wrap_mode ( Gtk . WrapMode . WORD )
2013-01-12 16:13:53 -05:00
details . set_border_width ( 6 )
2010-12-01 17:48:07 -05:00
sw . add ( details )
self . buf_expander . add ( sw )
2012-05-14 14:24:56 +01:00
self . vbox . pack_start ( self . buf_expander , False , False , 0 )
2010-12-01 17:48:07 -05:00
self . buf_expander . show_all ( )
def show_dialog ( self , primary_text , secondary_text = " " ,
title = " " , details = " " , chktext = " " ,
2013-09-06 20:16:37 -04:00
modal = True ) :
2009-09-23 16:42:56 -04:00
chkbox = None
res = None
2010-12-01 17:48:07 -05:00
# Hide starting widgets
2009-09-23 16:42:56 -04:00
self . hide ( )
2010-12-01 17:48:07 -05:00
self . buf_expander . hide ( )
2009-09-23 16:42:56 -04:00
for c in self . chk_vbox . get_children ( ) :
self . chk_vbox . remove ( c )
2010-12-01 17:48:07 -05:00
if details :
self . buffer . set_text ( details )
2010-12-08 13:05:38 -05:00
title = title or " "
2010-12-01 17:48:07 -05:00
self . buf_expander . show ( )
2009-09-23 16:42:56 -04:00
if chktext :
2012-05-14 14:24:56 +01:00
chkbox = Gtk . CheckButton ( chktext )
2009-09-23 16:42:56 -04:00
self . chk_vbox . add ( chkbox )
chkbox . show ( )
2010-12-01 17:48:07 -05:00
res = _launch_dialog ( self ,
primary_text , secondary_text or " " ,
title ,
2013-09-06 20:16:37 -04:00
modal = modal )
2010-12-01 17:48:07 -05:00
2009-09-23 16:42:56 -04:00
if chktext :
res = [ res , chkbox . get_active ( ) ]
return res