2021-01-11 15:31:58 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "SSourceControlChangelists.h"
2022-05-09 13:12:28 -04:00
# include "Styling/AppStyle.h"
2021-01-11 15:31:58 -04:00
2021-01-18 15:31:14 -04:00
# include "Algo/Transform.h"
2021-04-06 14:20:24 -04:00
# include "Logging/MessageLog.h"
2021-01-11 15:31:58 -04:00
# include "Widgets/DeclarativeSyntaxSupport.h"
# include "Widgets/Images/SImage.h"
# include "Widgets/Layout/SScrollBorder.h"
2021-01-27 15:28:56 -04:00
# include "Widgets/Input/SButton.h"
# include "Widgets/Layout/SBorder.h"
# include "Widgets/Layout/SBox.h"
2021-04-06 14:20:24 -04:00
# include "Widgets/Notifications/SNotificationList.h"
2021-01-11 15:31:58 -04:00
# include "ISourceControlProvider.h"
# include "ISourceControlModule.h"
2021-05-06 14:40:16 -04:00
# include "UncontrolledChangelistsModule.h"
2021-01-11 15:31:58 -04:00
# include "SourceControlOperations.h"
2021-01-18 09:42:33 -04:00
# include "ToolMenus.h"
2021-01-11 21:46:43 -04:00
# include "Widgets/Images/SLayeredImage.h"
2021-01-18 09:42:33 -04:00
# include "SSourceControlDescription.h"
2021-01-19 14:50:23 -04:00
# include "SourceControlWindows.h"
2021-02-04 11:50:49 -04:00
# include "SourceControlHelpers.h"
2022-01-31 17:03:09 -05:00
# include "SourceControlPreferences.h"
2021-01-19 14:50:23 -04:00
# include "AssetToolsModule.h"
# include "ContentBrowserModule.h"
# include "IContentBrowserSingleton.h"
2021-01-20 09:51:23 -04:00
# include "Misc/MessageDialog.h"
2021-03-24 08:29:57 -04:00
# include "Misc/ScopedSlowTask.h"
2021-02-04 11:50:49 -04:00
# include "Algo/AnyOf.h"
# include "SSourceControlSubmit.h"
# include "Framework/Application/SlateApplication.h"
2021-04-06 14:20:24 -04:00
# include "Framework/Notifications/NotificationManager.h"
2021-01-11 15:31:58 -04:00
# define LOCTEXT_NAMESPACE "SourceControlChangelist"
2021-04-19 11:21:23 -04:00
const FText SSourceControlChangelistsWidget : : ChangelistValidatedTag = LOCTEXT ( " ValidationTag " , " #changelist validated " ) ;
2021-03-10 15:03:45 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogSourceControlChangelist , All , All ) ;
2021-01-18 15:31:14 -04:00
//////////////////////////////
struct FSCCFileDragDropOp : public FDragDropOperation
{
DRAG_DROP_OPERATOR_TYPE ( FSCCFileDragDropOp , FDragDropOperation ) ;
using FDragDropOperation : : Construct ;
virtual TSharedPtr < SWidget > GetDefaultDecorator ( ) const override
{
2021-05-12 17:06:06 -04:00
FSourceControlStateRef FileState = Files . IsEmpty ( ) ? UncontrolledFiles [ 0 ] : Files [ 0 ] ;
return SSourceControlCommon : : GetSCCFileWidget ( MoveTemp ( FileState ) ) ;
2021-01-18 15:31:14 -04:00
}
TArray < FSourceControlStateRef > Files ;
2021-05-12 17:06:06 -04:00
TArray < FSourceControlStateRef > UncontrolledFiles ;
2021-01-18 15:31:14 -04:00
} ;
//////////////////////////////
2021-01-11 15:31:58 -04:00
SSourceControlChangelistsWidget : : SSourceControlChangelistsWidget ( )
{
2021-03-24 08:29:57 -04:00
bIsRefreshing = false ;
2021-01-11 15:31:58 -04:00
}
void SSourceControlChangelistsWidget : : Construct ( const FArguments & InArgs )
{
2021-01-13 11:07:12 -04:00
// Register delegates
ISourceControlModule & SCCModule = ISourceControlModule : : Get ( ) ;
2021-05-26 18:15:46 -04:00
FUncontrolledChangelistsModule & UncontrolledChangelistModule = FUncontrolledChangelistsModule : : Get ( ) ;
2021-01-13 11:07:12 -04:00
SCCModule . RegisterProviderChanged ( FSourceControlProviderChanged : : FDelegate : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnSourceControlProviderChanged ) ) ;
SourceControlStateChangedDelegateHandle = SCCModule . GetProvider ( ) . RegisterSourceControlStateChanged_Handle ( FSourceControlStateChanged : : FDelegate : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnSourceControlStateChanged ) ) ;
2021-05-26 18:15:46 -04:00
UncontrolledChangelistModule . OnUncontrolledChangelistModuleChanged . AddSP ( this , & SSourceControlChangelistsWidget : : OnSourceControlStateChanged ) ;
2021-01-13 11:07:12 -04:00
2021-01-11 15:31:58 -04:00
TreeView = CreateTreeviewWidget ( ) ;
ChildSlot
2021-01-13 16:50:22 -04:00
[
2021-01-27 15:28:56 -04:00
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
2021-01-11 15:31:58 -04:00
[
2021-01-27 15:28:56 -04:00
SNew ( SBorder )
2022-05-09 13:12:28 -04:00
. BorderImage ( FAppStyle : : GetBrush ( " ToolPanel.GroupBorder " ) )
2021-01-27 15:28:56 -04:00
. Padding ( 4 )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
MakeToolBar ( )
]
]
]
+ SVerticalBox : : Slot ( )
[
SNew ( SScrollBorder , TreeView . ToSharedRef ( ) )
2021-06-08 17:12:06 -04:00
. Visibility ( TAttribute < EVisibility > : : Create ( TAttribute < EVisibility > : : FGetter : : CreateLambda ( [ ] ( ) - > EVisibility { return ( ISourceControlModule : : Get ( ) . IsEnabled ( ) | | FUncontrolledChangelistsModule : : Get ( ) . IsEnabled ( ) )
? EVisibility : : Visible
: EVisibility : : Hidden ; } ) ) )
2021-01-27 15:28:56 -04:00
[
TreeView . ToSharedRef ( )
]
2021-01-13 16:50:22 -04:00
]
2021-03-24 08:29:57 -04:00
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
SNew ( SBorder )
[
2021-05-26 18:15:46 -04:00
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text_Lambda ( [ this ] ( ) { return RefreshStatus ; } )
. Visibility_Lambda ( [ this ] ( ) - > EVisibility
{
return bIsRefreshing ? EVisibility : : Visible : EVisibility : : Collapsed ;
} )
]
+ SHorizontalBox : : Slot ( )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
. Padding ( FMargin ( 2.f , 0.f ) )
[
SNew ( STextBlock )
. Text_Lambda ( [ ] ( ) { return FUncontrolledChangelistsModule : : Get ( ) . GetReconcileStatus ( ) ; } )
. Visibility_Lambda ( [ ] ( ) - > EVisibility
{
return FUncontrolledChangelistsModule : : Get ( ) . IsEnabled ( ) ? EVisibility : : Visible : EVisibility : : Collapsed ;
} )
]
2021-03-24 08:29:57 -04:00
]
]
2021-01-13 16:50:22 -04:00
] ;
bShouldRefresh = true ;
2021-01-11 15:31:58 -04:00
}
2021-01-27 15:28:56 -04:00
TSharedRef < SWidget > SSourceControlChangelistsWidget : : MakeToolBar ( )
{
FSlimHorizontalToolBarBuilder ToolBarBuilder ( nullptr , FMultiBoxCustomization : : None ) ;
ToolBarBuilder . AddToolBarButton (
FUIAction (
FExecuteAction : : CreateLambda ( [ this ] ( ) {
RequestRefresh ( ) ;
} ) ) ,
NAME_None ,
LOCTEXT ( " SourceControl_RefreshButton " , " Refresh " ) ,
LOCTEXT ( " SourceControl_RefreshButton_Tooltip " , " Refreshes changelists from source control provider. " ) ,
2022-05-09 13:12:28 -04:00
FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " SourceControl.Actions.Refresh " ) ) ;
2021-01-27 15:28:56 -04:00
2021-03-24 08:29:57 -04:00
ToolBarBuilder . AddToolBarButton (
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnNewChangelist ) ) ,
NAME_None ,
LOCTEXT ( " SourceControl_NewChangelistButton " , " New Changelist " ) ,
LOCTEXT ( " SourceControl_NewChangelistButton_Tooltip " , " Creates an empty changelist " ) ,
2022-05-09 13:12:28 -04:00
FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " SourceControl.Actions.Add " ) ) ;
2021-03-24 08:29:57 -04:00
2021-01-27 15:28:56 -04:00
return ToolBarBuilder . MakeWidget ( ) ;
}
2021-04-19 11:21:23 -04:00
bool SSourceControlChangelistsWidget : : HasValidationTag ( const FText & InChangelistDescription ) const
{
FString DescriptionString = InChangelistDescription . ToString ( ) ;
FString ValidationString = ChangelistValidatedTag . ToString ( ) ;
return DescriptionString . Find ( ValidationString ) ! = INDEX_NONE ;
}
void SSourceControlChangelistsWidget : : EditChangelistDescription ( const FText & InNewChangelistDescription , const FSourceControlChangelistStatePtr & InChangelistState ) const
{
auto EditChangelistOperation = ISourceControlOperation : : Create < FEditChangelist > ( ) ;
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
EditChangelistOperation - > SetDescription ( InNewChangelistDescription ) ;
SourceControlProvider . Execute ( EditChangelistOperation , InChangelistState - > GetChangelist ( ) ) ;
}
2021-01-13 16:50:22 -04:00
void SSourceControlChangelistsWidget : : Tick ( const FGeometry & AllottedGeometry , const double InCurrentTime , const float InDeltaTime )
{
if ( bShouldRefresh )
{
2021-06-08 17:12:06 -04:00
if ( ISourceControlModule : : Get ( ) . IsEnabled ( ) | | FUncontrolledChangelistsModule : : Get ( ) . IsEnabled ( ) )
2021-01-13 16:50:22 -04:00
{
RequestRefresh ( ) ;
bShouldRefresh = false ;
}
else
{
// No provider available, clear changelist tree
ClearChangelistsTree ( ) ;
}
}
2021-03-24 08:29:57 -04:00
if ( bIsRefreshing )
{
TickRefreshStatus ( InDeltaTime ) ;
}
2021-01-13 16:50:22 -04:00
}
void SSourceControlChangelistsWidget : : RequestRefresh ( )
2021-01-11 15:31:58 -04:00
{
2021-06-08 17:12:06 -04:00
bool bAnyProviderAvailable = false ;
2021-01-13 11:07:12 -04:00
if ( ISourceControlModule : : Get ( ) . IsEnabled ( ) )
{
2021-06-08 17:12:06 -04:00
bAnyProviderAvailable = true ;
2021-03-24 08:29:57 -04:00
StartRefreshStatus ( ) ;
2021-01-13 16:50:22 -04:00
TSharedRef < FUpdatePendingChangelistsStatus , ESPMode : : ThreadSafe > UpdatePendingChangelistsOperation = ISourceControlOperation : : Create < FUpdatePendingChangelistsStatus > ( ) ;
2021-01-13 11:07:12 -04:00
UpdatePendingChangelistsOperation - > SetUpdateAllChangelists ( true ) ;
UpdatePendingChangelistsOperation - > SetUpdateFilesStates ( true ) ;
2021-01-26 09:19:24 -04:00
UpdatePendingChangelistsOperation - > SetUpdateShelvedFilesStates ( true ) ;
2021-01-11 15:31:58 -04:00
2021-01-13 11:07:12 -04:00
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2021-02-08 09:36:20 -04:00
SourceControlProvider . Execute ( UpdatePendingChangelistsOperation , EConcurrency : : Asynchronous ) ;
2021-06-08 17:12:06 -04:00
}
if ( FUncontrolledChangelistsModule : : Get ( ) . IsEnabled ( ) )
{
bAnyProviderAvailable = true ;
2021-05-06 14:40:16 -04:00
FUncontrolledChangelistsModule & UncontrolledChangelistModule = FUncontrolledChangelistsModule : : Get ( ) ;
UncontrolledChangelistModule . UpdateStatus ( ) ;
2021-01-13 11:07:12 -04:00
}
2021-06-08 17:12:06 -04:00
if ( ! bAnyProviderAvailable )
2021-01-13 11:07:12 -04:00
{
// No provider available, clear changelist tree
2021-01-13 16:50:22 -04:00
ClearChangelistsTree ( ) ;
}
}
2021-03-24 08:29:57 -04:00
void SSourceControlChangelistsWidget : : StartRefreshStatus ( )
{
bIsRefreshing = true ;
RefreshStatusTimeElapsed = 0 ;
}
void SSourceControlChangelistsWidget : : TickRefreshStatus ( double InDeltaTime )
{
RefreshStatusTimeElapsed + = InDeltaTime ;
const int SecondsElapsed = ( int ) RefreshStatusTimeElapsed ;
RefreshStatus = FText : : Format ( LOCTEXT ( " SourceControl_RefreshStatus " , " Refreshing changelists... ({0} s) " ) , FText : : AsNumber ( SecondsElapsed ) ) ;
}
void SSourceControlChangelistsWidget : : EndRefreshStatus ( )
{
bIsRefreshing = false ;
}
2021-01-13 16:50:22 -04:00
void SSourceControlChangelistsWidget : : ClearChangelistsTree ( )
{
if ( ! ChangelistsNodes . IsEmpty ( ) )
{
2021-01-13 11:07:12 -04:00
ChangelistsNodes . Empty ( ) ;
TreeView - > RequestTreeRefresh ( ) ;
}
}
2021-01-11 15:31:58 -04:00
2021-01-13 16:50:22 -04:00
void SSourceControlChangelistsWidget : : Refresh ( )
2021-01-11 15:31:58 -04:00
{
2021-06-08 17:12:06 -04:00
if ( ISourceControlModule : : Get ( ) . IsEnabled ( ) | | FUncontrolledChangelistsModule : : Get ( ) . IsEnabled ( ) )
2021-01-11 15:31:58 -04:00
{
2021-01-26 10:56:16 -04:00
TMap < FSourceControlChangelistStateRef , ExpandedState > ExpandedStates ;
SaveExpandedState ( ExpandedStates ) ;
2021-01-13 11:07:12 -04:00
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2021-05-06 14:40:16 -04:00
FUncontrolledChangelistsModule & UncontrolledChangelistModule = FUncontrolledChangelistsModule : : Get ( ) ;
2021-01-13 11:07:12 -04:00
TArray < FSourceControlChangelistRef > Changelists = SourceControlProvider . GetChangelists ( EStateCacheUsage : : Use ) ;
2021-05-06 14:40:16 -04:00
TArray < FUncontrolledChangelistStateRef > UncontrolledChangelistStates = UncontrolledChangelistModule . GetChangelistStates ( ) ;
2021-01-13 11:07:12 -04:00
TArray < FSourceControlChangelistStateRef > ChangelistsStates ;
SourceControlProvider . GetState ( Changelists , ChangelistsStates , EStateCacheUsage : : Use ) ;
ChangelistsNodes . Reset ( ChangelistsStates . Num ( ) ) ;
2021-03-24 08:29:57 -04:00
// Count number of steps for slow task...
int32 ElementsToProcess = ChangelistsStates . Num ( ) ;
2021-05-06 14:40:16 -04:00
ElementsToProcess + = UncontrolledChangelistStates . Num ( ) ;
2021-03-24 08:29:57 -04:00
for ( FSourceControlChangelistStateRef ChangelistState : ChangelistsStates )
{
ElementsToProcess + = ChangelistState - > GetFilesStates ( ) . Num ( ) ;
ElementsToProcess + = ChangelistState - > GetShelvedFilesStates ( ) . Num ( ) ;
}
2021-05-06 14:40:16 -04:00
for ( FUncontrolledChangelistStateRef UncontrolledChangelistState : UncontrolledChangelistStates )
{
ElementsToProcess + = UncontrolledChangelistState - > GetFilesStates ( ) . Num ( ) ;
2021-06-08 17:12:06 -04:00
ElementsToProcess + = UncontrolledChangelistState - > GetOfflineFiles ( ) . Num ( ) ;
2021-05-06 14:40:16 -04:00
}
2021-08-31 15:12:47 -04:00
FScopedSlowTask SlowTask ( ElementsToProcess , LOCTEXT ( " SourceControl_RebuildTree " , " Refreshing Tree Items " ) ) ;
2021-03-24 08:29:57 -04:00
SlowTask . MakeDialog ( /*bShowCancelButton=*/ true ) ;
bool bBeautifyPaths = true ;
2021-01-13 11:07:12 -04:00
for ( FSourceControlChangelistStateRef ChangelistState : ChangelistsStates )
2021-01-11 15:31:58 -04:00
{
2021-01-13 11:07:12 -04:00
FChangelistTreeItemRef ChangelistTreeItem = MakeShareable ( new FChangelistTreeItem ( ChangelistState ) ) ;
2021-01-11 15:31:58 -04:00
2021-01-13 11:07:12 -04:00
for ( FSourceControlStateRef FileRef : ChangelistState - > GetFilesStates ( ) )
{
2021-03-24 08:29:57 -04:00
FChangelistTreeItemRef FileTreeItem = MakeShareable ( new FFileTreeItem ( FileRef , bBeautifyPaths ) ) ;
2021-01-13 11:07:12 -04:00
ChangelistTreeItem - > AddChild ( FileTreeItem ) ;
2021-03-24 08:29:57 -04:00
SlowTask . EnterProgressFrame ( ) ;
bBeautifyPaths & = ! SlowTask . ShouldCancel ( ) ;
2021-01-13 11:07:12 -04:00
}
2021-01-26 09:19:24 -04:00
if ( ChangelistState - > GetShelvedFilesStates ( ) . Num ( ) > 0 )
{
FChangelistTreeItemRef ShelvedChangelistTreeItem = MakeShareable ( new FShelvedChangelistTreeItem ( ) ) ;
ChangelistTreeItem - > AddChild ( ShelvedChangelistTreeItem ) ;
for ( FSourceControlStateRef ShelvedFileRef : ChangelistState - > GetShelvedFilesStates ( ) )
{
2021-03-24 08:29:57 -04:00
FChangelistTreeItemRef ShelvedFileTreeItem = MakeShareable ( new FShelvedFileTreeItem ( ShelvedFileRef , bBeautifyPaths ) ) ;
2021-01-26 09:19:24 -04:00
ShelvedChangelistTreeItem - > AddChild ( ShelvedFileTreeItem ) ;
2021-03-24 08:29:57 -04:00
SlowTask . EnterProgressFrame ( ) ;
bBeautifyPaths & = ! SlowTask . ShouldCancel ( ) ;
2021-01-26 09:19:24 -04:00
}
}
2021-01-13 11:07:12 -04:00
ChangelistsNodes . Add ( ChangelistTreeItem ) ;
2021-03-24 08:29:57 -04:00
SlowTask . EnterProgressFrame ( ) ;
bBeautifyPaths & = ! SlowTask . ShouldCancel ( ) ;
2021-01-13 11:07:12 -04:00
}
2021-01-13 16:50:22 -04:00
2021-05-06 14:40:16 -04:00
for ( FUncontrolledChangelistStateRef UncontrolledChangelistState : UncontrolledChangelistStates )
{
FChangelistTreeItemRef UncontrolledChangelistTreeItem = MakeShareable ( new FUncontrolledChangelistTreeItem ( UncontrolledChangelistState ) ) ;
2021-06-08 17:12:06 -04:00
for ( const FSourceControlStateRef & FileRef : UncontrolledChangelistState - > GetFilesStates ( ) )
2021-05-06 14:40:16 -04:00
{
FChangelistTreeItemRef FileTreeItem = MakeShareable ( new FFileTreeItem ( FileRef , bBeautifyPaths ) ) ;
UncontrolledChangelistTreeItem - > AddChild ( FileTreeItem ) ;
SlowTask . EnterProgressFrame ( ) ;
bBeautifyPaths & = ! SlowTask . ShouldCancel ( ) ;
}
2021-06-08 17:12:06 -04:00
for ( const FString & Filename : UncontrolledChangelistState - > GetOfflineFiles ( ) )
{
FChangelistTreeItemRef OfflineFileTreeItem = MakeShareable ( new FOfflineFileTreeItem ( Filename ) ) ;
UncontrolledChangelistTreeItem - > AddChild ( OfflineFileTreeItem ) ;
SlowTask . EnterProgressFrame ( ) ;
bBeautifyPaths & = ! SlowTask . ShouldCancel ( ) ;
}
2021-05-06 14:40:16 -04:00
ChangelistsNodes . Add ( UncontrolledChangelistTreeItem ) ;
SlowTask . EnterProgressFrame ( ) ;
bBeautifyPaths & = ! SlowTask . ShouldCancel ( ) ;
}
2021-01-26 10:56:16 -04:00
RestoreExpandedState ( ExpandedStates ) ;
2021-01-13 16:50:22 -04:00
TreeView - > RequestTreeRefresh ( ) ;
2021-01-13 11:07:12 -04:00
}
else
{
2021-01-13 16:50:22 -04:00
ClearChangelistsTree ( ) ;
2021-01-11 15:31:58 -04:00
}
2021-03-24 08:29:57 -04:00
EndRefreshStatus ( ) ;
2021-01-11 15:31:58 -04:00
}
2021-01-13 16:50:22 -04:00
void SSourceControlChangelistsWidget : : OnSourceControlProviderChanged ( ISourceControlProvider & OldProvider , ISourceControlProvider & NewProvider )
2021-01-11 15:31:58 -04:00
{
2021-01-13 16:50:22 -04:00
OldProvider . UnregisterSourceControlStateChanged_Handle ( SourceControlStateChangedDelegateHandle ) ;
SourceControlStateChangedDelegateHandle = NewProvider . RegisterSourceControlStateChanged_Handle ( FSourceControlStateChanged : : FDelegate : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnSourceControlStateChanged ) ) ;
2021-01-11 15:31:58 -04:00
2021-01-13 16:50:22 -04:00
bShouldRefresh = true ;
}
2021-01-11 15:31:58 -04:00
2021-01-13 16:50:22 -04:00
void SSourceControlChangelistsWidget : : OnSourceControlStateChanged ( )
{
Refresh ( ) ;
}
2021-01-11 15:31:58 -04:00
2021-01-13 16:50:22 -04:00
void SSourceControlChangelistsWidget : : OnChangelistsStatusUpdated ( const FSourceControlOperationRef & InOperation , ECommandResult : : Type InType )
{
Refresh ( ) ;
2021-01-11 15:31:58 -04:00
}
2021-01-13 20:52:07 -04:00
void SChangelistTree : : Private_SetItemSelection ( FChangelistTreeItemPtr TheItem , bool bShouldBeSelected , bool bWasUserDirected )
{
bool bAllowSelectionChange = true ;
if ( bShouldBeSelected & & ! SelectedItems . IsEmpty ( ) )
{
// Prevent selecting changelists and files at the same time.
FChangelistTreeItemPtr CurrentlySelectedItem = ( * SelectedItems . begin ( ) ) ;
if ( TheItem - > GetTreeItemType ( ) ! = CurrentlySelectedItem - > GetTreeItemType ( ) )
{
bAllowSelectionChange = false ;
}
// Prevent selecting items that don't share the same root
else if ( TheItem - > GetParent ( ) ! = CurrentlySelectedItem - > GetParent ( ) )
{
bAllowSelectionChange = false ;
}
}
if ( bAllowSelectionChange )
{
STreeView : : Private_SetItemSelection ( TheItem , bShouldBeSelected , bWasUserDirected ) ;
}
}
2021-01-18 09:42:33 -04:00
FSourceControlChangelistStatePtr SSourceControlChangelistsWidget : : GetCurrentChangelistState ( )
{
if ( ! TreeView )
{
return nullptr ;
}
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
if ( SelectedItems . Num ( ) ! = 1 | | SelectedItems [ 0 ] - > GetTreeItemType ( ) ! = IChangelistTreeItem : : Changelist )
{
return nullptr ;
}
else
{
return StaticCastSharedPtr < FChangelistTreeItem > ( SelectedItems [ 0 ] ) - > ChangelistState ;
}
}
2021-06-14 15:25:20 -04:00
FUncontrolledChangelistStatePtr SSourceControlChangelistsWidget : : GetCurrentUncontrolledChangelistState ( )
{
if ( ! TreeView )
{
return nullptr ;
}
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
if ( SelectedItems . Num ( ) ! = 1 | | SelectedItems [ 0 ] - > GetTreeItemType ( ) ! = IChangelistTreeItem : : UncontrolledChangelist )
{
return nullptr ;
}
else
{
return StaticCastSharedPtr < FUncontrolledChangelistTreeItem > ( SelectedItems [ 0 ] ) - > UncontrolledChangelistState ;
}
}
2021-01-18 09:42:33 -04:00
FSourceControlChangelistPtr SSourceControlChangelistsWidget : : GetCurrentChangelist ( )
{
FSourceControlChangelistStatePtr ChangelistState = GetCurrentChangelistState ( ) ;
return ChangelistState ? ( FSourceControlChangelistPtr ) ( ChangelistState - > GetChangelist ( ) ) : nullptr ;
}
2021-01-26 09:19:24 -04:00
FSourceControlChangelistStatePtr SSourceControlChangelistsWidget : : GetChangelistStateFromSelection ( )
2021-01-18 09:42:33 -04:00
{
if ( ! TreeView )
{
return nullptr ;
}
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
2021-01-26 09:19:24 -04:00
if ( SelectedItems . Num ( ) = = 0 | | SelectedItems [ 0 ] - > GetTreeItemType ( ) = = IChangelistTreeItem : : Invalid )
2021-01-18 09:42:33 -04:00
{
return nullptr ;
}
2021-01-26 09:19:24 -04:00
FChangelistTreeItemPtr Item = SelectedItems [ 0 ] ;
while ( Item & & Item - > GetTreeItemType ( ) ! = IChangelistTreeItem : : Invalid )
2021-01-18 09:42:33 -04:00
{
2021-01-26 09:19:24 -04:00
if ( Item - > GetTreeItemType ( ) = = IChangelistTreeItem : : Changelist )
return StaticCastSharedPtr < FChangelistTreeItem > ( Item ) - > ChangelistState ;
else
Item = Item - > GetParent ( ) ;
2021-01-18 09:42:33 -04:00
}
2021-01-26 09:19:24 -04:00
return nullptr ;
2021-01-18 09:42:33 -04:00
}
2021-01-26 09:19:24 -04:00
FSourceControlChangelistPtr SSourceControlChangelistsWidget : : GetChangelistFromSelection ( )
2021-01-18 09:42:33 -04:00
{
2021-01-26 09:19:24 -04:00
FSourceControlChangelistStatePtr ChangelistState = GetChangelistStateFromSelection ( ) ;
2021-01-18 09:42:33 -04:00
return ChangelistState ? ( FSourceControlChangelistPtr ) ( ChangelistState - > GetChangelist ( ) ) : nullptr ;
}
TArray < FString > SSourceControlChangelistsWidget : : GetSelectedFiles ( )
{
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
if ( SelectedItems . Num ( ) = = 0 | | SelectedItems [ 0 ] - > GetTreeItemType ( ) ! = IChangelistTreeItem : : File )
{
return TArray < FString > ( ) ;
}
else
{
TArray < FString > Files ;
2021-06-14 15:25:20 -04:00
2021-01-18 09:42:33 -04:00
for ( FChangelistTreeItemPtr Item : SelectedItems )
{
2021-06-14 15:25:20 -04:00
if ( Item - > GetTreeItemType ( ) ! = IChangelistTreeItem : : File )
{
continue ;
}
2021-01-18 09:42:33 -04:00
Files . Add ( StaticCastSharedPtr < FFileTreeItem > ( Item ) - > FileState - > GetFilename ( ) ) ;
}
return Files ;
}
}
2021-06-14 15:25:20 -04:00
void SSourceControlChangelistsWidget : : GetSelectedFiles ( TArray < FString > & OutControlledFiles , TArray < FString > & OutUncontrolledFiles )
{
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
for ( const FChangelistTreeItemPtr & Item : SelectedItems )
{
if ( Item - > GetTreeItemType ( ) ! = IChangelistTreeItem : : File )
{
continue ;
}
const FChangelistTreeItemPtr & Parent = Item - > GetParent ( ) ;
if ( ! Parent . IsValid ( ) )
{
continue ;
}
const FString & Filename = StaticCastSharedPtr < FFileTreeItem > ( Item ) - > FileState - > GetFilename ( ) ;
if ( Parent - > GetTreeItemType ( ) = = IChangelistTreeItem : : Changelist )
{
OutControlledFiles . Add ( Filename ) ;
}
else if ( Parent - > GetTreeItemType ( ) = = IChangelistTreeItem : : UncontrolledChangelist )
{
OutUncontrolledFiles . Add ( Filename ) ;
}
}
}
void SSourceControlChangelistsWidget : : GetSelectedFileStates ( TArray < FSourceControlStateRef > & OutControlledFileStates , TArray < FSourceControlStateRef > & OutUncontrolledFileStates )
{
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
for ( const FChangelistTreeItemPtr & Item : SelectedItems )
{
if ( Item - > GetTreeItemType ( ) ! = IChangelistTreeItem : : File )
{
continue ;
}
const FChangelistTreeItemPtr & Parent = Item - > GetParent ( ) ;
if ( ! Parent . IsValid ( ) )
{
continue ;
}
FSourceControlStateRef FileState = StaticCastSharedPtr < FFileTreeItem > ( Item ) - > FileState ;
if ( Parent - > GetTreeItemType ( ) = = IChangelistTreeItem : : Changelist )
{
OutControlledFileStates . Add ( MoveTemp ( FileState ) ) ;
}
else if ( Parent - > GetTreeItemType ( ) = = IChangelistTreeItem : : UncontrolledChangelist )
{
OutUncontrolledFileStates . Add ( MoveTemp ( FileState ) ) ;
}
}
}
2021-01-26 09:19:24 -04:00
TArray < FString > SSourceControlChangelistsWidget : : GetSelectedShelvedFiles ( )
{
TArray < FString > ShelvedFiles ;
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
if ( SelectedItems . Num ( ) > 0 )
{
if ( SelectedItems [ 0 ] - > GetTreeItemType ( ) = = IChangelistTreeItem : : ShelvedChangelist )
{
check ( SelectedItems . Num ( ) = = 1 ) ;
const TArray < FChangelistTreeItemPtr > & ShelvedChildren = SelectedItems [ 0 ] - > GetChildren ( ) ;
for ( FChangelistTreeItemPtr Item : ShelvedChildren )
{
ShelvedFiles . Add ( StaticCastSharedPtr < FShelvedFileTreeItem > ( Item ) - > FileState - > GetFilename ( ) ) ;
}
}
else if ( SelectedItems [ 0 ] - > GetTreeItemType ( ) = = IChangelistTreeItem : : ShelvedFile )
{
for ( FChangelistTreeItemPtr Item : SelectedItems )
{
ShelvedFiles . Add ( StaticCastSharedPtr < FShelvedFileTreeItem > ( Item ) - > FileState - > GetFilename ( ) ) ;
}
}
}
return ShelvedFiles ;
}
2021-06-14 15:25:20 -04:00
bool SSourceControlChangelistsWidget : : IsParentOfSelection ( const IChangelistTreeItem : : TreeItemType ParentType ) const
{
return Algo : : AnyOf ( TreeView - > GetSelectedItems ( ) , [ ParentType = ParentType ] ( const FChangelistTreeItemPtr & Item )
{
IChangelistTreeItem : : TreeItemType ItemType = Item - > GetTreeItemType ( ) ;
if ( ItemType = = ParentType )
{
return true ;
}
else if ( ( ItemType = = IChangelistTreeItem : : File ) | | ( ItemType = = IChangelistTreeItem : : ShelvedChangelist ) )
{
const FChangelistTreeItemPtr & Parent = Item - > GetParent ( ) ;
return Parent . IsValid ( ) & & ( Parent - > GetTreeItemType ( ) = = ParentType ) ;
}
else if ( ItemType = = IChangelistTreeItem : : ShelvedFile )
{
const FChangelistTreeItemPtr & Parent = Item - > GetParent ( ) ;
if ( Parent . IsValid ( ) )
{
const FChangelistTreeItemPtr & GrandParent = Parent - > GetParent ( ) ;
return GrandParent . IsValid ( ) & & ( GrandParent - > GetTreeItemType ( ) = = ParentType ) ;
}
}
return false ;
} ) ;
}
2021-01-18 09:42:33 -04:00
void SSourceControlChangelistsWidget : : OnNewChangelist ( )
{
FText ChangelistDescription ;
bool bOk = GetChangelistDescription (
nullptr ,
LOCTEXT ( " SourceControl.Changelist.New.Title " , " New Changelist... " ) ,
LOCTEXT ( " SourceControl.Changelist.New.Label " , " Enter a description for the changelist: " ) ,
ChangelistDescription ) ;
if ( ! bOk )
{
return ;
}
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
auto NewChangelistOperation = ISourceControlOperation : : Create < FNewChangelist > ( ) ;
NewChangelistOperation - > SetDescription ( ChangelistDescription ) ;
SourceControlProvider . Execute ( NewChangelistOperation ) ;
}
void SSourceControlChangelistsWidget : : OnDeleteChangelist ( )
{
if ( GetCurrentChangelist ( ) = = nullptr )
{
return ;
}
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FDeleteChangelist > ( ) , GetCurrentChangelist ( ) ) ;
}
bool SSourceControlChangelistsWidget : : CanDeleteChangelist ( )
{
FSourceControlChangelistStatePtr Changelist = GetCurrentChangelistState ( ) ;
return Changelist ! = nullptr & & Changelist - > GetFilesStates ( ) . Num ( ) = = 0 & & Changelist - > GetShelvedFilesStates ( ) . Num ( ) = = 0 ;
}
void SSourceControlChangelistsWidget : : OnEditChangelist ( )
{
FSourceControlChangelistStatePtr ChangelistState = GetCurrentChangelistState ( ) ;
if ( ChangelistState = = nullptr )
{
return ;
}
FText NewChangelistDescription = ChangelistState - > GetDescriptionText ( ) ;
bool bOk = GetChangelistDescription (
nullptr ,
2022-03-04 16:10:23 -05:00
LOCTEXT ( " SourceControl.Changelist.New.Title2 " , " Edit Changelist... " ) ,
LOCTEXT ( " SourceControl.Changelist.New.Label2 " , " Enter a new description for the changelist: " ) ,
2021-01-18 09:42:33 -04:00
NewChangelistDescription ) ;
if ( ! bOk )
{
return ;
}
2021-04-19 11:21:23 -04:00
EditChangelistDescription ( NewChangelistDescription , ChangelistState ) ;
2021-01-18 09:42:33 -04:00
}
void SSourceControlChangelistsWidget : : OnRevertUnchanged ( )
{
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
auto RevertUnchangedOperation = ISourceControlOperation : : Create < FRevertUnchanged > ( ) ;
2021-01-26 09:19:24 -04:00
SourceControlProvider . Execute ( RevertUnchangedOperation , GetChangelistFromSelection ( ) , GetSelectedFiles ( ) ) ;
2021-01-18 09:42:33 -04:00
}
2021-01-27 16:11:25 -04:00
bool SSourceControlChangelistsWidget : : CanRevertUnchanged ( )
{
return GetSelectedFiles ( ) . Num ( ) > 0 | | ( GetCurrentChangelistState ( ) & & GetCurrentChangelistState ( ) - > GetFilesStates ( ) . Num ( ) > 0 ) ;
}
2021-01-19 14:50:23 -04:00
void SSourceControlChangelistsWidget : : OnRevert ( )
{
2021-01-20 09:51:23 -04:00
FText DialogText ;
FText DialogTitle ;
2021-01-19 14:50:23 -04:00
2021-01-20 09:51:23 -04:00
const bool bApplyOnChangelist = ( GetCurrentChangelist ( ) ! = nullptr ) ;
if ( bApplyOnChangelist )
{
DialogText = LOCTEXT ( " SourceControl_ConfirmRevertChangelist " , " Are you sure you want to revert this changelist? " ) ;
DialogTitle = LOCTEXT ( " SourceControl_ConfirmRevertChangelist_Title " , " Confirm changelist revert " ) ;
}
else
{
DialogText = LOCTEXT ( " SourceControl_ConfirmRevertFiles " , " Are you sure you want to revert the selected files? " ) ;
DialogTitle = LOCTEXT ( " SourceControl_ConfirmReverFiles_Title " , " Confirm files revert " ) ;
}
EAppReturnType : : Type UserConfirmation = FMessageDialog : : Open ( EAppMsgType : : OkCancel , EAppReturnType : : Ok , DialogText , & DialogTitle ) ;
if ( UserConfirmation ! = EAppReturnType : : Ok )
{
return ;
}
2021-06-14 15:25:20 -04:00
TArray < FString > SelectedControlledFiles ;
TArray < FString > SelectedUncontrolledFiles ;
GetSelectedFiles ( SelectedControlledFiles , SelectedUncontrolledFiles ) ;
FSourceControlChangelistPtr SelectedChangelist = GetChangelistFromSelection ( ) ;
2021-01-20 09:51:23 -04:00
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2021-06-14 15:25:20 -04:00
// Reverts the selected Changelist or Files
2022-08-18 13:03:11 -04:00
if ( SelectedChangelist . IsValid ( ) )
2021-06-14 15:25:20 -04:00
{
2022-08-18 13:03:11 -04:00
TSet < FString > ToRevertFiles ;
FSourceControlChangelistStatePtr ChangelistState ;
ChangelistState = SourceControlProvider . GetState ( SelectedChangelist . ToSharedRef ( ) , EStateCacheUsage : : Use ) ;
if ( ChangelistState . IsValid ( ) )
2022-02-10 17:08:14 -05:00
{
2022-08-18 13:03:11 -04:00
Algo : : Transform ( ChangelistState - > GetFilesStates ( ) , ToRevertFiles , [ ] ( FSourceControlStateRef FileState )
2022-02-10 17:08:14 -05:00
{
2022-08-18 13:03:11 -04:00
return FileState - > GetFilename ( ) ;
} ) ;
}
// Enforce unique occurences of files.
ToRevertFiles . Append ( SelectedControlledFiles ) ;
SelectedControlledFiles = ToRevertFiles . Array ( ) ;
}
if ( ! SelectedControlledFiles . IsEmpty ( ) )
{
SourceControlHelpers : : RevertAndReloadPackages ( SelectedControlledFiles ) ;
2021-06-14 15:25:20 -04:00
}
FUncontrolledChangelistStatePtr SelectedUncontrolledChangelist = GetCurrentUncontrolledChangelistState ( ) ;
// Reverts the selected Uncontrolled Changelist
if ( SelectedUncontrolledChangelist . IsValid ( ) )
{
Algo : : Transform ( SelectedUncontrolledChangelist - > GetFilesStates ( ) , SelectedUncontrolledFiles , [ ] ( const FSourceControlStateRef & State ) { return State - > GetFilename ( ) ; } ) ;
2021-07-23 20:21:53 -04:00
}
2021-06-14 15:25:20 -04:00
2021-07-23 20:21:53 -04:00
// Reverts selected Uncontrolled Files
if ( ! SelectedUncontrolledFiles . IsEmpty ( ) )
{
2022-08-12 11:43:42 -04:00
FUncontrolledChangelistsModule : : Get ( ) . OnRevert ( SelectedUncontrolledFiles ) ;
2021-06-14 15:25:20 -04:00
}
2021-01-26 09:19:24 -04:00
}
2021-01-19 14:50:23 -04:00
2021-01-27 16:11:25 -04:00
bool SSourceControlChangelistsWidget : : CanRevert ( )
{
2021-06-14 15:25:20 -04:00
FSourceControlChangelistStatePtr CurrentChangelistState = GetCurrentChangelistState ( ) ;
FUncontrolledChangelistStatePtr CurrentUncontrolledChangelistState = GetCurrentUncontrolledChangelistState ( ) ;
return GetSelectedFiles ( ) . Num ( ) > 0
| | ( CurrentChangelistState . IsValid ( ) & & CurrentChangelistState - > GetFilesStates ( ) . Num ( ) > 0 )
| | ( CurrentUncontrolledChangelistState . IsValid ( ) & & CurrentUncontrolledChangelistState - > GetFilesStates ( ) . Num ( ) > 0 ) ;
2021-01-27 16:11:25 -04:00
}
2021-01-26 09:19:24 -04:00
void SSourceControlChangelistsWidget : : OnShelve ( )
{
2021-02-08 15:32:48 -04:00
FSourceControlChangelistStatePtr CurrentChangelist = GetChangelistStateFromSelection ( ) ;
if ( ! CurrentChangelist )
{
return ;
}
FText ChangelistDescription = CurrentChangelist - > GetDescriptionText ( ) ;
if ( ChangelistDescription . IsEmptyOrWhitespace ( ) )
{
bool bOk = GetChangelistDescription (
nullptr ,
LOCTEXT ( " SourceControl.Changelist.NewShelve " , " Shelving files... " ) ,
LOCTEXT ( " SourceControl.Changelist.NewShelve.Label " , " Enter a description for the changelist holding the shelve: " ) ,
ChangelistDescription ) ;
if ( ! bOk )
{
// User cancelled entering a changelist description; abort shelve
return ;
}
}
2021-01-26 09:19:24 -04:00
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
auto ShelveOperation = ISourceControlOperation : : Create < FShelve > ( ) ;
2021-02-08 15:32:48 -04:00
ShelveOperation - > SetDescription ( ChangelistDescription ) ;
SourceControlProvider . Execute ( ShelveOperation , CurrentChangelist - > GetChangelist ( ) , GetSelectedFiles ( ) ) ;
2021-01-26 09:19:24 -04:00
}
2021-01-19 14:50:23 -04:00
2021-01-26 09:19:24 -04:00
void SSourceControlChangelistsWidget : : OnUnshelve ( )
{
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
auto UnshelveOperation = ISourceControlOperation : : Create < FUnshelve > ( ) ;
SourceControlProvider . Execute ( UnshelveOperation , GetChangelistFromSelection ( ) , GetSelectedShelvedFiles ( ) ) ;
}
void SSourceControlChangelistsWidget : : OnDeleteShelvedFiles ( )
{
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
auto DeleteShelvedOperation = ISourceControlOperation : : Create < FDeleteShelved > ( ) ;
SourceControlProvider . Execute ( DeleteShelvedOperation , GetChangelistFromSelection ( ) , GetSelectedShelvedFiles ( ) ) ;
2021-01-19 14:50:23 -04:00
}
2022-08-08 09:19:30 -04:00
static bool GetChangelistValidationResult ( FSourceControlChangelistPtr InChangelist , FString & OutValidationTitleText , FString & OutValidationWarningsText , FString & OutValidationErrorsText )
2021-02-04 11:50:49 -04:00
{
FSourceControlPreSubmitDataValidationDelegate ValidationDelegate = ISourceControlModule : : Get ( ) . GetRegisteredPreSubmitDataValidation ( ) ;
EDataValidationResult ValidationResult = EDataValidationResult : : NotValidated ;
TArray < FText > ValidationErrors ;
TArray < FText > ValidationWarnings ;
2021-03-10 15:03:45 -04:00
bool bValidationResult = true ;
2021-02-04 11:50:49 -04:00
if ( ValidationDelegate . ExecuteIfBound ( InChangelist , ValidationResult , ValidationErrors , ValidationWarnings ) )
{
2021-08-11 15:40:41 -04:00
EMessageSeverity : : Type MessageSeverity = EMessageSeverity : : Info ;
2021-02-04 11:50:49 -04:00
if ( ValidationResult = = EDataValidationResult : : Invalid | | ValidationErrors . Num ( ) > 0 )
{
2022-08-08 09:19:30 -04:00
OutValidationTitleText = LOCTEXT ( " SourceControl.Submit.ChangelistValidationError " , " Changelist validation failed! " ) . ToString ( ) ;
2021-03-10 15:03:45 -04:00
bValidationResult = false ;
2021-08-11 15:40:41 -04:00
MessageSeverity = EMessageSeverity : : Error ;
2021-02-04 11:50:49 -04:00
}
else if ( ValidationResult = = EDataValidationResult : : NotValidated | | ValidationWarnings . Num ( ) > 0 )
{
2022-08-08 09:19:30 -04:00
OutValidationTitleText = LOCTEXT ( " SourceControl.Submit.ChangelistValidationWarning " , " Changelist validation has warnings! " ) . ToString ( ) ;
2021-08-11 15:40:41 -04:00
MessageSeverity = EMessageSeverity : : Warning ;
2021-02-04 11:50:49 -04:00
}
else
{
2022-08-08 09:19:30 -04:00
OutValidationTitleText = LOCTEXT ( " SourceControl.Submit.ChangelistValidationSuccess " , " Changelist validation successful! " ) . ToString ( ) ;
2021-02-04 11:50:49 -04:00
}
2021-08-11 15:40:41 -04:00
FMessageLog SourceControlLog ( " SourceControl " ) ;
2022-08-08 09:19:30 -04:00
SourceControlLog . Message ( MessageSeverity , FText : : FromString ( * OutValidationTitleText ) ) ;
2021-02-04 11:50:49 -04:00
2022-08-08 09:19:30 -04:00
auto AppendInfo = [ ] ( const TArray < FText > & Info , const FString & InfoType , FString & OutText )
2021-03-10 15:03:45 -04:00
{
2021-02-04 11:50:49 -04:00
const int32 MaxNumLinesDisplayed = 5 ;
2022-08-08 09:19:30 -04:00
int32 NumLinesDisplayed = 0 ;
2021-02-04 11:50:49 -04:00
if ( Info . Num ( ) > 0 )
{
2022-08-08 09:19:30 -04:00
OutText + = LINE_TERMINATOR ;
OutText + = FString : : Printf ( TEXT ( " Encountered %d %s: " ) , Info . Num ( ) , * InfoType ) ;
2021-02-04 11:50:49 -04:00
for ( const FText & Line : Info )
{
if ( NumLinesDisplayed > = MaxNumLinesDisplayed )
{
2022-08-08 09:19:30 -04:00
OutText + = LINE_TERMINATOR ;
OutText + = FString : : Printf ( TEXT ( " See log for complete list of %s " ) , * InfoType ) ;
2021-02-04 11:50:49 -04:00
break ;
}
2022-08-08 09:19:30 -04:00
OutText + = LINE_TERMINATOR ;
OutText + = Line . ToString ( ) ;
2021-02-04 11:50:49 -04:00
+ + NumLinesDisplayed ;
}
}
} ;
2021-08-11 15:40:41 -04:00
auto LogInfo = [ & SourceControlLog ] ( const TArray < FText > & Info , const FString & InfoType , const EMessageSeverity : : Type LogVerbosity )
2021-03-10 15:03:45 -04:00
{
if ( Info . Num ( ) > 0 )
{
2021-08-11 15:40:41 -04:00
SourceControlLog . Message ( LogVerbosity , FText : : Format ( LOCTEXT ( " SourceControl.Validation.ErrorEncountered " , " Encountered {0} {1}: " ) , FText : : AsNumber ( Info . Num ( ) ) , FText : : FromString ( * InfoType ) ) ) ;
2021-03-10 15:03:45 -04:00
for ( const FText & Line : Info )
{
2021-08-11 15:40:41 -04:00
SourceControlLog . Message ( LogVerbosity , Line ) ;
2021-03-10 15:03:45 -04:00
}
}
} ;
2022-08-08 09:19:30 -04:00
AppendInfo ( ValidationErrors , TEXT ( " errors " ) , OutValidationErrorsText ) ;
AppendInfo ( ValidationWarnings , TEXT ( " warnings " ) , OutValidationWarningsText ) ;
2021-03-10 15:03:45 -04:00
2021-08-11 15:40:41 -04:00
LogInfo ( ValidationErrors , TEXT ( " errors " ) , EMessageSeverity : : Error ) ;
LogInfo ( ValidationWarnings , TEXT ( " warnings " ) , EMessageSeverity : : Warning ) ;
2021-02-04 11:50:49 -04:00
}
2021-03-10 15:03:45 -04:00
return bValidationResult ;
2021-02-04 11:50:49 -04:00
}
2021-10-27 15:14:40 -04:00
static bool GetOnPresubmitResult ( FSourceControlChangelistStatePtr Changelist , FChangeListDescription & Description )
{
const TArray < FSourceControlStateRef > & FileStates = Changelist - > GetFilesStates ( ) ;
TArray < FString > LocalFilepathList ;
LocalFilepathList . Reserve ( FileStates . Num ( ) ) ;
for ( const FSourceControlStateRef & State : FileStates )
{
LocalFilepathList . Add ( State - > GetFilename ( ) ) ;
}
2022-07-21 08:31:47 -04:00
FText FailureMsg ;
if ( ! TryToVirtualizeFilesToSubmit ( LocalFilepathList , Description . Description , FailureMsg ) )
2021-10-27 15:14:40 -04:00
{
2022-07-21 08:31:47 -04:00
// Setup the notification for operation feedback
FNotificationInfo Info ( FailureMsg ) ;
2022-07-15 09:52:19 -04:00
2022-07-21 08:31:47 -04:00
Info . Text = LOCTEXT ( " SCC_Checkin_Failed " , " Failed to check in files! " ) ;
Info . ExpireDuration = 8.0f ;
Info . HyperlinkText = LOCTEXT ( " SCC_Checkin_ShowLog " , " Show Message Log " ) ;
Info . Hyperlink = FSimpleDelegate : : CreateLambda ( [ ] ( ) { FMessageLog ( " SourceControl " ) . Open ( EMessageSeverity : : Error , true ) ; } ) ;
2022-07-15 09:52:19 -04:00
2022-07-21 08:31:47 -04:00
TSharedPtr < SNotificationItem > Notification = FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
Notification - > SetCompletionState ( SNotificationItem : : CS_Fail ) ;
2021-10-27 15:14:40 -04:00
2022-07-21 08:31:47 -04:00
return false ;
2021-10-27 15:14:40 -04:00
}
return true ;
}
2021-01-18 09:42:33 -04:00
void SSourceControlChangelistsWidget : : OnSubmitChangelist ( )
{
2021-01-27 16:11:25 -04:00
FSourceControlChangelistStatePtr ChangelistState = GetCurrentChangelistState ( ) ;
2021-01-18 09:42:33 -04:00
2021-01-27 16:11:25 -04:00
if ( ! ChangelistState )
2021-01-18 09:42:33 -04:00
{
return ;
}
2022-08-08 09:19:30 -04:00
FString ChangelistValidationTitle ;
FString ChangelistValidationWarningsText ;
FString ChangelistValidationErrorsText ;
bool bValidationResult = GetChangelistValidationResult ( ChangelistState - > GetChangelist ( ) , ChangelistValidationTitle , ChangelistValidationWarningsText , ChangelistValidationErrorsText ) ;
2021-01-18 09:42:33 -04:00
2021-02-04 11:50:49 -04:00
// Build list of states for the dialog
2021-04-19 11:21:23 -04:00
const FText OriginalChangelistDescription = ChangelistState - > GetDescriptionText ( ) ;
const bool bAskForChangelistDescription = ( OriginalChangelistDescription . IsEmptyOrWhitespace ( ) ) ;
2021-04-26 09:23:26 -04:00
FText ChangelistDescriptionToSubmit = UpdateChangelistDescriptionToSubmitIfNeeded ( bValidationResult , OriginalChangelistDescription ) ;
2021-01-20 09:51:23 -04:00
2021-02-04 11:50:49 -04:00
TSharedRef < SWindow > NewWindow = SNew ( SWindow )
. Title ( NSLOCTEXT ( " SourceControl.ConfirmSubmit " , " Title " , " Confirm changelist submit " ) )
. SizingRule ( ESizingRule : : UserSized )
. ClientSize ( FVector2D ( 600 , 400 ) )
. SupportsMaximize ( true )
. SupportsMinimize ( false ) ;
TSharedRef < SSourceControlSubmitWidget > SourceControlWidget =
SNew ( SSourceControlSubmitWidget )
. ParentWindow ( NewWindow )
. Items ( ChangelistState - > GetFilesStates ( ) )
2021-04-19 11:21:23 -04:00
. Description ( ChangelistDescriptionToSubmit )
2022-08-08 09:19:30 -04:00
. ChangeValidationResult ( ChangelistValidationTitle )
. ChangeValidationWarnings ( ChangelistValidationWarningsText )
. ChangeValidationErrors ( ChangelistValidationErrorsText )
2021-02-04 11:50:49 -04:00
. AllowDescriptionChange ( bAskForChangelistDescription )
. AllowUncheckFiles ( false )
2021-03-10 15:03:45 -04:00
. AllowKeepCheckedOut ( false )
. AllowSubmit ( bValidationResult ) ;
2021-02-04 11:50:49 -04:00
NewWindow - > SetContent (
SourceControlWidget
) ;
FSlateApplication : : Get ( ) . AddModalWindow ( NewWindow , NULL ) ;
if ( SourceControlWidget - > GetResult ( ) = = ESubmitResults : : SUBMIT_ACCEPTED )
2021-01-20 09:51:23 -04:00
{
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2021-04-26 09:23:26 -04:00
FChangeListDescription Description ;
2021-01-20 09:51:23 -04:00
auto SubmitChangelistOperation = ISourceControlOperation : : Create < FCheckIn > ( ) ;
2021-04-06 14:20:24 -04:00
bool bCheckinSuccess = false ;
2021-01-20 09:51:23 -04:00
2021-04-26 09:23:26 -04:00
SourceControlWidget - > FillChangeListDescription ( Description ) ;
2021-02-04 11:50:49 -04:00
2021-10-27 15:14:40 -04:00
// Check if any of the presubmit hooks fail and if so early out to avoid the submit
if ( ! GetOnPresubmitResult ( ChangelistState , Description ) )
{
return ;
}
2021-04-26 09:23:26 -04:00
// If the description was modified, we add it to the operation to update the changelist
if ( ! OriginalChangelistDescription . EqualTo ( Description . Description ) )
{
2021-02-04 11:50:49 -04:00
SubmitChangelistOperation - > SetDescription ( Description . Description ) ;
2021-01-27 16:11:25 -04:00
}
2021-04-06 14:20:24 -04:00
bCheckinSuccess = SourceControlProvider . Execute ( SubmitChangelistOperation , ChangelistState - > GetChangelist ( ) ) = = ECommandResult : : Succeeded ;
// Setup the notification for operation feedback
FNotificationInfo Info ( SubmitChangelistOperation - > GetSuccessMessage ( ) ) ;
// Override the notification fields for failure ones
if ( ! bCheckinSuccess )
{
Info . Text = LOCTEXT ( " SCC_Checkin_Failed " , " Failed to check in files! " ) ;
}
Info . ExpireDuration = 8.0f ;
Info . HyperlinkText = LOCTEXT ( " SCC_Checkin_ShowLog " , " Show Message Log " ) ;
Info . Hyperlink = FSimpleDelegate : : CreateLambda ( [ ] ( ) { FMessageLog ( " SourceControl " ) . Open ( EMessageSeverity : : Info , true ) ; } ) ;
2021-08-11 15:40:41 -04:00
TSharedPtr < SNotificationItem > Notification = FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
Notification - > SetCompletionState ( bCheckinSuccess ? SNotificationItem : : CS_Success : SNotificationItem : : CS_Fail ) ;
2021-01-20 09:51:23 -04:00
}
2021-04-19 11:21:23 -04:00
}
2021-04-26 09:23:26 -04:00
FText SSourceControlChangelistsWidget : : UpdateChangelistDescriptionToSubmitIfNeeded ( const bool bInValidationResult , const FText & InOriginalChangelistDescription ) const
2021-04-19 11:21:23 -04:00
{
2022-01-31 17:03:09 -05:00
if ( bInValidationResult & & USourceControlPreferences : : IsValidationTagEnabled ( ) & & ( ! HasValidationTag ( InOriginalChangelistDescription ) ) )
2021-04-19 11:21:23 -04:00
{
FStringOutputDevice Str ;
Str . SetAutoEmitLineTerminator ( true ) ;
Str . Log ( InOriginalChangelistDescription ) ;
Str . Log ( ChangelistValidatedTag ) ;
FText ChangelistDescription = FText : : FromString ( Str ) ;
return ChangelistDescription ;
}
return InOriginalChangelistDescription ;
2021-01-18 09:42:33 -04:00
}
bool SSourceControlChangelistsWidget : : CanSubmitChangelist ( )
{
FSourceControlChangelistStatePtr Changelist = GetCurrentChangelistState ( ) ;
2021-01-27 16:11:25 -04:00
return Changelist ! = nullptr & & Changelist - > GetFilesStates ( ) . Num ( ) > 0 & & Changelist - > GetShelvedFilesStates ( ) . Num ( ) = = 0 ;
2021-01-18 09:42:33 -04:00
}
2021-08-11 15:40:41 -04:00
void SSourceControlChangelistsWidget : : OnValidateChangelist ( )
{
FSourceControlChangelistStatePtr ChangelistState = GetCurrentChangelistState ( ) ;
if ( ! ChangelistState )
{
return ;
}
2022-08-08 09:19:30 -04:00
FString ChangelistValidationTitle ;
FString ChangelistValidationWarningsText ;
FString ChangelistValidationErrorsText ;
bool bValidationResult = GetChangelistValidationResult ( ChangelistState - > GetChangelist ( ) , ChangelistValidationTitle , ChangelistValidationWarningsText , ChangelistValidationErrorsText ) ;
2021-08-11 15:40:41 -04:00
// Setup the notification for operation feedback
FNotificationInfo Info ( LOCTEXT ( " SCC_Validation_Success " , " Changelist validated " ) ) ;
// Override the notification fields for failure ones
if ( ! bValidationResult )
{
Info . Text = LOCTEXT ( " SCC_Validation_Failed " , " Failed to validate the changelist " ) ;
}
Info . ExpireDuration = 8.0f ;
Info . HyperlinkText = LOCTEXT ( " SCC_Validation_ShowLog " , " Show Message Log " ) ;
Info . Hyperlink = FSimpleDelegate : : CreateLambda ( [ ] ( ) { FMessageLog ( " SourceControl " ) . Open ( EMessageSeverity : : Info , true ) ; } ) ;
TSharedPtr < SNotificationItem > Notification = FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
Notification - > SetCompletionState ( bValidationResult ? SNotificationItem : : CS_Success : SNotificationItem : : CS_Fail ) ;
}
bool SSourceControlChangelistsWidget : : CanValidateChangelist ( )
{
FSourceControlChangelistStatePtr Changelist = GetCurrentChangelistState ( ) ;
return Changelist ! = nullptr & & Changelist - > GetFilesStates ( ) . Num ( ) > 0 ;
}
2021-03-24 08:29:57 -04:00
void SSourceControlChangelistsWidget : : OnMoveFiles ( )
{
2021-06-14 15:25:20 -04:00
TArray < FString > SelectedControlledFiles ;
TArray < FString > SelectedUncontrolledFiles ;
GetSelectedFiles ( SelectedControlledFiles , SelectedUncontrolledFiles ) ;
2021-03-24 08:29:57 -04:00
2021-06-14 15:25:20 -04:00
if ( SelectedControlledFiles . IsEmpty ( ) & & SelectedUncontrolledFiles . IsEmpty ( ) )
2021-03-24 08:29:57 -04:00
{
return ;
}
const bool bAddNewChangelistEntry = true ;
// Build selection list for changelists
TArray < SSourceControlDescriptionItem > Items ;
Items . Reset ( ChangelistsNodes . Num ( ) + ( bAddNewChangelistEntry ? 1 : 0 ) ) ;
if ( bAddNewChangelistEntry )
{
// First is always new changelist
Items . Emplace (
LOCTEXT ( " SourceControl_NewChangelistText " , " New Changelist " ) ,
LOCTEXT ( " SourceControl_NewChangelistDescription " , " <enter description here> " ) ,
/*bCanEditDescription=*/ true ) ;
}
const bool bCanEditAlreadyExistingChangelistDescription = false ;
for ( FChangelistTreeItemPtr Changelist : ChangelistsNodes )
{
2021-06-14 15:25:20 -04:00
if ( ! Changelist )
2021-03-24 08:29:57 -04:00
{
continue ;
}
2021-06-14 15:25:20 -04:00
if ( Changelist - > GetTreeItemType ( ) = = IChangelistTreeItem : : Changelist )
{
const auto & TypedChangelist = StaticCastSharedPtr < FChangelistTreeItem > ( Changelist ) ;
Items . Emplace ( TypedChangelist - > GetDisplayText ( ) , TypedChangelist - > GetDescriptionText ( ) , bCanEditAlreadyExistingChangelistDescription ) ;
}
else if ( Changelist - > GetTreeItemType ( ) = = IChangelistTreeItem : : UncontrolledChangelist )
{
const FUncontrolledChangelistTreeItemPtr & TypedChangelist = StaticCastSharedPtr < FUncontrolledChangelistTreeItem > ( Changelist ) ;
Items . Emplace ( TypedChangelist - > GetDisplayText ( ) , TypedChangelist - > GetDescriptionText ( ) , bCanEditAlreadyExistingChangelistDescription ) ;
}
2021-03-24 08:29:57 -04:00
}
int32 PickedItem = 0 ;
FText ChangelistDescription ;
bool bOk = PickChangelistOrNewWithDescription (
nullptr ,
LOCTEXT ( " SourceControl.MoveFiles.Title " , " Move Files To... " ) ,
LOCTEXT ( " SourceControl.MoveFIles.Label " , " Target Changelist: " ) ,
Items ,
PickedItem ,
ChangelistDescription ) ;
if ( ! bOk )
{
return ;
}
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
// Create new changelist
if ( bAddNewChangelistEntry & & PickedItem = = 0 )
{
auto NewChangelistOperation = ISourceControlOperation : : Create < FNewChangelist > ( ) ;
NewChangelistOperation - > SetDescription ( ChangelistDescription ) ;
2021-06-14 15:25:20 -04:00
SourceControlProvider . Execute ( NewChangelistOperation , SelectedControlledFiles ) ;
if ( ( ! SelectedUncontrolledFiles . IsEmpty ( ) ) & & NewChangelistOperation - > GetNewChangelist ( ) . IsValid ( ) )
{
FUncontrolledChangelistsModule : : Get ( ) . MoveFilesToControlledChangelist ( SelectedUncontrolledFiles , NewChangelistOperation - > GetNewChangelist ( ) ) ;
}
2021-03-24 08:29:57 -04:00
}
else
{
const int32 ChangelistIndex = ( bAddNewChangelistEntry ? PickedItem - 1 : PickedItem ) ;
2021-06-14 15:25:20 -04:00
const FChangelistTreeItemPtr & SelectedItem = ChangelistsNodes [ ChangelistIndex ] ;
if ( SelectedItem - > GetTreeItemType ( ) = = IChangelistTreeItem : : Changelist )
{
FSourceControlChangelistPtr Changelist = StaticCastSharedPtr < FChangelistTreeItem > ( SelectedItem ) - > ChangelistState - > GetChangelist ( ) ;
if ( ! SelectedControlledFiles . IsEmpty ( ) )
{
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FMoveToChangelist > ( ) , Changelist , SelectedControlledFiles ) ;
}
if ( ! SelectedUncontrolledFiles . IsEmpty ( ) )
{
FUncontrolledChangelistsModule : : Get ( ) . MoveFilesToControlledChangelist ( SelectedUncontrolledFiles , Changelist ) ;
}
}
else if ( SelectedItem - > GetTreeItemType ( ) = = IChangelistTreeItem : : UncontrolledChangelist )
{
const FUncontrolledChangelist UncontrolledChangelist = StaticCastSharedPtr < FUncontrolledChangelistTreeItem > ( SelectedItem ) - > UncontrolledChangelistState - > Changelist ;
TArray < FSourceControlStateRef > SelectedControlledFileStates ;
TArray < FSourceControlStateRef > SelectedUnControlledFileStates ;
GetSelectedFileStates ( SelectedControlledFileStates , SelectedUnControlledFileStates ) ;
if ( ( ! SelectedControlledFileStates . IsEmpty ( ) ) | | ( ! SelectedUnControlledFileStates . IsEmpty ( ) ) )
{
FUncontrolledChangelistsModule : : Get ( ) . MoveFilesToUncontrolledChangelist ( SelectedControlledFileStates , SelectedUnControlledFileStates , UncontrolledChangelist ) ;
}
}
2021-03-24 08:29:57 -04:00
}
}
2021-01-19 14:50:23 -04:00
void SSourceControlChangelistsWidget : : OnLocateFile ( )
2021-04-06 14:20:24 -04:00
{
2021-01-22 16:21:29 -04:00
TArray < FAssetData > AssetsToSync ;
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
2021-01-19 14:50:23 -04:00
2021-01-22 16:21:29 -04:00
for ( const FChangelistTreeItemPtr & SelectedItem : SelectedItems )
2021-01-19 14:50:23 -04:00
{
2021-01-22 16:21:29 -04:00
if ( SelectedItem - > GetTreeItemType ( ) = = IChangelistTreeItem : : File )
2021-01-19 14:50:23 -04:00
{
2021-11-12 10:23:14 -05:00
const FAssetDataArrayPtr & Assets = StaticCastSharedPtr < FFileTreeItem > ( SelectedItem ) - > GetAssetData ( ) ;
if ( Assets . IsValid ( ) )
{
AssetsToSync . Append ( * Assets ) ;
}
2021-01-19 14:50:23 -04:00
}
}
if ( AssetsToSync . Num ( ) > 0 )
{
FContentBrowserModule & ContentBrowserModule = FModuleManager : : Get ( ) . LoadModuleChecked < FContentBrowserModule > ( " ContentBrowser " ) ;
ContentBrowserModule . Get ( ) . SyncBrowserToAssets ( AssetsToSync , true ) ;
}
}
bool SSourceControlChangelistsWidget : : CanLocateFile ( )
{
2021-04-06 16:11:32 -04:00
TArray < FChangelistTreeItemPtr > SelectedItems = TreeView - > GetSelectedItems ( ) ;
auto HasAssetData = [ ] ( const FChangelistTreeItemPtr & SelectedItem )
{
2021-11-12 10:23:14 -05:00
if ( SelectedItem - > GetTreeItemType ( ) ! = IChangelistTreeItem : : File )
{
return false ;
}
const FAssetDataArrayPtr & Assets = StaticCastSharedPtr < FFileTreeItem > ( SelectedItem ) - > GetAssetData ( ) ;
return ( Assets . IsValid ( ) & & Assets - > Num ( ) > 0 ) ;
2021-04-06 16:11:32 -04:00
} ;
// Checks if at least one selected item has asset data (ie: accessible from ContentBrowser)
return SelectedItems . FindByPredicate ( HasAssetData ) ! = nullptr ;
2021-01-19 14:50:23 -04:00
}
void SSourceControlChangelistsWidget : : OnShowHistory ( )
{
TArray < FString > SelectedFiles = GetSelectedFiles ( ) ;
if ( SelectedFiles . Num ( ) > 0 )
{
FSourceControlWindows : : DisplayRevisionHistory ( SelectedFiles ) ;
}
}
void SSourceControlChangelistsWidget : : OnDiffAgainstDepot ( )
{
TArray < FString > SelectedFiles = GetSelectedFiles ( ) ;
if ( SelectedFiles . Num ( ) > 0 )
{
FSourceControlWindows : : DiffAgainstWorkspace ( SelectedFiles [ 0 ] ) ;
}
}
bool SSourceControlChangelistsWidget : : CanDiffAgainstDepot ( )
{
return GetSelectedFiles ( ) . Num ( ) = = 1 ;
}
2021-01-26 09:19:24 -04:00
void SSourceControlChangelistsWidget : : OnDiffAgainstWorkspace ( )
{
2021-02-08 09:36:20 -04:00
if ( GetSelectedShelvedFiles ( ) . Num ( ) > 0 )
{
FSourceControlStateRef FileState = StaticCastSharedPtr < FShelvedFileTreeItem > ( TreeView - > GetSelectedItems ( ) [ 0 ] ) - > FileState ;
FSourceControlWindows : : DiffAgainstShelvedFile ( FileState ) ;
}
2021-01-26 09:19:24 -04:00
}
bool SSourceControlChangelistsWidget : : CanDiffAgainstWorkspace ( )
{
return GetSelectedShelvedFiles ( ) . Num ( ) = = 1 ;
}
2021-01-18 09:42:33 -04:00
TSharedPtr < SWidget > SSourceControlChangelistsWidget : : OnOpenContextMenu ( )
{
UToolMenus * ToolMenus = UToolMenus : : Get ( ) ;
static const FName MenuName = " SourceControl.ChangelistContextMenu " ;
if ( ! ToolMenus - > IsMenuRegistered ( MenuName ) )
{
ToolMenus - > RegisterMenu ( MenuName ) ;
}
// Build up the menu for a selection
FToolMenuContext Context ;
UToolMenu * Menu = ToolMenus - > GenerateMenu ( MenuName , Context ) ;
2021-06-14 15:25:20 -04:00
2021-01-18 09:42:33 -04:00
bool bHasSelectedChangelist = ( GetCurrentChangelist ( ) ! = nullptr ) ;
2021-01-26 09:19:24 -04:00
bool bHasSelectedFiles = ( GetSelectedFiles ( ) . Num ( ) > 0 ) ;
bool bHasSelectedShelvedFiles = ( GetSelectedShelvedFiles ( ) . Num ( ) > 0 ) ;
bool bHasEmptySelection = ( ! bHasSelectedChangelist & & ! bHasSelectedFiles & & ! bHasSelectedShelvedFiles ) ;
2021-06-14 15:25:20 -04:00
bool bIsChangelistParentOfSelection = IsParentOfSelection ( IChangelistTreeItem : : Changelist ) ;
bool bIsUncontrolledChangelistParentOfSelection = IsParentOfSelection ( IChangelistTreeItem : : UncontrolledChangelist ) ;
2021-01-18 09:42:33 -04:00
FToolMenuSection & Section = Menu - > AddSection ( " Source Control " ) ;
// This should appear only on change lists
if ( bHasSelectedChangelist )
{
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " SubmitChangelist " , LOCTEXT ( " SourceControl_SubmitChangelist " , " Submit Changelist... " ) , LOCTEXT ( " SourceControl_SubmitChangeslit_Tooltip " , " Submits a changelist " ) , FSlateIcon ( ) ,
2021-01-18 09:42:33 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnSubmitChangelist ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanSubmitChangelist ) ) ) ;
2021-08-11 15:40:41 -04:00
Section . AddMenuEntry ( " ValidateChangelist " , LOCTEXT ( " SourceControl_ValidateChangelist " , " Validate Changelist " ) , LOCTEXT ( " SourceControl_ValidateChangeslit_Tooltip " , " Validates a changelist " ) , FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnValidateChangelist ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanValidateChangelist ) ) ) ;
2021-01-18 09:42:33 -04:00
}
// This can appear on both files & changelist
2021-06-14 15:25:20 -04:00
if ( bIsChangelistParentOfSelection )
2021-01-18 09:42:33 -04:00
{
Section . AddMenuEntry ( " RevertUnchanged " , LOCTEXT ( " SourceControl_RevertUnchanged " , " Revert Unchanged " ) , LOCTEXT ( " SourceControl_Revert_Unchanged_Tooltip " , " Reverts unchanged files & changelists " ) , FSlateIcon ( ) ,
2021-06-14 15:25:20 -04:00
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnRevertUnchanged ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanRevertUnchanged ) ) ) ;
}
2021-01-19 14:50:23 -04:00
2021-06-14 15:25:20 -04:00
if ( bIsChangelistParentOfSelection | | bIsUncontrolledChangelistParentOfSelection )
{
2021-01-19 14:50:23 -04:00
Section . AddMenuEntry ( " Revert " , LOCTEXT ( " SourceControl_Revert " , " Revert Files " ) , LOCTEXT ( " SourceControl_Revert_Tooltip " , " Reverts all files in the changelist or from the selection " ) , FSlateIcon ( ) ,
2021-01-27 16:11:25 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnRevert ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanRevert ) ) ) ;
2021-01-19 14:50:23 -04:00
}
2021-06-14 15:25:20 -04:00
if ( bIsChangelistParentOfSelection & & ( bHasSelectedFiles | | bHasSelectedShelvedFiles | | ( bHasSelectedChangelist & & ( GetCurrentChangelistState ( ) - > GetFilesStates ( ) . Num ( ) > 0 | | GetCurrentChangelistState ( ) - > GetShelvedFilesStates ( ) . Num ( ) > 0 ) ) ) )
2021-01-26 09:19:24 -04:00
{
2021-01-27 16:11:25 -04:00
Section . AddSeparator ( " ShelveSeparator " ) ;
2021-01-26 09:19:24 -04:00
}
2021-06-14 15:25:20 -04:00
if ( bIsChangelistParentOfSelection & & ( bHasSelectedFiles | | ( bHasSelectedChangelist & & GetCurrentChangelistState ( ) - > GetFilesStates ( ) . Num ( ) > 0 ) ) )
2021-01-26 09:19:24 -04:00
{
Section . AddMenuEntry ( " Shelve " , LOCTEXT ( " SourceControl_Shelve " , " Shelve Files " ) , LOCTEXT ( " SourceControl_Shelve_Tooltip " , " Shelves the changelist or the selected files " ) , FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnShelve ) ) ) ;
}
if ( bHasSelectedShelvedFiles | | ( bHasSelectedChangelist & & GetCurrentChangelistState ( ) - > GetShelvedFilesStates ( ) . Num ( ) > 0 ) )
{
Section . AddMenuEntry ( " Unshelve " , LOCTEXT ( " SourceControl_Unshelve " , " Unshelve Files " ) , LOCTEXT ( " SourceControl_Unshelve_Tooltip " , " Unshelve selected files or changelist " ) , FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnUnshelve ) ) ) ;
Section . AddMenuEntry ( " DeleteShelved " , LOCTEXT ( " SourceControl_DeleteShelved " , " Delete Shelved Files " ) , LOCTEXT ( " SourceControl_DeleteShelved_Tooltip " , " Delete selected shelved files or all from changelist " ) , FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnDeleteShelvedFiles ) ) ) ;
}
// Shelved files-only operations
if ( bHasSelectedShelvedFiles )
{
// Diff against workspace
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " DiffAgainstWorkspace " , LOCTEXT ( " SourceControl_DiffAgainstWorkspace " , " Diff Against Workspace Files... " ) , LOCTEXT ( " SourceControl_DiffAgainstWorkspace_Tooltip " , " Diff shelved file against the (local) workspace file " ) , FSlateIcon ( ) ,
2021-01-26 09:19:24 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnDiffAgainstWorkspace ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanDiffAgainstWorkspace ) ) ) ;
}
2021-01-19 14:50:23 -04:00
if ( bHasEmptySelection | | bHasSelectedChangelist )
{
2021-01-27 16:11:25 -04:00
Section . AddSeparator ( " ChangelistsSeparator " ) ;
2021-01-19 14:50:23 -04:00
}
// This should appear only if we have no selection
if ( bHasEmptySelection )
{
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " NewChangelist " , LOCTEXT ( " SourceControl_NewChangelist " , " New Changelist... " ) , LOCTEXT ( " SourceControl_NewChangelist_Tooltip " , " Creates an empty changelist " ) , FSlateIcon ( ) ,
2021-01-19 14:50:23 -04:00
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnNewChangelist ) ) ) ;
}
if ( bHasSelectedChangelist )
{
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " EditChangelist " , LOCTEXT ( " SourceControl_EditChangelist " , " Edit Changelist... " ) , LOCTEXT ( " SourceControl_Edit_Changelist_Tooltip " , " Edit a changelist description " ) , FSlateIcon ( ) ,
2021-01-19 14:50:23 -04:00
FUIAction ( FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnEditChangelist ) ) ) ;
Section . AddMenuEntry ( " DeleteChangelist " , LOCTEXT ( " SourceControl_DeleteChangelist " , " Delete Empty Changelist " ) , LOCTEXT ( " SourceControl_Delete_Changelist_Tooltip " , " Deletes an empty changelist " ) , FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnDeleteChangelist ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanDeleteChangelist ) ) ) ;
}
// Files-only operations
2021-01-26 09:19:24 -04:00
if ( bHasSelectedFiles )
2021-01-19 14:50:23 -04:00
{
2021-01-27 16:11:25 -04:00
Section . AddSeparator ( " FilesSeparator " ) ;
2021-01-19 14:50:23 -04:00
2021-03-24 08:29:57 -04:00
Section . AddMenuEntry ( " MoveFiles " , LOCTEXT ( " SourceControl_MoveFiles " , " Move Files To... " ) , LOCTEXT ( " SourceControl_MoveFiles_Tooltip " , " Move Files To A Different Changelist... " ) , FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnMoveFiles ) ) ) ;
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " LocateFile " , LOCTEXT ( " SourceControl_LocateFile " , " Locate File... " ) , LOCTEXT ( " SourceControl_LocateFile_Tooltip " , " Locate File in Project... " ) , FSlateIcon ( ) ,
2021-01-19 14:50:23 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnLocateFile ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanLocateFile ) ) ) ;
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " ShowHistory " , LOCTEXT ( " SourceControl_ShowHistory " , " Show History... " ) , LOCTEXT ( " SourceControl_ShowHistory_ToolTip " , " Show File History From Selection... " ) , FSlateIcon ( ) ,
2021-01-19 14:50:23 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnShowHistory ) ) ) ;
2021-02-28 23:55:37 -04:00
Section . AddMenuEntry ( " DiffAgainstLocalVersion " , LOCTEXT ( " SourceControl_DiffAgainstDepot " , " Diff Against Depot... " ) , LOCTEXT ( " SourceControl_DiffAgainstLocal_Tooltip " , " Diff local file against depot revision. " ) , FSlateIcon ( ) ,
2021-01-19 14:50:23 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : OnDiffAgainstDepot ) ,
FCanExecuteAction : : CreateSP ( this , & SSourceControlChangelistsWidget : : CanDiffAgainstDepot ) ) ) ;
2021-01-18 09:42:33 -04:00
}
2021-05-26 18:15:46 -04:00
if ( FUncontrolledChangelistsModule : : Get ( ) . IsEnabled ( ) )
{
Section . AddSeparator ( " ReconcileSeparator " ) ;
2021-06-21 11:04:24 -04:00
Section . AddMenuEntry ( " Reconcile assets " , LOCTEXT ( " SourceControl_ReconcileAssets " , " Reconcile assets " ) , LOCTEXT ( " SourceControl_ReconcileAssets_Tooltip " , " Look for uncontrolled modification in currently added assets. " ) , FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateLambda ( [ ] ( ) { FUncontrolledChangelistsModule : : Get ( ) . OnReconcileAssets ( ) ; } ) ) ) ;
2021-05-26 18:15:46 -04:00
}
2021-01-18 09:42:33 -04:00
return ToolMenus - > GenerateWidget ( Menu ) ;
}
2021-01-11 15:31:58 -04:00
TSharedRef < SChangelistTree > SSourceControlChangelistsWidget : : CreateTreeviewWidget ( )
{
return SAssignNew ( TreeView , SChangelistTree )
. ItemHeight ( 24.0f )
. TreeItemsSource ( & ChangelistsNodes )
. OnGenerateRow ( this , & SSourceControlChangelistsWidget : : OnGenerateRow )
. OnGetChildren ( this , & SSourceControlChangelistsWidget : : OnGetChildren )
. SelectionMode ( ESelectionMode : : Multi )
2021-01-18 09:42:33 -04:00
. OnContextMenuOpening ( this , & SSourceControlChangelistsWidget : : OnOpenContextMenu )
2021-01-11 15:31:58 -04:00
. HeaderRow
(
SNew ( SHeaderRow )
+ SHeaderRow : : Column ( " Change " )
. DefaultLabel ( LOCTEXT ( " Change " , " Change " ) )
. FillWidth ( 0.2f )
+ SHeaderRow : : Column ( " Description " )
. DefaultLabel ( LOCTEXT ( " Description " , " Description " ) )
2021-01-20 11:49:37 -04:00
. FillWidth ( 0.6f )
+ SHeaderRow : : Column ( " Type " )
. DefaultLabel ( LOCTEXT ( " Type " , " Type " ) )
. FillWidth ( 0.2f )
2021-01-11 15:31:58 -04:00
) ;
}
class SChangelistTableRow : public SMultiColumnTableRow < FChangelistTreeItemPtr >
{
public :
SLATE_BEGIN_ARGS ( SChangelistTableRow )
: _TreeItemToVisualize ( )
{ }
SLATE_ARGUMENT ( FChangelistTreeItemPtr , TreeItemToVisualize )
SLATE_END_ARGS ( )
public :
/**
* Construct child widgets that comprise this widget .
*
* @ param InArgs Declaration from which to construct this widget .
*/
void Construct ( const FArguments & InArgs , const TSharedRef < STableViewBase > & InOwner )
{
TreeItem = static_cast < FChangelistTreeItem * > ( InArgs . _TreeItemToVisualize . Get ( ) ) ;
auto Args = FSuperRowType : : FArguments ( ) ;
SMultiColumnTableRow < FChangelistTreeItemPtr > : : Construct ( Args , InOwner ) ;
}
// SMultiColumnTableRow overrides
virtual TSharedRef < SWidget > GenerateWidgetForColumn ( const FName & ColumnName ) override
{
if ( ColumnName = = TEXT ( " Change " ) )
{
2022-05-09 13:12:28 -04:00
const FSlateBrush * IconBrush = ( TreeItem ! = nullptr ) ? FAppStyle : : GetBrush ( TreeItem - > ChangelistState - > GetSmallIconName ( ) )
: FAppStyle : : GetBrush ( " SourceControl.Changelist " ) ;
2021-01-11 15:31:58 -04:00
return SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
[
SNew ( SExpanderArrow , SharedThis ( this ) )
]
+ 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 , & SChangelistTableRow : : GetChangelistText )
] ;
}
else if ( ColumnName = = TEXT ( " Description " ) )
{
return SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 2.0f , 0.0f )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( this , & SChangelistTableRow : : GetChangelistDescriptionText )
] ;
}
else
{
return SNullWidget : : NullWidget ;
}
}
FText GetChangelistText ( ) const
{
return TreeItem - > GetDisplayText ( ) ;
}
FText GetChangelistDescriptionText ( ) const
{
FString DescriptionString = TreeItem - > GetDescriptionText ( ) . ToString ( ) ;
2021-02-08 15:32:48 -04:00
// Here we'll both remove \r\n (when edited from the dialog) and \n (when we get it from the SCC)
DescriptionString . ReplaceInline ( TEXT ( " \r " ) , TEXT ( " " ) ) ;
2021-01-11 15:31:58 -04:00
DescriptionString . ReplaceInline ( TEXT ( " \n " ) , TEXT ( " " ) ) ;
DescriptionString . TrimEndInline ( ) ;
return FText : : FromString ( DescriptionString ) ;
}
2021-01-18 15:31:14 -04:00
protected :
//~ Begin STableRow Interface.
virtual FReply OnDrop ( const FGeometry & InGeometry , const FDragDropEvent & InDragDropEvent ) override
{
TSharedPtr < FSCCFileDragDropOp > Operation = InDragDropEvent . GetOperationAs < FSCCFileDragDropOp > ( ) ;
if ( Operation . IsValid ( ) )
{
FSourceControlChangelistPtr Changelist = TreeItem - > ChangelistState - > GetChangelist ( ) ;
check ( Changelist . IsValid ( ) ) ;
TArray < FString > Files ;
Algo : : Transform ( Operation - > Files , Files , [ ] ( const FSourceControlStateRef & State ) { return State - > GetFilename ( ) ; } ) ;
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2021-05-12 17:06:06 -04:00
FUncontrolledChangelistsModule & UncontrolledChangelistModule = FUncontrolledChangelistsModule : : Get ( ) ;
2021-01-18 15:31:14 -04:00
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FMoveToChangelist > ( ) , Changelist , Files ) ;
2021-05-12 17:06:06 -04:00
UncontrolledChangelistModule . MoveFilesToControlledChangelist ( Operation - > UncontrolledFiles , Changelist ) ;
2021-01-18 15:31:14 -04:00
}
return FReply : : Handled ( ) ;
}
//~ End STableRow Interface.
2021-01-11 15:31:58 -04:00
private :
/** The info about the widget that we are visualizing. */
FChangelistTreeItem * TreeItem ;
} ;
2021-05-06 14:40:16 -04:00
class SUncontrolledChangelistTableRow : public SMultiColumnTableRow < FChangelistTreeItemPtr >
{
public :
SLATE_BEGIN_ARGS ( SUncontrolledChangelistTableRow )
: _TreeItemToVisualize ( )
{
}
SLATE_ARGUMENT ( FChangelistTreeItemPtr , TreeItemToVisualize )
SLATE_END_ARGS ( )
public :
/**
* Construct child widgets that comprise this widget .
*
* @ param InArgs Declaration from which to construct this widget .
*/
void Construct ( const FArguments & InArgs , const TSharedRef < STableViewBase > & InOwner )
{
TreeItem = static_cast < FUncontrolledChangelistTreeItem * > ( InArgs . _TreeItemToVisualize . Get ( ) ) ;
auto Args = FSuperRowType : : FArguments ( ) ;
SMultiColumnTableRow < FChangelistTreeItemPtr > : : Construct ( Args , InOwner ) ;
}
// SMultiColumnTableRow overrides
virtual TSharedRef < SWidget > GenerateWidgetForColumn ( const FName & ColumnName ) override
{
if ( ColumnName = = TEXT ( " Change " ) )
{
2022-05-09 13:12:28 -04:00
const FSlateBrush * IconBrush = ( TreeItem ! = nullptr ) ? FAppStyle : : GetBrush ( TreeItem - > UncontrolledChangelistState - > GetSmallIconName ( ) )
: FAppStyle : : GetBrush ( " SourceControl.Changelist " ) ;
2021-05-06 14:40:16 -04:00
return SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
[
SNew ( SExpanderArrow , SharedThis ( this ) )
]
+ 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 )
] ;
}
else if ( ColumnName = = TEXT ( " Description " ) )
{
return SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 2.0f , 0.0f )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( this , & SUncontrolledChangelistTableRow : : GetChangelistDescriptionText )
] ;
}
else
{
return SNullWidget : : NullWidget ;
}
}
FText GetChangelistText ( ) const
{
return TreeItem - > GetDisplayText ( ) ;
}
FText GetChangelistDescriptionText ( ) const
{
FString DescriptionString = TreeItem - > GetDescriptionText ( ) . ToString ( ) ;
// Here we'll both remove \r\n (when edited from the dialog) and \n (when we get it from the SCC)
DescriptionString . ReplaceInline ( TEXT ( " \r " ) , TEXT ( " " ) ) ;
DescriptionString . ReplaceInline ( TEXT ( " \n " ) , TEXT ( " " ) ) ;
DescriptionString . TrimEndInline ( ) ;
return FText : : FromString ( DescriptionString ) ;
}
protected :
//~ Begin STableRow Interface.
virtual FReply OnDrop ( const FGeometry & InGeometry , const FDragDropEvent & InDragDropEvent ) override
{
TSharedPtr < FSCCFileDragDropOp > Operation = InDragDropEvent . GetOperationAs < FSCCFileDragDropOp > ( ) ;
if ( Operation . IsValid ( ) )
{
2021-05-12 17:06:06 -04:00
FUncontrolledChangelistsModule : : Get ( ) . MoveFilesToUncontrolledChangelist ( Operation - > Files , Operation - > UncontrolledFiles , TreeItem - > UncontrolledChangelistState - > Changelist ) ;
2021-05-06 14:40:16 -04:00
}
return FReply : : Handled ( ) ;
}
//~ End STableRow Interface.
private :
/** The info about the widget that we are visualizing. */
FUncontrolledChangelistTreeItem * TreeItem ;
} ;
2021-01-20 11:49:37 -04:00
class SFileTableRow : public SMultiColumnTableRow < FChangelistTreeItemPtr >
2021-01-11 15:31:58 -04:00
{
public :
SLATE_BEGIN_ARGS ( SFileTableRow )
: _TreeItemToVisualize ( )
{ }
SLATE_ARGUMENT ( FChangelistTreeItemPtr , TreeItemToVisualize )
2021-01-18 15:31:14 -04:00
SLATE_EVENT ( FOnDragDetected , OnDragDetected )
2021-01-11 15:31:58 -04:00
SLATE_END_ARGS ( )
public :
/**
* Construct child widgets that comprise this widget .
*
* @ param InArgs Declaration from which to construct this widget .
*/
void Construct ( const FArguments & InArgs , const TSharedRef < STableViewBase > & InOwner )
{
TreeItem = static_cast < FFileTreeItem * > ( InArgs . _TreeItemToVisualize . Get ( ) ) ;
2021-01-20 11:49:37 -04:00
auto Args = FSuperRowType : : FArguments ( )
. OnDragDetected ( InArgs . _OnDragDetected )
. ShowSelection ( true ) ;
FSuperRowType : : Construct ( Args , InOwner ) ;
}
// SMultiColumnTableRow overrides
virtual TSharedRef < SWidget > GenerateWidgetForColumn ( const FName & ColumnName ) override
{
if ( ColumnName = = TEXT ( " Change " ) ) // eq. to name
{
2021-02-04 17:41:41 -04:00
const int32 LeftOffset = ( TreeItem - > IsShelved ( ) ? 60 : 40 ) ;
2021-01-20 11:49:37 -04:00
return SNew ( SHorizontalBox )
2021-01-11 15:31:58 -04:00
// Icon
2021-01-18 15:31:14 -04:00
+ SHorizontalBox : : Slot ( )
2021-01-11 15:31:58 -04:00
. AutoWidth ( )
2021-02-04 17:41:41 -04:00
. Padding ( LeftOffset , 0 , 4 , 0 )
2021-01-11 15:31:58 -04:00
[
2021-02-04 17:41:41 -04:00
SSourceControlCommon : : GetSCCFileWidget ( TreeItem - > FileState , TreeItem - > IsShelved ( ) )
2021-01-11 15:31:58 -04:00
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
2021-01-20 11:49:37 -04:00
. Text ( this , & SFileTableRow : : GetDisplayName )
] ;
}
else if ( ColumnName = = TEXT ( " Description " ) ) // eq. to path
{
return SNew ( STextBlock )
2021-02-04 17:41:41 -04:00
. Text ( this , & SFileTableRow : : GetDisplayPath )
. ToolTipText ( this , & SFileTableRow : : GetFilename ) ;
2021-01-20 11:49:37 -04:00
}
else if ( ColumnName = = TEXT ( " Type " ) )
{
return SNew ( STextBlock )
. Text ( this , & SFileTableRow : : GetDisplayType )
. ColorAndOpacity ( this , & SFileTableRow : : GetDisplayColor ) ;
}
else
{
return SNullWidget : : NullWidget ;
}
2021-01-11 15:31:58 -04:00
}
2021-01-20 11:49:37 -04:00
FText GetDisplayName ( ) const
2021-01-11 15:31:58 -04:00
{
2021-02-04 17:41:41 -04:00
return TreeItem - > GetAssetName ( ) ;
}
FText GetFilename ( ) const
{
return TreeItem - > GetFileName ( ) ;
2021-01-20 11:49:37 -04:00
}
FText GetDisplayPath ( ) const
{
2021-02-04 17:41:41 -04:00
return TreeItem - > GetAssetPath ( ) ;
2021-01-20 11:49:37 -04:00
}
FText GetDisplayType ( ) const
{
2021-02-04 17:41:41 -04:00
return TreeItem - > GetAssetType ( ) ;
2021-01-20 11:49:37 -04:00
}
FSlateColor GetDisplayColor ( ) const
{
2021-02-04 17:41:41 -04:00
return TreeItem - > GetAssetTypeColor ( ) ;
2021-01-11 15:31:58 -04:00
}
2021-01-18 15:31:14 -04:00
protected :
//~ Begin STableRow Interface.
virtual void OnDragEnter ( FGeometry const & InGeometry , FDragDropEvent const & InDragDropEvent ) override
{
TSharedPtr < FDragDropOperation > DragOperation = InDragDropEvent . GetOperation ( ) ;
DragOperation - > SetCursorOverride ( EMouseCursor : : SlashedCircle ) ;
}
virtual void OnDragLeave ( FDragDropEvent const & InDragDropEvent ) override
{
TSharedPtr < FDragDropOperation > DragOperation = InDragDropEvent . GetOperation ( ) ;
DragOperation - > SetCursorOverride ( EMouseCursor : : None ) ;
}
//~ End STableRow Interface.
2021-01-11 15:31:58 -04:00
private :
/** The info about the widget that we are visualizing. */
FFileTreeItem * TreeItem ;
} ;
2021-06-08 17:12:06 -04:00
class SOfflineFileTableRow : public SMultiColumnTableRow < FChangelistTreeItemPtr >
{
public :
SLATE_BEGIN_ARGS ( SOfflineFileTableRow )
: _TreeItemToVisualize ( )
{
}
SLATE_ARGUMENT ( FChangelistTreeItemPtr , TreeItemToVisualize )
SLATE_END_ARGS ( )
public :
/**
* Construct child widgets that comprise this widget .
*
* @ param InArgs Declaration from which to construct this widget .
*/
void Construct ( const FArguments & InArgs , const TSharedRef < STableViewBase > & InOwner )
{
TreeItem = static_cast < FOfflineFileTreeItem * > ( InArgs . _TreeItemToVisualize . Get ( ) ) ;
auto Args = FSuperRowType : : FArguments ( ) . ShowSelection ( true ) ;
FSuperRowType : : Construct ( Args , InOwner ) ;
}
// SMultiColumnTableRow overrides
virtual TSharedRef < SWidget > GenerateWidgetForColumn ( const FName & ColumnName ) override
{
if ( ColumnName = = TEXT ( " Change " ) ) // eq. to name
{
return SNew ( SHorizontalBox )
// Icon
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 40 , 0 , 4 , 0 )
[
SNew ( SImage )
2022-05-09 13:12:28 -04:00
. Image ( FAppStyle : : GetBrush ( FName ( " SourceControl.OfflineFile_Small " ) ) )
2021-06-08 17:12:06 -04:00
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( this , & SOfflineFileTableRow : : GetDisplayName )
] ;
}
else if ( ColumnName = = TEXT ( " Description " ) ) // eq. to path
{
return SNew ( STextBlock )
. Text ( this , & SOfflineFileTableRow : : GetDisplayPath )
. ToolTipText ( this , & SOfflineFileTableRow : : GetFilename ) ;
}
else if ( ColumnName = = TEXT ( " Type " ) )
{
return SNew ( STextBlock )
. Text ( this , & SOfflineFileTableRow : : GetDisplayType )
. ColorAndOpacity ( this , & SOfflineFileTableRow : : GetDisplayColor ) ;
}
else
{
return SNullWidget : : NullWidget ;
}
}
FText GetDisplayName ( ) const
{
return TreeItem - > GetDisplayName ( ) ;
}
FText GetFilename ( ) const
{
return TreeItem - > GetPackageName ( ) ;
}
FText GetDisplayPath ( ) const
{
return TreeItem - > GetDisplayPath ( ) ;
}
FText GetDisplayType ( ) const
{
return TreeItem - > GetDisplayType ( ) ;
}
FSlateColor GetDisplayColor ( ) const
{
return TreeItem - > GetDisplayColor ( ) ;
}
protected :
//~ Begin STableRow Interface.
//~ End STableRow Interface.
private :
/** The info about the widget that we are visualizing. */
FOfflineFileTreeItem * TreeItem ;
} ;
2021-01-26 09:19:24 -04:00
class SShelvedChangelistTableRow : public SMultiColumnTableRow < FChangelistTreeItemPtr >
{
public :
SLATE_BEGIN_ARGS ( SShelvedChangelistTableRow )
: _TreeItemToVisualize ( )
{ }
SLATE_ARGUMENT ( FChangelistTreeItemPtr , TreeItemToVisualize )
SLATE_END_ARGS ( )
public :
/**
* Construct child widgets that comprise this widget .
*
* @ param InArgs Declaration from which to construct this widget .
*/
void Construct ( const FArguments & InArgs , const TSharedRef < STableViewBase > & InOwner )
{
TreeItem = static_cast < FShelvedChangelistTreeItem * > ( InArgs . _TreeItemToVisualize . Get ( ) ) ;
auto Args = FSuperRowType : : FArguments ( ) ;
SMultiColumnTableRow < FChangelistTreeItemPtr > : : Construct ( Args , InOwner ) ;
}
// SMultiColumnTableRow overrides
virtual TSharedRef < SWidget > GenerateWidgetForColumn ( const FName & ColumnName ) override
{
if ( ColumnName = = TEXT ( " Change " ) )
{
return SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 5 , 0 , 4 , 0 )
[
SNew ( SExpanderArrow , SharedThis ( this ) )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 5 , 0 , 0 , 0 )
[
SNew ( SImage )
2022-05-09 13:12:28 -04:00
. Image ( FAppStyle : : GetBrush ( " SourceControl.ShelvedChangelist " ) )
2021-01-26 09:19:24 -04:00
]
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f , 0.0f )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( this , & SShelvedChangelistTableRow : : GetText )
] ;
}
else
{
return SNullWidget : : NullWidget ;
}
}
protected :
FText GetText ( ) const
{
return TreeItem - > GetDisplayText ( ) ;
}
private :
/** The info about the widget that we are visualizing. */
FShelvedChangelistTreeItem * TreeItem ;
} ;
2021-01-11 15:31:58 -04:00
TSharedRef < ITableRow > SSourceControlChangelistsWidget : : OnGenerateRow ( FChangelistTreeItemPtr InTreeItem , const TSharedRef < STableViewBase > & OwnerTable )
{
switch ( InTreeItem - > GetTreeItemType ( ) )
{
case IChangelistTreeItem : : Changelist :
return SNew ( SChangelistTableRow , OwnerTable )
. TreeItemToVisualize ( InTreeItem ) ;
2021-05-06 14:40:16 -04:00
case IChangelistTreeItem : : UncontrolledChangelist :
return SNew ( SUncontrolledChangelistTableRow , OwnerTable )
. TreeItemToVisualize ( InTreeItem ) ;
2021-01-11 15:31:58 -04:00
case IChangelistTreeItem : : File :
return SNew ( SFileTableRow , OwnerTable )
2021-01-18 15:31:14 -04:00
. TreeItemToVisualize ( InTreeItem )
. OnDragDetected ( this , & SSourceControlChangelistsWidget : : OnFilesDragged ) ;
2021-01-11 15:31:58 -04:00
2021-06-08 17:12:06 -04:00
case IChangelistTreeItem : : OfflineFile :
return SNew ( SOfflineFileTableRow , OwnerTable )
. TreeItemToVisualize ( InTreeItem ) ;
2021-01-26 09:19:24 -04:00
case IChangelistTreeItem : : ShelvedChangelist :
return SNew ( SShelvedChangelistTableRow , OwnerTable )
. TreeItemToVisualize ( InTreeItem ) ;
case IChangelistTreeItem : : ShelvedFile :
2021-02-04 17:41:41 -04:00
return SNew ( SFileTableRow , OwnerTable )
2021-01-26 09:19:24 -04:00
. TreeItemToVisualize ( InTreeItem ) ;
2021-01-11 15:31:58 -04:00
default :
check ( false ) ;
} ;
return SNew ( STableRow < TSharedPtr < FString > > , OwnerTable ) ;
}
2021-01-18 15:31:14 -04:00
FReply SSourceControlChangelistsWidget : : OnFilesDragged ( const FGeometry & InGeometry , const FPointerEvent & InMouseEvent )
{
if ( InMouseEvent . IsMouseButtonDown ( EKeys : : LeftMouseButton ) & & ! TreeView - > GetSelectedItems ( ) . IsEmpty ( ) )
{
TSharedRef < FSCCFileDragDropOp > Operation = MakeShareable ( new FSCCFileDragDropOp ( ) ) ;
2021-05-12 17:06:06 -04:00
for ( FChangelistTreeItemPtr InTreeItem : TreeView - > GetSelectedItems ( ) )
{
if ( InTreeItem - > GetTreeItemType ( ) = = IChangelistTreeItem : : File )
{
FFileTreeItemRef FileTreeItem = StaticCastSharedRef < FFileTreeItem > ( InTreeItem . ToSharedRef ( ) ) ;
FSourceControlStateRef FileState = FileTreeItem - > FileState ;
if ( FileTreeItem - > GetParent ( ) - > GetTreeItemType ( ) = = IChangelistTreeItem : : UncontrolledChangelist )
{
Operation - > UncontrolledFiles . Add ( MoveTemp ( FileState ) ) ;
}
else
{
Operation - > Files . Add ( MoveTemp ( FileState ) ) ;
}
}
}
2021-01-18 15:31:14 -04:00
Operation - > Construct ( ) ;
2021-05-12 17:06:06 -04:00
return FReply : : Handled ( ) . BeginDragDrop ( Operation ) ;
2021-01-18 15:31:14 -04:00
}
return FReply : : Unhandled ( ) ;
}
2021-01-11 15:31:58 -04:00
void SSourceControlChangelistsWidget : : OnGetChildren ( FChangelistTreeItemPtr InParent , TArray < FChangelistTreeItemPtr > & OutChildren )
{
for ( auto & Child : InParent - > GetChildren ( ) )
{
// Should never have bogus entries in this list
check ( Child . IsValid ( ) ) ;
OutChildren . Add ( Child ) ;
}
}
2021-01-26 10:56:16 -04:00
void SSourceControlChangelistsWidget : : SaveExpandedState ( TMap < FSourceControlChangelistStateRef , ExpandedState > & ExpandedStates ) const
{
for ( FChangelistTreeItemPtr Root : ChangelistsNodes )
{
2021-05-26 18:15:46 -04:00
if ( ( Root - > GetTreeItemType ( ) ! = IChangelistTreeItem : : Changelist ) & & ( Root - > GetTreeItemType ( ) ! = IChangelistTreeItem : : UncontrolledChangelist ) )
2021-01-26 10:56:16 -04:00
{
continue ;
}
bool bChangelistExpanded = TreeView - > IsItemExpanded ( Root ) ;
bool bShelveExpanded = false ;
for ( FChangelistTreeItemPtr Child : Root - > GetChildren ( ) )
{
if ( Child - > GetTreeItemType ( ) = = IChangelistTreeItem : : ShelvedChangelist )
{
bShelveExpanded = TreeView - > IsItemExpanded ( Child ) ;
break ;
}
}
ExpandedState State ;
State . bChangelistExpanded = bChangelistExpanded ;
State . bShelveExpanded = bShelveExpanded ;
ExpandedStates . Add ( StaticCastSharedPtr < FChangelistTreeItem > ( Root ) - > ChangelistState , State ) ;
}
}
void SSourceControlChangelistsWidget : : RestoreExpandedState ( const TMap < FSourceControlChangelistStateRef , ExpandedState > & ExpandedStates )
{
for ( FChangelistTreeItemPtr Root : ChangelistsNodes )
{
2021-05-26 18:15:46 -04:00
if ( ( Root - > GetTreeItemType ( ) ! = IChangelistTreeItem : : Changelist ) & & ( Root - > GetTreeItemType ( ) ! = IChangelistTreeItem : : UncontrolledChangelist ) )
2021-01-26 10:56:16 -04:00
{
continue ;
}
FSourceControlChangelistStateRef ChangelistState = StaticCastSharedPtr < FChangelistTreeItem > ( Root ) - > ChangelistState ;
const ExpandedState * State = ExpandedStates . Find ( ChangelistState ) ;
if ( ! State )
{
continue ;
}
TreeView - > SetItemExpansion ( Root , State - > bChangelistExpanded ) ;
for ( FChangelistTreeItemPtr Child : Root - > GetChildren ( ) )
{
if ( Child - > GetTreeItemType ( ) = = IChangelistTreeItem : : ShelvedChangelist )
{
TreeView - > SetItemExpansion ( Child , State - > bShelveExpanded ) ;
break ;
}
}
}
}
2021-01-11 15:31:58 -04:00
# undef LOCTEXT_NAMESPACE