HEX
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/8.4.25
System: Windows NT DESKTOP-4TAV2RJ 10.0 build 19045 (Windows 10) AMD64
User: fred (0)
PHP: 8.4.25
Disabled: NONE
Upload Files
File: C:/Users/fred/anaconda3/Lib/site-packages/navigator_updater/widgets/dialogs/__init__.py
# -*- coding: utf-8 -*-

# pylint: disable=invalid-name,no-name-in-module,too-many-lines,unused-argument

# -----------------------------------------------------------------------------
# Copyright 2016 Anaconda, Inc.
#
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
# -----------------------------------------------------------------------------

"""Custom widgets used for dialog definition and styling."""

from qtpy.QtCore import Qt, QUrl, Signal
from qtpy.QtGui import QDesktopServices
from qtpy.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QTextEdit, QVBoxLayout

from navigator_updater.widgets import (
    ButtonBase, ButtonDanger, ButtonNormal, ButtonPrimary, FrameBase, LabelBase, SpacerHorizontal, SpacerVertical,
)


class FrameDialog(FrameBase):
    """Frame widget used for CSS styling of the body dialogs."""


class FrameDialogBody(FrameBase):
    """Frame widget used for CSS styling of the body dialogs."""


class FrameDialogTitleBar(FrameBase):
    """Frame widget used for CSS styling of the title bar of dialogs."""

    # pos, old_pos
    sig_moved = Signal(object, object)

    def __init__(self, parent=None):
        """Frame widget used for CSS styling of the title bar of dialogs."""
        super().__init__(parent=parent)
        self._mouse_pressed = False
        self.setMouseTracking(True)
        self._old_pos = None

    def mousePressEvent(self, event):
        """Override Qt method."""
        self._mouse_pressed = True
        self._old_pos = event.globalPos()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        """Override Qt method."""
        if self._mouse_pressed:
            self.sig_moved.emit(event.globalPos(), self._old_pos)
            self._old_pos = event.globalPos()
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        """Override Qt method."""
        self._mouse_pressed = False
        super().mouseReleaseEvent(event)


class LabelDialogTitleBar(LabelBase):
    """Label used for CSS styling of the title of dialogs."""


class ButtonDialogClose(ButtonBase):
    """Button used for CSS styling ot the close dialog button."""


class DialogBase(QDialog):
    """Base dialog widget."""

    def __init__(self, *args, **kwargs):
        """Base dialog widget."""
        super().__init__(*args, **kwargs)

        # Widgets
        self.frame_dialog = FrameDialog(self)
        self.frame_title_bar = FrameDialogTitleBar(self)
        self.frame_body = FrameDialogBody(self)
        self.button_close_dialog = ButtonDialogClose('X')
        self.label_title_bar = LabelDialogTitleBar('Title')
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.MSWindowsFixedSizeDialogHint)
        self.setSizeGripEnabled(False)

        # Widget setup
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
        self.button_close_dialog.setFocusPolicy(Qt.NoFocus)

        # Signals
        self.button_close_dialog.clicked.connect(self.reject)
        self.frame_title_bar.sig_moved.connect(self._move_dialog)

    def setWindowTitle(self, title):
        """Qt override."""
        self.label_title_bar.setText(title)

    def setLayout(self, body_layout):
        """Qt override."""
        title_layout = QHBoxLayout()
        title_layout.addWidget(self.label_title_bar)
        title_layout.addStretch(100000000)
        title_layout.addWidget(self.button_close_dialog)
        title_layout.setContentsMargins(0, 0, 0, 0)
        self.frame_title_bar.setLayout(title_layout)
        self.frame_body.setLayout(body_layout)

        layout_dialog = QVBoxLayout()
        layout_dialog.addWidget(self.frame_title_bar)
        layout_dialog.addWidget(self.frame_body)
        layout_dialog.setContentsMargins(0, 0, 0, 0)
        layout_dialog.setSpacing(0)
        self.frame_dialog.setLayout(layout_dialog)

        layout = QVBoxLayout()
        layout.addWidget(self.frame_dialog)
        self._fix_layout(layout)
        self._fix_layout(title_layout)
        super().setLayout(layout)

        # self.frame_title_bar.setMidLineWidth(self.frame_body.width())

    def _move_dialog(self, pos, old_pos):
        """Postion dialog callback to emulate title bar grab."""
        dx = old_pos.x() - pos.x()
        dy = old_pos.y() - pos.y()
        pos = self.pos()
        self.move(pos.x() - dx, pos.y() - dy)

    def _fix_layout(self, layout):
        if layout:
            layout.setSpacing(0)
            layout.setContentsMargins(0, 0, 0, 0)
            # layout.setSizeConstraint(QLayout.SetFixedSize)

            items = (layout.itemAt(i).widget() for i in range(layout.count()))
            for w in items:
                if w:
                    new_layout = w.layout()
                    self._fix_layout(new_layout)
        return layout


