Making the queue a file folder

This commit is contained in:
LarsBrubaker 2022-02-17 08:08:24 -08:00
parent 5bbf1b7ca1
commit 048e20b659
8 changed files with 81 additions and 622 deletions

View file

@ -864,15 +864,25 @@ namespace MatterHackers.MatterControl
forceAddQueue = true;
#endif
// only add the queue if there are items in it
var queueItems = QueueData.Instance.PrintItems.ToList();
if (forceAddQueue || queueItems.Any())
var queueDirectory = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, "Queue");
LegacyQueueFiles.ImportFromLegacy(queueDirectory);
if (forceAddQueue || Directory.Exists(queueDirectory))
{
this.Library.RegisterContainer(
new DynamicContainerLink(
"Print Queue".Localize(),
// make sure the queue directory exists
Directory.CreateDirectory(queueDirectory);
this.Library.RegisterContainer(new DynamicContainerLink(
"Queue".Localize(),
StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png")),
StaticData.Instance.LoadIcon(Path.Combine("Library", "queue_icon.png")),
() => new PrintQueueContainer()));
() => new FileSystemContainer(queueDirectory)
{
UseIncrementedNameDuringTypeChange = true,
DefaultSort = new LibrarySortBehavior()
{
SortKey = SortKey.ModifiedDate,
}
}));
}
this.Library.DesignAppsCollectionContainer = new DesignAppsCollectionContainer();

View file

@ -50,16 +50,6 @@ namespace MatterHackers.MatterControl
HashSet<string> filesToKeep = new HashSet<string>();
// Get a list of all the stl and amf files referenced in the queue.
foreach (PrintItemWrapper printItem in QueueData.Instance.PrintItems)
{
string fileLocation = printItem.FileLocation;
if (!filesToKeep.Contains(fileLocation))
{
filesToKeep.Add(fileLocation);
}
}
var allPrintItems = Datastore.Instance.dbSQLite.Query<PrintItem>("SELECT * FROM PrintItem;");
// Add in all the stl and amf files referenced in the library.

View file

@ -502,40 +502,8 @@ namespace MatterHackers.MatterControl.PrintHistory
primaryFlow.AddChild(timestampColumn);
}
public void ShowCantFindFileMessage(PrintItemWrapper printItemWrapper)
{
itemToRemove = printItemWrapper;
UiThread.RunOnIdle(() =>
{
string maxLengthName = printItemWrapper.FileLocation;
int maxLength = 43;
if (maxLengthName.Length > maxLength)
{
string start = maxLengthName.Substring(0, 15) + "...";
int amountRemaining = maxLength - start.Length;
string end = maxLengthName.Substring(maxLengthName.Length - amountRemaining, amountRemaining);
maxLengthName = start + end;
}
string notFoundMessage = "Oops! Could not find this file".Localize() + ":";
string message = "{0}:\n'{1}'".FormatWith(notFoundMessage, maxLengthName);
string titleLabel = "Item not Found".Localize();
StyledMessageBox.ShowMessageBox(OnConfirmRemove, message, titleLabel, StyledMessageBox.MessageType.OK);
});
}
private PrintItemWrapper itemToRemove;
private PrintTask printTask;
private GuiWidget indicator;
private TextWidget printInfoWidget;
private void OnConfirmRemove(bool messageBoxResponse)
{
if (messageBoxResponse)
{
int index = QueueData.Instance.GetIndex(itemToRemove);
UiThread.RunOnIdle(() => QueueData.Instance.RemoveAt(index));
}
}
}
}

View file

