Открывать внешние ссылки на пути к файлам с пробелами в QTextBrowser

Я работаю в приложении Python. В некоторых частях программы я сообщаю пользователю, что создаются разные файлы. Я показываю эту информацию в виджете QTextBrowser. Я хочу, чтобы этот текст был гиперссылкой, поэтому, если пользователь нажмет на гиперссылку, файл откроется во внешнем приложении. Если в пути к файлу нет пробелов, ссылки работают, но если в пути есть пробелы, ссылки не работают.

Прочитал много вопросов по этому поводу, но решения не нашел.

Я написал эти два теста.

Код 1 - я использую QLabel и ссылка работает отлично, но в QTextBrowser она открывается внутри браузера.

Вариант 1 работает, но остальные варианты не работают, потому что в пути есть пробелы.

Вариант 7 и 10, открыть файл, но внутри браузера.

КОД 1:

import sys

from PyQt5.QtWidgets import QApplication, QTextBrowser,QTextEdit,QLabel
from PyQt5.QtCore import QUrl

app = QApplication(sys.argv)
label=QLabel()
file_2='c:/temp/test 2/test.docx'
urlLink="<a href='file:///%s'>'Option_12'</a>"%(file_2)
label.setText(urlLink)
label.setOpenExternalLinks(True)
label.show()
sys.exit(app.exec_())

КОД 2:

import sys

from PyQt5.QtWidgets import QApplication, QTextBrowser,QTextEdit
from PyQt5.QtCore import QUrl

if __name__ == '__main__':
    app = QApplication(sys.argv)
    text_area = QTextBrowser()
    file='c:/temp/test.docx'
    link='<a href='"'{}'"'>Option_1</a>'.format(file)
    text_area.insertHtml(link)
    
    
    file_2='c:/temp/test 2/test.docx'
    link='<br><a href='"'{}'"'>Option_2</a></br>'.format(file_2)
    text_area.insertHtml(link)

    file_2_reformated=file_2.replace(" ", "\\ ")
    link='<br><a href='"'{}'"'>Option_3</a></br>'.format(file_2_reformated)
    text_area.insertHtml(link)

    file_2_reformated=file_2.replace(" ", "%20")
    link='<br><a href='"'{}'"'>Option_4</a></br>'.format(file_2_reformated)
    text_area.insertHtml(link)

    file_2_reformated=chr(34)+file_2+chr(34)
    link='<br><a href='"'{}'"'>Option_5</a></br>'.format(file_2_reformated)
    text_area.insertHtml(link)

    file_2_reformated = " \"" + file_2 + " \""
    link='<br><a href='"'{}'"'>Option_6</a></br>'.format(file_2_reformated)
    text_area.insertHtml(link)

    link='<br><a href='"'file:///{}'"'>Option_7</a></br>'.format(file_2)
    text_area.insertHtml(link)

    link='<br><a href='"'https://{}'"'>Option_8</a></br>'.format(file_2)
    text_area.insertHtml(link)

    file_3="file:///c:/temp/test 2/test.docx"
    link='<br><a href='"'https://{}'"'>Option_9</a></br>'.format(file_3)
    text_area.insertHtml(link)

    file_2='c:/temp/test 2/test.docx'
    link = '<br><a href="{}">Option_10</a></br>'.format(QUrl.fromLocalFile(file_2).toString())
    text_area.insertHtml(link)

    file_2='c:/temp/test 2/test.docx'
    link = '<br><a href="\'{}\'">Option_11</a></br>'.format(QUrl.fromLocalFile(file_2).toString())
    text_area.insertHtml(link)


    from pathlib import PureWindowsPath

    file_3 = PureWindowsPath("c:/temp/test 2/test.docx")
    link = '<br><a href="{}">Option_13</a></br>'.format(file_3.as_uri())
    text_area.insertHtml(link)
    
    text_area.setOpenExternalLinks(True)
    text_area.show()
    sys.exit(app.exec_())
 

РЕШЕНИЕ ОТ @ekhumoro

