Resizing of QMessageBox - python

I have created a QMessageBox as follows:
msg_box = QtGui.QMessageBox()
msg_box.setSizeGripEnabled(True)
msg_box.setIcon( QtGui.QMessageBox.Information )
msg_box.setText('The following files are not .jpg ')
msg_box.setInformativeText('No. of Items : {0}'.format(len(contents)))
msg_box.setDetailedText('{0}'.format('\n'.join([str(sel) for sel in img_sels])))
msg_box.setStandardButtons(QtGui.QMessageBox.Cancel)
msg_exec = msg_box.exec_()
User will select a handful of images, and if within the selections, if it consists of items that are not of jpeg/ .jpg format, these items' file path will be collated and be displayed in QMessageBox
One issue that I had is that, I am having difficulties in getting the QMessageBox to be resize or have the UI width conform according the the length or the text etc. As I am unable to do that, the popup ui displays the filepath almost like in a wrapped text format, somewhat unsightly.
Is there any other ways that I can do to improve the code and have it accommodate to the width etc?
If not, is there another QtGui command that I can consider to use it?

Related

Text aside and below an image in pyqt5

I am preparing a catalog for a small library. All books with main data are displayed. Next to each title there is a button that must show the cover image and a short description of the content. Something like this.
Until now I have not found anything that could help me, all the options present in designer do not allow to have the text arranged as I would like
You cannot achieve that layout using Designer, because the layout management of Qt always considers objects (widgets) having a rectangular shape, even if they contain text: text based widgets are just like other "rectangular widgets" and their content is not considered nor changed based on the "shape" of other elements in the layout: Qt layout managers always consider widgets as rectangles.
It can be done, though, using rich-text based widgets like QLabel (discouraged for this purpose[1]) or QTextEdit, by embedding the image in the document[2], since the (limited) HTML subset provided by the Qt rich text engine supports the basic float property[3] for images and tables.
The following basic HTML can be used with QTextEdit.setHtml():
<img src="path/to/image.png" style="float: right;">
Some very long text...
...
...
...
Here is the result:
The only issue is the path of the image.
If the image is stored with the Qt resource system, use that path (src=":path/in/resources")[4].
If the image is a local file, then just use python formatting with the path to that file, and ensure that that path is correct (consider that relative paths always use the working directory, which is the path from which the python interpreter is launched).
If the image is loaded internally (for instance, from the network) and not stored as a physical file, you can use the base64 encoding to show the image:
import base64
# ...
# assuming "imageData" is a Python "bytes" object
base64data = base64.b64encode(imageData).decode()
html = '''
<img src="data:image/whatever;base64,{}" style="float: right;">
'''.format(base64data)
# to avoid escaping of curly brackets for format() or f-string
html += '''
Some very long text...
'''
textEdit = QTextEdit(readOnly=True)
textEdit.setHtml(html)
Note that the value of data: in <img src=""> is actually pointless: you only need to provide the data: part, the value is actually not that relevant since Qt just uses QImage.loadFromData() and automatically guesses the format from the file using QImageReader. The result is the same that you would get by doing img = QImage('myimage') even if you don't specify the format and the file name has no specific/valid extension. This also obviously means that if the file/data is corrupted, the image might not be shown (and a "broken image" icon will be shown as a placeholder).
If the image was retrieved through Qt (for instance, using QFile.readAll() or downloaded with QNetworkAccessManager), then the the raw data is stored as a QByteArray, and the base64 data used above can be created with the following:
base64data = imageData.toBase64().data().decode()
as in:
# - encode using base64, as another QByteArray:
qtBase64 = imageData.toBase64()
# - convert it to a Python "bytes" object (b"..."):
pyBase64 = qtBase64.data()
# - make it a string:
base64data = pyBase64.decode()
The above is also valid if the image is stored on a database as raw data.
[1] QLabel obviously lacks direct support for scrolling, and it also has some important limitations when using rich text contents (most importantly, word wrapped contents) and the label is part of a complex layout.
[2] QLabel actually uses QTextDocument features internally, which enables rich text features (most importantly, word wrapping; see the above note) whenever it detects what could possibly be HTML formatted content (based on the return value of Qt.mightBeRichText()).
[3] Remember that the current Qt rich-text support is based on HTML4 and CSS2.1, so the only valid values of float are: left, right and none (the default). The CSS inherit value is also not supported.
[4] Be aware that PyQt6 dropped support for the pyrcc utility, but resource files can still be used (since they're implemented on the Qt side, not in Python) and built with the rcc utility provided by Qt: they added the -g python flag, similarly to what done for uic, which creates python compatible resource files. You only need to edit the import statement of the generated file to avoid issues (remember that PyQt and PySide can not be used together, and PySide might not be installed in the target system). See this answer.

Why isn't the PyQt5 QPushButton or QAction showing the desired image in Qtoolbar

I have the following code to show an image of 16x16 or 16x12 in jpg and png format using QPushButton:
navbar=QToolBar()
btn=QPushButton()
btn.setIcon(QIcon(QPixmap("back.jpg"))) #or .png
btn.clicked.connect(self.btn_pressed)
navbar.addWidget(btn)
I also tried just using QAction like so:
navbar=QToolBar()
action=QAction(QIcon(QPixmap("back.jpg")),"back",self)
action.triggered.connect(self.btn_pressed)
navbar.addAction(action)
They always either show the text or the actual button but empty with no text or rendered image and I can't see where everything fails.
As #furas mentioned Current Working Directory depends on which command line path the file is started and it was constantly changing so the dependency on my relative path was causing the issue.

change all fonts in powerpoint without opening the file

I wanted change the all fonts in about 100 powerpoint files, without opening the files. There are several shape types in each slide and each might have a different font. I used python-pptx package and wrote the following code to change the fonts of all texts in a powerpoint presentation. Although it does not give any error, it does not work, and the fonts in the file are still whatever they were, for example Arial. I also added print(shape.text) to make sure that it has found all texts, and it seems that there is no issue there. Is it a bug? Or am I missing anything?
prs = Presentation('f10.pptx')
for i, slide in enumerate(prs.slides):
for shape in slide.shapes:
print (shape.has_text_frame)
if shape.has_text_frame:
print(shape.text)
for p in shape.text_frame.paragraphs:
for r in p.runs:
print(r.font.name)
r.font.name = 'Tahoma'
print(r.font.name)
prs.save('f10_tahoma.pptx')
Besides, it seems that the package does not work for utf-8 characters. I added a text-box on the last slide by adding:
text_frame = shape.text_frame
text_frame.clear() # not necessary for newly-created shape
p = text_frame.paragraphs[0]
run = p.add_run()
run.text = 'سلام '
font = run.font
font.name = 'Andalus'
font.size = Pt(18)
before saving the file to add a textbox with utf-8 characters. It adds it there, and when I check the font it shows that it is set to Andalus, but actually it is not Andalus.
With Aspose.Slides for Python via .NET, you can easily change all fonts for all texts in your presentations. The following code example shows you how to do this:
import aspose.slides as slides
with slides.Presentation('example.pptx') as presentation:
for slide in presentation.slides:
for shape in slide.shapes:
if isinstance(shape, slides.AutoShape):
for paragraph in shape.text_frame.paragraphs:
for portion in paragraph.portions:
portion.portion_format.latin_font = slides.FontData('Tahoma')
You can also evaluate Aspose.Slides Cloud SDK for Python for presentation manipulating. This REST-based API allows you to make 150 free API calls per month for API learning and presentation processing.
Aspose Slides Online Viewer can be used to view presentations without PowerPoint installed.
I work at Aspose.
What language is the text of the file? Run.font properties work fine for UTF-8, but there is a separate font for cursive scripts like Arabic. Access to that secondary font is not implemented in python-pptx unfortunately, but that could explain at least part of the behavior you're seeing.
For roman character text (like that we're using here), there are a couple things to check.
The font in question needs to be installed on the machine PowerPoint is running on when the document is opened. Otherwise PowerPoint will substitute a font.
The font (typeface) name used in the XML will not always exactly match what appears in the PowerPoint drop-down selection box. You need to give that name to python-pptx in the exact form it should appear in the XML. You may need to make an example file that works by hand, perhaps containing a single slide with a single textbox for simplicity, and then inspect the XML of that file to find the "spelling" used for that typeface by PowerPoint.
You could do that with code like this:
prs = Presentation("example.pptx")
shape = prs.slides[0].shapes[0]
print(shape._element.xml)
You should be able to locate the typeface name somewhere in an element like <p:rPr> or <p:defRPr>.

How to to center selected text in QTextBrowser

The code posted below creates QTextBrowser window filling it with 100 lines of text: starting from MESSAGE-0000 all the way to MESSAGE-0099
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication([])
textBrowser = QtGui.QTextBrowser()
for i in range(100):
textBrowser.insertPlainText('MESSAGE-%04d'%i + '\n')
textBrowser.show()
app.exec_()
Question: How to find a line number where its text says: MESSAGE-0051, then select or highlight it and then scroll to it so the selected-highlightet line is positioned at the top edge of the QTextBrowser window, so the result would look like this:
How to achieve it?
If you search backwards, it will automatically scroll the selected line to the top of the viewport:
textBrowser.moveCursor(QtGui.QTextCursor.End)
textBrowser.find('MESSAGE-0051', QtGui.QTextDocument.FindBackward)
(Of course, if you search for say, MESSAGE-0095, it won't put the selected line at the top, because the view cannot scroll down that far).

Python images display

How can I create a python script that runs through the images (1.jpeg-n.jpeg) in a directory on a mac and displays them in a browser OR via another python program?
Do I import a file to python and than display in browser?
Do I extract the file names 1,2,3,4,5 and add that to a list, which I give to another function that calls a browser and displays?
Any help would be great.
Thanks!
Using Tkinter and PIL for this purpose is pretty trivial. Add muskies example to the information from this thread that contains this example:
# use a Tkinter label as a panel/frame with a background image
# note that Tkinter only reads gif and ppm images
# use the Python Image Library (PIL) for other image formats
# free from [url]http://www.pythonware.com/products/pil/index.htm[/url]
# give Tkinter a namespace to avoid conflicts with PIL
# (they both have a class named Image)
import Tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
root.title('background image')
# pick an image file you have .bmp .jpg .gif. .png
# load the file and covert it to a Tkinter image object
imageFile = "Flowers.jpg"
image1 = ImageTk.PhotoImage(Image.open(imageFile))
# get the image size
w = image1.width()
h = image1.height()
# position coordinates of root 'upper left corner'
x = 0
y = 0
# make the root window the size of the image
root.geometry("%dx%d+%d+%d" % (w, h, x, y))
# root has no image argument, so use a label as a panel
panel1 = tk.Label(root, image=image1)
panel1.pack(side='top', fill='both', expand='yes')
# put a button on the image panel to test it
button2 = tk.Button(panel1, text='button2')
button2.pack(side='top')
# save the panel's image from 'garbage collection'
panel1.image = image1
# start the event loop
root.mainloop()
Of course if you're more familiar with another GUI, go ahead and adapt the example, it shouldn't take much.
You first have to find all image filenames. You can use os.listdir(...) to get all files in a certain directory, or glob.glob(...) to find all files matching a certain pattern.
Showing the images is the second and more challenging part of this. The first option is to open the images in an external program, this can be a web browser. On (most) platforms a command firefox 1.jpeg will open the image 1.jpeg in the Firefox browser. You can use the subprocess module to execute such commands. If you want to show them using a nice GUI, you have to create a GUI using some framework and use this. But if you are a beginner this might be a little bit too difficult for you.
For example:
import glob
import subprocess
files = glob.glob('dir/*.jpeg')
for file in files:
subprocess.call(['firefox', file])
muksie's answer already contains very useful advice. If don't want to write the HTML file yourself or want something a little fancier you could use a small script I wrote for the MDP library. This basically allows you to just do:
import slideshow
slideshow.show_image_slideshow(filenames, image_size=(80,60))
This will create an HTML slideshow and open it in your browser. You can grab just the needed files here (only templet.py and the two slideshow files are needed), which might be better for you than getting the full library.
It might be a lot easier to just generate a static web page with pictures than building a GUI for displaying pictures.
You can just generate a hmtl page, put the images on it and start your web browser with the newly created html file. this gives you some possibilities for layout as well.
If you just want a picture in the browser then muksie gave a working example.

Categories

Resources