Ejemplo n.º 1
0
def check_executable_path_error_qt(path: Path, /) -> None:
    """Display an error using Qt about the app not running from the right path."""

    from nxdrive.qt import constants as qt
    from nxdrive.qt.imports import QApplication, QMessageBox, QPixmap
    from nxdrive.translator import Translator
    from nxdrive.utils import find_icon, find_resource

    app = QApplication([])
    app.setQuitOnLastWindowClosed(True)

    Translator(find_resource("i18n"))
    content = Translator.get("RUNNING_FROM_WRONG_PATH",
                             values=[str(path), f"{APP_NAME}.app"])

    icon = QPixmap(str(find_icon("app_icon.svg")))
    msg = QMessageBox()
    msg.setIconPixmap(icon)
    msg.setText(content)
    msg.setWindowTitle(APP_NAME)
    msg.addButton(Translator.get("QUIT"), qt.AcceptRole)
    msg.exec_()
Ejemplo n.º 2
0
def fatal_error_qt(exc_formatted: str) -> None:
    """Display a "friendly" dialog box on fatal error using Qt."""

    from PyQt5.QtCore import Qt, QUrl
    from PyQt5.QtGui import QDesktopServices, QIcon
    from PyQt5.QtWidgets import (
        QApplication,
        QDialog,
        QDialogButtonBox,
        QLabel,
        QTextEdit,
        QVBoxLayout,
    )

    from nxdrive.translator import Translator
    from nxdrive.utils import find_icon, find_resource

    def section(header: str, content: str) -> str:
        """Format a "section" of information."""
        return f"{header}\n```\n{content.strip()}\n```"

    Translator(find_resource("i18n"))
    tr = Translator.get

    app = QApplication([])
    app.setQuitOnLastWindowClosed(True)

    dialog = QDialog()
    dialog.setWindowTitle(tr("FATAL_ERROR_TITLE", [APP_NAME]))
    dialog.setWindowIcon(QIcon(str(find_icon("app_icon.svg"))))
    dialog.resize(800, 600)
    layout = QVBoxLayout()
    css = "font-family: monospace; font-size: 12px;"
    details = []

    # Display a little message to apologize
    info = QLabel(tr("FATAL_ERROR_MSG", [APP_NAME, COMPANY]))
    info.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
    layout.addWidget(info)

    # Display CLI arguments
    if sys.argv[1:]:
        text = tr("FATAL_ERROR_CLI_ARGS")
        label_cli = QLabel(text)
        label_cli.setAlignment(Qt.AlignVCenter)
        cli_args = QTextEdit()
        cli_args.setStyleSheet(css)
        cli_args.setReadOnly(True)
        args = "\n".join(arg for arg in sys.argv[1:])
        details.append(section(text, args))
        cli_args.setText(args)
        cli_args.setSizeAdjustPolicy(QTextEdit.AdjustToContents)
        layout.addWidget(label_cli)
        layout.addWidget(cli_args)

    # Display the exception
    text = tr("FATAL_ERROR_EXCEPTION")
    label_exc = QLabel(text)
    label_exc.setAlignment(Qt.AlignVCenter)
    exception = QTextEdit()
    exception.setStyleSheet(css)
    exception.setReadOnly(True)
    details.append(section(text, exc_formatted))
    exception.setText(exc_formatted)
    layout.addWidget(label_exc)
    layout.addWidget(exception)

    # Display last lines from the memory log
    with suppress(Exception):
        from nxdrive.report import Report

        # Last 20th lines
        raw_lines = Report.export_logs(-20)
        lines = b"\n".join(raw_lines).decode(errors="replace")

        if lines:
            text = tr("FATAL_ERROR_LOGS")
            label_log = QLabel(text)
            details.append(section(text, lines))
            label_log.setAlignment(Qt.AlignVCenter)
            layout.addWidget(label_log)

            logs = QTextEdit()
            logs.setStyleSheet(css)
            logs.setReadOnly(True)
            logs.setLineWrapColumnOrWidth(4096)
            logs.setLineWrapMode(QTextEdit.FixedPixelWidth)
            logs.setText(lines)
            layout.addWidget(logs)

    def open_update_site() -> None:
        """Open the update web site."""
        with suppress(Exception):
            QDesktopServices.openUrl(QUrl(Options.update_site_url))

    # Buttons
    buttons = QDialogButtonBox()
    buttons.setStandardButtons(QDialogButtonBox.Ok)
    buttons.accepted.connect(dialog.close)
    update_button = buttons.addButton(tr("FATAL_ERROR_UPDATE_BTN"),
                                      QDialogButtonBox.ActionRole)
    update_button.setToolTip(tr("FATAL_ERROR_UPDATE_TOOLTIP", [APP_NAME]))
    update_button.clicked.connect(open_update_site)
    layout.addWidget(buttons)

    def copy() -> None:
        """Copy details to the clipboard and change the text of the button. """
        osi.cb_set("\n".join(details))
        copy_paste.setText(tr("FATAL_ERROR_DETAILS_COPIED"))

    # "Copy details" button
    with suppress(Exception):
        from nxdrive.osi import AbstractOSIntegration

        osi = AbstractOSIntegration.get(None)
        copy_paste = buttons.addButton(tr("FATAL_ERROR_DETAILS_COPY"),
                                       QDialogButtonBox.ActionRole)
        copy_paste.clicked.connect(copy)

    dialog.setLayout(layout)
    dialog.show()
    app.exec_()
