diff --git a/src/cascadia/LocalTests_SettingsModel/ProfileTests.cpp b/src/cascadia/LocalTests_SettingsModel/ProfileTests.cpp index 27e8f190129..582a52c82c9 100644 --- a/src/cascadia/LocalTests_SettingsModel/ProfileTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ProfileTests.cpp @@ -36,6 +36,7 @@ namespace SettingsModelLocalTests TEST_METHOD(LayerProfileProperties); TEST_METHOD(LayerProfileIcon); TEST_METHOD(LayerProfilesOnArray); + TEST_METHOD(DuplicateProfileTest); TEST_CLASS_SETUP(ClassSetup) { @@ -307,4 +308,22 @@ namespace SettingsModelLocalTests VERIFY_ARE_EQUAL(L"profile4", settings->_allProfiles.GetAt(0).Name()); } + void ProfileTests::DuplicateProfileTest() + { + const std::string profile0String{ R"({ + "name" : "profile0", + "backgroundImage" : "some//path" + })" }; + + const auto profile0Json = VerifyParseSucceeded(profile0String); + + auto settings = winrt::make_self(); + + settings->_LayerOrCreateProfile(profile0Json); + auto duplicatedProfile = settings->DuplicateProfile(*settings->_FindMatchingProfile(profile0Json)); + duplicatedProfile.Name(L"profile0"); + + const auto duplicatedJson = winrt::get_self(duplicatedProfile)->ToJson(); + VERIFY_ARE_EQUAL(profile0Json, duplicatedJson); + } } diff --git a/src/cascadia/TerminalSettingsEditor/AddProfile.cpp b/src/cascadia/TerminalSettingsEditor/AddProfile.cpp new file mode 100644 index 00000000000..061a874ff07 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/AddProfile.cpp @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "AddProfile.h" +#include "AddProfile.g.cpp" +#include "AddProfilePageNavigationState.g.cpp" +#include "EnumEntry.h" + +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::System; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::UI::Xaml::Navigation; +using namespace winrt::Microsoft::Terminal::Settings::Model; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + AddProfile::AddProfile() + { + InitializeComponent(); + } + + void AddProfile::OnNavigatedTo(const NavigationEventArgs& e) + { + _State = e.Parameter().as(); + } + + void AddProfile::AddNewClick(const IInspectable& /*sender*/, + const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/) + { + _State.RequestAddNew(); + } + + void AddProfile::DuplicateClick(const IInspectable& /*sender*/, + const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/) + { + if (const auto selected = Profiles().SelectedItem()) + { + _State.RequestDuplicate(selected.try_as().Guid()); + } + } +} diff --git a/src/cascadia/TerminalSettingsEditor/AddProfile.h b/src/cascadia/TerminalSettingsEditor/AddProfile.h new file mode 100644 index 00000000000..39b78ffe981 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/AddProfile.h @@ -0,0 +1,63 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- AddProfile.h + +Abstract: +- This creates the 'add new profile' page in the settings UI and handles + user interaction with it, raising events to the main page as necessary + + +Author(s): +- Pankaj Bhojwani - March 2021 + +--*/ + +#pragma once + +#include "AddProfile.g.h" +#include "AddProfilePageNavigationState.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct AddProfilePageNavigationState : AddProfilePageNavigationStateT + { + public: + AddProfilePageNavigationState(const Model::CascadiaSettings& settings) : + _Settings{ settings } {} + + void RequestAddNew() + { + _AddNewHandlers(winrt::guid{}); + } + + void RequestDuplicate(GUID profile) + { + _AddNewHandlers(profile); + } + + WINRT_PROPERTY(Model::CascadiaSettings, Settings, nullptr) + WINRT_CALLBACK(AddNew, AddNewArgs); + }; + + struct AddProfile : AddProfileT + { + public: + AddProfile(); + + void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e); + + void AddNewClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); + void DuplicateClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); + + WINRT_PROPERTY(Editor::AddProfilePageNavigationState, State, nullptr); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(AddProfile); +} diff --git a/src/cascadia/TerminalSettingsEditor/AddProfile.idl b/src/cascadia/TerminalSettingsEditor/AddProfile.idl new file mode 100644 index 00000000000..82ee2a64e44 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/AddProfile.idl @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + delegate void AddNewArgs(Guid profile); + + runtimeclass AddProfilePageNavigationState + { + Microsoft.Terminal.Settings.Model.CascadiaSettings Settings; + void RequestAddNew(); + void RequestDuplicate(Guid profile); + event AddNewArgs AddNew; + }; + + [default_interface] runtimeclass AddProfile : Windows.UI.Xaml.Controls.Page + { + AddProfile(); + AddProfilePageNavigationState State { get; }; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/AddProfile.xaml b/src/cascadia/TerminalSettingsEditor/AddProfile.xaml new file mode 100644 index 00000000000..5cff69b877c --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/AddProfile.xaml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.cpp b/src/cascadia/TerminalSettingsEditor/MainPage.cpp index 99f692fcff7..80017380915 100644 --- a/src/cascadia/TerminalSettingsEditor/MainPage.cpp +++ b/src/cascadia/TerminalSettingsEditor/MainPage.cpp @@ -11,6 +11,7 @@ #include "Profiles.h" #include "GlobalAppearance.h" #include "ColorSchemes.h" +#include "AddProfile.h" #include "..\types\inc\utils.hpp" #include @@ -122,8 +123,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // refresh the current page using the SelectedItem data we collected before the refresh if (selectedItemTag) { - const auto& selectedItemStringTag{ selectedItemTag.try_as() }; - const auto& selectedItemProfileTag{ selectedItemTag.try_as() }; for (const auto& item : menuItems) { if (const auto& menuItem{ item.try_as() }) @@ -132,22 +131,28 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { if (const auto& stringTag{ tag.try_as() }) { - if (stringTag == selectedItemStringTag) + if (const auto& selectedItemStringTag{ selectedItemTag.try_as() }) { - // found the one that was selected before the refresh - SettingsNav().SelectedItem(item); - _Navigate(*stringTag); - co_return; + if (stringTag == selectedItemStringTag) + { + // found the one that was selected before the refresh + SettingsNav().SelectedItem(item); + _Navigate(*stringTag); + co_return; + } } } else if (const auto& profileTag{ tag.try_as() }) { - if (profileTag->Guid() == selectedItemProfileTag->Guid()) + if (const auto& selectedItemProfileTag{ selectedItemTag.try_as() }) { - // found the one that was selected before the refresh - SettingsNav().SelectedItem(item); - _Navigate(*profileTag); - co_return; + if (profileTag->Guid() == selectedItemProfileTag->Guid()) + { + // found the one that was selected before the refresh + SettingsNav().SelectedItem(item); + _Navigate(*profileTag); + co_return; + } } } } @@ -182,6 +187,34 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return false; } + // Method Description: + // - Creates a new profile and navigates to it in the Settings UI + // Arguments: + // - profileGuid: the guid of the profile we want to duplicate, + // can be empty to indicate that we should create a fresh profile + void MainPage::_AddProfileHandler(winrt::guid profileGuid) + { + uint32_t insertIndex; + auto selectedItem{ SettingsNav().SelectedItem() }; + auto menuItems{ SettingsNav().MenuItems() }; + menuItems.IndexOf(selectedItem, insertIndex); + if (profileGuid != winrt::guid{}) + { + // if we were given a non-empty guid, we want to duplicate the corresponding profile + const auto profile = _settingsClone.FindProfile(profileGuid); + if (profile) + { + const auto duplicated = _settingsClone.DuplicateProfile(profile); + _CreateAndNavigateToNewProfile(insertIndex, duplicated); + } + } + else + { + // we were given an empty guid, create a new profile + _CreateAndNavigateToNewProfile(insertIndex, nullptr); + } + } + uint64_t MainPage::GetHostingWindow() const noexcept { return reinterpret_cast(_hostingHwnd.value_or(nullptr)); @@ -227,18 +260,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation if (const auto navString = clickedItemContainer.Tag().try_as()) { - if (navString == addProfileTag) - { - // "AddProfile" needs to create a new profile before we can navigate to it - uint32_t insertIndex; - SettingsNav().MenuItems().IndexOf(clickedItemContainer, insertIndex); - _CreateAndNavigateToNewProfile(insertIndex); - } - else - { - // Otherwise, navigate to the page - _Navigate(*navString); - } + _Navigate(*navString); } else if (const auto profile = clickedItemContainer.Tag().try_as()) { @@ -281,6 +303,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone.GlobalSettings())); } + else if (clickedItemTag == addProfileTag) + { + auto addProfileState{ winrt::make(_settingsClone) }; + addProfileState.AddNew({ get_weak(), &MainPage::_AddProfileHandler }); + contentFrame().Navigate(xaml_typename(), addProfileState); + } } // Method Description: @@ -348,7 +376,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation MUX::Controls::NavigationViewItem addProfileItem; addProfileItem.Content(box_value(RS_(L"Nav_AddNewProfile/Content"))); addProfileItem.Tag(box_value(addProfileTag)); - addProfileItem.SelectsOnInvoked(false); FontIcon icon; // This is the "Add" symbol @@ -358,9 +385,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation SettingsNav().MenuItems().Append(addProfileItem); } - void MainPage::_CreateAndNavigateToNewProfile(const uint32_t index) + void MainPage::_CreateAndNavigateToNewProfile(const uint32_t index, const Model::Profile& profile) { - const auto newProfile{ _settingsClone.CreateNewProfile() }; + const auto newProfile{ profile ? profile : _settingsClone.CreateNewProfile() }; const auto profileViewModel{ _viewModelForProfile(newProfile) }; const auto navItem{ _CreateProfileNavViewItem(profileViewModel) }; SettingsNav().MenuItems().InsertAt(index, navItem); diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.h b/src/cascadia/TerminalSettingsEditor/MainPage.h index 544f57b4d3e..6b20721c4c5 100644 --- a/src/cascadia/TerminalSettingsEditor/MainPage.h +++ b/src/cascadia/TerminalSettingsEditor/MainPage.h @@ -35,9 +35,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation std::optional _hostingHwnd; void _InitializeProfilesList(); - void _CreateAndNavigateToNewProfile(const uint32_t index); + void _CreateAndNavigateToNewProfile(const uint32_t index, const Model::Profile& profile); winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem _CreateProfileNavViewItem(const Editor::ProfileViewModel& profile); void _DeleteProfile(const Windows::Foundation::IInspectable sender, const Editor::DeleteProfileEventArgs& args); + void _AddProfileHandler(const winrt::guid profileGuid); void _Navigate(hstring clickedItemTag); void _Navigate(const Editor::ProfileViewModel& profile); diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj index b83ddad621c..1408f2a2977 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj @@ -38,6 +38,9 @@ Actions.xaml + + AddProfile.xaml + Converters.idl @@ -105,6 +108,9 @@ Designer + + Designer + Designer @@ -138,6 +144,9 @@ Actions.xaml + + AddProfile.xaml + Converters.idl @@ -206,6 +215,10 @@ Actions.xaml Code + + AddProfile.xaml + Code + diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index f48db5fce6e..28fd54e3e7f 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -117,6 +117,24 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Create New Button + + + New empty profile + Button label that creates a new profile with default settings. + + + Duplicate a profile + This is the header for a control that lets the user duplicate one of their existing profiles. + + + Duplicate Button + + + Duplicate + Button label that duplicates the selected profile and navigates to the duplicate's page. + Background This is the header for a control that lets the user select the background color for text displayed on the screen. @@ -790,8 +808,8 @@ {Locked="⚠"} A disclaimer that appears when the unsaved changes to the settings are present. - Add new - Header for the "add new" menu item. This creates a new profile and navigates to that page. + Add a new profile + Header for the "add new" menu item. This navigates to the page where users can add a new profile. Profiles diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index 142678a7ba1..0913a37f66c 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -249,6 +249,137 @@ winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::CreateNew return *newProfile; } +// Method Description: +// - Duplicate a new profile based off another profile's settings +// - This differs from Profile::Copy because it also copies over settings +// that were not defined in the json (for example, settings that were +// defined in one of the parents) +// - This will not duplicate settings that were defined in profiles.defaults +// however, because we do not want the json blob generated from the new profile +// to contain those settings +// Arguments: +// - source: the Profile object we are duplicating (must not be null) +// Return Value: +// - a reference to the new profile +winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::DuplicateProfile(Model::Profile source) +{ + THROW_HR_IF_NULL(E_INVALIDARG, source); + + winrt::com_ptr duplicated; + if (_userDefaultProfileSettings) + { + duplicated = _userDefaultProfileSettings->CreateChild(); + } + else + { + duplicated = winrt::make_self(); + } + _allProfiles.Append(*duplicated); + + if (!source.Hidden()) + { + _activeProfiles.Append(*duplicated); + } + + winrt::hstring newName{ fmt::format(L"{} ({})", source.Name(), RS_(L"CopySuffix")) }; + + // Check if this name already exists and if so, append a number + for (uint32_t candidateIndex = 0; candidateIndex < _allProfiles.Size() + 1; ++candidateIndex) + { + if (std::none_of(begin(_allProfiles), end(_allProfiles), [&](auto&& profile) { return profile.Name() == newName; })) + { + break; + } + // There is a theoretical unsigned integer wraparound, which is OK + newName = fmt::format(L"{} ({} {})", source.Name(), RS_(L"CopySuffix"), candidateIndex + 2); + } + duplicated->Name(winrt::hstring(newName)); + +#define DUPLICATE_SETTING_MACRO(settingName) \ + if (source.Has##settingName() || \ + (source.##settingName##OverrideSource() != nullptr && source.##settingName##OverrideSource().Origin() != OriginTag::ProfilesDefaults)) \ + { \ + duplicated->##settingName(source.##settingName()); \ + } + +#define DUPLICATE_APPEARANCE_SETTING_MACRO(settingName) \ + if (source.DefaultAppearance().Has##settingName() || \ + (source.DefaultAppearance().##settingName##OverrideSource() != nullptr && source.DefaultAppearance().##settingName##OverrideSource().SourceProfile().Origin() != OriginTag::ProfilesDefaults)) \ + { \ + duplicated->DefaultAppearance().##settingName(source.DefaultAppearance().##settingName()); \ + } + + DUPLICATE_SETTING_MACRO(Hidden); + DUPLICATE_SETTING_MACRO(Icon); + DUPLICATE_SETTING_MACRO(CloseOnExit); + DUPLICATE_SETTING_MACRO(TabTitle); + DUPLICATE_SETTING_MACRO(TabColor); + DUPLICATE_SETTING_MACRO(SuppressApplicationTitle); + DUPLICATE_SETTING_MACRO(UseAcrylic); + DUPLICATE_SETTING_MACRO(AcrylicOpacity); + DUPLICATE_SETTING_MACRO(ScrollState); + DUPLICATE_SETTING_MACRO(FontFace); + DUPLICATE_SETTING_MACRO(FontSize); + DUPLICATE_SETTING_MACRO(FontWeight); + DUPLICATE_SETTING_MACRO(Padding); + DUPLICATE_SETTING_MACRO(Commandline); + DUPLICATE_SETTING_MACRO(StartingDirectory); + DUPLICATE_SETTING_MACRO(AntialiasingMode); + DUPLICATE_SETTING_MACRO(ForceFullRepaintRendering); + DUPLICATE_SETTING_MACRO(SoftwareRendering); + DUPLICATE_SETTING_MACRO(HistorySize); + DUPLICATE_SETTING_MACRO(SnapOnInput); + DUPLICATE_SETTING_MACRO(AltGrAliasing); + DUPLICATE_SETTING_MACRO(BellStyle); + + DUPLICATE_APPEARANCE_SETTING_MACRO(ColorSchemeName); + DUPLICATE_APPEARANCE_SETTING_MACRO(Foreground); + DUPLICATE_APPEARANCE_SETTING_MACRO(Background); + DUPLICATE_APPEARANCE_SETTING_MACRO(SelectionBackground); + DUPLICATE_APPEARANCE_SETTING_MACRO(CursorColor); + DUPLICATE_APPEARANCE_SETTING_MACRO(PixelShaderPath); + DUPLICATE_APPEARANCE_SETTING_MACRO(BackgroundImagePath); + DUPLICATE_APPEARANCE_SETTING_MACRO(BackgroundImageOpacity); + DUPLICATE_APPEARANCE_SETTING_MACRO(BackgroundImageStretchMode); + DUPLICATE_APPEARANCE_SETTING_MACRO(BackgroundImageAlignment); + DUPLICATE_APPEARANCE_SETTING_MACRO(RetroTerminalEffect); + DUPLICATE_APPEARANCE_SETTING_MACRO(CursorShape); + DUPLICATE_APPEARANCE_SETTING_MACRO(CursorHeight); + + // UnfocusedAppearance is treated as a single setting, + // but requires a little more legwork to duplicate properly + if (source.HasUnfocusedAppearance() || + (source.UnfocusedAppearanceOverrideSource() != nullptr && source.UnfocusedAppearanceOverrideSource().Origin() != OriginTag::ProfilesDefaults)) + { + // First, get a com_ptr to the source's unfocused appearance + // We need this to be able to call CopyAppearance (it is alright to simply call CopyAppearance here + // instead of needing a separate function like DuplicateAppearance since UnfocusedAppearance is treated + // as a single setting) + winrt::com_ptr sourceUnfocusedAppearanceImpl; + sourceUnfocusedAppearanceImpl.copy_from(winrt::get_self(source.UnfocusedAppearance())); + + // Get a weak ref to the duplicate profile so we can provide a source profile to the new UnfocusedAppearance + // we are about to create + const auto weakRefToDuplicated = weak_ref(*duplicated); + auto duplicatedUnfocusedAppearanceImpl = AppearanceConfig::CopyAppearance(sourceUnfocusedAppearanceImpl, weakRefToDuplicated); + + // Make sure to add the default appearance of the duplicated profile as a parent to the duplicate's UnfocusedAppearance + winrt::com_ptr duplicatedDefaultAppearanceImpl; + duplicatedDefaultAppearanceImpl.copy_from(winrt::get_self(duplicated->DefaultAppearance())); + duplicatedUnfocusedAppearanceImpl->InsertParent(duplicatedDefaultAppearanceImpl); + + // Finally, set the duplicate's UnfocusedAppearance + duplicated->UnfocusedAppearance(*duplicatedUnfocusedAppearanceImpl); + } + + if (source.HasConnectionType()) + { + duplicated->ConnectionType(source.ConnectionType()); + } + + return *duplicated; +} + // Method Description: // - Gets our list of warnings we found during loading. These are things that we // knew were bad when we called `_ValidateSettings` last. diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h index e2d88e9b04b..d63d39d458c 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h @@ -98,6 +98,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::guid GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const; + Model::Profile DuplicateProfile(Model::Profile source); void RefreshDefaultTerminals(); static bool IsDefaultTerminalAvailable() noexcept; diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl index 6f50235413a..0428a98be4b 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl @@ -31,6 +31,8 @@ namespace Microsoft.Terminal.Settings.Model Windows.Foundation.Collections.IObservableVector AllProfiles { get; }; Windows.Foundation.Collections.IObservableVector ActiveProfiles { get; }; + Profile DuplicateProfile(Profile sourceProfile); + KeyMapping KeyMap { get; }; Windows.Foundation.Collections.IVectorView Warnings { get; }; diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp index c96b78005b7..016b6bb3b37 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp @@ -1033,6 +1033,7 @@ void CascadiaSettings::_ApplyDefaultsFromUserSettings() _userDefaultProfileSettings = winrt::make_self(); _userDefaultProfileSettings->LayerJson(defaultSettings); + _userDefaultProfileSettings->Origin(OriginTag::ProfilesDefaults); const auto numOfProfiles{ _allProfiles.Size() }; for (uint32_t profileIndex = 0; profileIndex < numOfProfiles; ++profileIndex) diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index 9ea28ba1841..ed5903703d5 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -16,7 +16,8 @@ namespace Microsoft.Terminal.Settings.Model Custom = 0, InBox, Generated, - Fragment + Fragment, + ProfilesDefaults }; enum CloseOnExitMode diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index 8f8aece2a2f..7dbf81e936b 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -154,6 +154,10 @@ Close tabs after index {0} {0} will be replaced with a number + + Copy + The suffix we add to the name of a duplicated profile. + Move tab {0} {0} will be replaced with a "forward" / "backward"