mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-10 13:35:31 +02:00
Check the shell attributes of the items to see if we should show the Power Rename menu item and or perform a rename. Also fix a unit test for the SVG Thumbnail Provider. (#5158)
This commit is contained in:
@@ -67,6 +67,10 @@ HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirs
|
|||||||
if (CSettingsInstance().GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS)))
|
if (CSettingsInstance().GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS)))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
|
// Check if at least one of the selected items is actually renamable.
|
||||||
|
if (!DataObjectContainsRenamableItem(m_spdo))
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
HRESULT hr = E_UNEXPECTED;
|
HRESULT hr = E_UNEXPECTED;
|
||||||
if (m_spdo && !(uFlags & (CMF_DEFAULTONLY | CMF_VERBSONLY | CMF_OPTIMIZEFORINVOKE)))
|
if (m_spdo && !(uFlags & (CMF_DEFAULTONLY | CMF_VERBSONLY | CMF_OPTIMIZEFORINVOKE)))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source)
|
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source)
|
||||||
{
|
{
|
||||||
HRESULT hr = (source && wcslen(source) > 0) ? S_OK : E_INVALIDARG;
|
HRESULT hr = (source && wcslen(source) > 0) ? S_OK : E_INVALIDARG;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
PWSTR newName = nullptr;
|
PWSTR newName = nullptr;
|
||||||
@@ -226,6 +226,23 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT _GetShellItemArrayFromDataOject(_In_ IUnknown* dataSource, _COM_Outptr_ IShellItemArray** items)
|
||||||
|
{
|
||||||
|
*items = nullptr;
|
||||||
|
CComPtr<IDataObject> dataObj;
|
||||||
|
HRESULT hr;
|
||||||
|
if (SUCCEEDED(dataSource->QueryInterface(IID_PPV_ARGS(&dataObj))))
|
||||||
|
{
|
||||||
|
hr = SHCreateShellItemArrayFromDataObject(dataObj, IID_PPV_ARGS(items));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = dataSource->QueryInterface(IID_PPV_ARGS(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* psrm, _In_ int depth = 0)
|
HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* psrm, _In_ int depth = 0)
|
||||||
{
|
{
|
||||||
HRESULT hr = E_INVALIDARG;
|
HRESULT hr = E_INVALIDARG;
|
||||||
@@ -280,16 +297,7 @@ HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* ps
|
|||||||
HRESULT EnumerateDataObject(_In_ IUnknown* dataSource, _In_ IPowerRenameManager* psrm)
|
HRESULT EnumerateDataObject(_In_ IUnknown* dataSource, _In_ IPowerRenameManager* psrm)
|
||||||
{
|
{
|
||||||
CComPtr<IShellItemArray> spsia;
|
CComPtr<IShellItemArray> spsia;
|
||||||
IDataObject* dataObj{};
|
HRESULT hr = _GetShellItemArrayFromDataOject(dataSource, &spsia);
|
||||||
HRESULT hr;
|
|
||||||
if (SUCCEEDED(dataSource->QueryInterface(IID_IDataObject, reinterpret_cast<void**>(&dataObj))))
|
|
||||||
{
|
|
||||||
hr = SHCreateShellItemArrayFromDataObject(dataObj, IID_PPV_ARGS(&spsia));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = dataSource->QueryInterface(IID_IShellItemArray, reinterpret_cast<void**>(&spsia));
|
|
||||||
}
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
CComPtr<IEnumShellItems> spesi;
|
CComPtr<IEnumShellItems> spesi;
|
||||||
@@ -465,3 +473,31 @@ BOOL GetEnumeratedFileName(__out_ecount(cchMax) PWSTR pszUniqueName, UINT cchMax
|
|||||||
|
|
||||||
return fRet;
|
return fRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate through the data source and checks if at least 1 item has SFGAO_CANRENAME.
|
||||||
|
// We do not enumerate child items - only the items the user selected.
|
||||||
|
bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource)
|
||||||
|
{
|
||||||
|
bool hasRenamable = false;
|
||||||
|
CComPtr<IShellItemArray> spsia;
|
||||||
|
if (SUCCEEDED(_GetShellItemArrayFromDataOject(dataSource, &spsia)))
|
||||||
|
{
|
||||||
|
CComPtr<IEnumShellItems> spesi;
|
||||||
|
if (SUCCEEDED(spsia->EnumItems(&spesi)))
|
||||||
|
{
|
||||||
|
ULONG celtFetched;
|
||||||
|
CComPtr<IShellItem> spsi;
|
||||||
|
while ((S_OK == spesi->Next(1, &spsi, &celtFetched)))
|
||||||
|
{
|
||||||
|
SFGAOF attrs;
|
||||||
|
if (SUCCEEDED(spsi->GetAttributes(SFGAO_CANRENAME, &attrs)) &&
|
||||||
|
attrs & SFGAO_CANRENAME)
|
||||||
|
{
|
||||||
|
hasRenamable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasRenamable;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source);
|
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source);
|
||||||
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags);
|
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags);
|
||||||
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME LocalTime);
|
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME LocalTime);
|
||||||
|
bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource);
|
||||||
HRESULT EnumerateDataObject(_In_ IUnknown* pdo, _In_ IPowerRenameManager* psrm);
|
HRESULT EnumerateDataObject(_In_ IUnknown* pdo, _In_ IPowerRenameManager* psrm);
|
||||||
BOOL GetEnumeratedFileName(
|
BOOL GetEnumeratedFileName(
|
||||||
__out_ecount(cchMax) PWSTR pszUniqueName,
|
__out_ecount(cchMax) PWSTR pszUniqueName,
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ IFACEMETHODIMP CPowerRenameItem::ShouldRenameItem(_In_ DWORD flags, _Out_ bool*
|
|||||||
bool excludeBecauseFolder = (m_isFolder && (flags & PowerRenameFlags::ExcludeFolders));
|
bool excludeBecauseFolder = (m_isFolder && (flags & PowerRenameFlags::ExcludeFolders));
|
||||||
bool excludeBecauseFile = (!m_isFolder && (flags & PowerRenameFlags::ExcludeFiles));
|
bool excludeBecauseFile = (!m_isFolder && (flags & PowerRenameFlags::ExcludeFiles));
|
||||||
bool excludeBecauseSubFolderContent = (m_depth > 0 && (flags & PowerRenameFlags::ExcludeSubfolders));
|
bool excludeBecauseSubFolderContent = (m_depth > 0 && (flags & PowerRenameFlags::ExcludeSubfolders));
|
||||||
*shouldRename = (m_selected && hasChanged && !excludeBecauseFile &&
|
*shouldRename = (m_selected && m_canRename && hasChanged && !excludeBecauseFile &&
|
||||||
!excludeBecauseFolder && !excludeBecauseSubFolderContent);
|
!excludeBecauseFolder && !excludeBecauseSubFolderContent);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -237,12 +237,16 @@ HRESULT CPowerRenameItem::_Init(_In_ IShellItem* psi)
|
|||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// Check if we are a folder now so we can check this attribute quickly later
|
// Check if we are a folder now so we can check this attribute quickly later
|
||||||
|
// Also check if the shell allows us to rename the item.
|
||||||
SFGAOF att = 0;
|
SFGAOF att = 0;
|
||||||
hr = psi->GetAttributes(SFGAO_STREAM | SFGAO_FOLDER, &att);
|
hr = psi->GetAttributes(SFGAO_STREAM | SFGAO_FOLDER | SFGAO_CANRENAME, &att);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// Some items can be both folders and streams (ex: zip folders).
|
// Some items can be both folders and streams (ex: zip folders).
|
||||||
m_isFolder = (att & SFGAO_FOLDER) && !(att & SFGAO_STREAM);
|
m_isFolder = (att & SFGAO_FOLDER) && !(att & SFGAO_STREAM);
|
||||||
|
// The shell lets us know if an item should not be renamed
|
||||||
|
// (ex: user profile director, windows dir, etc).
|
||||||
|
m_canRename = (att & SFGAO_CANRENAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ protected:
|
|||||||
bool m_selected = true;
|
bool m_selected = true;
|
||||||
bool m_isFolder = false;
|
bool m_isFolder = false;
|
||||||
bool m_isDateParsed = false;
|
bool m_isDateParsed = false;
|
||||||
|
bool m_canRename = true;
|
||||||
int m_id = -1;
|
int m_id = -1;
|
||||||
int m_iconIndex = -1;
|
int m_iconIndex = -1;
|
||||||
UINT m_depth = 0;
|
UINT m_depth = 0;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace SvgThumbnailProviderUnitTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void CheckBlockedElements_ShouldReturnNullBitmap_IfBlockedElementsIsPresentInNestedLevel()
|
public void CheckBlockedElements_ShouldReturnNonNullBitmap_IfBlockedElementsIsPresentInNestedLevel()
|
||||||
{
|
{
|
||||||
var svgBuilder = new StringBuilder();
|
var svgBuilder = new StringBuilder();
|
||||||
svgBuilder.AppendLine("<svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">");
|
svgBuilder.AppendLine("<svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">");
|
||||||
@@ -43,7 +43,7 @@ namespace SvgThumbnailProviderUnitTests
|
|||||||
svgBuilder.AppendLine("</svg>");
|
svgBuilder.AppendLine("</svg>");
|
||||||
|
|
||||||
Bitmap thumbnail = SvgThumbnailProvider.SvgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
Bitmap thumbnail = SvgThumbnailProvider.SvgThumbnailProvider.GetThumbnail(svgBuilder.ToString(), 256);
|
||||||
Assert.IsTrue(thumbnail == null);
|
Assert.IsTrue(thumbnail != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|||||||
Reference in New Issue
Block a user