Search code examples
pdfhyperlinkpyqt5qgraphicsscene

PYQT5 - Link to page in exported pdf


I am creating an application to draw instructions for a user. The one creating the instructions can add multiple pages and then export them to .pdf. All of that works fine, except that I can't seem to get links between the different pages.

I want to add an initial page that will show all the pages and have links to them (table of contents) and add a button on each page that will link to the next / previous page.

What I currently have to export is this:

def __export_page_to_pdf(self):
    """ Export the current pages to pdf. . """
    printer = QtPrintSupport.QPrinter()
    printer.setOutputFormat(QtPrintSupport.QPrinter.PdfFormat)
    printer.setOutputFileName("instructions.pdf")
    printer.setPageSize(QtGui.QPageSize(self.__page.size, QtGui.QPageSize.Point))

    painter = QtGui.QPainter(printer)
    for page_number in range(self.__page_count):
        self.set_page(page_number)

        x_scale = self.__page.size.width() / self.width()
        y_scale = self.__page.size.height() / self.height()
        painter.scale(x_scale, y_scale)

        self.render(painter)

        if page_number < self.__page_count - 1:
            painter.resetTransform()
            printer.newPage()
    painter.end()

The self.set_page(page_number) changes the current page so the one requested can be rendered. self.set_page(0) contains the page with the TOC.

All pages are shown in a QGraphicsScene. I'd appreciate any hints on how to create the links between these pages.


Solution

  • After the response by ekhumoro I investigated 3rd party software. The functionality that I seek is possible with the PyMuPdf package. The steps to take are to place text / images in the original pdf. Then using the PyMuPdf package use a snippet similar to this one:

    import fitz # This is the import name for PyMuPdf. Use pip install PyMuPdf to install
    doc = fitz.open("test.pdf")
    new_link = {
        "kind": 1, # I am unsure what this does but it is required.
        "from": fitz.Rect(32, 504, 50, 534), # Locaton of the link.
        "page": 1, # The page to link to.
        "to": fitz.Point(0, 0), # The location on the new page.
        "zoom": 0 # The zoom of the new page.
    }
    
    for i in range(doc.page_count): # Use this method of iterating to prevent pages not being edited.
        page_link = dict(new_link) # Copy template.
        page_link["page"] = i + 1 # Update page to link to.
        doc[i].insert_link(page_link) # Insert the link.