Пример #1
0
class UISNMPValues(object):
    def __init__(self, parent, host):
        """Prepare the snmp values dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('snmp_values.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.window_snmp.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.window_snmp,
                                                   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
            if widget.get_label():
                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()))
        # Initialize services
        self.model = SNMPValues(self.ui.store_values)
        self.services = {}
        for service in model_devices.devices[host.device].services:
            oid = model_services.services[service].description
            self.services[service] = oid
            value = SNMPValueInfo(name=service, value='', timestamp=0)
            self.model.add_data(value)
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(), Gtk.SortType.ASCENDING)
        self.host = host
        self.ui.window_snmp.set_title(_('SNMP values for %s') % host.name)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Groups dialog"""
        self.ui.window_snmp.show()

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

    def on_window_snmp_delete_event(self, widget, event):
        self.destroy()

    def on_action_refresh_activate(self, action):
        fixed_arguments = [
            'snmpget',
        ]
        fixed_arguments.append('-v1' if self.host.version == 1 else '-v2c')
        fixed_arguments.append('-c')
        fixed_arguments.append(self.host.community)
        fixed_arguments.append('-OvQn')
        fixed_arguments.append('-t')
        fixed_arguments.append('0.3')
        fixed_arguments.append('%s:%s:%d' %
                               (self.host.protocol.lower(), self.host.address,
                                self.host.port_number))
        services = self.services.keys()
        if self.host.requests == REQUESTS_MULTIPLE:
            # Process multiple requests at once
            arguments = fixed_arguments[:]
            arguments.extend([self.services[value] for value in services])
            process = subprocess.Popen(args=arguments,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
            stdout = process.communicate()[0].split('\n')
            for counter in xrange(len(services)):
                treeiter = self.model.rows[services[counter]]
                self.model.set_value(treeiter, stdout[counter])
        else:
            # Process a single request
            for service in services:
                arguments = fixed_arguments[:]
                arguments.append(self.services[service])
                treeiter = self.model.rows[service]
                process = subprocess.Popen(args=arguments,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
                stdout = process.communicate()[0].split('\n')
                self.model.set_value(treeiter, stdout[0])
Пример #2
0
class UISNMPValues(object):
    def __init__(self, parent, host):
        """Prepare the snmp values dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('snmp_values.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.window_snmp.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.window_snmp,
                                                   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
            if widget.get_label():
                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()))
        # Initialize services
        self.model = SNMPValues(self.ui.store_values)
        self.services = {}
        for service in model_devices.devices[host.device].services:
            oid = model_services.services[service].numeric_oid
            self.services[service] = oid
            value = SNMPValueInfo(name=service, value='', timestamp=0)
            self.model.add_data(value)
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(), Gtk.SortType.ASCENDING)
        self.host = host
        self.ui.window_snmp.set_title(_('SNMP values for %s') % host.name)
        self.semaphore = None
        self.completed_threads = 0
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Groups dialog"""
        self.ui.window_snmp.show()

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

    def on_window_snmp_delete_event(self, widget, event):
        """Window closing event"""
        # Disable timer and scan when the window is closed
        self.ui.action_timer.set_active(False)
        self.ui.action_refresh.set_active(False)
        self.destroy()

    def on_action_refresh_activate(self, action):
        """Update values"""
        def update_ui(values):
            """Update the UI in a thread-safe way using GLib"""
            for service in self.services.keys():
                treeiter = self.model.rows[service]
                self.model.set_value(
                    treeiter,
                    values.get(self.services[service], _('<SNMP Error>')))
                if values.has_key('error'):
                    print values

            # Start scan again if the timer is enabled
            if self.ui.action_timer.get_active():
                GLib.timeout_add(self.ui.adjustment_timer.get_value(),
                                 self.on_action_refresh_activate, action)
            else:
                # Stop the scan
                self.ui.action_refresh.set_active(False)

        def worker(host, oids):
            """Get a reply from SNMP and update the model accordingly"""
            try:
                values = snmp.snmp.get_from_host(host, oids)
            except SNMPException as error:
                print 'Exception: %s' % error.value
                values = {'error': 'Exception: %s' % error.value}
            GLib.idle_add(update_ui, values)

        if self.ui.action_refresh.get_active():
            # Scan for new data
            self.completed_threads = 0
            self.ui.action_refresh.set_icon_name('media-playback-stop')
            # Set the number of maximum running threads
            self.semaphore = threading.BoundedSemaphore(1)
            self.semaphore.cancel = False
            oids = []
            for service in self.services.keys():
                treeiter = self.model.rows[service]
                self.model.set_value(treeiter, '')
                oids.append(self.services[service])
            # Create a new thread and launch it
            thread = SemaphoredThread(semaphore=self.semaphore,
                                      callback=worker,
                                      arguments=(self.host, oids),
                                      name=self.services[service],
                                      target=worker)
            thread.start()
        else:
            # Stop a previous scan
            self.semaphore.cancel = True
            self.ui.action_refresh.set_icon_name('media-playback-start')
            # Disable the timer when the scan is stopped
            self.ui.action_timer.set_active(False)
        # Returning False the timer automatically ends
        # It will be fired again after the scan is completed
        return False

    def on_action_timer_toggled(self, action):
        """Enable the timer for the autoscan"""
        if self.ui.action_timer.get_active():
            # Start scan when the timer is active
            self.ui.action_refresh.set_active(True)
Пример #3
0
class UIMain(object):
    def __init__(self, application):
        self.application = application
        snmp.snmp = snmp.SNMP()
        # Load settings
        settings.settings = settings.Settings(FILE_SETTINGS, False)
        settings.positions = settings.Settings(FILE_WINDOWS_POSITION, False)
        settings.services = settings.Settings(FILE_SERVICES, False)
        settings.devices = settings.Settings(FILE_DEVICES, 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),
                numeric_oid=snmp.snmp.translate(
                    settings.services.get(key, OPTION_SERVICE_DESCRIPTION)))
        # Load devices
        for key in settings.devices.get_sections():
            model_devices.devices[key] = DeviceInfo(
                name=key,
                description=settings.devices.get(key,
                                                 OPTION_DEVICE_DESCRIPTION),
                services=settings.devices.get_list(key,
                                                   OPTION_DEVICE_SERVICES))
        self.loadUI()
        self.model_hosts = ModelHosts(self.ui.store_hosts)
        self.model_groups = ModelGroups(self.ui.store_groups)
        # 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_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_devices,
             self.ui.action_groups, 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"""
        settings.positions.save_window_position(self.ui.win_main,
                                                SECTION_WINDOW_NAME)
        settings.positions.save()
        settings.services.save()
        settings.devices.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
        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)
        self.reload_hosts()
        if selected_row:
            # Automatically select again the previously selected row
            self.ui.tvw_connections.set_cursor(path=selected_path,
                                               column=None,
                                               start_editing=False)

    def on_action_devices_activate(self, action):
        """Edit devices"""
        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
        dialog_devices = UIDevices(parent=self.ui.win_main)
        # Load devices list
        dialog_devices.model.load(model_devices.devices)
        dialog_devices.show()
        # Get the new devices list, clear and store the list again
        model_devices.devices = dialog_devices.model.dump()
        dialog_devices.destroy()
        settings.devices.clear()
        for key in model_devices.devices.iterkeys():
            settings.devices.set(section=key,
                                 option=OPTION_DEVICE_DESCRIPTION,
                                 value=model_devices.devices[key].description)
            settings.devices.set(section=key,
                                 option=OPTION_DEVICE_SERVICES,
                                 value=','.join(
                                     model_devices.devices[key].services))
        self.reload_hosts()
        if selected_row:
            # 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
            settings_host = settings.Settings(filename=os.path.join(
                hosts_path, filename),
                                              case_sensitive=True)
            host = HostInfo(
                name=settings_host.get(SECTION_HOST, OPTION_HOST_NAME),
                description=settings_host.get(SECTION_HOST,
                                              OPTION_HOST_DESCRIPTION),
                protocol=settings_host.get(SECTION_HOST, OPTION_HOST_PROTOCOL),
                address=settings_host.get(SECTION_HOST, OPTION_HOST_ADDRESS),
                port_number=settings_host.get_int(SECTION_HOST,
                                                  OPTION_HOST_PORT),
                version=settings_host.get_int(SECTION_HOST,
                                              OPTION_HOST_VERSION),
                community=settings_host.get(SECTION_HOST,
                                            OPTION_HOST_COMMUNITY),
                device=settings_host.get(SECTION_HOST, OPTION_HOST_DEVICE))
            self.add_host(host, False)

    def add_host(self, host, 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)
        # 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)
            settings_host.set(SECTION_HOST, OPTION_HOST_PROTOCOL,
                              host.protocol)
            settings_host.set(SECTION_HOST, OPTION_HOST_ADDRESS, host.address)
            settings_host.set_int(SECTION_HOST, OPTION_HOST_PORT,
                                  host.port_number)
            settings_host.set_int(SECTION_HOST, OPTION_HOST_VERSION,
                                  host.version)
            settings_host.set(SECTION_HOST, OPTION_HOST_COMMUNITY,
                              host.community)
            settings_host.set(SECTION_HOST, OPTION_HOST_DEVICE, host.device)
            # 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(name='',
                               description='',
                               protocol='UDP',
                               address='',
                               port_number=161,
                               version=1,
                               community='public',
                               device='',
                               title=_('Add a new host'),
                               treeiter=None)
        if response == Gtk.ResponseType.OK:
            host = HostInfo(dialog.name, dialog.description, dialog.protocol,
                            dialog.address, dialog.port_number, dialog.version,
                            dialog.community, dialog.device)
            self.add_host(host=host, 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:
            dialog = UIHost(parent=self.ui.win_main, hosts=self.model_hosts)
            # Show the edit host dialog
            model = self.model_hosts
            name = model.get_key(selected_row)
            selected_iter = model.get_iter(name)
            response = dialog.show(
                name=name,
                description=model.get_description(selected_row),
                protocol=model.get_protocol(selected_row),
                address=model.get_address(selected_row),
                port_number=model.get_port_number(selected_row),
                version=model.get_version(selected_row),
                community=model.get_community(selected_row),
                device=model.get_device(selected_row),
                title=_('Edit host'),
                treeiter=selected_iter)
            if response == Gtk.ResponseType.OK:
                # Remove older host and add the newer
                host = HostInfo(dialog.name, dialog.description,
                                dialog.protocol, dialog.address,
                                dialog.port_number, dialog.version,
                                dialog.community, dialog.device)
                self.remove_host(name)
                self.add_host(host=host, 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)
            dialog.destroy()

    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:
            # Start host connection
            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"""
        row = get_treeview_selected_row(self.ui.tvw_connections)
        if row:
            model = self.model_hosts
            name = self.model_hosts.get_key(row)
            description = self.model_hosts.get_description(row)
            selected_iter = self.model_hosts.get_iter(name)
            dialog = UIHost(parent=self.ui.win_main, hosts=self.model_hosts)
            # Show the edit host dialog
            response = dialog.show(name=_('Copy of %s') % name,
                                   description=description,
                                   title=_('Copy host'),
                                   protocol=model.get_protocol(row),
                                   address=model.get_address(row),
                                   port_number=model.get_port_number(row),
                                   version=model.get_version(row),
                                   community=model.get_community(row),
                                   device=model.get_device(row),
                                   treeiter=None)
            if response == Gtk.ResponseType.OK:
                host = HostInfo(dialog.name, dialog.description,
                                dialog.protocol, dialog.address,
                                dialog.port_number, dialog.version,
                                dialog.community, dialog.device)
                self.add_host(host=host, 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)
            dialog.destroy()

    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(True)
            self.ui.actions_host.set_sensitive(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:
            model = self.model_hosts
            dialog = UISNMPValues(
                parent=self.ui.win_main,
                host=HostInfo(name=model.get_key(selected_row),
                              description=model.get_description(selected_row),
                              protocol=model.get_protocol(selected_row),
                              address=model.get_address(selected_row),
                              port_number=model.get_port_number(selected_row),
                              version=model.get_version(selected_row),
                              community=model.get_community(selected_row),
                              device=model.get_device(selected_row)))
            dialog.show()

    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)
Пример #4
0
class UIDevices(object):
    def __init__(self, parent):
        """Prepare the devices dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('devices.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_devices.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(self.ui.dialog_devices,
                                                   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 devices
        self.model = ModelDevices(self.ui.store_devices)
        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 devices dialog"""
        self.ui.dialog_devices.run()
        self.ui.dialog_devices.hide()

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

    def on_action_add_activate(self, action):
        """Add a new device"""
        dialog = UIDeviceDetail(self.ui.dialog_devices, self.model)
        if dialog.show(name='',
                       description='',
                       services=[],
                       title=_('Add new device type'),
                       treeiter=None) == Gtk.ResponseType.OK:
            self.model.add_data(
                DeviceInfo(name=dialog.name,
                           description=dialog.description,
                           services=dialog.services))
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Edit the selected device"""
        selected_row = get_treeview_selected_row(self.ui.tvw_devices)
        if selected_row:
            name = self.model.get_key(selected_row)
            description = self.model.get_description(selected_row)
            services = self.model.get_services(selected_row)
            selected_iter = self.model.get_iter(name)
            dialog = UIDeviceDetail(self.ui.dialog_devices, self.model)
            if dialog.show(name=name,
                           description=description,
                           services=services,
                           title=_('Edit device type'),
                           treeiter=selected_iter) == Gtk.ResponseType.OK:
                # Update values
                self.model.set_data(
                    selected_iter,
                    DeviceInfo(name=dialog.name,
                               description=dialog.description,
                               services=dialog.services))
            dialog.destroy()

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

    def on_tvw_devices_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_edit.activate()
Пример #5
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)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_edit_service, 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 = services
        self.selected_iter = None
        self.name = ''
        self.description = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, name, description, numeric_oid, title, treeiter):
        """Show the Services detail dialog"""
        self.ui.txt_name.set_text(name)
        self.ui.txt_description.set_text(description)
        self.ui.txt_numeric_oid.set_text(numeric_oid)
        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.numeric_oid = self.ui.txt_numeric_oid.get_text().strip()
        return response

    def destroy(self):
        """Destroy the Service detail dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_edit_service, SECTION_WINDOW_NAME)
        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),
                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 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'))
        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)
        self.ui.txt_numeric_oid.set_text(
            snmp.snmp.translate(widget.get_text().strip()) or
            _('Unkown OID'))
