mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-02 09:47:16 +03:00
details: Track serial pages as console tabs
A bit cleaner conceptually, and shrinks the ever growing details.py
This commit is contained in:
parent
cdc82e62a2
commit
10161a8fdb
@ -692,246 +692,6 @@
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_border">False</property>
|
||||
<signal name="switch-page" handler="on_details_pages_switch_page" after="yes" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="console-pages">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_border">False</property>
|
||||
<signal name="switch-page" handler="on_console_pages_switch_page" after="yes" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkLabel" id="console-unavailable">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>The console is currently unavailable</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="width_chars">40</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label434">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Unavailable</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="console-auth">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">3</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">3</property>
|
||||
<property name="row_spacing">3</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-auth-password">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Password:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">console-auth-password</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="console-auth-password">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="visibility">False</property>
|
||||
<signal name="activate" handler="on_console_auth_password_activate" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="console-auth-remember">
|
||||
<property name="label" translatable="yes">_Save this password in your keyring</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-auth-username">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Username:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">console-auth-username</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="console-auth-username">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="activate" handler="on_console_auth_password_activate" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="console-auth-login">
|
||||
<property name="label" translatable="yes">_Login</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="clicked" handler="on_console_auth_login_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment17">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment18">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment19">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label438">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Auth</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="console-gfx-scroll">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport" id="console-gfx-viewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resize_mode">queue</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label439">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Graphics</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label420">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Console</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
@ -7309,9 +7069,6 @@ I/O:</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label77">
|
||||
@ -7319,6 +7076,249 @@ I/O:</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Details</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="console-pages">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_border">False</property>
|
||||
<signal name="switch-page" handler="on_console_pages_switch_page" after="yes" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkLabel" id="console-unavailable">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>The console is currently unavailable</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="width_chars">40</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label434">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Unavailable</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="console-auth">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">3</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">3</property>
|
||||
<property name="row_spacing">3</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-auth-password">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Password:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">console-auth-password</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="console-auth-password">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="visibility">False</property>
|
||||
<signal name="activate" handler="on_console_auth_password_activate" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="console-auth-remember">
|
||||
<property name="label" translatable="yes">_Save this password in your keyring</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-auth-username">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Username:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">console-auth-username</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="console-auth-username">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="activate" handler="on_console_auth_password_activate" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="console-auth-login">
|
||||
<property name="label" translatable="yes">_Login</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="clicked" handler="on_console_auth_login_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment17">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment18">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment19">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label438">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Auth</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="console-gfx-scroll">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport" id="console-gfx-viewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resize_mode">queue</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label439">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Graphics</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label420">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">Console</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
|
@ -39,11 +39,14 @@ import logging
|
||||
import virtManager.uihelpers as uihelpers
|
||||
from virtManager.autodrawer import AutoDrawer
|
||||
from virtManager.baseclass import vmmGObjectUI, vmmGObject
|
||||
from virtManager.serialcon import vmmSerialConsole
|
||||
from virtManager.details import DETAILS_PAGE_CONSOLE
|
||||
|
||||
# Console pages
|
||||
PAGE_UNAVAILABLE = 0
|
||||
PAGE_AUTHENTICATE = 1
|
||||
PAGE_VIEWER = 2
|
||||
(CONSOLE_PAGE_UNAVAILABLE,
|
||||
CONSOLE_PAGE_AUTHENTICATE,
|
||||
CONSOLE_PAGE_VIEWER,
|
||||
CONSOLE_PAGE_OFFSET) = range(4)
|
||||
|
||||
|
||||
def has_property(obj, setting):
|
||||
@ -713,6 +716,10 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
self.widget("console-gfx-viewport").modify_bg(Gtk.StateType.NORMAL,
|
||||
black)
|
||||
|
||||
self.serial_tabs = []
|
||||
self.last_gfx_page = 0
|
||||
self._init_menus()
|
||||
|
||||
# Signals are added by vmmDetails. Don't use connect_signals here
|
||||
# or it changes will be overwritten
|
||||
|
||||
@ -749,6 +756,11 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
self.fs_toolbar.destroy()
|
||||
self.fs_toolbar = None
|
||||
|
||||
for serial in self.serial_tabs:
|
||||
serial.cleanup()
|
||||
self.serial_tabs = []
|
||||
|
||||
|
||||
##########################
|
||||
# Initialization helpers #
|
||||
##########################
|
||||
@ -803,6 +815,12 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
|
||||
pages.add(self.fs_drawer)
|
||||
|
||||
def _init_menus(self):
|
||||
# Serial list menu
|
||||
smenu = Gtk.Menu()
|
||||
smenu.connect("show", self.populate_serial_menu)
|
||||
self.widget("details-menu-view-serial-list").set_submenu(smenu)
|
||||
|
||||
def change_title(self, ignore1=None):
|
||||
title = self.vm.get_name() + " " + _("Virtual Machine")
|
||||
|
||||
@ -1006,13 +1024,13 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
page = pages.get_current_page()
|
||||
|
||||
if runable:
|
||||
if page != PAGE_UNAVAILABLE:
|
||||
pages.set_current_page(PAGE_UNAVAILABLE)
|
||||
if page != CONSOLE_PAGE_UNAVAILABLE:
|
||||
pages.set_current_page(CONSOLE_PAGE_UNAVAILABLE)
|
||||
|
||||
self.view_vm_status()
|
||||
return
|
||||
|
||||
elif page in [PAGE_UNAVAILABLE, PAGE_VIEWER]:
|
||||
elif page in [CONSOLE_PAGE_UNAVAILABLE, CONSOLE_PAGE_VIEWER]:
|
||||
if self.viewer and self.viewer.is_open():
|
||||
self.activate_viewer_page()
|
||||
else:
|
||||
@ -1022,6 +1040,7 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
|
||||
return
|
||||
|
||||
|
||||
###################
|
||||
# Page Navigation #
|
||||
###################
|
||||
@ -1032,7 +1051,7 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
with care
|
||||
"""
|
||||
self.close_viewer()
|
||||
self.widget("console-pages").set_current_page(PAGE_UNAVAILABLE)
|
||||
self.widget("console-pages").set_current_page(CONSOLE_PAGE_UNAVAILABLE)
|
||||
self.widget("details-menu-vm-screenshot").set_sensitive(False)
|
||||
self.widget("details-menu-usb-redirection").set_sensitive(False)
|
||||
self.widget("console-unavailable").set_label("<b>" + msg + "</b>")
|
||||
@ -1042,58 +1061,53 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
self.widget("details-menu-vm-screenshot").set_sensitive(False)
|
||||
self.widget("details-menu-usb-redirection").set_sensitive(False)
|
||||
|
||||
if withPassword:
|
||||
self.widget("console-auth-password").show()
|
||||
self.widget("label-auth-password").show()
|
||||
else:
|
||||
self.widget("console-auth-password").hide()
|
||||
self.widget("label-auth-password").hide()
|
||||
self.widget("console-auth-password").set_visible(withPassword)
|
||||
self.widget("label-auth-password").set_visible(withPassword)
|
||||
|
||||
if withUsername:
|
||||
self.widget("console-auth-username").show()
|
||||
self.widget("label-auth-username").show()
|
||||
else:
|
||||
self.widget("console-auth-username").hide()
|
||||
self.widget("label-auth-username").hide()
|
||||
self.widget("console-auth-username").set_visible(withUsername)
|
||||
self.widget("label-auth-username").set_visible(withUsername)
|
||||
|
||||
self.widget("console-auth-username").set_text(username)
|
||||
self.widget("console-auth-password").set_text(pw)
|
||||
|
||||
if self.config.has_keyring():
|
||||
self.widget("console-auth-remember").set_sensitive(True)
|
||||
if pw != "" or username != "":
|
||||
self.widget("console-auth-remember").set_active(True)
|
||||
else:
|
||||
self.widget("console-auth-remember").set_active(False)
|
||||
else:
|
||||
self.widget("console-auth-remember").set_sensitive(False)
|
||||
self.widget("console-pages").set_current_page(PAGE_AUTHENTICATE)
|
||||
if withUsername:
|
||||
self.widget("console-auth-username").grab_focus()
|
||||
else:
|
||||
self.widget("console-auth-password").grab_focus()
|
||||
|
||||
self.widget("console-auth-username").set_text(username)
|
||||
self.widget("console-auth-password").set_text(pw)
|
||||
|
||||
self.widget("console-auth-remember").set_sensitive(
|
||||
bool(self.config.has_keyring()))
|
||||
if self.config.has_keyring():
|
||||
self.widget("console-auth-remember").set_active(bool(pw and
|
||||
username))
|
||||
|
||||
self.widget("console-pages").set_current_page(
|
||||
CONSOLE_PAGE_AUTHENTICATE)
|
||||
|
||||
|
||||
def activate_viewer_page(self):
|
||||
self.widget("console-pages").set_current_page(PAGE_VIEWER)
|
||||
self.widget("console-pages").set_current_page(CONSOLE_PAGE_VIEWER)
|
||||
self.widget("details-menu-vm-screenshot").set_sensitive(True)
|
||||
if self.viewer and self.viewer.display:
|
||||
self.viewer.display.grab_focus()
|
||||
|
||||
if self.viewer.has_usb_redirection() and \
|
||||
self.vm.has_spicevmc_type_redirdev():
|
||||
if (self.viewer.has_usb_redirection() and
|
||||
self.vm.has_spicevmc_type_redirdev()):
|
||||
self.widget("details-menu-usb-redirection").set_sensitive(True)
|
||||
return
|
||||
|
||||
def page_changed(self, ignore1=None, ignore2=None, ignore3=None):
|
||||
pagenum = self.widget("console-pages").get_current_page()
|
||||
if pagenum < CONSOLE_PAGE_OFFSET:
|
||||
self.last_gfx_page = pagenum
|
||||
self.set_allow_fullscreen()
|
||||
|
||||
def set_allow_fullscreen(self):
|
||||
cpage = self.widget("console-pages").get_current_page()
|
||||
dpage = self.widget("details-pages").get_current_page()
|
||||
|
||||
allow_fullscreen = (dpage == 0 and
|
||||
cpage == PAGE_VIEWER and
|
||||
allow_fullscreen = (dpage == DETAILS_PAGE_CONSOLE and
|
||||
cpage == CONSOLE_PAGE_VIEWER and
|
||||
self.viewer_connected)
|
||||
|
||||
self.widget("control-fullscreen").set_sensitive(allow_fullscreen)
|
||||
@ -1358,3 +1372,159 @@ class vmmConsolePages(vmmGObjectUI):
|
||||
viewer_alloc.width = desktop_w
|
||||
viewer_alloc.height = desktop_h
|
||||
self.viewer.display.size_allocate(viewer_alloc)
|
||||
|
||||
|
||||
###########################
|
||||
# Serial console handling #
|
||||
###########################
|
||||
|
||||
def activate_default_console_page(self):
|
||||
if self.vm.get_graphics_devices() or not self.vm.get_serial_devs():
|
||||
return
|
||||
|
||||
# Show serial console
|
||||
devs = self.build_serial_list()
|
||||
for name, ignore, sensitive, ignore, cb, serialidx in devs:
|
||||
if not sensitive or not cb:
|
||||
continue
|
||||
|
||||
self._show_serial_tab(name, serialidx)
|
||||
break
|
||||
|
||||
def build_serial_list(self):
|
||||
ret = []
|
||||
|
||||
def add_row(text, err, sensitive, do_radio, cb, serialidx):
|
||||
ret.append([text, err, sensitive, do_radio, cb, serialidx])
|
||||
|
||||
devs = self.vm.get_serial_devs()
|
||||
if len(devs) == 0:
|
||||
add_row(_("No text console available"),
|
||||
None, False, False, None, None)
|
||||
|
||||
def build_desc(dev):
|
||||
if dev.virtual_device_type == "console":
|
||||
return "Text Console %d" % (dev.vmmindex + 1)
|
||||
return "Serial %d" % (dev.vmmindex + 1)
|
||||
|
||||
for dev in devs:
|
||||
desc = build_desc(dev)
|
||||
idx = dev.vmmindex
|
||||
|
||||
err = vmmSerialConsole.can_connect(self.vm, dev)
|
||||
sensitive = not bool(err)
|
||||
|
||||
def cb(src):
|
||||
return self.control_serial_tab(src, desc, idx)
|
||||
|
||||
add_row(desc, err, sensitive, True, cb, idx)
|
||||
|
||||
return ret
|
||||
|
||||
def current_serial_dev(self):
|
||||
current_page = self.widget("console-pages").get_current_page()
|
||||
if not current_page >= CONSOLE_PAGE_OFFSET:
|
||||
return
|
||||
|
||||
serial_idx = current_page - CONSOLE_PAGE_OFFSET
|
||||
if len(self.serial_tabs) < serial_idx:
|
||||
return
|
||||
|
||||
return self.serial_tabs[serial_idx]
|
||||
|
||||
def control_serial_tab(self, src_ignore, name, target_port):
|
||||
self.widget("details-pages").set_current_page(DETAILS_PAGE_CONSOLE)
|
||||
if name == "graphics":
|
||||
self.widget("console-pages").set_current_page(self.last_gfx_page)
|
||||
else:
|
||||
self._show_serial_tab(name, target_port)
|
||||
|
||||
def _show_serial_tab(self, name, target_port):
|
||||
serial = None
|
||||
for s in self.serial_tabs:
|
||||
if s.name == name:
|
||||
serial = s
|
||||
break
|
||||
|
||||
if not serial:
|
||||
serial = vmmSerialConsole(self.vm, target_port, name)
|
||||
|
||||
title = Gtk.Label(label=name)
|
||||
self.widget("console-pages").append_page(serial.box, title)
|
||||
self.serial_tabs.append(serial)
|
||||
serial.open_console()
|
||||
|
||||
page_idx = self.serial_tabs.index(serial) + CONSOLE_PAGE_OFFSET
|
||||
self.widget("console-pages").set_current_page(page_idx)
|
||||
|
||||
def _close_serial_tab(self, serial):
|
||||
if not serial in self.serial_tabs:
|
||||
return
|
||||
|
||||
page_idx = self.serial_tabs.index(serial) + CONSOLE_PAGE_OFFSET
|
||||
self.widget("console-pages").remove_page(page_idx)
|
||||
|
||||
serial.cleanup()
|
||||
self.serial_tabs.remove(serial)
|
||||
|
||||
|
||||
def populate_serial_menu(self, src):
|
||||
for ent in src:
|
||||
src.remove(ent)
|
||||
|
||||
serial_page_dev = self.current_serial_dev()
|
||||
showing_graphics = (
|
||||
self.widget("console-pages").get_current_page() ==
|
||||
CONSOLE_PAGE_VIEWER)
|
||||
|
||||
# Populate serial devices
|
||||
group = None
|
||||
itemlist = self.build_serial_list()
|
||||
for msg, err, sensitive, do_radio, cb, ignore in itemlist:
|
||||
if do_radio:
|
||||
item = Gtk.RadioMenuItem(group)
|
||||
item.set_label(msg)
|
||||
if group is None:
|
||||
group = item
|
||||
else:
|
||||
item = Gtk.MenuItem(msg)
|
||||
|
||||
item.set_sensitive(sensitive)
|
||||
|
||||
if err and not sensitive:
|
||||
item.set_tooltip_text(err)
|
||||
|
||||
if cb:
|
||||
item.connect("toggled", cb)
|
||||
|
||||
# Tab is already open, make sure marked as such
|
||||
if (sensitive and
|
||||
serial_page_dev and
|
||||
serial_page_dev.name == msg):
|
||||
item.set_active(True)
|
||||
|
||||
src.add(item)
|
||||
|
||||
src.add(Gtk.SeparatorMenuItem())
|
||||
|
||||
# Populate graphical devices
|
||||
devs = self.vm.get_graphics_devices()
|
||||
if len(devs) == 0:
|
||||
item = Gtk.MenuItem(_("No graphical console available"))
|
||||
item.set_sensitive(False)
|
||||
src.add(item)
|
||||
else:
|
||||
dev = devs[0]
|
||||
item = Gtk.RadioMenuItem(group)
|
||||
item.set_label(_("Graphical Console %s") %
|
||||
dev.pretty_type_simple(dev.type))
|
||||
if group is None:
|
||||
group = item
|
||||
|
||||
if showing_graphics:
|
||||
item.set_active(True)
|
||||
item.connect("toggled", self.control_serial_tab,
|
||||
dev.virtual_device_type, dev.type)
|
||||
src.add(item)
|
||||
|
||||
src.show_all()
|
||||
|
@ -34,9 +34,7 @@ from virtManager.storagebrowse import vmmStorageBrowser
|
||||
from virtManager.baseclass import vmmGObjectUI
|
||||
from virtManager.addhardware import vmmAddHardware
|
||||
from virtManager.choosecd import vmmChooseCD
|
||||
from virtManager.console import vmmConsolePages
|
||||
from virtManager.snapshots import vmmSnapshotPage
|
||||
from virtManager.serialcon import vmmSerialConsole
|
||||
from virtManager.graphwidgets import Sparkline
|
||||
|
||||
import virtinst
|
||||
@ -140,10 +138,9 @@ remove_pages = [HW_LIST_TYPE_NIC, HW_LIST_TYPE_INPUT,
|
||||
BOOT_ACTIVE) = range(4)
|
||||
|
||||
# Main tab pages
|
||||
(PAGE_CONSOLE,
|
||||
PAGE_DETAILS,
|
||||
PAGE_SNAPSHOTS,
|
||||
PAGE_DYNAMIC_OFFSET) = range(4)
|
||||
(DETAILS_PAGE_DETAILS,
|
||||
DETAILS_PAGE_CONSOLE,
|
||||
DETAILS_PAGE_SNAPSHOTS) = range(3)
|
||||
|
||||
|
||||
def prettyify_disk_bus(bus):
|
||||
@ -359,13 +356,11 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.widget("details-toolbar").hide()
|
||||
self.widget("details-menubar").hide()
|
||||
pages = self.widget("details-pages")
|
||||
pages.set_current_page(PAGE_DETAILS)
|
||||
pages.set_current_page(DETAILS_PAGE_DETAILS)
|
||||
|
||||
|
||||
self.active_edits = []
|
||||
|
||||
self.serial_tabs = []
|
||||
self.last_console_page = PAGE_CONSOLE
|
||||
self.addhw = None
|
||||
self.media_choosers = {"cdrom": None, "floppy": None}
|
||||
self.storage_browser = None
|
||||
@ -374,6 +369,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.ignoreDetails = False
|
||||
self._cpu_copy_host = False
|
||||
|
||||
from virtManager.console import vmmConsolePages
|
||||
self.console = vmmConsolePages(self.vm, self.builder, self.topwin)
|
||||
self.snapshots = vmmSnapshotPage(self.vm, self.builder, self.topwin)
|
||||
self.widget("snapshot-placeholder").add(self.snapshots.top_box)
|
||||
@ -579,10 +575,6 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.media_choosers[key].cleanup()
|
||||
self.media_choosers = {}
|
||||
|
||||
for serial in self.serial_tabs:
|
||||
serial.cleanup()
|
||||
self.serial_tabs = []
|
||||
|
||||
self.console.cleanup()
|
||||
self.console = None
|
||||
self.snapshots.cleanup()
|
||||
@ -686,11 +678,6 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.addhwmenu.add(addHW)
|
||||
self.addhwmenu.add(rmHW)
|
||||
|
||||
# Serial list menu
|
||||
smenu = Gtk.Menu()
|
||||
smenu.connect("show", self.populate_serial_menu)
|
||||
self.widget("details-menu-view-serial-list").set_submenu(smenu)
|
||||
|
||||
# Don't allowing changing network/disks for Dom0
|
||||
dom0 = self.vm.is_management_domain()
|
||||
self.widget("add-hardware-button").set_sensitive(not dom0)
|
||||
@ -1115,106 +1102,6 @@ class vmmDetails(vmmGObjectUI):
|
||||
|
||||
self.addhwmenu.popup(None, None, None, None, 0, event.time)
|
||||
|
||||
def build_serial_list(self):
|
||||
ret = []
|
||||
|
||||
def add_row(text, err, sensitive, do_radio, cb, serialidx):
|
||||
ret.append([text, err, sensitive, do_radio, cb, serialidx])
|
||||
|
||||
devs = self.vm.get_serial_devs()
|
||||
if len(devs) == 0:
|
||||
add_row(_("No text console available"),
|
||||
None, False, False, None, None)
|
||||
|
||||
def build_desc(dev):
|
||||
if dev.virtual_device_type == "console":
|
||||
return "Text Console %d" % (dev.vmmindex + 1)
|
||||
return "Serial %d" % (dev.vmmindex + 1)
|
||||
|
||||
for dev in devs:
|
||||
desc = build_desc(dev)
|
||||
idx = dev.vmmindex
|
||||
|
||||
err = vmmSerialConsole.can_connect(self.vm, dev)
|
||||
sensitive = not bool(err)
|
||||
|
||||
def cb(src):
|
||||
return self.control_serial_tab(src, desc, idx)
|
||||
|
||||
add_row(desc, err, sensitive, True, cb, idx)
|
||||
|
||||
return ret
|
||||
|
||||
def current_serial_dev(self):
|
||||
showing_serial = (self.last_console_page >= PAGE_DYNAMIC_OFFSET)
|
||||
if not showing_serial:
|
||||
return
|
||||
|
||||
serial_idx = self.last_console_page - PAGE_DYNAMIC_OFFSET
|
||||
if len(self.serial_tabs) < serial_idx:
|
||||
return
|
||||
|
||||
return self.serial_tabs[serial_idx]
|
||||
|
||||
def populate_serial_menu(self, src):
|
||||
for ent in src:
|
||||
src.remove(ent)
|
||||
|
||||
serial_page_dev = self.current_serial_dev()
|
||||
showing_graphics = (self.last_console_page == PAGE_CONSOLE)
|
||||
|
||||
# Populate serial devices
|
||||
group = None
|
||||
itemlist = self.build_serial_list()
|
||||
for msg, err, sensitive, do_radio, cb, ignore in itemlist:
|
||||
if do_radio:
|
||||
item = Gtk.RadioMenuItem(group)
|
||||
item.set_label(msg)
|
||||
if group is None:
|
||||
group = item
|
||||
else:
|
||||
item = Gtk.MenuItem(msg)
|
||||
|
||||
item.set_sensitive(sensitive)
|
||||
|
||||
if err and not sensitive:
|
||||
item.set_tooltip_text(err)
|
||||
|
||||
if cb:
|
||||
item.connect("toggled", cb)
|
||||
|
||||
# Tab is already open, make sure marked as such
|
||||
if (sensitive and
|
||||
serial_page_dev and
|
||||
serial_page_dev.name == msg):
|
||||
item.set_active(True)
|
||||
|
||||
src.add(item)
|
||||
|
||||
src.add(Gtk.SeparatorMenuItem())
|
||||
|
||||
# Populate graphical devices
|
||||
devs = self.vm.get_graphics_devices()
|
||||
if len(devs) == 0:
|
||||
item = Gtk.MenuItem(_("No graphical console available"))
|
||||
item.set_sensitive(False)
|
||||
src.add(item)
|
||||
else:
|
||||
dev = devs[0]
|
||||
item = Gtk.RadioMenuItem(group)
|
||||
item.set_label(_("Graphical Console %s") %
|
||||
dev.pretty_type_simple(dev.type))
|
||||
if group is None:
|
||||
group = item
|
||||
|
||||
if showing_graphics:
|
||||
item.set_active(True)
|
||||
item.connect("toggled", self.control_serial_tab,
|
||||
dev.virtual_device_type, dev.type)
|
||||
src.add(item)
|
||||
|
||||
src.show_all()
|
||||
|
||||
def control_fullscreen(self, src):
|
||||
menu = self.widget("details-menu-view-fullscreen")
|
||||
if src.get_active() != menu.get_active():
|
||||
@ -1386,19 +1273,19 @@ class vmmDetails(vmmGObjectUI):
|
||||
src == self.widget("details-menu-view-snapshots"))
|
||||
|
||||
pages = self.widget("details-pages")
|
||||
if pages.get_current_page() == PAGE_DETAILS:
|
||||
if pages.get_current_page() == DETAILS_PAGE_DETAILS:
|
||||
if self.has_unapplied_changes(self.get_hw_row()):
|
||||
self.sync_details_console_view(True)
|
||||
return
|
||||
self.disable_apply()
|
||||
|
||||
if is_details:
|
||||
pages.set_current_page(PAGE_DETAILS)
|
||||
pages.set_current_page(DETAILS_PAGE_DETAILS)
|
||||
elif is_snapshot:
|
||||
self.snapshots.show_page()
|
||||
pages.set_current_page(PAGE_SNAPSHOTS)
|
||||
pages.set_current_page(DETAILS_PAGE_SNAPSHOTS)
|
||||
else:
|
||||
pages.set_current_page(self.last_console_page)
|
||||
pages.set_current_page(DETAILS_PAGE_CONSOLE)
|
||||
|
||||
def sync_details_console_view(self, newpage):
|
||||
details = self.widget("control-vm-details")
|
||||
@ -1408,8 +1295,8 @@ class vmmDetails(vmmGObjectUI):
|
||||
snapshot = self.widget("control-snapshots")
|
||||
snapshot_menu = self.widget("details-menu-view-snapshots")
|
||||
|
||||
is_details = newpage == PAGE_DETAILS
|
||||
is_snapshot = newpage == PAGE_SNAPSHOTS
|
||||
is_details = newpage == DETAILS_PAGE_DETAILS
|
||||
is_snapshot = newpage == DETAILS_PAGE_SNAPSHOTS
|
||||
is_console = not is_details and not is_snapshot
|
||||
|
||||
try:
|
||||
@ -1430,9 +1317,6 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.sync_details_console_view(newpage)
|
||||
self.console.set_allow_fullscreen()
|
||||
|
||||
if newpage == PAGE_CONSOLE or newpage >= PAGE_DYNAMIC_OFFSET:
|
||||
self.last_console_page = newpage
|
||||
|
||||
def change_run_text(self, can_restore):
|
||||
if can_restore:
|
||||
text = _("_Restore")
|
||||
@ -1511,41 +1395,27 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.emit("action-exit-app")
|
||||
|
||||
def activate_default_console_page(self):
|
||||
if self.vm.get_graphics_devices() or not self.vm.get_serial_devs():
|
||||
return
|
||||
|
||||
# Only show serial page if we are already on console view
|
||||
pages = self.widget("details-pages")
|
||||
if pages.get_current_page() != PAGE_CONSOLE:
|
||||
if pages.get_current_page() != DETAILS_PAGE_CONSOLE:
|
||||
return
|
||||
|
||||
# Show serial console
|
||||
devs = self.build_serial_list()
|
||||
for name, ignore, sensitive, ignore, cb, serialidx in devs:
|
||||
if not sensitive or not cb:
|
||||
continue
|
||||
|
||||
self._show_serial_tab(name, serialidx)
|
||||
break
|
||||
|
||||
self.console.activate_default_console_page()
|
||||
|
||||
# activate_* are called from engine.py via CLI options
|
||||
|
||||
def activate_default_page(self):
|
||||
pages = self.widget("details-pages")
|
||||
pages.set_current_page(PAGE_CONSOLE)
|
||||
pages.set_current_page(DETAILS_PAGE_CONSOLE)
|
||||
self.activate_default_console_page()
|
||||
|
||||
def activate_console_page(self):
|
||||
pages = self.widget("details-pages")
|
||||
pages.set_current_page(PAGE_CONSOLE)
|
||||
pages.set_current_page(DETAILS_PAGE_CONSOLE)
|
||||
|
||||
def activate_performance_page(self):
|
||||
self.widget("details-pages").set_current_page(PAGE_DETAILS)
|
||||
self.widget("details-pages").set_current_page(DETAILS_PAGE_DETAILS)
|
||||
self.set_hw_selection(HW_LIST_TYPE_STATS)
|
||||
|
||||
def activate_config_page(self):
|
||||
self.widget("details-pages").set_current_page(PAGE_DETAILS)
|
||||
self.widget("details-pages").set_current_page(DETAILS_PAGE_DETAILS)
|
||||
|
||||
def add_hardware(self, src_ignore):
|
||||
try:
|
||||
@ -1700,49 +1570,6 @@ class vmmDetails(vmmGObjectUI):
|
||||
file(filename, "wb").write(ret)
|
||||
|
||||
|
||||
#########################
|
||||
# Serial Console pieces #
|
||||
#########################
|
||||
|
||||
def control_serial_tab(self, src_ignore, name, target_port):
|
||||
pages = self.widget("details-pages")
|
||||
is_graphics = (name == "graphics")
|
||||
is_serial = not is_graphics
|
||||
|
||||
if is_graphics:
|
||||
pages.set_current_page(PAGE_CONSOLE)
|
||||
elif is_serial:
|
||||
self._show_serial_tab(name, target_port)
|
||||
|
||||
def _show_serial_tab(self, name, target_port):
|
||||
serial = None
|
||||
for s in self.serial_tabs:
|
||||
if s.name == name:
|
||||
serial = s
|
||||
break
|
||||
|
||||
if not serial:
|
||||
serial = vmmSerialConsole(self.vm, target_port, name)
|
||||
|
||||
title = Gtk.Label(label=name)
|
||||
self.widget("details-pages").append_page(serial.box, title)
|
||||
self.serial_tabs.append(serial)
|
||||
serial.open_console()
|
||||
|
||||
page_idx = self.serial_tabs.index(serial) + PAGE_DYNAMIC_OFFSET
|
||||
self.widget("details-pages").set_current_page(page_idx)
|
||||
|
||||
def _close_serial_tab(self, serial):
|
||||
if not serial in self.serial_tabs:
|
||||
return
|
||||
|
||||
page_idx = self.serial_tabs.index(serial) + PAGE_DYNAMIC_OFFSET
|
||||
self.widget("details-pages").remove_page(page_idx)
|
||||
|
||||
serial.cleanup()
|
||||
self.serial_tabs.remove(serial)
|
||||
|
||||
|
||||
############################
|
||||
# Details/Hardware getters #
|
||||
############################
|
||||
@ -2688,12 +2515,12 @@ class vmmDetails(vmmGObjectUI):
|
||||
raise
|
||||
|
||||
# Stats page needs to be refreshed every tick
|
||||
if (page == PAGE_DETAILS and
|
||||
if (page == DETAILS_PAGE_DETAILS and
|
||||
self.get_hw_selection(HW_LIST_COL_TYPE) == HW_LIST_TYPE_STATS):
|
||||
self.refresh_stats_page()
|
||||
|
||||
def page_refresh(self, page):
|
||||
if page != PAGE_DETAILS:
|
||||
if page != DETAILS_PAGE_DETAILS:
|
||||
return
|
||||
|
||||
# This function should only be called when the VM xml actually
|
||||
|
Loading…
x
Reference in New Issue
Block a user