Files
UnrealEngineUWP/Engine/Source/Editor/SourceControlWindows/Private/SSourceControlSubmit.cpp

731 lines
23 KiB
C++
Raw Normal View History

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "SourceControlWindowsPCH.h"
#include "AssetToolsModule.h"
#include "MessageLog.h"
#include "SNotificationList.h"
#include "NotificationManager.h"
#include "FileHelpers.h"
#include "SSourceControlSubmit.h"
IMPLEMENT_MODULE( FDefaultModuleImpl, SourceControlWindows );
#if SOURCE_CONTROL_WITH_SLATE
#define LOCTEXT_NAMESPACE "SSourceControlSubmit"
namespace SSourceControlSubmitWidgetDefs
{
const FName ColumnID_CheckBoxLabel("CheckBox");
const FName ColumnID_IconLabel("Icon");
const FName ColumnID_FileLabel("File");
const float CheckBoxColumnWidth = 23.0f;
const float IconColumnWidth = 21.0f;
}
FSubmitItem::FSubmitItem(const FSourceControlStateRef& InItem)
: Item(InItem)
{
CheckBoxState = ECheckBoxState::Checked;
DisplayName = FText::FromString(Item->GetFilename());
}
void SSourceControlSubmitListRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView)
{
SourceControlSubmitWidgetPtr = InArgs._SourceControlSubmitWidget;
Item = InArgs._Item;
SMultiColumnTableRow<TSharedPtr<FSubmitItem>>::Construct(FSuperRowType::FArguments(), InOwnerTableView);
}
TSharedRef<SWidget> SSourceControlSubmitListRow::GenerateWidgetForColumn(const FName& ColumnName)
{
// Create the widget for this item
TSharedPtr<SSourceControlSubmitWidget> SourceControlSubmitWidget = SourceControlSubmitWidgetPtr.Pin();
if (SourceControlSubmitWidget.IsValid())
{
return SourceControlSubmitWidget->GenerateWidgetForItemAndColumn(Item, ColumnName);
}
// Packages dialog no longer valid; return a valid, null widget.
return SNullWidget::NullWidget;
}
void SSourceControlSubmitWidget::Construct(const FArguments& InArgs)
{
ParentFrame = InArgs._ParentWindow.Get();
SortByColumn = SSourceControlSubmitWidgetDefs::ColumnID_FileLabel;
SortMode = EColumnSortMode::Ascending;
for (const auto& Item : InArgs._Items.Get())
{
ListViewItems.Add(MakeShareable(new FSubmitItem(Item)));
}
TSharedRef<SHeaderRow> HeaderRowWidget = SNew(SHeaderRow);
HeaderRowWidget->AddColumn(
SHeaderRow::Column(SSourceControlSubmitWidgetDefs::ColumnID_CheckBoxLabel)
[
SNew(SCheckBox)
.IsChecked(this, &SSourceControlSubmitWidget::GetToggleSelectedState)
.OnCheckStateChanged(this, &SSourceControlSubmitWidget::OnToggleSelectedCheckBox)
]
.FixedWidth(SSourceControlSubmitWidgetDefs::CheckBoxColumnWidth)
);
HeaderRowWidget->AddColumn(
SHeaderRow::Column(SSourceControlSubmitWidgetDefs::ColumnID_IconLabel)
[
SNew(SSpacer)
]
.SortMode(this, &SSourceControlSubmitWidget::GetColumnSortMode, SSourceControlSubmitWidgetDefs::ColumnID_IconLabel)
.OnSort(this, &SSourceControlSubmitWidget::OnColumnSortModeChanged)
.FixedWidth(SSourceControlSubmitWidgetDefs::IconColumnWidth)
);
HeaderRowWidget->AddColumn(
SHeaderRow::Column(SSourceControlSubmitWidgetDefs::ColumnID_FileLabel)
.DefaultLabel(LOCTEXT("FileColumnLabel", "File"))
.SortMode(this, &SSourceControlSubmitWidget::GetColumnSortMode, SSourceControlSubmitWidgetDefs::ColumnID_FileLabel)
.OnSort(this, &SSourceControlSubmitWidget::OnColumnSortModeChanged)
.FillWidth(7.0f)
);
ChildSlot
[
SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
.Padding(5)
[
SNew( STextBlock )
.Text( NSLOCTEXT("SourceControl.SubmitPanel", "ChangeListDesc", "Changelist Description") )
]
+SVerticalBox::Slot()
.AutoHeight()
.Padding(FMargin(5, 0, 5, 5))
[
SNew(SBox)
.WidthOverride(520)
[
SAssignNew( ChangeListDescriptionTextCtrl, SMultiLineEditableTextBox )
.SelectAllTextWhenFocused( true )
.AutoWrapText( true )
]
]
+SVerticalBox::Slot()
.Padding(FMargin(5, 0))
[
SNew(SBorder)
[
SAssignNew(ListView, SListView<TSharedPtr<FSubmitItem>>)
.ItemHeight(20)
.ListItemsSource(&ListViewItems)
.OnGenerateRow(this, &SSourceControlSubmitWidget::OnGenerateRowForList)
.HeaderRow(HeaderRowWidget)
.SelectionMode(ESelectionMode::None)
]
]
+SVerticalBox::Slot()
.AutoHeight()
.Padding(FMargin(5, 5, 5, 0))
[
SNew( SBorder)
.Visibility(this, &SSourceControlSubmitWidget::IsWarningPanelVisible)
.Padding(5)
[
SNew( SErrorText )
.ErrorText( NSLOCTEXT("SourceControl.SubmitPanel", "ChangeListDescWarning", "Changelist description is required to submit") )
]
]
+SVerticalBox::Slot()
.AutoHeight()
.Padding(5)
[
SNew(SWrapBox)
.UseAllottedWidth(true)
+SWrapBox::Slot()
.Padding(0.0f, 0.0f, 16.0f, 0.0f)
[
SNew(SCheckBox)
.OnCheckStateChanged( this, &SSourceControlSubmitWidget::OnCheckStateChanged_KeepCheckedOut)
.IsChecked( this, &SSourceControlSubmitWidget::GetKeepCheckedOut )
[
SNew(STextBlock)
.Text(NSLOCTEXT("SourceControl.SubmitPanel", "KeepCheckedOut", "Keep Files Checked Out") )
]
]
]
+SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Right)
.VAlign(VAlign_Bottom)
.Padding(0.0f,0.0f,0.0f,5.0f)
[
SNew(SUniformGridPanel)
.SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding"))
.MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
.MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight"))
+SUniformGridPanel::Slot(0,0)
[
SNew(SButton)
.HAlign(HAlign_Center)
.ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
.IsEnabled(this, &SSourceControlSubmitWidget::IsOKEnabled)
.Text( NSLOCTEXT("SourceControl.SubmitPanel", "OKButton", "OK") )
.OnClicked(this, &SSourceControlSubmitWidget::OKClicked)
]
+SUniformGridPanel::Slot(1,0)
[
SNew(SButton)
.HAlign(HAlign_Center)
.ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
.Text( NSLOCTEXT("SourceControl.SubmitPanel", "CancelButton", "Cancel") )
.OnClicked(this, &SSourceControlSubmitWidget::CancelClicked)
]
]
]
];
RequestSort();
DialogResult = ESubmitResults::SUBMIT_CANCELED;
KeepCheckedOut = ECheckBoxState::Unchecked;
ParentFrame.Pin()->SetWidgetToFocusOnActivate(ChangeListDescriptionTextCtrl);
}
TSharedRef<SWidget> SSourceControlSubmitWidget::GenerateWidgetForItemAndColumn(TSharedPtr<FSubmitItem> Item, const FName ColumnID) const
{
check(Item.IsValid());
const FMargin RowPadding(3, 0, 0, 0);
TSharedPtr<SWidget> ItemContentWidget;
if (ColumnID == SSourceControlSubmitWidgetDefs::ColumnID_CheckBoxLabel)
{
ItemContentWidget = SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(RowPadding)
[
SNew(SCheckBox)
.IsChecked(Item.Get(), &FSubmitItem::GetCheckBoxState)
.OnCheckStateChanged(Item.Get(), &FSubmitItem::SetCheckBoxState)
];
}
else if (ColumnID == SSourceControlSubmitWidgetDefs::ColumnID_IconLabel)
{
ItemContentWidget = SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SImage)
.Image(FEditorStyle::GetBrush(Item->GetIconName()))
.ToolTipText(Item->GetIconTooltip())
];
}
else if (ColumnID == SSourceControlSubmitWidgetDefs::ColumnID_FileLabel)
{
ItemContentWidget = SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(RowPadding)
[
SNew(STextBlock)
.Text(Item->GetDisplayName())
];
}
return ItemContentWidget.ToSharedRef();
}
ECheckBoxState SSourceControlSubmitWidget::GetToggleSelectedState() const
{
// Default to a Checked state
ECheckBoxState PendingState = ECheckBoxState::Checked;
// Iterate through the list of selected items
for (const auto& Item : ListViewItems)
{
if (Item->GetCheckBoxState() == ECheckBoxState::Unchecked)
{
// If any item in the list is Unchecked, then represent the entire set of highlighted items as Unchecked,
// so that the first (user) toggle of ToggleSelectedCheckBox consistently Checks all items
PendingState = ECheckBoxState::Unchecked;
break;
}
}
return PendingState;
}
void SSourceControlSubmitWidget::OnToggleSelectedCheckBox(ECheckBoxState InNewState)
{
for (const auto& Item : ListViewItems)
{
Item->SetCheckBoxState(InNewState);
}
ListView->RequestListRefresh();
}
void SSourceControlSubmitWidget::FillChangeListDescription(FChangeListDescription& OutDesc)
{
OutDesc.Description = ChangeListDescriptionTextCtrl->GetText();
OutDesc.FilesForAdd.Empty();
OutDesc.FilesForSubmit.Empty();
for (const auto& Item : ListViewItems)
{
if (Item->GetCheckBoxState() == ECheckBoxState::Checked)
{
if (Item->CanCheckIn())
{
OutDesc.FilesForSubmit.Add(Item->GetFilename());
}
else if (Item->NeedsAdding())
{
OutDesc.FilesForAdd.Add(Item->GetFilename());
}
}
}
}
bool SSourceControlSubmitWidget::WantToKeepCheckedOut()
{
return KeepCheckedOut == ECheckBoxState::Checked ? true : false;
}
FReply SSourceControlSubmitWidget::OKClicked()
{
DialogResult = ESubmitResults::SUBMIT_ACCEPTED;
ParentFrame.Pin()->RequestDestroyWindow();
return FReply::Handled();
}
FReply SSourceControlSubmitWidget::CancelClicked()
{
DialogResult = ESubmitResults::SUBMIT_CANCELED;
ParentFrame.Pin()->RequestDestroyWindow();
return FReply::Handled();
}
bool SSourceControlSubmitWidget::IsOKEnabled() const
{
return !ChangeListDescriptionTextCtrl->GetText().IsEmpty();
}
EVisibility SSourceControlSubmitWidget::IsWarningPanelVisible() const
{
return IsOKEnabled()? EVisibility::Hidden : EVisibility::Visible;
}
void SSourceControlSubmitWidget::OnCheckStateChanged_KeepCheckedOut(ECheckBoxState InState)
{
KeepCheckedOut = InState;
}
ECheckBoxState SSourceControlSubmitWidget::GetKeepCheckedOut() const
{
return KeepCheckedOut;
}
TSharedRef<ITableRow> SSourceControlSubmitWidget::OnGenerateRowForList(TSharedPtr<FSubmitItem> SubmitItem, const TSharedRef<STableViewBase>& OwnerTable)
{
TSharedRef<ITableRow> Row =
SNew(SSourceControlSubmitListRow, OwnerTable)
.SourceControlSubmitWidget(SharedThis(this))
.Item(SubmitItem)
.IsEnabled(SubmitItem->IsEnabled());
return Row;
}
EColumnSortMode::Type SSourceControlSubmitWidget::GetColumnSortMode(const FName ColumnId) const
{
if (SortByColumn != ColumnId)
{
return EColumnSortMode::None;
}
return SortMode;
}
void SSourceControlSubmitWidget::OnColumnSortModeChanged(const EColumnSortPriority::Type SortPriority, const FName& ColumnId, const EColumnSortMode::Type InSortMode)
{
SortByColumn = ColumnId;
SortMode = InSortMode;
RequestSort();
}
void SSourceControlSubmitWidget::RequestSort()
{
// Sort the list of root items
SortTree();
ListView->RequestListRefresh();
}
void SSourceControlSubmitWidget::SortTree()
{
if (SortByColumn == SSourceControlSubmitWidgetDefs::ColumnID_FileLabel)
{
if (SortMode == EColumnSortMode::Ascending)
{
ListViewItems.Sort([](const TSharedPtr<FSubmitItem>& A, const TSharedPtr<FSubmitItem>& B) {
return A->GetDisplayName().ToString() < B->GetDisplayName().ToString(); });
}
else if (SortMode == EColumnSortMode::Descending)
{
ListViewItems.Sort([](const TSharedPtr<FSubmitItem>& A, const TSharedPtr<FSubmitItem>& B) {
return A->GetDisplayName().ToString() >= B->GetDisplayName().ToString(); });
}
}
else if (SortByColumn == SSourceControlSubmitWidgetDefs::ColumnID_IconLabel)
{
if (SortMode == EColumnSortMode::Ascending)
{
ListViewItems.Sort([](const TSharedPtr<FSubmitItem>& A, const TSharedPtr<FSubmitItem>& B) {
return A->GetIconName().ToString() < B->GetIconName().ToString(); });
}
else if (SortMode == EColumnSortMode::Descending)
{
ListViewItems.Sort([](const TSharedPtr<FSubmitItem>& A, const TSharedPtr<FSubmitItem>& B) {
return A->GetIconName().ToString() >= B->GetIconName().ToString(); });
}
}
}
TWeakPtr<SNotificationItem> FSourceControlWindows::ChoosePackagesToCheckInNotification;
void FSourceControlWindows::ChoosePackagesToCheckInCompleted(const TArray<UPackage*>& LoadedPackages, const TArray<FString>& PackageNames, const TArray<FString>& ConfigFiles)
{
if (ChoosePackagesToCheckInNotification.IsValid())
{
ChoosePackagesToCheckInNotification.Pin()->ExpireAndFadeout();
}
ChoosePackagesToCheckInNotification.Reset();
// Prompt the user to ask if they would like to first save any dirty packages they are trying to check-in
const FEditorFileUtils::EPromptReturnCode UserResponse = FEditorFileUtils::PromptForCheckoutAndSave(LoadedPackages, true, true);
// If the user elected to save dirty packages, but one or more of the packages failed to save properly OR if the user
// canceled out of the prompt, don't follow through on the check-in process
const bool bShouldProceed = (UserResponse == FEditorFileUtils::EPromptReturnCode::PR_Success || UserResponse == FEditorFileUtils::EPromptReturnCode::PR_Declined);
if (bShouldProceed)
{
TArray<FString> PendingDeletePaths;
PendingDeletePaths.Add(FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir()));
PendingDeletePaths.Add(FPaths::ConvertRelativePathToFull(FPaths::GameContentDir()));
PendingDeletePaths.Add(FPaths::ConvertRelativePathToFull(FPaths::GameConfigDir()));
const bool bUseSourceControlStateCache = true;
PromptForCheckin(bUseSourceControlStateCache, PackageNames, PendingDeletePaths, ConfigFiles);
}
else
{
// If a failure occurred, alert the user that the check-in was aborted. This warning shouldn't be necessary if the user cancelled
// from the dialog, because they obviously intended to cancel the whole operation.
if (UserResponse == FEditorFileUtils::EPromptReturnCode::PR_Failure)
{
FMessageDialog::Open(EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "SCC_Checkin_Aborted", "Check-in aborted as a result of save failure."));
}
}
}
void FSourceControlWindows::ChoosePackagesToCheckInCancelled(FSourceControlOperationRef InOperation)
{
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
SourceControlProvider.CancelOperation(InOperation);
if (ChoosePackagesToCheckInNotification.IsValid())
{
ChoosePackagesToCheckInNotification.Pin()->ExpireAndFadeout();
}
ChoosePackagesToCheckInNotification.Reset();
}
void FSourceControlWindows::ChoosePackagesToCheckInCallback(const FSourceControlOperationRef& InOperation, ECommandResult::Type InResult)
{
if (ChoosePackagesToCheckInNotification.IsValid())
{
ChoosePackagesToCheckInNotification.Pin()->ExpireAndFadeout();
}
ChoosePackagesToCheckInNotification.Reset();
if (InResult == ECommandResult::Succeeded)
{
// Get a list of all the checked out packages
TArray<FString> PackageNames;
TArray<UPackage*> LoadedPackages;
TMap<FString, FSourceControlStatePtr> PackageStates;
FEditorFileUtils::FindAllSubmittablePackageFiles(PackageStates, true);
for (TMap<FString, FSourceControlStatePtr>::TConstIterator PackageIter(PackageStates); PackageIter; ++PackageIter)
{
const FString PackageName = *PackageIter.Key();
const FSourceControlStatePtr CurPackageSCCState = PackageIter.Value();
UPackage* Package = FindPackage(nullptr, *PackageName);
if (Package != nullptr)
{
LoadedPackages.Add(Package);
}
PackageNames.Add(PackageName);
}
// Get a list of all the checked out config files
TMap<FString, FSourceControlStatePtr> ConfigFileStates;
TArray<FString> ConfigFilesToSubmit;
FEditorFileUtils::FindAllSubmittableConfigFiles(ConfigFileStates);
for (TMap<FString, FSourceControlStatePtr>::TConstIterator It(ConfigFileStates); It; ++It)
{
ConfigFilesToSubmit.Add(It.Key());
}
ChoosePackagesToCheckInCompleted(LoadedPackages, PackageNames, ConfigFilesToSubmit);
}
else if (InResult == ECommandResult::Failed)
{
FMessageLog EditorErrors("EditorErrors");
EditorErrors.Warning(LOCTEXT("CheckInOperationFailed", "Failed checking source control status!"));
EditorErrors.Notify();
}
}
void FSourceControlWindows::ChoosePackagesToCheckIn()
{
if (ISourceControlModule::Get().IsEnabled())
{
if (ISourceControlModule::Get().GetProvider().IsAvailable())
{
// make sure we update the SCC status of all packages (this could take a long time, so we will run it as a background task)
Copying //UE4/Dev-Editor to Dev-Main (//UE4/Dev-Main) #lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2771249 on 2015/11/18 by Joe.Tidmarsh Ensure that UCircularThrobber's Radius determines the widget's desired size when a child of UCanvasPanelSlot. #jira UE-23186 Change 2794402 on 2015/12/08 by Joe.Tidmarsh Reverting recent changes to Circular throbber. It's unintuative to enforce Size To Content. Will find some other solution. Change 2803507 on 2015/12/15 by Richard.TalbotWatkin BSP poly extrusion can now only be done in the normal direction of the poly. #jira UE-24168 - BSP face breaks off when extruding on Y or Z axes Change 2803510 on 2015/12/15 by Richard.TalbotWatkin Building new static mesh LODs now initializes override vertex colors based on LOD0. #jira UE-23747 - CLONE - if LODs are generated for meshes with vertex colors in a level the vertex colors dont propagate to the LOD in the level Change 2808877 on 2015/12/18 by Alexis.Matte Make sure the delta scale sign is swap when we have multiple axis with different sign current axis value #jira UE-21574 #codereview nick.darnell Change 2810114 on 2015/12/21 by Alexis.Matte #jira UE-23769 We now expose a message telling the user that we found some mesh that are not reference by any scene node in the fbx file. #codereview nick.darnell Change 2810211 on 2015/12/21 by Richard.TalbotWatkin Fixed issue with Show Only Selected not showing members of actor groups. #jira UE-24453 - CLONE - Show Selected is broken for certain Orion meshes Change 2811035 on 2015/12/22 by Alexis.Matte #jira UE-24671 Polish UI #codereview nick.darnell Change 2811123 on 2015/12/22 by Alexis.Matte #jira UE-21936 We now can decide which fbx sdk compatibility version we can use when exportting to a fbx file. #codereview nick.darnell Change 2812830 on 2015/12/28 by Richard.TalbotWatkin Prevent engine assets' properties from having project assets assigned to them. #jira UE-18215 - Details panel: prevent engine content from referencing game content Change 2812854 on 2015/12/28 by Richard.TalbotWatkin Fixed issue where floating windows were having their border size erroneously added again and again. Allowed PIE windows to not respect work area bounds if they are created centered, so that they can overlap off the edge of the screen. #jira UE-24465 - 10 Pixels Added to Width & Height of Floating Editor Windows Each Time Project is Reopened #jira UE-24364 - "Always Center Window to Screen" No Longer Functioning in New Editor Window (PIE) Change 2812875 on 2015/12/28 by Alexis.Matte #jira ue-22237 first implementation for skeletal mesh scene import and reimport. Small refator to remove duplicate code in different fbx list ui. #codereview nick.darnell Change 2813172 on 2015/12/29 by Alexis.Matte #jira ue-21656 Partial submit, the base code is there to add all light type with there properties. #codereview nick.darnell Change 2813403 on 2015/12/30 by Richard.TalbotWatkin PIE in New Editor Window now respects the Game Gets Mouse Control setting. This provides a workaround for UE-24824 where attempting to drag a PIE window fails due to the viewport capturing and locking the mouse to itself in FSceneViewport::OnFocusReceived. Change 2813429 on 2015/12/30 by Alexis.Matte #jira ue-21656 -spotlight and point light support fbx attenuation -fix the light orientation so now directional and spotlight point to the same direction of the fbx #codereview nick.darnell Change 2813456 on 2015/12/30 by Alexis.Matte #jira ue-21656 -Import the camera from fbx #codereview nick.darnell Change 2813457 on 2015/12/30 by Richard.TalbotWatkin Fixed issues with the code which determines whether the user is attempting to assign a game asset/class to an engine asset's property. #jira UE-18215 - Details panel: prevent engine content from referencing game content Change 2813475 on 2015/12/30 by Richard.TalbotWatkin Removed erroneous debug code. Change 2814451 on 2016/01/04 by Joe.Tidmarsh Fixed Tint colour for circular throbber. #jira UE-24445 Change 2814546 on 2016/01/04 by Richard.TalbotWatkin Force Message Log to update its category list if a new category is added while it is open. #jira UE-24266 - Message Log not updating Categories in Real-Time Change 2814613 on 2016/01/04 by Alexis.Matte [CL 2851481 by Nick Darnell in Main branch]
2016-02-01 14:57:29 -05:00
TArray<FString> Filenames;
Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir()));
Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::GameContentDir()));
Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::GameConfigDir()));
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
FSourceControlOperationRef Operation = ISourceControlOperation::Create<FUpdateStatus>();
StaticCastSharedRef<FUpdateStatus>(Operation)->SetCheckingAllFiles(false);
SourceControlProvider.Execute(Operation, Filenames, EConcurrency::Asynchronous, FSourceControlOperationComplete::CreateStatic(&FSourceControlWindows::ChoosePackagesToCheckInCallback));
if (ChoosePackagesToCheckInNotification.IsValid())
{
ChoosePackagesToCheckInNotification.Pin()->ExpireAndFadeout();
}
FNotificationInfo Info(LOCTEXT("ChooseAssetsToCheckInIndicator", "Checking for assets to check in..."));
Info.bFireAndForget = false;
Info.ExpireDuration = 0.0f;
Info.FadeOutDuration = 1.0f;
if (SourceControlProvider.CanCancelOperation(Operation))
{
Info.ButtonDetails.Add(FNotificationButtonInfo(
LOCTEXT("ChoosePackagesToCheckIn_CancelButton", "Cancel"),
LOCTEXT("ChoosePackagesToCheckIn_CancelButtonTooltip", "Cancel the check in operation."),
FSimpleDelegate::CreateStatic(&FSourceControlWindows::ChoosePackagesToCheckInCancelled, Operation)
));
}
ChoosePackagesToCheckInNotification = FSlateNotificationManager::Get().AddNotification(Info);
if (ChoosePackagesToCheckInNotification.IsValid())
{
ChoosePackagesToCheckInNotification.Pin()->SetCompletionState(SNotificationItem::CS_Pending);
}
}
else
{
FMessageLog EditorErrors("EditorErrors");
EditorErrors.Warning(LOCTEXT("NoSCCConnection", "No connection to source control available!"))
->AddToken(FDocumentationToken::Create(TEXT("Engine/UI/SourceControl")));
EditorErrors.Notify();
}
}
}
bool FSourceControlWindows::CanChoosePackagesToCheckIn()
{
return !ChoosePackagesToCheckInNotification.IsValid();
}
bool FSourceControlWindows::PromptForCheckin(bool bUseSourceControlStateCache, const TArray<FString>& InPackageNames, const TArray<FString>& InPendingDeletePaths, const TArray<FString>& InConfigFiles)
{
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
bool bCheckInSuccess = true;
// Get filenames for packages and config to be checked in
TArray<FString> AllFiles = SourceControlHelpers::PackageFilenames(InPackageNames);
AllFiles.Append(InConfigFiles);
// Prepare a list of files to have their states updated
if (!bUseSourceControlStateCache)
{
TArray<FString> UpdateRequest;
UpdateRequest.Append(AllFiles);
// If there are pending delete paths to update, add them here.
UpdateRequest.Append(InPendingDeletePaths);
// Force an update on everything that's been requested
if (UpdateRequest.Num() > 0)
{
SourceControlProvider.Execute(ISourceControlOperation::Create<FUpdateStatus>(), UpdateRequest);
}
}
// Get file status of packages and config
TArray<FSourceControlStateRef> States;
SourceControlProvider.GetState(AllFiles, States, EStateCacheUsage::Use);
if (InPendingDeletePaths.Num() > 0)
{
// Get any files pending delete
TArray<FSourceControlStateRef> PendingDeleteItems = SourceControlProvider.GetCachedStateByPredicate(
[](const FSourceControlStateRef& State) { return State->IsDeleted(); }
);
// And append them to the list
States.Append(PendingDeleteItems);
}
if (States.Num())
{
TSharedRef<SWindow> NewWindow = SNew(SWindow)
.Title(NSLOCTEXT("SourceControl.SubmitWindow", "Title", "Submit Files"))
.SizingRule(ESizingRule::UserSized)
.ClientSize(FVector2D(600, 400))
.SupportsMaximize(true)
.SupportsMinimize(false);
TSharedRef<SSourceControlSubmitWidget> SourceControlWidget =
SNew(SSourceControlSubmitWidget)
.ParentWindow(NewWindow)
.Items(States);
NewWindow->SetContent(
SourceControlWidget
);
FSlateApplication::Get().AddModalWindow(NewWindow, NULL);
if (SourceControlWidget->GetResult() == ESubmitResults::SUBMIT_ACCEPTED)
{
//Get description from the dialog
FChangeListDescription Description;
SourceControlWidget->FillChangeListDescription(Description);
//revert all unchanged files that were submitted
if ( Description.FilesForSubmit.Num() > 0 )
{
SourceControlHelpers::RevertUnchangedFiles(SourceControlProvider, Description.FilesForSubmit);
//make sure all files are still checked out
for (int32 VerifyIndex = Description.FilesForSubmit.Num()-1; VerifyIndex >= 0; --VerifyIndex)
{
FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(Description.FilesForSubmit[VerifyIndex], EStateCacheUsage::Use);
if( SourceControlState.IsValid() && !SourceControlState->IsCheckedOut() && !SourceControlState->IsAdded() && !SourceControlState->IsDeleted() )
{
Description.FilesForSubmit.RemoveAt(VerifyIndex);
}
}
}
TArray<FString> CombinedFileList = Description.FilesForAdd;
CombinedFileList.Append(Description.FilesForSubmit);
if(Description.FilesForAdd.Num() > 0)
{
bCheckInSuccess &= (SourceControlProvider.Execute(ISourceControlOperation::Create<FMarkForAdd>(), Description.FilesForAdd) == ECommandResult::Succeeded);
}
if(CombinedFileList.Num() > 0)
{
TSharedRef<FCheckIn, ESPMode::ThreadSafe> CheckInOperation = ISourceControlOperation::Create<FCheckIn>();
CheckInOperation->SetDescription(Description.Description);
bCheckInSuccess &= (SourceControlProvider.Execute(CheckInOperation, CombinedFileList) == ECommandResult::Succeeded);
if(bCheckInSuccess)
{
// report success with a notification
FNotificationInfo Info(CheckInOperation->GetSuccessMessage());
Info.ExpireDuration = 8.0f;
Info.HyperlinkText = LOCTEXT("SCC_Checkin_ShowLog", "Show Message Log");
Info.Hyperlink = FSimpleDelegate::CreateStatic([](){ FMessageLog("SourceControl").Open(EMessageSeverity::Info, true); });
FSlateNotificationManager::Get().AddNotification(Info);
// also add to the log
FMessageLog("SourceControl").Info(CheckInOperation->GetSuccessMessage());
}
}
if(!bCheckInSuccess)
{
FMessageLog("SourceControl").Notify(LOCTEXT("SCC_Checkin_Failed", "Failed to check in files!"));
}
// If we checked in ok, do we want to to re-check out the files we just checked in?
else
{
if( SourceControlWidget->WantToKeepCheckedOut() == true )
{
// Re-check out files
if(SourceControlProvider.Execute(ISourceControlOperation::Create<FCheckOut>(), CombinedFileList) != ECommandResult::Succeeded)
{
FMessageDialog::Open( EAppMsgType::Ok, LOCTEXT("SCC_Checkin_ReCheckOutFailed", "Failed to re-check out files.") );
}
}
}
}
}
else
{
FMessageLog EditorErrors("EditorErrors");
EditorErrors.Warning(LOCTEXT("NoAssetsToCheckIn", "No assets to check in!"));
EditorErrors.Notify();
}
return bCheckInSuccess;
}
#undef LOCTEXT_NAMESPACE
#endif // SOURCE_CONTROL_WITH_SLATE