1078 lines
36 KiB
C++
1078 lines
36 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SSourceControlChangelistRows.h"
|
|
|
|
#include "ComponentReregisterContext.h"
|
|
#include "FileHelpers.h"
|
|
#include "ISourceControlModule.h"
|
|
#include "PackageTools.h"
|
|
#include "PackageSourceControlHelper.h"
|
|
#include "SourceControlHelpers.h"
|
|
#include "UncontrolledChangelistsModule.h"
|
|
#include "SourceControlOperations.h"
|
|
#include "UnsavedAssetsTrackerModule.h"
|
|
#include "Styling/AppStyle.h"
|
|
#include "Widgets/Images/SImage.h"
|
|
#include "Widgets/Input/SButton.h"
|
|
#include "Widgets/Text/STextBlock.h"
|
|
#include "Algo/Transform.h"
|
|
#include "Containers/Ticker.h"
|
|
#include "RevisionControlStyle/RevisionControlStyle.h"
|
|
#include "Styling/SlateStyleRegistry.h"
|
|
#include "Styling/StarshipCoreStyle.h"
|
|
#include "Misc/ComparisonUtility.h"
|
|
#include "Misc/MessageDialog.h"
|
|
#include "Widgets/Images/SThrobber.h"
|
|
#include "Widgets/Layout/SWidgetSwitcher.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "SourceControlChangelistRow"
|
|
|
|
namespace
|
|
{
|
|
bool CheckoutAndSavePackages(const TArray<FString>& Files)
|
|
{
|
|
FPackageSourceControlHelper PackageHelper;
|
|
TArray<FString> PackageNames;
|
|
PackageNames.Reserve(Files.Num());
|
|
for (const FString& Filename : Files)
|
|
{
|
|
PackageNames.Add(UPackageTools::FilenameToPackageName(Filename));
|
|
}
|
|
|
|
if (PackageHelper.Checkout(PackageNames))
|
|
{
|
|
TArray<UPackage*> Packages;
|
|
Packages.Reserve(PackageNames.Num());
|
|
{
|
|
for (const FString& PackageName : PackageNames)
|
|
{
|
|
UPackage* Package = FindPackage(nullptr, *PackageName);
|
|
if (ensure(Package))
|
|
{
|
|
Packages.Add(Package);
|
|
}
|
|
else
|
|
{
|
|
Packages.Add(UPackageTools::LoadPackage(PackageName));
|
|
}
|
|
}
|
|
}
|
|
constexpr bool bOnlyDirty = false;
|
|
return UEditorLoadingAndSavingUtils::SavePackages(Packages, bOnlyDirty);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
FName SourceControlFileViewColumn::CheckBox::Id() { return TEXT("CheckBox"); }
|
|
|
|
FName SourceControlFileViewColumn::Icon::Id() { return TEXT("Icon"); }
|
|
FText SourceControlFileViewColumn::Icon::GetDisplayText() {return LOCTEXT("Name_Icon", "Revision Control Status"); }
|
|
FText SourceControlFileViewColumn::Icon::GetToolTipText() { return LOCTEXT("Icon_Column_Tooltip", "Displays the asset/file status"); }
|
|
|
|
FName SourceControlFileViewColumn::Shelve::Id() { return TEXT("Shelve"); }
|
|
FText SourceControlFileViewColumn::Shelve::GetDisplayText() { return LOCTEXT("Name_Shelve", "Revision Control Shelve"); }
|
|
FText SourceControlFileViewColumn::Shelve::GetToolTipText() { return LOCTEXT("Shelve_Column_Tooltip", "Displays the shelve status"); }
|
|
|
|
FName SourceControlFileViewColumn::Name::Id() { return TEXT("Name"); }
|
|
FText SourceControlFileViewColumn::Name::GetDisplayText() { return LOCTEXT("Name_Column", "Name"); }
|
|
FText SourceControlFileViewColumn::Name::GetToolTipText() { return LOCTEXT("Name_Column_Tooltip", "Displays the asset/file name"); }
|
|
|
|
FName SourceControlFileViewColumn::Path::Id() { return TEXT("Path"); }
|
|
FText SourceControlFileViewColumn::Path::GetDisplayText() { return LOCTEXT("Path_Column", "Path"); }
|
|
FText SourceControlFileViewColumn::Path::GetToolTipText() { return LOCTEXT("Path_Column_Tooltip", "Displays the asset/file path"); }
|
|
|
|
FName SourceControlFileViewColumn::Type::Id() { return TEXT("Type"); }
|
|
FText SourceControlFileViewColumn::Type::GetDisplayText() { return LOCTEXT("Type_Column", "Type"); }
|
|
FText SourceControlFileViewColumn::Type::GetToolTipText() { return LOCTEXT("Type_Column_Tooltip", "Displays the asset type"); }
|
|
|
|
FName SourceControlFileViewColumn::LastModifiedTimestamp::Id() { return TEXT("LastModifiedTimestamp"); }
|
|
FText SourceControlFileViewColumn::LastModifiedTimestamp::GetDisplayText() {return LOCTEXT("LastModifiedTimestamp_Column", "Last Saved"); }
|
|
FText SourceControlFileViewColumn::LastModifiedTimestamp::GetToolTipText() { return LOCTEXT("LastMofiedTimestamp_Column_Tooltip", "Displays the last time the file/asset was saved on user hard drive"); }
|
|
|
|
FName SourceControlFileViewColumn::CheckedOutByUser::Id() { return TEXT("CheckedOutByUser"); }
|
|
FText SourceControlFileViewColumn::CheckedOutByUser::GetDisplayText() { return LOCTEXT("CheckedOutByUser_Column", "User"); }
|
|
FText SourceControlFileViewColumn::CheckedOutByUser::GetToolTipText() { return LOCTEXT("CheckedOutByUser_Column_Tooltip", "Displays the other user(s) that checked out the file/asset, if any"); }
|
|
|
|
FName SourceControlFileViewColumn::Changelist::Id() { return TEXT("Changelist"); }
|
|
FText SourceControlFileViewColumn::Changelist::GetDisplayText() { return LOCTEXT("Changelist_Column", "Changelist"); }
|
|
FText SourceControlFileViewColumn::Changelist::GetToolTipText() { return LOCTEXT("Changelist_Column_Tooltip", "Displays the changelist the asset/file belongs to, if any"); }
|
|
|
|
FName SourceControlFileViewColumn::Dirty::Id() { return TEXT("Dirty"); }
|
|
FText SourceControlFileViewColumn::Dirty::GetDisplayText() { return LOCTEXT("Dirty_Column", "Unsaved"); }
|
|
FText SourceControlFileViewColumn::Dirty::GetToolTipText() { return LOCTEXT("Dirty_Column_Tooltip", "Displays whether the asset/file has unsaved changes"); }
|
|
|
|
FName SourceControlFileViewColumn::Discard::Id() { return TEXT("Discard"); }
|
|
FText SourceControlFileViewColumn::Discard::GetDisplayText() { return LOCTEXT("Discard_Column", "Discard Unsaved Changes"); }
|
|
FText SourceControlFileViewColumn::Discard::GetToolTipText() { return LOCTEXT("Discard_Column_Tooltip", "Provides option to discard unsaved changes to an asset/file"); }
|
|
|
|
namespace SourceControlFileViewColumn
|
|
{
|
|
TFunction<int32(const IFileViewTreeItem&, const IFileViewTreeItem&)> GetColumnComparer(FName ColumnId, EPathFlags PathFlags)
|
|
{
|
|
if (ColumnId == SourceControlFileViewColumn::CheckBox::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
ECheckBoxState LhsVal = Lhs.GetCheckBoxState();
|
|
ECheckBoxState RhsVal = Rhs.GetCheckBoxState();
|
|
return LhsVal < RhsVal ? -1 : (LhsVal == RhsVal ? 0 : 1);
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Icon::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
int32 LhsVal = Lhs.GetIconSortingPriority();
|
|
int32 RhsVal = Rhs.GetIconSortingPriority();
|
|
return LhsVal < RhsVal ? -1 : (LhsVal == RhsVal ? 0 : 1);
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Shelve::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
const IChangelistTreeItem::TreeItemType LhsTreeItemType = Lhs.GetTreeItemType();
|
|
const IChangelistTreeItem::TreeItemType RhsTreeItemType = Rhs.GetTreeItemType();
|
|
|
|
return LhsTreeItemType < RhsTreeItemType ? -1 : (LhsTreeItemType == RhsTreeItemType ? 0 : 1);
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Name::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
return UE::ComparisonUtility::CompareNaturalOrder(*Lhs.GetName(), *Rhs.GetName());
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Path::Id())
|
|
{
|
|
if (PathFlags == EPathFlags::ShowingPackageName)
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
return Lhs.GetPackageName().Compare(Rhs.GetPackageName());
|
|
};
|
|
}
|
|
else if (PathFlags == EPathFlags::ShowingVersePath)
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
if (Lhs.GetVersePath().IsValid() && Rhs.GetVersePath().IsValid())
|
|
{
|
|
return Lhs.GetVersePath().Compare(Rhs.GetVersePath());
|
|
}
|
|
else if (Lhs.GetVersePath().IsValid())
|
|
{
|
|
return Lhs.GetVersePath().ToString().Compare(Rhs.GetPath());
|
|
}
|
|
else if (Rhs.GetVersePath().IsValid())
|
|
{
|
|
return Lhs.GetPath().Compare(Rhs.GetVersePath().ToString());
|
|
}
|
|
return Lhs.GetPath().Compare(Rhs.GetPath());
|
|
};
|
|
}
|
|
else if (PathFlags == (EPathFlags::ShowingPackageName | EPathFlags::ShowingVersePath))
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
if (Lhs.GetVersePath().IsValid() && Rhs.GetVersePath().IsValid())
|
|
{
|
|
return Lhs.GetVersePath().Compare(Rhs.GetVersePath());
|
|
}
|
|
else if (Lhs.GetVersePath().IsValid())
|
|
{
|
|
return Lhs.GetVersePath().ToString().Compare(Rhs.GetPackageName());
|
|
}
|
|
else if (Rhs.GetVersePath().IsValid())
|
|
{
|
|
return Lhs.GetPackageName().Compare(Rhs.GetVersePath().ToString());
|
|
}
|
|
return Lhs.GetPackageName().Compare(Rhs.GetPackageName());
|
|
};
|
|
}
|
|
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
return Lhs.GetPath().Compare(Rhs.GetPath());
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Type::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
return FCString::Stricmp(*Lhs.GetType(), *Rhs.GetType());
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::LastModifiedTimestamp::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
const FDateTime& LhsVal = Lhs.GetLastModifiedDateTime();
|
|
const FDateTime& RhsVal = Rhs.GetLastModifiedDateTime();
|
|
return LhsVal < RhsVal ? -1 : (LhsVal == RhsVal ? 0 : 1);
|
|
};
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::CheckedOutByUser::Id())
|
|
{
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
return FCString::Stricmp(*Lhs.GetCheckedOutBy(), *Rhs.GetCheckedOutBy());
|
|
};
|
|
}
|
|
else
|
|
{
|
|
checkNoEntry();
|
|
return [](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
return &Lhs < &Rhs ? -1 : (&Lhs == &Rhs ? 0 : 1);
|
|
};
|
|
};
|
|
}
|
|
|
|
TFunction<bool(const IFileViewTreeItem&, const IFileViewTreeItem&)> GetSortPredicate(EColumnSortMode::Type SortMode, FName ColumnId, EPathFlags PathFlags)
|
|
{
|
|
int32 Sign;
|
|
if (SortMode == EColumnSortMode::Ascending)
|
|
{
|
|
Sign = 1;
|
|
}
|
|
else if (SortMode == EColumnSortMode::Descending)
|
|
{
|
|
Sign = -1;
|
|
}
|
|
else
|
|
{
|
|
return {};
|
|
}
|
|
|
|
TArray<TFunction<int32(const IFileViewTreeItem&, const IFileViewTreeItem&)>> ColumnComparers;
|
|
ColumnComparers.Reserve(3);
|
|
|
|
ColumnComparers.Add(GetColumnComparer(ColumnId, PathFlags));
|
|
|
|
if (ColumnId != Path::Id())
|
|
{
|
|
// Use name and path as tie breakers.
|
|
if (ColumnId != Name::Id())
|
|
{
|
|
ColumnComparers.Add(GetColumnComparer(Name::Id(), PathFlags));
|
|
}
|
|
ColumnComparers.Add(GetColumnComparer(Path::Id(), PathFlags));
|
|
}
|
|
|
|
return [Sign, ColumnComparers = MoveTemp(ColumnComparers)](const IFileViewTreeItem& Lhs, const IFileViewTreeItem& Rhs)
|
|
{
|
|
for (const TFunction<int32(const IFileViewTreeItem&, const IFileViewTreeItem&)>& ColumnComparer : ColumnComparers)
|
|
{
|
|
const int32 Result = ColumnComparer(Lhs, Rhs);
|
|
if (Result != 0)
|
|
{
|
|
return Sign * Result < 0;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
}
|
|
|
|
FText FormatChangelistFileCountText(int32 DisplayedCount, int32 TotalCount)
|
|
{
|
|
return DisplayedCount == TotalCount ?
|
|
FText::Format(INVTEXT("({0})"), TotalCount) :
|
|
FText::Format(LOCTEXT("FilterNum", "({0} out of {1})"), DisplayedCount, TotalCount);
|
|
}
|
|
|
|
void SChangelistTableRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwner)
|
|
{
|
|
TreeItem = static_cast<FChangelistTreeItem*>(InArgs._TreeItemToVisualize.Get());
|
|
OnPostDrop = InArgs._OnPostDrop;
|
|
|
|
SetToolTipText(GetChangelistDescriptionText());
|
|
|
|
STableRow<FChangelistTreeItemPtr>::Construct(
|
|
STableRow<FChangelistTreeItemPtr>::FArguments()
|
|
.Style(FAppStyle::Get(), "TableView.Row")
|
|
.Content()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot() // Icon
|
|
.AutoWidth()
|
|
[
|
|
SNew(SImage)
|
|
.Image_Lambda([this]()
|
|
{
|
|
return (TreeItem != nullptr) ?FAppStyle::GetBrush(TreeItem->ChangelistState->GetSmallIconName()) : FAppStyle::GetBrush("SourceControl.Changelist");
|
|
})
|
|
]
|
|
+SHorizontalBox::Slot() // Changelist number.
|
|
.Padding(2, 0, 0, 0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(this, &SChangelistTableRow::GetChangelistText)
|
|
.HighlightText(InArgs._HighlightText)
|
|
]
|
|
+SHorizontalBox::Slot() // Files count.
|
|
.Padding(4, 0, 4, 0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda([this]()
|
|
{
|
|
// Check if the 'Shelved Files' node is currently linked to the tree view. (not filtered out).
|
|
return FormatChangelistFileCountText(TreeItem->ShelvedChangelistItem->GetParent() ? TreeItem->GetChildren().Num() - 1 : TreeItem->GetChildren().Num(), TreeItem->GetFileCount());
|
|
})
|
|
]
|
|
+SHorizontalBox::Slot() // Description.
|
|
.Padding(2, 0, 0, 0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(this, &SChangelistTableRow::GetChangelistDescriptionSingleLineText)
|
|
.HighlightText(InArgs._HighlightText)
|
|
]
|
|
], InOwner);
|
|
}
|
|
|
|
void SChangelistTableRow::PopulateSearchString(const FChangelistTreeItem& Item, TArray<FString>& OutStrings)
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayText().ToString()); // The changelist number
|
|
OutStrings.Emplace(Item.GetDescriptionText().ToString()); // The changelist description.
|
|
}
|
|
|
|
FText SChangelistTableRow::GetChangelistText() const
|
|
{
|
|
return TreeItem->GetDisplayText();
|
|
}
|
|
|
|
FText SChangelistTableRow::GetChangelistDescriptionText() const
|
|
{
|
|
return TreeItem->GetDescriptionText();
|
|
}
|
|
|
|
FText SChangelistTableRow::GetChangelistDescriptionSingleLineText() const
|
|
{
|
|
using namespace SSourceControlCommon;
|
|
return GetSingleLineChangelistDescription(TreeItem->GetDescriptionText(), ESingleLineFlags::NewlineConvertToSpace);
|
|
}
|
|
|
|
FReply SChangelistTableRow::OnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent)
|
|
{
|
|
TSharedPtr<FSCCFileDragDropOp> DropOperation = InDragDropEvent.GetOperationAs<FSCCFileDragDropOp>();
|
|
if (DropOperation.IsValid())
|
|
{
|
|
FSourceControlChangelistPtr DestChangelist = TreeItem->ChangelistState->GetChangelist();
|
|
check(DestChangelist.IsValid());
|
|
|
|
// NOTE: The UI don't show 'source controlled files' and 'uncontrolled files' at the same time. User cannot select and drag/drop both file types at the same time.
|
|
if (!DropOperation->Files.IsEmpty())
|
|
{
|
|
TArray<FString> Files;
|
|
Algo::Transform(DropOperation->Files, Files, [](const FSourceControlStateRef& State) { return State->GetFilename(); });
|
|
|
|
SSourceControlCommon::ExecuteChangelistOperationWithSlowTaskWrapper(LOCTEXT("Dropping_Files_On_Changelist", "Moving file(s) to the selected changelist..."), [&]()
|
|
{
|
|
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
|
|
SourceControlProvider.Execute(ISourceControlOperation::Create<FMoveToChangelist>(), DestChangelist, Files, EConcurrency::Synchronous, FSourceControlOperationComplete::CreateLambda(
|
|
[](const TSharedRef<ISourceControlOperation>& Operation, ECommandResult::Type InResult)
|
|
{
|
|
if (InResult == ECommandResult::Succeeded)
|
|
{
|
|
SSourceControlCommon::DisplaySourceControlOperationNotification(LOCTEXT("Drop_Files_On_Changelist_Succeeded", "File(s) successfully moved to the selected changelist."), SNotificationItem::CS_Success);
|
|
}
|
|
else if (InResult == ECommandResult::Failed)
|
|
{
|
|
SSourceControlCommon::DisplaySourceControlOperationNotification(LOCTEXT("Drop_Files_On_Changelist_Failed", "Failed to move the file(s) to the selected changelist."), SNotificationItem::CS_Fail);
|
|
}
|
|
}));
|
|
});
|
|
}
|
|
else if (!DropOperation->UncontrolledFiles.IsEmpty())
|
|
{
|
|
// NOTE: This function does several operations that can fails but we don't get feedback.
|
|
SSourceControlCommon::ExecuteUncontrolledChangelistOperationWithSlowTaskWrapper(LOCTEXT("Dropping_Uncontrolled_Files_On_Changelist", "Moving uncontrolled file(s) to the selected changelist..."),
|
|
[&DropOperation, &DestChangelist]()
|
|
{
|
|
FUncontrolledChangelistsModule::Get().MoveFilesToControlledChangelist(DropOperation->UncontrolledFiles, DestChangelist, SSourceControlCommon::OpenConflictDialog);
|
|
|
|
// TODO: Fix MoveFilesToControlledChangelist() to report the possible errors and display a notification.
|
|
});
|
|
|
|
OnPostDrop.ExecuteIfBound();
|
|
}
|
|
else if (!DropOperation->OfflineFiles.IsEmpty())
|
|
{
|
|
const TArray<FString>& Files = DropOperation->OfflineFiles;
|
|
SSourceControlCommon::ExecuteChangelistOperationWithSlowTaskWrapper(LOCTEXT("Dropping_Files_On_Changelist", "Moving file(s) to the selected changelist..."), [&]()
|
|
{
|
|
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
|
|
|
|
if (!CheckoutAndSavePackages(Files))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SourceControlProvider.Execute(ISourceControlOperation::Create<FMoveToChangelist>(), DestChangelist, Files, EConcurrency::Synchronous, FSourceControlOperationComplete::CreateLambda(
|
|
[](const TSharedRef<ISourceControlOperation>& Operation, ECommandResult::Type InResult)
|
|
{
|
|
if (InResult == ECommandResult::Succeeded)
|
|
{
|
|
SSourceControlCommon::DisplaySourceControlOperationNotification(LOCTEXT("Drop_Files_On_Changelist_Succeeded", "File(s) successfully moved to the selected changelist."), SNotificationItem::CS_Success);
|
|
}
|
|
else if (InResult == ECommandResult::Failed)
|
|
{
|
|
SSourceControlCommon::DisplaySourceControlOperationNotification(LOCTEXT("Drop_Files_On_Changelist_Failed", "Failed to move the file(s) to the selected changelist."), SNotificationItem::CS_Fail);
|
|
}
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
|
|
void SUncontrolledChangelistTableRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwner)
|
|
{
|
|
TreeItem = static_cast<FUncontrolledChangelistTreeItem*>(InArgs._TreeItemToVisualize.Get());
|
|
OnPostDrop = InArgs._OnPostDrop;
|
|
|
|
const FSlateBrush* IconBrush = (TreeItem != nullptr) ?
|
|
FAppStyle::GetBrush(TreeItem->UncontrolledChangelistState->GetSmallIconName()) :
|
|
FAppStyle::GetBrush("SourceControl.Changelist");
|
|
|
|
SetToolTipText(GetChangelistText());
|
|
|
|
STableRow<FChangelistTreeItemPtr>::Construct(
|
|
STableRow<FChangelistTreeItemPtr>::FArguments()
|
|
.Style(FAppStyle::Get(), "TableView.Row")
|
|
.Content()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SImage)
|
|
.Image(IconBrush)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(2.0f, 0.0f)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(this, &SUncontrolledChangelistTableRow::GetChangelistText)
|
|
.HighlightText(InArgs._HighlightText)
|
|
]
|
|
+SHorizontalBox::Slot() // Files/Offline file count.
|
|
.Padding(4, 0, 4, 0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda([this]()
|
|
{
|
|
return FormatChangelistFileCountText(TreeItem->GetChildren().Num(), TreeItem->GetFileCount());
|
|
})
|
|
]
|
|
], InOwner);
|
|
}
|
|
|
|
void SUncontrolledChangelistTableRow::PopulateSearchString(const FUncontrolledChangelistTreeItem& Item, TArray<FString>& OutStrings)
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayText().ToString());
|
|
}
|
|
|
|
FText SUncontrolledChangelistTableRow::GetChangelistText() const
|
|
{
|
|
return TreeItem->GetDisplayText();
|
|
}
|
|
|
|
|
|
FReply SUncontrolledChangelistTableRow::OnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent)
|
|
{
|
|
TSharedPtr<FSCCFileDragDropOp> Operation = InDragDropEvent.GetOperationAs<FSCCFileDragDropOp>();
|
|
|
|
if (Operation.IsValid())
|
|
{
|
|
if (Operation->OfflineFiles.IsEmpty())
|
|
{
|
|
SSourceControlCommon::ExecuteUncontrolledChangelistOperationWithSlowTaskWrapper(LOCTEXT("Drag_File_To_Uncontrolled_Changelist", "Moving file(s) to the selected uncontrolled changelists..."),
|
|
[this, &Operation]()
|
|
{
|
|
FUncontrolledChangelistsModule::Get().MoveFilesToUncontrolledChangelist(Operation->Files, Operation->UncontrolledFiles, TreeItem->UncontrolledChangelistState->Changelist);
|
|
});
|
|
}
|
|
// Drop unsaved assets (offline files)
|
|
else
|
|
{
|
|
const TArray<FString>& Files = Operation->OfflineFiles;
|
|
if (!CheckoutAndSavePackages(Files))
|
|
{
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
SSourceControlCommon::ExecuteUncontrolledChangelistOperationWithSlowTaskWrapper(LOCTEXT("Drag_File_To_Uncontrolled_Changelist", "Moving file(s) to the selected uncontrolled changelists..."),
|
|
[this, &Files]()
|
|
{
|
|
FUncontrolledChangelistsModule::Get().MoveFilesToUncontrolledChangelist(Files, TreeItem->UncontrolledChangelistState->Changelist);
|
|
});
|
|
}
|
|
|
|
OnPostDrop.ExecuteIfBound();
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
void SUnsavedAssetsTableRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwner)
|
|
{
|
|
STableRow<FChangelistTreeItemPtr>::Construct(
|
|
STableRow<FChangelistTreeItemPtr>::FArguments()
|
|
.Style(FAppStyle::Get(), "TableView.Row")
|
|
.Content()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SImage)
|
|
.Image(FAppStyle::GetBrush("Assets.Unsaved"))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(2.0f, 0.0f)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("SourceControl_Unsaved", "Unsaved"))
|
|
]
|
|
+SHorizontalBox::Slot() // Files/Offline file count.
|
|
.Padding(4, 0, 4, 0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda([] { return FText::Format(FText::FromString("({0})"), FUnsavedAssetsTrackerModule::Get().GetUnsavedAssetNum()); })
|
|
]
|
|
], InOwner);
|
|
}
|
|
|
|
|
|
void SFileTableRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwner)
|
|
{
|
|
TreeItem = static_cast<FFileTreeItem*>(InArgs._TreeItemToVisualize.Get());
|
|
|
|
HighlightText = InArgs._HighlightText;
|
|
|
|
PathFlags = InArgs._PathFlags;
|
|
|
|
FSuperRowType::FArguments Args = FSuperRowType::FArguments()
|
|
.OnDragDetected(InArgs._OnDragDetected)
|
|
.ShowSelection(true);
|
|
FSuperRowType::Construct(Args, InOwner);
|
|
}
|
|
|
|
TSharedRef<SWidget> SFileTableRow::GenerateWidgetForColumn(const FName& ColumnId)
|
|
{
|
|
auto ConstructPaddedWidget =
|
|
[](const TSharedRef<SWidget>& Widget)
|
|
{
|
|
TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);
|
|
|
|
HorizontalBox->AddSlot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(8, 0, 0, 0)
|
|
[
|
|
Widget
|
|
];
|
|
|
|
return HorizontalBox;
|
|
};
|
|
|
|
if (ColumnId == SourceControlFileViewColumn::CheckBox::Id())
|
|
{
|
|
return SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.Padding(FMargin(10.0f, 3.0f, 6.0f, 3.0f))
|
|
[
|
|
SNew(SCheckBox)
|
|
.IsChecked(this, &SFileTableRow::GetCheckBoxState)
|
|
.OnCheckStateChanged(this, &SFileTableRow::SetCheckBoxState)
|
|
];
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Icon::Id())
|
|
{
|
|
return SNew(SBox)
|
|
.WidthOverride(16) // Small Icons are usually 16x16
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SSourceControlCommon::GetSCCStatusWidget(TreeItem->FileState)
|
|
];
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Shelve::Id())
|
|
{
|
|
return SNew(SBox)
|
|
.WidthOverride(16) // Small Icons are usually 16x16
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SSourceControlCommon::GetSCCShelveWidget(TreeItem->IsShelved())
|
|
];
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Name::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.Text(this, &SFileTableRow::GetDisplayName)
|
|
.ToolTipText(this, &SFileTableRow::GetDisplayName)
|
|
.HighlightText(HighlightText);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Path::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.Text(this, &SFileTableRow::GetDisplayPath)
|
|
.ToolTipText(this, &SFileTableRow::GetFilename)
|
|
.HighlightText(HighlightText);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Type::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.Text(this, &SFileTableRow::GetDisplayType)
|
|
.ToolTipText(this, &SFileTableRow::GetDisplayType)
|
|
.ColorAndOpacity(this, &SFileTableRow::GetDisplayColor)
|
|
.HighlightText(HighlightText);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::LastModifiedTimestamp::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.ToolTipText(this, &SFileTableRow::GetLastModifiedTimestamp)
|
|
.Text(this, &SFileTableRow::GetLastModifiedTimestamp);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::CheckedOutByUser::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.ToolTipText(this, &SFileTableRow::GetCheckedOutByUser)
|
|
.Text(this, &SFileTableRow::GetCheckedOutByUser);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else
|
|
{
|
|
return SNullWidget::NullWidget;
|
|
}
|
|
}
|
|
|
|
void SFileTableRow::PopulateSearchString(const FFileTreeItem& Item, SourceControlFileViewColumn::EPathFlags PathFlags, TArray<FString>& OutStrings)
|
|
{
|
|
OutStrings.Emplace(Item.GetAssetName().ToString()); // Name
|
|
if (EnumHasAnyFlags(PathFlags, SourceControlFileViewColumn::EPathFlags::ShowingVersePath) && Item.GetVersePath().IsValid())
|
|
{
|
|
OutStrings.Emplace(Item.GetAssetVersePath().ToString());
|
|
}
|
|
else if (EnumHasAnyFlags(PathFlags, SourceControlFileViewColumn::EPathFlags::ShowingPackageName))
|
|
{
|
|
OutStrings.Emplace(Item.GetAssetPackageName().ToString()); // Path
|
|
}
|
|
else
|
|
{
|
|
OutStrings.Emplace(Item.GetAssetPath().ToString()); // Path
|
|
}
|
|
OutStrings.Emplace(Item.GetAssetType().ToString()); // Type
|
|
OutStrings.Emplace(Item.GetLastModifiedTimestamp().ToString());
|
|
OutStrings.Emplace(Item.GetCheckedOutByUser().ToString());
|
|
}
|
|
|
|
ECheckBoxState SFileTableRow::GetCheckBoxState() const
|
|
{
|
|
return TreeItem->GetCheckBoxState();
|
|
}
|
|
|
|
void SFileTableRow::SetCheckBoxState(ECheckBoxState NewState)
|
|
{
|
|
TreeItem->SetCheckBoxState(NewState);
|
|
}
|
|
|
|
FText SFileTableRow::GetDisplayName() const
|
|
{
|
|
return TreeItem->GetAssetName();
|
|
}
|
|
|
|
FText SFileTableRow::GetFilename() const
|
|
{
|
|
return TreeItem->GetFileName();
|
|
}
|
|
|
|
FText SFileTableRow::GetDisplayPath() const
|
|
{
|
|
if (EnumHasAnyFlags(PathFlags.Get(SourceControlFileViewColumn::EPathFlags::Default), SourceControlFileViewColumn::EPathFlags::ShowingVersePath) && TreeItem->GetVersePath().IsValid())
|
|
{
|
|
return TreeItem->GetAssetVersePath();
|
|
}
|
|
else if (EnumHasAnyFlags(PathFlags.Get(SourceControlFileViewColumn::EPathFlags::Default), SourceControlFileViewColumn::EPathFlags::ShowingPackageName))
|
|
{
|
|
return TreeItem->GetAssetPackageName();
|
|
}
|
|
return TreeItem->GetAssetPath();
|
|
}
|
|
|
|
FText SFileTableRow::GetDisplayType() const
|
|
{
|
|
return TreeItem->GetAssetType();
|
|
}
|
|
|
|
FSlateColor SFileTableRow::GetDisplayColor() const
|
|
{
|
|
return TreeItem->GetAssetTypeColor();
|
|
}
|
|
|
|
FText SFileTableRow::GetLastModifiedTimestamp() const
|
|
{
|
|
return TreeItem->GetLastModifiedTimestamp();
|
|
}
|
|
|
|
FText SFileTableRow::GetCheckedOutByUser() const
|
|
{
|
|
return TreeItem->GetCheckedOutByUser();
|
|
}
|
|
|
|
void SFileTableRow::OnDragEnter(FGeometry const& InGeometry, FDragDropEvent const& InDragDropEvent)
|
|
{
|
|
TSharedPtr<FDragDropOperation> DragOperation = InDragDropEvent.GetOperation();
|
|
DragOperation->SetCursorOverride(EMouseCursor::SlashedCircle);
|
|
}
|
|
|
|
void SFileTableRow::OnDragLeave(FDragDropEvent const& InDragDropEvent)
|
|
{
|
|
TSharedPtr<FDragDropOperation> DragOperation = InDragDropEvent.GetOperation();
|
|
DragOperation->SetCursorOverride(EMouseCursor::None);
|
|
}
|
|
|
|
|
|
void SShelvedFilesTableRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView)
|
|
{
|
|
TreeItem = static_cast<FShelvedChangelistTreeItem*>(InArgs._TreeItemToVisualize.Get());
|
|
|
|
STableRow<FChangelistTreeItemPtr>::Construct(
|
|
STableRow<FChangelistTreeItemPtr>::FArguments()
|
|
.Content()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(5, 0, 0, 0)
|
|
[
|
|
SNew(SImage)
|
|
.Image(FAppStyle::GetBrush("SourceControl.ShelvedChangelist"))
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.Padding(2.0f, 1.0f)
|
|
.VAlign(VAlign_Center)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda([this](){ return TreeItem->GetDisplayText(); })
|
|
.HighlightText(InArgs._HighlightText)
|
|
]
|
|
+SHorizontalBox::Slot() // Shelved file count.
|
|
.Padding(4, 0, 4, 0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda([this]()
|
|
{
|
|
return FormatChangelistFileCountText(TreeItem->GetChildren().Num(), static_cast<const FChangelistTreeItem*>(TreeItem->GetParent().Get())->GetShelvedFileCount());
|
|
})
|
|
]
|
|
],
|
|
InOwnerTableView);
|
|
}
|
|
|
|
void SShelvedFilesTableRow::PopulateSearchString(const FShelvedChangelistTreeItem& Item, TArray<FString>& OutStrings)
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayText().ToString());
|
|
}
|
|
|
|
|
|
void SOfflineFileTableRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwner)
|
|
{
|
|
TreeItem = static_cast<FOfflineFileTreeItem*>(InArgs._TreeItemToVisualize.Get());
|
|
HighlightText = InArgs._HighlightText;
|
|
PathFlags = InArgs._PathFlags;
|
|
|
|
FSuperRowType::FArguments Args = FSuperRowType::FArguments()
|
|
.OnDragDetected(InArgs._OnDragDetected)
|
|
.ShowSelection(true);
|
|
FSuperRowType::Construct(Args, InOwner);
|
|
}
|
|
|
|
TSharedRef<SWidget> SOfflineFileTableRow::GenerateWidgetForColumn(const FName& ColumnId)
|
|
{
|
|
auto ConstructPaddedWidget =
|
|
[](const TSharedRef<SWidget>& Widget)
|
|
{
|
|
TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);
|
|
|
|
HorizontalBox->AddSlot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(8, 0, 0, 0)
|
|
[
|
|
Widget
|
|
];
|
|
|
|
return HorizontalBox;
|
|
};
|
|
|
|
if (ColumnId == SourceControlFileViewColumn::CheckBox::Id())
|
|
{
|
|
return SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.Padding(FMargin(10.0f, 3.0f, 6.0f, 3.0f))
|
|
[
|
|
SNew(SCheckBox)
|
|
.IsChecked(this, &SOfflineFileTableRow::GetCheckBoxState)
|
|
.OnCheckStateChanged(this, &SOfflineFileTableRow::SetCheckBoxState)
|
|
];
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Icon::Id())
|
|
{
|
|
return SNew(SBox)
|
|
.WidthOverride(16) // Small Icons are usually 16x16
|
|
.HAlign(HAlign_Center)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SImage)
|
|
.Image(FAppStyle::GetBrush(FName("SourceControl.OfflineFile_Small")))
|
|
];
|
|
}
|
|
if (ColumnId == SourceControlFileViewColumn::Shelve::Id())
|
|
{
|
|
return SNew(SBox)
|
|
.WidthOverride(16) // Small Icons are usually 16x16
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNullWidget::NullWidget
|
|
];
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Name::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.ToolTipText(this, &SOfflineFileTableRow::GetDisplayName)
|
|
.Text(this, &SOfflineFileTableRow::GetDisplayName)
|
|
.HighlightText(HighlightText);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Path::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.Text(this, &SOfflineFileTableRow::GetDisplayPath)
|
|
.ToolTipText(this, &SOfflineFileTableRow::GetFilename)
|
|
.HighlightText(HighlightText);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Type::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.Text(this, &SOfflineFileTableRow::GetDisplayType)
|
|
.ToolTipText(this, &SOfflineFileTableRow::GetDisplayType)
|
|
.ColorAndOpacity(this, &SOfflineFileTableRow::GetDisplayColor)
|
|
.HighlightText(HighlightText);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::LastModifiedTimestamp::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.ToolTipText(this, &SOfflineFileTableRow::GetLastModifiedTimestamp)
|
|
.Text(this, &SOfflineFileTableRow::GetLastModifiedTimestamp);
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::CheckedOutByUser::Id())
|
|
{
|
|
TSharedPtr<SWidget> Widget = SNew(STextBlock)
|
|
.Text(FText::GetEmpty());
|
|
return ConstructPaddedWidget(Widget.ToSharedRef());
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Dirty::Id())
|
|
{
|
|
if (FUnsavedAssetsTrackerModule::Get().IsAssetUnsaved(GetFilename().ToString()))
|
|
{
|
|
return SNew(SBox)
|
|
.WidthOverride(16) // Small Icons are usually 16x16
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNew(SImage)
|
|
.Image(FAppStyle::GetBrush(FName("SourceControl.OfflineFile_Small")))
|
|
];
|
|
}
|
|
return SNew(SBox)
|
|
.WidthOverride(16); // Small Icons are usually 16x16
|
|
}
|
|
else if (ColumnId == SourceControlFileViewColumn::Discard::Id())
|
|
{
|
|
FString Filename = TreeItem->GetFullPathname();
|
|
if (!FUnsavedAssetsTrackerModule::Get().IsAssetUnsaved(Filename))
|
|
{
|
|
return SNew(SBox)
|
|
.WidthOverride(16); // Small Icons are usually 16x16
|
|
}
|
|
|
|
TSharedRef<SWidgetSwitcher> DiscardSwitcher = SNew(SWidgetSwitcher);
|
|
|
|
TSharedRef<SImage> DiscardButton = SNew(SImage)
|
|
.DesiredSizeOverride(FVector2D{ 16.0f })
|
|
.Image(FAppStyle::Get().GetBrush("Icons.XCircle"))
|
|
.ColorAndOpacity(FSlateColor::UseSubduedForeground())
|
|
.OnMouseButtonDown_Lambda([this, DiscardSwitcher] (const FGeometry&, const FPointerEvent&) -> FReply
|
|
{
|
|
// Normalize packagenames and filenames
|
|
FString PackageName;
|
|
{
|
|
FString TreeName = TreeItem->GetPackageName();
|
|
|
|
if (!FPackageName::TryConvertFilenameToLongPackageName(TreeName, PackageName))
|
|
{
|
|
PackageName = MoveTemp(TreeName);
|
|
}
|
|
}
|
|
// Validate we have a saved map
|
|
if (UPackage* Package = FindPackage(nullptr, *PackageName))
|
|
{
|
|
UPackage* LevelPackage = Package->GetOutermost();
|
|
if (LevelPackage == GetTransientPackage()
|
|
|| LevelPackage->HasAnyFlags(RF_Transient)
|
|
|| !FPackageName::IsValidLongPackageName(LevelPackage->GetName()))
|
|
{
|
|
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("DiscardUnsavedChangesSaveMap", "You need to save the level before discarding unsaved changes."));
|
|
return FReply::Handled();
|
|
}
|
|
}
|
|
|
|
DiscardSwitcher->SetActiveWidgetIndex(1);
|
|
ExecuteOnGameThread(UE_SOURCE_LOCATION,
|
|
[this]
|
|
{
|
|
TArray<FString> PackageToReload { TreeItem->GetPackageName() };
|
|
const bool bAllowReloadWorld = true;
|
|
const bool bInteractive = false;
|
|
USourceControlHelpers::ApplyOperationAndReloadPackages(
|
|
PackageToReload,
|
|
[](const TArray<FString>&) -> bool { return true; },
|
|
bAllowReloadWorld,
|
|
bInteractive
|
|
);
|
|
});
|
|
|
|
return FReply::Handled();
|
|
});
|
|
|
|
DiscardSwitcher->AddSlot()[
|
|
DiscardButton
|
|
];
|
|
DiscardSwitcher->AddSlot()[
|
|
SNew(SCircularThrobber)
|
|
.Radius(7.5f)
|
|
];
|
|
|
|
return
|
|
SNew(SBox)
|
|
.WidthOverride(16) // Small Icons are usually 16x16
|
|
.Padding(FMargin{1, 0})
|
|
.ToolTipText(LOCTEXT("UnsavedAsset_DiscardChanges", "Discard unsaved changes"))
|
|
[
|
|
DiscardSwitcher
|
|
];
|
|
}
|
|
else
|
|
{
|
|
return SNullWidget::NullWidget;
|
|
}
|
|
}
|
|
|
|
void SOfflineFileTableRow::PopulateSearchString(const FOfflineFileTreeItem& Item, SourceControlFileViewColumn::EPathFlags PathFlags, TArray<FString>& OutStrings)
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayName().ToString()); // Name
|
|
if (EnumHasAnyFlags(PathFlags, SourceControlFileViewColumn::EPathFlags::ShowingVersePath) && Item.GetVersePath().IsValid())
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayVersePath().ToString());
|
|
}
|
|
else if (EnumHasAnyFlags(PathFlags, SourceControlFileViewColumn::EPathFlags::ShowingPackageName))
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayPackageName().ToString()); // Path
|
|
}
|
|
else
|
|
{
|
|
OutStrings.Emplace(Item.GetDisplayPath().ToString()); // Path
|
|
}
|
|
OutStrings.Emplace(Item.GetDisplayType().ToString()); // Type
|
|
OutStrings.Emplace(Item.GetLastModifiedTimestamp().ToString());
|
|
}
|
|
|
|
ECheckBoxState SOfflineFileTableRow::GetCheckBoxState() const
|
|
{
|
|
return TreeItem->GetCheckBoxState();
|
|
}
|
|
|
|
void SOfflineFileTableRow::SetCheckBoxState(ECheckBoxState NewState)
|
|
{
|
|
TreeItem->SetCheckBoxState(NewState);
|
|
}
|
|
|
|
FText SOfflineFileTableRow::GetDisplayName() const
|
|
{
|
|
return TreeItem->GetDisplayName();
|
|
}
|
|
|
|
FText SOfflineFileTableRow::GetFilename() const
|
|
{
|
|
return TreeItem->GetDisplayPackageName();
|
|
}
|
|
|
|
FText SOfflineFileTableRow::GetDisplayPath() const
|
|
{
|
|
if (EnumHasAnyFlags(PathFlags.Get(SourceControlFileViewColumn::EPathFlags::Default), SourceControlFileViewColumn::EPathFlags::ShowingVersePath) && TreeItem->GetVersePath().IsValid())
|
|
{
|
|
return TreeItem->GetDisplayVersePath();
|
|
}
|
|
else if (EnumHasAnyFlags(PathFlags.Get(SourceControlFileViewColumn::EPathFlags::Default), SourceControlFileViewColumn::EPathFlags::ShowingPackageName))
|
|
{
|
|
return TreeItem->GetDisplayPackageName();
|
|
}
|
|
return TreeItem->GetDisplayPath();
|
|
}
|
|
|
|
FText SOfflineFileTableRow::GetDisplayType() const
|
|
{
|
|
return TreeItem->GetDisplayType();
|
|
}
|
|
|
|
FSlateColor SOfflineFileTableRow::GetDisplayColor() const
|
|
{
|
|
return TreeItem->GetDisplayColor();
|
|
}
|
|
|
|
FText SOfflineFileTableRow::GetLastModifiedTimestamp() const
|
|
{
|
|
return TreeItem->GetLastModifiedTimestamp();
|
|
}
|
|
|
|
void SOfflineFileTableRow::OnDragEnter(FGeometry const& InGeometry, FDragDropEvent const& InDragDropEvent)
|
|
{
|
|
TSharedPtr<FDragDropOperation> DragOperation = InDragDropEvent.GetOperation();
|
|
DragOperation->SetCursorOverride(EMouseCursor::SlashedCircle);
|
|
}
|
|
|
|
void SOfflineFileTableRow::OnDragLeave(FDragDropEvent const& InDragDropEvent)
|
|
{
|
|
TSharedPtr<FDragDropOperation> DragOperation = InDragDropEvent.GetOperation();
|
|
DragOperation->SetCursorOverride(EMouseCursor::None);
|
|
}
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|