def __init__(self, parent):
     """Prepare the command arguments dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('command_arguments.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_arguments.set_transient_for(parent)
     # Restore the saved size and position
     settings.positions.restore_window_position(self.ui.dialog_arguments,
                                                SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Initialize column headers
     for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
         widget.set_title(text(widget.get_title()))
     # Load the arguments
     self.model_arguments = self.ui.store_arguments
     self.arguments = '[]'
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#2
0
 def __init__(self, parent):
     """Prepare the groups dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('groups.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_groups.set_transient_for(parent)
     # Restore the saved size and position
     settings.positions.restore_window_position(self.ui.dialog_groups,
                                                SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Initialize column headers
     for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
         widget.set_title(text(widget.get_title()))
     # Load the groups
     self.model = ModelGroups(self.ui.store_groups)
     self.selected_iter = None
     # Sort the data in the models
     self.model.model.set_sort_column_id(
         self.ui.column_name.get_sort_column_id(), Gtk.SortType.ASCENDING)
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
 def __init__(self, parent, services):
     """Prepare the services detail dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('service_detail.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_edit_service.set_transient_for(parent)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize labels
     for widget in self.ui.get_objects_by_type(Gtk.Label):
         widget.set_label(text(widget.get_label()))
         widget.set_tooltip_text(widget.get_label().replace('_', ''))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     self.model = services
     self.selected_iter = None
     self.name = ''
     self.description = ''
     self.command = '[]'
     self.terminal = False
     self.icon = ''
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#4
0
 def __init__(self, parent, delete_event_cb):
     """Prepare the Debug dialog"""
     self.on_window_debug_delete_event = delete_event_cb
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('debug.glade'))
     # Initialize preferences
     self.actions_preferences = {
         DEBUG_ENABLED: self.ui.action_enable,
         DEBUG_ENABLED_HIDDEN: self.ui.action_enable_hidden,
         DEBUG_SHOW_INFO: self.ui.action_show_info,
         DEBUG_SHOW_WARNING: self.ui.action_show_warning,
         DEBUG_SHOW_ERROR: self.ui.action_show_error,
         DEBUG_TIMESTAMP: self.ui.action_show_timestamp,
         DEBUG_FOLLOW_TEXT: self.ui.action_follow_text,
     }
     for key in self.actions_preferences:
         self.actions_preferences[key].set_active(preferences.get(key))
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#5
0
 def __init__(self, parent, destinations):
     """Prepare the service association dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('service_association.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_association.set_transient_for(parent)
     # Restore the saved size and position
     settings.positions.restore_window_position(self.ui.dialog_association,
                                                SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize labels
     for widget in self.ui.get_objects_by_type(Gtk.Label):
         widget.set_label(text(widget.get_label()))
         widget.set_tooltip_text(widget.get_label().replace('_', ''))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Load destinations
     self.destinations = destinations
     self.ui.cbo_destinations.set_model(self.destinations.model)
     # Load services
     self.services = ModelServices(self.ui.store_services)
     self.services.load(model_services.services)
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
     self.service_arguments_widgets = {}
示例#6
0
 def __init__(self, parent, services):
     """Prepare the services detail dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('service_detail.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_edit_service.set_transient_for(parent)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize labels
     for widget in self.ui.get_objects_by_type(Gtk.Label):
         widget.set_label(text(widget.get_label()))
         widget.set_tooltip_text(widget.get_label().replace('_', ''))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     self.model = services
     self.selected_iter = None
     self.name = ''
     self.description = ''
     self.command = '[]'
     self.terminal = False
     self.icon = ''
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#7
0
 def __init__(self, parent, destinations):
     """Prepare the destination dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('destination.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_destination.set_transient_for(parent)
     # Restore the saved size and position
     settings.positions.restore_window_position(
         self.ui.dialog_destination, SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize labels
     for widget in self.ui.get_objects_by_type(Gtk.Label):
         widget.set_label(text(widget.get_label()))
         widget.set_tooltip_text(widget.get_label().replace('_', ''))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     self.model = destinations
     self.selected_iter = None
     self.name = ''
     self.value = ''
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#8
0
 def __init__(self, parent):
     """Prepare the services dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('services.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_services.set_transient_for(parent)
     # Restore the saved size and position
     settings.positions.restore_window_position(
         self.ui.dialog_services, SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Initialize column headers
     for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
         widget.set_title(text(widget.get_title()))
     # Load the services
     self.model = ModelServices(self.ui.store_services)
     self.selected_iter = None
     self.ui.cell_icon.props.height = preferences.get(preferences.ICON_SIZE)
     # Sort the data in the models
     self.model.model.set_sort_column_id(
         self.ui.column_name.get_sort_column_id(),
         Gtk.SortType.ASCENDING)
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
 def __init__(self, parent):
     """Prepare the command arguments dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file("command_arguments.glade"))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_arguments.set_transient_for(parent)
     # Restore the saved size and position
     settings.positions.restore_window_position(self.ui.dialog_arguments, SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace("_", ""))
     # Initialize column headers
     for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
         widget.set_title(text(widget.get_title()))
     # Load the arguments
     self.model_arguments = self.ui.store_arguments
     self.arguments = "[]"
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#10
0
 def __init__(self, parent, delete_event_cb):
     """Prepare the Debug dialog"""
     self.on_window_debug_delete_event = delete_event_cb
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('debug.glade'))
     # Initialize preferences
     self.actions_preferences = {
         DEBUG_ENABLED: self.ui.action_enable,
         DEBUG_ENABLED_HIDDEN: self.ui.action_enable_hidden,
         DEBUG_SHOW_INFO: self.ui.action_show_info,
         DEBUG_SHOW_WARNING: self.ui.action_show_warning,
         DEBUG_SHOW_ERROR: self.ui.action_show_error,
         DEBUG_TIMESTAMP: self.ui.action_show_timestamp,
         DEBUG_FOLLOW_TEXT: self.ui.action_follow_text,
     }
     for key in self.actions_preferences:
         self.actions_preferences[key].set_active(preferences.get(key))
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#11
0
 def loadUI(self):
     """Load the interface UI"""
     self.ui = GtkBuilderLoader(get_ui_file('main.glade'))
     self.ui.win_main.set_application(self.application)
     self.ui.win_main.set_title(APP_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     # Initialize column headers
     for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
         widget.set_title(text(widget.get_title()))
     # Set list items row height
     icon_size = preferences.ICON_SIZE
     self.ui.cell_name.props.height = preferences.get(icon_size)
     self.ui.cell_group_name.props.height = preferences.get(icon_size)
     # Set groups visibility
     self.ui.scroll_groups.set_visible(
         preferences.get(preferences.GROUPS_SHOW))
     # Add a Gtk.Headerbar, only for GTK+ 3.10.0 and higher
     if (not Gtk.check_version(3, 10, 0)
             and not preferences.get(preferences.HEADERBARS_DISABLE)):
         self.load_ui_headerbar()
         if preferences.get(preferences.HEADERBARS_REMOVE_TOOLBAR):
             # This is only for development, it should always be True
             # Remove the redundant toolbar
             self.ui.toolbar_main.destroy()
         # Flatten the Gtk.ScrolledWindows
         self.ui.scroll_groups.set_shadow_type(Gtk.ShadowType.NONE)
         self.ui.scroll_connections.set_shadow_type(Gtk.ShadowType.NONE)
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#12
0
 def __init__(self, parent, delete_event_cb):
     """Prepare the processes dialog"""
     self.on_window_processes_delete_event = delete_event_cb
     self.processes = {}
     self.poller_id = None
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('processes.glade'))
     # Restore the saved size and position
     settings.positions.restore_window_position(
         self.ui.window_processes, SECTION_WINDOW_NAME)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     self.model = ModelProcesses(self.ui.store_processes)
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#13
0
 def __init__(self, parent):
     """Prepare the argument dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('command_argument.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_argument.set_transient_for(parent)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize labels
     for widget in self.ui.get_objects_by_type(Gtk.Label):
         widget.set_label(text(widget.get_label()))
         widget.set_tooltip_text(widget.get_label().replace('_', ''))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     self.argument = ''
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#14
0
 def startup(self, application):
     """Configure the application during the startup"""
     self.ui = UIMain(self)
     # Add the about action to the app menu
     action = Gio.SimpleAction(name="settings_folder")
     action.connect("activate", self.on_app_settings_folder_activate)
     self.add_action(action)
     # Add the about action to the app menu
     action = Gio.SimpleAction(name="about")
     action.connect("activate", self.on_app_about_activate)
     self.add_action(action)
     # Add the quit action to the app menu
     action = Gio.SimpleAction(name="quit")
     action.connect("activate", self.on_app_quit_activate)
     self.add_action(action)
     # Add the app menu
     builder_appmenu = GtkBuilderLoader(get_ui_file('appmenu.ui'))
     self.set_app_menu(builder_appmenu.app_menu)
示例#15
0
 def __init__(self, parent):
     """Prepare the about dialog"""
     # Retrieve the translators list
     translators = []
     for line in readlines(FILE_TRANSLATORS, False):
         if ':' in line:
             line = line.split(':', 1)[1]
         line = line.replace('(at)', '@').strip()
         if line not in translators:
             translators.append(line)
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('about.glade'))
     # Set various properties
     self.ui.dialog_about.set_program_name(APP_NAME)
     self.ui.dialog_about.set_version('Version %s' % APP_VERSION)
     self.ui.dialog_about.set_comments(APP_DESCRIPTION)
     self.ui.dialog_about.set_website(APP_URL)
     self.ui.dialog_about.set_copyright(APP_COPYRIGHT)
     # Prepare lists for authors and contributors
     authors = ['%s <%s>' % (APP_AUTHOR, APP_AUTHOR_EMAIL)]
     contributors = []
     for line in readlines(FILE_CONTRIBUTORS, False):
         contributors.append(line)
     if len(contributors) > 0:
         contributors.insert(0, _('Contributors:'))
         authors.extend(contributors)
     self.ui.dialog_about.set_authors(authors)
     self.ui.dialog_about.set_license('\n'.join(
         readlines(FILE_LICENSE, True)))
     self.ui.dialog_about.set_translator_credits('\n'.join(translators))
     # Retrieve the external resources links
     # only for GTK+ 3.6.0 and higher
     if not Gtk.check_version(3, 6, 0):
         for line in readlines(FILE_RESOURCES, False):
             resource_type, resource_url = line.split(':', 1)
             self.ui.dialog_about.add_credit_section(
                 resource_type, (resource_url, ))
     icon_logo = Pixbuf.new_from_file(FILE_ICON)
     self.ui.dialog_about.set_logo(icon_logo)
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_about.set_transient_for(parent)
示例#16
0
 def __init__(self, parent):
     """Prepare the argument dialog"""
     # Load the user interface
     self.ui = GtkBuilderLoader(get_ui_file('command_argument.glade'))
     if not preferences.get(preferences.DETACHED_WINDOWS):
         self.ui.dialog_argument.set_transient_for(parent)
     # Initialize actions
     for widget in self.ui.get_objects_by_type(Gtk.Action):
         # Connect the actions accelerators
         widget.connect_accelerator()
         # Set labels
         widget.set_label(text(widget.get_label()))
     # Initialize labels
     for widget in self.ui.get_objects_by_type(Gtk.Label):
         widget.set_label(text(widget.get_label()))
         widget.set_tooltip_text(widget.get_label().replace('_', ''))
     # Initialize tooltips
     for widget in self.ui.get_objects_by_type(Gtk.Button):
         action = widget.get_related_action()
         if action:
             widget.set_tooltip_text(action.get_label().replace('_', ''))
     self.argument = ''
     # Connect signals from the glade file to the module functions
     self.ui.connect_signals(self)
示例#17
0
class UIServices(object):
    def __init__(self, parent):
        """Prepare the services dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('services.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_services.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_services,
                                                   SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the services
        self.model = ModelServices(self.ui.store_services)
        self.selected_iter = None
        self.ui.cell_icon.props.height = preferences.get(preferences.ICON_SIZE)
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(), Gtk.SortType.ASCENDING)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Services dialog"""
        self.ui.dialog_services.run()
        self.ui.dialog_services.hide()

    def destroy(self):
        """Destroy the Services dialog"""
        settings.positions.save_window_position(self.ui.dialog_services,
                                                SECTION_WINDOW_NAME)
        self.ui.dialog_services.destroy()
        self.ui.dialog_services = None

    def on_action_add_activate(self, action):
        """Add a new service"""
        dialog = UIServiceDetail(self.ui.dialog_services, self.model)
        if dialog.show(default_name='',
                       default_description='',
                       default_command='',
                       default_terminal=False,
                       default_icon='',
                       title=_('Add new service'),
                       treeiter=None) == Gtk.ResponseType.OK:
            self.model.add_data(
                ServiceInfo(name=dialog.name,
                            description=dialog.description,
                            command=dialog.command,
                            terminal=dialog.terminal,
                            icon=dialog.icon))
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Edit the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_services)
        if selected_row:
            name = self.model.get_key(selected_row)
            description = self.model.get_description(selected_row)
            command = self.model.get_command(selected_row)
            terminal = self.model.get_terminal(selected_row)
            icon = self.model.get_icon(selected_row)
            selected_iter = self.model.get_iter(name)
            dialog = UIServiceDetail(self.ui.dialog_services, self.model)
            if dialog.show(default_name=name,
                           default_description=description,
                           default_command=command,
                           default_terminal=terminal,
                           default_icon=icon,
                           title=_('Edit service'),
                           treeiter=selected_iter) == Gtk.ResponseType.OK:
                # Update values
                self.model.set_data(
                    selected_iter,
                    ServiceInfo(name=dialog.name,
                                description=dialog.description,
                                command=dialog.command,
                                terminal=dialog.terminal,
                                icon=dialog.icon))
            dialog.destroy()

    def on_action_remove_activate(self, action):
        """Remove the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_services)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_services,
                message_type=Gtk.MessageType.WARNING,
                title=None,
                msg1=_("Remove service"),
                msg2=_("Remove the selected service?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model.remove(selected_row)

    def on_tvw_services_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_edit.activate()
示例#18
0
class UIServices(object):
    def __init__(self, parent):
        """Prepare the services dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('services.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_services.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_services, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the services
        self.model = ModelServices(self.ui.store_services)
        self.selected_iter = None
        self.ui.cell_icon.props.height = preferences.get(preferences.ICON_SIZE)
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Services dialog"""
        self.ui.dialog_services.run()
        self.ui.dialog_services.hide()

    def destroy(self):
        """Destroy the Services dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_services, SECTION_WINDOW_NAME)
        self.ui.dialog_services.destroy()
        self.ui.dialog_services = None

    def on_action_add_activate(self, action):
        """Add a new service"""
        dialog = UIServiceDetail(self.ui.dialog_services, self.model)
        if dialog.show(default_name='',
                       default_description='',
                       default_command='',
                       default_terminal=False,
                       default_icon='',
                       title=_('Add new service'),
                       treeiter=None) == Gtk.ResponseType.OK:
            self.model.add_data(ServiceInfo(name=dialog.name,
                                            description=dialog.description,
                                            command=dialog.command,
                                            terminal=dialog.terminal,
                                            icon=dialog.icon))
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Edit the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_services)
        if selected_row:
            name = self.model.get_key(selected_row)
            description = self.model.get_description(selected_row)
            command = self.model.get_command(selected_row)
            terminal = self.model.get_terminal(selected_row)
            icon = self.model.get_icon(selected_row)
            selected_iter = self.model.get_iter(name)
            dialog = UIServiceDetail(self.ui.dialog_services, self.model)
            if dialog.show(default_name=name,
                           default_description=description,
                           default_command=command,
                           default_terminal=terminal,
                           default_icon=icon,
                           title=_('Edit service'),
                           treeiter=selected_iter
                           ) == Gtk.ResponseType.OK:
                # Update values
                self.model.set_data(selected_iter, ServiceInfo(
                    name=dialog.name,
                    description=dialog.description,
                    command=dialog.command,
                    terminal=dialog.terminal,
                    icon=dialog.icon))
            dialog.destroy()

    def on_action_remove_activate(self, action):
        """Remove the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_services)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_services,
                message_type=Gtk.MessageType.WARNING,
                title=None,
                msg1=_("Remove service"),
                msg2=_("Remove the selected service?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model.remove(selected_row)

    def on_tvw_services_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_edit.activate()
示例#19
0
class UICommandArgument(object):
    def __init__(self, parent):
        """Prepare the argument dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('command_argument.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_argument.set_transient_for(parent)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.argument = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_value):
        """Show the command argument dialog"""
        self.ui.txt_argument.set_text(default_value)
        self.ui.txt_argument.grab_focus()
        response = self.ui.dialog_argument.run()
        self.ui.dialog_argument.hide()
        self.argument = self.ui.txt_argument.get_text().strip()
        return response

    def destroy(self):
        """Destroy the command argument dialog"""
        self.ui.dialog_argument.destroy()
        self.ui.dialog_argument = None

    def on_action_confirm_activate(self, action):
        """Check che argument before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(
                widget=widget,
                widgets=(self.ui.txt_argument, ),
                label=self.ui.lbl_error_message,
                infobar=self.ui.infobar_error_message,
                error_msg=error_msg)
        if len(self.ui.txt_argument.get_text().strip()) == 0:
            # Show error for missing argument
            show_error_message_on_infobar(
                self.ui.txt_argument,
                _('The argument is missing'))
        else:
            self.ui.dialog_argument.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_argument_changed(self, widget):
        """Check the argument value field"""
        check_invalid_input(widget, False, True, True)
示例#20
0
class UIProcesses(object):
    def __init__(self, parent, delete_event_cb):
        """Prepare the processes dialog"""
        self.on_window_processes_delete_event = delete_event_cb
        self.processes = {}
        self.poller_id = None
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('processes.glade'))
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.window_processes, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.model = ModelProcesses(self.ui.store_processes)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the processes dialog"""
        settings.positions.restore_window_position(
            self.ui.window_processes, SECTION_WINDOW_NAME)
        self.ui.window_processes.show()

    def hide(self):
        """Hide the processes dialog"""
        settings.positions.save_window_position(
            self.ui.window_processes, SECTION_WINDOW_NAME)
        self.ui.window_processes.hide()

    def destroy(self):
        """Destroy the Debug dialog"""
        self.hide()
        self.ui.window_processes.destroy()
        self.ui.window_processes = None

    def add_process(self, host, destination, service, command):
        """Add a new process"""
        process = subprocess.Popen(args=get_list_from_string_list(command),
                                   shell=False)
        treeiter = self.model.add_data(ProcessInfo(host,
                                                   destination,
                                                   service,
                                                   process))
        # Enable process actions
        self.ui.actions_processes.set_sensitive(True)
        # Save process for further polling
        self.processes[self.model.get_key(treeiter)] = process
        self.model.add_detail(treeiter,
                              _('Process started'),
                              'media-playback-start')
        self.start_polling()

    def poll_processes(self):
        """Poll each process to check if it was terminated"""
        for key in self.processes.keys():
            process = self.processes[key]
            return_code = process.poll()
            # Has the process exited?
            if return_code is not None:
                treeiter = self.model.get_iter(key)
                self.model.add_detail(treeiter,
                                      _('Exit code: %d') % return_code,
                                      'media-playback-stop')
                # Remove the completed process
                self.processes.pop(key)
        if len(self.processes):
            # Continue the polling
            return True
        else:
            # Stop the polling
            self.poller_id = None
            return False

    def start_polling(self):
        """Start the poller timeout if it wasn't already started"""
        if not self.poller_id:
            self.poller_id = GLib.timeout_add(1000, self.poll_processes)

    def on_action_process_activate(self, action):
        """Execute an action for the selected process"""
        selected_row = get_treeview_selected_row(self.ui.tvw_processes)
        if selected_row:
            iter_parent = self.model.model.iter_parent(selected_row)
            selected_path = self.model.model[selected_row].path
            # Get the path of the process
            if iter_parent is None:
                tree_path = self.model.model[selected_row].path
            else:
                tree_path = self.model.model[iter_parent].path
            #
            selected_key = self.model.get_key(tree_path)
            if selected_key in self.processes:
                selected_process = self.processes[selected_key]
                treeiter = self.model.get_iter(selected_key)
                if action is self.ui.action_kill:
                    # Resume the process and terminate it
                    selected_process.send_signal(subprocess.signal.SIGCONT)
                    selected_process.terminate()
                    debug.add_info(
                        _('The process with the PID %d was terminated') % (
                            selected_process.pid))
                    self.model.add_detail(treeiter,
                                          _('Process terminated'),
                                          'media-playback-stop')
                elif action is self.ui.action_pause:
                    # Pause the process by sending the STOP signal
                    selected_process.send_signal(subprocess.signal.SIGSTOP)
                    debug.add_info(
                        _('The process with the PID %d was paused') % (
                            selected_process.pid))
                    self.model.add_detail(treeiter,
                                          _('Process paused'),
                                          'media-playback-pause')
                elif action is self.ui.action_resume:
                    # Pause the process by sending the CONT signal
                    selected_process.send_signal(subprocess.signal.SIGCONT)
                    debug.add_info(
                        _('The process with the PID %d was resumed') % (
                            selected_process.pid))
                    self.model.add_detail(treeiter,
                                          _('Process resumed'),
                                          'media-playback-start')

    def on_tvw_processes_row_activated(self, widget, treepath, column):
        """Expand or collapse the selected row"""
        selected_row = get_treeview_selected_row(self.ui.tvw_processes)
        if selected_row:
            iter_parent = self.ui.store_processes.iter_parent(selected_row)
            selected_path = self.model.model[selected_row].path
            # Get the path of the process
            if iter_parent is None:
                tree_path = self.model.model[selected_row].path
                expanded = self.ui.tvw_processes.row_expanded(tree_path)
                if expanded:
                    self.ui.tvw_processes.collapse_row(tree_path)
                else:
                    self.ui.tvw_processes.expand_row(tree_path, True)

    def on_tvw_processes_key_press_event(self, widget, event):
        """Expand and collapse nodes with keyboard arrows"""
        selected_row = get_treeview_selected_row(self.ui.tvw_processes)
        if selected_row and event.keyval in (Gdk.KEY_Left, Gdk.KEY_Right):
            iter_parent = self.ui.store_processes.iter_parent(selected_row)
            if selected_row and iter_parent is None:
                tree_path = self.model.get_path(selected_row)
                expanded = self.ui.tvw_processes.row_expanded(tree_path)
                if event.keyval == Gdk.KEY_Left and expanded:
                    # Collapse the selected node
                    self.ui.tvw_processes.collapse_row(tree_path)
                elif event.keyval == Gdk.KEY_Right and not expanded:
                    # Expand the selected node
                    self.ui.tvw_processes.expand_row(tree_path, False)
        elif event.keyval == Gdk.KEY_Menu:
            # Show popup menu on Menu key press
            event = Gdk.EventButton()
            event.type = Gdk.EventType.BUTTON_RELEASE
            event.button = Gdk.BUTTON_SECONDARY
            self.ui.tvw_processes.event(event)

    def on_tvw_processes_button_release_event(self, widget, event):
        """Show processes popup menu on right click"""
        if event.button == Gdk.BUTTON_SECONDARY:
            show_popup_menu(self.ui.menu_popup, event.button)
示例#21
0
class UIDebug(object):
    def __init__(self, parent, delete_event_cb):
        """Prepare the Debug dialog"""
        self.on_window_debug_delete_event = delete_event_cb
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('debug.glade'))
        # Initialize preferences
        self.actions_preferences = {
            DEBUG_ENABLED: self.ui.action_enable,
            DEBUG_ENABLED_HIDDEN: self.ui.action_enable_hidden,
            DEBUG_SHOW_INFO: self.ui.action_show_info,
            DEBUG_SHOW_WARNING: self.ui.action_show_warning,
            DEBUG_SHOW_ERROR: self.ui.action_show_error,
            DEBUG_TIMESTAMP: self.ui.action_show_timestamp,
            DEBUG_FOLLOW_TEXT: self.ui.action_follow_text,
        }
        for key in self.actions_preferences:
            self.actions_preferences[key].set_active(preferences.get(key))
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Debug dialog"""
        settings.positions.restore_window_position(self.ui.window_debug,
                                                   SECTION_WINDOW_NAME)
        self.ui.window_debug.show()

    def hide(self):
        """Hide the Debug dialog"""
        settings.positions.save_window_position(self.ui.window_debug,
                                                SECTION_WINDOW_NAME)
        self.ui.window_debug.hide()

    def destroy(self):
        """Destroy the Debug dialog"""
        self.hide()
        self.ui.window_debug.destroy()
        self.ui.window_debug = None

    def clear(self):
        """Clear the debug buffer"""
        self.ui.buffer_debug.set_text('')

    def add_text(self, text):
        """Add a text to the debug buffer"""
        if preferences.get(DEBUG_ENABLED) and (
                preferences.get(DEBUG_ENABLED_HIDDEN)
                or self.ui.window_debug.get_visible()):
            # Insert the text at the end
            self.ui.buffer_debug.insert(self.ui.buffer_debug.get_end_iter(),
                                        text)
            # Follow the text if requested
            if preferences.get(DEBUG_FOLLOW_TEXT):
                process_events()
                self.ui.textview_debug.scroll_to_iter(
                    iter=self.ui.buffer_debug.get_end_iter(),
                    within_margin=0.0,
                    use_align=False,
                    xalign=0.0,
                    yalign=0.0)

    def add_line(self, severity, text):
        """Add a text line to the debug buffer"""
        # Check the requested severity level
        if (severity == INFO and preferences.get(DEBUG_SHOW_INFO) or
            (severity == WARNING and preferences.get(DEBUG_SHOW_WARNING))
                or (severity == ERROR and preferences.get(DEBUG_SHOW_ERROR))):
            timestamp = (DEBUG_FORMAT_TIMESTAMP.format(datetime.datetime.now())
                         if preferences.get(DEBUG_TIMESTAMP) else '')
            self.add_text(
                DEBUG_FORMAT.format(timestamp=timestamp,
                                    severity=severity,
                                    text=text))

    def add_info(self, text):
        """Add a text line to the debug buffer with severity info"""
        self.add_line(INFO, text)

    def add_warning(self, text):
        """Add a text line to the debug buffer with severity warning"""
        self.add_line(WARNING, text)

    def add_error(self, text):
        """Add a text line to the debug buffer with severity error"""
        self.add_line(ERROR, text)

    def on_action_clear_activate(self, action):
        """Clear the debug text"""
        self.clear()

    def on_action_set_debug_flag(self, action):
        """Enable/disable various debug flags"""
        for key in self.actions_preferences:
            if action is self.actions_preferences[key]:
                preferences.set(key, action.get_active())
                break
示例#22
0
class UIServiceAssociation(object):
    def __init__(self, parent, destinations):
        """Prepare the service association dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('service_association.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_association.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_association,
                                                   SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Load destinations
        self.destinations = destinations
        self.ui.cbo_destinations.set_model(self.destinations.model)
        # Load services
        self.services = ModelServices(self.ui.store_services)
        self.services.load(model_services.services)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)
        self.service_arguments_widgets = {}

    def show(self, default_description, default_destination, default_service,
             default_arguments):
        """Show the Service association dialog"""
        # Set default description
        self.ui.entry_description.set_text(default_description)
        # Set default destination
        if default_destination:
            self.ui.cbo_destinations.set_active_id(default_destination)
        elif self.destinations.count() > 0:
            self.ui.cbo_destinations.set_active(0)
        # Set default service
        if default_service:
            self.ui.cbo_services.set_active_id(default_service)
        elif self.services.count() > 0:
            self.ui.cbo_services.set_active(0)
        # Set default arguments
        for argument in self.service_arguments_widgets:
            (new_label, new_entry) = self.service_arguments_widgets[argument]
            if argument in default_arguments:
                new_entry.set_text(default_arguments[argument])
        # Show the dialog
        response = self.ui.dialog_association.run()
        self.ui.dialog_association.hide()
        self.destination = self.ui.cbo_destinations.get_active_id()
        self.service = self.ui.cbo_services.get_active_id()
        self.description = self.ui.entry_description.get_text()
        # Prepares argument values
        self.arguments = {}
        for argument in self.service_arguments_widgets:
            (new_label, new_entry) = self.service_arguments_widgets[argument]
            self.arguments[argument] = new_entry.get_text()
        return response

    def destroy(self):
        """Destroy the Service association dialog"""
        settings.positions.save_window_position(self.ui.dialog_association,
                                                SECTION_WINDOW_NAME)
        self.ui.dialog_association.destroy()
        self.ui.dialog_association = None

    def on_cbo_services_changed(self, widget):
        """Update the service arguments widgets"""
        treeiter = self.ui.cbo_services.get_active_iter()
        # Remove the previously added arguments widgets
        for argument in self.service_arguments_widgets:
            (new_label, new_entry) = self.service_arguments_widgets[argument]
            new_label.destroy()
            new_entry.destroy()
        self.service_arguments_widgets = {}
        # Collect the needed arguments
        command = get_list_from_string_list(
            self.services.get_command(treeiter))
        row_number = 0
        processed_arguments = []
        # The argument address, already has a default widget
        processed_arguments.append('address')
        for option in command:
            arguments = get_string_fields(option)
            # Add a pair of widgets for each argument
            for argument in arguments:
                # Skip existing arguments
                if argument in processed_arguments:
                    continue
                row_number += 1
                processed_arguments.append(argument)
                # Add a new descriptive label for the argument
                new_label = Gtk.Label('%s:' % argument.title())
                new_label.set_xalign(1.0)
                new_label.set_visible(True)
                self.ui.grid_service_arguments.attach(child=new_label,
                                                      left=0,
                                                      top=row_number,
                                                      width=1,
                                                      height=1)
                # Add a new entry for the argument value
                new_entry = Gtk.Entry()
                new_entry.set_visible(True)
                new_entry.set_hexpand(True)
                self.ui.grid_service_arguments.attach(child=new_entry,
                                                      left=1,
                                                      top=row_number,
                                                      width=1,
                                                      height=1)
                # Save a tuple of widgets, to remove later
                self.service_arguments_widgets[argument] = (new_label,
                                                            new_entry)

    def on_cbo_destinations_changed(self, widget):
        """Update the address entry for the selected destination"""
        treeiter = self.ui.cbo_destinations.get_active_iter()
        self.ui.entry_service_arguments_address.set_text(
            self.destinations.get_value(treeiter))
示例#23
0
class UIDebug(object):
    def __init__(self, parent, delete_event_cb):
        """Prepare the Debug dialog"""
        self.on_window_debug_delete_event = delete_event_cb
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('debug.glade'))
        # Initialize preferences
        self.actions_preferences = {
            DEBUG_ENABLED: self.ui.action_enable,
            DEBUG_ENABLED_HIDDEN: self.ui.action_enable_hidden,
            DEBUG_SHOW_INFO: self.ui.action_show_info,
            DEBUG_SHOW_WARNING: self.ui.action_show_warning,
            DEBUG_SHOW_ERROR: self.ui.action_show_error,
            DEBUG_TIMESTAMP: self.ui.action_show_timestamp,
            DEBUG_FOLLOW_TEXT: self.ui.action_follow_text,
        }
        for key in self.actions_preferences:
            self.actions_preferences[key].set_active(preferences.get(key))
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Debug dialog"""
        settings.positions.restore_window_position(
            self.ui.window_debug, SECTION_WINDOW_NAME)
        self.ui.window_debug.show()

    def hide(self):
        """Hide the Debug dialog"""
        settings.positions.save_window_position(
            self.ui.window_debug, SECTION_WINDOW_NAME)
        self.ui.window_debug.hide()

    def destroy(self):
        """Destroy the Debug dialog"""
        self.hide()
        self.ui.window_debug.destroy()
        self.ui.window_debug = None

    def clear(self):
        """Clear the debug buffer"""
        self.ui.buffer_debug.set_text('')

    def add_text(self, text):
        """Add a text to the debug buffer"""
        if preferences.get(DEBUG_ENABLED) and (
                preferences.get(DEBUG_ENABLED_HIDDEN) or
                self.ui.window_debug.get_visible()):
            # Insert the text at the end
            self.ui.buffer_debug.insert(self.ui.buffer_debug.get_end_iter(),
                                        text)
            # Follow the text if requested
            if preferences.get(DEBUG_FOLLOW_TEXT):
                process_events()
                self.ui.textview_debug.scroll_to_iter(
                    iter=self.ui.buffer_debug.get_end_iter(),
                    within_margin=0.0,
                    use_align=False,
                    xalign=0.0,
                    yalign=0.0)

    def add_line(self, severity, text):
        """Add a text line to the debug buffer"""
        # Check the requested severity level
        if (severity == INFO and preferences.get(DEBUG_SHOW_INFO) or
            (severity == WARNING and preferences.get(DEBUG_SHOW_WARNING)) or
                (severity == ERROR and preferences.get(DEBUG_SHOW_ERROR))):
            timestamp = (DEBUG_FORMAT_TIMESTAMP.format(datetime.datetime.now())
                         if preferences.get(DEBUG_TIMESTAMP) else '')
            self.add_text(DEBUG_FORMAT.format(timestamp=timestamp,
                                              severity=severity,
                                              text=text))

    def add_info(self, text):
        """Add a text line to the debug buffer with severity info"""
        self.add_line(INFO, text)

    def add_warning(self, text):
        """Add a text line to the debug buffer with severity warning"""
        self.add_line(WARNING, text)

    def add_error(self, text):
        """Add a text line to the debug buffer with severity error"""
        self.add_line(ERROR, text)

    def on_action_clear_activate(self, action):
        """Clear the debug text"""
        self.clear()

    def on_action_set_debug_flag(self, action):
        """Enable/disable various debug flags"""
        for key in self.actions_preferences:
            if action is self.actions_preferences[key]:
                preferences.set(key, action.get_active())
                break
class UIServiceDetail(object):
    def __init__(self, parent, services):
        """Prepare the services detail dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('service_detail.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_edit_service.set_transient_for(parent)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.model = services
        self.selected_iter = None
        self.name = ''
        self.description = ''
        self.command = '[]'
        self.terminal = False
        self.icon = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_name, default_description, default_command,
             default_terminal, default_icon, title, treeiter):
        """Show the Services detail dialog"""
        self.ui.txt_name.set_text(default_name)
        self.ui.txt_description.set_text(default_description)
        self.ui.txt_command.set_text(default_command)
        self.ui.chk_terminal.set_active(default_terminal)
        self.ui.txt_icon.set_text(default_icon)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_edit_service.set_title(title)
        self.selected_iter = treeiter
        response = self.ui.dialog_edit_service.run()
        self.ui.dialog_edit_service.hide()
        self.name = self.ui.txt_name.get_text().strip()
        self.description = self.ui.txt_description.get_text().strip()
        self.command = self.ui.txt_command.get_text().strip()
        self.terminal = self.ui.chk_terminal.get_active()
        self.icon = self.ui.txt_icon.get_text().strip()
        return response

    def destroy(self):
        """Destroy the Services dialog"""
        self.ui.dialog_edit_service.destroy()
        self.ui.dialog_edit_service = None

    def on_action_confirm_activate(self, action):
        """Check che service configuration before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(widget=widget,
                                         widgets=(self.ui.txt_name,
                                                  self.ui.txt_description,
                                                  self.ui.txt_command),
                                         label=self.ui.lbl_error_message,
                                         infobar=self.ui.infobar_error_message,
                                         error_msg=error_msg)

        name = self.ui.txt_name.get_text().strip()
        description = self.ui.txt_description.get_text().strip()
        command = self.ui.txt_command.get_text().strip()
        terminal = self.ui.chk_terminal.get_active()
        icon = self.ui.txt_icon.get_text().strip()
        if len(name) == 0:
            # Show error for missing service name
            show_error_message_on_infobar(self.ui.txt_name,
                                          _('The service name is missing'))
        elif '\'' in name or '\\' in name or '/' in name or ',' in name:
            # Show error for invalid service name
            show_error_message_on_infobar(self.ui.txt_name,
                                          _('The service name is invalid'))
        elif self.model.get_iter(name) not in (None, self.selected_iter):
            # Show error for existing service name
            show_error_message_on_infobar(
                self.ui.txt_name, _('A service with that name already exists'))
        elif len(description) == 0:
            # Show error for missing service description
            show_error_message_on_infobar(
                self.ui.txt_description,
                _('The service description is missing'))
        elif '\'' in description or '\\' in description:
            # Show error for invalid service description
            show_error_message_on_infobar(
                self.ui.txt_description,
                _('The service description is invalid'))
        elif len(command) == 0:
            # Show error for missing service description
            show_error_message_on_infobar(self.ui.txt_command,
                                          _('The service command is missing'))
        elif len(icon) > 0 and not os.path.isfile(icon):
            # Show error for missing service description
            show_error_message_on_infobar(
                self.ui.txt_icon, _('The service icon doesn'
                                    't exists'))
        else:
            self.ui.dialog_edit_service.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_name_changed(self, widget):
        """Check the service name field"""
        check_invalid_input(widget, False, False, False)

    def on_txt_description_changed(self, widget):
        """Check the service description field"""
        check_invalid_input(widget, False, True, False)

    def on_txt_icon_changed(self, widget):
        """Check the icon field"""
        text = widget.get_text().strip()
        if len(text) > 0 and os.path.isfile(text):
            icon_size = preferences.get(preferences.ICON_SIZE)
            self.ui.image_icon.set_from_pixbuf(
                GdkPixbuf.Pixbuf.new_from_file_at_size(text, icon_size,
                                                       icon_size))
            icon_name = None
        else:
            icon_name = 'dialog-error' if len(text) > 0 else None
            self.ui.image_icon.set_from_icon_name('image-missing',
                                                  Gtk.IconSize.LARGE_TOOLBAR)
        widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY,
                                       icon_name)

    def on_action_browse_icon_activate(self, action):
        """Browse for an icon file"""
        def update_preview_cb(widget, image, get_preview_filename, set_active):
            """Update preview by trying to load the image"""
            try:
                # Try to load the image from the previewed file
                image.set_from_pixbuf(
                    GdkPixbuf.Pixbuf.new_from_file_at_size(
                        get_preview_filename(),
                        preferences.get(preferences.PREVIEW_SIZE),
                        preferences.get(preferences.PREVIEW_SIZE)))
                set_active(True)
            except:
                # Hide the preview widget for errors
                image.set_from_pixbuf(None)
                set_active(False)

        # Prepare the browse for icon dialog
        dialog = UIFileChooserOpenFile(self.ui.dialog_edit_service,
                                       text("Select a File"))
        dialog.add_filter(_("All Image Files"), "image/*", None)
        dialog.add_filter(_("All Files"), None, "*")
        dialog.set_filename(self.ui.txt_icon.get_text())
        # Set the image preview widget
        image_preview = Gtk.Image()
        image_preview.set_hexpand(False)
        image_preview.set_size_request(
            preferences.get(preferences.PREVIEW_SIZE), -1)
        dialog.set_preview_widget(image_preview, update_preview_cb)
        # Show the browse for icon dialog
        filename = dialog.show()
        if filename is not None:
            self.ui.txt_icon.set_text(filename)
        dialog.destroy()

    def on_action_configure_activate(self, action):
        """Configure the arguments list"""
        dialog = UICommandArguments(self.ui.dialog_edit_service)
        dialog.show(default_command=self.ui.txt_command.get_text())
        self.ui.txt_command.set_text(dialog.arguments)
示例#25
0
class UIGroups(object):
    def __init__(self, parent):
        """Prepare the groups dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('groups.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_groups.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_groups,
                                                   SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the groups
        self.model = ModelGroups(self.ui.store_groups)
        self.selected_iter = None
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(), Gtk.SortType.ASCENDING)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Groups dialog"""
        self.ui.dialog_groups.run()
        self.ui.dialog_groups.hide()

    def destroy(self):
        """Destroy the Groups dialog"""
        settings.positions.save_window_position(self.ui.dialog_groups,
                                                SECTION_WINDOW_NAME)
        self.ui.dialog_groups.destroy()
        self.ui.dialog_groups = None

    def on_action_add_activate(self, action):
        """Add a new group"""
        dialog = UIGroupDetail(self.ui.dialog_groups, self.model)
        if dialog.show(default_name='',
                       title=_('Add new group'),
                       treeiter=None) == Gtk.ResponseType.OK:
            os.mkdir(os.path.join(DIR_HOSTS, dialog.name))
            self.model.add_data(
                GroupInfo(name=dialog.name, description=dialog.name))
            debug.add_info(_('Added a new group "%s"') % dialog.name)
        dialog.destroy()

    def on_action_remove_activate(self, action):
        """Remove the selected group"""
        selected_row = get_treeview_selected_row(self.ui.tvw_groups)
        group_name = self.model.get_key(selected_row) if selected_row else ''
        if selected_row and group_name and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_groups,
                message_type=Gtk.MessageType.WARNING,
                title=None,
                msg1=_('Remove the group'),
                msg2=_('Remove the group «%s»?') % group_name,
                is_response_id=Gtk.ResponseType.YES):
            group_path = os.path.join(DIR_HOSTS, group_name)
            # Check for directory not empty
            if len(os.listdir(group_path)) and not show_message_dialog(
                    class_=UIMessageDialogNoYes,
                    parent=self.ui.dialog_groups,
                    message_type=Gtk.MessageType.WARNING,
                    title=None,
                    msg1=_('The group is not empty'),
                    msg2='%s\n%s\n\n%s' % (
                        text('If you delete an item, it will '
                             'be permanently lost.'),
                        _('All the hosts defined for the group will be lost.'),
                        _('Are you sure you want to delete the '
                          'group «%s»?') % group_name,
                    ),
                    is_response_id=Gtk.ResponseType.YES):
                # Exit immediately without deleting the group
                return
            # Delete all the contained files and the directory for the group
            for filename in os.listdir(group_path):
                os.remove(os.path.join(group_path, filename))
            os.rmdir(group_path)
            debug.add_info(_('Removed the group "%s"') % group_name)
            self.model.remove(selected_row)
示例#26
0
class UIDestination(object):
    def __init__(self, parent, destinations):
        """Prepare the destination dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('destination.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_destination.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_destination,
                                                   SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.model = destinations
        self.selected_iter = None
        self.name = ''
        self.value = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_name, default_value, title, treeiter):
        """Show the destination dialog"""
        self.ui.txt_name.set_text(default_name)
        self.ui.txt_value.set_text(default_value)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_destination.set_title(title)
        self.selected_iter = treeiter
        response = self.ui.dialog_destination.run()
        self.ui.dialog_destination.hide()
        self.name = self.ui.txt_name.get_text().strip()
        self.value = self.ui.txt_value.get_text().strip()
        return response

    def destroy(self):
        """Destroy the destination dialog"""
        settings.positions.save_window_position(self.ui.dialog_destination,
                                                SECTION_WINDOW_NAME)
        self.ui.dialog_destination.destroy()
        self.ui.dialog_destination = None

    def on_action_confirm_activate(self, action):
        """Check the destination configuration before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(widget=widget,
                                         widgets=(self.ui.txt_name,
                                                  self.ui.txt_value),
                                         label=self.ui.lbl_error_message,
                                         infobar=self.ui.infobar_error_message,
                                         error_msg=error_msg)

        name = self.ui.txt_name.get_text().strip()
        value = self.ui.txt_value.get_text().strip()
        if len(name) == 0:
            # Show error for missing destination name
            show_error_message_on_infobar(self.ui.txt_name,
                                          _('The destination name is missing'))
        elif '\'' in name or '\\' in name:
            # Show error for invalid destination name
            show_error_message_on_infobar(self.ui.txt_name,
                                          _('The destination name is invalid'))
        elif self.model.get_iter(name) not in (None, self.selected_iter):
            # Show error for existing destination name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('A destination with that name already exists'))
        elif len(value) == 0:
            # Show error for missing destination value
            show_error_message_on_infobar(
                self.ui.txt_value, _('The destination value is missing'))
        else:
            self.ui.dialog_destination.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_name_changed(self, widget):
        """Check the destination name field"""
        check_invalid_input(widget, False, False, False)
示例#27
0
class UIDestination(object):
    def __init__(self, parent, destinations):
        """Prepare the destination dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('destination.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_destination.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_destination, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.model = destinations
        self.selected_iter = None
        self.name = ''
        self.value = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_name, default_value, title, treeiter):
        """Show the destination dialog"""
        self.ui.txt_name.set_text(default_name)
        self.ui.txt_value.set_text(default_value)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_destination.set_title(title)
        self.selected_iter = treeiter
        response = self.ui.dialog_destination.run()
        self.ui.dialog_destination.hide()
        self.name = self.ui.txt_name.get_text().strip()
        self.value = self.ui.txt_value.get_text().strip()
        return response

    def destroy(self):
        """Destroy the destination dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_destination, SECTION_WINDOW_NAME)
        self.ui.dialog_destination.destroy()
        self.ui.dialog_destination = None

    def on_action_confirm_activate(self, action):
        """Check the destination configuration before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(
                widget=widget,
                widgets=(self.ui.txt_name, self.ui.txt_value),
                label=self.ui.lbl_error_message,
                infobar=self.ui.infobar_error_message,
                error_msg=error_msg)
        name = self.ui.txt_name.get_text().strip()
        value = self.ui.txt_value.get_text().strip()
        if len(name) == 0:
            # Show error for missing destination name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The destination name is missing'))
        elif '\'' in name or '\\' in name:
            # Show error for invalid destination name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The destination name is invalid'))
        elif self.model.get_iter(name) not in (None, self.selected_iter):
            # Show error for existing destination name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('A destination with that name already exists'))
        elif len(value) == 0:
            # Show error for missing destination value
            show_error_message_on_infobar(
                self.ui.txt_value,
                _('The destination value is missing'))
        else:
            self.ui.dialog_destination.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_name_changed(self, widget):
        """Check the destination name field"""
        check_invalid_input(widget, False, False, False)
示例#28
0
class UICommandArgument(object):
    def __init__(self, parent):
        """Prepare the argument dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('command_argument.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_argument.set_transient_for(parent)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.argument = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_value):
        """Show the command argument dialog"""
        self.ui.txt_argument.set_text(default_value)
        self.ui.txt_argument.grab_focus()
        response = self.ui.dialog_argument.run()
        self.ui.dialog_argument.hide()
        self.argument = self.ui.txt_argument.get_text().strip()
        return response

    def destroy(self):
        """Destroy the command argument dialog"""
        self.ui.dialog_argument.destroy()
        self.ui.dialog_argument = None

    def on_action_confirm_activate(self, action):
        """Check che argument before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(widget=widget,
                                         widgets=(self.ui.txt_argument, ),
                                         label=self.ui.lbl_error_message,
                                         infobar=self.ui.infobar_error_message,
                                         error_msg=error_msg)

        if len(self.ui.txt_argument.get_text().strip()) == 0:
            # Show error for missing argument
            show_error_message_on_infobar(self.ui.txt_argument,
                                          _('The argument is missing'))
        else:
            self.ui.dialog_argument.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_argument_changed(self, widget):
        """Check the argument value field"""
        check_invalid_input(widget, False, True, True)
示例#29
0
class UIGroups(object):
    def __init__(self, parent):
        """Prepare the groups dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('groups.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_groups.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_groups, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the groups
        self.model = ModelGroups(self.ui.store_groups)
        self.selected_iter = None
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Groups dialog"""
        self.ui.dialog_groups.run()
        self.ui.dialog_groups.hide()

    def destroy(self):
        """Destroy the Groups dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_groups, SECTION_WINDOW_NAME)
        self.ui.dialog_groups.destroy()
        self.ui.dialog_groups = None

    def on_action_add_activate(self, action):
        """Add a new group"""
        dialog = UIGroupDetail(self.ui.dialog_groups, self.model)
        if dialog.show(default_name='',
                       title=_('Add new group'),
                       treeiter=None) == Gtk.ResponseType.OK:
            os.mkdir(os.path.join(DIR_HOSTS, dialog.name))
            self.model.add_data(GroupInfo(name=dialog.name,
                                          description=dialog.name))
            debug.add_info(_('Added a new group "%s"') % dialog.name)
        dialog.destroy()

    def on_action_remove_activate(self, action):
        """Remove the selected group"""
        selected_row = get_treeview_selected_row(self.ui.tvw_groups)
        group_name = self.model.get_key(selected_row) if selected_row else ''
        if selected_row and group_name and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_groups,
                message_type=Gtk.MessageType.WARNING,
                title=None,
                msg1=_('Remove the group'),
                msg2=_('Remove the group «%s»?') % group_name,
                is_response_id=Gtk.ResponseType.YES):
            group_path = os.path.join(DIR_HOSTS, group_name)
            # Check for directory not empty
            if len(os.listdir(group_path)) and not show_message_dialog(
                    class_=UIMessageDialogNoYes,
                    parent=self.ui.dialog_groups,
                    message_type=Gtk.MessageType.WARNING,
                    title=None,
                    msg1=_('The group is not empty'),
                    msg2='%s\n%s\n\n%s' % (
                        text('If you delete an item, it will '
                             'be permanently lost.'),
                        _('All the hosts defined for the group will be lost.'),
                        _('Are you sure you want to delete the '
                          'group «%s»?') % group_name,
                                       ),
                    is_response_id=Gtk.ResponseType.YES):
                # Exit immediately without deleting the group
                return
            # Delete all the contained files and the directory for the group
            for filename in os.listdir(group_path):
                os.remove(os.path.join(group_path, filename))
            os.rmdir(group_path)
            debug.add_info(_('Removed the group "%s"') % group_name)
            self.model.remove(selected_row)
示例#30
0
class UICommandArguments(object):
    def __init__(self, parent):
        """Prepare the command arguments dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file("command_arguments.glade"))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_arguments.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_arguments, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace("_", ""))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the arguments
        self.model_arguments = self.ui.store_arguments
        self.arguments = "[]"
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_command):
        """Show the command arguments dialog"""
        arguments = get_list_from_string_list(default_command)
        for argument in arguments:
            self.model_arguments.append((argument,))
        self.ui.dialog_arguments.run()
        self.ui.dialog_arguments.hide()
        arguments = []
        for treeiter in self.model_arguments:
            arguments.append(self.model_arguments[treeiter.path][0])
        self.arguments = json.dumps(arguments)

    def destroy(self):
        """Destroy the command arguments dialog"""
        settings.positions.save_window_position(self.ui.dialog_arguments, SECTION_WINDOW_NAME)
        self.ui.dialog_arguments.destroy()
        self.ui.dialog_arguments = None

    def on_action_add_activate(self, action):
        """Add a new argument"""
        dialog = UICommandArgument(self.ui.dialog_arguments)
        if dialog.show(default_value="") == Gtk.ResponseType.OK:
            self.model_arguments.append((dialog.argument,))
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Edit the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_arguments)
        if selected_row:
            argument = self.model_arguments[selected_row][0]
            dialog = UICommandArgument(self.ui.dialog_arguments)
            if dialog.show(default_value=argument) == Gtk.ResponseType.OK:
                # Update values
                self.model_arguments.set_value(selected_row, 0, dialog.argument)
            dialog.destroy()

    def on_action_remove_activate(self, action):
        """Remove the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_arguments)
        if selected_row and show_message_dialog(
            class_=UIMessageDialogNoYes,
            parent=self.ui.dialog_arguments,
            message_type=Gtk.MessageType.WARNING,
            title=None,
            msg1=_("Remove argument"),
            msg2=_("Remove the selected argument?"),
            is_response_id=Gtk.ResponseType.YES,
        ):
            self.model_arguments.remove(selected_row)

    def on_tvw_arguments_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_edit.activate()
class UIServiceAssociation(object):
    def __init__(self, parent, destinations):
        """Prepare the service association dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('service_association.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_association.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_association, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Load destinations
        self.destinations = destinations
        self.ui.cbo_destinations.set_model(self.destinations.model)
        # Load services
        self.services = ModelServices(self.ui.store_services)
        self.services.load(model_services.services)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)
        self.service_arguments_widgets = {}

    def show(self, default_description, default_destination, default_service,
             default_arguments):
        """Show the Service association dialog"""
        # Set default description
        self.ui.entry_description.set_text(default_description)
        # Set default destination
        if default_destination:
            self.ui.cbo_destinations.set_active_id(default_destination)
        elif self.destinations.count() > 0:
            self.ui.cbo_destinations.set_active(0)
        # Set default service
        if default_service:
            self.ui.cbo_services.set_active_id(default_service)
        elif self.services.count() > 0:
            self.ui.cbo_services.set_active(0)
        # Set default arguments
        for argument in self.service_arguments_widgets:
            (new_label, new_entry) = self.service_arguments_widgets[argument]
            if argument in default_arguments:
                new_entry.set_text(default_arguments[argument])
        # Show the dialog
        response = self.ui.dialog_association.run()
        self.ui.dialog_association.hide()
        self.destination = self.ui.cbo_destinations.get_active_id()
        self.service = self.ui.cbo_services.get_active_id()
        self.description = self.ui.entry_description.get_text()
        # Prepares argument values
        self.arguments = {}
        for argument in self.service_arguments_widgets:
            (new_label, new_entry) = self.service_arguments_widgets[argument]
            self.arguments[argument] = new_entry.get_text()
        return response

    def destroy(self):
        """Destroy the Service association dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_association, SECTION_WINDOW_NAME)
        self.ui.dialog_association.destroy()
        self.ui.dialog_association = None

    def on_cbo_services_changed(self, widget):
        """Update the service arguments widgets"""
        treeiter = self.ui.cbo_services.get_active_iter()
        # Remove the previously added arguments widgets
        for argument in self.service_arguments_widgets:
            (new_label, new_entry) = self.service_arguments_widgets[argument]
            new_label.destroy()
            new_entry.destroy()
        self.service_arguments_widgets = {}
        # Collect the needed arguments
        command = get_list_from_string_list(
            self.services.get_command(treeiter))
        row_number = 0
        processed_arguments = []
        # The argument address, already has a default widget
        processed_arguments.append('address')
        for option in command:
            arguments = get_string_fields(option)
            # Add a pair of widgets for each argument
            for argument in arguments:
                # Skip existing arguments
                if argument in processed_arguments:
                    continue
                row_number += 1
                processed_arguments.append(argument)
                # Add a new descriptive label for the argument
                new_label = Gtk.Label('%s:' % argument.title())
                new_label.set_xalign(1.0)
                new_label.set_visible(True)
                self.ui.grid_service_arguments.attach(child=new_label,
                                                      left=0,
                                                      top=row_number,
                                                      width=1,
                                                      height=1)
                # Add a new entry for the argument value
                new_entry = Gtk.Entry()
                new_entry.set_visible(True)
                new_entry.set_hexpand(True)
                self.ui.grid_service_arguments.attach(child=new_entry,
                                                      left=1,
                                                      top=row_number,
                                                      width=1,
                                                      height=1)
                # Save a tuple of widgets, to remove later
                self.service_arguments_widgets[argument] = (
                    new_label, new_entry)

    def on_cbo_destinations_changed(self, widget):
        """Update the address entry for the selected destination"""
        treeiter = self.ui.cbo_destinations.get_active_iter()
        self.ui.entry_service_arguments_address.set_text(
            self.destinations.get_value(treeiter))
示例#32
0
class UIHost(object):
    def __init__(self, parent, hosts):
        """Prepare the host dialog"""
        self.hosts = hosts
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('host.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_host.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_host, SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the destinations
        self.model_destinations = ModelDestinations(self.ui.store_destinations)
        self.model_associations = ModelAssociations(self.ui.store_associations)
        self.selected_iter = None
        # Sort the data in the models
        self.model_destinations.model.set_sort_column_id(
            self.ui.column_destinations_name.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_name, default_description, title, treeiter):
        """Show the destinations dialog"""
        self.ui.txt_name.set_text(default_name)
        self.ui.txt_description.set_text(default_description)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_host.set_title(title)
        self.selected_iter = treeiter
        self.model_associations.model.set_sort_column_id(
            self.ui.column_associations_destination.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        # Show the dialog
        response = self.ui.dialog_host.run()
        self.ui.dialog_host.hide()
        self.name = self.ui.txt_name.get_text().strip()
        self.description = self.ui.txt_description.get_text().strip()
        return response

    def destroy(self):
        """Destroy the destinations dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_host, SECTION_WINDOW_NAME)
        self.ui.dialog_host.destroy()
        self.ui.dialog_host = None

    def on_action_destinations_add_activate(self, action):
        """Add a new destination"""
        dialog = UIDestination(self.ui.dialog_host, self.model_destinations)
        if dialog.show(default_name='',
                       default_value='',
                       title=_('Add new destination'),
                       treeiter=None) == Gtk.ResponseType.OK:
            self.model_destinations.add_data(
                DestinationInfo(name=dialog.name, value=dialog.value))
        # Get the new destinations list, clear and store the list again
        dialog.destroy()

    def on_action_destinations_edit_activate(self, action):
        """Edit the selected destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_destinations)
        if selected_row:
            name = self.model_destinations.get_key(selected_row)
            value = self.model_destinations.get_value(selected_row)
            selected_iter = self.model_destinations.get_iter(name)
            dialog = UIDestination(self.ui.dialog_host,
                                   self.model_destinations)
            if dialog.show(default_name=name,
                           default_value=value,
                           title=_('Edit destination'),
                           treeiter=selected_iter
                           ) == Gtk.ResponseType.OK:
                # Update values
                self.model_destinations.set_data(
                    selected_iter, DestinationInfo(name=dialog.name,
                                                   value=dialog.value))
            dialog.destroy()

    def on_action_destinations_remove_activate(self, action):
        """Remove the selected destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_destinations)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_host,
                message_type=Gtk.MessageType.QUESTION,
                title=None,
                msg1=_("Remove destination"),
                msg2=_("Remove the selected destination?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model_destinations.remove(selected_row)

    def on_tvw_destinations_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_destinations_edit.activate()

    def on_action_confirm_activate(self, action):
        """Check che host configuration before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(
                widget=widget,
                widgets=(self.ui.txt_name, self.ui.txt_description),
                label=self.ui.lbl_error_message,
                infobar=self.ui.infobar_error_message,
                error_msg=error_msg)
        name = self.ui.txt_name.get_text().strip()
        description = self.ui.txt_description.get_text().strip()
        if len(name) == 0:
            # Show error for missing host name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The host name is missing'))
        elif '\'' in name or '\\' in name or '/' in name:
            # Show error for invalid host name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The host name is invalid'))
        elif self.hosts.get_iter(name) not in (None, self.selected_iter):
            # Show error for existing host name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('A host with that name already exists'))
        elif len(description) == 0:
            # Show error for missing host description
            show_error_message_on_infobar(
                self.ui.txt_description,
                _('The host description is missing'))
        else:
            self.ui.dialog_host.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_name_changed(self, widget):
        """Check the host name field"""
        check_invalid_input(widget, False, False, False)

    def on_txt_description_changed(self, widget):
        """Check the host description field"""
        check_invalid_input(widget, False, True, True)

    def on_notebook_switch_page(self, widget, children, number):
        """Disable GtkActionGroup on page change"""
        self.ui.actions_destinations.set_sensitive(number == 0)
        self.ui.actions_associations.set_sensitive(number != 0)

    def on_action_tab_page_activate(self, action):
        """Switch GtkNotebook page on GtkAction activation"""
        self.ui.notebook.set_current_page(
            0 if action is self.ui.action_tab_page1 else 1)

    def on_action_associations_add_activate(self, action):
        """Add a new service association"""
        dialog = UIServiceAssociation(self.ui.dialog_host,
                                      self.model_destinations)
        if dialog.show('', None, None) == Gtk.ResponseType.OK:
            self.model_associations.add_data(
                self.model_associations.count() + 1,
                dialog.destination,
                dialog.description,
                model_services.services[dialog.service],
                dialog.arguments)
        dialog.destroy()

    def on_action_associations_remove_activate(self, action):
        """Remove the selected destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_associations)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_host,
                message_type=Gtk.MessageType.QUESTION,
                title=None,
                msg1=_("Remove association"),
                msg2=_("Remove the selected association?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model_associations.remove(selected_row)

    def on_action_associations_edit_activate(self, action):
        """Edit the selected service association"""
        selected_row = get_treeview_selected_row(self.ui.tvw_associations)
        if selected_row:
            dialog = UIServiceAssociation(self.ui.dialog_host,
                                          self.model_destinations)
            model = self.model_associations
            selected_key = model.get_key(selected_row)
            selected_iter = model.get_iter(selected_key)
            if dialog.show(
                    model.get_description(selected_row),
                    model.get_destination_name(selected_row),
                    model.get_service_name(selected_row),
                    json.loads(model.get_arguments(selected_row))
                    ) == Gtk.ResponseType.OK:
                model.set_data(
                    treeiter=selected_iter,
                    description=dialog.description,
                    destination_name=dialog.destination,
                    service=model_services.services[dialog.service],
                    arguments=dialog.arguments)
            dialog.destroy()

    def on_tvw_associations_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_associations_edit.activate()
示例#33
0
class UIMain(object):
    def __init__(self, application):
        self.application = application
        # Load settings
        settings.settings = settings.Settings(FILE_SETTINGS, False)
        settings.positions = settings.Settings(FILE_WINDOWS_POSITION, False)
        settings.services = settings.Settings(FILE_SERVICES, False)
        preferences.preferences = preferences.Preferences()
        # Load services
        for key in settings.services.get_sections():
            model_services.services[key] = ServiceInfo(
                name=key,
                description=settings.services.get(key,
                                                  OPTION_SERVICE_DESCRIPTION),
                command=settings.services.get(key, OPTION_SERVICE_COMMAND),
                terminal=settings.services.get_boolean(
                    key, OPTION_SERVICE_TERMINAL),
                icon=settings.services.get(key, OPTION_SERVICE_ICON))
        self.loadUI()
        self.model_hosts = ModelHosts(self.ui.store_hosts)
        self.model_groups = ModelGroups(self.ui.store_groups)
        # Prepare the debug dialog
        debug.debug = debug.UIDebug(self.ui.win_main,
                                    self.on_window_debug_delete_event)
        # Prepare the processes dialog
        processes.processes = processes.UIProcesses(
            self.ui.win_main, self.on_window_processes_delete_event)
        # Load the groups and hosts list
        self.hosts = {}
        self.reload_groups()
        # Sort the data in the models
        self.model_groups.model.set_sort_column_id(
            self.ui.column_group.get_sort_column_id(), Gtk.SortType.ASCENDING)
        self.model_hosts.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(), Gtk.SortType.ASCENDING)
        # Automatically select the first host if any
        self.ui.tvw_groups.set_cursor(0)
        if self.model_hosts.count() > 0:
            self.ui.tvw_connections.set_cursor(0)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.win_main,
                                                   SECTION_WINDOW_NAME)

    def loadUI(self):
        """Load the interface UI"""
        self.ui = GtkBuilderLoader(get_ui_file('main.glade'))
        self.ui.win_main.set_application(self.application)
        self.ui.win_main.set_title(APP_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.ToolButton):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Set list items row height
        icon_size = preferences.ICON_SIZE
        self.ui.cell_name.props.height = preferences.get(icon_size)
        self.ui.cell_group_name.props.height = preferences.get(icon_size)
        # Set groups visibility
        self.ui.scroll_groups.set_visible(
            preferences.get(preferences.GROUPS_SHOW))
        # Add a Gtk.Headerbar, only for GTK+ 3.10.0 and higher
        if (not Gtk.check_version(3, 10, 0)
                and not preferences.get(preferences.HEADERBARS_DISABLE)):
            self.load_ui_headerbar()
            if preferences.get(preferences.HEADERBARS_REMOVE_TOOLBAR):
                # This is only for development, it should always be True
                # Remove the redundant toolbar
                self.ui.toolbar_main.destroy()
            # Flatten the Gtk.ScrolledWindows
            self.ui.scroll_groups.set_shadow_type(Gtk.ShadowType.NONE)
            self.ui.scroll_connections.set_shadow_type(Gtk.ShadowType.NONE)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def load_ui_headerbar(self):
        """Add a Gtk.HeaderBar to the window with buttons"""
        def create_button_from_action(action):
            """Create a new Gtk.Button from a Gtk.Action"""
            if isinstance(action, Gtk.ToggleAction):
                new_button = Gtk.ToggleButton()
            else:
                new_button = Gtk.Button()
            new_button.set_use_action_appearance(False)
            new_button.set_related_action(action)
            # Use icon from the action
            icon_name = action.get_icon_name()
            if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS):
                icon_name += '-symbolic'
            # Get desired icon size
            icon_size = (Gtk.IconSize.BUTTON
                         if preferences.get(preferences.HEADERBARS_SMALL_ICONS)
                         else Gtk.IconSize.LARGE_TOOLBAR)
            new_button.set_image(
                Gtk.Image.new_from_icon_name(icon_name, icon_size))
            # Set the tooltip from the action label
            new_button.set_tooltip_text(action.get_label().replace('_', ''))
            return new_button

        # Add the Gtk.HeaderBar
        header_bar = Gtk.HeaderBar()
        header_bar.props.title = self.ui.win_main.get_title()
        header_bar.set_show_close_button(True)
        self.ui.win_main.set_titlebar(header_bar)
        # Add buttons to the left side
        for action in (self.ui.action_new, self.ui.action_edit,
                       self.ui.action_copy, self.ui.action_connect,
                       self.ui.action_delete):
            header_bar.pack_start(create_button_from_action(action))
        # Add buttons to the right side (in reverse order)
        for action in reversed((self.ui.action_services, self.ui.action_groups,
                                self.ui.action_debug, self.ui.action_processes,
                                self.ui.action_about)):
            header_bar.pack_end(create_button_from_action(action))

    def run(self):
        """Show the UI"""
        self.ui.win_main.show_all()

    def on_win_main_delete_event(self, widget, event):
        """Save the settings and close the application"""
        debug.debug.destroy()
        processes.processes.destroy()
        settings.positions.save_window_position(self.ui.win_main,
                                                SECTION_WINDOW_NAME)
        settings.positions.save()
        settings.services.save()
        settings.settings.save()
        self.application.quit()

    def on_action_about_activate(self, action):
        """Show the about dialog"""
        dialog = UIAbout(self.ui.win_main)
        dialog.show()
        dialog.destroy()

    def on_action_quit_activate(self, action):
        """Close the application by closing the main window"""
        event = Gdk.Event()
        event.key.type = Gdk.EventType.DELETE
        self.ui.win_main.event(event)

    def on_action_services_activate(self, action):
        """Edit services"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if selected_row:
            iter_parent = self.ui.store_hosts.iter_parent(selected_row)
            selected_path = self.model_hosts.model[selected_row].path
            # Get the path of the host
            if iter_parent is None:
                tree_path = self.model_hosts.model[selected_row].path
            else:
                tree_path = self.model_hosts.model[iter_parent].path
            expanded = self.ui.tvw_connections.row_expanded(tree_path)
        dialog_services = UIServices(parent=self.ui.win_main)
        # Load services list
        dialog_services.model.load(model_services.services)
        dialog_services.show()
        # Get the new services list, clear and store the list again
        model_services.services = dialog_services.model.dump()
        dialog_services.destroy()
        settings.services.clear()
        for key in model_services.services.iterkeys():
            settings.services.set(
                section=key,
                option=OPTION_SERVICE_DESCRIPTION,
                value=model_services.services[key].description)
            settings.services.set(section=key,
                                  option=OPTION_SERVICE_COMMAND,
                                  value=model_services.services[key].command)
            settings.services.set_boolean(
                section=key,
                option=OPTION_SERVICE_TERMINAL,
                value=model_services.services[key].terminal)
            settings.services.set(section=key,
                                  option=OPTION_SERVICE_ICON,
                                  value=model_services.services[key].icon)
        self.reload_hosts()
        if selected_row:
            # Automatically expand the row if it was expanded before
            if expanded:
                self.ui.tvw_connections.expand_row(tree_path, True)
            # Automatically select again the previously selected row
            self.ui.tvw_connections.set_cursor(path=selected_path,
                                               column=None,
                                               start_editing=False)

    def reload_hosts(self):
        """Load hosts from the settings files"""
        self.model_hosts.clear()
        self.hosts.clear()
        hosts_path = self.get_current_group_path()
        # Fix bug where the groups model isn't yet emptied, resulting in
        # being still used after a clear, then an invalid path
        if not os.path.isdir(hosts_path):
            return
        for filename in os.listdir(hosts_path):
            # Skip folders, used for groups
            if os.path.isdir(os.path.join(hosts_path, filename)):
                continue
            debug.add_info('Loading host %s' %
                           os.path.join(hosts_path, filename))
            settings_host = settings.Settings(filename=os.path.join(
                hosts_path, filename),
                                              case_sensitive=True)
            name = settings_host.get(SECTION_HOST, OPTION_HOST_NAME)
            description = settings_host.get(SECTION_HOST,
                                            OPTION_HOST_DESCRIPTION)
            host = HostInfo(name=name, description=description)
            destinations = {}
            # Load host destinations
            if SECTION_DESTINATIONS in settings_host.get_sections():
                for option in settings_host.get_options(SECTION_DESTINATIONS):
                    value = settings_host.get(SECTION_DESTINATIONS, option)
                    destinations[option] = DestinationInfo(name=option,
                                                           value=value)
            # Load associations
            association_index = 1
            associations_count = settings_host.get_int(
                section=SECTION_HOST, option=OPTION_HOST_ASSOCIATIONS)
            while association_index <= associations_count:
                section = '%s %d' % (SECTION_ASSOCIATION, association_index)
                host.add_association(
                    description=settings_host.get(
                        section=section,
                        option=OPTION_ASSOCIATION_DESCRIPTION),
                    destination_name=settings_host.get(
                        section=section,
                        option=OPTION_ASSOCIATION_DESTINATION),
                    service_name=settings_host.get(
                        section=section, option=OPTION_ASSOCIATION_SERVICE),
                    arguments=json.loads(
                        settings_host.get(
                            section=section,
                            option=OPTION_ASSOCIATION_ARGUMENTS)))
                association_index += 1
            self.add_host(host, destinations, False)

    def add_host(self, host, destinations, update_settings):
        """Add a new host along as with its destinations"""
        # Add the host to the data and to the model
        self.hosts[host.name] = host
        treeiter = self.model_hosts.add_data(host)
        # Add the destinations to the data
        for destination_name in destinations:
            destination = destinations[destination_name]
            host.add_destination(item=destination)
        # Add service associations to the model
        for association in host.associations:
            description = association.description
            service_name = association.service_name
            service_arguments = json.dumps(association.service_arguments)
            destination = destinations[association.destination_name]
            if service_name in model_services.services:
                service = model_services.services[service_name]
                self.model_hosts.add_association(treeiter=treeiter,
                                                 description=description,
                                                 destination=destination,
                                                 service=service,
                                                 arguments=service_arguments)
            else:
                debug.add_warning('service %s not found' % service_name)
        # Update settings file if requested
        if update_settings:
            hosts_path = self.get_current_group_path()
            settings_host = settings.Settings(filename=os.path.join(
                hosts_path, '%s.conf' % host.name),
                                              case_sensitive=True)
            # Add host information
            settings_host.set(SECTION_HOST, OPTION_HOST_NAME, host.name)
            settings_host.set(SECTION_HOST, OPTION_HOST_DESCRIPTION,
                              host.description)
            # Add destinations
            for key in host.destinations:
                destination = host.destinations[key]
                settings_host.set(section=SECTION_DESTINATIONS,
                                  option=destination.name,
                                  value=destination.value)
            association_index = 0
            for association in host.associations:
                arguments = json.dumps(association.service_arguments)
                # Add associations to the settings
                association_index += 1
                section = '%s %d' % (SECTION_ASSOCIATION, association_index)
                settings_host.set(section=section,
                                  option=OPTION_ASSOCIATION_DESCRIPTION,
                                  value=association.description)
                settings_host.set(section=section,
                                  option=OPTION_ASSOCIATION_DESTINATION,
                                  value=association.destination_name)
                settings_host.set(section=section,
                                  option=OPTION_ASSOCIATION_SERVICE,
                                  value=association.service_name)
                settings_host.set(section=section,
                                  option=OPTION_ASSOCIATION_ARGUMENTS,
                                  value=arguments)
            settings_host.set_int(section=SECTION_HOST,
                                  option=OPTION_HOST_ASSOCIATIONS,
                                  value=association_index)
            # Save the settings to the file
            settings_host.save()

    def remove_host(self, name):
        """Remove a host by its name"""
        hosts_path = self.get_current_group_path()
        filename = os.path.join(hosts_path, '%s.conf' % name)
        if os.path.isfile(filename):
            os.unlink(filename)
        self.hosts.pop(name)
        self.model_hosts.remove(self.model_hosts.get_iter(name))

    def reload_groups(self):
        """Load groups from hosts folder"""
        self.model_groups.clear()
        # Always add a default group
        self.model_groups.add_data(GroupInfo('', _('Default group')))
        for filename in os.listdir(DIR_HOSTS):
            if os.path.isdir(os.path.join(DIR_HOSTS, filename)):
                # For each folder add a new group
                self.model_groups.add_data(GroupInfo(filename, filename))

    def on_action_new_activate(self, action):
        """Define a new host"""
        dialog = UIHost(parent=self.ui.win_main, hosts=self.model_hosts)
        response = dialog.show(default_name='',
                               default_description='',
                               title=_('Add a new host'),
                               treeiter=None)
        if response == Gtk.ResponseType.OK:
            destinations = dialog.model_destinations.dump()
            associations = dialog.model_associations.dump()
            host = HostInfo(dialog.name, dialog.description)
            # Set the associations
            for values in associations:
                (destination_name, description, service_name,
                 service_arguments) = associations[values]
                destination = destinations[destination_name]
                arguments = json.loads(service_arguments)
                host.add_association(description=description,
                                     destination_name=destination_name,
                                     service_name=service_name,
                                     arguments=arguments)
            self.add_host(host=host,
                          destinations=destinations,
                          update_settings=True)
            # Automatically select the newly added host
            self.ui.tvw_connections.set_cursor(
                path=self.model_hosts.get_path_by_name(dialog.name),
                column=None,
                start_editing=False)
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Define a new host"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if selected_row:
            if self.is_selected_row_host():
                # First level (host)
                name = self.model_hosts.get_key(selected_row)
                description = self.model_hosts.get_description(selected_row)
                selected_iter = self.model_hosts.get_iter(name)
                expanded = self.ui.tvw_connections.row_expanded(
                    self.model_hosts.get_path(selected_iter))
                dialog = UIHost(parent=self.ui.win_main,
                                hosts=self.model_hosts)
                # Restore the destinations for the selected host
                destinations = self.hosts[name].destinations
                for destination_name in destinations:
                    destination = destinations[destination_name]
                    dialog.model_destinations.add_data(destination)
                # Restore the associations for the selected host
                for association in self.hosts[name].associations:
                    service_name = association.service_name
                    if service_name in model_services.services:
                        dialog.model_associations.add_data(
                            index=dialog.model_associations.count(),
                            name=association.destination_name,
                            description=association.description,
                            service=model_services.services[service_name],
                            arguments=association.service_arguments)
                    else:
                        debug.add_warning('service %s not found' %
                                          service_name)
                # Show the edit host dialog
                response = dialog.show(default_name=name,
                                       default_description=description,
                                       title=_('Edit host'),
                                       treeiter=selected_iter)
                if response == Gtk.ResponseType.OK:
                    # Remove older host and add the newer
                    destinations = dialog.model_destinations.dump()
                    associations = dialog.model_associations.dump()
                    host = HostInfo(dialog.name, dialog.description)
                    # Set the associations
                    for values in associations:
                        (destination_name, description, service_name,
                         service_arguments) = associations[values]
                        destination = destinations[destination_name]
                        arguments = json.loads(service_arguments)
                        host.add_association(description=description,
                                             destination_name=destination_name,
                                             service_name=service_name,
                                             arguments=arguments)
                    self.remove_host(name)
                    self.add_host(host=host,
                                  destinations=destinations,
                                  update_settings=True)
                    # Get the path of the host
                    tree_path = self.model_hosts.get_path_by_name(dialog.name)
                    # Automatically select again the previously selected host
                    self.ui.tvw_connections.set_cursor(path=tree_path,
                                                       column=None,
                                                       start_editing=False)
                    # Automatically expand the row if it was expanded before
                    if expanded:
                        self.ui.tvw_connections.expand_row(tree_path, False)

    def on_tvw_connections_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if selected_row and self.is_selected_row_host():
            # Start host edit
            self.ui.action_edit.activate()
        else:
            # Connect to the destination
            self.ui.action_connect.activate()

    def on_action_delete_activate(self, action):
        """Remove the selected host"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.win_main,
                message_type=Gtk.MessageType.QUESTION,
                title=None,
                msg1=_("Remove host"),
                msg2=_("Remove the selected host?"),
                is_response_id=Gtk.ResponseType.YES):
            self.remove_host(self.model_hosts.get_key(selected_row))

    def on_action_copy_activate(self, action):
        """Copy the selected host to another"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if selected_row:
            if self.is_selected_row_host():
                # First level (host)
                name = self.model_hosts.get_key(selected_row)
                description = self.model_hosts.get_description(selected_row)
                selected_iter = self.model_hosts.get_iter(name)
                expanded = self.ui.tvw_connections.row_expanded(
                    self.model_hosts.get_path(selected_iter))
                dialog = UIHost(parent=self.ui.win_main,
                                hosts=self.model_hosts)
                # Restore the destinations for the selected host
                destinations = self.hosts[name].destinations
                for destination_name in destinations:
                    destination = destinations[destination_name]
                    dialog.model_destinations.add_data(destination)
                # Restore the associations for the selected host
                for association in self.hosts[name].associations:
                    service_name = association.service_name
                    if service_name in model_services.services:
                        dialog.model_associations.add_data(
                            index=dialog.model_associations.count(),
                            name=association.destination_name,
                            description=association.description,
                            service=model_services.services[service_name],
                            arguments=association.service_arguments)
                    else:
                        debug.add_warning('service %s not found' %
                                          service_name)
                # Show the edit host dialog
                response = dialog.show(default_name=_('Copy of %s') % name,
                                       default_description='',
                                       title=_('Copy host'),
                                       treeiter=None)
                if response == Gtk.ResponseType.OK:
                    destinations = dialog.model_destinations.dump()
                    associations = dialog.model_associations.dump()
                    host = HostInfo(dialog.name, dialog.description)
                    # Set the associations
                    for values in associations:
                        (destination_name, description, service_name,
                         service_arguments) = associations[values]
                        destination = destinations[destination_name]
                        arguments = json.loads(service_arguments)
                        host.add_association(description=description,
                                             destination_name=destination_name,
                                             service_name=service_name,
                                             arguments=arguments)
                    self.add_host(host=host,
                                  destinations=destinations,
                                  update_settings=True)
                    # Get the path of the host
                    tree_path = self.model_hosts.get_path_by_name(dialog.name)
                    # Automatically select again the previously selected host
                    self.ui.tvw_connections.set_cursor(path=tree_path,
                                                       column=None,
                                                       start_editing=False)
                    # Automatically expand the row if it was expanded before
                    if expanded:
                        self.ui.tvw_connections.expand_row(tree_path, False)
                        # Collapse the duplicated row
                        self.ui.tvw_connections.collapse_row(
                            self.model_hosts.get_path(selected_iter))

    def on_tvw_connections_cursor_changed(self, widget):
        """Set actions sensitiveness for host and connection"""
        if get_treeview_selected_row(self.ui.tvw_connections):
            self.ui.actions_connection.set_sensitive(
                not self.is_selected_row_host())
            self.ui.actions_host.set_sensitive(self.is_selected_row_host())

    def on_action_debug_toggled(self, action):
        """Show and hide the debug window"""
        if self.ui.action_debug.get_active():
            debug.debug.show()
        else:
            debug.debug.hide()

    def on_window_debug_delete_event(self, widget, event):
        """Catch the delete_event in the debug window to hide the window"""
        self.ui.action_debug.set_active(False)
        return True

    def on_action_processes_toggled(self, action):
        """Show and hide the processes window"""
        if self.ui.action_processes.get_active():
            processes.processes.show()
        else:
            processes.processes.hide()

    def on_window_processes_delete_event(self, widget, event):
        """Catch the delete_event in the processes window to hide the window"""
        self.ui.action_processes.set_active(False)
        return True

    def on_tvw_connections_key_press_event(self, widget, event):
        """Expand and collapse nodes with keyboard arrows"""
        if event.keyval in (Gdk.KEY_Left, Gdk.KEY_Right):
            # Collapse or expand the selected row using <Left> and <Right>
            selected_row = get_treeview_selected_row(self.ui.tvw_connections)
            if (selected_row and self.is_selected_row_host()):
                if event.keyval == Gdk.KEY_Left:
                    self.ui.action_host_collapse.activate()
                elif event.keyval == Gdk.KEY_Right:
                    self.ui.action_host_expand.activate()
                return True

    def on_action_connect_activate(self, action):
        """Establish the connection for the destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if selected_row and not self.is_selected_row_host():
            host = self.hosts[self.model_hosts.get_key(
                self.ui.store_hosts.iter_parent(selected_row))]
            destination_name = self.model_hosts.get_key(selected_row)
            destination = host.destinations[destination_name]
            description = self.model_hosts.get_association(selected_row)
            service_name = self.model_hosts.get_service(selected_row)
            service_arguments = self.model_hosts.get_arguments(selected_row)
            arguments = json.loads(service_arguments)
            association = host.find_association(description=description,
                                                destination=destination.name,
                                                service=service_name,
                                                arguments=arguments)
            if service_name in model_services.services:
                service = model_services.services[service_name]
                command = service.command
                # Prepares the arguments
                arguments_map = {}
                arguments_map['address'] = destination.value
                for key in association.service_arguments:
                    arguments_map[key] = association.service_arguments[key]
                # Execute command
                try:
                    command = command.format(**arguments_map)
                    processes.processes.add_process(host, destination, service,
                                                    command)
                except KeyError as error:
                    # An error occurred processing the command
                    error_msg1 = _('Connection open failed')
                    error_msg2 = _('An error occurred processing the '
                                   'service command.')
                    show_message_dialog(class_=UIMessageDialogClose,
                                        parent=self.ui.win_main,
                                        message_type=Gtk.MessageType.ERROR,
                                        title=None,
                                        msg1=error_msg1,
                                        msg2=error_msg2,
                                        is_response_id=None)
                    debug.add_error(error_msg2)
                    debug.add_error('Host: "%s"' % host.name)
                    debug.add_error('Destination name: "%s"' %
                                    destination.name)
                    debug.add_error('Destination value: "%s"' %
                                    destination.value)
                    debug.add_error('Service: %s' % service.name),
                    debug.add_error('Command: "%s"' % command)
            else:
                debug.add_warning('service %s not found' % service_name)

    def is_selected_row_host(self):
        """Return if the currently selected row is an host"""
        return self.ui.store_hosts.iter_parent(
            get_treeview_selected_row(self.ui.tvw_connections)) is None

    def get_current_group_path(self):
        """Return the path of the currently selected group"""
        selected_row = get_treeview_selected_row(self.ui.tvw_groups)
        group_name = self.model_groups.get_key(selected_row) if selected_row \
            else ''
        return os.path.join(DIR_HOSTS, group_name) if group_name else DIR_HOSTS

    def on_tvw_groups_cursor_changed(self, widget):
        """Set actions sensitiveness for host and connection"""
        if get_treeview_selected_row(self.ui.tvw_groups):
            self.reload_hosts()
            # Automatically select the first host for the group
            self.ui.tvw_connections.set_cursor(0)

    def on_action_groups_activate(self, widget):
        """Edit groups"""
        dialog_groups = UIGroups(parent=self.ui.win_main)
        dialog_groups.model = self.model_groups
        dialog_groups.ui.tvw_groups.set_model(self.model_groups.model)
        dialog_groups.show()
        dialog_groups.destroy()

    def on_tvw_groups_button_release_event(self, widget, event):
        """Show groups popup menu on right click"""
        if event.button == Gdk.BUTTON_SECONDARY:
            show_popup_menu(self.ui.menu_groups, event.button)

    def on_tvw_connections_button_release_event(self, widget, event):
        """Show connections popup menu on right click"""
        if event.button == Gdk.BUTTON_SECONDARY:
            show_popup_menu(self.ui.menu_connections, event.button)

    def on_action_group_previous_activate(self, action):
        """Move to the previous group"""
        selected_row = get_treeview_selected_row(self.ui.tvw_groups)
        new_iter = self.model_groups.model.iter_previous(selected_row)
        if new_iter:
            # Select the newly selected row in the groups list
            new_path = self.model_groups.get_path(new_iter)
            self.ui.tvw_groups.set_cursor(new_path)

    def on_action_group_next_activate(self, action):
        """Move to the next group"""
        selected_row = get_treeview_selected_row(self.ui.tvw_groups)
        new_iter = self.model_groups.model.iter_next(selected_row)
        if new_iter:
            # Select the newly selected row in the groups list
            new_path = self.model_groups.get_path(new_iter)
            self.ui.tvw_groups.set_cursor(new_path)

    def on_action_host_collapse_activate(self, action):
        """Collapse the selected host and hide the associations"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if (selected_row and self.is_selected_row_host()):
            tree_path = self.model_hosts.get_path(selected_row)
            if self.ui.tvw_connections.row_expanded(tree_path):
                self.ui.tvw_connections.collapse_row(tree_path)

    def on_action_host_expand_activate(self, action):
        """Expand the selected host and show the associations"""
        selected_row = get_treeview_selected_row(self.ui.tvw_connections)
        if (selected_row and self.is_selected_row_host()):
            tree_path = self.model_hosts.get_path(selected_row)
            if not self.ui.tvw_connections.row_expanded(tree_path):
                self.ui.tvw_connections.expand_row(tree_path, False)
示例#34
0
class UIHost(object):
    def __init__(self, parent, hosts):
        """Prepare the host dialog"""
        self.hosts = hosts
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('host.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_host.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_host,
                                                   SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the destinations
        self.model_destinations = ModelDestinations(self.ui.store_destinations)
        self.model_associations = ModelAssociations(self.ui.store_associations)
        self.selected_iter = None
        # Sort the data in the models
        self.model_destinations.model.set_sort_column_id(
            self.ui.column_destinations_name.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_name, default_description, title, treeiter):
        """Show the destinations dialog"""
        self.ui.txt_name.set_text(default_name)
        self.ui.txt_description.set_text(default_description)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_host.set_title(title)
        self.selected_iter = treeiter
        self.model_associations.model.set_sort_column_id(
            self.ui.column_associations_destination.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        # Show the dialog
        response = self.ui.dialog_host.run()
        self.ui.dialog_host.hide()
        self.name = self.ui.txt_name.get_text().strip()
        self.description = self.ui.txt_description.get_text().strip()
        return response

    def destroy(self):
        """Destroy the destinations dialog"""
        settings.positions.save_window_position(self.ui.dialog_host,
                                                SECTION_WINDOW_NAME)
        self.ui.dialog_host.destroy()
        self.ui.dialog_host = None

    def on_action_destinations_add_activate(self, action):
        """Add a new destination"""
        dialog = UIDestination(self.ui.dialog_host, self.model_destinations)
        if dialog.show(default_name='',
                       default_value='',
                       title=_('Add new destination'),
                       treeiter=None) == Gtk.ResponseType.OK:
            self.model_destinations.add_data(
                DestinationInfo(name=dialog.name, value=dialog.value))
        # Get the new destinations list, clear and store the list again
        dialog.destroy()

    def on_action_destinations_edit_activate(self, action):
        """Edit the selected destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_destinations)
        if selected_row:
            name = self.model_destinations.get_key(selected_row)
            value = self.model_destinations.get_value(selected_row)
            selected_iter = self.model_destinations.get_iter(name)
            dialog = UIDestination(self.ui.dialog_host,
                                   self.model_destinations)
            if dialog.show(default_name=name,
                           default_value=value,
                           title=_('Edit destination'),
                           treeiter=selected_iter) == Gtk.ResponseType.OK:
                # Update values
                self.model_destinations.set_data(
                    selected_iter,
                    DestinationInfo(name=dialog.name, value=dialog.value))
            dialog.destroy()

    def on_action_destinations_remove_activate(self, action):
        """Remove the selected destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_destinations)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_host,
                message_type=Gtk.MessageType.QUESTION,
                title=None,
                msg1=_("Remove destination"),
                msg2=_("Remove the selected destination?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model_destinations.remove(selected_row)

    def on_tvw_destinations_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_destinations_edit.activate()

    def on_action_confirm_activate(self, action):
        """Check che host configuration before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(widget=widget,
                                         widgets=(self.ui.txt_name,
                                                  self.ui.txt_description),
                                         label=self.ui.lbl_error_message,
                                         infobar=self.ui.infobar_error_message,
                                         error_msg=error_msg)

        name = self.ui.txt_name.get_text().strip()
        description = self.ui.txt_description.get_text().strip()
        if len(name) == 0:
            # Show error for missing host name
            show_error_message_on_infobar(self.ui.txt_name,
                                          _('The host name is missing'))
        elif '\'' in name or '\\' in name or '/' in name:
            # Show error for invalid host name
            show_error_message_on_infobar(self.ui.txt_name,
                                          _('The host name is invalid'))
        elif self.hosts.get_iter(name) not in (None, self.selected_iter):
            # Show error for existing host name
            show_error_message_on_infobar(
                self.ui.txt_name, _('A host with that name already exists'))
        elif len(description) == 0:
            # Show error for missing host description
            show_error_message_on_infobar(self.ui.txt_description,
                                          _('The host description is missing'))
        else:
            self.ui.dialog_host.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_name_changed(self, widget):
        """Check the host name field"""
        check_invalid_input(widget, False, False, False)

    def on_txt_description_changed(self, widget):
        """Check the host description field"""
        check_invalid_input(widget, False, True, True)

    def on_notebook_switch_page(self, widget, children, number):
        """Disable GtkActionGroup on page change"""
        self.ui.actions_destinations.set_sensitive(number == 0)
        self.ui.actions_associations.set_sensitive(number != 0)

    def on_action_tab_page_activate(self, action):
        """Switch GtkNotebook page on GtkAction activation"""
        self.ui.notebook.set_current_page(
            0 if action is self.ui.action_tab_page1 else 1)

    def on_action_associations_add_activate(self, action):
        """Add a new service association"""
        dialog = UIServiceAssociation(self.ui.dialog_host,
                                      self.model_destinations)
        if dialog.show('', None, None) == Gtk.ResponseType.OK:
            self.model_associations.add_data(
                self.model_associations.count() + 1, dialog.destination,
                dialog.description, model_services.services[dialog.service],
                dialog.arguments)
        dialog.destroy()

    def on_action_associations_remove_activate(self, action):
        """Remove the selected destination"""
        selected_row = get_treeview_selected_row(self.ui.tvw_associations)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_host,
                message_type=Gtk.MessageType.QUESTION,
                title=None,
                msg1=_("Remove association"),
                msg2=_("Remove the selected association?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model_associations.remove(selected_row)

    def on_action_associations_edit_activate(self, action):
        """Edit the selected service association"""
        selected_row = get_treeview_selected_row(self.ui.tvw_associations)
        if selected_row:
            dialog = UIServiceAssociation(self.ui.dialog_host,
                                          self.model_destinations)
            model = self.model_associations
            selected_key = model.get_key(selected_row)
            selected_iter = model.get_iter(selected_key)
            if dialog.show(model.get_description(selected_row),
                           model.get_destination_name(selected_row),
                           model.get_service_name(selected_row),
                           json.loads(model.get_arguments(
                               selected_row))) == Gtk.ResponseType.OK:
                model.set_data(treeiter=selected_iter,
                               description=dialog.description,
                               destination_name=dialog.destination,
                               service=model_services.services[dialog.service],
                               arguments=dialog.arguments)
            dialog.destroy()

    def on_tvw_associations_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_associations_edit.activate()
class UICommandArguments(object):
    def __init__(self, parent):
        """Prepare the command arguments dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('command_arguments.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_arguments.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_arguments,
                                                   SECTION_WINDOW_NAME)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        # Initialize column headers
        for widget in self.ui.get_objects_by_type(Gtk.TreeViewColumn):
            widget.set_title(text(widget.get_title()))
        # Load the arguments
        self.model_arguments = self.ui.store_arguments
        self.arguments = '[]'
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_command):
        """Show the command arguments dialog"""
        arguments = get_list_from_string_list(default_command)
        for argument in arguments:
            self.model_arguments.append((argument, ))
        self.ui.dialog_arguments.run()
        self.ui.dialog_arguments.hide()
        arguments = []
        for treeiter in self.model_arguments:
            arguments.append(self.model_arguments[treeiter.path][0])
        self.arguments = json.dumps(arguments)

    def destroy(self):
        """Destroy the command arguments dialog"""
        settings.positions.save_window_position(self.ui.dialog_arguments,
                                                SECTION_WINDOW_NAME)
        self.ui.dialog_arguments.destroy()
        self.ui.dialog_arguments = None

    def on_action_add_activate(self, action):
        """Add a new argument"""
        dialog = UICommandArgument(self.ui.dialog_arguments)
        if dialog.show(default_value='') == Gtk.ResponseType.OK:
            self.model_arguments.append((dialog.argument, ))
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Edit the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_arguments)
        if selected_row:
            argument = self.model_arguments[selected_row][0]
            dialog = UICommandArgument(self.ui.dialog_arguments)
            if dialog.show(default_value=argument) == Gtk.ResponseType.OK:
                # Update values
                self.model_arguments.set_value(selected_row, 0,
                                               dialog.argument)
            dialog.destroy()

    def on_action_remove_activate(self, action):
        """Remove the selected service"""
        selected_row = get_treeview_selected_row(self.ui.tvw_arguments)
        if selected_row and show_message_dialog(
                class_=UIMessageDialogNoYes,
                parent=self.ui.dialog_arguments,
                message_type=Gtk.MessageType.WARNING,
                title=None,
                msg1=_("Remove argument"),
                msg2=_("Remove the selected argument?"),
                is_response_id=Gtk.ResponseType.YES):
            self.model_arguments.remove(selected_row)

    def on_tvw_arguments_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_edit.activate()
示例#36
0
class UIServiceDetail(object):
    def __init__(self, parent, services):
        """Prepare the services detail dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('service_detail.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_edit_service.set_transient_for(parent)
        # Initialize actions
        for widget in self.ui.get_objects_by_type(Gtk.Action):
            # Connect the actions accelerators
            widget.connect_accelerator()
            # Set labels
            widget.set_label(text(widget.get_label()))
        # Initialize labels
        for widget in self.ui.get_objects_by_type(Gtk.Label):
            widget.set_label(text(widget.get_label()))
            widget.set_tooltip_text(widget.get_label().replace('_', ''))
        # Initialize tooltips
        for widget in self.ui.get_objects_by_type(Gtk.Button):
            action = widget.get_related_action()
            if action:
                widget.set_tooltip_text(action.get_label().replace('_', ''))
        self.model = services
        self.selected_iter = None
        self.name = ''
        self.description = ''
        self.command = '[]'
        self.terminal = False
        self.icon = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, default_name, default_description, default_command,
             default_terminal, default_icon, title, treeiter):
        """Show the Services detail dialog"""
        self.ui.txt_name.set_text(default_name)
        self.ui.txt_description.set_text(default_description)
        self.ui.txt_command.set_text(default_command)
        self.ui.chk_terminal.set_active(default_terminal)
        self.ui.txt_icon.set_text(default_icon)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_edit_service.set_title(title)
        self.selected_iter = treeiter
        response = self.ui.dialog_edit_service.run()
        self.ui.dialog_edit_service.hide()
        self.name = self.ui.txt_name.get_text().strip()
        self.description = self.ui.txt_description.get_text().strip()
        self.command = self.ui.txt_command.get_text().strip()
        self.terminal = self.ui.chk_terminal.get_active()
        self.icon = self.ui.txt_icon.get_text().strip()
        return response

    def destroy(self):
        """Destroy the Services dialog"""
        self.ui.dialog_edit_service.destroy()
        self.ui.dialog_edit_service = None

    def on_action_confirm_activate(self, action):
        """Check che service configuration before confirm"""
        def show_error_message_on_infobar(widget, error_msg):
            """Show the error message on the GtkInfoBar"""
            set_error_message_on_infobar(
                widget=widget,
                widgets=(self.ui.txt_name, self.ui.txt_description,
                         self.ui.txt_command),
                label=self.ui.lbl_error_message,
                infobar=self.ui.infobar_error_message,
                error_msg=error_msg)
        name = self.ui.txt_name.get_text().strip()
        description = self.ui.txt_description.get_text().strip()
        command = self.ui.txt_command.get_text().strip()
        terminal = self.ui.chk_terminal.get_active()
        icon = self.ui.txt_icon.get_text().strip()
        if len(name) == 0:
            # Show error for missing service name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The service name is missing'))
        elif '\'' in name or '\\' in name or '/' in name or ',' in name:
            # Show error for invalid service name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The service name is invalid'))
        elif self.model.get_iter(name) not in (None, self.selected_iter):
            # Show error for existing service name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('A service with that name already exists'))
        elif len(description) == 0:
            # Show error for missing service description
            show_error_message_on_infobar(
                self.ui.txt_description,
                _('The service description is missing'))
        elif '\'' in description or '\\' in description:
            # Show error for invalid service description
            show_error_message_on_infobar(
                self.ui.txt_description,
                _('The service description is invalid'))
        elif len(command) == 0:
            # Show error for missing service description
            show_error_message_on_infobar(
                self.ui.txt_command,
                _('The service command is missing'))
        elif len(icon) > 0 and not os.path.isfile(icon):
            # Show error for missing service description
            show_error_message_on_infobar(
                self.ui.txt_icon,
                _('The service icon doesn''t exists'))
        else:
            self.ui.dialog_edit_service.response(Gtk.ResponseType.OK)

    def on_infobar_error_message_response(self, widget, response_id):
        """Close the infobar"""
        if response_id == Gtk.ResponseType.CLOSE:
            self.ui.infobar_error_message.set_visible(False)

    def on_txt_name_changed(self, widget):
        """Check the service name field"""
        check_invalid_input(widget, False, False, False)

    def on_txt_description_changed(self, widget):
        """Check the service description field"""
        check_invalid_input(widget, False, True, False)

    def on_txt_icon_changed(self, widget):
        """Check the icon field"""
        text = widget.get_text().strip()
        if len(text) > 0 and os.path.isfile(text):
            icon_size = preferences.get(preferences.ICON_SIZE)
            self.ui.image_icon.set_from_pixbuf(
                GdkPixbuf.Pixbuf.new_from_file_at_size(text,
                                                       icon_size,
                                                       icon_size))
            icon_name = None
        else:
            icon_name = 'dialog-error' if len(text) > 0 else None
            self.ui.image_icon.set_from_icon_name('image-missing',
                                                  Gtk.IconSize.LARGE_TOOLBAR)
        widget.set_icon_from_icon_name(
            Gtk.EntryIconPosition.SECONDARY, icon_name)

    def on_action_browse_icon_activate(self, action):
        """Browse for an icon file"""
        def update_preview_cb(widget, image, get_preview_filename, set_active):
            """Update preview by trying to load the image"""
            try:
                # Try to load the image from the previewed file
                image.set_from_pixbuf(GdkPixbuf.Pixbuf.new_from_file_at_size(
                    get_preview_filename(),
                    preferences.get(preferences.PREVIEW_SIZE),
                    preferences.get(preferences.PREVIEW_SIZE)))
                set_active(True)
            except:
                # Hide the preview widget for errors
                image.set_from_pixbuf(None)
                set_active(False)
        # Prepare the browse for icon dialog
        dialog = UIFileChooserOpenFile(self.ui.dialog_edit_service,
                                       text("Select a File"))
        dialog.add_filter(_("All Image Files"), "image/*", None)
        dialog.add_filter(_("All Files"), None, "*")
        dialog.set_filename(self.ui.txt_icon.get_text())
        # Set the image preview widget
        image_preview = Gtk.Image()
        image_preview.set_hexpand(False)
        image_preview.set_size_request(
            preferences.get(preferences.PREVIEW_SIZE), -1)
        dialog.set_preview_widget(image_preview, update_preview_cb)
        # Show the browse for icon dialog
        filename = dialog.show()
        if filename is not None:
            self.ui.txt_icon.set_text(filename)
        dialog.destroy()

    def on_action_configure_activate(self, action):
        """Configure the arguments list"""
        dialog = UICommandArguments(self.ui.dialog_edit_service)
        dialog.show(default_command=self.ui.txt_command.get_text())
        self.ui.txt_command.set_text(dialog.arguments)