class MessageBox(DialogBase):  # pylint: disable=too-many-instance-attributes
    """Base message box dialog."""

    QUESTION_BOX = 100
    INFORMATION_BOX = 101
    ERROR_BOX = 102
    REMOVE_BOX = 103

    sig_url_clicked = Signal(object)

    def __init__(  # pylint: disable=too-many-arguments,too-many-statements
            self, type_, error='', title='', text='', learn_more=None
    ):
        """Base message box dialog."""
        super().__init__()
        #        self.tracker = GATracker()
        self.label_text = QLabel(text)
        self.textbox_error = QTextEdit()
        self.button_ok = ButtonPrimary('Ok')
        self.button_yes = ButtonPrimary('Yes')
        self.button_no = ButtonNormal('No')
        self.button_copy = ButtonNormal('Copy text')
        self.button_learn = ButtonNormal('Learn more')
        self.button_remove = ButtonDanger('Remove')
        self.button_cancel = ButtonNormal('Cancel')
        self.bbox = QDialogButtonBox(Qt.Horizontal)

        self.label_text.setOpenExternalLinks(False)
        self.label_text.linkActivated.connect(self.url_clicked)
        self.textbox_error.setReadOnly(True)
        self.textbox_error.setFrameStyle(QTextEdit.Plain)
        self.textbox_error.setFrameShape(QTextEdit.NoFrame)
        self.setMinimumWidth(260)
        self.textbox_error.verticalScrollBar().show()
        self.setWindowTitle(title)

        error = error.split('\n')
        error = '<br>'.join(error)
        self.textbox_error.setText(error)

        # Layouts
        layout = QVBoxLayout()
        layout.addWidget(self.label_text)
        layout.addWidget(SpacerVertical())
        if error:
            layout.addWidget(self.textbox_error)
            layout.addWidget(SpacerVertical())
            layout.addWidget(self.button_copy)
            layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())

        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()

        layout.addLayout(layout_buttons)

        self.layout = layout
        self.setLayout(layout)

        # Signals
        self.button_copy.clicked.connect(self.copy_text)
        self.button_ok.clicked.connect(self.accept)
        self.button_yes.clicked.connect(self.accept)
        self.button_no.clicked.connect(self.reject)
        self.button_remove.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)

        # Setup
        self.button_learn.setVisible(bool(learn_more))
        if bool(learn_more):
            layout_buttons.addWidget(self.button_learn)
            layout_buttons.addWidget(SpacerHorizontal())
            self.button_learn.clicked.connect(
                lambda: self.show_url(learn_more)
            )

        if type_ == self.ERROR_BOX:
            layout_buttons.addWidget(self.button_ok)
            self.button_yes.setVisible(False)
            self.button_no.setVisible(False)
            self.button_remove.setVisible(False)
            self.button_cancel.setVisible(False)
        elif type_ == self.INFORMATION_BOX:
            layout_buttons.addWidget(self.button_ok)
            self.button_yes.setVisible(False)
            self.button_no.setVisible(False)
            self.textbox_error.setVisible(False)
            self.button_copy.setVisible(False)
            self.button_remove.setVisible(False)
            self.button_cancel.setVisible(False)
        elif type_ == self.QUESTION_BOX:
            layout_buttons.addStretch()
            layout_buttons.addWidget(self.button_no)
            layout_buttons.addWidget(SpacerHorizontal())
            layout_buttons.addWidget(self.button_yes)
            layout_buttons.addWidget(SpacerHorizontal())
            self.textbox_error.setVisible(False)
            self.button_ok.setVisible(False)
            self.button_copy.setVisible(False)
            self.button_remove.setVisible(False)
            self.button_cancel.setVisible(False)
        elif type_ == self.REMOVE_BOX:
            layout_buttons.addStretch()
            layout_buttons.addWidget(self.button_cancel)
            layout_buttons.addWidget(SpacerHorizontal())
            layout_buttons.addWidget(self.button_remove)
            layout_buttons.addWidget(SpacerHorizontal())
            self.textbox_error.setVisible(False)
            self.button_ok.setVisible(False)
            self.button_copy.setVisible(False)
            self.button_yes.setVisible(False)
            self.button_no.setVisible(False)

    def url_clicked(self, url):
        """Emit url interaction."""
        self.sig_url_clicked.emit(url)

    def copy_text(self):
        """Copy all the content of the displayed error message."""
        self.textbox_error.selectAll()
        self.textbox_error.copy()

    def show_url(self, url=None):
        """Open url in default browser."""
        if url:
            qurl = QUrl(url)
            QDesktopServices.openUrl(qurl)
            self.tracker.track_event('help', 'documentation', url)


class MessageBoxInformation(MessageBox):
    """Information message box."""

    def __init__(self, text='', error='', title=''):
        """Information message box."""
        super().__init__(
            text=text,
            title=title,
            type_=self.INFORMATION_BOX,
        )