def initialize(self):
        """
        Initialize User QWidget

        """

        main_layout = QVBoxLayout(self)
        self.setLayout(main_layout)
        main_layout.setContentsMargins(0, 0, 0, 0)

        main_layout.addWidget(get_logo_widget(self, _('User View')))

        user_widget = QWidget(self)
        user_layout = QGridLayout(user_widget)

        user_title = QLabel(_('User informations:'))
        user_title.setObjectName('itemtitle')
        user_layout.addWidget(user_title, 0, 0, 1, 2)
        user_layout.setAlignment(user_title, Qt.AlignCenter)

        # User QWidgets
        user_layout.addWidget(self.get_informations_widget(), 1, 0, 1, 1)
        user_layout.addWidget(self.get_notes_mail_widget(), 1, 1, 1, 1)
        user_layout.addWidget(self.get_notifications_widget(), 2, 0, 1, 2)

        main_layout.addWidget(user_widget)
        center_widget(self)
    def get_hosts_notif_widget(self):
        """
        Create and return notification QWidget for hosts

        :return: hosts notification QWidget
        :rtype: QWidget
        """

        host_notif_widget = QWidget()
        host_notif_layout = QGridLayout()
        host_notif_widget.setLayout(host_notif_layout)

        notif_title = QLabel(_('Hosts notifications configurations'))
        notif_title.setObjectName('itemtitle')
        host_notif_layout.addWidget(notif_title, 0, 0, 1, 2)

        state_title = QLabel(_("Notification enabled:"))
        state_title.setObjectName("subtitle")
        host_notif_layout.addWidget(state_title, 1, 0, 1, 1)
        self.hostnotif_toggle_btn = ToggleQWidgetButton()
        self.hostnotif_toggle_btn.initialize()
        self.hostnotif_toggle_btn.update_btn_state(
            data_manager.database['user'].data['host_notifications_enabled']
        )
        self.hostnotif_toggle_btn.toggle_btn.clicked.connect(lambda: self.enable_notifications(
            'host_notifications_enabled', self.hostnotif_toggle_btn.is_checked()
        ))
        self.hostnotif_toggle_btn.setObjectName('host_notifications_enabled')
        host_notif_layout.addWidget(self.hostnotif_toggle_btn, 1, 1, 1, 1)
        host_notif_layout.setAlignment(self.hostnotif_toggle_btn, Qt.AlignRight)

        period_title = QLabel(_('Notification period:'))
        period_title.setObjectName('subtitle')
        host_notif_layout.addWidget(period_title, 2, 0, 1, 1)
        self.labels['host_notification_period'].setText(
            data_manager.get_period_name(
                data_manager.database['user'].data['host_notification_period']
            )
        )
        host_notif_layout.addWidget(self.labels['host_notification_period'], 2, 1, 1, 1)

        option_btn = QPushButton()
        option_btn.setIcon(QIcon(settings.get_image('options')))
        option_btn.setFixedSize(64, 32)
        option_btn.clicked.connect(lambda: show_options_dialog(
            'host',
            data_manager.database['user'].data['host_notification_options']
        ))

        host_notif_layout.addWidget(option_btn, 3, 0, 1, 2)
        host_notif_layout.setAlignment(option_btn, Qt.AlignCenter)

        return host_notif_widget
    def get_notes_mail_widget(self):
        """
        Return QWidget with notes and email areas and edition buttons

        :return: notes and email QWidget
        :rtype: QWidget
        """

        notes_widget = QWidget()
        notes_layout = QGridLayout(notes_widget)

        # Notes title and button
        notes_label = QLabel(_('Notes:'))
        notes_label.setObjectName('subtitle')
        notes_layout.addWidget(notes_label, 0, 0, 1, 1)

        notes_btn = QPushButton()
        notes_btn.setIcon(QIcon(settings.get_image('edit')))
        notes_btn.setToolTip(_("Edit your notes."))
        notes_btn.setFixedSize(32, 32)
        notes_btn.clicked.connect(lambda: self.patch_data('notes'))
        notes_layout.addWidget(notes_btn, 0, 2, 1, 1)

        # Notes scroll area
        self.labels['notes'].setText(data_manager.database['user'].data['notes'])
        self.labels['notes'].setWordWrap(True)
        self.labels['notes'].setTextInteractionFlags(Qt.TextSelectableByMouse)
        notes_scrollarea = QScrollArea()
        notes_scrollarea.setWidget(self.labels['notes'])
        notes_scrollarea.setWidgetResizable(True)
        notes_scrollarea.setObjectName('notes')
        notes_layout.addWidget(notes_scrollarea, 1, 0, 1, 3)

        # Mail
        mail_label = QLabel(_('Email:'))
        mail_label.setObjectName('subtitle')
        notes_layout.addWidget(mail_label, 2, 0, 1, 1)
        self.labels['email'].setObjectName('edit')
        notes_layout.addWidget(self.labels['email'], 2, 1, 1, 1)

        mail_btn = QPushButton()
        mail_btn.setIcon(QIcon(settings.get_image('edit')))
        mail_btn.setFixedSize(32, 32)
        mail_btn.clicked.connect(lambda: self.patch_data('email'))
        notes_layout.addWidget(mail_btn, 2, 2, 1, 1)

        notes_layout.setAlignment(Qt.AlignTop)

        return notes_widget
    def update_aliases_on_gui(self):
        '''Updates aliases on the dialog using the info in the book's aliases dict'''
        aliases_widget = QWidget()
        aliases_layout = QGridLayout(aliases_widget)
        aliases_layout.setAlignment(Qt.AlignTop)

        # add aliases for current book
        for index, (character, aliases) in enumerate(sorted(self.book.aliases.items())):
            label = QLabel(character + ':')
            label.setFixedWidth(150)
            aliases_layout.addWidget(label, index, 0)
            line_edit = QLineEdit(', '.join([self.TITLE_CASE(alias) for alias in aliases]))
            line_edit.setFixedWidth(350)
            line_edit.textEdited.connect(functools.partial(self.edit_aliases, character))
            aliases_layout.addWidget(line_edit, index, 1)

        self._scroll_area.setWidget(aliases_widget)
    def update_aliases_on_gui(self):
        '''Updates aliases on the dialog using the info in the book's aliases dict'''
        aliases_widget = QWidget()
        aliases_layout = QGridLayout(aliases_widget)
        aliases_layout.setAlignment(Qt.AlignTop)

        # add aliases for current book
        for index, (character,
                    aliases) in enumerate(sorted(self.book.aliases.items())):
            label = QLabel(character + ':')
            label.setFixedWidth(150)
            aliases_layout.addWidget(label, index, 0)
            line_edit = QLineEdit(', '.join(
                [self.TITLE_CASE(alias) for alias in aliases]))
            line_edit.setFixedWidth(350)
            line_edit.textEdited.connect(
                functools.partial(self.edit_aliases, character))
            aliases_layout.addWidget(line_edit, index, 1)

        self._scroll_area.setWidget(aliases_widget)
    def initialize(self):
        """
        Initialize dock QWidget

        """

        layout = QGridLayout()
        self.setLayout(layout)

        # Add Alignak status
        status = QLabel(_('Alignak'))
        status.setObjectName('itemtitle')
        layout.addWidget(status)
        layout.setAlignment(status, Qt.AlignCenter)
        self.status_widget.initialize()
        layout.addWidget(self.status_widget)

        # Livestate
        livestate = QLabel(_('Livestate'))
        livestate.setObjectName('itemtitle')
        layout.addWidget(livestate)
        layout.setAlignment(livestate, Qt.AlignCenter)
        self.livestate_widget.initialize()
        layout.addWidget(self.livestate_widget)

        # Last Events
        last_event_label = QLabel(_('Last Events'))
        last_event_label.setObjectName('itemtitle')
        layout.addWidget(last_event_label)
        layout.setAlignment(last_event_label, Qt.AlignCenter)
        layout.addWidget(get_events_widget())