import sys
from PyQt5.QtWidgets import QApplication, QTextBrowser
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtCore import QUrl

if __name__ == '__main__':

    app = QApplication(sys.argv)

    text_area = QTextBrowser()
    text_area.setOpenLinks(False)

    def handle_links(url):
        if not url.scheme():
            url = QUrl.fromLocalFile(url.toString())
        QDesktopServices.openUrl(url)

    text_area.anchorClicked.connect(handle_links)

    file='c:/temp/test.docx'
    link='<a href='"'{}'"'>Option_1</a>'.format(file)
    text_area.insertHtml(link)   

    file_2='c:/temp/test 2/test.docx'    
    link='<br><a href='"'file:///{}'"'>Option_7</a></br>'.format(file_2)
    text_area.insertHtml(link)

    link = '<br><a href="{}">Option_10</a></br>'.format(QUrl.fromLocalFile(file_2).toString())
    text_area.insertHtml(link)

    from pathlib import PureWindowsPath

    file_3 = PureWindowsPath("c:/temp/test 2/test.docx")
    link = '<br><a href="{}">Option_13</a></br>'.format(file_3.as_uri())
    text_area.insertHtml(link)

    text_area.show()
    sys.exit(app.exec_())

person RBenet    schedule 26.01.2021    source источник
comment
QTextBrowser не может отображать PDF, поэтому вам нужно использовать другие параметры, такие как QWebEngineView.   -  person eyllanesc    schedule 27.01.2021
comment
Большое спасибо за ответ. Но я не хочу открывать только файл pdf. Я хочу, чтобы Windows открывала для меня файлы любого типа. Вариант 1, который я опубликовал, делает то, что я хочу. Проблема в том, что в имени файла есть пробел.   -  person RBenet    schedule 27.01.2021
comment
Цитирование выглядит скомканным. Если вы хотите получить путь к файлу в одинарных кавычках внутри href в двойных кавычках, попробуйте следующее: '<a href="\'{}\'">Option_1</a>'.format(file).   -  person ekhumoro    schedule 27.01.2021
comment
Спасибо @eyllanesc Чтобы избежать путаницы, я изменил документ как docx, а не pdf.   -  person RBenet    schedule 27.01.2021
comment
Спасибо @ekhumoro, я показываю ваш ответ как вариант 11, этот вариант не работает (ничего не происходит)   -  person RBenet    schedule 27.01.2021


Ответы (1)


Проблема в том, что setOpenExternalLinks(True) будет не открывать URL-адреса с помощью схемы file:, но вы должны использовать схему file: для открытия путей к файлам, содержащих пробелы. Чтобы обойти это, вы можете использовать пользовательский обработчик ссылок. Следующий скрипт показывает, как это сделать:

import sys
from PyQt5.QtWidgets import QApplication, QTextBrowser
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtCore import QUrl

if __name__ == '__main__':

    app = QApplication(sys.argv)

    text_area = QTextBrowser()
    text_area.setOpenLinks(False)

    def handle_links(url):
        if not url.scheme():
            url = QUrl.fromLocalFile(url.toString())
        QDesktopServices.openUrl(url)

    text_area.anchorClicked.connect(handle_links)

    file = 'c:/temp/test.docx'
    link = '<a href="{}">Option_1</a>'.format(file)
    text_area.insertHtml(link)

    file_2 = 'c:/temp/test 2/test.docx'
    link = '<br><a href="{}">Option_2</a></br>'.format(file_2)
    text_area.insertHtml(link)

    text_area.show()
    sys.exit(app.exec_())
person ekhumoro    schedule 27.01.2021
comment
NB: это работает для меня в Linux, но я не проверял это в Windows. - person ekhumoro; 27.01.2021
comment
ОГРОМНОЕ СПАСИБО!!! Вы даете мне решение. В windows вариант 2 не работает, а вот варианты 7,10 и 13 работают отлично!!!! Я добавлю код в свой ответ. - person RBenet; 27.01.2021