Windows: Don't force native file dialogs to index compressed files

We use QWindowsShellItem to hook into the native windows file dialog
and interface correctly with special windows folders. We create objects
of QWindowsShellItem e.g. when the user selects a file. We then probe
the shell item for various attributes, e.g. to see if it represents a
folder.

The selected item might be a compress archive of significant size, and
checking whether that archive is a folder can take significant amount
of time during which the UI is completely blocked.

To prevent that, first check whether the item is a compress item, or a
stream, and if so, don't check whether it has sub-folders.

Also, don't use the SFGAO_DISPLAYATTRMASK value, which the API
documentation [1] explicitly documents as "Don't use".

[1] https://learn.microsoft.com/en-us/windows/win32/shell/sfgao

Fixes: QTBUG-107618
Change-Id: Ifcdec53ec3f8a0236d849a0b72a71afbd03d8290
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
(cherry picked from commit 933eb68a9d81391174b772fd49f344082b61fa1b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2022-10-20 12:58:39 +02:00 committed by Qt Cherry-pick Bot
parent c22bf97cb1
commit 520a837888

View File

@ -544,8 +544,18 @@ QWindowsShellItem::QWindowsShellItem(IShellItem *item)
: m_item(item)
, m_attributes(0)
{
if (FAILED(item->GetAttributes(SFGAO_CAPABILITYMASK | SFGAO_DISPLAYATTRMASK | SFGAO_CONTENTSMASK | SFGAO_STORAGECAPMASK, &m_attributes)))
SFGAOF mask = (SFGAO_CAPABILITYMASK | SFGAO_CONTENTSMASK | SFGAO_STORAGECAPMASK);
// Check for attributes which might be expensive to enumerate for subfolders
if (FAILED(item->GetAttributes((SFGAO_STREAM | SFGAO_COMPRESSED), &m_attributes))) {
m_attributes = 0;
} else {
// If the item is compressed or stream, skip expensive subfolder test
if (m_attributes & (SFGAO_STREAM | SFGAO_COMPRESSED))
mask &= ~SFGAO_HASSUBFOLDER;
if (FAILED(item->GetAttributes(mask, &m_attributes)))
m_attributes = 0;
}
}
QString QWindowsShellItem::path() const