Example #7
0
 def layout_using_grid(self):
     label_1 = QLabel('Our first label')
     label_2 = QLabel('Another Label')
     label_span = QLabel('Label spanning columns span')
     
     
     button_1=QPushButton('Click 1')
     button_2=QPushButton('Click 2')
     
     grid_layout = QGridLayout()
     
     grid_layout.addWidget(label_1, 0,0)
     grid_layout.addWidget(button_1, 0,1)
     
     grid_layout.addWidget(label_2, 1, 0)
     grid_layout.addWidget(button_2, 1,1)
     
     grid_layout.addWidget(label_span, 2,0,1,3)
     
     grid_layout.setAlignment(Qt.AlignTop | Qt.AlignLeft)
     grid_layout.setAlignment(Qt.AlignBottom)
     grid_layout.setAlignment(label_1, Qt.AlignRight)
     grid_layout.setAlignment(label_2, Qt.AlignRight)
     
     layout_widget =QWidget()
     layout_widget.setLayout(grid_layout)
     
     self.setCentralWidget(layout_widget)
    def initialize(self):
        """
        Intialize Spy QWidget

        """

        layout = QGridLayout()
        self.setLayout(layout)

        spy_icon = QLabel()
        spy_pixmap = QPixmap(settings.get_image('spy'))
        spy_icon.setPixmap(spy_pixmap)
        spy_icon.setScaledContents(True)
        spy_icon.setFixedSize(20, 20)
        layout.addWidget(spy_icon, 0, 0, 1, 1)
        layout.setAlignment(spy_icon, Qt.AlignRight)

        spy_title = QLabel(_('Spy Hosts'))
        spy_title.setObjectName('title')
        spy_title.setMinimumHeight(40)
        layout.addWidget(spy_title, 0, 1, 1, 1)

        hint_lbl = QLabel('Click to refresh, double-click to stop spying')
        hint_lbl.setObjectName('subtitle')
        layout.addWidget(hint_lbl, 1, 0, 1, 1)
        layout.setAlignment(hint_lbl, Qt.AlignCenter)

        self.host_services_lbl.setObjectName('subtitle')
        layout.addWidget(self.host_services_lbl, 1, 1, 1, 1)
        layout.setAlignment(self.host_services_lbl, Qt.AlignCenter)

        self.spy_list_widget.setDragDropMode(QAbstractItemView.DragDrop)
        self.spy_list_widget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.spy_list_widget.doubleClicked.connect(self.remove_event)
        self.spy_list_widget.setAcceptDrops(True)
        self.spy_list_widget.setWordWrap(True)
        self.spy_list_widget.insertItem(0, self.get_hint_item())
        self.spy_list_widget.item_dropped.connect(
            get_events_widget().remove_event)
        self.spy_list_widget.clicked.connect(
            lambda: self.manage_host_events(self.spy_list_widget.currentRow()))
        layout.addWidget(self.spy_list_widget, 2, 0, 1, 1)

        self.host_list_widget.setObjectName('spy')
        # self.host_list_widget.setMinimumWidth(500)
        layout.addWidget(self.host_list_widget, 2, 1, 1, 1)

        spy_interval = int(settings.get_config('Alignak-app',
                                               'spy_interval')) * 1000
        self.spy_timer.setInterval(spy_interval)
        self.spy_timer.start()
        self.spy_timer.timeout.connect(self.send_spy_events)
    def initialize(self):
        """
        Intialize Spy QWidget

        """

        layout = QGridLayout()
        self.setLayout(layout)

        spy_icon = QLabel()
        spy_pixmap = QPixmap(settings.get_image('spy'))
        spy_icon.setPixmap(spy_pixmap)
        spy_icon.setScaledContents(True)
        spy_icon.setFixedSize(20, 20)
        layout.addWidget(spy_icon, 0, 0, 1, 1)
        layout.setAlignment(spy_icon, Qt.AlignRight)

        spy_title = QLabel(_('Spy Hosts'))
        spy_title.setObjectName('title')
        spy_title.setMinimumHeight(40)
        layout.addWidget(spy_title, 0, 1, 1, 1)

        hint_lbl = QLabel('Click to refresh, double-click to stop spying')
        hint_lbl.setObjectName('subtitle')
        layout.addWidget(hint_lbl, 1, 0, 1, 1)
        layout.setAlignment(hint_lbl, Qt.AlignCenter)

        self.host_services_lbl.setObjectName('subtitle')
        layout.addWidget(self.host_services_lbl, 1, 1, 1, 1)
        layout.setAlignment(self.host_services_lbl, Qt.AlignCenter)

        self.spy_list_widget.setDragDropMode(QAbstractItemView.DragDrop)
        self.spy_list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.spy_list_widget.doubleClicked.connect(self.remove_event)
        self.spy_list_widget.setAcceptDrops(True)
        self.spy_list_widget.setWordWrap(True)
        self.spy_list_widget.insertItem(0, self.get_hint_item())
        self.spy_list_widget.item_dropped.connect(get_events_widget().remove_event)
        self.spy_list_widget.clicked.connect(
            lambda: self.manage_host_events(self.spy_list_widget.currentRow())
        )
        layout.addWidget(self.spy_list_widget, 2, 0, 1, 1)

        self.host_list_widget.setObjectName('spy')
        # self.host_list_widget.setMinimumWidth(500)
        layout.addWidget(self.host_list_widget, 2, 1, 1, 1)

        spy_interval = int(settings.get_config('Alignak-app', 'spy_interval')) * 1000
        self.spy_timer.setInterval(spy_interval)
        self.spy_timer.start()
        self.spy_timer.timeout.connect(self.send_spy_events)
