class SourceWidget(QWidget):
    """
    Used to display summary information about a source in the list view.
    """

    CSS = '''
    QWidget#color_bar {
        background-color: #9211ff;
    }
    QLabel#source_name {
        font-family: Open Sans;
        font-size: 16px;
        font-weight: bold;
        color: #000;
    }
    QLabel#timestamp {
        font-family: Open Sans;
        font-size: 12px;
        color: #000;
    }
    '''

    def __init__(self, source: Source):
        super().__init__()

        # Store source
        self.source = source

        # Set css id
        self.setObjectName('source_widget')

        # Set styles
        self.setStyleSheet(self.CSS)

        # Set layout
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        # Remove margins and spacing
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(0)

        # Set up gutter
        self.gutter = QWidget()
        self.gutter.setObjectName('gutter')
        self.gutter.setFixedWidth(30)
        gutter_layout = QVBoxLayout(self.gutter)
        gutter_layout.setContentsMargins(0, 0, 0, 0)
        gutter_layout.setSpacing(0)
        self.star = StarToggleButton(self.source)
        spacer = QWidget()
        gutter_layout.addWidget(self.star)
        gutter_layout.addWidget(spacer)

        # Set up summary
        self.summary = QWidget()
        self.summary.setObjectName('summary')
        summary_layout = QVBoxLayout(self.summary)
        summary_layout.setContentsMargins(0, 0, 0, 0)
        summary_layout.setSpacing(0)
        self.name = QLabel()
        self.name.setObjectName('source_name')
        self.preview = QLabel('')
        self.preview.setObjectName('preview')
        self.preview.setWordWrap(True)
        summary_layout.addWidget(self.name)
        summary_layout.addWidget(self.preview)

        # Set up metadata
        self.metadata = QWidget()
        self.metadata.setObjectName('metadata')
        metadata_layout = QVBoxLayout(self.metadata)
        metadata_layout.setContentsMargins(0, 0, 0, 0)
        metadata_layout.setSpacing(0)
        self.attached = SvgLabel('paperclip.svg', QSize(16, 16))
        self.attached.setObjectName('paperclip')
        self.attached.setFixedSize(QSize(20, 20))
        spacer = QWidget()
        metadata_layout.addWidget(self.attached, 1, Qt.AlignRight)
        metadata_layout.addWidget(spacer, 1)

        # Set up source row
        self.source_row = QWidget()
        source_row_layout = QHBoxLayout(self.source_row)
        source_row_layout.setContentsMargins(0, 0, 0, 0)
        source_row_layout.setSpacing(0)
        source_row_layout.addWidget(self.gutter, 1)
        source_row_layout.addWidget(self.summary, 1)
        source_row_layout.addWidget(self.metadata, 1)

        # Set up timestamp
        self.updated = QLabel()
        self.updated.setObjectName('timestamp')

        # Add widgets to main layout
        layout.addWidget(self.source_row, 1)
        layout.addWidget(self.updated, 1, Qt.AlignRight)

        self.update()

    def setup(self, controller):
        """
        Pass through the controller object to this widget.
        """
        self.controller = controller
        self.star.setup(self.controller)

    def update(self):
        """
        Updates the displayed values with the current values from self.source.
        """
        self.updated.setText(arrow.get(self.source.last_updated).humanize())
        self.name.setText("<strong>{}</strong>".format(
            html.escape(self.source.journalist_designation)))
        if self.source.document_count == 0:
            self.attached.hide()

    def delete_source(self, event):
        if self.controller.api is None:
            self.controller.on_action_requiring_login()
            return
        else:
            messagebox = DeleteSourceMessageBox(self, self.source,
                                                self.controller)
            messagebox.launch()
class ErrorStatusBar(QWidget):
    """
    A pop-up status bar for displaying messages about application errors to the user. Messages will
    be displayed for a given duration or until the message is cleared or updated with a new message.
    """

    CSS = '''
    #error_vertical_bar {
        background-color: #f22b5d;
    }
    #error_icon {
        background-color: qlineargradient(
            x1: 0,
            y1: 0,
            x2: 0,
            y2: 1,
            stop: 0 #fff,
            stop: 0.2 #fff,
            stop: 1 #fff
        );
    }
    #error_status_bar {
        background-color: qlineargradient(
            x1: 0,
            y1: 0,
            x2: 0,
            y2: 1,
            stop: 0 #fff,
            stop: 0.2 #fff,
            stop: 1 #fff
        );
        font-weight: bold;
        color: #f22b5d;
    }
    '''

    def __init__(self):
        super().__init__()

        # Set styles
        self.setStyleSheet(self.CSS)

        # Set layout
        layout = QHBoxLayout(self)
        self.setLayout(layout)

        # Remove margins and spacing
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        # Error vertical bar
        self.vertical_bar = QWidget()
        self.vertical_bar.setObjectName('error_vertical_bar')  # Set css id
        self.vertical_bar.setFixedWidth(10)

        # Error icon
        self.label = SvgLabel('error_icon.svg', svg_size=QSize(32, 32))
        self.label.setObjectName('error_icon')  # Set css id
        self.label.setFixedWidth(42)

        # Error status bar
        self.status_bar = QStatusBar()
        self.status_bar.setObjectName('error_status_bar')  # Set css id
        self.status_bar.setSizeGripEnabled(False)

        # Add widgets to layout
        layout.addWidget(self.vertical_bar)
        layout.addWidget(self.label)
        layout.addWidget(self.status_bar)

        # Hide until a message needs to be displayed
        self.vertical_bar.hide()
        self.label.hide()
        self.status_bar.hide()

        # Only show errors for a set duration
        self.status_timer = QTimer()
        self.status_timer.timeout.connect(self._on_status_timeout)

    def _hide(self):
        self.vertical_bar.hide()
        self.label.hide()
        self.status_bar.hide()

    def _show(self):
        self.vertical_bar.show()
        self.label.show()
        self.status_bar.show()

    def _on_status_timeout(self):
        self._hide()

    def update_message(self, message: str, duration: int):
        """
        Display a status message to the user for a given duration.
        """
        self.status_bar.showMessage(message, duration)
        self.status_timer.start(duration)
        self._show()

    def clear_message(self):
        """
        Clear any message currently in the status bar.
        """
        self.status_bar.clearMessage()
        self._hide()