Ejemplo n.º 3
0
def show_critical_error() -> None:
    """ Display a "friendly" dialog box on fatal error. """

    import traceback

    from PyQt5.QtCore import Qt
    from PyQt5.QtGui import QIcon
    from PyQt5.QtWidgets import (
        QApplication,
        QDialog,
        QDialogButtonBox,
        QLabel,
        QTextEdit,
        QVBoxLayout,
    )

    app = QApplication([])
    app.setQuitOnLastWindowClosed(True)

    dialog = QDialog()
    dialog.setWindowTitle("Nuxeo Drive - Fatal error")
    dialog.resize(600, 400)
    layout = QVBoxLayout()
    css = "font-family: monospace; font-size: 12px;"
    details = ["Exception:"]

    with suppress(Exception):
        from nxdrive.utils import find_icon

        dialog.setWindowIcon(QIcon(find_icon("app_icon.svg")))

    # Display a little message to apologize
    text = f"""Ooops! Unfortunately, a fatal error occurred and Nuxeo Drive has stopped.
Please share the following informations with Nuxeo support : we’ll do our best to fix it!
"""
    info = QLabel(text)
    info.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
    layout.addWidget(info)

    # Display the the exception
    label_exc = QLabel("Exception:")
    label_exc.setAlignment(Qt.AlignVCenter)
    exception = QTextEdit()
    exception.setStyleSheet(css)
    exception.setReadOnly(True)
    exc_formatted = traceback.format_exception(*sys.exc_info())
    details += exc_formatted
    exception.setText("".join(exc_formatted))
    layout.addWidget(label_exc)
    layout.addWidget(exception)

    # Display last lines from the memory log
    with suppress(Exception):
        from nxdrive.report import Report

        # Last 20th lines
        lines = Report.export_logs(-20)
        lines = b"\n".join(lines).decode(errors="replace")

        details += ["Logs before the crash:", lines]
        label_log = QLabel("Logs before the crash:")
        label_log.setAlignment(Qt.AlignVCenter)
        layout.addWidget(label_log)

        logs = QTextEdit()
        logs.setStyleSheet(css)
        logs.setReadOnly(True)
        logs.setLineWrapColumnOrWidth(4096)
        logs.setLineWrapMode(QTextEdit.FixedPixelWidth)
        logs.setText(lines)
        layout.addWidget(logs)

    # Buttons
    buttons = QDialogButtonBox()
    buttons.setStandardButtons(QDialogButtonBox.Ok)
    buttons.accepted.connect(dialog.close)
    layout.addWidget(buttons)

    def copy() -> None:
        """Copy details to the clipboard and change the text of the button. """
        copy_to_clipboard("\n".join(details))
        copy_paste.setText("Details copied!")

    # "Copy details" button
    with suppress(Exception):
        from nxdrive.utils import copy_to_clipboard

        copy_paste = buttons.addButton("Copy details",
                                       QDialogButtonBox.ActionRole)
        copy_paste.clicked.connect(copy)

    dialog.setLayout(layout)
    dialog.show()
    app.exec_()