using JD.AssetBrowser.ViewModel; using JD.Core; using JD.Perforce; using JetBrains.Annotations; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Input; using JD.Asset; using Plume.Interfaces.WPF; using Plume.Interfaces.WPF.Dialogs; using Ubisoft; namespace Trinity { public class MoveDialogViewModel : INotifyPropertyChanged { private AssetViewModel _selectedFile; private string _newName; private string _newLocation; private string _changeListName = "Rename/move files(s)"; private ICommand _moveCommand; private ICommand _browseCommand; public ICommand MoveCommand => _moveCommand ?? (_moveCommand = new RelayCommand(SafeMoveOrRename)); public ICommand BrowseCommand => _browseCommand ?? (_browseCommand = new RelayCommand(BrowseNewLocation)); public DialogButton MoveButton { get; } public AssetViewModel SelectedFile { get { return _selectedFile; } set { _selectedFile = value; var filesToUpdate = new List { value }; filesToUpdate.AddRange(_selectedFile.Model.ReferencedBy.Select(x => AssetDatabaseViewModel.Instance.GetOrCreateViewModel(x))); FilesToUpdate = filesToUpdate; ChangeListName = $"Renaming/moving {_selectedFile.Name}"; } } public string ChangeListName { get { return _changeListName; } set { if (value == _changeListName) return; _changeListName = value; OnPropertyChanged(); } } public List FilesToUpdate { get; set; } public string Name => SelectedFile != null ? SelectedFile.Name : ""; public string NewName { get { return _newName; } set { if (value == _newName) return; _newName = value; OnPropertyChanged(); } } public string Location => SelectedFile != null ? SelectedFile.IsFolder ? SelectedFile.AbsolutePath : SelectedFile.AbsoluteDirPath : ""; public string NewLocation { get { return _newLocation; } set { if (value == _newLocation) return; _newLocation = value; OnPropertyChanged(); } } public Visibility NameGroupBoxVisibility => SelectedFile.IsFolder ? Visibility.Collapsed : Visibility.Visible; public MoveDialogViewModel() { MoveButton = new DialogButton { Command = MoveCommand, Text = "Move/Rename" }; } public void BrowseNewLocation() { var dialog = new System.Windows.Forms.FolderBrowserDialog { SelectedPath = Location }; var result = dialog.ShowDialog(); if (result != System.Windows.Forms.DialogResult.OK) { return; } NewLocation = dialog.SelectedPath; } public void SafeMoveOrRename() { try { MoveOrRename(); } catch (Exception e) { ShowError(e.ToString()); } } public void MoveOrRename() { if (!P4Manager.Instance.Connected) { ShowError("Not connected to Perforce! Please check the configuration file: " + PerforceUtils.GetConfigFilePath(DataRoot.Value)); return; } if (string.IsNullOrEmpty(NewLocation) && string.IsNullOrEmpty(NewName)) { ShowError("You have to either select a new name or a new location."); return; } var location = string.IsNullOrEmpty(NewLocation) ? Location : NewLocation; var name = string.IsNullOrEmpty(NewName) ? Name : NewName; if (!DataRoot.ExtractRelativePath(location, out _)) { ShowError("The location is not valid. It has to be in the data root."); return; } if (!P4Manager.Instance.PerforceWrapper.IsInClientView(location)) { ShowError("The location is not valid. It has to be in the perforce client view."); return; } var oldPath = Path.GetFullPath(SelectedFile.Model.Path); var newPath = Path.GetFullPath(SelectedFile.IsFolder ? location : Path.Combine(location, name)); var oldRelativePath = SelectedFile.Model.Path.RelativeUri; if (DataRoot.ExtractRelativePath(newPath, out var newRelativePath)) { SelectedFile.Model.Path = new PathInfo(newRelativePath, DataRoot.Value); } else { ShowError($"Unable to extract relative path from \"{newPath}\"."); return; } // Move operation string changelist = P4Manager.Instance.PerforceService.CurrentPendingChangelist.Change; if (string.IsNullOrEmpty(changelist)) { changelist = P4Manager.Instance.PerforceWrapper.GetOrCreatePendingChangelist(ChangeListName); } if (SelectedFile.IsFolder) { P4Manager.Instance.PerforceWrapper.MoveFolder(oldPath, newPath, changelist); } else { P4Manager.Instance.PerforceWrapper.Move(oldPath, newPath, changelist); } // We update paths and references foreach (var file in FilesToUpdate.Except(SelectedFile)) { file.Model.Path = file.Model.Path.ToString().Replace(oldPath, newPath); file.Model.Dependencies.ReplaceAll(oldPath, newPath, StringComparison.InvariantCultureIgnoreCase); file.Model.ReferencedBy.ReplaceAll(oldPath, newPath, StringComparison.InvariantCultureIgnoreCase); } // We open for edit files to update var filesToupdate = FilesToUpdate.Where(x => !x.IsFolder).Select(x => x.AbsolutePath).ToList(); P4Manager.Instance.PerforceWrapper.OpenForEdit(filesToupdate, changelist); // We replace dependent files content foreach (var file in FilesToUpdate.Except(SelectedFile)) { var content = File.ReadAllText(file.AbsolutePath); content = content.Replace(oldRelativePath, newRelativePath, StringComparison.OrdinalIgnoreCase); File.WriteAllText(file.AbsolutePath, content); } var notificationManager = ((IWpfApplication)Application.Current).NotificationManager; notificationManager.ShowSuccess("Move/rename successfull"); } private void ShowError(string message) { var logger = ((IWpfApplication)Application.Current).Logger; logger.Error(message); var notificationManager = ((IWpfApplication)Application.Current).NotificationManager; notificationManager.ShowError(message); } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }