Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor extract conversation.PrintFileDialog #1498

Merged
merged 2 commits into from
May 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions securedrop_client/gui/conversation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
# Import classes here to make possible to import them from securedrop_client.gui.conversation
from .delete import DeleteConversationDialog # noqa: F401
from .export import Dialog as ExportFileDialog # noqa: F401
from .export import PrintDialog as PrintFileDialog # noqa: F401
1 change: 1 addition & 0 deletions securedrop_client/gui/conversation/export/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .dialog import ExportDialog as Dialog # noqa: F401
from .print_dialog import PrintDialog # noqa: F401
134 changes: 134 additions & 0 deletions securedrop_client/gui/conversation/export/print_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
from gettext import gettext as _

from PyQt5.QtCore import QSize, pyqtSlot

from securedrop_client.export import ExportError, ExportStatus
from securedrop_client.gui.base import ModalDialog, SecureQLabel
from securedrop_client.logic import Controller


class PrintDialog(ModalDialog):

FILENAME_WIDTH_PX = 260

def __init__(self, controller: Controller, file_uuid: str, file_name: str) -> None:
super().__init__()

self.controller = controller
self.file_uuid = file_uuid
self.file_name = SecureQLabel(
file_name, wordwrap=False, max_length=self.FILENAME_WIDTH_PX
).text()
self.error_status = "" # Hold onto the error status we receive from the Export VM

# Connect controller signals to slots
self.controller.export.printer_preflight_success.connect(self._on_preflight_success)
self.controller.export.printer_preflight_failure.connect(self._on_preflight_failure)

# Connect parent signals to slots
self.continue_button.setEnabled(False)
self.continue_button.clicked.connect(self._run_preflight)

# Dialog content
self.starting_header = _(
"Preparing to print:"
"<br />"
'<span style="font-weight:normal">{}</span>'.format(self.file_name)
)
self.ready_header = _(
"Ready to print:"
"<br />"
'<span style="font-weight:normal">{}</span>'.format(self.file_name)
)
self.insert_usb_header = _("Connect USB printer")
self.error_header = _("Printing failed")
self.starting_message = _(
"<h2>Managing printout risks</h2>"
"<b>QR codes and web addresses</b>"
"<br />"
"Never type in and open web addresses or scan QR codes contained in printed "
"documents without taking security precautions. If you are unsure how to "
"manage this risk, please contact your administrator."
"<br /><br />"
"<b>Printer dots</b>"
"<br />"
"Any part of a printed page may contain identifying information "
"invisible to the naked eye, such as printer dots. Please carefully "
"consider this risk when working with or publishing scanned printouts."
)
self.insert_usb_message = _("Please connect your printer to a USB port.")
self.generic_error_message = _("See your administrator for help.")

self._show_starting_instructions()
self.start_animate_header()
self._run_preflight()

def _show_starting_instructions(self) -> None:
self.header.setText(self.starting_header)
self.body.setText(self.starting_message)
self.error_details.hide()
self.adjustSize()

def _show_insert_usb_message(self) -> None:
self.continue_button.clicked.disconnect()
self.continue_button.clicked.connect(self._run_preflight)
self.header.setText(self.insert_usb_header)
self.body.setText(self.insert_usb_message)
self.error_details.hide()
self.adjustSize()

def _show_generic_error_message(self) -> None:
self.continue_button.clicked.disconnect()
self.continue_button.clicked.connect(self.close)
self.continue_button.setText(_("DONE"))
self.header.setText(self.error_header)
self.body.setText( # nosemgrep: semgrep.untranslated-gui-string
"{}: {}".format(self.error_status, self.generic_error_message)
)
self.error_details.hide()
self.adjustSize()

@pyqtSlot()
def _run_preflight(self) -> None:
self.controller.run_printer_preflight_checks()

@pyqtSlot()
def _print_file(self) -> None:
self.controller.print_file(self.file_uuid)
self.close()

@pyqtSlot()
def _on_preflight_success(self) -> None:
# If the continue button is disabled then this is the result of a background preflight check
self.stop_animate_header()
self.header_icon.update_image("printer.svg", svg_size=QSize(64, 64))
self.header.setText(self.ready_header)
if not self.continue_button.isEnabled():
self.continue_button.clicked.disconnect()
self.continue_button.clicked.connect(self._print_file)
self.continue_button.setEnabled(True)
self.continue_button.setFocus()
return

self._print_file()

