diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index 889a7c4e3..5bb575231 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -754,20 +754,30 @@ class Renderer: p.drawOn(canvas, 0, -h - ad[1]) canvas.restoreState() - def draw_page(self, canvas: Canvas, order: Order, op: OrderPosition, show_page=True): - for o in self.layout: - if o['type'] == "barcodearea": - self._draw_barcodearea(canvas, op, o) - elif o['type'] == "imagearea": - self._draw_imagearea(canvas, op, order, o) - elif o['type'] == "textarea": - self._draw_textarea(canvas, op, order, o) - elif o['type'] == "poweredby": - self._draw_poweredby(canvas, op, o) - if self.bg_pdf: - canvas.setPageSize((self.bg_pdf.getPage(0).mediaBox[2], self.bg_pdf.getPage(0).mediaBox[3])) - if show_page: - canvas.showPage() + def draw_page(self, canvas: Canvas, order: Order, op: OrderPosition, show_page=True, only_page=None): + page_count = self.bg_pdf.getNumPages() + + if not only_page and not show_page: + raise ValueError("only_page=None and show_page=False cannot be combined") + + for page in range(page_count): + if only_page and only_page != page + 1: + continue + for o in self.layout: + if o.get('page', 1) != page + 1: + continue + if o['type'] == "barcodearea": + self._draw_barcodearea(canvas, op, o) + elif o['type'] == "imagearea": + self._draw_imagearea(canvas, op, order, o) + elif o['type'] == "textarea": + self._draw_textarea(canvas, op, order, o) + elif o['type'] == "poweredby": + self._draw_poweredby(canvas, op, o) + if self.bg_pdf: + canvas.setPageSize((self.bg_pdf.getPage(page).mediaBox[2], self.bg_pdf.getPage(page).mediaBox[3])) + if show_page: + canvas.showPage() def render_background(self, buffer, title=_('Ticket')): if settings.PDFTK: @@ -780,7 +790,7 @@ class Renderer: subprocess.run([ settings.PDFTK, os.path.join(d, 'front.pdf'), - 'background', + 'multibackground', os.path.join(d, 'back.pdf'), 'output', os.path.join(d, 'out.pdf'), @@ -794,8 +804,8 @@ class Renderer: new_pdf = PdfFileReader(buffer) output = PdfFileWriter() - for page in new_pdf.pages: - bg_page = copy.copy(self.bg_pdf.getPage(0)) + for i, page in enumerate(new_pdf.pages): + bg_page = copy.copy(self.bg_pdf.getPage(i)) bg_page.mergePage(page) output.addPage(bg_page) diff --git a/src/pretix/control/templates/pretixcontrol/pdf/index.html b/src/pretix/control/templates/pretixcontrol/pdf/index.html index e829f9adb..117382c44 100644 --- a/src/pretix/control/templates/pretixcontrol/pdf/index.html +++ b/src/pretix/control/templates/pretixcontrol/pdf/index.html @@ -23,7 +23,7 @@
-
+
@@ -48,6 +48,8 @@ {% trans "Editor" %}
+
").addClass("nav-item"); + var $a = $("").text(i).attr("href", "#").attr("data-page", i).appendTo($li); + if (i === editor.pdf_page_number) { + $li.addClass("active") + } + $("#page_nav").append($li) + $a.on("click", function (event) { + console.log("switch to page", $(this).attr("data-page")); + editor.fabric.deactivateAll(); + editor._load_page(parseInt($(this).attr("data-page"))); + event.preventDefault(); + return true; + }) + } + $("#page_nav").show(); + } + }, + _load_pdf: function (dump) { // TODO: Loading indicators var url = editor.pdf_url; @@ -279,36 +358,13 @@ var editor = { loadingTask.promise.then(function (pdf) { console.log('PDF loaded'); - // Fetch the first page - var pageNumber = 1; - pdf.getPage(pageNumber).then(function (page) { - console.log('Page loaded'); - var canvas = document.getElementById('pdf-canvas'); - - var scale = editor.$cva.width() / page.getViewport(1.0).width; - var viewport = page.getViewport(scale); - - // Prepare canvas using PDF page dimensions - var context = canvas.getContext('2d'); - context.clearRect(0, 0, canvas.width, canvas.height); - canvas.height = viewport.height; - canvas.width = viewport.width; - - editor.pdf_page = page; - editor.pdf_scale = scale; - editor.pdf_viewport = viewport; - - // Render PDF page into canvas context - var renderContext = { - canvasContext: context, - viewport: viewport - }; - var renderTask = page.render(renderContext); - renderTask.then(function () { - console.log('Page rendered'); - editor._init_fabric(dump); - }); - }); + editor.pdf = pdf; + editor.pdf_page_count = pdf.numPages; + if (editor.pdf_page_count > 10) { + alert('Please do not upload files with more than 10 pages for performance reasons.') + } + editor._init_page_nav(); + editor._load_page(1, dump); }, function (reason) { var msg = gettext('The PDF background file could not be loaded for the following reason:'); editor._error(msg + ' ' + reason); @@ -664,6 +720,7 @@ var editor = { editor._history_modification_in_progress = true; var objs = []; for (var i in editor.clipboard) { + editor.clipboard[i].page = editor.pdf_page_number; objs.push(editor._add_from_data(editor.clipboard[i])); } editor.fabric.discardActiveObject(); diff --git a/src/pretix/static/pretixcontrol/scss/pdfeditor.css b/src/pretix/static/pretixcontrol/scss/pdfeditor.css index fd92a1055..eea4cde21 100644 --- a/src/pretix/static/pretixcontrol/scss/pdfeditor.css +++ b/src/pretix/static/pretixcontrol/scss/pdfeditor.css @@ -69,3 +69,10 @@ body { margin-top: 10px; margin-bottom: 0; } +.panel-pdf-editor .panel-body { + padding: 0; +} +.panel-pdf-editor .panel-body .nav-pills { + padding: 15px; + background: #eee; +}