Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Qt 5.15 QML PDF viewer cannot open password protected PDFs
Forum Update on Monday, May 27th 2025

Qt 5.15 QML PDF viewer cannot open password protected PDFs

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
9 Posts 4 Posters 1.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    Vloois
    wrote on 20 Aug 2021, 09:27 last edited by
    #1

    Hi,
    I installed the latest Qt version (5.15.5) with Commercial license with (among other modules):

    • MSVC 2019 (64-bit)
    • Sources
    • Qt PDF
    • Qt WebEngine

    I am running on Windows 10, trying to run the Multipage PDF example (C:\Qt\Examples\Qt-5.15.5\pdf\multipage). It runs but I cannot open a password protected PDF. It gives the dialog to enter the password, but then says: "Error loading file:///C:/Temp/TestLongPDFOnline-protected.pdf file not found", but I can open the same PDF with other applications. In viewer.qml it also says Unknown component (M300) at PdfMultiPageView (line 243).

    In the Application Output area I get these warnings/errors:
    qrc:/qt-project.org/qtpdf/qml/PdfMultiPageView.qml:297:25: Unable to assign [undefined] to QQuickPdfDocument*
    qrc:/qt-project.org/qtpdf/qml/PdfMultiPageView.qml:166: TypeError: Cannot read property 'source' of undefined
    qrc:/qt-project.org/qtpdf/qml/PdfMultiPageView.qml:164:17: QML Image: Error decoding: file:///C:/Temp/TestLongPDFOnline-protected.pdf: Unable to read image data

    When I try to view the file with the errors by clicking on "qrc:/qt-project.org/qtpdf/qml/PdfMultiPageView.qml" I get a popup with the following:
    "Could not open "\qt-project.org\qtpdf\qml\PdfMultiPageView.qml" for reading. Either the file does not exist or you do not have the permission to open it". The file was installed in C:\Qt\5.15.5\msvc2019_64\qml\QtQuick\Pdf\qml\PdfMultiPageView.qml

    I am required to add functionality to my own application for viewing password protected PDFs and therefore would like to use methods similar to this example. Any advice on how to get the example to work properly will be greatly appreciated.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 20 Aug 2021, 19:11 last edited by
      #2

      Hi,

      Maybe a silly question but did you call setPassword before loading the document ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      V 1 Reply Last reply 23 Aug 2021, 10:16
      0
      • S SGaist
        20 Aug 2021, 19:11

        Hi,

        Maybe a silly question but did you call setPassword before loading the document ?

        V Offline
        V Offline
        Vloois
        wrote on 23 Aug 2021, 10:16 last edited by
        #3

        @SGaist see below for the code of viewer.qml in the example. The file is loaded (document.source = file), the signal is triggered that a password is required, the password is entered (and set accordingly with onAccepted: document.password = passwordField.text). But the status of PdfDocument doesn't change once the password has been set, it remains PdfDocument.Error. Must I somehow reload once the password has been set? Thank you for your help.

        /****************************************************************************
        **
        ** Copyright (C) 2020 The Qt Company Ltd.
        ** Contact: https://www.qt.io/licensing/
        **
        ** This file is part of the examples of the Qt Toolkit.
        **
        ** $QT_BEGIN_LICENSE:BSD$
        ** Commercial License Usage
        ** Licensees holding valid commercial Qt licenses may use this file in
        ** accordance with the commercial license agreement provided with the
        ** Software or, alternatively, in accordance with the terms contained in
        ** a written agreement between you and The Qt Company. For licensing terms
        ** and conditions see https://www.qt.io/terms-conditions. For further
        ** information use the contact form at https://www.qt.io/contact-us.
        **
        ** BSD License Usage
        ** Alternatively, you may use this file under the terms of the BSD license
        ** as follows:
        **
        ** "Redistribution and use in source and binary forms, with or without
        ** modification, are permitted provided that the following conditions are
        ** met:
        **   * Redistributions of source code must retain the above copyright
        **     notice, this list of conditions and the following disclaimer.
        **   * Redistributions in binary form must reproduce the above copyright
        **     notice, this list of conditions and the following disclaimer in
        **     the documentation and/or other materials provided with the
        **     distribution.
        **   * Neither the name of The Qt Company Ltd nor the names of its
        **     contributors may be used to endorse or promote products derived
        **     from this software without specific prior written permission.
        **
        **
        ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
        ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
        ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
        ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
        **
        ** $QT_END_LICENSE$
        **
        ****************************************************************************/
        import QtQml 2.14 // workaround for QTBUG-82873
        import QtQuick 2.14
        import QtQuick.Controls 2.14
        import QtQuick.Layouts 1.14
        import QtQuick.Pdf 5.15
        import QtQuick.Shapes 1.14
        import QtQuick.Window 2.14
        import Qt.labs.platform 1.1 as Platform
        
        ApplicationWindow {
            id: root
            width: 800
            height: 1024
            color: "lightgrey"
            title: document.title
            visible: true
            property string source // for main.cpp
        
            header: ToolBar {
                RowLayout {
                    anchors.fill: parent
                    anchors.rightMargin: 6
                    ToolButton {
                        action: Action {
                            shortcut: StandardKey.Open
                            icon.source: "resources/document-open.svg"
                            onTriggered: fileDialog.open()
                        }
                    }
                    ToolButton {
                        action: Action {
                            shortcut: StandardKey.ZoomIn
                            enabled: view.renderScale < 10
                            icon.source: "resources/zoom-in.svg"
                            onTriggered: view.renderScale *= Math.sqrt(2)
                        }
                    }
                    ToolButton {
                        action: Action {
                            shortcut: StandardKey.ZoomOut
                            enabled: view.renderScale > 0.1
                            icon.source: "resources/zoom-out.svg"
                            onTriggered: view.renderScale /= Math.sqrt(2)
                        }
                    }
                    ToolButton {
                        action: Action {
                            icon.source: "resources/zoom-fit-width.svg"
                            onTriggered: view.scaleToWidth(root.contentItem.width, root.contentItem.height)
                        }
                    }
                    ToolButton {
                        action: Action {
                            icon.source: "resources/zoom-fit-best.svg"
                            onTriggered: view.scaleToPage(root.contentItem.width, root.contentItem.height)
                        }
                    }
                    ToolButton {
                        action: Action {
                            shortcut: "Ctrl+0"
                            icon.source: "resources/zoom-original.svg"
                            onTriggered: view.resetScale()
                        }
                    }
                    ToolButton {
                        action: Action {
                            shortcut: "Ctrl+L"
                            icon.source: "resources/rotate-left.svg"
                            onTriggered: view.pageRotation -= 90
                        }
                    }
                    ToolButton {
                        action: Action {
                            shortcut: "Ctrl+R"
                            icon.source: "resources/rotate-right.svg"
                            onTriggered: view.pageRotation += 90
                        }
                    }
                    ToolButton {
                        action: Action {
                            icon.source: "resources/go-previous-view-page.svg"
                            enabled: view.backEnbled
                            onTriggered: view.back()
                        }
                        ToolTip.visible: enabled && hovered
                        ToolTip.delay: 2000
                        ToolTip.text: "go back"
                    }
                    SpinBox {
                        id: currentPageSB
                        from: 1
                        to: document.pageCount
                        editable: true
                        onValueModified: view.goToPage(value - 1)
                        Shortcut {
                            sequence: StandardKey.MoveToPreviousPage
                            onActivated: view.goToPage(currentPageSB.value - 2)
                        }
                        Shortcut {
                            sequence: StandardKey.MoveToNextPage
                            onActivated: view.goToPage(currentPageSB.value)
                        }
                    }
                    ToolButton {
                        action: Action {
                            icon.source: "resources/go-next-view-page.svg"
                            enabled: view.forwardEnabled
                            onTriggered: view.forward()
                        }
                        ToolTip.visible: enabled && hovered
                        ToolTip.delay: 2000
                        ToolTip.text: "go forward"
                    }
                    ToolButton {
                        action: Action {
                            shortcut: StandardKey.SelectAll
                            icon.source: "resources/edit-select-all.svg"
                            onTriggered: view.selectAll()
                        }
                    }
                    ToolButton {
                        action: Action {
                            shortcut: StandardKey.Copy
                            icon.source: "resources/edit-copy.svg"
                            enabled: view.selectedText !== ""
                            onTriggered: view.copySelectionToClipboard()
                        }
                    }
                    Shortcut {
                        sequence: StandardKey.Find
                        onActivated: searchField.forceActiveFocus()
                    }
                    Shortcut {
                        sequence: StandardKey.Quit
                        onActivated: Qt.quit()
                    }
                }
            }
        
            Platform.FileDialog {
                id: fileDialog
                title: "Open a PDF file"
                nameFilters: [ "PDF files (*.pdf)" ]
                onAccepted: document.source = file
            }
        
            Dialog {
                id: passwordDialog
                title: "Password"
                standardButtons: Dialog.Ok | Dialog.Cancel
                modal: true
                closePolicy: Popup.CloseOnEscape
                anchors.centerIn: parent
                width: 300
        
                TextField {
                    id: passwordField
                    placeholderText: qsTr("Please provide the password")
                    echoMode: TextInput.Password
                    width: parent.width
                    onAccepted: passwordDialog.accept()
                }
                onAccepted: document.password = passwordField.text
            }
        
            Dialog {
                id: errorDialog
                title: "Error loading " + document.source
                standardButtons: Dialog.Ok
                modal: true
                closePolicy: Popup.CloseOnEscape
                anchors.centerIn: parent
                width: 300
        
                Label {
                    id: errorField
                    text: document.error
                }
            }
        
            PdfDocument {
                id: document
                source: Qt.resolvedUrl(root.source)
                onStatusChanged: {
                    if (status === PdfDocument.Error) errorDialog.open()
                    view.document = (status === PdfDocument.Ready ? document : undefined)
                }
                onPasswordRequired: {
                    passwordDialog.open()
                    passwordField.forceActiveFocus()
                }
            }
        
            PdfMultiPageView {
                id: view
                anchors.fill: parent
                anchors.leftMargin: searchDrawer.position * searchDrawer.width
                document: root.document
                searchString: searchField.text
                onCurrentPageChanged: currentPageSB.value = view.currentPage + 1
            }
        
            Drawer {
                id: searchDrawer
                edge: Qt.LeftEdge
                modal: false
                width: 300
                y: root.header.height
                height: view.height
                dim: false
                clip: true
                ListView {
                    id: searchResultsList
                    anchors.fill: parent
                    anchors.margins: 2
                    model: view.searchModel
                    ScrollBar.vertical: ScrollBar { }
                    delegate: ItemDelegate {
                        width: parent ? parent.width : 0
                        RowLayout {
                            anchors.fill: parent
                            spacing: 0
                            Label {
                                text: "Page " + (page + 1) + ": "
                            }
                            Label {
                                text: contextBefore
                                elide: Text.ElideLeft
                                horizontalAlignment: Text.AlignRight
                                Layout.fillWidth: true
                                Layout.preferredWidth: parent.width / 2
                            }
                            Label {
                                font.bold: true
                                text: view.searchString
                                width: implicitWidth
                            }
                            Label {
                                text: contextAfter
                                elide: Text.ElideRight
                                Layout.fillWidth: true
                                Layout.preferredWidth: parent.width / 2
                            }
                        }
                        highlighted: ListView.isCurrentItem
                        onClicked: {
                            searchResultsList.currentIndex = index
                            view.goToLocation(page, location, 0)
                            view.searchModel.currentResult = indexOnPage
                        }
                    }
                }
            }
        
            footer: ToolBar {
                height: footerRow.implicitHeight
                RowLayout {
                    id: footerRow
                    anchors.fill: parent
                    ToolButton {
                        action: Action {
                            icon.source: "resources/go-up-search.svg"
                            shortcut: StandardKey.FindPrevious
                            onTriggered: view.searchBack()
                        }
                        ToolTip.visible: enabled && hovered
                        ToolTip.delay: 2000
                        ToolTip.text: "find previous"
                    }
                    TextField {
                        id: searchField
                        placeholderText: "search"
                        Layout.minimumWidth: 150
                        Layout.fillWidth: true
                        onAccepted: searchDrawer.open()
                        Image {
                            visible: searchField.text !== ""
                            source: "resources/edit-clear.svg"
                            anchors {
                                right: parent.right
                                top: parent.top
                                bottom: parent.bottom
                                margins: 3
                                rightMargin: 5
                            }
                            TapHandler {
                                onTapped: searchField.clear()
                            }
                        }
                    }
                    ToolButton {
                        action: Action {
                            icon.source: "resources/go-down-search.svg"
                            shortcut: StandardKey.FindNext
                            onTriggered: view.searchForward()
                        }
                        ToolTip.visible: enabled && hovered
                        ToolTip.delay: 2000
                        ToolTip.text: "find next"
                    }
                    Label {
                        id: statusLabel
                        property size implicitPointSize: document.pagePointSize(view.currentPage)
                        text: "page " + (currentPageSB.value) + " of " + document.pageCount +
                              " scale " + view.renderScale.toFixed(2) +
                              " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt"
                        visible: document.pageCount > 0
                    }
                }
            }
        }
        
        
        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 23 Aug 2021, 19:55 last edited by
          #4

          @Vloois said in Qt 5.15 QML PDF viewer cannot open password protected PDFs:

          onPasswordRequired

          What if you set the password directly in the handler ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          V 1 Reply Last reply 24 Aug 2021, 07:46
          0
          • S SGaist
            23 Aug 2021, 19:55

            @Vloois said in Qt 5.15 QML PDF viewer cannot open password protected PDFs:

            onPasswordRequired

            What if you set the password directly in the handler ?

            V Offline
            V Offline
            Vloois
            wrote on 24 Aug 2021, 07:46 last edited by
            #5

            @SGaist Thank you for your response.

            I have hard coded the password in the handler as below, just to see if it makes a difference, but still get the same problem. I've also tried another PDF document encrypted using another platform, but still get the same issue.

            onPasswordRequired: {
                        //passwordDialog.open()
                        //passwordField.forceActiveFocus()
                        document.password = "Owner"
                    }
            

            Can you replicate the problem on your side if you run the example?

            eyllanescE 1 Reply Last reply 24 Aug 2021, 07:50
            0
            • V Vloois
              24 Aug 2021, 07:46

              @SGaist Thank you for your response.

              I have hard coded the password in the handler as below, just to see if it makes a difference, but still get the same problem. I've also tried another PDF document encrypted using another platform, but still get the same issue.

              onPasswordRequired: {
                          //passwordDialog.open()
                          //passwordField.forceActiveFocus()
                          document.password = "Owner"
                      }
              

              Can you replicate the problem on your side if you run the example?

              eyllanescE Offline
              eyllanescE Offline
              eyllanesc
              wrote on 24 Aug 2021, 07:50 last edited by
              #6

              @Vloois Could you share a .pdf file protected with its respective password to be able to test?

              If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

              V 1 Reply Last reply 24 Aug 2021, 09:00
              0
              • eyllanescE eyllanesc
                24 Aug 2021, 07:50

                @Vloois Could you share a .pdf file protected with its respective password to be able to test?

                V Offline
                V Offline
                Vloois
                wrote on 24 Aug 2021, 09:00 last edited by
                #7

                @eyllanesc said in Qt 5.15 QML PDF viewer cannot open password protected PDFs:

                Could you share a .pdf file protected with its respective password to be able to test?

                I'm not sure if there is an easier to way share files, when trying to upload it I got an error "You do not have enough privileges for this action.", but you can download it from Dropbox with the links below:

                Long is a pdf I got online and password protected using this site https://www.adobe.com/acrobat/online/password-protect-pdf.html the password is "Test123".

                Short is a pdf I generated with QTextDocument and QPrinter and encrypted with QPDF (http://qpdf.sourceforge.net/ unrelated to Qt), the passwords are "User" or "Owner".

                Thank you.

                1 Reply Last reply
                0
                • V Offline
                  V Offline
                  Vloois
                  wrote on 17 Sept 2021, 09:57 last edited by
                  #8

                  Just an update to anyone struggling with the same issue - it seems it is a bug and has been logged (https://bugreports.qt.io/browse/QTBUG-96574) hopefully they will attend to it shortly.

                  1 Reply Last reply
                  1
                  • S Offline
                    S Offline
                    Smoreily
                    wrote on 21 Oct 2021, 09:45 last edited by
                    #9

                    If you enter the correct password, the viewer can open the PDF file. As for your question, I suggest you delete the password on the PDF first, so that you can open the PDF directly on the viewer.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved