Reputation: 48260
I need to get the visible title of a Qt top level window (or MDI subwindow), because I want to list window titles in different places just like they're visible for the user.
Consider a program that supports multiple top level editor windows (or an MDI area with similar purposes) that should list the titles of those windows, like a menu or an internal "window manager".
If I want to list those windows and also support the [*]
placeholder for the windowModified
property, their windowTitle()
will return that annoying placeholder no matter of their state.
Unfortunately, the windowTitle
feature is a bit abstract, for the following reasons:
windowModified
feature, it always returns the placeholder if it's set;[*]
placeholder can be "escaped" with multiple, even occurrences, in order to actually display [*]
in the window title: Title [*][*]
will always be shown as Title [*]
no matter the value of the windowModified
property;windowTitle
property is an empty string (the default), it falls back to the windowFilePath
property, which not only make it always include the [*]
placeholder, but could also behave oddly in the rare case that property contains the [*]
placeholder; while I realize that this is a very odd (and somehow irresponsible, assuming the system actually supports it) situation, I still want a reliable way to get the currently resulting window title, even in those rare (though "wrong") situations;Is there a way to get the real title that Qt sets for the window, considering the above?
Upvotes: -2
Views: 905
Reputation: 11064
The best approach for top level windows (not MDI subwindows) is to use QWindow::title
:
This property holds the window's title in the windowing system
The window title might appear in the title area of the window decorations, depending on the windowing system and the window flags. It might also be used by the windowing system to identify the window in other contexts, such as in the task switcher.
How to obtain the QWindow
?
If you already know the QWidget
, you can use QWidget::windowHandle
. Note that the QWindow
object is only available for native widgets (f.ex. top level widgets, but not for MDI subwindow).
Another approach is to directly query for all the top level windows using QGuiApplication::topLevelWindows
MDI subwindow support?
As those MDI subwindows are not top level windows, the QWindow
doesn't exists. So, this approach doesn't work in that case. Possible solutions are:
Upvotes: 1
Reputation: 48260
There is no absolute and certain way to get the title that the OS will finally show in the title bar of a top level window.
As explained in the windowTitle
documentation, some systems might support displaying the applicationDisplayName
. Some highly customizable (Linux) OS might show an altered version of the provided title. There is almost no way to get the "final", displayed title, unless you want to dig into specific OS modules that interface with the Window Manager (and that might not be enough anyway, due to the high level of customization possible on *nix systems).
Considering that what's relevant for the OP is the "internal" window title (what Qt finally "relays" to the system), the solution is to implement what Qt actually does internally with qt_setWindowTitle_helperHelper()
.
Be aware that the Qt implementation is not perfect. There are some odd cases when specific combinations of the placeholder string are used. For instance:
[*] [*] [*]
as window title results in "[*]
" being shown for an unmodified window and "* [*] *
" otherwise;[*] [*][*] [*]
, the unmodified window title is " [*] [*]
" (note the leading space) and the other is "* [*]* [*]
"While, as said above, the Qt implementation is far from perfect, what we're interested into is the actual window title relayed to the OS, so we must adhere to it, since the visual result is the important aspect, no matter whether it's "correct" or not.
Finally, remember that this implementation might become invalid in the future, in case Qt developers decide to change this behavior (and, I believe, they should).
The following code is a simple function that will return the actual window title relayed to the OS for a give widget, which can be used for any situation in which the visible title has to be displayed:
def realWindowTitle(widget):
title = widget.windowTitle()
placeHolder = '[*]'
if not placeHolder in title:
return title
phSize = len(placeHolder)
style = widget.style()
if (widget.isWindowModified()
and style.styleHint(
style.SH_TitleBar_ModifyNotification, None, widget)
# for PyQt6 or full Enum support use
# style.StyleHint.SH_TitleBar_ModifyNotification
):
replaceHolder = '*'
else:
replaceHolder = ''
index = title.find(placeHolder)
while index != -1:
index += phSize
count = 1
while title.find(placeHolder, index) == index:
count += 1
index += phSize
if count % 2: # odd number of [*] -> replace last one
lastIndex = title.rfind(placeHolder, 0, index)
title = (title[:lastIndex]
+ replaceHolder
+ title[lastIndex + phSize:])
index = title.find(placeHolder, index)
# return "escaped" sequences of the remaining double placeholders
return title.replace('[*][*]', placeHolder)
Upvotes: 0