Example #10
0
 def layout_using_grid(self):
     label_1 = QLabel('Our first label')
     label_2 = QLabel('Another Label')
     label_span = QLabel('Label spanning columns span')
     
     
     button_1=QPushButton('Click 1')
     button_2=QPushButton('Click 2')
     
     grid_layout = QGridLayout()
     
     grid_layout.addWidget(label_1, 0,0)
     grid_layout.addWidget(button_1, 0,1)
     
     grid_layout.addWidget(label_2, 1, 0)
     grid_layout.addWidget(button_2, 1,1)
     
     grid_layout.addWidget(label_span, 2,0,1,3)
     
     grid_layout.setAlignment(Qt.AlignTop | Qt.AlignLeft)
     grid_layout.setAlignment(Qt.AlignBottom)
     grid_layout.setAlignment(label_1, Qt.AlignRight)
     grid_layout.setAlignment(label_2, Qt.AlignRight)
     
     layout_widget =QWidget()
     layout_widget.setLayout(grid_layout)
     
     self.setCentralWidget(layout_widget)
     
     
     
     
     
     
 #def horizontal_vertical_box_layout(self):
     
 #def positional_widget_layout(self):
     
     
     #print(self.menuBar().size())
     #mbar_height = self.menuBar().height()
     #print(mbar_height)
     #label_1.move(10,mbar_height)
     
     ''' 
    def initialize(self):
        """
        Initialize QWidget

        """

        self.update_status()

        layout = QGridLayout()
        self.setLayout(layout)

        # Backend state
        connected_title = QLabel(_('Backend API'))
        connected_title.setObjectName('subtitle')
        layout.addWidget(connected_title, 0, 0, 1, 1)

        self.backend_connected.setFixedSize(16, 16)
        self.backend_connected.setScaledContents(True)
        self.backend_connected.setToolTip(_('Status of the backend API connection'))
        layout.addWidget(self.backend_connected, 0, 1, 1, 1)
        layout.setAlignment(self.backend_connected, Qt.AlignCenter)

        # WS state
        ws_title = QLabel(_('Web Service'))
        ws_title.setObjectName('subtitle')
        layout.addWidget(ws_title, 0, 2, 1, 1)

        self.ws_connected.setFixedSize(16, 16)
        self.ws_connected.setScaledContents(True)
        self.ws_connected.setToolTip(_('Status of the Web Service connection'))
        layout.addWidget(self.ws_connected, 0, 3, 1, 1)
        layout.setAlignment(self.ws_connected, Qt.AlignCenter)

        # Daemons state
        daemons_title = QLabel(_('Alignak'))
        daemons_title.setObjectName('subtitle')
        layout.addWidget(daemons_title, 1, 0, 1, 1)

        self.status_dialog.initialize()
        self.update_status_btn(self.status_dialog.update_dialog())
        self.status_btn.setFixedSize(32, 32)
        self.status_btn.clicked.connect(self.show_status_dialog)
        self.status_btn.setToolTip(_('Status of daemons connection'))
        layout.addWidget(self.status_btn, 1, 1, 1, 1)
        layout.setAlignment(self.status_btn, Qt.AlignCenter)

        # User
        user_lbl = QLabel(_('User'))
        user_lbl.setObjectName('subtitle')
        layout.addWidget(user_lbl, 1, 2, 1, 1)

        self.profile_widget.initialize()
        self.profile_btn.setIcon(QIcon(settings.get_image('user')))
        self.profile_btn.setFixedSize(32, 32)
        self.profile_btn.clicked.connect(self.show_user_widget)
        self.profile_btn.setToolTip(_('View current user'))
        layout.addWidget(self.profile_btn, 1, 3, 1, 1)

        # Refresh timer
        update_status = int(settings.get_config('Alignak-app', 'update_status')) * 1000
        self.refresh_timer.setInterval(update_status)
        self.refresh_timer.start()
        self.refresh_timer.timeout.connect(self.update_status)
class DashboardQWidget(QWidget):
    """
        Class who manage Host and Services resume QWidgets with number of:

        * Hosts: ``UP``, ``UNREACHABLE``, ``DOWN``
        * Services: ``OK``, ``WARNING``, ``CRITICAL``, ``UNKNWON``, ``UNREACHABLE``
        * Hosts and services: ``NOT_MONITORED``, ``ACKNOWLEDGED``, ``DOWNTIMED``

    """

    def __init__(self, parent=None):
        super(DashboardQWidget, self).__init__(parent)
        # Fields
        self.layout = QGridLayout()
        self.items_nb = {
            'hosts_nb': QLabel(),
            'services_nb': QLabel()
        }
        self.hosts_labels = {
            'hosts_up': QLabel(),
            'hosts_unreachable': QLabel(),
            'hosts_down': QLabel(),
            'hosts_not_monitored': QLabel(),
            'acknowledge': QLabel(),
            'downtime': QLabel()
        }
        self.services_labels = {
            'services_ok': QLabel(),
            'services_warning': QLabel(),
            'services_critical': QLabel(),
            'services_unknown': QLabel(),
            'services_unreachable': QLabel(),
            'services_not_monitored': QLabel(),
            'acknowledge': QLabel(),
            'downtime': QLabel()
        }
        self.hosts_buttons = {
            'hosts_up': QPushButton(),
            'hosts_unreachable': QPushButton(),
            'hosts_down': QPushButton(),
            'hosts_not_monitored': QPushButton(),
            'acknowledge': QPushButton(),
            'downtime': QPushButton()
        }
        self.services_buttons = {
            'services_ok': QPushButton(),
            'services_warning': QPushButton(),
            'services_critical': QPushButton(),
            'services_unknown': QPushButton(),
            'services_unreachable': QPushButton(),
            'services_not_monitored': QPushButton(),
            'acknowledge': QPushButton(),
            'downtime': QPushButton()
        }
        self.refresh_timer = QTimer()
        self.setFixedHeight(85)

    def initialize(self):
        """
        Initialize QWidget

        """

        self.setLayout(self.layout)
        self.layout.setContentsMargins(0, 0, 0, 0)

        self.get_host_resume_widget()
        self.get_services_resume_widget()

        self.update_dashboard()

        update_dashboard = int(settings.get_config('Alignak-app', 'update_dashboard')) * 1000
        self.refresh_timer.setInterval(update_dashboard)
        self.refresh_timer.start()
        self.refresh_timer.timeout.connect(self.update_dashboard)

    def get_host_resume_widget(self):
        """
        Return Host resume QWidget

        """

        self.layout.addWidget(QLabel(_('<b>Hosts:</b>')), 0, 0, 1, 1)
        self.items_nb['hosts_nb'].setObjectName('subtitle')
        self.layout.addWidget(self.items_nb['hosts_nb'], 1, 0, 1, 1)
        row = 1
        for icon in Host.get_available_icons():
            self.hosts_buttons[icon].setIcon(QIcon(settings.get_image(icon)))
            self.hosts_buttons[icon].setFixedSize(48, 24)
            self.hosts_buttons[icon].setObjectName(icon)
            self.hosts_buttons[icon].setToolTip(
                _('Hosts %s. See in WebUI ?') % icon.replace('hosts_', '').upper()
            )
            self.hosts_buttons[icon].clicked.connect(
                lambda: self.open_item_type_url('hosts')
            )
            self.layout.addWidget(self.hosts_buttons[icon], 0, row, 1, 1)
            self.layout.setAlignment(self.hosts_buttons[icon], Qt.AlignCenter)
            self.hosts_labels[icon].setObjectName(icon)
            self.layout.addWidget(self.hosts_labels[icon], 1, row, 1, 1)
            self.layout.setAlignment(self.hosts_labels[icon], Qt.AlignCenter)
            row += 1

    def get_services_resume_widget(self):
        """
        Return Services resume QWidget

        """

        self.layout.addWidget(QLabel('<b>Services:</b>'), 2, 0, 1, 1)
        self.items_nb['services_nb'].setObjectName('subtitle')
        self.layout.addWidget(self.items_nb['services_nb'], 3, 0, 1, 1)
        row = 1
        for icon in Service.get_available_icons():
            self.services_buttons[icon].setIcon(QIcon(settings.get_image(icon)))
            self.services_buttons[icon].setFixedSize(48, 24)
            self.services_buttons[icon].setObjectName(icon)
            self.services_buttons[icon].setToolTip(
                _('Services %s. See in WebUI ?') % icon.replace('services_', '').upper()
            )
            self.services_buttons[icon].clicked.connect(
                lambda: self.open_item_type_url('services')
            )
            self.layout.addWidget(self.services_buttons[icon], 2, row, 1, 1)
            self.layout.setAlignment(self.services_buttons[icon], Qt.AlignCenter)
            self.services_labels[icon].setObjectName(icon)
            self.layout.addWidget(self.services_labels[icon], 3, row, 1, 1)
            self.layout.setAlignment(self.services_labels[icon], Qt.AlignCenter)
            row += 1

    def open_item_type_url(self, item_type):
        """
        Retrieve sender to send right endpoint to open_url() function for item type

        :param item_type: type of item: hosts | services
        :type item_type: str
        """

        endpoint = self.sender().objectName()

        open_url('%s%s' % (item_type, get_url_endpoint_from_icon_name(endpoint)))

    def update_dashboard(self):
        """
        Update number of items in dashboard

        """

        synthesis = data_manager.get_synthesis_count()

        hosts_sum = 0
        for item in synthesis['hosts']:
            hosts_sum += synthesis['hosts'][item]
        services_sum = 0
        for item in synthesis['services']:
            services_sum += synthesis['services'][item]

        # Hosts percentages
        self.items_nb['hosts_nb'].setText("%d hosts" % hosts_sum)
        for icon in Host.get_available_icons():
            host_nb = synthesis['hosts'][icon.replace('hosts_', '')]
            percent = 0.0
            try:
                percent = float(host_nb) * 100.0 / float(hosts_sum)
            except ZeroDivisionError:
                pass
            item_text = '%d (%.02f%%)' % (host_nb, percent)
            self.hosts_labels[icon].setText(item_text)

        # Services percentage
        self.items_nb['services_nb'].setText("%d services" % services_sum)
        for icon in Service.get_available_icons():
            service_nb = synthesis['services'][icon.replace('services_', '')]
            percent = 0.0
            try:
                percent = float(service_nb) * 100.0 / float(services_sum)
            except ZeroDivisionError:
                pass
            item_text = '%d (%.01f%%)' % (service_nb, percent)
            self.services_labels[icon].setText(item_text)

        for button in self.hosts_buttons:
            if settings.get_config('Alignak', 'webui'):
                self.hosts_buttons[button].setEnabled(True)
                self.hosts_buttons[button].setToolTip(
                    _('Hosts %s. See in WebUI ?') % button.replace('hosts_', '').upper()
                )
            else:
                self.hosts_buttons[button].setToolTip(
                    _("Hosts %s. WebUI is not set in configuration file.") % button.replace(
                        'hosts_', '').upper()
                )

        for button in self.services_buttons:
            if settings.get_config('Alignak', 'webui'):
                self.services_buttons[button].setEnabled(True)
                self.services_buttons[button].setToolTip(
                    _('Services %s. See in WebUI ?') % button.replace('services_', '').upper()
                )
            else:
                self.services_buttons[button].setToolTip(
                    _("Services %s. WebUI is not set in configuration file.") % button.replace(
                        'services_', '').upper()
                )
    def get_informations_widget(self):
        """
        Create and return QWidget with user informations

        :return: main QWidget
        :rtype: QWidget
        """

        information_widget = QWidget()
        info_layout = QGridLayout()
        information_widget.setLayout(info_layout)

        title_labels = {
            'realm': QLabel(_('Realm:')),
            'is_admin': QLabel(_('Administrator:')),
            'role': QLabel(_('Role:')),
            'command': QLabel(_('Commands:')),
            'password': QLabel(_('Password')),
            'alias': QLabel(_('Alias:')),
            'token': QLabel(_('Token:')),
        }

        for label in title_labels:
            title_labels[label].setObjectName('subtitle')

        # Alias, role and realm
        info_layout.addWidget(title_labels['alias'], 0, 0, 1, 2)
        info_layout.addWidget(self.labels['alias'], 0, 1, 1, 2)

        info_layout.addWidget(title_labels['role'], 1, 0, 1, 2)
        info_layout.addWidget(self.labels['role'], 1, 1, 1, 2)

        info_layout.addWidget(title_labels['realm'], 2, 0, 1, 2)
        info_layout.addWidget(self.labels['realm'], 2, 1, 1, 2)

        # Administrator
        title_labels['is_admin'].setMinimumHeight(32)
        info_layout.addWidget(title_labels['is_admin'], 3, 0, 1, 1)
        self.labels['is_admin'].setFixedSize(14, 14)
        self.labels['is_admin'].setScaledContents(True)
        info_layout.addWidget(self.labels['is_admin'], 3, 1, 1, 1)
        info_layout.setAlignment(self.labels['is_admin'], Qt.AlignCenter)

        # Commands
        title_labels['command'].setMinimumHeight(32)
        info_layout.addWidget(title_labels['command'], 3, 2, 1, 1)
        self.labels['can_submit_commands'].setFixedSize(14, 14)
        self.labels['can_submit_commands'].setScaledContents(True)
        info_layout.addWidget(self.labels['can_submit_commands'], 3, 3, 1, 1)
        info_layout.setAlignment(self.labels['can_submit_commands'], Qt.AlignCenter)

        # Password
        info_layout.addWidget(title_labels['password'], 4, 0, 1, 1)
        password_btn = QPushButton()
        password_btn.setIcon(QIcon(settings.get_image('password')))
        password_btn.setToolTip(_('Change my password'))
        password_btn.setFixedSize(32, 32)
        password_btn.clicked.connect(lambda: self.patch_data('password'))
        info_layout.addWidget(password_btn, 4, 1, 1, 1)

        # Token (only for administrators)
        info_layout.addWidget(title_labels['token'], 4, 2, 1, 1)
        self.token_btn.setIcon(QIcon(settings.get_image('token')))
        self.token_btn.setFixedSize(32, 32)
        self.token_btn.clicked.connect(self.show_token_dialog)
        info_layout.addWidget(self.token_btn, 4, 3, 1, 1)

        return information_widget
class PlotToolbarOptions(QWidget):
    def __init__(self,
                 parent,
                 series_style,
                 theme_manager,
                 plot,
                 options=None,
                 legend_control=None,
                 right_padding=0.0,
                 has_extra_tools=False):
        QWidget.__init__(self, parent)
        self._theme_manager = theme_manager
        self._plot = plot
        self._toolbar_container = ToolbarContainer(plot)

        self._background_color_qt = _to_qt_color(
            series_style.get_color_from_key('axes_background'))
        self._foreground_color_qt = _to_qt_color(
            series_style.get_color_from_key('axes_foreground'))
        interpolation = interpolate_rgb(self._background_color_qt,
                                        self._foreground_color_qt, 3)
        self._icon_hover_color = interpolation[1]

        self._toolbar = PlotToolbarWidget(self._toolbar_container, plot,
                                          self._foreground_color_qt,
                                          self._icon_hover_color)
        self._toolbar.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self._layout = QGridLayout(self)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(0)
        self._layout.addWidget(plot, 0, 0, 1, 3)
        self._background_opacity = 0.8
        plot.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        if options is not None:
            if isinstance(options, PlotOptionsView):
                plot.setOptionsView(options)
            self._options = self._add_popout(ToolType.options, options)
        else:
            self._options = None

        if legend_control is not None:
            if isinstance(legend_control, LegendControlView):
                plot.setLegendControl(legend_control)
            self._legend_control = self._add_popout(ToolType.legend,
                                                    legend_control)
            legend_control.hasHiddenSeriesChanged.connect(
                self._handle_has_hidden_series_changed)
        else:
            self._legend_control = None

        self._toolbar_layout = QVBoxLayout(self._toolbar_container)
        self._toolbar_layout.addWidget(self._toolbar, Qt.AlignTop)

        self._layout.addWidget(self._toolbar_container, 0, 1,
                               Qt.AlignRight | Qt.AlignTop)
        self._layout.setColumnStretch(0, 1)
        self._layout.setColumnStretch(1, 0)
        if right_padding > 0:
            self._padding_widget = QWidget(self)
            self._padding_widget.setVisible(False)
            self._layout.addWidget(self._padding_widget, 0, 2)
            self._layout.setColumnMinimumWidth(2, right_padding)
        else:
            self._padding_widget = None

        if not has_extra_tools:
            self._toolbar_layout.addStretch()

    def _handle_has_hidden_series_changed(self, has_hidden):
        color = None if not has_hidden else self._theme_manager.get_color(
            'highlight')
        self._toolbar.setColor(ToolType.legend, color)

    def _handle_tool_activated(self, tool_type, view):
        def _(tool, active):
            if tool == tool_type:
                view.setVisible(active)
                if self._padding_widget:
                    self._padding_widget.setVisible(active)
                if active:
                    self._toolbar_container.setStyleSheet(
                        "ToolbarContainer {{ background-color: {} }}".format(
                            format_color(self._background_color_qt,
                                         ColorFormat.rgba_string_256,
                                         self._background_opacity)))
                    self._layout.setAlignment(self._toolbar_container,
                                              Qt.AlignRight)
                    if self._padding_widget:
                        self._padding_widget.setStyleSheet(
                            "QWidget {{ background-color: {} }}".format(
                                format_color(self._background_color_qt,
                                             ColorFormat.rgba_string_256,
                                             self._background_opacity)))
                else:
                    self._layout.setAlignment(self._toolbar_container,
                                              Qt.AlignRight | Qt.AlignTop)
                    self._toolbar_container.setStyleSheet("")
                    if self._padding_widget:
                        self._padding_widget.setStyleSheet("")

        return _

    def addTool(self, tool_widget):
        self._toolbar_layout.addWidget(HLine(self._plot), Qt.AlignTop)
        self._toolbar_layout.addWidget(tool_widget,
                                       Qt.AlignTop | Qt.AlignCenter)
        self._toolbar_layout.addStretch()

    @property
    def icon_color(self):
        return self._foreground_color_qt

    @property
    def icon_hover_color(self):
        return self._icon_hover_color

    @property
    def toolbar(self):
        return self._toolbar

    def _add_popout(self, tool_type, view):
        popout = PopoutWidget(self, view, self._background_color_qt,
                              self._foreground_color_qt,
                              self._background_opacity)
        popout.setVisible(False)
        self._layout.addWidget(popout, 0, 0, Qt.AlignRight)
        self._toolbar.toolActivated.connect(
            self._handle_tool_activated(tool_type, popout))
        return popout
class StatusQDialog(QDialog):
    """
        Class who create QWidget for Daemons status.
    """
    def __init__(self, parent=None):
        super(StatusQDialog, self).__init__(parent)
        self.setStyleSheet(settings.css_style)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setObjectName('dialog')
        # Fields
        self.offset = None
        self.daemons_layout = QGridLayout()
        self.labels = {}
        self.no_status_lbl = QLabel()

    def initialize(self):
        """
        Initialize QDialog

        """

        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(0, 0, 0, 0)

        main_layout.addWidget(get_logo_widget(self, _('User View')))

        # Daemons QWidget
        daemons_widget = QWidget(self)
        daemons_widget.setLayout(self.daemons_layout)

        daemons = data_manager.database['alignakdaemon']

        # Init QLabels
        self.init_daemons_labels(daemons)

        # Add daemons label
        line = 0
        self.add_daemon_titles_labels(line)

        for daemon_item in daemons:
            line += 1
            self.add_daemon_labels(daemon_item, line)

        line += 1

        # Ok QPushButton
        ok_btn = QPushButton(_('OK'))
        ok_btn.setObjectName('ok')
        ok_btn.setFixedSize(120, 30)
        ok_btn.clicked.connect(self.accept)
        self.daemons_layout.addWidget(ok_btn, line, 0, 1, 7)
        self.daemons_layout.setAlignment(ok_btn, Qt.AlignCenter)

        main_layout.addWidget(daemons_widget)
        center_widget(self)

    def init_daemons_labels(self, daemons):
        """
        Initialize the daemon QLabels for each daemons

        :param daemons: list of daemon items
        :type daemons: list
        """

        daemons_attributes = [
            'alive', 'name', 'reachable', 'spare', 'address', 'passive',
            'last_check'
        ]

        for daemon in daemons:
            self.labels[daemon.name] = {}
            for attribute in daemons_attributes:
                self.labels[daemon.name][attribute] = QLabel()

    def add_daemon_titles_labels(self, line):
        """
        Add QLabels titles for daemons to layout

        :param line: current line of layout
        :type line: int
        """

        # Icon Name Address	Reachable	Spare	Passive daemon	Last check
        icon_title = QLabel(_('State'))
        icon_title.setObjectName('title')
        self.daemons_layout.addWidget(icon_title, line, 0, 1, 1)
        self.daemons_layout.setAlignment(icon_title, Qt.AlignCenter)

        name_title = QLabel(_('Daemon name'))
        name_title.setObjectName('title')
        self.daemons_layout.addWidget(name_title, line, 1, 1, 1)

        address_title = QLabel(_('Address'))
        address_title.setObjectName('title')
        self.daemons_layout.addWidget(address_title, line, 2, 1, 1)

        reachable_title = QLabel(_('Reachable'))
        reachable_title.setObjectName('title')
        self.daemons_layout.addWidget(reachable_title, line, 3, 1, 1)
        self.daemons_layout.setAlignment(reachable_title, Qt.AlignCenter)

        spare_title = QLabel(_('Spare'))
        spare_title.setObjectName('title')
        self.daemons_layout.addWidget(spare_title, line, 4, 1, 1)
        self.daemons_layout.setAlignment(spare_title, Qt.AlignCenter)

        passive_title = QLabel(_('Passive daemon'))
        passive_title.setObjectName('title')
        self.daemons_layout.addWidget(passive_title, line, 5, 1, 1)
        self.daemons_layout.setAlignment(passive_title, Qt.AlignCenter)

        check_title = QLabel(_('Last check'))
        check_title.setObjectName('title')
        self.daemons_layout.addWidget(check_title, line, 6, 1, 1)

    def add_daemon_labels(self, daemon_item, line):
        """
        Add daemon QLabels to layout

        :param daemon_item: daemon item
        :type daemon_item: alignak_app.items.item_daemon.Daemon
        :param line: current line of layout
        :type line: int
        """

        # Alive
        self.labels[daemon_item.name]['alive'].setFixedSize(18, 18)
        self.labels[daemon_item.name]['alive'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['alive'],
                                      line, 0, 1, 1)
        self.daemons_layout.setAlignment(
            self.labels[daemon_item.name]['alive'], Qt.AlignCenter)

        # Name
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['name'],
                                      line, 1, 1, 1)

        # Address
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['address'],
                                      line, 2, 1, 1)

        # Reachable
        self.labels[daemon_item.name]['reachable'].setFixedSize(14, 14)
        self.labels[daemon_item.name]['reachable'].setScaledContents(True)
        self.daemons_layout.addWidget(
            self.labels[daemon_item.name]['reachable'], line, 3, 1, 1)
        self.daemons_layout.setAlignment(
            self.labels[daemon_item.name]['reachable'], Qt.AlignCenter)

        # Spare
        self.labels[daemon_item.name]['spare'].setFixedSize(14, 14)
        self.labels[daemon_item.name]['spare'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['spare'],
                                      line, 4, 1, 1)
        self.daemons_layout.setAlignment(
            self.labels[daemon_item.name]['spare'], Qt.AlignCenter)

        # Passive
        self.labels[daemon_item.name]['passive'].setFixedSize(14, 14)
        self.labels[daemon_item.name]['passive'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['passive'],
                                      line, 5, 1, 1)
        self.daemons_layout.setAlignment(
            self.labels[daemon_item.name]['passive'], Qt.AlignCenter)

        # Last check
        self.daemons_layout.addWidget(
            self.labels[daemon_item.name]['last_check'], line, 6, 1, 1)

    def update_dialog(self):
        """
        Update StatusQDialog labels and return if all daemons are ok or not

        :return: if status of daemons is ok or not
        :rtype: bool
        """

        daemons = data_manager.database['alignakdaemon']
        status_ok = True

        for daemon_item in daemons:
            if daemon_item.name in self.labels:
                # Connected icon
                self.labels[daemon_item.name]['alive'].setPixmap(
                    get_icon_pixmap(daemon_item.data['alive'],
                                    ['connected', 'disconnected']))

                # Labels
                self.labels[daemon_item.name]['name'].setText(daemon_item.name)
                self.labels[daemon_item.name]['address'].setText(
                    '%s:%s' %
                    (daemon_item.data['address'], daemon_item.data['port']))
                self.labels[daemon_item.name]['reachable'].setPixmap(
                    get_icon_pixmap(daemon_item.data['reachable'],
                                    ['checked', 'error']))
                self.labels[daemon_item.name]['spare'].setPixmap(
                    get_icon_pixmap(daemon_item.data['spare'],
                                    ['checked', 'error']))
                self.labels[daemon_item.name]['passive'].setPixmap(
                    get_icon_pixmap(daemon_item.data['passive'],
                                    ['checked', 'error']))
                last_check = get_diff_since_last_timestamp(
                    daemon_item.data['last_check'])
                self.labels[daemon_item.name]['last_check'].setText(last_check)

                # Check if daemon is a problem
                if self.daemon_is_problem(daemon_item):
                    status_ok = False
            else:
                logger.error('KeyError: %s', daemon_item.name)
                logger.error('\tLabel keys : %s', self.labels.keys())

        return status_ok

    @staticmethod
    def daemon_is_problem(daemon_item):
        """
        Check Daemon Refresh and if daemon is alive. Send a message if needed

        :param daemon_item: Daemon item
        :type daemon_item: alignak_app.items.daemon.Daemon
        :return: if daemon is a problem True, else False
        :rtype: bool
        """

        is_problem = False

        actual_freshness = get_diff_since_last_timestamp(
            daemon_item.data['last_check'], 'minutes')
        freshness = settings.get_config('Alignak-app', 'daemons_freshness')
        if int(actual_freshness) > int(freshness):
            send_event(
                'CRITICAL' if 'arbiter' in daemon_item.name else 'WARNING',
                _('Freshness expired for %s') % daemon_item.name,
                timer=True)
            is_problem = True
            logger.warning('Daemon freshness expired: %s(%dmn)',
                           daemon_item.name, actual_freshness)

        if not daemon_item.data['alive']:
            send_event(
                'CRITICAL' if 'arbiter' in daemon_item.name else 'WARNING',
                _('Daemon %s is dead !') % daemon_item.name,
                timer=True)
            logger.warning('Daemon %s is dead...', daemon_item.name)
            is_problem = True

        return is_problem

    def mousePressEvent(self, event):  # pragma: no cover
        """ QWidget.mousePressEvent(QMouseEvent) """

        self.offset = event.pos()

    def mouseMoveEvent(self, event):  # pragma: no cover
        """ 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))
Example #16
0
    def initialize(self):
        """
        Initialize QWidget

        """

        self.update_status()

        layout = QGridLayout()
        self.setLayout(layout)

        # Backend state
        connected_title = QLabel(_('Backend API'))
        connected_title.setObjectName('subtitle')
        layout.addWidget(connected_title, 0, 0, 1, 1)

        self.backend_connected.setFixedSize(16, 16)
        self.backend_connected.setScaledContents(True)
        self.backend_connected.setToolTip(
            _('Status of the backend API connection'))
        layout.addWidget(self.backend_connected, 0, 1, 1, 1)
        layout.setAlignment(self.backend_connected, Qt.AlignCenter)

        # WS state
        ws_title = QLabel(_('Web Service'))
        ws_title.setObjectName('subtitle')
        layout.addWidget(ws_title, 0, 2, 1, 1)

        self.ws_connected.setFixedSize(16, 16)
        self.ws_connected.setScaledContents(True)
        self.ws_connected.setToolTip(_('Status of the Web Service connection'))
        layout.addWidget(self.ws_connected, 0, 3, 1, 1)
        layout.setAlignment(self.ws_connected, Qt.AlignCenter)

        # Daemons state
        daemons_title = QLabel(_('Alignak'))
        daemons_title.setObjectName('subtitle')
        layout.addWidget(daemons_title, 1, 0, 1, 1)

        self.status_dialog.initialize()
        self.update_status_btn(self.status_dialog.update_dialog())
        self.status_btn.setFixedSize(32, 32)
        self.status_btn.clicked.connect(self.show_status_dialog)
        self.status_btn.setToolTip(_('Status of daemons connection'))
        layout.addWidget(self.status_btn, 1, 1, 1, 1)
        layout.setAlignment(self.status_btn, Qt.AlignCenter)

        # User
        user_lbl = QLabel(_('User'))
        user_lbl.setObjectName('subtitle')
        layout.addWidget(user_lbl, 1, 2, 1, 1)

        self.profile_widget.initialize()
        self.profile_btn.setIcon(QIcon(settings.get_image('user')))
        self.profile_btn.setFixedSize(32, 32)
        self.profile_btn.clicked.connect(self.show_user_widget)
        self.profile_btn.setToolTip(_('View current user'))
        layout.addWidget(self.profile_btn, 1, 3, 1, 1)

        # Refresh timer
        update_status = int(settings.get_config('Alignak-app',
                                                'update_status')) * 1000
        self.refresh_timer.setInterval(update_status)
        self.refresh_timer.start()
        self.refresh_timer.timeout.connect(self.update_status)
class StatusQDialog(QDialog):
    """
        Class who create QWidget for Daemons status.
    """

    def __init__(self, parent=None):
        super(StatusQDialog, self).__init__(parent)
        self.setStyleSheet(settings.css_style)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setObjectName('dialog')
        # Fields
        self.offset = None
        self.daemons_layout = QGridLayout()
        self.labels = {}
        self.no_status_lbl = QLabel()

    def initialize(self):
        """
        Initialize QDialog

        """

        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(0, 0, 0, 0)

        main_layout.addWidget(get_logo_widget(self, _('User View')))

        # Daemons QWidget
        daemons_widget = QWidget(self)
        daemons_widget.setLayout(self.daemons_layout)

        daemons = data_manager.database['alignakdaemon']

        # Init QLabels
        self.init_daemons_labels(daemons)

        # Add daemons label
        line = 0
        self.add_daemon_titles_labels(line)

        for daemon_item in daemons:
            line += 1
            self.add_daemon_labels(daemon_item, line)

        line += 1

        # Ok QPushButton
        ok_btn = QPushButton(_('OK'))
        ok_btn.setObjectName('ok')
        ok_btn.setFixedSize(120, 30)
        ok_btn.clicked.connect(self.accept)
        self.daemons_layout.addWidget(ok_btn, line, 0, 1, 7)
        self.daemons_layout.setAlignment(ok_btn, Qt.AlignCenter)

        main_layout.addWidget(daemons_widget)
        center_widget(self)

    def init_daemons_labels(self, daemons):
        """
        Initialize the daemon QLabels for each daemons

        :param daemons: list of daemon items
        :type daemons: list
        """

        daemons_attributes = [
            'alive', 'name', 'reachable', 'spare', 'address', 'passive', 'last_check'
        ]

        for daemon in daemons:
            self.labels[daemon.name] = {}
            for attribute in daemons_attributes:
                self.labels[daemon.name][attribute] = QLabel()

    def add_daemon_titles_labels(self, line):
        """
        Add QLabels titles for daemons to layout

        :param line: current line of layout
        :type line: int
        """

        # Icon Name Address	Reachable	Spare	Passive daemon	Last check
        icon_title = QLabel(_('State'))
        icon_title.setObjectName('title')
        self.daemons_layout.addWidget(icon_title, line, 0, 1, 1)
        self.daemons_layout.setAlignment(icon_title, Qt.AlignCenter)

        name_title = QLabel(_('Daemon name'))
        name_title.setObjectName('title')
        self.daemons_layout.addWidget(name_title, line, 1, 1, 1)

        address_title = QLabel(_('Address'))
        address_title.setObjectName('title')
        self.daemons_layout.addWidget(address_title, line, 2, 1, 1)

        reachable_title = QLabel(_('Reachable'))
        reachable_title.setObjectName('title')
        self.daemons_layout.addWidget(reachable_title, line, 3, 1, 1)
        self.daemons_layout.setAlignment(reachable_title, Qt.AlignCenter)

        spare_title = QLabel(_('Spare'))
        spare_title.setObjectName('title')
        self.daemons_layout.addWidget(spare_title, line, 4, 1, 1)
        self.daemons_layout.setAlignment(spare_title, Qt.AlignCenter)

        passive_title = QLabel(_('Passive daemon'))
        passive_title.setObjectName('title')
        self.daemons_layout.addWidget(passive_title, line, 5, 1, 1)
        self.daemons_layout.setAlignment(passive_title, Qt.AlignCenter)

        check_title = QLabel(_('Last check'))
        check_title.setObjectName('title')
        self.daemons_layout.addWidget(check_title, line, 6, 1, 1)

    def add_daemon_labels(self, daemon_item, line):
        """
        Add daemon QLabels to layout

        :param daemon_item: daemon item
        :type daemon_item: alignak_app.items.item_daemon.Daemon
        :param line: current line of layout
        :type line: int
        """

        # Alive
        self.labels[daemon_item.name]['alive'].setFixedSize(18, 18)
        self.labels[daemon_item.name]['alive'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['alive'], line, 0, 1, 1)
        self.daemons_layout.setAlignment(self.labels[daemon_item.name]['alive'], Qt.AlignCenter)

        # Name
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['name'], line, 1, 1, 1)

        # Address
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['address'], line, 2, 1, 1)

        # Reachable
        self.labels[daemon_item.name]['reachable'].setFixedSize(14, 14)
        self.labels[daemon_item.name]['reachable'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['reachable'], line, 3, 1, 1)
        self.daemons_layout.setAlignment(self.labels[daemon_item.name]['reachable'], Qt.AlignCenter)

        # Spare
        self.labels[daemon_item.name]['spare'].setFixedSize(14, 14)
        self.labels[daemon_item.name]['spare'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['spare'], line, 4, 1, 1)
        self.daemons_layout.setAlignment(self.labels[daemon_item.name]['spare'], Qt.AlignCenter)

        # Passive
        self.labels[daemon_item.name]['passive'].setFixedSize(14, 14)
        self.labels[daemon_item.name]['passive'].setScaledContents(True)
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['passive'], line, 5, 1, 1)
        self.daemons_layout.setAlignment(self.labels[daemon_item.name]['passive'], Qt.AlignCenter)

        # Last check
        self.daemons_layout.addWidget(self.labels[daemon_item.name]['last_check'], line, 6, 1, 1)

    def update_dialog(self):
        """
        Update StatusQDialog labels and return if all daemons are ok or not

        :return: if status of daemons is ok or not
        :rtype: bool
        """

        daemons = data_manager.database['alignakdaemon']
        status_ok = True

        for daemon_item in daemons:
            if daemon_item.name in self.labels:
                # Connected icon
                self.labels[daemon_item.name]['alive'].setPixmap(
                    get_icon_pixmap(daemon_item.data['alive'], ['connected', 'disconnected'])
                )

                # Labels
                self.labels[daemon_item.name]['name'].setText(daemon_item.name)
                self.labels[daemon_item.name]['address'].setText(
                    '%s:%s' % (daemon_item.data['address'], daemon_item.data['port'])
                )
                self.labels[daemon_item.name]['reachable'].setPixmap(
                    get_icon_pixmap(daemon_item.data['reachable'], ['checked', 'error'])
                )
                self.labels[daemon_item.name]['spare'].setPixmap(
                    get_icon_pixmap(daemon_item.data['spare'], ['checked', 'error'])
                )
                self.labels[daemon_item.name]['passive'].setPixmap(
                    get_icon_pixmap(daemon_item.data['passive'], ['checked', 'error'])
                )
                last_check = get_diff_since_last_timestamp(daemon_item.data['last_check'])
                self.labels[daemon_item.name]['last_check'].setText(last_check)

                # Check if daemon is a problem
                if self.daemon_is_problem(daemon_item):
                    status_ok = False
            else:
                logger.error('KeyError: %s', daemon_item.name)
                logger.error('\tLabel keys : %s', self.labels.keys())

        return status_ok

    @staticmethod
    def daemon_is_problem(daemon_item):
        """
        Check Daemon Refresh and if daemon is alive. Send a message if needed

        :param daemon_item: Daemon item
        :type daemon_item: alignak_app.items.daemon.Daemon
        :return: if daemon is a problem True, else False
        :rtype: bool
        """

        is_problem = False

        actual_freshness = get_diff_since_last_timestamp(
            daemon_item.data['last_check'], 'minutes'
        )
        freshness = settings.get_config('Alignak-app', 'daemons_freshness')
        if int(actual_freshness) > int(freshness):
            send_event(
                'CRITICAL' if 'arbiter' in daemon_item.name else 'WARNING',
                _('Freshness expired for %s') % daemon_item.name,
                timer=True
            )
            is_problem = True
            logger.warning('Daemon freshness expired: %s(%dmn)', daemon_item.name, actual_freshness)

        if not daemon_item.data['alive']:
            send_event(
                'CRITICAL' if 'arbiter' in daemon_item.name else 'WARNING',
                _('Daemon %s is dead !') % daemon_item.name,
                timer=True
            )
            logger.warning('Daemon %s is dead...', daemon_item.name)
            is_problem = True

        return is_problem

    def mousePressEvent(self, event):  # pragma: no cover
        """ QWidget.mousePressEvent(QMouseEvent) """

        self.offset = event.pos()

    def mouseMoveEvent(self, event):  # pragma: no cover
        """ 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 DashboardFactory(QWidget):
    """
        Class who help to create Dashboard QWidget.
    """
    def __init__(self, parent=None):
        super(DashboardFactory, self).__init__(parent)
        self.row = 0
        self.setMaximumWidth(parent.width())
        self.state_data = {}
        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)
        self.setStyleSheet(get_css())

    def create_state_labels(self, state_name):
        """
        Generate 4 QLabel and 1 QProgressBar and store them in "state_data"
        QLabels are: state_icon | state_text | state_number | state_diff
        QProgressBar get value of percent.
        All are added on one row define by "row" value

        :param state_name: name of the state to be stored
        :type state_name: str
        """

        # Icon
        icon = QPixmap(get_image_path(state_name))
        state_icon = QLabel()
        state_icon.setFixedSize(16, 16)
        state_icon.setScaledContents(True)
        state_icon.setPixmap(icon)

        # Initialize Labels
        state_text = QLabel(self.define_label(state_name))
        state_number = QLabel()
        state_diff = QLabel()

        # QProgressBar
        progress_bar = QProgressBar()
        progress_bar.setValue(0)
        progress_bar.setFixedHeight(20)
        progress_bar.setObjectName(state_name)

        # Layout
        self.main_layout.addWidget(state_icon, self.row, 0)
        self.main_layout.addWidget(state_text, self.row, 1)
        self.main_layout.addWidget(state_number, self.row, 2)
        self.main_layout.setAlignment(state_number, Qt.AlignCenter)
        self.main_layout.addWidget(state_diff, self.row, 3)
        self.main_layout.addWidget(progress_bar, self.row, 4)

        # Store state
        self.state_data[state_name] = {
            'icon': state_icon,
            'state_number': state_number,
            'diff': state_diff,
            'progress_bar': progress_bar
        }

        # Increment vertically position for next widget
        self.row += 1

    def add_separator(self):
        """
        Add an horizontal line to layout.
        """

        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Sunken)
        separator.setMinimumSize(self.width(), 2)

        # Add to layout
        self.main_layout.addWidget(separator, self.row, 0, 1, 5)

        # Increment vertically position for next widget
        self.row += 1

    def update_states(self, state_name, nb_items, diff, percent):
        """
        Update nb_items, diff and progress_bar value for the given "state_name"

        :param state_name: name of the state to be update
        :type state_name: str
        :param nb_items: state
        :type nb_items: str
        :param diff: str
        :type diff: str
        :param percent: value of progress bar
        :type percent: int
        """

        # State number
        self.state_data[state_name]['state_number'].setText(str(nb_items))

        # Icon
        if nb_items == 0 and 'downtime' not in state_name and 'acknowledge' not in state_name:
            if 'hosts' in state_name:
                self.state_data[state_name]['icon'].setPixmap(
                    QPixmap(get_image_path('hosts_none')))
            else:
                self.state_data[state_name]['icon'].setPixmap(
                    QPixmap(get_image_path('services_none')))
        else:
            self.state_data[state_name]['icon'].setPixmap(
                QPixmap(get_image_path(state_name)))

        # Diff between last check
        if diff != 0:
            self.state_data[state_name]['diff'].setText('<b>(%s)</b>' %
                                                        "{0:+d}".format(diff))
        else:
            self.state_data[state_name]['diff'].setText('')

        # ProgressBar
        if percent == 0.0:
            self.state_data[state_name]['progress_bar'].setFormat('-')
            self.state_data[state_name]['progress_bar'].setValue(0)
        else:
            self.state_data[state_name]['progress_bar'].setFormat('%.02f%%' %
                                                                  percent)
            self.state_data[state_name]['progress_bar'].setValue(
                float(percent))

    @staticmethod
    def get_percentages_states(synthesis):
        """
        Calculates and return the sum of the items and their percentages

        :param synthesis: backend synthesis data
        :type synthesis: dict
        :return: percentages of each states
        :rtype: dict
        """

        # Initialize percentage
        percentages = {
            'hosts': {},
            'services': {},
        }

        # Get sum for hosts and services
        hosts_sum = 0
        for h_state in synthesis['hosts']:
            hosts_sum += synthesis['hosts'][h_state]
        services_sum = 0
        for s_state in synthesis['services']:
            services_sum += synthesis['services'][s_state]

        # Calculates the percentage
        try:
            for state in synthesis['hosts']:
                percentages['hosts'][state] = \
                    float(synthesis['hosts'][state]) * 100.0 / float(hosts_sum)
            # Services
            for state in synthesis['services']:
                percentages['services'][state] = \
                    float(synthesis['services'][state]) * 100.0 / float(services_sum)
        except ZeroDivisionError as e:
            logger.error(str(e))

        # Fill percentages if not filled before
        host_states = ['up', 'unreachable', 'down', 'acknowledge', 'downtime']
        service_states = [
            'ok', 'warning', 'critical', 'unknown', 'unreachable',
            'acknowledge', 'downtime'
        ]
        for host_state in host_states:
            if host_state not in percentages['hosts']:
                percentages['hosts'][host_state] = 0.0
        for service_state in service_states:
            if service_state not in percentages['services']:
                percentages['services'][service_state] = 0.0

        return percentages

    @staticmethod
    def define_label(name):
        """
        Define label text for QLabel "label_state"

        :param name: name of state
        :type name: str
        :return: label text
        :rtype: str
        """

        label_model = {
            "hosts_up": "Hosts UP:",
            "hosts_down": "Hosts DOWN:",
            "hosts_unreachable": "Hosts UNREACHABLE:",
            "hosts_acknowledge": "Hosts ACKNOWLEDGED:",
            "hosts_downtime": "Hosts DOWNTIMED:",
            "services_ok": "Services OK:",
            "services_warning": "Services WARNING:",
            "services_critical": "Services CRITICAL:",
            "services_unknown": "Services UNKNOWN:",
            "services_unreachable": "Services UNREACHABLE:",
            "services_acknowledge": "Services ACKNOWLEDGED:",
            "services_downtime": "Services DOWNTIMED:",
        }

        try:
            return label_model[name]
        except KeyError as e:
            logger.error('Bad label state name: %s', name)
            logger.error(str(e))
            return 'Unknow field'
    def get_notifications_widget(self, item_type, options):
        """
        Create QWidget with options and their icons

        :param item_type: define item type for options: host or service
        :type item_type: str
        :param options: list of notification options
        :type options: list
        :return: QWidget with options and icons
        :rtype: QWidget
        """

        options_widget = QWidget()
        options_widget.setObjectName('dialog')
        options_layout = QGridLayout(options_widget)

        options_title = QLabel(_("Options:"))
        options_title.setObjectName("itemtitle")
        options_layout.addWidget(options_title, 0, 0, 1, 2)
        options_layout.setAlignment(options_title, Qt.AlignCenter)

        # Get current options and QLabels
        item_options = list(options_values[item_type])
        options_labels = {}
        for option in item_options:
            options_labels[option] = QLabel()

        line = 1
        while item_options:
            if line == 2:
                alert_lbl = QLabel('Alerts:')
                alert_lbl.setObjectName('subtitle')
                options_layout.addWidget(alert_lbl, line, 0, 1, 2)
                line += 1
            else:
                # Current option
                opt = item_options.pop(0)

                # Title
                object_name = ''
                if opt not in ['n', 's', 'f']:
                    object_name = 'offset'
                object_name += 'option' + str(
                    self.get_selected_options(item_type, options)[opt])
                self.titles_labels[item_type][opt].setObjectName(object_name)
                options_layout.addWidget(self.titles_labels[item_type][opt],
                                         line, 0, 1, 1)

                # Icon
                options_labels[opt].setPixmap(
                    get_icon_pixmap(
                        self.get_selected_options(item_type, options)[opt],
                        ['checked', 'error']))
                options_labels[opt].setFixedSize(14, 14)
                options_labels[opt].setScaledContents(True)
                options_layout.addWidget(options_labels[opt], line, 1, 1, 1)
                line += 1

        # Login button
        accept_btn = QPushButton(_('OK'), self)
        accept_btn.clicked.connect(self.accept)
        accept_btn.setObjectName('ok')
        accept_btn.setMinimumHeight(30)
        options_layout.addWidget(accept_btn, line, 0, 1, 2)

        return options_widget
Example #20
0
    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()
Example #21
0
class _ExecuteTab(QTabWidget):
    """Tab used to execute modules or shell commands on the selected bot."""
    def __init__(self, responses_tab: _ResponsesTab, model):
        super().__init__()

        self._model = model
        self._current_layout = None
        self._current_bot = None

        self._layout = QGridLayout()
        self._sub_layout = QVBoxLayout()
        self._module_view = ModuleView(responses_tab)

        self._layout.setAlignment(Qt.AlignTop)
        self.setLayout(self._layout)
        self.set_empty_layout()

    def set_current_bot(self, bot: Bot):
        """Sets the connected bot this tab will interact with."""
        self._current_bot = bot

    def _clear_layout(self):
        while self._layout.count():
            child = self._layout.takeAt(0)

            if child.widget():
                child.widget().deleteLater()
        while self._sub_layout.count():
            child = self._sub_layout.takeAt(0)

            if child.widget():
                child.widget().deleteLater()

    def set_empty_layout(self):
        """Default layout shown when the user has not yet selected a row."""
        self._current_layout = "Empty"
        self._clear_layout()

        self._layout.addWidget(
            QLabel("Please select a bot in the table above."), 0, 0)

    def set_module_layout(self, module_name: str = "screenshot"):
        """Sets the layout which can execute modules."""
        self._current_layout = "Module"
        self._clear_layout()

        command_type_label = QLabel("Command type: ")
        command_type_combobox = QComboBox()

        command_type_combobox.addItem("Module")
        command_type_combobox.addItem("Shell")

        module_label = QLabel("Module name: ")
        module_combobox = QComboBox()

        for module_name in modules.get_names():
            module_combobox.addItem(module_name)

        module_combobox.currentTextChanged.connect(self._on_module_change)
        command_type_combobox.currentTextChanged.connect(
            self._on_command_type_change)

        self._layout.setColumnStretch(1, 1)
        self._layout.addWidget(command_type_label, 0, 0)
        self._layout.addWidget(command_type_combobox, 0, 1)
        self._layout.addWidget(module_label, 1, 0)
        self._layout.addWidget(module_combobox, 1, 1)

        # Module layout
        cached_module = modules.get_module(module_name)

        if not cached_module:
            cached_module = modules.load_module(module_name, self._module_view,
                                                self._model)

        input_fields = []

        for option_name in cached_module.get_setup_messages():
            input_field = QLineEdit()

            self._sub_layout.addWidget(QLabel(option_name))
            self._sub_layout.addWidget(input_field)
            input_fields.append(input_field)

        run_button = QPushButton("Run")
        run_button.setMaximumWidth(250)
        run_button.setMinimumHeight(25)

        run_button.pressed.connect(lambda: self._on_module_run(
            module_combobox.currentText(), input_fields))

        self._sub_layout.addWidget(QLabel(""))
        self._sub_layout.addWidget(run_button)
        self._sub_layout.setContentsMargins(0, 15, 0, 0)
        self._layout.addLayout(self._sub_layout,
                               self._layout.rowCount() + 2, 0, 1, 2)

        self._on_module_change(module_combobox.currentText())

    def set_shell_layout(self):
        """Sets the layout which can execute shell commands."""
        self._current_layout = "Shell"
        self._clear_layout()

        command_type_label = QLabel("Command type: ")
        command_type_combobox = QComboBox()

        command_type_combobox.addItem("Shell")
        command_type_combobox.addItem("Module")

        command_label = QLabel("Command:")
        command_input = QLineEdit()

        run_button = QPushButton("Run")
        run_button.setMaximumWidth(250)
        run_button.setMinimumHeight(25)

        command_type_combobox.currentTextChanged.connect(
            self._on_command_type_change)
        run_button.pressed.connect(lambda: self._on_command_run(command_input))

        self._layout.addWidget(command_type_label, 0, 0)
        self._layout.addWidget(command_type_combobox, 0, 1)
        self._layout.addWidget(command_label, 1, 0)
        self._layout.addWidget(command_input, 1, 1)

        self._sub_layout.addWidget(QLabel(""))
        self._sub_layout.addWidget(run_button)
        self._sub_layout.setContentsMargins(0, 15, 0, 0)
        self._layout.addLayout(self._sub_layout,
                               self._layout.rowCount() + 2, 0, 1, 2)

    def _on_command_type_change(self, text: str):
        """Handles the command type combobox change event."""
        if text == "Module":
            self.set_module_layout()
        else:
            self.set_shell_layout()

    def _on_module_change(self, module_name: str):
        """Handles module combobox changes."""
        while self._sub_layout.count():
            child = self._sub_layout.takeAt(0)

            if child.widget():
                child.widget().deleteLater()

        cached_module = modules.get_module(module_name)

        if not cached_module:
            cached_module = modules.load_module(module_name, self._module_view,
                                                self._model)

        input_fields = []

        for option_name in cached_module.get_setup_messages():
            input_field = QLineEdit()
            input_fields.append(input_field)

            self._sub_layout.addWidget(QLabel(option_name))
            self._sub_layout.addWidget(input_field)

        run_button = QPushButton("Run")
        run_button.setMaximumWidth(250)
        run_button.setMinimumHeight(25)

        run_button.pressed.connect(
            lambda: self._on_module_run(module_name, input_fields))

        self._sub_layout.addWidget(QLabel(""))
        self._sub_layout.addWidget(run_button)
        self._sub_layout.setContentsMargins(0, 15, 0, 0)

    def display_info(self, text: str):
        message_box = QMessageBox()

        message_box.setIcon(QMessageBox.Information)
        message_box.setWindowTitle("Information")
        message_box.setText(text)
        message_box.setStandardButtons(QMessageBox.Ok)
        message_box.exec_()

    def _on_module_run(self, module_name: str, input_fields: list):
        """Handles running modules."""
        set_options = []

        for input_field in input_fields:
            set_options.append(input_field.text())

        module = modules.get_module(module_name)

        if not module:
            module = modules.load_module(module_name, self._module_view,
                                         self._model)

        successful, options = module.setup(set_options)

        if successful:
            if module_name == "remove_bot":
                code = loaders.get_remove_code(self._current_bot.loader_name)
            elif module_name == "update_bot":
                code = loaders.get_update_code(self._current_bot.loader_name)
            else:
                code = modules.get_code(module_name)

            if not options:
                options = {}

            options["module_name"] = module_name

            self._model.add_command(self._current_bot.uid,
                                    Command(CommandType.MODULE, code, options))

            self.display_info("Module added to the queue of:\n {}@{}".format(
                self._current_bot.username, self._current_bot.hostname))

    def _on_command_run(self, command_input: QLineEdit):
        """Handles running commands."""
        if command_input.text().strip() == "":
            return

        self._model.add_command(
            self._current_bot.uid,
            Command(CommandType.SHELL,
                    command_input.text().encode()))

        command_input.clear()
        self.display_info("Command added to the queue of:\n {}@{}".format(
            self._current_bot.username, self._current_bot.hostname))
    def get_notifications_widget(self, item_type, options):
        """
        Create QWidget with options and their icons

        :param item_type: define item type for options: host or service
        :type item_type: str
        :param options: list of notification options
        :type options: list
        :return: QWidget with options and icons
        :rtype: QWidget
        """

        options_widget = QWidget()
        options_widget.setObjectName('dialog')
        options_layout = QGridLayout(options_widget)

        options_title = QLabel(_("Options:"))
        options_title.setObjectName("itemtitle")
        options_layout.addWidget(options_title, 0, 0, 1, 2)
        options_layout.setAlignment(options_title, Qt.AlignCenter)

        # Get current options and QLabels
        item_options = list(options_values[item_type])
        options_labels = {}
        for option in item_options:
            options_labels[option] = QLabel()

        line = 1
        while item_options:
            if line == 2:
                alert_lbl = QLabel('Alerts:')
                alert_lbl.setObjectName('subtitle')
                options_layout.addWidget(alert_lbl, line, 0, 1, 2)
                line += 1
            else:
                # Current option
                opt = item_options.pop(0)

                # Title
                object_name = ''
                if opt not in ['n', 's', 'f']:
                    object_name = 'offset'
                object_name += 'option' + str(self.get_selected_options(item_type, options)[opt])
                self.titles_labels[item_type][opt].setObjectName(object_name)
                options_layout.addWidget(self.titles_labels[item_type][opt], line, 0, 1, 1)

                # Icon
                options_labels[opt].setPixmap(get_icon_pixmap(
                    self.get_selected_options(item_type, options)[opt], ['checked', 'error']
                ))
                options_labels[opt].setFixedSize(14, 14)
                options_labels[opt].setScaledContents(True)
                options_layout.addWidget(options_labels[opt], line, 1, 1, 1)
                line += 1

        # Login button
        accept_btn = QPushButton(_('OK'), self)
        accept_btn.clicked.connect(self.accept)
        accept_btn.setObjectName('ok')
        accept_btn.setMinimumHeight(30)
        options_layout.addWidget(accept_btn, line, 0, 1, 2)

        return options_widget
class BookConfigWidget(QDialog):
    def __init__(self, db, ids, parent):
        QDialog.__init__(self, parent)
        self.resize(500,500)
        self._index = 0

        self._book_settings = []

        http_proxy = get_proxies(debug=False).get('http', None)
        if http_proxy:
            self._proxy = True
            self._http_address = ':'.join(http_proxy.split(':')[:-1])
            self._http_port = int(http_proxy.split(':')[-1])

            aConnection = HTTPConnection(self._http_address, self._http_port)
            aConnection.set_tunnel('www.amazon.com', 80)
            sConnection = HTTPConnection(self._http_address, self._http_port)
            sConnection.set_tunnel('www.shelfari.com', 80)
        else:
            aConnection = HTTPConnection('www.amazon.com')
            sConnection = HTTPConnection('www.shelfari.com')

        for book_id in ids:
            self._book_settings.append(BookSettings(db, book_id, aConnection, sConnection))

        self.v_layout = QVBoxLayout(self)

        self.setWindowTitle('title - author')

        # add asin and shelfari url text boxes
        self.asin_layout = QHBoxLayout(None)
        self.asin_label = QLabel('ASIN:')
        self.asin_label.setFixedWidth(75)
        self.asin_edit = QLineEdit('')
        self.asin_edit.textEdited.connect(self.edit_asin)
        self.asin_layout.addWidget(self.asin_label)
        self.asin_layout.addWidget(self.asin_edit)
        self.v_layout.addLayout(self.asin_layout)

        self.shelfari_layout = QHBoxLayout(None)
        self.shelfari_url = QLabel('Shelfari URL:')
        self.shelfari_url.setFixedWidth(75)
        self.shelfari_url_edit = QLineEdit('')
        self.shelfari_url_edit.textEdited.connect(self.edit_shelfari_url)
        self.shelfari_layout.addWidget(self.shelfari_url)
        self.shelfari_layout.addWidget(self.shelfari_url_edit)
        self.v_layout.addLayout(self.shelfari_layout)

        self.update_buttons_layout = QHBoxLayout(None)
        self.update_asin_button = QPushButton('Search for ASIN')
        self.update_asin_button.setFixedWidth(150)
        self.update_asin_button.clicked.connect(self.search_for_asin)
        self.update_buttons_layout.addWidget(self.update_asin_button)

        self.update_shelfari_url_button = QPushButton('Search for Shelfari URL')
        self.update_shelfari_url_button.setFixedWidth(150)
        self.update_shelfari_url_button.clicked.connect(self.search_for_shelfari_url)
        self.update_buttons_layout.addWidget(self.update_shelfari_url_button)

        self.update_aliases_button = QPushButton('Update Aliases from URL')
        self.update_aliases_button.setFixedWidth(150)
        self.update_aliases_button.clicked.connect(self.update_aliases)
        self.update_buttons_layout.addWidget(self.update_aliases_button)
        self.v_layout.addLayout(self.update_buttons_layout)

        # add scrollable area for aliases
        self.aliases_label = QLabel('Aliases:')
        self.v_layout.addWidget(self.aliases_label)
        self.scroll_area = QScrollArea()
        self.v_layout.addWidget(self.scroll_area)

        # add status box
        self.status = QLabel('')
        self.v_layout.addWidget(self.status)

        # add previous, ok, cancel, and next buttons
        self.buttons_layout = QHBoxLayout(None)
        self.buttons_layout.setAlignment(Qt.AlignRight)

        if len(ids) > 1:
            self.previous_button = QPushButton("Previous")
            self.previous_button.setEnabled(False)
            self.previous_button.setFixedWidth(100)
            self.previous_button.clicked.connect(self.previous)
            self.buttons_layout.addWidget(self.previous_button)

        self.OK_button = QPushButton("OK")
        self.OK_button.setFixedWidth(100)
        self.OK_button.clicked.connect(self.ok)
        self.buttons_layout.addWidget(self.OK_button)

        self.cancel_button = QPushButton("Cancel")
        self.cancel_button.setFixedWidth(100)
        self.cancel_button.clicked.connect(self.cancel)
        self.buttons_layout.addWidget(self.cancel_button)

        if len(ids) > 1:
            self.next_button = QPushButton("Next")
            self.next_button.setFixedWidth(100)
            self.next_button.clicked.connect(self.next)
            self.buttons_layout.addWidget(self.next_button)

        self.v_layout.addLayout(self.buttons_layout)
        self.setLayout(self.v_layout)

        self.show_book_prefs()
        self.show()

    @property
    def book(self):
        return self._book_settings[self._index]
    
    def edit_asin(self, val):
        self.book.asin = val

    def edit_shelfari_url(self, val):
        http_string = 'http://www.'
        index = 0
        if val[:len(http_string)] != http_string:
            for i, letter in enumerate(val):
                if i < len(http_string):
                    if letter == http_string[i]:
                            index += 1
                    else:
                        break
                else:
                    break
            self.shelfari_url_edit.setText(http_string + val[index:])

        self.book.shelfari_url = val

    def search_for_asin(self):
        asin = None
        asin = self.book.get_asin()
        if not asin:
            if self.book.prefs['asin'] != '':
                self.status.setText('ASIN not found. Using original asin.')
                self.asin_edit.setText(self.book.prefs['asin'])
            else:
                self.status.setText('ASIN not found.')
                self.asin_edit.setText('')
        else:
            self.status.setText('ASIN found.')
            self.book.asin = asin
            self.asin_edit.setText(asin)

    def search_for_shelfari_url(self):
        url = None
        if self.asin_edit.text() != '' and self.asin_edit.text() != 'ASIN not found':
            url = self.book.search_shelfari(self.asin_edit.text())
        if not url:
            if self.book._prefs['asin'] != '':
                url = self.book.search_shelfari(self.book._prefs['asin'])
        if not url:
            if self.book.title != 'Unknown' and self.book.author != 'Unknown':
                url = self.book.search_shelfari(self.book.title_and_author)
        if url:
            self.status.setText('Shelfari url found.')
            self.update_aliases_button.setEnabled(True)
            self.book.shelfari_url = url
            self.shelfari_url_edit.setText(url)
        else:
            self.status.setText('Shelfari url not found.')
            self.update_aliases_button.setEnabled(False)
            self.shelfari_url_edit.setText('')

    def update_aliases(self):
        url = self.shelfari_url_edit.text()
        domain_end_index = url[7:].find('/') + 7
        if domain_end_index == -1: domain_end_index = len(url)

        test_url = HTTPConnection(url[7:domain_end_index])
        test_url.request('HEAD', url[domain_end_index:])

        if test_url.getresponse().status == 200:
            self.book.update_aliases(overwrite=True)
            self.update_aliases_on_gui()
            self.status.setText('Aliases updated.')
        else:
            self.status.setText('Invalid shelfari url.')

    def edit_aliases(self, term, val):
        self.book.aliases = (term, val)

    def previous(self):
        self.status.setText('')
        self._index -= 1
        self.next_button.setEnabled(True)
        if self._index == 0:
            self.previous_button.setEnabled(False)
        self.show_book_prefs()

    def ok(self):
        for book in self._book_settings:
            book.save()
        self.close()

    def cancel(self):
        self.close()

    def next(self):
        self.status.setText('')
        self._index += 1
        self.previous_button.setEnabled(True)
        if self._index == len(self._book_settings) - 1:
            self.next_button.setEnabled(False)
        self.show_book_prefs()

    def show_book_prefs(self):
        self.setWindowTitle(self.book.title_and_author)
        self.asin_edit.setText(self.book.asin)
        self.shelfari_url_edit.setText(self.book.shelfari_url)
        self.update_aliases_on_gui()

    def update_aliases_on_gui(self):
        self.aliases_widget = QWidget()
        self.aliases_layout = QGridLayout(self.aliases_widget)
        self.aliases_layout.setAlignment(Qt.AlignTop)

        # add aliases for current book
        for index, aliases in enumerate(sorted(self.book.aliases.items())):
            label = QLabel(aliases[0] + ':')
            label.setFixedWidth(125)
            self.aliases_layout.addWidget(label, index, 0)

            line_edit = QLineEdit(', '.join(aliases[1]))
            line_edit.setFixedWidth(300)
            line_edit.textEdited.connect(functools.partial(self.edit_aliases, aliases[0]))
            self.aliases_layout.addWidget(line_edit, index, 1)

        self.scroll_area.setWidget(self.aliases_widget)