[New+]Support for variables in template filenames (#37074)

* Add variable support - initial version without UI

* Add variable in template filename support in New+

* Fix XAML style

* Addressed code review feedback
This commit is contained in:
Christian Gaarden Gaardmark
2025-03-18 04:52:51 -07:00
committed by GitHub
parent 1d358af600
commit 1f81d14000
28 changed files with 592 additions and 96 deletions

View File

@@ -6,7 +6,6 @@
#include "new_utilities.h"
#include <cassert>
#include <thread>
#include <shellapi.h>
#include <shlobj_core.h>
using namespace Microsoft::WRL;
@@ -17,7 +16,7 @@ template_item::template_item(const std::filesystem::path entry)
path = entry;
}
std::wstring template_item::get_menu_title(const bool show_extension, const bool show_starting_digits) const
std::wstring template_item::get_menu_title(const bool show_extension, const bool show_starting_digits, const bool show_resolved_variables) const
{
std::wstring title = path.filename();
@@ -27,13 +26,21 @@ std::wstring template_item::get_menu_title(const bool show_extension, const bool
title = remove_starting_digits_from_filename(title);
}
if (show_resolved_variables)
{
title = helpers::variables::resolve_variables_in_filename(title, constants::non_localizable::parent_folder_name_variable);
}
if (show_extension || !path.has_extension())
{
return title;
}
std::wstring ext = path.extension();
title = title.substr(0, title.length() - ext.length());
if (!helpers::filesystem::is_directory(path))
{
std::wstring ext = path.extension();
title = title.substr(0, title.length() - ext.length());
}
return title;
}
@@ -53,7 +60,8 @@ std::wstring template_item::get_target_filename(const bool include_starting_digi
std::wstring template_item::remove_starting_digits_from_filename(std::wstring filename) const
{
filename.erase(0, min(filename.find_first_not_of(L"0123456789 ."), filename.size()));
filename.erase(0, min(filename.find_first_not_of(L"0123456789"), filename.size()));
filename.erase(0, min(filename.find_first_not_of(L" ."), filename.size()));
return filename;
}
@@ -70,7 +78,7 @@ HICON template_item::get_explorer_icon_handle() const
std::filesystem::path template_item::copy_object_to(const HWND window_handle, const std::filesystem::path destination) const
{
// SHFILEOPSTRUCT wants the from and to paths to be terminated with two NULLs,
// SHFILEOPSTRUCT wants the from and to paths to be terminated with two NULLs.
wchar_t double_terminated_path_from[MAX_PATH + 1] = { 0 };
wcsncpy_s(double_terminated_path_from, this->path.c_str(), this->path.wstring().length());
double_terminated_path_from[this->path.wstring().length() + 1] = 0;
@@ -84,37 +92,16 @@ std::filesystem::path template_item::copy_object_to(const HWND window_handle, co
file_operation_params.hwnd = window_handle;
file_operation_params.pFrom = double_terminated_path_from;
file_operation_params.pTo = double_terminated_path_to;
file_operation_params.fFlags = FOF_RENAMEONCOLLISION | FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS | FOF_WANTMAPPINGHANDLE;
file_operation_params.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS;
const int result = SHFileOperation(&file_operation_params);
if (!file_operation_params.hNameMappings)
if (result != 0)
{
// No file name collision on copy
if (utilities::is_directory(this->path))
{
// Append dir for consistency on directory naming inclusion for with and without collision
std::filesystem::path with_dir = destination;
with_dir /= this->path.filename();
return with_dir;
}
return destination;
throw std::runtime_error("Failed to copy template");
}
struct file_operation_collision_mapping
{
int index;
SHNAMEMAPPING* mapping;
};
file_operation_collision_mapping* mapping = static_cast<file_operation_collision_mapping*>(file_operation_params.hNameMappings);
SHNAMEMAPPING* map = &mapping->mapping[0];
std::wstring final_path(map->pszNewPath);
SHFreeNameMappings(file_operation_params.hNameMappings);
return final_path;
return destination;
}
void template_item::refresh_target(const std::filesystem::path target_final_fullpath) const