2014-02-17 16:35:24 -08:00
/ *
Copyright ( c ) 2014 , Lars Brubaker
All rights reserved .
Redistribution and use in source and binary forms , with or without
2015-04-08 15:20:10 -07:00
modification , are permitted provided that the following conditions are met :
2014-02-17 16:35:24 -08:00
1. Redistributions of source code must retain the above copyright notice , this
2015-04-08 15:20:10 -07:00
list of conditions and the following disclaimer .
2014-02-17 16:35:24 -08:00
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
2015-04-08 15:20:10 -07:00
and / or other materials provided with the distribution .
2014-02-17 16:35:24 -08:00
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
2015-04-08 15:20:10 -07:00
of the authors and should not be interpreted as representing official policies ,
2014-02-17 16:35:24 -08:00
either expressed or implied , of the FreeBSD Project .
* /
2014-01-29 19:09:30 -08:00
using MatterHackers.Agg.UI ;
2017-03-15 16:17:06 -07:00
using MatterHackers.DataConverters3D ;
2014-01-29 19:09:30 -08:00
using MatterHackers.MatterControl.DataStorage ;
2014-10-11 14:48:10 -07:00
using MatterHackers.MatterControl.PrintQueue ;
2015-04-08 15:20:10 -07:00
using MatterHackers.PolygonMesh.Processors ;
2014-01-29 19:09:30 -08:00
using Newtonsoft.Json ;
2015-04-08 15:20:10 -07:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.IO.Compression ;
using System.Linq ;
2014-01-29 19:09:30 -08:00
namespace MatterHackers.MatterControl
{
2015-04-08 15:20:10 -07:00
internal class ManifestItem
{
public int ItemQuantity { get ; set ; }
public string Name { get ; set ; }
public string FileName { get ; set ; }
}
internal class Project
{
private List < ManifestItem > projectFiles ;
private string projectName = "Test Project" ;
private string projectDateCreated ;
public Project ( )
{
DateTime now = DateTime . Now ;
projectDateCreated = now . ToString ( "s" ) ;
}
public List < ManifestItem > ProjectFiles
{
get
{
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 ProjectFileHandler
{
private Project project ;
private Dictionary < string , ManifestItem > sourceFiles = new Dictionary < string , ManifestItem > ( ) ;
private HashSet < string > addedFileNames = new HashSet < string > ( ) ;
public ProjectFileHandler ( List < PrintItem > projectFiles )
{
if ( projectFiles ! = null )
{
project = new Project ( ) ;
foreach ( PrintItem item in projectFiles )
{
if ( sourceFiles . ContainsKey ( item . FileLocation ) )
{
sourceFiles [ item . FileLocation ] . ItemQuantity = sourceFiles [ item . FileLocation ] . ItemQuantity + 1 ;
}
else
{
string fileNameOnly = Path . GetFileName ( item . FileLocation ) ;
if ( addedFileNames . Contains ( fileNameOnly ) )
{
StyledMessageBox . ShowMessageBox ( null , string . Format ( "Duplicate file name found but in a different folder '{0}'. This part will not be added to the collection.\n\n{1}" , fileNameOnly , item . FileLocation ) , "Duplicate File" ) ;
continue ;
}
addedFileNames . Add ( fileNameOnly ) ;
ManifestItem manifestItem = new ManifestItem ( ) ;
manifestItem . ItemQuantity = 1 ;
manifestItem . Name = item . Name ;
manifestItem . FileName = Path . GetFileName ( item . FileLocation ) ;
sourceFiles . Add ( item . FileLocation , manifestItem ) ;
}
}
List < ManifestItem > manifestFiles = sourceFiles . Values . ToList ( ) ;
project . ProjectFiles = manifestFiles ;
}
}
//Opens Save file dialog and outputs current queue as a project
public void SaveAs ( )
{
SaveFileDialogParams saveParams = new SaveFileDialogParams ( "Save Project|*.zip" ) ;
2014-01-29 19:09:30 -08:00
2014-10-11 15:11:26 -07:00
FileDialog . SaveFileDialog ( saveParams , onSaveFileSelected ) ;
2015-04-08 15:20:10 -07:00
}
2014-01-29 19:09:30 -08:00
2015-04-08 15:20:10 -07:00
private void onSaveFileSelected ( SaveFileDialogParams saveParams )
2014-10-11 15:11:26 -07:00
{
2016-02-12 10:26:40 -08:00
if ( ! string . IsNullOrEmpty ( saveParams . FileName ) )
2014-10-11 15:11:26 -07:00
{
ExportToProjectArchive ( saveParams . FileName ) ;
}
}
2015-08-21 11:04:27 -07:00
private static string applicationDataPath = ApplicationDataStorage . ApplicationUserDataPath ;
2015-04-08 15:20:10 -07:00
private static string archiveStagingFolder = Path . Combine ( applicationDataPath , "data" , "temp" , "project-assembly" ) ;
private static string defaultManifestPathAndFileName = Path . Combine ( archiveStagingFolder , "manifest.json" ) ;
private static string defaultProjectPathAndFileName = Path . Combine ( applicationDataPath , "data" , "default.zip" ) ;
public static void EmptyFolder ( System . IO . DirectoryInfo directory )
{
foreach ( System . IO . FileInfo file in directory . GetFiles ( ) ) file . Delete ( ) ;
foreach ( System . IO . DirectoryInfo subDirectory in directory . GetDirectories ( ) ) subDirectory . Delete ( true ) ;
}
public void ExportToProjectArchive ( string savedFileName = null )
{
if ( savedFileName = = null )
{
savedFileName = defaultProjectPathAndFileName ;
}
//If the temp folder doesn't exist - create it, otherwise clear it
2014-12-03 15:29:11 -08:00
if ( ! Directory . Exists ( archiveStagingFolder ) )
2015-04-08 15:20:10 -07:00
{
2014-12-03 15:29:11 -08:00
Directory . CreateDirectory ( archiveStagingFolder ) ;
2015-04-08 15:20:10 -07:00
}
else
{
2014-12-03 15:29:11 -08:00
System . IO . DirectoryInfo directory = new System . IO . DirectoryInfo ( @archiveStagingFolder ) ;
2015-04-08 15:20:10 -07:00
EmptyFolder ( directory ) ;
}
2014-01-29 19:09:30 -08:00
2015-02-09 19:26:37 -08:00
//Create and save the project manifest file into the temp directory
File . WriteAllText ( defaultManifestPathAndFileName , JsonConvert . SerializeObject ( this . project , Newtonsoft . Json . Formatting . Indented ) ) ;
2014-03-07 10:12:55 -08:00
2014-12-03 15:29:11 -08:00
foreach ( KeyValuePair < string , ManifestItem > item in this . sourceFiles )
{
CopyFileToTempFolder ( item . Key , item . Value . FileName ) ;
}
2015-02-09 19:26:37 -08:00
2016-01-04 21:18:57 -08:00
// Delete or move existing file out of the way as CreateFromDirectory will not overwrite and throws an exception
2015-04-08 15:20:10 -07:00
if ( File . Exists ( savedFileName ) )
2015-02-10 10:56:56 -08:00
{
try
{
File . Delete ( savedFileName ) ;
}
2015-04-08 15:20:10 -07:00
catch ( Exception ex )
2015-02-10 10:56:56 -08:00
{
string directory = Path . GetDirectoryName ( savedFileName ) ;
string fileName = Path . GetFileNameWithoutExtension ( savedFileName ) ;
string extension = Path . GetExtension ( savedFileName ) ;
string candidatePath ;
2015-04-08 15:20:10 -07:00
for ( int i = 1 ; i < 20 ; i + + )
2015-02-10 10:56:56 -08:00
{
candidatePath = Path . Combine ( directory , string . Format ( "{0}({1}){2}" , fileName , i , extension ) ) ;
2015-04-08 15:20:10 -07:00
if ( ! File . Exists ( candidatePath ) )
2015-02-10 10:56:56 -08:00
{
File . Move ( savedFileName , candidatePath ) ;
break ;
}
}
}
}
2015-04-08 15:20:10 -07:00
ZipFile . CreateFromDirectory ( archiveStagingFolder , savedFileName , CompressionLevel . Optimal , true ) ;
2015-02-09 19:26:37 -08:00
}
2014-03-07 10:12:55 -08:00
2014-12-03 15:29:11 -08:00
private static void CopyFileToTempFolder ( string sourceFile , string fileName )
2015-04-08 15:20:10 -07:00
{
if ( File . Exists ( sourceFile ) )
{
2014-12-03 15:29:11 -08:00
try
{
// Will not overwrite if the destination file already exists.
File . Copy ( sourceFile , Path . Combine ( archiveStagingFolder , fileName ) ) ;
}
2014-03-07 10:12:55 -08:00
2015-04-08 15:20:10 -07:00
// Catch exception if the file was already copied.
2014-12-03 15:29:11 -08:00
catch ( IOException copyError )
{
Console . WriteLine ( copyError . Message ) ;
}
2015-04-08 15:20:10 -07:00
}
}
2014-01-29 19:09:30 -08:00
2017-03-15 16:17:06 -07:00
public static List < PrintItem > ImportFromProjectArchive ( string loadedFileName = null )
2015-04-08 15:20:10 -07:00
{
if ( loadedFileName = = null )
{
loadedFileName = defaultProjectPathAndFileName ;
}
2015-08-08 11:25:51 -07:00
if ( ! System . IO . File . Exists ( loadedFileName ) )
{
return null ;
}
2016-01-11 16:43:57 -08:00
try
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
using ( FileStream fs = File . OpenRead ( loadedFileName ) )
using ( ZipArchive zip = new ZipArchive ( fs ) )
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
int projectHashCode = zip . GetHashCode ( ) ;
2015-04-08 15:20:10 -07:00
2016-01-11 16:43:57 -08:00
//If the temp folder doesn't exist - create it, otherwise clear it
string stagingFolder = Path . Combine ( applicationDataPath , "data" , "temp" , "project-extract" , projectHashCode . ToString ( ) ) ;
if ( ! Directory . Exists ( stagingFolder ) )
{
Directory . CreateDirectory ( stagingFolder ) ;
}
else
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
System . IO . DirectoryInfo directory = new System . IO . DirectoryInfo ( @stagingFolder ) ;
EmptyFolder ( directory ) ;
}
2015-04-08 15:20:10 -07:00
2016-01-11 16:43:57 -08:00
List < PrintItem > printItemList = new List < PrintItem > ( ) ;
Project projectManifest = null ;
2015-04-08 15:20:10 -07:00
2016-01-11 16:43:57 -08:00
foreach ( ZipArchiveEntry zipEntry in zip . Entries )
{
string sourceExtension = Path . GetExtension ( zipEntry . Name ) . ToUpper ( ) ;
// Note: directories have empty Name properties
//
// Only process ZipEntries that are:
// - not directories and
// - are in the ValidFileExtension list or
// - have a .GCODE extension or
// - are named manifest.json
if ( ! string . IsNullOrWhiteSpace ( zipEntry . Name ) & &
( zipEntry . Name = = "manifest.json"
| | MeshFileIo . ValidFileExtensions ( ) . Contains ( sourceExtension )
| | sourceExtension = = ".GCODE" ) )
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
string extractedFileName = Path . Combine ( stagingFolder , zipEntry . Name ) ;
2015-04-08 15:20:10 -07:00
2016-01-11 16:43:57 -08:00
string neededPathForZip = Path . GetDirectoryName ( extractedFileName ) ;
if ( ! Directory . Exists ( neededPathForZip ) )
{
Directory . CreateDirectory ( neededPathForZip ) ;
}
using ( Stream zipStream = zipEntry . Open ( ) )
using ( FileStream streamWriter = File . Create ( extractedFileName ) )
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
zipStream . CopyTo ( streamWriter ) ;
}
if ( zipEntry . Name = = "manifest.json" )
{
using ( StreamReader sr = new System . IO . StreamReader ( extractedFileName ) )
{
projectManifest = ( Project ) Newtonsoft . Json . JsonConvert . DeserializeObject ( sr . ReadToEnd ( ) , typeof ( Project ) ) ;
}
2015-04-08 15:20:10 -07:00
}
}
}
2016-01-11 16:43:57 -08:00
if ( projectManifest ! = null )
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
foreach ( ManifestItem item in projectManifest . ProjectFiles )
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
for ( int i = 1 ; i < = item . ItemQuantity ; i + + )
{
2017-03-15 16:17:06 -07:00
printItemList . Add ( new PrintItem ( )
{
FileLocation = Path . Combine ( stagingFolder , item . FileName ) ,
Name = item . Name
} ) ;
2016-01-11 16:43:57 -08:00
}
2015-04-08 15:20:10 -07:00
}
}
2016-01-11 16:43:57 -08:00
else
2015-04-08 15:20:10 -07:00
{
2016-01-11 16:43:57 -08:00
string [ ] files = Directory . GetFiles ( stagingFolder , "*.*" , SearchOption . AllDirectories ) ;
foreach ( string fileName in files )
{
2017-03-15 16:17:06 -07:00
printItemList . Add ( new PrintItem ( )
{
FileLocation = fileName ,
Name = Path . GetFileNameWithoutExtension ( fileName )
} ) ;
2016-01-11 16:43:57 -08:00
}
2015-04-08 15:20:10 -07:00
}
2016-01-11 16:43:57 -08:00
return printItemList ;
}
}
catch
{
return null ;
2015-04-08 15:20:10 -07:00
}
}
}
}