Open a .pdf by clicking on QLabel made as Hyperlink - python

I have been trying to create something which lets me click on Qlabel (converted to hyperlink) and opens a .pdf file.
I got the two following ideas from PYQT QLabel link to open folder on computer:
Idea 1
self.text_label.setText(' Reference Link')
self.text_label.setOpenExternalLinks(True)
Idea 2
self.text_label.setText("<a href={}>Reference Link</a>".format("/Documents/To%20be%20Saved/hello.pdf"))
self.text_label.setOpenExternalLinks(True)
None of the ideas seem to open that pdf file. I see the hyperlink created but if I click it, it does nothing.

The URL must be encoded:
file:///C:/Users/Shaurya/Documents/To%20be%20saved/hello.pdf
In addition to showing the fullpath so that whoever manages this resource as a browser can find it.
To do this you must use toEncoded() as shown below:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QLabel()
path = r"C:\Users\Shaurya\Documents\To be saved\hello.pdf"
# or
# path = QDir.home().filePath(r"Documents\To be saved\hello.pdf")
# or
# path = QDir(QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation)).filePath(r"To be saved\hello.pdf")
url = bytearray(QUrl.fromLocalFile(path).toEncoded()).decode() # file:///C:/Users/Shaurya/Documents/To%20be%20saved/hello.pdf
text = "<a href={}>Reference Link> </a>".format(url)
w.setText(text)
w.setOpenExternalLinks(True)
w.show()
sys.exit(app.exec_())

Related

PyQT drag and drop to reorder items

Im trying to make a small app that would help me rename pictures. Since i want to manually order them, i had the idea to simply show a window with thumbnails inside in a grid ( or small scale images, doesnt matter ), and then drag and drop reorder them as i see fit. Afterwards its just click a button and they get properly named acording to the order.
Is there any container or something that would allow its inside widgets to be moved around like that while also properly displaying the inside widgets?
The ways im thinking of currently since i cant find anything else, is to make the whole background a canvas, move x/y on drag/drop of the pictures and then calculate where im dropping it off and manually reorder the whole canvas again and keep redrawing.
Im open to different python solution if anyone has them, but after checking wxwidgets and tkinter, i havent found anything that would be a solution to this without a lot of manual code.
After ekhumoro hint, i was able to solve it.
Heres a sample code that reads the current folder of its files, shows them as "thumbnails", and allows reordering.
#!/usr/bin/python
import sys, os
from PyQt5.QtWidgets import (QListWidget, QWidget, QMessageBox,
QApplication, QVBoxLayout,QAbstractItemView,QListWidgetItem )
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import QListView
class Example(QWidget):
def __init__(self):
super().__init__()
self.icon_size = 200
self.initUI()
def loadImageItem(self, fajl,folder=None):
icon = QIcon()
item = QListWidgetItem()
if folder is not None:
pot = os.path.join(folder,fajl)
else:
pot = fajl
icon.addFile(pot,size=QSize(self.icon_size,self.icon_size))
item.setIcon(icon)
item.setTextAlignment(Qt.AlignBottom)
return item
def initUI(self):
vbox = QVBoxLayout(self)
listWidget = QListWidget()
#make it icons
listWidget.setDragDropMode(QAbstractItemView.InternalMove)
listWidget.setFlow(QListView.LeftToRight)
listWidget.setWrapping(True)
listWidget.setResizeMode(QListView.Adjust)
listWidget.setMovement(QListView.Snap)
listWidget.setIconSize(QSize(200,200))
folder = os.getcwd()
#folder = "/mnt/Data/pictures/2022-10-30 Sveta Katarina/izbor/1"
files = os.listdir(folder)
files = [f for f in files if os.path.isfile(os.path.join(folder,f))]
for foo in files:
listWidget.addItem(self.loadImageItem(foo,folder=folder))
vbox.addWidget(listWidget)
self.setLayout(vbox)
self.setGeometry(10, 10, 1260, 820)
self.setWindowTitle('Image renamer')
self.show()
def main():
App = QApplication(sys.argv)
ex = Example()
sys.exit(App.exec())
if __name__ == '__main__':
main()

link to file in OS in python for QTableWidgetItem

I want to create a hyperlink of (file_path ) using python that will point to the file in operating system. I am able to get the path of the file. How can I create a hyperlink of this path and store in a variable. I want to display this in the QtWidgets as link where user can click and open the file stored in windows OS.
file_path = os.path.join(dir_path, FileName)
self.documents.setItem(0, 0, QtWidgets.QTableWidgetItem(file_path))
You can use QLabel with html content to create clickable link.
from PyQt5 import QtWidgets, QtCore
import os
if __name__ == "__main__":
app = QtWidgets.QApplication([])
path = os.environ["USERPROFILE"]
text = "click me"
label = QtWidgets.QLabel('{}'.format(path, text))
label.show()
label.linkActivated.connect(os.startfile)
app.exec()

Blank page and error with only a specific url with pyqt webview in python