@ -1,170 +0,0 @@
/*
Copyright (c) 2022, John Lewin, Lars Brubaker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
namespace MatterHackers.MatterControl.Library
{
public class PrintQueueContainer : WritableContainer
{
public PrintQueueContainer()
{
this.IsProtected = false;
this.ChildContainers = new SafeList<ILibraryContainerLink>();
this.Items = new SafeList<ILibraryItem>();
this.Name = "Print Queue".Localize();
}
public override void Load()
{
var queueItems = QueueData.Instance.PrintItems.ToList();
var existingItems = queueItems.Where(p => File.Exists(p.FileLocation)).ToList();
var missingItems = queueItems.Except(existingItems).ToList();
this.Items = new SafeList<ILibraryItem>(existingItems.Select(p => new FileSystemFileItem(p.FileLocation)
{
Name = p.Name
})
.Concat<ILibraryItem>(missingItems.Select(p => new MissingFileItem(p.Name))));
}
public override async void Add(IEnumerable<ILibraryItem> items)
{
await AddAllItems(items);
this.ReloadContent();
}
public override void Save(ILibraryItem item, IObject3D content)
{
if (item is FileSystemFileItem fileItem)
{
// save using the normal uncompressed mcx file
// Serialize the scene to disk using a modified Json.net pipeline with custom ContractResolvers and JsonConverters
File.WriteAllText(fileItem.FilePath, content.ToJson().Result);
this.OnItemContentChanged(new LibraryItemChangedEventArgs(fileItem));
}
}
public override void SetThumbnail(ILibraryItem item, int width, int height, ImageBuffer imageBuffer)
{
#if DEBUG
//throw new NotImplementedException();
#endif
}
public static async Task AddAllItems(IEnumerable<ILibraryItem> items)
{
await Task.Run(async () =>
{
foreach (var item in items)
{
switch (item)
{
case ILibraryAssetStream streamItem:
string itemPath;
if (streamItem is FileSystemFileItem fileItem)
{
// Get existing file path
itemPath = fileItem.FilePath;
}
else
{
// Copy stream to library path
itemPath = ApplicationDataStorage.Instance.GetNewLibraryFilePath("." + streamItem.ContentType);
using (var outputStream = File.OpenWrite(itemPath))
{
using (var streamInteface = await streamItem.GetStream(null))
{
streamInteface.Stream.CopyTo(outputStream);
}
}
}
// Add to Queue
if (File.Exists(itemPath))
{
QueueData.Instance.AddItem(
new PrintItemWrapper(
new PrintItem(streamItem.Name, itemPath)),
0);
}
break;
}
}
});
}
public override void Remove(IEnumerable<ILibraryItem> items)
{
foreach (var fileSystemItem in items.OfType<FileSystemFileItem>())
{
if (fileSystemItem != null)
{
var matches = QueueData.Instance.PrintItems.Where(p => p.FileLocation == fileSystemItem.FilePath).ToList();
foreach(var printItem in matches)
{
int index = QueueData.Instance.GetIndex(printItem);
if (index != -1)
{
QueueData.Instance.RemoveAt(index);
}
}
}
}
this.ReloadContent();
}
public override bool AllowAction(ContainerActions containerActions)
{
return containerActions != ContainerActions.AddContainers;
}
public override void Dispose()
{
}
}
}

View file

@ -1,302 +0,0 @@
/*
Copyright (c) 2017, Kevin Pope, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using MatterHackers.Agg;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.PolygonMesh.Processors;
namespace MatterHackers.MatterControl.PrintQueue
{
public class ItemChangedArgs : EventArgs
{
public int Index { get; private set; }
internal ItemChangedArgs(int index)
{
this.Index = index;
}
}
public class QueueData
{
public static readonly string SdCardFileName = "SD_CARD";
private List<PrintItemWrapper> printItems = new List<PrintItemWrapper>();
public List<PrintItemWrapper> PrintItems
{
get { return printItems; }
}
public RootedObjectEventHandler ItemAdded = new RootedObjectEventHandler();
public RootedObjectEventHandler ItemRemoved = new RootedObjectEventHandler();
private static QueueData instance;
public static QueueData Instance
{
get
{
if (instance == null)
{
instance = new QueueData();
instance.LoadDefaultQueue();
}
return instance;
}
}
public void RemoveAt(int index)
{
if (index >= 0 && index < ItemCount)
{
PrintItems.RemoveAt(index);
OnItemRemoved(new ItemChangedArgs(index));
SaveDefaultQueue();
}
}
public void OnItemRemoved(EventArgs e)
{
ItemRemoved.CallEvents(this, e);
}
public PrintItemWrapper GetPrintItemWrapper(int index)
{
if (index >= 0 && index < PrintItems.Count)
{
return PrintItems[index];
}
return null;
}
public int GetIndex(PrintItemWrapper printItem)
{
return PrintItems.IndexOf(printItem);
}
public string[] GetItemNames()
{
List<string> itemNames = new List<string>();
for (int i = 0; i < PrintItems.Count; i++)
{
itemNames.Add(PrintItems[i].Name);
}
return itemNames.ToArray();
}
public string GetItemName(int itemIndex)
{
return PrintItems[itemIndex].Name;
}
public List<PrintItem> CreateReadOnlyPartList(bool includeProtectedItems)
{
List<PrintItem> listToReturn = new List<PrintItem>();
for (int i = 0; i < ItemCount; i++)
{
var printItem = GetPrintItemWrapper(i).PrintItem;
if (includeProtectedItems
|| !printItem.Protected)
{
listToReturn.Add(printItem);
}
}
return listToReturn;
}
private static readonly bool Is32Bit = IntPtr.Size == 4;
private PrintItemWrapper partUnderConsideration = null;
public enum ValidateSizeOn32BitSystems { Required, Skip }
public void AddItem(PrintItemWrapper item, int indexToInsert = -1, ValidateSizeOn32BitSystems checkSize = ValidateSizeOn32BitSystems.Required)
{
if (Is32Bit)
{
// Check if the part we are adding is BIG. If it is warn the user and
// possibly don't add it
bool warnAboutFileSize = false;
long estimatedMemoryUse = 0;
if (File.Exists(item.FileLocation)
&& checkSize == ValidateSizeOn32BitSystems.Required)
{
estimatedMemoryUse = GetEstimatedMemoryUse(item.FileLocation);
// If we have less than 2 gigs memory, warn on smaller file size
if (AggContext.PhysicalMemory < 2000000000)
{
if (estimatedMemoryUse > 100000000)
{
warnAboutFileSize = true;
}
}
else
{
if (estimatedMemoryUse > 500000000)
{
warnAboutFileSize = true;
}
}
}
if (warnAboutFileSize)
{
partUnderConsideration = item;
// Show a dialog and only load the part to the queue if the user clicks yes.
UiThread.RunOnIdle(() =>
{
string memoryWarningMessage = "Are you sure you want to add this part ({0}) to the Queue?\nThe 3D part you are trying to load may be too complicated and cause performance or stability problems.\n\nConsider reducing the geometry before proceeding.".Localize().FormatWith(item.Name);
StyledMessageBox.ShowMessageBox(
UserSaidToAllowAddToQueue, memoryWarningMessage, "File May Cause Problems".Localize(), StyledMessageBox.MessageType.YES_NO, "Add To Queue", "Do Not Add");
// show a dialog to tell the user there is an update
});
return;
}
else
{
DoAddItem(item, indexToInsert);
}
}
else
{
DoAddItem(item, indexToInsert);
}
}
public static long GetEstimatedMemoryUse(string fileLocation)
{
switch (Path.GetExtension(fileLocation).ToUpper())
{
case ".STL":
return StlProcessing.GetEstimatedMemoryUse(fileLocation);
case ".3MF":
case ".AMF":
return AmfDocument.GetEstimatedMemoryUse(fileLocation);
case ".OBJ":
throw new NotImplementedException();
}
return 0;
}
private void UserSaidToAllowAddToQueue(bool messageBoxResponse)
{
if (messageBoxResponse)
{
DoAddItem(partUnderConsideration, -1);
}
}
private void DoAddItem(PrintItemWrapper item, int insertAt)
{
if (insertAt == -1)
{
insertAt = PrintItems.Count;
}
PrintItems.Insert(insertAt, item);
OnItemAdded(new ItemChangedArgs(insertAt));
SaveDefaultQueue();
}
public void LoadDefaultQueue()
{
RemoveAll();
ManifestFileHandler manifest = new ManifestFileHandler(null);
List<PrintItem> partFiles = manifest.ImportFromJson();
if (partFiles != null)
{
foreach (PrintItem item in partFiles)
{
AddItem(new PrintItemWrapper(item), -1, QueueData.ValidateSizeOn32BitSystems.Skip);
}
}
RemoveAllSdCardFiles();
}
public void RemoveAllSdCardFiles()
{
for (int i = ItemCount - 1; i >= 0; i--)
{
PrintItem printItem = PrintItems[i].PrintItem;
if (printItem.FileLocation == QueueData.SdCardFileName)
{
RemoveAt(i);
}
}
}
public void OnItemAdded(EventArgs e)
{
ItemAdded.CallEvents(this, e);
}
public void SaveDefaultQueue()
{
List<PrintItem> partList = CreateReadOnlyPartList(true);
ManifestFileHandler manifest = new ManifestFileHandler(partList);
manifest.ExportToJson();
}
public int ItemCount
{
get
{
return PrintItems.Count;
}
}
public void RemoveAll()
{
for (int i = PrintItems.Count - 1; i >= 0; i--)
{
RemoveAt(i);
}
}
}
}

View file

@ -216,9 +216,6 @@ namespace MatterHackers.MatterControl
ApplicationSettings.Instance.set(ApplicationSettingsKey.DesktopPosition, string.Format("{0},{1}", DesktopPosition.x, DesktopPosition.y));
}
// Save a snapshot of the prints in queue
QueueData.Instance.SaveDefaultQueue();
// If we are waiting for a response and get another request, just cancel the close until we get a response.
if (exitDialogOpen)
{

View file

@ -35,113 +35,79 @@ using Newtonsoft.Json;
namespace MatterHackers.MatterControl
{
internal class ManifestFile
public class QueueData
{
private static QueueData instance;
public static QueueData Instance
{
get
{
if (instance == null)
{
instance = new QueueData();
}
return instance;
}
}
public int ItemCount
{
get
{
throw new NotImplementedException();
}
}
public void AddItem(string filePath)
{
throw new NotImplementedException();
}
public string GetFirstItem()
{
throw new NotImplementedException();
}
public IEnumerable<string> GetItemNames()
{
throw new NotImplementedException();
}
}
public class LegacyQueueFiles
{
private List<PrintItem> projectFiles;
private string projectName = "Test Project";
private string projectDateCreated;
public List<PrintItem> ProjectFiles { get; set; }
public ManifestFile()
public static void ImportFromLegacy(string destPath)
{
DateTime now = DateTime.Now;
projectDateCreated = now.ToString("s");
}
var filePath = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "default.mcp");
public List<PrintItem> ProjectFiles
{
get
if (!File.Exists(filePath))
{
return projectFiles;
}
set
{
projectFiles = value;
}
}
public string ProjectName
{
get
{
return projectName;
}
set
{
projectName = value;
}
}
public string ProjectDateCreated
{
get
{
return projectDateCreated;
}
set
{
projectDateCreated = value;
}
}
}
internal class ManifestFileHandler
{
private ManifestFile project;
public ManifestFileHandler(List<PrintItem> projectFiles)
{
if (projectFiles != null)
{
project = new ManifestFile();
project.ProjectFiles = projectFiles;
}
}
private static string applicationDataPath = ApplicationDataStorage.ApplicationUserDataPath;
private static string defaultPathAndFileName = Path.Combine(applicationDataPath , "data", "default.mcp");
public void ExportToJson(string savedFileName = null)
{
if (savedFileName == null)
{
savedFileName = defaultPathAndFileName;
}
string jsonString = JsonConvert.SerializeObject(this.project, Newtonsoft.Json.Formatting.Indented);
string pathToDataFolder = Path.Combine(applicationDataPath, "data");
if (!Directory.Exists(pathToDataFolder))
{
Directory.CreateDirectory(pathToDataFolder);
}
File.WriteAllText(savedFileName, jsonString);
}
public List<PrintItem> ImportFromJson(string filePath = null)
{
if (filePath == null)
{
filePath = defaultPathAndFileName;
}
if (!System.IO.File.Exists(filePath))
{
return null;
// nothing to do
return;
}
string json = File.ReadAllText(filePath);
ManifestFile newProject = JsonConvert.DeserializeObject<ManifestFile>(json);
if (newProject == null)
{
return new List<PrintItem>();
}
LegacyQueueFiles newProject = JsonConvert.DeserializeObject<LegacyQueueFiles>(json);
if (newProject.ProjectFiles.Count == 0)
{
return;
}
return newProject.ProjectFiles;
Directory.CreateDirectory(destPath);
foreach (var printItem in newProject.ProjectFiles)
{
var destFile = Path.Combine(destPath, Path.ChangeExtension(printItem.Name, Path.GetExtension(printItem.FileLocation)));
if (!File.Exists(destFile)
&& File.Exists(printItem.FileLocation))
{
// copy the print item to the destination directory
File.Copy(printItem.FileLocation, destFile, true);
}
}
}
}
}

View file

@ -626,13 +626,13 @@ namespace MatterHackers.MatterControl.Tests.Automation
if (!File.Exists(mcpPath))
{
File.WriteAllText(mcpPath, JsonConvert.SerializeObject(new ManifestFile()
File.WriteAllText(mcpPath, JsonConvert.SerializeObject(new LegacyQueueFiles()
{
ProjectFiles = new List<PrintItem>()
}, Formatting.Indented));
}
var queueItemData = JsonConvert.DeserializeObject<ManifestFile>(File.ReadAllText(mcpPath));
var queueItemData = JsonConvert.DeserializeObject<LegacyQueueFiles>(File.ReadAllText(mcpPath));
string queueData = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "testitems");