class ProxyQDialog(QDialog): """ Class who create a Proxy QDialog """ def __init__(self, parent=None): super(ProxyQDialog, self).__init__(parent) self.setWindowTitle(_('Proxy Configuration')) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(320, 380) # Fields self.proxy_address = QLineEdit() self.proxy_user = QLineEdit() self.proxy_password = QLineEdit() self.offset = None def initialize_dialog(self): """ Initialize Proxy QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Proxy Settings'))) main_layout.addWidget(self.get_proxy_widget()) center_widget(self) def get_proxy_widget(self): """ Return the proxy QWidget :return: proxy QWidget :rtype: QWidget """ proxy_widget = QWidget() proxy_widget.setObjectName('dialog') proxy_layout = QVBoxLayout(proxy_widget) # Title title_lbl = QLabel(_('Proxy Settings')) title_lbl.setObjectName('itemtitle') proxy_layout.addWidget(title_lbl) proxy_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define your proxy. Be sure to enter a valid address.') ) desc_label.setWordWrap(True) proxy_layout.addWidget(desc_label) # Proxy Settings proxy_lbl = QLabel(_('Proxy Address with Port')) proxy_layout.addWidget(proxy_lbl) proxy = settings.get_config('Alignak', 'proxy') self.proxy_address.setText(proxy) self.proxy_address.setPlaceholderText(_('proxy adress:port...')) self.proxy_address.setFixedHeight(25) proxy_layout.addWidget(self.proxy_address) # Proxy User proxy_user_lbl = QLabel(_('Proxy User (Optional)')) proxy_layout.addWidget(proxy_user_lbl) proxy_user = settings.get_config('Alignak', 'proxy_user') self.proxy_user.setText(proxy_user) self.proxy_user.setPlaceholderText(_('proxy user...')) self.proxy_user.setFixedHeight(25) proxy_layout.addWidget(self.proxy_user) # Proxy Password proxy_password_lbl = QLabel(_('Proxy Password (Optional)')) proxy_layout.addWidget(proxy_password_lbl) if settings.get_config('Alignak', 'proxy_password'): self.proxy_password.setText(settings.get_config('Alignak', 'proxy_password')) self.proxy_password.setPlaceholderText(_('proxy password...')) self.proxy_password.setFixedHeight(25) self.proxy_password.setEchoMode(QLineEdit.Password) proxy_layout.addWidget(self.proxy_password) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept_proxy) proxy_layout.addWidget(valid_btn) return proxy_widget def accept_proxy(self): """ Accept QDialog if proxy is valid """ if self.proxy_address.text() or self.proxy_user.text() or self.proxy_password.text(): try: _, _, _ = self.proxy_address.text().split(':') self.accept() except ValueError: self.proxy_error() else: self.accept() @staticmethod def proxy_error(): # pragma: no cover - not testable """ Display a Message QDialog error """ error_dialog = MessageQDialog() error_dialog.initialize( 'Proxy Error', 'error', 'Wrong proxy setting !', 'You must enter a valid address: "http://proxy:port"' ) error_dialog.exec_() def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ServerQDialog(QDialog): """ Class who create Server QDialog. """ def __init__(self, parent=None): super(ServerQDialog, self).__init__(parent) self.setWindowTitle(_('Alignak Settings')) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(340, 420) # Fields self.server_proc = QLineEdit() self.server_url = QLineEdit() self.server_port = QLineEdit() self.webservice_url = QLineEdit() self.proxy_address = QLineEdit() self.proxy_user = QLineEdit() self.proxy_password = QLineEdit() self.offset = None def initialize_dialog(self): """ Initialize Server QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Alignak Settings'))) main_layout.addWidget(self.get_settings_widget()) center_widget(self) def get_settings_widget(self): """ Return the alignak settings QWidget :return: settings QWidget :rtype: QWidget """ server_widget = QWidget() server_widget.setObjectName('dialog') server_layout = QVBoxLayout(server_widget) # Title title_lbl = QLabel(_('Alignak Backend')) title_lbl.setObjectName('itemtitle') server_layout.addWidget(title_lbl) server_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define alignak settings. Be sure to enter a valid address.' )) desc_label.setWordWrap(True) server_layout.addWidget(desc_label) # Server URL server_lbl = QLabel(_('Server')) server_layout.addWidget(server_lbl) self.server_url.setText(settings.get_config('Alignak', 'url')) self.server_url.setPlaceholderText(_('alignak backend url...')) self.server_url.setFixedHeight(25) server_layout.addWidget(self.server_url) # Server Port port_lbl = QLabel(_('Port')) server_layout.addWidget(port_lbl) cur_port = settings.get_config('Alignak', 'backend').split(':')[2] self.server_port.setText(cur_port) self.server_port.setPlaceholderText(_('alignak backend port...')) self.server_port.setFixedHeight(25) server_layout.addWidget(self.server_port) # Server Processes (displayed only for Unix platforms) if 'win32' not in sys.platform: process_lbl = QLabel(_('Processes')) server_layout.addWidget(process_lbl) cur_proc = settings.get_config('Alignak', 'processes') self.server_proc.setText(cur_proc) self.server_proc.setPlaceholderText( _('alignak backend processes...')) self.server_proc.setFixedHeight(25) server_layout.addWidget(self.server_proc) # Web Service description server_layout.addStretch(1) webservice_lbl = QLabel(_('Web Service')) webservice_lbl.setObjectName('itemtitle') server_layout.addWidget(webservice_lbl) ws_desc_lbl = QLabel( _('Here you can define your alignak web service url, with port if needed' )) ws_desc_lbl.setWordWrap(True) server_layout.addWidget(ws_desc_lbl) # Web Service URL self.webservice_url.setText( settings.get_config('Alignak', 'webservice')) self.webservice_url.setPlaceholderText(_('alignak webservice url...')) self.webservice_url.setFixedHeight(25) server_layout.addWidget(self.webservice_url) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept) server_layout.addWidget(valid_btn) return server_widget def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ProblemsQWidget(QWidget): """ Class who create Problems QWidget """ def __init__(self, parent=None): super(ProblemsQWidget, self).__init__(parent) self.setWindowIcon(QIcon(settings.get_image('icon'))) # Fields self.line_search = QLineEdit() self.problems_table = ProblemsQTableView() self.problems_title = QLabel() self.actions_widget = ActionsQWidget() self.spy_widget = None self.filter_hosts_btn = ToggleQWidgetButton() self.filter_services_btn = ToggleQWidgetButton() self.spy_btn = QPushButton() self.host_btn = QPushButton() self.refresh_timer = QTimer() def initialize(self, spy_widget): """ Initialize QWidget and set SpyQWidget :param spy_widget: instance of SpyQWidget to manage spy events :type spy_widget: alignak_app.qobjects.events.spy.SpyQWidget """ problem_layout = QVBoxLayout() problem_layout.setContentsMargins(5, 20, 5, 5) self.setLayout(problem_layout) self.spy_widget = spy_widget self.problems_title.setObjectName('title') problem_layout.addWidget(self.problems_title) problem_layout.addWidget(self.get_search_widget()) problem_layout.addWidget(self.get_btn_widget()) problem_layout.addWidget(self.problems_table) self.update_problems_data() update_problems = int( settings.get_config('Alignak-app', 'update_problems')) * 1000 self.refresh_timer.setInterval(update_problems) self.refresh_timer.start() self.refresh_timer.timeout.connect(self.update_problems_data) def get_current_user_role_item(self): """ Return current selected item by ``Qt.UserRole`` :return: current selected item or None :rtype: alignak_app.items.item.Item """ item = self.problems_table.model().data( self.problems_table.selectionModel().currentIndex(), Qt.UserRole) return item def update_action_buttons(self): """ Update status of action buttons and set current item for ActionsQWidget """ # Get item by UserRole item = self.get_current_user_role_item() if item: # If the elements had been ack or downtimed, they would not be present self.actions_widget.acknowledge_btn.setEnabled(True) self.actions_widget.downtime_btn.setEnabled(True) self.actions_widget.item = item if 'service' in item.item_type: host_id = item.data['host'] else: host_id = item.item_id self.spy_btn.setEnabled( bool(host_id not in self.spy_widget.spy_list_widget.spied_hosts)) self.host_btn.setEnabled(True) else: self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) self.host_btn.setEnabled(False) self.spy_btn.setEnabled(False) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(5, 20, 5, 10) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Problems')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Problems')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) self.line_search.setPlaceholderText( _('Type text to filter problems...')) layout.addWidget(self.line_search) # Refresh button refresh_btn = QPushButton(_('Refresh')) refresh_btn.setObjectName('ok') refresh_btn.setFixedSize(120, search_lbl.height()) refresh_btn.setToolTip(_('Refresh problems')) refresh_btn.clicked.connect(self.update_problems_data) layout.addWidget(refresh_btn) return widget def get_btn_widget(self): """ Return QWidget with spy and host synthesis QPushButtons :return: widget with spy and host button :rtype: QWidget """ widget_btn = QWidget() layout_btn = QHBoxLayout() layout_btn.setContentsMargins(0, 0, 0, 5) widget_btn.setLayout(layout_btn) host_filter = QLabel(_('Filter hosts')) host_filter.setObjectName('subtitle') layout_btn.addWidget(host_filter) self.filter_hosts_btn.initialize() self.filter_hosts_btn.update_btn_state(False) self.filter_hosts_btn.toggle_btn.clicked.connect( lambda: self.update_problems_data('host')) layout_btn.addWidget(self.filter_hosts_btn) service_filter = QLabel(_('Filter services')) service_filter.setObjectName('subtitle') layout_btn.addWidget(service_filter) self.filter_services_btn.initialize() self.filter_services_btn.update_btn_state(False) self.filter_services_btn.toggle_btn.clicked.connect( lambda: self.update_problems_data('service')) layout_btn.addWidget(self.filter_services_btn) layout_btn.addStretch() self.host_btn.setIcon(QIcon(settings.get_image('host'))) self.host_btn.setFixedSize(80, 20) self.host_btn.setEnabled(False) self.host_btn.setToolTip(_('See current item in synthesis view')) layout_btn.addWidget(self.host_btn) self.spy_btn.setIcon(QIcon(settings.get_image('spy'))) self.spy_btn.setFixedSize(80, 20) self.spy_btn.setEnabled(False) self.spy_btn.setToolTip(_('Spy current host')) self.spy_btn.clicked.connect(self.add_spied_host) layout_btn.addWidget(self.spy_btn) self.actions_widget.initialize(None) self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) layout_btn.addWidget(self.actions_widget) layout_btn.setAlignment(Qt.AlignCenter) return widget_btn def add_spied_host(self): """ Add a host to spied hosts """ # Get item by UserRole item = self.get_current_user_role_item() if item: if 'service' in item.item_type: item_id = item.data['host'] else: item_id = item.item_id app_backend.query_services(item_id) self.spy_widget.spy_list_widget.add_spy_host(item_id) self.spy_widget.update_parent_spytab() self.update_action_buttons() def update_problems_data(self, item_type=''): """ Update data of Problems QTableWidget and problems title :param item_type: type of item to filter :type item_type: str """ problems_data = data_manager.get_problems() old_research = self.line_search.text() if self.parent(): self.parent().parent().setTabText( self.parent().parent().indexOf(self), _("Problems (%d)") % len(problems_data['problems'])) self.problems_title.setText( _('There are %d problems to manage (hosts: %d, services: %d)') % (len(problems_data['problems']), problems_data['hosts_nb'], problems_data['services_nb'])) if self.filter_hosts_btn.is_checked( ) and not self.filter_services_btn.is_checked(): item_type = 'host' if self.filter_services_btn.is_checked( ) and not self.filter_hosts_btn.is_checked(): item_type = 'service' if not self.filter_services_btn.is_checked( ) and not self.filter_hosts_btn.is_checked(): item_type = '' if isinstance(item_type, str): if 'host' in item_type and self.filter_hosts_btn.is_checked(): if self.filter_services_btn.is_checked(): self.filter_services_btn.update_btn_state(False) if 'service' in item_type and self.filter_services_btn.is_checked( ): if self.filter_hosts_btn.is_checked(): self.filter_hosts_btn.update_btn_state(False) problems_data['problems'] = [ item for item in problems_data['problems'] if item_type in item.item_type ] proxy_filter = self.problems_table.update_view(problems_data) if problems_data['problems']: self.line_search.textChanged.connect(proxy_filter.setFilterRegExp) else: self.problems_title.setText( _('If problems are found, they will be displayed here.')) self.problems_table.selectionModel().selectionChanged.connect( self.update_action_buttons) self.update_action_buttons() if old_research: self.line_search.setText(old_research) self.line_search.textChanged.emit(old_research)
class ServerQDialog(QDialog): """ Class who create Server QDialog. """ def __init__(self, parent=None): super(ServerQDialog, self).__init__(parent) self.setWindowTitle(_('Alignak Settings')) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(340, 420) # Fields self.server_proc = QLineEdit() self.server_url = QLineEdit() self.server_port = QLineEdit() self.webservice_url = QLineEdit() self.proxy_address = QLineEdit() self.proxy_user = QLineEdit() self.proxy_password = QLineEdit() self.offset = None def initialize_dialog(self): """ Initialize Server QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Alignak Settings'))) main_layout.addWidget(self.get_settings_widget()) center_widget(self) def get_settings_widget(self): """ Return the alignak settings QWidget :return: settings QWidget :rtype: QWidget """ server_widget = QWidget() server_widget.setObjectName('dialog') server_layout = QVBoxLayout(server_widget) # Title title_lbl = QLabel(_('Alignak Backend')) title_lbl.setObjectName('itemtitle') server_layout.addWidget(title_lbl) server_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define alignak settings. Be sure to enter a valid address.') ) desc_label.setWordWrap(True) server_layout.addWidget(desc_label) # Server URL server_lbl = QLabel(_('Server')) server_layout.addWidget(server_lbl) self.server_url.setText(settings.get_config('Alignak', 'url')) self.server_url.setPlaceholderText(_('alignak backend url...')) self.server_url.setFixedHeight(25) server_layout.addWidget(self.server_url) # Server Port port_lbl = QLabel(_('Port')) server_layout.addWidget(port_lbl) cur_port = settings.get_config('Alignak', 'backend').split(':')[2] self.server_port.setText(cur_port) self.server_port.setPlaceholderText(_('alignak backend port...')) self.server_port.setFixedHeight(25) server_layout.addWidget(self.server_port) # Server Processes (displayed only for Unix platforms) if 'win32' not in sys.platform: process_lbl = QLabel(_('Processes')) server_layout.addWidget(process_lbl) cur_proc = settings.get_config('Alignak', 'processes') self.server_proc.setText(cur_proc) self.server_proc.setPlaceholderText(_('alignak backend processes...')) self.server_proc.setFixedHeight(25) server_layout.addWidget(self.server_proc) # Web Service description server_layout.addStretch(1) webservice_lbl = QLabel(_('Web Service')) webservice_lbl.setObjectName('itemtitle') server_layout.addWidget(webservice_lbl) ws_desc_lbl = QLabel( _('Here you can define your alignak web service url, with port if needed') ) ws_desc_lbl.setWordWrap(True) server_layout.addWidget(ws_desc_lbl) # Web Service URL self.webservice_url.setText(settings.get_config('Alignak', 'webservice')) self.webservice_url.setPlaceholderText(_('alignak webservice url...')) self.webservice_url.setFixedHeight(25) server_layout.addWidget(self.webservice_url) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept) server_layout.addWidget(valid_btn) return server_widget def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class SynthesisQWidget(QWidget): """ Class who manage Synthesis view with Host and Services QWidgets """ def __init__(self, parent=None): super(SynthesisQWidget, self).__init__(parent) # Fields self.host_widget = HostQWidget() self.services_widget = ServicesQWidget() self.line_search = QLineEdit() self.completer = QCompleter() self.hint_widget = QWidget() def initialize_synthesis(self): """ Initialize Synthesis QWidget """ synthesis_layout = QVBoxLayout() synthesis_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(synthesis_layout) # Search widget search_widget = self.get_search_widget() synthesis_layout.addWidget(search_widget) # Host widget self.host_widget.initialize() self.host_widget.setMaximumHeight(self.width() * 0.5) synthesis_layout.addWidget(self.host_widget) # Hint Widget hint_text = _( '<h4>Dahsboard</h4>' '<ul><li>At the top of App, ' 'you have a dashboard that summarizes the number of items per state.</li></ul>' '<h4>Tabs</h4>' '<ul><li><h4>Host Synthesis</h4></li>' 'Tap in the search bar to view a host and its services.' '<li><h4>Problems</h4></li>' 'The "Problems" tab will show you all problems detected in your backend.' '<li><h4>Spy Hosts</h4></li>' 'A "Spy Host" will keep you regularly informed of his condition. ' 'You will also see problems detected for this host, in the "Spy Hosts" panel.</ul>' '<h4>Alignak</h4>' '<ul><li>You can see your backend status and daemons if available, ' 'as well as your profile.</li></ul>' '<h4>Livestate</h4>' '<ul><li>In the livestate, you can see global state of your monitored items.</li></ul>' '<h4>Events</h4>' '<ul><li>Events will show you informative messages your actions inside App.</li></ul>' ) hint_layout = QVBoxLayout(self.hint_widget) hint_label = QLabel(hint_text) hint_label.setObjectName('subtitle') hint_layout.addWidget(hint_label) synthesis_layout.addWidget(self.hint_widget) # Services widget self.services_widget.initialize() synthesis_layout.addWidget(self.services_widget) # Align all widgets to Top synthesis_layout.setAlignment(Qt.AlignTop) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Host')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Host')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) layout.addWidget(self.line_search) self.create_line_search([]) return widget def create_line_search(self, hostnames_list): """ Add all hosts to QLineEdit and set QCompleter :param hostnames_list: list of host names :type hostnames_list: list """ # Get QStringListModel model = self.completer.model() if not model: model = QStringListModel() model.setStringList(hostnames_list) # Configure QCompleter from model self.completer.setFilterMode(Qt.MatchContains) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setModel(model) self.completer.popup().setObjectName('popup') # Add completer to QLineEdit self.line_search.setCompleter(self.completer) self.line_search.setPlaceholderText(_('Type a host name to display its data')) self.line_search.setToolTip(_('Type a host name to display its data')) def update_synthesis(self, host, services, not_spied): """ Update Synthesis QWidget with given host and services :param host: host item :type host: alignak_app.items.host.Host :param services: list of services attached to host :type services: list :param not_spied: define if host is spied or not :type not_spied: bool """ self.host_widget.spy_btn.setEnabled(not_spied) if host: logger.info('Display %s in synthesis view', host.name) # Update Qwidgets self.host_widget.update_host(host) self.services_widget.update_widget(services) self.hint_widget.hide() self.host_widget.show() self.services_widget.show() # If the service element does not have the same ID as the host, reset to None if self.services_widget.service_data_widget.service_item: if self.services_widget.service_data_widget.service_item.data['host'] != \ self.host_widget.host_item.item_id: self.services_widget.service_data_widget.service_item = None else: self.host_widget.hide() self.services_widget.hide() self.hint_widget.show()
class LoginQDialog(QDialog): """ Class who create login QDialog. """ def __init__(self, parent=None): super(LoginQDialog, self).__init__(parent) self.setWindowTitle('Login to Alignak') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(310, 360) # Fields self.username_line = QLineEdit() self.password_line = QLineEdit() self.proxies = {} self.offset = None def create_widget(self): """ Create widget login """ # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) main_layout.addWidget(get_logo_widget(self, _('Login'), exitapp=True)) # Login QWidget login_widget = QWidget(self) login_widget.setObjectName('dialog') login_layout = QGridLayout() login_widget.setLayout(login_layout) # _ = init_localization() title = QLabel(_('Welcome to Alignak-app')) title.setObjectName('itemtitle') title.setContentsMargins(1, 1, 1, 1) login_layout.addWidget(title, 0, 0, 1, 2) login_layout.setAlignment(title, Qt.AlignCenter) version = QLabel(_('Version %s') % __version__) version.setObjectName('subtitle') login_layout.addWidget(version, 1, 0, 1, 2) login_layout.setAlignment(version, Qt.AlignCenter | Qt.AlignTop) # Alignak server login_label = QLabel(_('Configure Alignak server')) login_layout.addWidget(login_label, 2, 0, 1, 1) login_layout.setAlignment(login_label, Qt.AlignRight) server_btn = QPushButton() server_btn.clicked.connect(self.handle_server) server_btn.setFixedSize(35, 35) server_btn.setIcon(QIcon(settings.get_image('server_settings'))) server_btn.setToolTip(_('Configure Alignak Server')) login_layout.addWidget(server_btn, 2, 1, 1, 1) # Proxy settings proxy_lbl = QLabel(_('Configure Proxy')) login_layout.addWidget(proxy_lbl, 3, 0, 1, 1) login_layout.setAlignment(proxy_lbl, Qt.AlignRight) proxy_btn = QPushButton() proxy_btn.setIcon(QIcon(settings.get_image('password'))) proxy_btn.setToolTip(_('Configure your Proxy')) proxy_btn.setFixedSize(35, 35) proxy_btn.clicked.connect(self.handle_proxy) login_layout.addWidget(proxy_btn, 3, 1, 1, 1) # Connection label connection_lbl = QLabel() connection_lbl.setText(_('<b>Log-in</b> to use the application')) connection_lbl.setWordWrap(True) login_layout.addWidget(connection_lbl, 4, 0, 1, 2) # Username field self.username_line.setFixedHeight(25) self.username_line.setPlaceholderText(_('username...')) login_layout.addWidget(self.username_line, 5, 0, 1, 2) # Password field self.password_line.setFixedHeight(25) self.password_line.setPlaceholderText(_('password...')) self.password_line.setEchoMode(QLineEdit.Password) login_layout.addWidget(self.password_line, 6, 0, 1, 2) # Login button login_button = QPushButton(_('LOGIN'), self) login_button.clicked.connect(self.accept_login) login_button.setObjectName('valid') login_button.setMinimumHeight(30) login_button.setDefault(True) login_layout.addWidget(login_button, 7, 0, 1, 2) main_layout.addWidget(login_widget) self.setLayout(main_layout) center_widget(self) if settings.get_config('Alignak', 'proxy_user'): self.handle_proxy() def accept_login(self): """ Accept Login or not if backend is connected """ username = str(self.username_line.text()) password = str(self.password_line.text()) # Set proxy only if in config if not self.proxies and settings.get_config('Alignak', 'proxy'): self.set_proxy_settings() if app_backend.login(username, password, proxies=self.proxies): self.accept() else: self.reject() def set_proxy_settings(self, proxy_password=None): """ Set the proxy settings, with password if given :param proxy_password: the pasword of proxy :type proxy_password: str """ if settings.get_config('Alignak', 'proxy_user'): # Model is: {'http': 'http://*****:*****@proxy:port'} protocol, address, port = settings.get_config('Alignak', 'proxy').split(':') proxy_user = settings.get_config('Alignak', 'proxy_user') address = address.replace('//', '') proxy = { protocol: '%s://%s:%s@%s:%s' % (protocol, proxy_user, proxy_password, address, port) } self.proxies = proxy elif settings.get_config('Alignak', 'proxy'): protocol = settings.get_config('Alignak', 'proxy').split(':')[0] self.proxies = {protocol: settings.get_config('Alignak', 'proxy')} else: self.proxies = {} def handle_proxy(self): # pragma: no cover - not testable """ Handle Proxy QDialog display and set proxies for login """ proxy_dialog = ProxyQDialog() proxy_dialog.initialize_dialog() self.proxies = None if proxy_dialog.exec_() == ProxyQDialog.Accepted: proxy_address = proxy_dialog.proxy_address.text().rstrip() proxy_user = proxy_dialog.proxy_user.text().rstrip() proxy_password = proxy_dialog.proxy_password.text().rstrip() # Save proxy and user proxy for next login settings.set_config('Alignak', 'proxy', proxy_address) settings.set_config('Alignak', 'proxy_user', proxy_user) self.set_proxy_settings(proxy_password) @staticmethod def handle_server(): # pragma: no cover - not testable """ Handle for Server QDialog and set alignak backend server settings """ server_dialog = ServerQDialog() server_dialog.initialize_dialog() if server_dialog.exec_() == QDialog.Accepted: if server_dialog.server_port.text().rstrip(): backend_url = '%(url)s:' + str( server_dialog.server_port.text()).rstrip() else: backend_url = '%(url)s' settings.set_config('Alignak', 'backend', backend_url) settings.set_config('Alignak', 'url', str(server_dialog.server_url.text()).rstrip()) settings.set_config('Alignak', 'processes', str(server_dialog.server_proc.text()).rstrip()) settings.set_config( 'Alignak', 'webservice', str(server_dialog.webservice_url.text()).rstrip()) def showEvent(self, _): """ QDialog.showEvent(QShowEvent) """ self.username_line.setFocus() def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ValidatorQDialog(QDialog): """ Class who create Validator QDialog to edit text in Alignak-app with regexp to validate """ def __init__(self, parent=None): super(ValidatorQDialog, self).__init__(parent) self.setWindowTitle('Edit Dialog') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(250, 200) # Fields self.line_edit = QLineEdit() self.valid_text = QLabel() self.validator = QRegExpValidator() self.old_text = '' def initialize(self, title, text, regexp): """ Initialize QDialog for ValidatorQDialog :param title: title of the QDialog :type title: str :param text: text to edit :type text: str :param regexp: regular expression to validate :type regexp: str """ self.old_text = text center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, title)) text_title = QLabel(_("Edit your text:")) text_title.setObjectName('subtitle') main_layout.addWidget(text_title) main_layout.setAlignment(text_title, Qt.AlignCenter) main_layout.addWidget(self.get_text_widget(regexp)) def get_text_widget(self, regexp): """ Return text QWidget with QTextEdit :return: text QWidget :rtype: QWidget """ text_widget = QWidget() text_widget.setObjectName('dialog') text_layout = QVBoxLayout() text_widget.setLayout(text_layout) text_layout.addWidget(self.valid_text) qreg_exp = QRegExp(regexp) self.validator.setRegExp(qreg_exp) self.line_edit.setPlaceholderText(_('type your text...')) self.line_edit.setText(self.old_text) self.line_edit.setValidator(self.validator) self.line_edit.setFixedHeight(25) self.line_edit.textChanged.connect(self.check_text) text_layout.addWidget(self.line_edit) # Accept button accept_btn = QPushButton(_('Confirm'), self) accept_btn.clicked.connect(self.accept_text) accept_btn.setObjectName('valid') accept_btn.setMinimumHeight(30) text_layout.addWidget(accept_btn) return text_widget def check_text(self): """ Valid email with ``QRegExpValidator`` and inform user """ state = self.validator.validate(self.line_edit.text(), 0)[0] if state == QRegExpValidator.Acceptable: text = 'Valid email' color = '#27ae60' # green else: text = 'Invalid email !' color = '#e67e22' # orange self.valid_text.setStyleSheet('QLabel { color: %s; }' % color) self.valid_text.setText(text) def accept_text(self): # pragma: no cover """ Set Edit QDialog to Rejected or Accepted (prevent to patch for nothing) """ state = self.validator.validate(self.line_edit.text(), 0)[0] if self.old_text == self.line_edit.text(): self.reject() elif not self.old_text or self.old_text.isspace(): if not self.line_edit.text() or self.line_edit.text().isspace(): self.reject() else: if state == QRegExpValidator.Acceptable: self.accept() else: self.reject() elif not self.line_edit.text() or self.line_edit.text().isspace(): self.line_edit.setText('') self.accept() else: if state == QRegExpValidator.Acceptable: self.accept() else: self.reject()
class SynthesisQWidget(QWidget): """ Class who manage Synthesis view with Host and Services QWidgets """ def __init__(self, parent=None): super(SynthesisQWidget, self).__init__(parent) # Fields self.host_widget = HostQWidget() self.services_widget = ServicesQWidget() self.line_search = QLineEdit() self.completer = QCompleter() self.hint_widget = QWidget() def initialize_synthesis(self): """ Initialize Synthesis QWidget """ synthesis_layout = QVBoxLayout() synthesis_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(synthesis_layout) # Search widget search_widget = self.get_search_widget() synthesis_layout.addWidget(search_widget) # Host widget self.host_widget.initialize() self.host_widget.setMaximumHeight(self.width() * 0.5) synthesis_layout.addWidget(self.host_widget) # Hint Widget hint_text = _( '<h4>Dahsboard</h4>' '<ul><li>At the top of App, ' 'you have a dashboard that summarizes the number of items per state.</li></ul>' '<h4>Tabs</h4>' '<ul><li><h4>Host Synthesis</h4></li>' 'Tap in the search bar to view a host and its services.' '<li><h4>Problems</h4></li>' 'The "Problems" tab will show you all problems detected in your backend.' '<li><h4>Spy Hosts</h4></li>' 'A "Spy Host" will keep you regularly informed of his condition. ' 'You will also see problems detected for this host, in the "Spy Hosts" panel.</ul>' '<h4>Alignak</h4>' '<ul><li>You can see your backend status and daemons if available, ' 'as well as your profile.</li></ul>' '<h4>Livestate</h4>' '<ul><li>In the livestate, you can see global state of your monitored items.</li></ul>' '<h4>Events</h4>' '<ul><li>Events will show you informative messages your actions inside App.</li></ul>' ) hint_layout = QVBoxLayout(self.hint_widget) hint_label = QLabel(hint_text) hint_label.setObjectName('subtitle') hint_layout.addWidget(hint_label) synthesis_layout.addWidget(self.hint_widget) # Services widget self.services_widget.initialize() synthesis_layout.addWidget(self.services_widget) # Align all widgets to Top synthesis_layout.setAlignment(Qt.AlignTop) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Host')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Host')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) layout.addWidget(self.line_search) self.create_line_search([]) return widget def create_line_search(self, hostnames_list): """ Add all hosts to QLineEdit and set QCompleter :param hostnames_list: list of host names :type hostnames_list: list """ # Get QStringListModel model = self.completer.model() if not model: model = QStringListModel() model.setStringList(hostnames_list) # Configure QCompleter from model self.completer.setFilterMode(Qt.MatchContains) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setModel(model) self.completer.popup().setObjectName('popup') # Add completer to QLineEdit self.line_search.setCompleter(self.completer) self.line_search.setPlaceholderText( _('Type a host name to display its data')) self.line_search.setToolTip(_('Type a host name to display its data')) def update_synthesis(self, host, services, not_spied): """ Update Synthesis QWidget with given host and services :param host: host item :type host: alignak_app.items.host.Host :param services: list of services attached to host :type services: list :param not_spied: define if host is spied or not :type not_spied: bool """ self.host_widget.spy_btn.setEnabled(not_spied) if host: logger.info('Display %s in synthesis view', host.name) # Update Qwidgets self.host_widget.update_host(host) self.services_widget.update_widget(services) self.hint_widget.hide() self.host_widget.show() self.services_widget.show() # If the service element does not have the same ID as the host, reset to None if self.services_widget.service_data_widget.service_item: if self.services_widget.service_data_widget.service_item.data['host'] != \ self.host_widget.host_item.item_id: self.services_widget.service_data_widget.service_item = None else: self.host_widget.hide() self.services_widget.hide() self.hint_widget.show()
class ProblemsQWidget(QWidget): """ Class who create Problems QWidget """ def __init__(self, parent=None): super(ProblemsQWidget, self).__init__(parent) self.setWindowIcon(QIcon(settings.get_image('icon'))) # Fields self.line_search = QLineEdit() self.problems_table = ProblemsQTableView() self.problems_title = QLabel() self.actions_widget = ActionsQWidget() self.spy_widget = None self.filter_hosts_btn = ToggleQWidgetButton() self.filter_services_btn = ToggleQWidgetButton() self.spy_btn = QPushButton() self.host_btn = QPushButton() self.refresh_timer = QTimer() def initialize(self, spy_widget): """ Initialize QWidget and set SpyQWidget :param spy_widget: instance of SpyQWidget to manage spy events :type spy_widget: alignak_app.qobjects.events.spy.SpyQWidget """ problem_layout = QVBoxLayout() problem_layout.setContentsMargins(5, 20, 5, 5) self.setLayout(problem_layout) self.spy_widget = spy_widget self.problems_title.setObjectName('title') problem_layout.addWidget(self.problems_title) problem_layout.addWidget(self.get_search_widget()) problem_layout.addWidget(self.get_btn_widget()) problem_layout.addWidget(self.problems_table) self.update_problems_data() update_problems = int(settings.get_config('Alignak-app', 'update_problems')) * 1000 self.refresh_timer.setInterval(update_problems) self.refresh_timer.start() self.refresh_timer.timeout.connect(self.update_problems_data) def get_current_user_role_item(self): """ Return current selected item by ``Qt.UserRole`` :return: current selected item or None :rtype: alignak_app.items.item.Item """ item = self.problems_table.model().data( self.problems_table.selectionModel().currentIndex(), Qt.UserRole ) return item def update_action_buttons(self): """ Update status of action buttons and set current item for ActionsQWidget """ # Get item by UserRole item = self.get_current_user_role_item() if item: # If the elements had been ack or downtimed, they would not be present self.actions_widget.acknowledge_btn.setEnabled(True) self.actions_widget.downtime_btn.setEnabled(True) self.actions_widget.item = item if 'service' in item.item_type: host_id = item.data['host'] else: host_id = item.item_id self.spy_btn.setEnabled( bool(host_id not in self.spy_widget.spy_list_widget.spied_hosts) ) self.host_btn.setEnabled(True) else: self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) self.host_btn.setEnabled(False) self.spy_btn.setEnabled(False) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(5, 20, 5, 10) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Problems')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Problems')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) self.line_search.setPlaceholderText(_('Type text to filter problems...')) layout.addWidget(self.line_search) # Refresh button refresh_btn = QPushButton(_('Refresh')) refresh_btn.setObjectName('ok') refresh_btn.setFixedSize(120, search_lbl.height()) refresh_btn.setToolTip(_('Refresh problems')) refresh_btn.clicked.connect(self.update_problems_data) layout.addWidget(refresh_btn) return widget def get_btn_widget(self): """ Return QWidget with spy and host synthesis QPushButtons :return: widget with spy and host button :rtype: QWidget """ widget_btn = QWidget() layout_btn = QHBoxLayout() layout_btn.setContentsMargins(0, 0, 0, 5) widget_btn.setLayout(layout_btn) host_filter = QLabel(_('Filter hosts')) host_filter.setObjectName('subtitle') layout_btn.addWidget(host_filter) self.filter_hosts_btn.initialize() self.filter_hosts_btn.update_btn_state(False) self.filter_hosts_btn.toggle_btn.clicked.connect(lambda: self.update_problems_data('host')) layout_btn.addWidget(self.filter_hosts_btn) service_filter = QLabel(_('Filter services')) service_filter.setObjectName('subtitle') layout_btn.addWidget(service_filter) self.filter_services_btn.initialize() self.filter_services_btn.update_btn_state(False) self.filter_services_btn.toggle_btn.clicked.connect( lambda: self.update_problems_data('service') ) layout_btn.addWidget(self.filter_services_btn) layout_btn.addStretch() self.host_btn.setIcon(QIcon(settings.get_image('host'))) self.host_btn.setFixedSize(80, 20) self.host_btn.setEnabled(False) self.host_btn.setToolTip(_('See current item in synthesis view')) layout_btn.addWidget(self.host_btn) self.spy_btn.setIcon(QIcon(settings.get_image('spy'))) self.spy_btn.setFixedSize(80, 20) self.spy_btn.setEnabled(False) self.spy_btn.setToolTip(_('Spy current host')) self.spy_btn.clicked.connect(self.add_spied_host) layout_btn.addWidget(self.spy_btn) self.actions_widget.initialize(None) self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) layout_btn.addWidget(self.actions_widget) layout_btn.setAlignment(Qt.AlignCenter) return widget_btn def add_spied_host(self): """ Add a host to spied hosts """ # Get item by UserRole item = self.get_current_user_role_item() if item: if 'service' in item.item_type: item_id = item.data['host'] else: item_id = item.item_id app_backend.query_services(item_id) self.spy_widget.spy_list_widget.add_spy_host(item_id) self.spy_widget.update_parent_spytab() self.update_action_buttons() def update_problems_data(self, item_type=''): """ Update data of Problems QTableWidget and problems title :param item_type: type of item to filter :type item_type: str """ problems_data = data_manager.get_problems() old_research = self.line_search.text() if self.parent(): self.parent().parent().setTabText( self.parent().parent().indexOf(self), _("Problems (%d)") % len(problems_data['problems']) ) self.problems_title.setText( _('There are %d problems to manage (hosts: %d, services: %d)') % ( len(problems_data['problems']), problems_data['hosts_nb'], problems_data['services_nb'] ) ) if self.filter_hosts_btn.is_checked() and not self.filter_services_btn.is_checked(): item_type = 'host' if self.filter_services_btn.is_checked() and not self.filter_hosts_btn.is_checked(): item_type = 'service' if not self.filter_services_btn.is_checked() and not self.filter_hosts_btn.is_checked(): item_type = '' if isinstance(item_type, str): if 'host' in item_type and self.filter_hosts_btn.is_checked(): if self.filter_services_btn.is_checked(): self.filter_services_btn.update_btn_state(False) if 'service' in item_type and self.filter_services_btn.is_checked(): if self.filter_hosts_btn.is_checked(): self.filter_hosts_btn.update_btn_state(False) problems_data['problems'] = [ item for item in problems_data['problems'] if item_type in item.item_type ] proxy_filter = self.problems_table.update_view(problems_data) if problems_data['problems']: self.line_search.textChanged.connect(proxy_filter.setFilterRegExp) else: self.problems_title.setText(_('If problems are found, they will be displayed here.')) self.problems_table.selectionModel().selectionChanged.connect(self.update_action_buttons) self.update_action_buttons() if old_research: self.line_search.setText(old_research) self.line_search.textChanged.emit(old_research)
class PasswordQDialog(QDialog): """ Class who create PasswordDialog QDialog """ def __init__(self, parent=None): super(PasswordQDialog, self).__init__(parent) self.setWindowTitle('User Password') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(300, 300) # Fields self.pass_edit = QLineEdit() self.confirm_edit = QLineEdit() self.help_label = QLabel() def initialize(self): """ Initialize QDialog for PasswordDialog """ center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Edit Password'))) pass_title = QLabel(_("Please type a new PASSWORD:"******"Your password must contain at least 5 characters.")) self.help_label.setWordWrap(True) pass_layout.addWidget(self.help_label) # Accept button accept_btn = QPushButton('Confirm', self) accept_btn.clicked.connect(self.handle_confirm) accept_btn.setObjectName('valid') accept_btn.setMinimumHeight(30) pass_layout.addWidget(accept_btn) main_layout.addWidget(pass_widget) def handle_confirm(self): """ Handle accept_btn for password """ if bool(self.pass_edit.text() == self.confirm_edit.text()) and \ len(self.pass_edit.text()) > 4 and len(self.confirm_edit.text()) > 4: self.accept() else: if bool(self.pass_edit.text() != self.confirm_edit.text()): self.help_label.setText(_("Passwords do not match !")) self.help_label.setStyleSheet("color: red;") if len(self.pass_edit.text()) < 5 or len(self.confirm_edit.text()) < 5: self.help_label.setText(_("Your password must contain at least 5 characters.")) self.help_label.setStyleSheet("color: orange;")
class Synthesis(QWidget): """ Class who create the Synthesis QWidget. """ first_display = True def __init__(self, parent=None): super(Synthesis, self).__init__(parent) self.setStyleSheet(get_css()) # Fields self.line_search = QLineEdit() self.app_backend = None self.action_manager = None self.host_synthesis = None self.app_widget = AppQWidget() self.old_checkbox_states = {} def initialize(self, app_backend): """ Create the QWidget with its items and layout. :param app_backend: app_backend of alignak. :type app_backend: alignak_app.core.backend.AppBackend """ logger.info('Create Synthesis View...') # App_backend self.app_backend = app_backend self.action_manager = ActionManager(app_backend) layout = QGridLayout() self.setLayout(layout) # button button = QPushButton('Search / Refresh Host', self) button.setObjectName('search') button.setFixedHeight(22) button.setToolTip('Search Host') button.clicked.connect(self.display_host_synthesis) layout.addWidget(button, 0, 4, 1, 1) layout.setAlignment(button, Qt.AlignTop) self.line_search.setFixedHeight(button.height()) self.line_search.returnPressed.connect(button.click) self.line_search.cursorPositionChanged.connect(button.click) layout.addWidget(self.line_search, 0, 0, 1, 4) layout.setAlignment(self.line_search, Qt.AlignTop) self.app_widget.initialize('Host Synthesis View') self.app_widget.add_widget(self) self.app_widget.setMinimumSize(1300, 750) refresh_interval = int(get_app_config('Alignak-App', 'item_interval')) if bool(refresh_interval) and refresh_interval > 0: logger.debug('Hosts synthesis will be refresh in %ss', str(refresh_interval)) refresh_interval *= 1000 else: logger.error( '"item_interval" option must be greater than 0. Replace by default: 30s' ) refresh_interval = 30000 refresh_timer = QTimer(self) refresh_timer.start(refresh_interval) refresh_timer.timeout.connect(self.display_host_synthesis) def create_line_search(self): """ Add all hosts to QLineEdit and set QCompleter """ # Create list for QStringModel hosts_list = [] params = {'where': json.dumps({'_is_template': False})} all_hosts = self.app_backend.get('host', params, ['name']) if all_hosts: for host in all_hosts['_items']: hosts_list.append(host['name']) model = QStringListModel() model.setStringList(hosts_list) # Create completer from model completer = QCompleter() completer.setFilterMode(Qt.MatchContains) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setModel(model) # Add completer to "line edit" self.line_search.setCompleter(completer) self.line_search.setPlaceholderText( 'Type a host name to display its data') self.line_search.setToolTip('Type a host name to display its data') def display_host_synthesis(self): """ Display Synthesis QWidget. Remove and delete HostSynthesis if exists """ if self.isVisible() or self.first_display: # If first display, create line search from hosts list if self.first_display: self.create_line_search() self.first_display = False host_name = str(self.line_search.text()).rstrip() backend_data = None old_row = -1 if host_name: backend_data = self.app_backend.get_host_with_services( host_name) # Store old data, remove and delete host_synthesis if self.host_synthesis: # Store old data if self.host_synthesis.services_list: old_row = self.host_synthesis.services_list.currentRow() if self.host_synthesis.check_boxes: for key in self.host_synthesis.check_boxes: self.old_checkbox_states[key] = \ self.host_synthesis.check_boxes[key].isChecked() # Remove and delete QWidget self.layout().removeWidget(self.host_synthesis) self.host_synthesis.deleteLater() self.host_synthesis = None # Create the new host_synthesis self.host_synthesis = HostSynthesis(self.action_manager) self.host_synthesis.initialize(backend_data) # Restore old data if old_row >= 0 and self.host_synthesis.services_list: self.host_synthesis.services_list.setCurrentRow(old_row) if self.old_checkbox_states and self.host_synthesis.check_boxes: for key, checked in self.old_checkbox_states.items(): try: self.host_synthesis.check_boxes[key].setChecked( checked) except KeyError as e: logger.warning('Can\'t reapply filter [%s]: %s', e, checked) self.layout().addWidget(self.host_synthesis, 1, 0, 1, 5)