-
Notifications
You must be signed in to change notification settings - Fork 42
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
Initial support for IPP / driverless printing #2332
Draft
deeplow
wants to merge
5
commits into
main
Choose a base branch
from
2088-ipp-printers
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
63a791c
Initial support for IPP / driverless printing
deeplow 0bfba7e
Pull in pygobject as a Debian package dependency
deeplow ffe386a
Replace XPP with Gtk print dialog and dependencies
deeplow 3e72356
WIP: Print Dialog: hack to obtain exceptions raised in print dialog
deeplow 66eb231
Handle printer discovery failure through exceptions
deeplow File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# avahi-daemon so that driverless printers are detected when | ||
# plugged in via USB, overriding 75-qubes-vm.preset | ||
|
||
enable avahi-daemon.service |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from securedrop_export.exceptions import ExportException | ||
|
||
from .status import Status | ||
|
||
|
||
class PrinterNotFoundException(ExportException): | ||
def __init__(self, sderror=None): | ||
super().__init__() | ||
self.sdstatus = Status.ERROR_PRINTER_NOT_FOUND |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import gi | ||
|
||
gi.require_version("Gtk", "4.0") | ||
import logging | ||
|
||
from gi.repository import Gtk | ||
|
||
from securedrop_export.exceptions import ExportException | ||
from securedrop_export.print.status import Status | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class GtkExceptionRaiser: | ||
""" | ||
Context manager to keep track of exceptions to be raised after GTK exits | ||
|
||
This is a workaround for the fact that GTK does not behave like regular | ||
libraries. Exceptions raised by the GUI code are always caught within GTK. | ||
The context manager provides a way to store these exceptions. | ||
|
||
Usage: | ||
|
||
class SomeApplication(Gtk.Application): | ||
def __init__(self, raise_later_func): | ||
super().__init__() | ||
self.raise_later_func = raise_later_func | ||
|
||
[...] | ||
|
||
def on_something_bad_happening(self): | ||
self.raise_later_func(Exception("something happned")) | ||
self.quit() | ||
|
||
with GtkExceptionRaiser() as raise_later_func: | ||
app = SomeApplication(raise_later_func) | ||
app.run() | ||
""" | ||
|
||
def __init__(self): | ||
self.exception_to_raise = None | ||
|
||
def raise_later_func(self, exception): | ||
self.exception_to_raise = exception | ||
|
||
def __enter__(self): | ||
return self.raise_later_func | ||
|
||
def __exit__(self, exc_type, exc_val, exc_tb): | ||
if self.exception_to_raise: | ||
raise self.exception_to_raise | ||
|
||
|
||
class PrintDialog(Gtk.Application): | ||
def __init__(self, file_to_print, raise_later_func): | ||
super().__init__(application_id="org.securedrop.PrintDialog") | ||
self.file_to_print = file_to_print | ||
self.raise_later_func = raise_later_func | ||
self.connect("activate", self.on_activate) | ||
|
||
def on_activate(self, app): | ||
window = Gtk.Window(application=app) | ||
window.hide() | ||
self.dialog = Gtk.PrintUnixDialog.new("Print Document", window) | ||
self.dialog.connect("response", self.on_response) | ||
self.dialog.connect("close", self.quit) | ||
self.dialog.show() | ||
|
||
def on_response(self, parent_widget, response_id): | ||
if response_id == Gtk.ResponseType.OK: | ||
self.dialog.hide() | ||
settings = self.dialog.get_settings() | ||
printer = self.dialog.get_selected_printer() | ||
page_setup = self.dialog.get_page_setup() | ||
job = Gtk.PrintJob.new("print job", printer, settings, page_setup) | ||
job.set_source_file(self.file_to_print) | ||
job.send(self.on_job_complete, user_data=None) | ||
elif response_id == Gtk.ResponseType.CANCEL: | ||
# FIXME should this exist or should it simply cancel and not report errors | ||
self.raise_later_func( | ||
ExportException(sdstatus=Status.ERROR_PRINT, sderror="User canceled dialog") | ||
) | ||
self.quit() | ||
elif response_id == Gtk.ResponseType.DELETE_EVENT: | ||
self.quit() | ||
|
||
def on_job_complete(self, print_job, user_data, error): | ||
if error: | ||
self.raise_later_func( | ||
ExportException(sdstatus=Status.ERROR_PRINT, sderror=error.message) | ||
) | ||
self.quit() | ||
|
||
|
||
def open_print_dialog(file_to_print): | ||
with GtkExceptionRaiser() as raise_later_func: | ||
app = PrintDialog(file_to_print, raise_later_func) | ||
app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed the
_wait_for_print()
method because the print dialog can already obtains some eventual errors occurred during the print job. So my implementation simply exits the dialog either with some error or success.Proposed Troubleshooting Workflow
But not all failures were marked as errors by the print dialog. For example, I tried to print with an open tray and both dialogs were closed (
PRINT_SUCCESS
), but the printer errored out. Luckily, there is some information on the top right-hand corner of the screen:If I wanted to troubleshoot, I could click on the little "printer" icon in the tray menu and it would open the queued print documents and some actions to troubleshoot:
Instead of waiting for the document to be printed with a spinning icon in the client dialog, I'd propose that we close all dialogs if successfully sent the job to the printer tools. What this means .
I guess ultimately this a UX question. Should I re-implement a way to have the client print dialog hanging / waiting while a document is fully printed, or should all print-related dialogs close as soon as the print is initiated and we let the users troubleshoot via messages in the right-hand corner and the respective print queue utility (accessed from the tray menu)?