Files
UnrealEngineUWP/Engine/Source/Developer/DesktopWidgets/Private/Widgets/Input/SFilePathPicker.cpp
Alejandro Arango 384b7bed75 ImgMedia and FilePathPicker: Added option for the file picker to return an absolute path when the path comes from the system dialog.
This eliminates the ambiguity when the path is returned is relative, since for the image sequence path we support paths to be specified relative to the project (typed by the user) while the dialog returned paths relative to the process, but the callback for the textfield and the dialog are the same at the file picker layer. The issue ultimately happens because when ".." hits the root folder, it behaves as a no-op. So multiple relative paths can point to the same file for the same given starting directory.

The flag added to SFilePathPicker defaults to the previous behavior (which is to return paths relative to the process).

#rb trivial
#jira UE-157535
#preflight 62b611d40716a4b4d12854b0

[CL 20815496 by Alejandro Arango in ue5-main branch]
2022-06-24 15:39:56 -04:00

122 lines
3.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Widgets/Input/SFilePathPicker.h"
#include "DesktopPlatformModule.h"
#include "Widgets/SBoxPanel.h"
#include "Framework/Application/SlateApplication.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/Input/SButton.h"
#define LOCTEXT_NAMESPACE "SFilePathPicker"
/* SFilePathPicker interface
*****************************************************************************/
void SFilePathPicker::Construct( const FArguments& InArgs )
{
BrowseDirectory = InArgs._BrowseDirectory;
BrowseTitle = InArgs._BrowseTitle;
FilePath = InArgs._FilePath;
FileTypeFilter = InArgs._FileTypeFilter;
OnPathPicked = InArgs._OnPathPicked;
DialogReturnsFullPath = InArgs._DialogReturnsFullPath;
ChildSlot
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.VAlign(VAlign_Center)
[
// file path text box
SAssignNew(TextBox, SEditableTextBox)
.Text(this, &SFilePathPicker::HandleTextBoxText)
.Font(InArgs._Font)
.SelectAllTextWhenFocused(true)
.ClearKeyboardFocusOnCommit(false)
.OnTextCommitted(this, &SFilePathPicker::HandleTextBoxTextCommitted)
.SelectAllTextOnCommit(false)
.IsReadOnly(InArgs._IsReadOnly)
]
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(4.0f, 0.0f, 0.0f, 0.0f)
.VAlign(VAlign_Center)
[
// browse button
SNew(SButton)
.ButtonStyle(InArgs._BrowseButtonStyle)
.ToolTipText(InArgs._BrowseButtonToolTip)
.OnClicked(this, &SFilePathPicker::HandleBrowseButtonClicked)
.ContentPadding(2.0f)
.ForegroundColor(FSlateColor::UseForeground())
.IsFocusable(false)
[
SNew(SImage)
.Image(InArgs._BrowseButtonImage)
.ColorAndOpacity(FSlateColor::UseForeground())
]
]
];
}
/* SFilePathPicker callbacks
*****************************************************************************/
FReply SFilePathPicker::HandleBrowseButtonClicked()
{
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
if (DesktopPlatform == nullptr)
{
return FReply::Handled();
}
const FString DefaultPath = BrowseDirectory.IsSet()
? BrowseDirectory.Get()
: FPaths::GetPath(FilePath.Get());
// show the file browse dialog
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().FindWidgetWindow(AsShared());
void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid())
? ParentWindow->GetNativeWindow()->GetOSWindowHandle()
: nullptr;
TArray<FString> OutFiles;
if (DesktopPlatform->OpenFileDialog(ParentWindowHandle, BrowseTitle.Get().ToString(), DefaultPath, TEXT(""), FileTypeFilter.Get(), EFileDialogFlags::None, OutFiles))
{
if (DialogReturnsFullPath.Get())
{
OnPathPicked.ExecuteIfBound(FPaths::ConvertRelativePathToFull(OutFiles[0]));
}
else
{
OnPathPicked.ExecuteIfBound(OutFiles[0]);
}
}
return FReply::Handled();
}
FText SFilePathPicker::HandleTextBoxText() const
{
return FText::FromString(FilePath.Get());
}
void SFilePathPicker::HandleTextBoxTextCommitted( const FText& NewText, ETextCommit::Type CommitInfo )
{
OnPathPicked.ExecuteIfBound(NewText.ToString());
}
#undef LOCTEXT_NAMESPACE