diff --git a/app/routes/labels_tape.py b/app/routes/labels_tape.py index ccae0ec..70b6368 100644 --- a/app/routes/labels_tape.py +++ b/app/routes/labels_tape.py @@ -46,7 +46,15 @@ def printer_config(): } -def _options_query(options, labels): +def _group_spec(): + """ + The manual grouping from the page: "1,2|3" means parts 1 and 2 share a + label and part 3 is on its own. Empty means "work it out from drawers". + """ + return (request.values.get('groups') or '').strip() + + +def _options_query(options, labels, group_spec=None): """ The chosen options as query args, so a redirect back to the tape page comes back exactly as the user left it. Without this, printing bounced @@ -65,6 +73,8 @@ def _options_query(options, labels): 'align': options.align, 'fields': options.fields, } + if group_spec: + query['groups'] = group_spec # Checkboxes: only present when on, which is what the parser expects. if options.rotate: query['rotate'] = '1' @@ -115,13 +125,16 @@ def index(): source, rotate_default=config['rotate'], size_default=config['size_mode'], tape_default=config['tape']) - plan = tape_printer.plan_groups(labels, options) + group_spec = _group_spec() + plan = tape_printer.plan_groups(labels, options, group_spec) tape = tape_printer.get_tape(options.tape) return render_template( 'admin/labels/tape.html', labels=labels, plan=plan, + group_spec=tape_printer.spec_from_groups( + [item['labels'] for item in plan]), ids=','.join(str(l.id) for l in labels), options=options, tapes=tape_printer.TAPE_PRESETS, @@ -235,15 +248,18 @@ def print_tape(): except ipp_client.IPPError as exc: flash(f'Could not reach the printer: {exc}', 'danger') return redirect(url_for('tape.index', - **_options_query(options, labels))) + **_options_query(options, labels, + _group_spec()))) if not mime_type: flash('The printer did not offer a format LIM can produce. Use ' 'Download PDF instead.', 'warning') return redirect(url_for('tape.index', - **_options_query(options, labels))) + **_options_query(options, labels, + _group_spec()))) upload_folder = current_app.config['UPLOAD_FOLDER'] - plan = tape_printer.plan_groups(labels, options) + group_spec = _group_spec() + plan = tape_printer.plan_groups(labels, options, group_spec) if options.is_fixed and not tape_printer.tape_fits_label(options.tape): flash(f'{tape_printer.LABEL_WIDTH_MM:.0f}mm labels need 50mm tape - ' @@ -261,8 +277,13 @@ def print_tape(): document = tape_printer.image_to_bytes(image, mime_type) # copies is handled by repeating the job rather than the IPP # copies attribute: tape printers vary wildly in honouring it. + # + # Paced rather than fired in a burst: the VC-500W takes one job + # at a time and answers "busy" to anything arriving while the + # tape is still moving, so each job waits for the printer to go + # idle and retries while it is still working. for _ in range(options.copies): - ipp_client.print_job( + ipp_client.print_job_paced( host, document, mime_type, job_name=f'LIM: {name}'[:120], port=config['port'], path=config['path']) @@ -279,7 +300,8 @@ def print_tape(): for problem in failures[:5]: flash(problem, 'danger') - return redirect(url_for('tape.index', **_options_query(options, labels))) + return redirect(url_for('tape.index', + **_options_query(options, labels, group_spec))) @tape_bp.route('/download.pdf', methods=['GET', 'POST']) @@ -298,7 +320,7 @@ def download_pdf(): source, rotate_default=config['rotate'], size_default=config['size_mode'], tape_default=config['tape']) buffer = tape_printer.render_batch_pdf( - labels, options, current_app.config['UPLOAD_FOLDER']) + labels, options, current_app.config['UPLOAD_FOLDER'], _group_spec()) if buffer is None: flash('Nothing to render.', 'warning') return redirect(url_for('labels.index'))