@pyqtSlot(object)
def _on_preflight_failure(self, error: ExportError) -> None:
self.stop_animate_header()
self.header_icon.update_image("printer.svg", svg_size=QSize(64, 64))
self.error_status = error.status
# If the continue button is disabled then this is the result of a background preflight check
if not self.continue_button.isEnabled():
self.continue_button.clicked.disconnect()
if error.status == ExportStatus.PRINTER_NOT_FOUND.value:
self.continue_button.clicked.connect(self._show_insert_usb_message)
else:
self.continue_button.clicked.connect(self._show_generic_error_message)

self.continue_button.setEnabled(True)
self.continue_button.setFocus()
else:
if error.status == ExportStatus.PRINTER_NOT_FOUND.value:
self._show_insert_usb_message()
else:
self._show_generic_error_message()
142 changes: 6 additions & 136 deletions securedrop_client/gui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,17 @@
Source,
User,
)
from securedrop_client.export import ExportError, ExportStatus
from securedrop_client.gui.actions import (
DeleteConversationAction,
DeleteSourceAction,
DownloadConversation,
)
from securedrop_client.gui.base import (
ModalDialog,
SecureQLabel,
SvgLabel,
SvgPushButton,
SvgToggleButton,
from securedrop_client.gui.base import SecureQLabel, SvgLabel, SvgPushButton, SvgToggleButton
from securedrop_client.gui.conversation import (
DeleteConversationDialog,
ExportFileDialog,
PrintFileDialog,
)
from securedrop_client.gui.conversation import DeleteConversationDialog, ExportFileDialog
from securedrop_client.gui.source import DeleteSourceDialog
from securedrop_client.logic import Controller
from securedrop_client.resources import load_css, load_icon, load_image, load_movie
Expand Down Expand Up @@ -2411,7 +2408,7 @@ def _on_print_clicked(self) -> None:
if not self.controller.downloaded_file_exists(self.file):
return

dialog = PrintDialog(self.controller, self.uuid, self.file.filename)
dialog = PrintFileDialog(self.controller, self.uuid, self.file.filename)
dialog.exec()

def _on_left_click(self) -> None:
Expand Down Expand Up @@ -2461,133 +2458,6 @@ def stop_button_animation(self) -> None:
self._set_file_state()


class PrintDialog(ModalDialog):

FILENAME_WIDTH_PX = 260

def __init__(self, controller: Controller, file_uuid: str, file_name: str) -> None:
super().__init__()

self.controller = controller
self.file_uuid = file_uuid
self.file_name = SecureQLabel(
file_name, wordwrap=False, max_length=self.FILENAME_WIDTH_PX
).text()
self.error_status = "" # Hold onto the error status we receive from the Export VM

# Connect controller signals to slots
self.controller.export.printer_preflight_success.connect(self._on_preflight_success)
self.controller.export.printer_preflight_failure.connect(self._on_preflight_failure)

# Connect parent signals to slots
self.continue_button.setEnabled(False)
self.continue_button.clicked.connect(self._run_preflight)

# Dialog content
self.starting_header = _(
"Preparing to print:"
"<br />"
'<span style="font-weight:normal">{}</span>'.format(self.file_name)
)
self.ready_header = _(
"Ready to print:"
"<br />"
'<span style="font-weight:normal">{}</span>'.format(self.file_name)
)
self.insert_usb_header = _("Connect USB printer")
self.error_header = _("Printing failed")
self.starting_message = _(
"<h2>Managing printout risks</h2>"
"<b>QR codes and web addresses</b>"
"<br />"
"Never type in and open web addresses or scan QR codes contained in printed "
"documents without taking security precautions. If you are unsure how to "
"manage this risk, please contact your administrator."
"<br /><br />"
"<b>Printer dots</b>"
"<br />"
"Any part of a printed page may contain identifying information "
"invisible to the naked eye, such as printer dots. Please carefully "
"consider this risk when working with or publishing scanned printouts."
)
self.insert_usb_message = _("Please connect your printer to a USB port.")
self.generic_error_message = _("See your administrator for help.")

self._show_starting_instructions()
self.start_animate_header()
self._run_preflight()

def _show_starting_instructions(self) -> None:
self.header.setText(self.starting_header)
self.body.setText(self.starting_message)
self.error_details.hide()
self.adjustSize()

def _show_insert_usb_message(self) -> None:
self.continue_button.clicked.disconnect()
self.continue_button.clicked.connect(self._run_preflight)
self.header.setText(self.insert_usb_header)
self.body.setText(self.insert_usb_message)
self.error_details.hide()
self.adjustSize()

def _show_generic_error_message(self) -> None:
self.continue_button.clicked.disconnect()
self.continue_button.clicked.connect(self.close)
self.continue_button.setText(_("DONE"))
self.header.setText(self.error_header)
self.body.setText( # nosemgrep: semgrep.untranslated-gui-string
"{}: {}".format(self.error_status, self.generic_error_message)
)
self.error_details.hide()
self.adjustSize()

@pyqtSlot()
def _run_preflight(self) -> None:
self.controller.run_printer_preflight_checks()

@pyqtSlot()
def _print_file(self) -> None:
self.controller.print_file(self.file_uuid)
self.close()

@pyqtSlot()
def _on_preflight_success(self) -> None:
# If the continue button is disabled then this is the result of a background preflight check
self.stop_animate_header()
self.header_icon.update_image("printer.svg", svg_size=QSize(64, 64))
self.header.setText(self.ready_header)
if not self.continue_button.isEnabled():
self.continue_button.clicked.disconnect()
self.continue_button.clicked.connect(self._print_file)
self.continue_button.setEnabled(True)
self.continue_button.setFocus()
return

self._print_file()

@pyqtSlot(object)
def _on_preflight_failure(self, error: ExportError) -> None:
self.stop_animate_header()
self.header_icon.update_image("printer.svg", svg_size=QSize(64, 64))
self.error_status = error.status
# If the continue button is disabled then this is the result of a background preflight check
if not self.continue_button.isEnabled():
self.continue_button.clicked.disconnect()
if error.status == ExportStatus.PRINTER_NOT_FOUND.value:
self.continue_button.clicked.connect(self._show_insert_usb_message)
else:
self.continue_button.clicked.connect(self._show_generic_error_message)

self.continue_button.setEnabled(True)
self.continue_button.setFocus()
else:
if error.status == ExportStatus.PRINTER_NOT_FOUND.value:
self._show_insert_usb_message()
else:
self._show_generic_error_message()


class ConversationScrollArea(QScrollArea):

MARGIN_BOTTOM = 28
Expand Down
48 changes: 24 additions & 24 deletions securedrop_client/locale/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -140,30 +140,6 @@ msgstr ""
msgid " DOWNLOADING "
msgstr ""

msgid "Preparing to print:<br /><span style=\"font-weight:normal\">{}</span>"
msgstr ""

msgid "Ready to print:<br /><span style=\"font-weight:normal\">{}</span>"
msgstr ""

msgid "Connect USB printer"
msgstr ""

msgid "Printing failed"
msgstr ""

msgid "<h2>Managing printout risks</h2><b>QR codes and web addresses</b><br />Never type in and open web addresses or scan QR codes contained in printed documents without taking security precautions. If you are unsure how to manage this risk, please contact your administrator.<br /><br /><b>Printer dots</b><br />Any part of a printed page may contain identifying information invisible to the naked eye, such as printer dots. Please carefully consider this risk when working with or publishing scanned printouts."
msgstr ""

msgid "Please connect your printer to a USB port."
msgstr ""

msgid "See your administrator for help."
msgstr ""

msgid "DONE"
msgstr ""

msgid "Earlier files and messages deleted."
msgstr ""

Expand Down Expand Up @@ -292,6 +268,9 @@ msgstr ""
msgid "The passphrase provided did not work. Please try again."
msgstr ""

msgid "See your administrator for help."
msgstr ""

msgid "The CONTINUE button will be disabled until the Export VM is ready"
msgstr ""

Expand All @@ -301,6 +280,27 @@ msgstr ""
msgid "SUBMIT"
msgstr ""

msgid "DONE"
msgstr ""

msgid "Preparing to print:<br /><span style=\"font-weight:normal\">{}</span>"
msgstr ""

msgid "Ready to print:<br /><span style=\"font-weight:normal\">{}</span>"
msgstr ""

msgid "Connect USB printer"
msgstr ""

msgid "Printing failed"
msgstr ""

msgid "<h2>Managing printout risks</h2><b>QR codes and web addresses</b><br />Never type in and open web addresses or scan QR codes contained in printed documents without taking security precautions. If you are unsure how to manage this risk, please contact your administrator.<br /><br /><b>Printer dots</b><br />Any part of a printed page may contain identifying information invisible to the naked eye, such as printer dots. Please carefully consider this risk when working with or publishing scanned printouts."
msgstr ""

msgid "Please connect your printer to a USB port."
msgstr ""

msgid "YES, DELETE ENTIRE SOURCE ACCOUNT"
msgstr ""

Expand Down
Loading