Files
PowerToys/src/modules/Projects/ProjectsEditor/ViewModels/MainViewModel.cs

298 lines
10 KiB
C#
Raw Normal View History

2024-05-21 16:55:15 +02:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
2024-05-21 16:55:15 +02:00
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Media.Imaging;
2024-05-28 18:21:30 +02:00
using ManagedCommon;
2024-05-21 16:55:15 +02:00
using ProjectsEditor.Models;
using ProjectsEditor.Utils;
using static ProjectsEditor.Data.ProjectsData;
namespace ProjectsEditor.ViewModels
{
public class MainViewModel : INotifyPropertyChanged, IDisposable
{
private ProjectsEditorIO _projectsEditorIO;
public ObservableCollection<Project> Projects { get; set; }
public IEnumerable<Project> ProjectsView
{
get
{
IEnumerable<Project> projects = string.IsNullOrEmpty(_searchTerm) ? Projects : Projects.Where(x => x.Name.Contains(_searchTerm, StringComparison.InvariantCultureIgnoreCase));
if (projects == null)
{
return Enumerable.Empty<Project>();
}
OrderBy orderBy = (OrderBy)_orderByIndex;
if (orderBy == OrderBy.LastViewed)
{
return projects.OrderByDescending(x => x.LastLaunchedTime);
}
else if (orderBy == OrderBy.Created)
{
return projects.OrderByDescending(x => x.CreationTime);
}
else
{
return projects.OrderBy(x => x.Name);
}
}
}
private string _searchTerm;
public string SearchTerm
{
get => _searchTerm;
set
{
_searchTerm = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(ProjectsView)));
}
}
private int _orderByIndex;
public int OrderByIndex
{
get => _orderByIndex;
set
{
_orderByIndex = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(ProjectsView)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
private Project editedProject;
private bool isEditedProjectNewlyCreated;
private string projectNameBeingEdited;
private MainWindow _mainWindow;
private System.Timers.Timer lastUpdatedTimer;
public MainViewModel(ProjectsEditorIO projectsEditorIO)
{
_projectsEditorIO = projectsEditorIO;
lastUpdatedTimer = new System.Timers.Timer();
lastUpdatedTimer.Interval = 1000;
lastUpdatedTimer.Elapsed += LastUpdatedTimerElapsed;
lastUpdatedTimer.Start();
}
public void Initialize()
{
foreach (Project project in Projects)
{
project.Initialize();
}
OnPropertyChanged(new PropertyChangedEventArgs(nameof(ProjectsView)));
}
public void SetEditedProject(Project editedProject)
{
this.editedProject = editedProject;
}
public void SaveProject(Project projectToSave)
{
editedProject.Name = projectToSave.Name;
editedProject.IsShortcutNeeded = projectToSave.IsShortcutNeeded;
editedProject.PreviewImage = projectToSave.PreviewImage;
for (int appIndex = 0; appIndex < editedProject.Applications.Count; appIndex++)
{
editedProject.Applications[appIndex].IsSelected = projectToSave.Applications[appIndex].IsSelected;
editedProject.Applications[appIndex].CommandLineArguments = projectToSave.Applications[appIndex].CommandLineArguments;
}
editedProject.OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs("AppsCountString"));
editedProject.Initialize();
_projectsEditorIO.SerializeProjects(Projects.ToList());
if (editedProject.IsShortcutNeeded)
{
CreateShortcut(editedProject);
}
}
private void CreateShortcut(Project project)
2024-05-21 16:55:15 +02:00
{
object shDesktop = (object)"Desktop";
IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
string shortcutAddress = (string)shell.SpecialFolders.Item(ref shDesktop) + $"\\{project.Name}.lnk";
2024-05-21 16:55:15 +02:00
IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shortcutAddress);
shortcut.Description = $"Project Launcher {project.Id}";
2024-05-21 16:55:15 +02:00
string basePath = AppDomain.CurrentDomain.BaseDirectory;
shortcut.TargetPath = Path.Combine(basePath, "ProjectsLauncher.exe");
shortcut.Arguments = '"' + project.Id + '"';
2024-05-21 16:55:15 +02:00
shortcut.WorkingDirectory = basePath;
2024-06-12 13:16:34 +02:00
string shortcutIconFilename = (string)shell.SpecialFolders.Item(ref shDesktop) + $"\\{project.Name}.ico";
Bitmap icon = ProjectIcon.DrawIcon(ProjectIcon.IconTextFromProjectName(project.Name));
ProjectIcon.SaveIcon(icon, shortcutIconFilename);
shortcut.IconLocation = shortcutIconFilename;
2024-05-21 16:55:15 +02:00
shortcut.Save();
}
public void SaveProjectName(Project project)
{
projectNameBeingEdited = project.Name;
}
public void CancelProjectName(Project project)
{
project.Name = projectNameBeingEdited;
}
public async void AddNewProject()
{
await Task.Run(() => RunSnapshotTool());
if (_projectsEditorIO.ParseProjects(this).Result == true && Projects.Count != 0)
{
int repeatCounter = 1;
string newName = Projects.Count != 0 ? Projects.Last().Name : "Project 1"; // TODO: localizable project name
while (Projects.Where(x => x.Name.Equals(Projects.Last().Name, StringComparison.Ordinal)).Count() > 1)
{
Projects.Last().Name = $"{newName} ({repeatCounter})";
repeatCounter++;
}
_projectsEditorIO.SerializeProjects(Projects.ToList());
EditProject(Projects.Last(), true);
}
}
public void EditProject(Project selectedProject, bool isNewlyCreated = false)
{
isEditedProjectNewlyCreated = isNewlyCreated;
var editPage = new ProjectEditor(this);
SetEditedProject(selectedProject);
Project projectEdited = new Project(selectedProject) { EditorWindowTitle = isNewlyCreated ? Properties.Resources.CreateProject : Properties.Resources.EditProject };
if (isNewlyCreated)
{
projectEdited.Initialize();
}
editPage.DataContext = projectEdited;
_mainWindow.ShowPage(editPage);
lastUpdatedTimer.Stop();
}
public void CancelLastEdit()
{
if (isEditedProjectNewlyCreated)
{
Projects.Remove(editedProject);
_projectsEditorIO.SerializeProjects(Projects.ToList());
}
}
public void DeleteProject(Project selectedProject)
{
Projects.Remove(selectedProject);
_projectsEditorIO.SerializeProjects(Projects.ToList());
OnPropertyChanged(new PropertyChangedEventArgs(nameof(ProjectsView)));
}
public void SetMainWindow(MainWindow mainWindow)
{
_mainWindow = mainWindow;
}
public void SwitchToMainView()
{
_mainWindow.SwitchToMainView();
SearchTerm = string.Empty;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(SearchTerm)));
lastUpdatedTimer.Start();
}
public void LaunchProject(string projectId)
{
if (!Projects.Where(x => x.Id == projectId).Any())
{
2024-05-28 18:21:30 +02:00
Logger.LogWarning($"Project to launch not find. Id: {projectId}");
2024-05-21 16:55:15 +02:00
return;
}
LaunchProject(Projects.Where(x => x.Id == projectId).First(), true);
}
public async void LaunchProject(Project project, bool exitAfterLaunch = false)
{
2024-05-27 16:33:30 +02:00
await Task.Run(() => RunLauncher(project.Id));
2024-05-21 16:55:15 +02:00
if (_projectsEditorIO.ParseProjects(this).Result == true)
{
2024-05-27 16:33:30 +02:00
OnPropertyChanged(new PropertyChangedEventArgs(nameof(ProjectsView)));
}
2024-05-21 16:55:15 +02:00
if (exitAfterLaunch)
{
2024-05-28 18:21:30 +02:00
Logger.LogInfo($"Launched the project {project.Name}. Exiting.");
2024-05-21 16:55:15 +02:00
Environment.Exit(0);
}
}
private void LastUpdatedTimerElapsed(object sender, ElapsedEventArgs e)
{
if (Projects == null)
{
return;
}
foreach (Project project in Projects)
{
project.OnPropertyChanged(new PropertyChangedEventArgs("LastLaunched"));
}
}
private void RunSnapshotTool(string filename = null)
{
Process p = new Process();
p.StartInfo = new ProcessStartInfo(@".\ProjectsSnapshotTool.exe");
p.StartInfo.CreateNoWindow = true;
if (!string.IsNullOrEmpty(filename))
{
p.StartInfo.Arguments = filename;
}
p.Start();
p.WaitForExit();
}
private void RunLauncher(string projectId)
{
Process p = new Process();
p.StartInfo = new ProcessStartInfo(@".\ProjectsLauncher.exe", projectId);
p.StartInfo.CreateNoWindow = true;
p.Start();
p.WaitForExit();
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
}