Пример #6
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)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_edit_service, 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 = services
        self.selected_iter = None
        self.name = ''
        self.description = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, name, description, title, treeiter):
        """Show the Services detail dialog"""
        self.ui.txt_name.set_text(name)
        self.ui.txt_description.set_text(description)
        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()
        return response

    def destroy(self):
        """Destroy the Service detail dialog"""
        settings.positions.save_window_position(
            self.ui.dialog_edit_service, SECTION_WINDOW_NAME)
        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),
                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 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'))
        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)
Пример #7
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
            if widget.get_label():
                widget.set_label(text(widget.get_label()))
            else:
                widget.set_label(text(widget.get_short_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()))
        self.selected_iter = None
        self.model_devices = ModelDevices(self.ui.store_devices)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, name, description, protocol, address, port_number, version,
             community, device, title, treeiter):
        """Show the destinations dialog"""
        self.ui.txt_name.set_text(name)
        self.ui.txt_description.set_text(description)
        self.ui.combo_protocol.set_active_id(protocol)
        self.ui.txt_address.set_text(address)
        self.ui.spin_port_number.set_value(port_number)
        self.ui.action_snmp_v1.set_current_value(version)
        self.ui.txt_community.set_text(community)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_host.set_title(title)
        self.selected_iter = treeiter
        # Load the list of the devices
        for device_info in model_devices.devices.values():
            self.model_devices.add_data(device_info)
        if device:
            self.ui.combo_device.set_active_id(device)
        if (self.ui.combo_device.get_active_id() < 0
                and self.model_devices.count()):
            self.ui.combo_device.set_active(0)
        # 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()
        self.protocol = self.ui.combo_protocol.get_active_id()
        self.address = self.ui.txt_address.get_text().strip()
        self.port_number = self.ui.spin_port_number.get_value_as_int()
        self.version = 2 if self.ui.action_snmp_v2c.get_active() else 1
        self.community = self.ui.txt_community.get_text().strip()
        self.device = self.ui.combo_device.get_active_id()
        return response

    def destroy(self):
        """Destroy the host 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_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,
                         self.ui.txt_address, self.ui.txt_community),
                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()
        address = self.ui.txt_address.get_text().strip()
        community = self.ui.txt_community.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'))
        elif len(address) == 0:
            # Show error for missing address
            show_error_message_on_infobar(self.ui.txt_address,
                                          _('The host address is missing'))
        elif '\'' in address or '\\' in address or '/' in address:
            # Show error for invalid address
            show_error_message_on_infobar(self.ui.txt_address,
                                          _('The host address is invalid'))
        elif len(community) == 0:
            # Show error for missing community string
            show_error_message_on_infobar(self.ui.txt_community,
                                          _('The community string 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_txt_address_changed(self, widget):
        """Check the host address field"""
        check_invalid_input(widget, False, False, False)

    def on_txt_community_changed(self, widget):
        """Check the community string field"""
        check_invalid_input(widget, False, True, True)
Пример #8
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
            if widget.get_label():
                widget.set_label(text(widget.get_label()))
            else:
                widget.set_label(text(widget.get_short_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()))
        self.selected_iter = None
        self.model_devices = ModelDevices(self.ui.store_devices)
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, name, description, protocol, address, port_number, version,
             community, device, title, treeiter):
        """Show the destinations dialog"""
        self.ui.txt_name.set_text(name)
        self.ui.txt_description.set_text(description)
        self.ui.combo_protocol.set_active_id(protocol)
        self.ui.txt_address.set_text(address)
        self.ui.spin_port_number.set_value(port_number)
        self.ui.action_snmp_v1.set_current_value(version)
        self.ui.txt_community.set_text(community)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_host.set_title(title)
        self.selected_iter = treeiter
        # Load the list of the devices
        for device_info in model_devices.devices.values():
            self.model_devices.add_data(device_info)
        if device:
            self.ui.combo_device.set_active_id(device)
        if (self.ui.combo_device.get_active_id() < 0 and
                self.model_devices.count()):
            self.ui.combo_device.set_active(0)
        # 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()
        self.protocol = self.ui.combo_protocol.get_active_id()
        self.address = self.ui.txt_address.get_text().strip()
        self.port_number = self.ui.spin_port_number.get_value_as_int()
        self.version = 2 if self.ui.action_snmp_v2c.get_active() else 1
        self.community = self.ui.txt_community.get_text().strip()
        self.device = self.ui.combo_device.get_active_id()
        return response

    def destroy(self):
        """Destroy the host 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_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,
                         self.ui.txt_address, self.ui.txt_community),
                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()
        address = self.ui.txt_address.get_text().strip()
        community = self.ui.txt_community.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'))
        elif len(address) == 0:
            # Show error for missing address
            show_error_message_on_infobar(
                self.ui.txt_address,
                _('The host address is missing'))
        elif '\'' in address or '\\' in address or '/' in address:
            # Show error for invalid address
            show_error_message_on_infobar(
                self.ui.txt_address,
                _('The host address is invalid'))
        elif len(community) == 0:
            # Show error for missing community string
            show_error_message_on_infobar(
                self.ui.txt_community,
                _('The community string 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_txt_address_changed(self, widget):
        """Check the host address field"""
        check_invalid_input(widget, False, False, False)

    def on_txt_community_changed(self, widget):
        """Check the community string field"""
        check_invalid_input(widget, False, True, True)
Пример #9
0
class UIGroupDetail(object):
    def __init__(self, parent, groups):
        """Prepare the group detail dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('group_detail.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_edit_group.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 = groups
        self.name = ''
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self, name, title, treeiter):
        """Show the Group detail dialog"""
        self.ui.txt_name.set_text(name)
        self.ui.txt_name.grab_focus()
        self.ui.dialog_edit_group.set_title(title)
        response = self.ui.dialog_edit_group.run()
        self.ui.dialog_edit_group.hide()
        self.name = self.ui.txt_name.get_text().strip()
        return response

    def destroy(self):
        """Destroy the Group detail dialog"""
        self.ui.dialog_edit_group.destroy()
        self.ui.dialog_edit_group = None

    def on_action_confirm_activate(self, action):
        """Check che group 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, ),
                label=self.ui.lbl_error_message,
                infobar=self.ui.infobar_error_message,
                error_msg=error_msg)
        name = self.ui.txt_name.get_text().strip()
        if len(name) == 0:
            # Show error for missing group name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The group name is missing'))
        elif '\'' in name or '\\' in name or '/' in name or ',' in name:
            # Show error for invalid group name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('The Group name is invalid'))
        elif self.model.get_iter(name):
            # Show error for existing group name
            show_error_message_on_infobar(
                self.ui.txt_name,
                _('A group with that name already exists'))
        else:
            self.ui.dialog_edit_group.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 group name field"""
        check_invalid_input(widget, False, False, False)
Пример #10
0
class UISNMPValues(object):
    def __init__(self, parent, host):
        """Prepare the snmp values dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('snmp_values.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.window_snmp.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.window_snmp, 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
            if widget.get_label():
                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()))
        # Initialize services
        self.model = SNMPValues(self.ui.store_values)
        self.services = {}
        for service in model_devices.devices[host.device].services:
            oid = model_services.services[service].numeric_oid
            self.services[service] = oid
            value = SNMPValueInfo(name=service, value='', timestamp=0)
            self.model.add_data(value)
        # Sort the data in the models
        self.model.model.set_sort_column_id(
            self.ui.column_name.get_sort_column_id(),
            Gtk.SortType.ASCENDING)
        self.host = host
        self.ui.window_snmp.set_title(_('SNMP values for %s') % host.name)
        self.semaphore = None
        self.completed_threads = 0
        # Connect signals from the glade file to the module functions
        self.ui.connect_signals(self)

    def show(self):
        """Show the Groups dialog"""
        self.ui.window_snmp.show()

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

    def on_window_snmp_delete_event(self, widget, event):
        """Window closing event"""
        # Disable timer and scan when the window is closed
        self.ui.action_timer.set_active(False)
        self.ui.action_refresh.set_active(False)
        self.destroy()

    def on_action_refresh_activate(self, action):
        """Update values"""
        def update_ui(values):
            """Update the UI in a thread-safe way using GLib"""
            for service in self.services.keys():
                treeiter = self.model.rows[service]
                self.model.set_value(treeiter,
                                     values.get(self.services[service],
                                                _('<SNMP Error>')))
                if values.has_key('error'):
                    print values

            # Start scan again if the timer is enabled
            if self.ui.action_timer.get_active():
                GLib.timeout_add(self.ui.adjustment_timer.get_value(),
                                 self.on_action_refresh_activate,
                                 action)
            else:
                # Stop the scan
                self.ui.action_refresh.set_active(False)

        def worker(host, oids):
            """Get a reply from SNMP and update the model accordingly"""
            try:
                values = snmp.snmp.get_from_host(host, oids)
            except SNMPException as error:
                print 'Exception: %s' % error.value
                values = {'error': 'Exception: %s' % error.value}
            GLib.idle_add(update_ui, values)

        if self.ui.action_refresh.get_active():
            # Scan for new data
            self.completed_threads = 0
            self.ui.action_refresh.set_icon_name('media-playback-stop')
            # Set the number of maximum running threads
            self.semaphore = threading.BoundedSemaphore(1)
            self.semaphore.cancel = False
            oids = []
            for service in self.services.keys():
                treeiter = self.model.rows[service]
                self.model.set_value(treeiter, '')
                oids.append(self.services[service])
            # Create a new thread and launch it
            thread = SemaphoredThread(semaphore=self.semaphore,
                                      callback=worker,
                                      arguments=(self.host, oids),
                                      name=self.services[service],
                                      target=worker)
            thread.start()
        else:
            # Stop a previous scan
            self.semaphore.cancel = True
            self.ui.action_refresh.set_icon_name('media-playback-start')
            # Disable the timer when the scan is stopped
            self.ui.action_timer.set_active(False)
        # Returning False the timer automatically ends
        # It will be fired again after the scan is completed
        return False

    def on_action_timer_toggled(self, action):
        """Enable the timer for the autoscan"""
        if self.ui.action_timer.get_active():
            # Start scan when the timer is active
            self.ui.action_refresh.set_active(True)
Пример #11
0
class UIDevices(object):
    def __init__(self, parent):
        """Prepare the devices dialog"""
        # Load the user interface
        self.ui = GtkBuilderLoader(get_ui_file('devices.glade'))
        if not preferences.get(preferences.DETACHED_WINDOWS):
            self.ui.dialog_devices.set_transient_for(parent)
        # Restore the saved size and position
        settings.positions.restore_window_position(
            self.ui.dialog_devices, 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 devices
        self.model = ModelDevices(self.ui.store_devices)
        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 devices dialog"""
        self.ui.dialog_devices.run()
        self.ui.dialog_devices.hide()

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

    def on_action_add_activate(self, action):
        """Add a new device"""
        dialog = UIDeviceDetail(self.ui.dialog_devices, self.model)
        if dialog.show(name='',
                       description='',
                       services=[],
                       title=_('Add new device type'),
                       treeiter=None) == Gtk.ResponseType.OK:
            self.model.add_data(DeviceInfo(name=dialog.name,
                                           description=dialog.description,
                                           services=dialog.services))
        dialog.destroy()

    def on_action_edit_activate(self, action):
        """Edit the selected device"""
        selected_row = get_treeview_selected_row(self.ui.tvw_devices)
        if selected_row:
            name = self.model.get_key(selected_row)
            description = self.model.get_description(selected_row)
            services = self.model.get_services(selected_row)
            selected_iter = self.model.get_iter(name)
            dialog = UIDeviceDetail(self.ui.dialog_devices, self.model)
            if dialog.show(name=name,
                           description=description,
                           services=services,
                           title=_('Edit device type'),
                           treeiter=selected_iter
                           ) == Gtk.ResponseType.OK:
                # Update values
                self.model.set_data(selected_iter, DeviceInfo(
                    name=dialog.name,
                    description=dialog.description,
                    services=dialog.services))
            dialog.destroy()

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

    def on_tvw_devices_row_activated(self, widget, treepath, column):
        """Edit the selected row on activation"""
        self.ui.action_edit.activate()
Пример #12
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(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))
        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)
            self.model.remove(selected_row)
Пример #13
0
class UIMain(object):
    def __init__(self, application):
        self.application = application
        snmp.snmp = snmp.SNMP()
        # Load settings
        settings.settings = settings.Settings(FILE_SETTINGS, False)
        settings.positions = settings.Settings(FILE_WINDOWS_POSITION, False)
        settings.services = settings.Settings(FILE_SERVICES, False)
        settings.devices = settings.Settings(FILE_DEVICES, 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),
                numeric_oid=snmp.snmp.translate(settings.services.get(
                    key, OPTION_SERVICE_DESCRIPTION)))
        # Load devices
        for key in settings.devices.get_sections():
            model_devices.devices[key] = DeviceInfo(
                name=key,
                description=settings.devices.get(
                    key, OPTION_DEVICE_DESCRIPTION),
                services=settings.devices.get_list(
                    key, OPTION_DEVICE_SERVICES))
        self.loadUI()
        self.model_hosts = ModelHosts(self.ui.store_hosts)
        self.model_groups = ModelGroups(self.ui.store_groups)
        # 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_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_devices,
                                self.ui.action_groups,
                                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"""
        settings.positions.save_window_position(
            self.ui.win_main, SECTION_WINDOW_NAME)
        settings.positions.save()
        settings.services.save()
        settings.devices.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
        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)
        self.reload_hosts()
        if selected_row:
            # Automatically select again the previously selected row
            self.ui.tvw_connections.set_cursor(path=selected_path,
                                               column=None,
                                               start_editing=False)

    def on_action_devices_activate(self, action):
        """Edit devices"""
        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
        dialog_devices = UIDevices(parent=self.ui.win_main)
        # Load devices list
        dialog_devices.model.load(model_devices.devices)
        dialog_devices.show()
        # Get the new devices list, clear and store the list again
        model_devices.devices = dialog_devices.model.dump()
        dialog_devices.destroy()
        settings.devices.clear()
        for key in model_devices.devices.iterkeys():
            settings.devices.set(
                section=key,
                option=OPTION_DEVICE_DESCRIPTION,
                value=model_devices.devices[key].description)
            settings.devices.set(
                section=key,
                option=OPTION_DEVICE_SERVICES,
                value=','.join(model_devices.devices[key].services))
        self.reload_hosts()
        if selected_row:
            # 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
            settings_host = settings.Settings(
                filename=os.path.join(hosts_path, filename),
                case_sensitive=True)
            host = HostInfo(
                name=settings_host.get(SECTION_HOST, OPTION_HOST_NAME),
                description=settings_host.get(SECTION_HOST,
                                              OPTION_HOST_DESCRIPTION),
                protocol=settings_host.get(SECTION_HOST, OPTION_HOST_PROTOCOL),
                address=settings_host.get(SECTION_HOST, OPTION_HOST_ADDRESS),
                port_number=settings_host.get_int(SECTION_HOST,
                                                  OPTION_HOST_PORT),
                version=settings_host.get_int(SECTION_HOST,
                                              OPTION_HOST_VERSION),
                community=settings_host.get(SECTION_HOST,
                                            OPTION_HOST_COMMUNITY),
                device=settings_host.get(SECTION_HOST, OPTION_HOST_DEVICE))
            self.add_host(host, False)

    def add_host(self, host, 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)
        # 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)
            settings_host.set(SECTION_HOST, OPTION_HOST_PROTOCOL,
                              host.protocol)
            settings_host.set(SECTION_HOST, OPTION_HOST_ADDRESS, host.address)
            settings_host.set_int(SECTION_HOST, OPTION_HOST_PORT,
                                  host.port_number)
            settings_host.set_int(SECTION_HOST, OPTION_HOST_VERSION,
                                  host.version)
            settings_host.set(SECTION_HOST, OPTION_HOST_COMMUNITY,
                              host.community)
            settings_host.set(SECTION_HOST, OPTION_HOST_DEVICE, host.device)
            # 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(name='',
                               description='',
                               protocol='UDP',
                               address='',
                               port_number=161,
                               version=1,
                               community='public',
                               device='',
                               title=_('Add a new host'),
                               treeiter=None)
        if response == Gtk.ResponseType.OK:
            host = HostInfo(dialog.name, dialog.description, dialog.protocol,
                            dialog.address, dialog.port_number, dialog.version,
                            dialog.community, dialog.device)
            self.add_host(host=host,
                          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:
            dialog = UIHost(parent=self.ui.win_main,
                            hosts=self.model_hosts)
            # Show the edit host dialog
            model = self.model_hosts
            name = model.get_key(selected_row)
            selected_iter = model.get_iter(name)
            response = dialog.show(
                name=name,
                description=model.get_description(selected_row),
                protocol=model.get_protocol(selected_row),
                address=model.get_address(selected_row),
                port_number=model.get_port_number(selected_row),
                version=model.get_version(selected_row),
                community=model.get_community(selected_row),
                device=model.get_device(selected_row),
                title=_('Edit host'),
                treeiter=selected_iter)
            if response == Gtk.ResponseType.OK:
                # Remove older host and add the newer
                host = HostInfo(dialog.name, dialog.description,
                                dialog.protocol, dialog.address,
                                dialog.port_number, dialog.version,
                                dialog.community, dialog.device)
                self.remove_host(name)
                self.add_host(host=host,
                              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)
            dialog.destroy()

    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:
            # Start host connection
            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"""
        row = get_treeview_selected_row(self.ui.tvw_connections)
        if row:
            model = self.model_hosts
            name = self.model_hosts.get_key(row)
            description = self.model_hosts.get_description(row)
            selected_iter = self.model_hosts.get_iter(name)
            dialog = UIHost(parent=self.ui.win_main,
                            hosts=self.model_hosts)
            # Show the edit host dialog
            response = dialog.show(name=_('Copy of %s') % name,
                                   description=description,
                                   title=_('Copy host'),
                                   protocol=model.get_protocol(row),
                                   address=model.get_address(row),
                                   port_number=model.get_port_number(row),
                                   version=model.get_version(row),
                                   community=model.get_community(row),
                                   device=model.get_device(row),
                                   treeiter=None)
            if response == Gtk.ResponseType.OK:
                host = HostInfo(dialog.name, dialog.description,
                                dialog.protocol, dialog.address,
                                dialog.port_number, dialog.version,
                                dialog.community, dialog.device)
                self.add_host(host=host,
                              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)
            dialog.destroy()

    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(True)
            self.ui.actions_host.set_sensitive(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:
            model = self.model_hosts
            dialog = UISNMPValues(
                parent=self.ui.win_main,
                host=HostInfo(name=model.get_key(selected_row),
                              description=model.get_description(selected_row),
                              protocol=model.get_protocol(selected_row),
                              address=model.get_address(selected_row),
                              port_number=model.get_port_number(selected_row),
                              version=model.get_version(selected_row),
                              community=model.get_community(selected_row),
                              device=model.get_device(selected_row))
            )
            dialog.show()

    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)