PDA

View Full Version : Width for QProgressDialog should be determined by Dialog's Window Title



apatwork
1st October 2018, 16:22
Hi there,

I am just implementing a QProgressDialog. Everything works as expected except one strange behavior:

I cannot manage to ensure that the dialog's horizontal size is big enough to show the complete text of the window title I defined. Here's my code:



QProgressDialog progress(QString("Loading %1 Objects").arg(ids.size()), "Abort", 0, ids.size(), this);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(500);
progress.setWindowTitle("My really somewhat long Window Title");


I tried to accomplish this using the setSizePolicy() method but without success. But there should be a simple way to accomplish this ...

d_stranz
3rd October 2018, 22:24
You have to retrieve the dialog's font metrics, determine the pixel length of the string in that font, then resize the dialog's width to be wide enough to contain that plus everything inside the dialog plus the control buttons and icons on the title bar. Otherwise, if the width is too narrow, the title will be elided ("My really somewhat long ...").

The size policy applies only to the children within the dialog, not the title bar.

apatwork
4th October 2018, 14:12
Thanks a lot, d_stranz! I added these lines of code to the
progress dialog configuration code shown in my first posting:


const QString dlgTitle("My really somewhat long Window Title");
progress.setWindowTitle(dlgTitle);
QFont displayFont(font());
QFontMetrics fm(displayFont);
int widthInPixels(fm.width(dlgTitle) + 120);
progress.setMinimumWidth(widthInPixels);

I added 120 pixels to ensure that the dialog is wide enough to contain
the icon on the upper left corner as well as the X-button on the upper
right corner.

As you already mentioned I need to take into account the
width of the contents of the dialog (this will always be narrower than the title
string) as well as the widths of the icons present in the window
title. I found this approach:


QStyle *style = qApp->style();
QIcon closeIcon(style->standardIcon(QStyle::SP_TitleBarCloseButton));

Unfortunately I couldn't figure out how to determine the actual width
of such an icon.
My assumption is that the icon on the upper left corner of the dialog
window might have the same size as the X-button.

d_stranz
4th October 2018, 16:17
My assumption is that the icon on the upper left corner of the dialog
window might have the same size as the X-button.

That is probably not a bad assumption. The QIcon can tell you what the QSize is. Anyway if it is your dialog, you can add as much padding as you want to the title. By the way QWidget::windowIcon() will return the top-left corner icon if there is any.

You may also have some problems if the OS has font magnification turned on. I use a big 4K monitor, and have the font magnification set to 125% so I can read it. I have noticed some problems with Qt apps where dialogs did not take this into account so the text was clipped. So you may need to temporarily change the font magnification for your screen to make sure your calculations still work.

apatwork
4th October 2018, 17:21
Phantastic! Thanks a lot once again, d_stranz!

I already studied the QIcon class's APIs and encountered the method
actualSize(). But I don't completely understand how to use it:



QSize QIcon::actualSize(const QSize &size, QIcon::Mode mode = Normal, QIcon::State state = Off) const

The documentation says:

Returns the actual size of the icon for the requested size, mode, and
state. The result might be smaller than requested, but never
larger. The returned size is in device-independent pixels (This is
relevant for high-dpi pixmaps.)

My problem with that description is that I don't know what is meant
with "requested size".

d_stranz
4th October 2018, 22:30
My problem with that description is that I don't know what is meant with "requested size".

I see your problem. QIcon is designed to return a scaled pixmap for whatever size is requested. You can provide QIcon with several pixmaps to choose from, using QIcon::addPixmap(). If you ask for a size that is in-between the size of one of the pixmaps, it will choose the smaller one, or create one by interpolating or scaling down one of the ones it does have.

There is another way to get at this, and that is to use QStyle::pixelMetrix() and one of the QStyle::PixelMetric enums: QStyle::PM_TitleBarHeight (and assume width == height for icons), QStyle::PM_TitleBarButtonIconSize, or QStyle::PM_TitleBarButtonSize. The last two are Qt >= 5.8.

apatwork
5th October 2018, 10:22
Whow! Thank you very much for the explanation!

I now tried the computation using the QStyle object. My code looks as follows (progress is an instance of type QProgressDialog):


QStyle *style(qApp->style());
QStyleOptionButton btn;
int metricVal(style->pixelMetric(QStyle::PM_TitleBarHeight, &btn, &progress));
QFont displayFont(font());
QFontMetrics fm(displayFont);
int widthInPixels(fm.width(dlgTitle) + 2 * metricVal);
progress.setMinimumWidth(widthInPixels);

Surprisingly for me this did not lead to a completely visible window title. The resulting minimum width of the QProgressDialog window was still about 20% too small.

I even tried the other QStyle values you mentioned but they led to an even smaller resulting width. The metricVal values returned were these:


QStyle::PM_TitleBarButtonIconSize -- 16
QStyle::PM_TitleBarHeight -- 24
QStyle::PM_TitleBarButtonSize -- 19

I should mention that I'm developing my Qt application on RedHat Enterprise Linux v. 7.x.

d_stranz
5th October 2018, 16:30
I wonder if QDialog::font() is returning the default font for the dialog, and that it might be a different font (controlled by the OS) for the title bar? Try changing the default font in Qt Designer (or in your dialog constructor) and see if the title font changes. I would bet that it doesn't.

I am searching for a Qt class / method that will allow you to retrieve the title bar font, but so far I'm not having any luck.

apatwork
9th October 2018, 13:48
Hi,

I agree completely with you. The size of the font being used in the window title is definitively larger than the font size used in the dialog window and it displays bold shape characters.

I also tried to figure out how I could retrieve the font used in the window title using Qt APIs but until now without success. During my research I learned that the window title's properties are defined by the window manager in Linux and so possibly there might be no API in Qt that allows access to this information.

Finally I ended up with this code:


const QString dlgTitle("My really somewhat long Window Title");
QStyle *style(qApp->style());
QStyleOptionButton btn;
int metricVal(style->pixelMetric(QStyle::PM_TitleBarHeight, &btn, &progress));
QFont displayFont(font());

// Enlarge font size by one point and switch to bold display.
displayFont.setPointSize(displayFont.pointSize() + 1);
displayFont.setBold(true);
QFontMetrics fm(displayFont);

// Add two times the title bar height to the width used up by the text.
int widthInPixels(fm.width(dlgTitle) + 2 * metricVal);

progress.setMinimumWidth(widthInPixels);

I'm not really happy with this solution but at least it works on Linux.