I have got an issue when using this following code with a specific url only:
import sys
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView,QWebSettings
class Browser(QWebView):
def __init__(self):
QWebView.__init__(self)
Settings = self.settings()
Settings.setAttribute(QWebSettings.JavascriptEnabled, True)
Settings.setAttribute(QWebSettings.JavaEnabled, True)
Settings.setAttribute(QWebSettings.PluginsEnabled, True)
Settings.setAttribute(QWebSettings.AutoLoadImages, True)
self.loadFinished.connect(self._result_available)
def _result_available(self, ok):
frame = self.page().mainFrame()
print unicode(frame.toHtml()).encode('utf-8')
if __name__ == '__main__':
app = QApplication(sys.argv)
view = Browser()
from_url=True
url_to_view='https://www.twitch.tv/'
if from_url==True:
view.load(QUrl(url_to_view))
view.show()
app.exec_()
When running this code I get a blank page and this error:
QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.
QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.
It is very strange because I have got this issue only with the https://www.twitch.tv/ url. I had try to replace url with https://www.google.com or anything else and it works fine.
I was expecting that it was relative to python2 and PyQt4, but I have got the same issue when running on python3 and PyQt5 implementation
Someone could help me to properly load the page with pyqt ?

Calling function from Jupyter Notebook not reading string

This seems simple. I have a Jupyter Notebook with the following code allowing for a file dialog so the user can select a file to analyze. There are a couple of different files used and it is important the user selects the proper file in the proper order. I am trying to add information to the Window title so the user knows which file the script is looking for.
Here is the Notebook code:
import PCB_utility
f_name = PCB_utility.get_file('Select Bitwise data file')
df_bitwise = pd.read_excel(f_name, sheetname = 'lvtemporary_653630', header=(0))
f_name = PCB_utility.get_file('Select ARINC 429 data file')
df_ARINC = pd.read_csv(f_name, sep = '\t', header=(0))
The file dialog works. The user selects the file, and the program just does what it needs to. I am trying to make it a little more user friendly.
PCB_utility looks like this:
import sys
from PyQt4.QtGui import *
#from PyQt4.QtCore import *
def get_file(Instructions):
filename = QFileDialog.getOpenFileName(None, Instructions, '/')
return(filename)
The problem is the Instructions are NOT making through to the dialog box. I manually entered this function into the IPython section and it works beautifully. It doesn't add the extra text when I call it from the notebook. It just has the standard 'Open File'.
Here is the code that finally worked:
import sys
from PyQt4.QtGui import *
def get_file(Instructions):
# Create an PyQT4 application object.
app = QApplication(sys.argv)
# The QWidget widget is the base class of all user interface objects in PyQt4.
wid = QWidget()
# Get filename using QFileDialog
filename = QFileDialog.getOpenFileName(wid, Instructions, '/')
return(filename)
sys.exit(app.exec_())
I needed to add the PyQt4 application and widget, then close it. I have to admit I don't quite understand why, but it works.
OP already found solution, but for others that looking for the same thing - you can use IPython magic command for enabling IPython GUI event loop integration, to make working external GUI called from IPython (i.e. Jupyter notebook):
# Magic (we must tell IPython that we will be running an external Qt GUI)
%gui qt5
from PyQt5.QtWidgets import QFileDialog
def select_file(directory='./'):
fname = QFileDialog.getOpenFileName(None,
'Select file...',
directory,
filter='All files (*)')
return fname[0]
As original question is for PyQt4, above command %gui qt5 should be replaced with %gui qt4 or only %gui qt.
To do the same thing without magic commands (similar to OP's solution):
import sys
from PyQt5.QtWidgets import QApplication, QFileDialog
def select_file(directory='./'):
app = QApplication(sys.argv)
fname = QFileDialog.getOpenFileName(None,
'Select file...',
directory,
filter='All files (*)')
return fname[0]

PyQt QWebKit frame bug?

I'm using Python, PyQt4, and QtWebKit to load a web page into a bare-bones browser to examine the data.
However, there is a small issue. I'm trying to get the contents and src of every iframe on the loaded page. I'm using webView.page().mainFrame().childFrames() to get the frames. To problem is, childFrames() loads the frames ONLY if they're visible by the browser. For example, when your browser is positioned at the top of the page, childFrames() will not load the iframes are at the footer of the page. Is there a way or setting I could tweak where I can get all ads? I've attached the source of my "browser". Try scrolling down when the page finishes it's loading. Watch the console and you will see that the iframes load dynamically. Please help.
from PyQt4 import QtGui, QtCore, QtWebKit
import sys
import unicodedata
class Sp():
def Main(self):
self.webView = QtWebKit.QWebView()
self.webView.load(QtCore.QUrl("http://www.msnbc.msn.com/id/41197838/ns/us_news-environment/"))
self.webView.show()
QtCore.QObject.connect(self.webView,QtCore.SIGNAL("loadFinished(bool)"),self.Load)
def Load(self):
frame = self.webView.page().mainFrame()
children = frame.childFrames()
fT = []
for x in children:
print "=========================================="
print unicodedata.normalize('NFKD', unicode(x.url().toString())).encode('ascii','ignore')
print "=========================================="
fT.append([unicode(x.url().toString()),unicode(x.toHtml()),[]])
for x in range(len(fT)):
f = children[x]
tl = []
for fx in f.childFrames():
print "___________________________________________"
print unicodedata.normalize('NFKD', unicode(fx.url().toString())).encode('ascii','ignore')
print "___________________________________________"
tl.append([unicode(fx.url().toString()),unicode(fx.toHtml()),[]])
fT[x][2] = tl
app = QtGui.QApplication(sys.argv)
s = Sp()
s.Main()
app.exec_()
Not sure why you're doing what you're doing, but if it's only loading what's visible, you can set the page viewport size to the content size and that should load everything:
def Load(self):
self.webView.page().setViewportSize(
self.webView.page().mainFrame().contentsSize())
However, this has a weird effect in the GUI so this solution may be unacceptable for what you are trying to do.

Categories