Compare commits

...

11 Commits

Author SHA1 Message Date
e66eea0c83 Format 2025-02-28 16:11:48 -07:00
3044da0413 v2.14 2020-08-09 17:29:41 +02:00
7cb819d401 Update template
* Faster display after searching large amount of files
* Also show "searching..." indicator.
* Fix [..] position
2020-08-09 17:29:25 +02:00
b3476e455a Bugfix: UNC paths stopped working since 2.1 2020-08-09 13:31:17 +02:00
a68b36c02e version 2.13 2020-05-05 20:20:27 +02:00
87914ff327 Be more specific on StreamWriter and template encoding to avoid EncoderFallbackException 2020-05-05 18:16:38 +02:00
1726eb9301 version 2.12 2020-04-29 19:20:13 +02:00
8156351973 Rework how to read and execute command line to fix issues introduced in last version. Now command line is completely separate from GUI. 2020-04-29 19:05:29 +02:00
fa80b22ad0 Make parent folder [..] sticky 2020-04-29 19:02:28 +02:00
2ef355bb2d Add "onlyLinkExtensions" variable in template to allow customizing what files to link 2020-04-28 19:12:52 +02:00
a622e419a1 Get ful path from model on-the-fly to reduce memory consumsion 2020-04-28 19:12:04 +02:00
17 changed files with 1579 additions and 1145 deletions

1
.vscode/format-report.json vendored Normal file
View File

@ -0,0 +1 @@
[]

19
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,19 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
},
{
"type": "node",
"request": "launch",
"name": "node Launch Current Opened File",
"program": "${file}"
}
]
}

31
.vscode/mklink.md vendored Normal file
View File

@ -0,0 +1,31 @@
---
type: "note"
created: "2023-10-20T03:53:13.742Z"
updated: "2023-10-20T04:00:37.259Z"
---
# mklink
```bash
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper"
```
```bash
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper"
```
```bash
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode"
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss"
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders"
mkdir "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish"
mkdir "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish"
mkdir "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish"
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode" "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.111.0"
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss" "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.111.0"
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders" "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.111.0"
```
```bash Thu Jul 18 2024 13:47:40 GMT-0700 (Mountain Standard Time)
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.vscode\.UserSecrets" "C:\Users\phares\AppData\Roaming\Microsoft\UserSecrets\8da397d4-13ec-4576-9722-3c79cad25563"
```

20
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
"[markdown]": {
"editor.wordWrap": "off"
},
"cSpell.words": [
"Amstrad",
"doesnt",
"dont",
"Doubleclick",
"Finalizers",
"harddrive",
"propval",
"propvals",
"refrences",
"SETTINGSROOT",
"subdirs",
"subfolders",
"treeview"
]
}

163
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,163 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "User Secrets Init",
"command": "dotnet",
"type": "process",
"args": [
"user-secrets",
"-p",
"${workspaceFolder}/Snap2HTML.sln",
"init"
],
"problemMatcher": "$msCompile"
},
{
"label": "User Secrets Set",
"command": "dotnet",
"type": "process",
"args": [
"user-secrets",
"-p",
"${workspaceFolder}/Snap2HTML.sln",
"set",
"_UserSecretsId",
"0c43f9aa-96e9-4298-967c-ed069d79e262"
],
"problemMatcher": "$msCompile"
},
{
"label": "Format",
"command": "dotnet",
"type": "process",
"args": [
"format",
"--report",
".vscode",
"--verbosity",
"detailed",
"--severity",
"warn"
],
"problemMatcher": "$msCompile"
},
{
"label": "Format-Whitespaces",
"command": "dotnet",
"type": "process",
"args": [
"format",
"whitespace"
],
"problemMatcher": "$msCompile"
},
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"-r",
"win-x64",
"${workspaceFolder}/Snap2HTML.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "build Linux",
"command": "dotnet",
"type": "process",
"args": [
"build",
"-r",
"linux-x64",
"${workspaceFolder}/Snap2HTML.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Snap2HTML.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/Snap2HTML.sln"
],
"problemMatcher": "$msCompile"
},
{
"label": "Publish AOT",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"-r",
"win-x64",
"-c",
"Release",
"-p:PublishAot=true",
"${workspaceFolder}/Snap2HTML.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "Publish AOT Linux",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"-r",
"linux-x64",
"-c",
"Release",
"-p:PublishAot=true",
"${workspaceFolder}/Snap2HTML.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "MSBuild for EAF Deployment Packages",
"command": "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe",
"type": "process",
"args": [
"/target:Build",
"/restore:True",
"/p:RestoreSources=https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/%3Bhttps://tfs.intra.infineon.com/tfs/FactoryIntegration/_packaging/EAF/nuget/v3/index.json%3Bhttps://tfs.intra.infineon.com/tfs/FactoryIntegration/_packaging/EAF%40Local/nuget/v3/index.json%3Bhttps://api.nuget.org/v3/index.json",
"/detailedsummary",
"/consoleloggerparameters:PerformanceSummary;ErrorsOnly;",
"/property:Configuration=Debug;TargetFrameworkVersion=v4.8",
"Snap2HTML.sln"
],
"problemMatcher": "$msCompile"
},
{
"label": "Jest",
"type": "shell",
"command": "npx jest",
"problemMatcher": []
}
]
}

View File

@ -120,7 +120,7 @@ namespace CommandLine.Utility
// MOD: Don't split on commas // MOD: Don't split on commas
//AddListValues(parts[1], valuesWithoutQuotes.Split(',')); //AddListValues(parts[1], valuesWithoutQuotes.Split(','));
Add( parts[1], valuesWithoutQuotes ); Add(parts[1], valuesWithoutQuotes);
break; break;
} }
} }

View File

@ -15,12 +15,21 @@ namespace Snap2HTML
public bool openInBrowser { get; set; } public bool openInBrowser { get; set; }
public bool linkFiles { get; set; } public bool linkFiles { get; set; }
public string linkRoot { get; set; } public string linkRoot { get; set; }
public SnapSettings()
{
this.skipHiddenItems = true;
this.skipSystemItems = true;
this.openInBrowser = false;
this.linkFiles = false;
this.linkRoot = "";
}
} }
public class SnappedFile public class SnappedFile
{ {
public SnappedFile( string name ) public SnappedFile(string name)
{ {
this.Name = name; this.Name = name;
this.Properties = new Dictionary<string, string>(); this.Properties = new Dictionary<string, string>();
@ -29,9 +38,9 @@ namespace Snap2HTML
public string Name { get; set; } public string Name { get; set; }
public Dictionary<string, string> Properties { get; set; } public Dictionary<string, string> Properties { get; set; }
public string GetProp( string key ) public string GetProp(string key)
{ {
if( this.Properties.ContainsKey( key ) ) if (this.Properties.ContainsKey(key))
return this.Properties[key]; return this.Properties[key];
else else
return ""; return "";
@ -41,24 +50,43 @@ namespace Snap2HTML
public class SnappedFolder public class SnappedFolder
{ {
public SnappedFolder( string name, string path ) public SnappedFolder(string name, string path)
{ {
this.Name = name; this.Name = name;
this.Path = path; this.Path = path;
this.Properties = new Dictionary<string, string>(); this.Properties = new Dictionary<string, string>();
this.Files = new List<SnappedFile>(); this.Files = new List<SnappedFile>();
this.FullPath = ( this.Path + "\\" + this.Name ).Replace( "\\\\", "\\" );
} }
public string Name { get; set; } public string Name { get; set; }
public string Path { get; set; } public string Path { get; set; }
public string FullPath { get; set; }
public Dictionary<string, string> Properties { get; set; } public Dictionary<string, string> Properties { get; set; }
public List<SnappedFile> Files { get; set; } public List<SnappedFile> Files { get; set; }
public string GetProp( string key ) public string GetFullPath()
{ {
if( this.Properties.ContainsKey( key ) ) string path;
if (this.Path.EndsWith(@"\"))
path = this.Path + this.Name;
else
path = this.Path + @"\" + this.Name;
if (path.EndsWith(@"\")) // remove trailing backslash
{
if (!Utils.IsWildcardMatch(@"?:\", path, false)) // except for drive letters
{
path = path.Remove(path.Length - 1);
}
}
return path;
}
public string GetProp(string key)
{
if (this.Properties.ContainsKey(key))
return this.Properties[key]; return this.Properties[key];
else else
return ""; return "";

View File

@ -4,30 +4,36 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Collections.Specialized;
using System.Configuration; using System.Configuration;
using System.Configuration.Provider; using System.Configuration.Provider;
using System.Windows.Forms;
using System.Collections.Specialized;
using Microsoft.Win32;
using System.Xml;
using System.IO; using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Win32;
public class PortableSettingsProvider : SettingsProvider { public class PortableSettingsProvider : SettingsProvider
{
const string SETTINGSROOT = "Settings"; const string SETTINGSROOT = "Settings";
//XML Root Node //XML Root Node
public override void Initialize(string name, NameValueCollection col) { public override void Initialize(string name, NameValueCollection col)
{
base.Initialize(this.ApplicationName, col); base.Initialize(this.ApplicationName, col);
} }
public override string ApplicationName { public override string ApplicationName
get { {
if (Application.ProductName.Trim().Length > 0) { get
{
if (Application.ProductName.Trim().Length > 0)
{
return Application.ProductName; return Application.ProductName;
} }
else { else
{
FileInfo fi = new FileInfo(Application.ExecutablePath); FileInfo fi = new FileInfo(Application.ExecutablePath);
return fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length); return fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length);
} }
@ -36,41 +42,50 @@ public class PortableSettingsProvider : SettingsProvider {
//Do nothing //Do nothing
} }
public override string Name { public override string Name
{
get { return "PortableSettingsProvider"; } get { return "PortableSettingsProvider"; }
} }
public virtual string GetAppSettingsPath() { public virtual string GetAppSettingsPath()
{
//Used to determine where to store the settings //Used to determine where to store the settings
System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath); System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath);
return fi.DirectoryName; return fi.DirectoryName;
} }
public virtual string GetAppSettingsFilename() { public virtual string GetAppSettingsFilename()
{
//Used to determine the filename to store the settings //Used to determine the filename to store the settings
return ApplicationName + ".settings"; return ApplicationName + ".settings";
} }
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals) { public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
//Iterate through the settings to be stored //Iterate through the settings to be stored
//Only dirty settings are included in propvals, and only ones relevant to this provider //Only dirty settings are included in propvals, and only ones relevant to this provider
foreach (SettingsPropertyValue propval in propvals) { foreach (SettingsPropertyValue propval in propvals)
{
SetValue(propval); SetValue(propval);
} }
try { try
{
SettingsXML.Save(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename())); SettingsXML.Save(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename()));
} }
catch (Exception ex) { catch (Exception)
{
} }
//Ignore if cant save, device been ejected //Ignore if cant save, device been ejected
} }
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props) { public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props)
{
//Create new collection of values //Create new collection of values
SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();
//Iterate through the settings to be retrieved //Iterate through the settings to be retrieved
foreach (SettingsProperty setting in props) { foreach (SettingsProperty setting in props)
{
SettingsPropertyValue value = new SettingsPropertyValue(setting); SettingsPropertyValue value = new SettingsPropertyValue(setting);
value.IsDirty = false; value.IsDirty = false;
@ -82,17 +97,22 @@ public class PortableSettingsProvider : SettingsProvider {
private XmlDocument _settingsXML = null; private XmlDocument _settingsXML = null;
private XmlDocument SettingsXML { private XmlDocument SettingsXML
get { {
get
{
//If we dont hold an xml document, try opening one. //If we dont hold an xml document, try opening one.
//If it doesnt exist then create a new one ready. //If it doesnt exist then create a new one ready.
if (_settingsXML == null) { if (_settingsXML == null)
{
_settingsXML = new XmlDocument(); _settingsXML = new XmlDocument();
try { try
{
_settingsXML.Load(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename())); _settingsXML.Load(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename()));
} }
catch (Exception ex) { catch (Exception)
{
//Create new document //Create new document
XmlDeclaration dec = _settingsXML.CreateXmlDeclaration("1.0", "utf-8", string.Empty); XmlDeclaration dec = _settingsXML.CreateXmlDeclaration("1.0", "utf-8", string.Empty);
_settingsXML.AppendChild(dec); _settingsXML.AppendChild(dec);
@ -108,23 +128,30 @@ public class PortableSettingsProvider : SettingsProvider {
} }
} }
private string GetValue(SettingsProperty setting) { private string GetValue(SettingsProperty setting)
{
string ret = ""; string ret = "";
try { try
if (IsRoaming(setting)) { {
if (IsRoaming(setting))
{
ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + setting.Name).InnerText; ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + setting.Name).InnerText;
} }
else { else
{
ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + setting.Name).InnerText; ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + setting.Name).InnerText;
} }
} }
catch (Exception ex) { catch (Exception)
if ((setting.DefaultValue != null)) { {
if ((setting.DefaultValue != null))
{
ret = setting.DefaultValue.ToString(); ret = setting.DefaultValue.ToString();
} }
else { else
{
ret = ""; ret = "";
} }
} }
@ -132,7 +159,8 @@ public class PortableSettingsProvider : SettingsProvider {
return ret; return ret;
} }
private void SetValue(SettingsPropertyValue propVal) { private void SetValue(SettingsPropertyValue propVal)
{
XmlElement MachineNode = default(XmlElement); XmlElement MachineNode = default(XmlElement);
XmlElement SettingNode = default(XmlElement); XmlElement SettingNode = default(XmlElement);
@ -140,42 +168,53 @@ public class PortableSettingsProvider : SettingsProvider {
//Determine if the setting is roaming. //Determine if the setting is roaming.
//If roaming then the value is stored as an element under the root //If roaming then the value is stored as an element under the root
//Otherwise it is stored under a machine name node //Otherwise it is stored under a machine name node
try { try
if (IsRoaming(propVal.Property)) { {
if (IsRoaming(propVal.Property))
{
SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + propVal.Name); SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + propVal.Name);
} }
else { else
{
SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + propVal.Name); SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + propVal.Name);
} }
} }
catch (Exception ex) { catch (Exception)
{
SettingNode = null; SettingNode = null;
} }
//Check to see if the node exists, if so then set its new value //Check to see if the node exists, if so then set its new value
if ((SettingNode != null)) { if ((SettingNode != null))
{
SettingNode.InnerText = propVal.SerializedValue.ToString(); SettingNode.InnerText = propVal.SerializedValue.ToString();
} }
else { else
if (IsRoaming(propVal.Property)) { {
if (IsRoaming(propVal.Property))
{
//Store the value as an element of the Settings Root Node //Store the value as an element of the Settings Root Node
SettingNode = SettingsXML.CreateElement(propVal.Name); SettingNode = SettingsXML.CreateElement(propVal.Name);
SettingNode.InnerText = propVal.SerializedValue.ToString(); SettingNode.InnerText = propVal.SerializedValue.ToString();
SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(SettingNode); SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(SettingNode);
} }
else { else
{
//Its machine specific, store as an element of the machine name node, //Its machine specific, store as an element of the machine name node,
//creating a new machine name node if one doesnt exist. //creating a new machine name node if one doesnt exist.
try { try
{
MachineNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName); MachineNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName);
} }
catch (Exception ex) { catch (Exception)
{
MachineNode = SettingsXML.CreateElement(Environment.MachineName); MachineNode = SettingsXML.CreateElement(Environment.MachineName);
SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode); SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode);
} }
if (MachineNode == null) { if (MachineNode == null)
{
MachineNode = SettingsXML.CreateElement(Environment.MachineName); MachineNode = SettingsXML.CreateElement(Environment.MachineName);
SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode); SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode);
} }
@ -187,11 +226,14 @@ public class PortableSettingsProvider : SettingsProvider {
} }
} }
private bool IsRoaming(SettingsProperty prop) { private bool IsRoaming(SettingsProperty prop)
{
//Determine if the setting is marked as Roaming //Determine if the setting is marked as Roaming
foreach (DictionaryEntry d in prop.Attributes) { foreach (DictionaryEntry d in prop.Attributes)
{
Attribute a = (Attribute)d.Value; Attribute a = (Attribute)d.Value;
if (a is System.Configuration.SettingsManageabilityAttribute) { if (a is System.Configuration.SettingsManageabilityAttribute)
{
return true; return true;
} }
} }

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("RL Vision")] [assembly: AssemblyCompany("RL Vision")]
[assembly: AssemblyProduct("Snap2HTML")] [assembly: AssemblyProduct("Snap2HTML")]
[assembly: AssemblyCopyright( "Copyright © RL Vision 2011-2020" )] [assembly: AssemblyCopyright("Copyright © RL Vision 2011-2020")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion( "2.11.0.0" )] [assembly: AssemblyVersion("2.14.0.0")]
[assembly: AssemblyFileVersion( "2.11.0.0" )] [assembly: AssemblyFileVersion("2.14.0.0")]

View File

@ -99,9 +99,9 @@
Starts the program with the given root path already set Starts the program with the given root path already set
Full: Snap2HTMl.exe [-path:"root folder path"] [-outfile:"filename"] Full: Snap2HTMl.exe -path:"root folder path" -outfile:"filename"
[-link:"link to path"] [-title:"page title"] [-link:"link to path"] [-title:"page title"]
[-hidden] [-system] [-hidden] [-system] [-silent]
-path:"root folder path" - The root path to load. -path:"root folder path" - The root path to load.
Example: -path:"c:\temp" Example: -path:"c:\temp"
@ -113,7 +113,8 @@
-link:"link to path" - The path to link files to. -link:"link to path" - The path to link files to.
Example: -link:"c:\temp" Example: -link:"c:\temp"
-title:"page title" - Set the page title -title:"page title" - Set the page title. If omitted, title
is generated based on path.
-hidden - Include hidden items -hidden - Include hidden items
@ -122,14 +123,16 @@
-silent - Run without showing the window (only -silent - Run without showing the window (only
if both -path and -outfile are used) if both -path and -outfile are used)
Notes: When both -path and -outfile are specified, the program will
Notes: Using -path and -outfile will cause the program to automatically automatically start generating the snapshot, and quit when done.
start generating the snapshot, and quit when done!
Always surround paths and filenames with quotes ("")! Always surround paths and filenames with quotes ("")!
Do not include the [sqaure brackets] when you write your command In silent mode, in case or error the program will just quit
line. (Sqaure brackets signify optional command line parameters) without telling why.
Do not include the [square brackets] when you write your command
line. (Square brackets signify optional command line parameters)
--- Template Design --------------------------------------------------------- --- Template Design ---------------------------------------------------------
@ -229,6 +232,20 @@
v2.11 (2020-04-18) v2.11 (2020-04-18)
Fixed a threading issue that caused the program to hang on some systems Fixed a threading issue that caused the program to hang on some systems
v2.12 (2020-04-29)
Reduced memory consumption when generating HTML
Parent folder link [..] is now sticky
Reworked command line code to fix issues in 2.11
A few small tweaks too
v2.13 (2020-05-05)
Fixed an encoding issue causing EncoderFallbackException while saving
v2.14 (2020-08-09)
UNC paths work again (including linking)
Searches returning lots of items should be a bit faster now
And a few smaller fixes as usual
--- End User License Agreement ----------------------------------------------- --- End User License Agreement -----------------------------------------------

View File

@ -1,4 +1,5 @@
namespace Snap2HTML.Properties { namespace Snap2HTML.Properties
{
// This class allows you to handle specific events on the settings class: // This class allows you to handle specific events on the settings class:
// The SettingChanging event is raised before a setting's value is changed. // The SettingChanging event is raised before a setting's value is changed.
// The PropertyChanged event is raised after a setting's value is changed. // The PropertyChanged event is raised after a setting's value is changed.
@ -18,19 +19,19 @@
this.SettingsLoaded += this.SettingsLoadedEventHandler; this.SettingsLoaded += this.SettingsLoadedEventHandler;
} }
private void SettingChangingEventHandler( object sender, System.Configuration.SettingChangingEventArgs e ) private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e)
{ {
// Add code to handle the SettingChangingEvent event here. // Add code to handle the SettingChangingEvent event here.
} }
private void SettingsSavingEventHandler( object sender, System.ComponentModel.CancelEventArgs e ) private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e)
{ {
// Add code to handle the SettingsSaving event here. // Add code to handle the SettingsSaving event here.
System.Console.WriteLine( "Settings Saving..." ); System.Console.WriteLine("Settings Saving...");
} }
private void SettingsLoadedEventHandler( object sender, System.Configuration.SettingsLoadedEventArgs e ) private void SettingsLoadedEventHandler(object sender, System.Configuration.SettingsLoadedEventArgs e)
{ {
System.Console.WriteLine( "Settings Loaded..." ); System.Console.WriteLine("Settings Loaded...");
} }
} }
} }

View File

@ -14,73 +14,73 @@ namespace Snap2HTML
class Utils class Utils
{ {
// Hack to sort folders correctly even if they have spaces/periods in them // Hack to sort folders correctly even if they have spaces/periods in them
public static List<string> SortDirList( List<string> lstDirs ) public static List<string> SortDirList(List<string> lstDirs)
{ {
for( int n = 0; n < lstDirs.Count; n++ ) for (int n = 0; n < lstDirs.Count; n++)
{ {
lstDirs[n] = lstDirs[n].Replace( " ", "1|1" ); lstDirs[n] = lstDirs[n].Replace(" ", "1|1");
lstDirs[n] = lstDirs[n].Replace( ".", "2|2" ); lstDirs[n] = lstDirs[n].Replace(".", "2|2");
} }
lstDirs.Sort(); lstDirs.Sort();
for( int n = 0; n < lstDirs.Count; n++ ) for (int n = 0; n < lstDirs.Count; n++)
{ {
lstDirs[n] = lstDirs[n].Replace( "1|1", " " ); lstDirs[n] = lstDirs[n].Replace("1|1", " ");
lstDirs[n] = lstDirs[n].Replace( "2|2", "." ); lstDirs[n] = lstDirs[n].Replace("2|2", ".");
} }
return lstDirs; return lstDirs;
} }
// Replaces characters that may appear in filenames/paths that have special meaning to JavaScript // Replaces characters that may appear in filenames/paths that have special meaning to JavaScript
// Info on u2028/u2029: https://en.wikipedia.org/wiki/Newline#Unicode // Info on u2028/u2029: https://en.wikipedia.org/wiki/Newline#Unicode
public static string MakeCleanJsString( string s ) public static string MakeCleanJsString(string s)
{ {
return s.Replace( "\\", "\\\\" ) return s.Replace("\\", "\\\\")
.Replace( "&", "&amp;" ) .Replace("&", "&amp;")
.Replace( "\u2028", "" ) .Replace("\u2028", "")
.Replace( "\u2029", "" ) .Replace("\u2029", "")
.Replace( "\u0004", "" ); .Replace("\u0004", "");
} }
// Test string for matches against a wildcard pattern. Use ? and * as wildcards. (Wrapper around RegEx) // Test string for matches against a wildcard pattern. Use ? and * as wildcards. (Wrapper around RegEx)
public static bool IsWildcardMatch( String wildcard, String text, bool casesensitive ) public static bool IsWildcardMatch(String wildcard, String text, bool casesensitive)
{ {
System.Text.StringBuilder sb = new System.Text.StringBuilder( wildcard.Length + 10 ); System.Text.StringBuilder sb = new System.Text.StringBuilder(wildcard.Length + 10);
sb.Append( "^" ); sb.Append("^");
for( int i = 0; i < wildcard.Length; i++ ) for (int i = 0; i < wildcard.Length; i++)
{ {
char c = wildcard[i]; char c = wildcard[i];
switch( c ) switch (c)
{ {
case '*': case '*':
sb.Append( ".*" ); sb.Append(".*");
break; break;
case '?': case '?':
sb.Append( "." ); sb.Append(".");
break; break;
default: default:
sb.Append( System.Text.RegularExpressions.Regex.Escape( wildcard[i].ToString() ) ); sb.Append(System.Text.RegularExpressions.Regex.Escape(wildcard[i].ToString()));
break; break;
} }
} }
sb.Append( "$" ); sb.Append("$");
System.Text.RegularExpressions.Regex regex; System.Text.RegularExpressions.Regex regex;
if( casesensitive ) if (casesensitive)
regex = new System.Text.RegularExpressions.Regex( sb.ToString(), System.Text.RegularExpressions.RegexOptions.None ); regex = new System.Text.RegularExpressions.Regex(sb.ToString(), System.Text.RegularExpressions.RegexOptions.None);
else else
regex = new System.Text.RegularExpressions.Regex( sb.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase ); regex = new System.Text.RegularExpressions.Regex(sb.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
return regex.IsMatch( text ); return regex.IsMatch(text);
} }
public static int ToUnixTimestamp( DateTime value ) public static int ToUnixTimestamp(DateTime value)
{ {
return (int)Math.Truncate( ( value.ToUniversalTime().Subtract( new DateTime( 1970, 1, 1 ) ) ).TotalSeconds ); return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
} }
public static long ParseLong(string s) public static long ParseLong(string s)
{ {
long num; long num;
if( Int64.TryParse( s, out num ) ) if (Int64.TryParse(s, out num))
{ {
return num; return num;
} }

View File

@ -54,6 +54,7 @@
this.pictureBox4 = new System.Windows.Forms.PictureBox(); this.pictureBox4 = new System.Windows.Forms.PictureBox();
this.label4 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label();
this.tabPage2 = new System.Windows.Forms.TabPage(); this.tabPage2 = new System.Windows.Forms.TabPage();
this.pictureBoxDonate = new System.Windows.Forms.PictureBox();
this.groupBoxMoreApps = new System.Windows.Forms.GroupBox(); this.groupBoxMoreApps = new System.Windows.Forms.GroupBox();
this.label33 = new System.Windows.Forms.Label(); this.label33 = new System.Windows.Forms.Label();
this.label32 = new System.Windows.Forms.Label(); this.label32 = new System.Windows.Forms.Label();
@ -78,6 +79,7 @@
this.tabPage3.SuspendLayout(); this.tabPage3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).BeginInit();
this.tabPage2.SuspendLayout(); this.tabPage2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxDonate)).BeginInit();
this.groupBoxMoreApps.SuspendLayout(); this.groupBoxMoreApps.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
@ -354,6 +356,7 @@
// //
// tabPage2 // tabPage2
// //
this.tabPage2.Controls.Add(this.pictureBoxDonate);
this.tabPage2.Controls.Add(this.groupBoxMoreApps); this.tabPage2.Controls.Add(this.groupBoxMoreApps);
this.tabPage2.Controls.Add(this.pictureBox1); this.tabPage2.Controls.Add(this.pictureBox1);
this.tabPage2.Controls.Add(this.linkLabel1); this.tabPage2.Controls.Add(this.linkLabel1);
@ -368,6 +371,18 @@
this.tabPage2.Text = "About"; this.tabPage2.Text = "About";
this.tabPage2.UseVisualStyleBackColor = true; this.tabPage2.UseVisualStyleBackColor = true;
// //
// pictureBoxDonate
//
this.pictureBoxDonate.Cursor = System.Windows.Forms.Cursors.Hand;
this.pictureBoxDonate.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxDonate.Image")));
this.pictureBoxDonate.Location = new System.Drawing.Point(193, 132);
this.pictureBoxDonate.Name = "pictureBoxDonate";
this.pictureBoxDonate.Size = new System.Drawing.Size(74, 21);
this.pictureBoxDonate.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBoxDonate.TabIndex = 6;
this.pictureBoxDonate.TabStop = false;
this.pictureBoxDonate.Click += new System.EventHandler(this.pictureBoxDonate_Click);
//
// groupBoxMoreApps // groupBoxMoreApps
// //
this.groupBoxMoreApps.Controls.Add(this.label33); this.groupBoxMoreApps.Controls.Add(this.label33);
@ -378,9 +393,9 @@
this.groupBoxMoreApps.Controls.Add(this.label11); this.groupBoxMoreApps.Controls.Add(this.label11);
this.groupBoxMoreApps.Controls.Add(this.pictureBox3); this.groupBoxMoreApps.Controls.Add(this.pictureBox3);
this.groupBoxMoreApps.Controls.Add(this.pictureBox2); this.groupBoxMoreApps.Controls.Add(this.pictureBox2);
this.groupBoxMoreApps.Location = new System.Drawing.Point(6, 174); this.groupBoxMoreApps.Location = new System.Drawing.Point(6, 176);
this.groupBoxMoreApps.Name = "groupBoxMoreApps"; this.groupBoxMoreApps.Name = "groupBoxMoreApps";
this.groupBoxMoreApps.Size = new System.Drawing.Size(318, 130); this.groupBoxMoreApps.Size = new System.Drawing.Size(318, 128);
this.groupBoxMoreApps.TabIndex = 5; this.groupBoxMoreApps.TabIndex = 5;
this.groupBoxMoreApps.TabStop = false; this.groupBoxMoreApps.TabStop = false;
this.groupBoxMoreApps.Text = "More utilities by me"; this.groupBoxMoreApps.Text = "More utilities by me";
@ -389,7 +404,7 @@
// //
this.label33.AutoSize = true; this.label33.AutoSize = true;
this.label33.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label33.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label33.Location = new System.Drawing.Point(210, 29); this.label33.Location = new System.Drawing.Point(209, 27);
this.label33.Name = "label33"; this.label33.Name = "label33";
this.label33.Size = new System.Drawing.Size(91, 13); this.label33.Size = new System.Drawing.Size(91, 13);
this.label33.TabIndex = 13; this.label33.TabIndex = 13;
@ -399,18 +414,18 @@
// //
this.label32.AutoSize = true; this.label32.AutoSize = true;
this.label32.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label32.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label32.Location = new System.Drawing.Point(66, 29); this.label32.Location = new System.Drawing.Point(58, 27);
this.label32.Name = "label32"; this.label32.Name = "label32";
this.label32.Size = new System.Drawing.Size(66, 13); this.label32.Size = new System.Drawing.Size(108, 13);
this.label32.TabIndex = 10; this.label32.TabIndex = 10;
this.label32.Text = "Snap2IMG"; this.label32.Text = "Exif Tag Remover";
// //
// linkLabel3 // linkLabel3
// //
this.linkLabel3.AutoSize = true; this.linkLabel3.AutoSize = true;
this.linkLabel3.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; this.linkLabel3.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.linkLabel3.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192))))); this.linkLabel3.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
this.linkLabel3.Location = new System.Drawing.Point(66, 100); this.linkLabel3.Location = new System.Drawing.Point(58, 100);
this.linkLabel3.Name = "linkLabel3"; this.linkLabel3.Name = "linkLabel3";
this.linkLabel3.Size = new System.Drawing.Size(51, 13); this.linkLabel3.Size = new System.Drawing.Size(51, 13);
this.linkLabel3.TabIndex = 12; this.linkLabel3.TabIndex = 12;
@ -421,18 +436,18 @@
// //
// label17 // label17
// //
this.label17.Location = new System.Drawing.Point(66, 42); this.label17.Location = new System.Drawing.Point(58, 40);
this.label17.Name = "label17"; this.label17.Name = "label17";
this.label17.Size = new System.Drawing.Size(100, 74); this.label17.Size = new System.Drawing.Size(108, 74);
this.label17.TabIndex = 11; this.label17.TabIndex = 11;
this.label17.Text = "Generate contact sheets (thumbnail index) for folders on your hard drive."; this.label17.Text = "Delete all metadata before publishing images to protect your privacy.";
// //
// linkLabel2 // linkLabel2
// //
this.linkLabel2.AutoSize = true; this.linkLabel2.AutoSize = true;
this.linkLabel2.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; this.linkLabel2.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.linkLabel2.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192))))); this.linkLabel2.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
this.linkLabel2.Location = new System.Drawing.Point(210, 100); this.linkLabel2.Location = new System.Drawing.Point(209, 100);
this.linkLabel2.Name = "linkLabel2"; this.linkLabel2.Name = "linkLabel2";
this.linkLabel2.Size = new System.Drawing.Size(51, 13); this.linkLabel2.Size = new System.Drawing.Size(51, 13);
this.linkLabel2.TabIndex = 10; this.linkLabel2.TabIndex = 10;
@ -443,16 +458,16 @@
// //
// label11 // label11
// //
this.label11.Location = new System.Drawing.Point(210, 42); this.label11.Location = new System.Drawing.Point(209, 40);
this.label11.Name = "label11"; this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(102, 71); this.label11.Size = new System.Drawing.Size(102, 71);
this.label11.TabIndex = 9; this.label11.TabIndex = 9;
this.label11.Text = "File renaming utility with lots of time saving automation features."; this.label11.Text = "Advanced file renaming utility that will save you lots of time.";
// //
// pictureBox3 // pictureBox3
// //
this.pictureBox3.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox3.Image"))); this.pictureBox3.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox3.Image")));
this.pictureBox3.Location = new System.Drawing.Point(169, 29); this.pictureBox3.Location = new System.Drawing.Point(169, 27);
this.pictureBox3.Name = "pictureBox3"; this.pictureBox3.Name = "pictureBox3";
this.pictureBox3.Size = new System.Drawing.Size(39, 48); this.pictureBox3.Size = new System.Drawing.Size(39, 48);
this.pictureBox3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.pictureBox3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
@ -462,9 +477,9 @@
// pictureBox2 // pictureBox2
// //
this.pictureBox2.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox2.Image"))); this.pictureBox2.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox2.Image")));
this.pictureBox2.Location = new System.Drawing.Point(12, 29); this.pictureBox2.Location = new System.Drawing.Point(10, 27);
this.pictureBox2.Name = "pictureBox2"; this.pictureBox2.Name = "pictureBox2";
this.pictureBox2.Size = new System.Drawing.Size(48, 48); this.pictureBox2.Size = new System.Drawing.Size(46, 39);
this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox2.TabIndex = 0; this.pictureBox2.TabIndex = 0;
this.pictureBox2.TabStop = false; this.pictureBox2.TabStop = false;
@ -484,7 +499,7 @@
this.linkLabel1.AutoSize = true; this.linkLabel1.AutoSize = true;
this.linkLabel1.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; this.linkLabel1.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.linkLabel1.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192))))); this.linkLabel1.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
this.linkLabel1.Location = new System.Drawing.Point(163, 104); this.linkLabel1.Location = new System.Drawing.Point(163, 101);
this.linkLabel1.Name = "linkLabel1"; this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(120, 13); this.linkLabel1.Size = new System.Drawing.Size(120, 13);
this.linkLabel1.TabIndex = 3; this.linkLabel1.TabIndex = 3;
@ -495,7 +510,7 @@
// labelAboutSoftware // labelAboutSoftware
// //
this.labelAboutSoftware.AutoSize = true; this.labelAboutSoftware.AutoSize = true;
this.labelAboutSoftware.Location = new System.Drawing.Point(163, 87); this.labelAboutSoftware.Location = new System.Drawing.Point(163, 84);
this.labelAboutSoftware.Name = "labelAboutSoftware"; this.labelAboutSoftware.Name = "labelAboutSoftware";
this.labelAboutSoftware.Size = new System.Drawing.Size(135, 13); this.labelAboutSoftware.Size = new System.Drawing.Size(135, 13);
this.labelAboutSoftware.TabIndex = 2; this.labelAboutSoftware.TabIndex = 2;
@ -564,6 +579,7 @@
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).EndInit();
this.tabPage2.ResumeLayout(false); this.tabPage2.ResumeLayout(false);
this.tabPage2.PerformLayout(); this.tabPage2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxDonate)).EndInit();
this.groupBoxMoreApps.ResumeLayout(false); this.groupBoxMoreApps.ResumeLayout(false);
this.groupBoxMoreApps.PerformLayout(); this.groupBoxMoreApps.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
@ -618,6 +634,7 @@
private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label7;
private System.Windows.Forms.LinkLabel linkLabel5; private System.Windows.Forms.LinkLabel linkLabel5;
private System.Windows.Forms.Label label8; private System.Windows.Forms.Label label8;
private System.Windows.Forms.PictureBox pictureBoxDonate;
} }
} }

View File

@ -11,32 +11,32 @@ namespace Snap2HTML
{ {
public partial class frmMain : Form public partial class frmMain : Form
{ {
private string outFile = ""; // set when automating via command line
private bool initDone = false; private bool initDone = false;
private bool runningAutomated = false;
public frmMain() public frmMain()
{ {
InitializeComponent(); InitializeComponent();
} }
private void frmMain_Load( object sender, EventArgs e ) private void frmMain_Load(object sender, EventArgs e)
{ {
this.Text = Application.ProductName + " (Press F1 for Help)"; this.Text = Application.ProductName + " (Press F1 for Help)";
labelAboutVersion.Text = "version " + Application.ProductVersion.Split( '.' )[0] + "." + Application.ProductVersion.Split( '.' )[1]; labelAboutVersion.Text = "version " + Application.ProductVersion.Split('.')[0] + "." + Application.ProductVersion.Split('.')[1];
// initialize some settings // initialize some settings
int left = Snap2HTML.Properties.Settings.Default.WindowLeft; int left = Snap2HTML.Properties.Settings.Default.WindowLeft;
int top = Snap2HTML.Properties.Settings.Default.WindowTop; int top = Snap2HTML.Properties.Settings.Default.WindowTop;
if( left >= 0 ) this.Left = left; if (left >= 0) this.Left = left;
if( top >= 0 ) this.Top = top; if (top >= 0) this.Top = top;
if( System.IO.Directory.Exists( txtRoot.Text ) ) if (System.IO.Directory.Exists(txtRoot.Text))
{ {
SetRootPath( txtRoot.Text , true); SetRootPath(txtRoot.Text, true);
} }
else else
{ {
SetRootPath( "" , false ); SetRootPath("", false);
} }
txtLinkRoot.Enabled = chkLinkFiles.Checked; txtLinkRoot.Enabled = chkLinkFiles.Checked;
@ -45,7 +45,7 @@ namespace Snap2HTML
tabPage1.DragDrop += DragDropHandler; tabPage1.DragDrop += DragDropHandler;
tabPage1.DragEnter += DragEnterHandler; tabPage1.DragEnter += DragEnterHandler;
tabPage1.AllowDrop = true; tabPage1.AllowDrop = true;
foreach( Control cnt in tabPage1.Controls ) foreach (Control cnt in tabPage1.Controls)
{ {
cnt.DragDrop += DragDropHandler; cnt.DragDrop += DragDropHandler;
cnt.DragEnter += DragEnterHandler; cnt.DragEnter += DragEnterHandler;
@ -57,10 +57,11 @@ namespace Snap2HTML
initDone = true; initDone = true;
} }
private void frmMain_Shown( object sender, EventArgs e ) private void frmMain_Shown(object sender, EventArgs e)
{ {
// parse command line // parse command line
var commandLine = Environment.CommandLine; var commandLine = Environment.CommandLine;
commandLine = commandLine.Replace("-output:", "-outfile:"); // correct wrong parameter to avoid confusion
var splitCommandLine = Arguments.SplitCommandLine(commandLine); var splitCommandLine = Arguments.SplitCommandLine(commandLine);
var arguments = new Arguments(splitCommandLine); var arguments = new Arguments(splitCommandLine);
@ -69,36 +70,59 @@ namespace Snap2HTML
{ {
if (System.IO.Directory.Exists(splitCommandLine[1])) if (System.IO.Directory.Exists(splitCommandLine[1]))
{ {
SetRootPath( splitCommandLine[1] ); SetRootPath(splitCommandLine[1]);
} }
} }
var autoRun = false; var settings = new SnapSettings();
if (arguments.Exists("path") && arguments.Exists("outfile"))
if (arguments.IsTrue("hidden")) chkHidden.Checked = true;
if (arguments.IsTrue("system")) chkSystem.Checked = true;
if( arguments.Exists( "path" ) )
{ {
// note: relative paths not handled this.runningAutomated = true;
string path = arguments.Single( "path" );
if( !System.IO.Directory.Exists( path ) ) path = Environment.CurrentDirectory + System.IO.Path.DirectorySeparatorChar + path;
if( System.IO.Directory.Exists( path ) ) settings.rootFolder = arguments.Single("path");
{ settings.outputFile = arguments.Single("outfile");
SetRootPath( path );
// if outfile is also given, start generating snapshot // First validate paths
if (arguments.Exists("outfile")) if (!System.IO.Directory.Exists(settings.rootFolder))
{ {
autoRun = true; if (!arguments.Exists("silent"))
outFile = arguments.Single("outfile"); {
cmdCreate.PerformClick(); MessageBox.Show("Input path does not exist: " + settings.rootFolder, "Automation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
} }
Application.Exit();
} }
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(settings.outputFile)))
{
if (!arguments.Exists("silent"))
{
MessageBox.Show("Output path does not exist: " + System.IO.Path.GetDirectoryName(settings.outputFile), "Automation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Application.Exit();
}
// Rest of settings
settings.skipHiddenItems = !arguments.Exists("hidden");
settings.skipSystemItems = !arguments.Exists("system");
settings.openInBrowser = false;
settings.linkFiles = false;
if (arguments.Exists("link"))
{
settings.linkFiles = true;
settings.linkRoot = arguments.Single("link");
}
settings.title = "Snapshot of " + settings.rootFolder;
if (arguments.Exists("title"))
{
settings.title = arguments.Single("title");
}
} }
// keep window hidden in silent mode // keep window hidden in silent mode
if( arguments.IsTrue( "silent" ) && autoRun ) if (arguments.IsTrue("silent") && this.runningAutomated)
{ {
Visible = false; Visible = false;
} }
@ -107,24 +131,17 @@ namespace Snap2HTML
Opacity = 100; Opacity = 100;
} }
// run link/title after path, since path automatically updates title if (this.runningAutomated)
if( arguments.Exists( "link" ) )
{ {
chkLinkFiles.Checked = true; StartProcessing(settings);
txtLinkRoot.Text = arguments.Single( "link" );
txtLinkRoot.Enabled = true;
}
if( arguments.Exists( "title" ) )
{
txtTitle.Text = arguments.Single( "title" );
} }
} }
private void frmMain_FormClosing( object sender, FormClosingEventArgs e ) private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{ {
if( backgroundWorker.IsBusy ) e.Cancel = true; if (backgroundWorker.IsBusy) e.Cancel = true;
if( outFile == "" ) // don't save settings when automated through command line if (!this.runningAutomated) // don't save settings when automated through command line
{ {
Snap2HTML.Properties.Settings.Default.WindowLeft = this.Left; Snap2HTML.Properties.Settings.Default.WindowLeft = this.Left;
Snap2HTML.Properties.Settings.Default.WindowTop = this.Top; Snap2HTML.Properties.Settings.Default.WindowTop = this.Top;
@ -140,37 +157,20 @@ namespace Snap2HTML
{ {
try try
{ {
SetRootPath( folderBrowserDialog1.SelectedPath ); SetRootPath(folderBrowserDialog1.SelectedPath);
} }
catch( System.Exception ex ) catch (System.Exception ex)
{ {
MessageBox.Show( "Could not select folder: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); MessageBox.Show("Could not select folder:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
SetRootPath( "", false ); SetRootPath("", false);
} }
} }
} }
private void cmdCreate_Click(object sender, EventArgs e) private void cmdCreate_Click(object sender, EventArgs e)
{ {
// ensure source path format // ask for output file
txtRoot.Text = System.IO.Path.GetFullPath( txtRoot.Text ); string fileName = new System.IO.DirectoryInfo(txtRoot.Text + @"\").Name;
if (txtRoot.Text.EndsWith(@"\")) txtRoot.Text = txtRoot.Text.Substring(0, txtRoot.Text.Length - 1);
if( Utils.IsWildcardMatch( "?:", txtRoot.Text, false ) ) txtRoot.Text += @"\"; // add backslash to path if only letter and colon eg "c:"
// add slash or backslash to end of link (in cases where it is clearthat we we can)
if( !txtLinkRoot.Text.EndsWith( @"/" ) && txtLinkRoot.Text.ToLower().StartsWith( @"http" ) ) // web site
{
txtLinkRoot.Text += @"/";
}
if( !txtLinkRoot.Text.EndsWith( @"\" ) && Utils.IsWildcardMatch( "?:*", txtLinkRoot.Text, false ) ) // local disk
{
txtLinkRoot.Text += @"\";
}
// get output file
if( outFile == "" )
{
string fileName = new System.IO.DirectoryInfo( txtRoot.Text + @"\" ).Name;
char[] invalid = System.IO.Path.GetInvalidFileNameChars(); char[] invalid = System.IO.Path.GetInvalidFileNameChars();
for (int i = 0; i < invalid.Length; i++) for (int i = 0; i < invalid.Length; i++)
{ {
@ -178,31 +178,16 @@ namespace Snap2HTML
} }
saveFileDialog1.DefaultExt = "html"; saveFileDialog1.DefaultExt = "html";
if( !fileName.ToLower().EndsWith( ".html" ) ) fileName += ".html"; if (!fileName.ToLower().EndsWith(".html")) fileName += ".html";
saveFileDialog1.FileName = fileName; saveFileDialog1.FileName = fileName;
saveFileDialog1.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*"; saveFileDialog1.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*";
saveFileDialog1.InitialDirectory = System.IO.Path.GetDirectoryName(txtRoot.Text); saveFileDialog1.InitialDirectory = System.IO.Path.GetDirectoryName(txtRoot.Text);
saveFileDialog1.CheckPathExists = true;
if (saveFileDialog1.ShowDialog() != DialogResult.OK) return; if (saveFileDialog1.ShowDialog() != DialogResult.OK) return;
}
else // command line
{
saveFileDialog1.FileName = outFile;
}
if( !saveFileDialog1.FileName.ToLower().EndsWith( ".html" ) ) saveFileDialog1.FileName += ".html"; if (!saveFileDialog1.FileName.ToLower().EndsWith(".html")) saveFileDialog1.FileName += ".html";
// make sure output path exists
if( !System.IO.Directory.Exists( System.IO.Path.GetDirectoryName( saveFileDialog1.FileName ) ) )
{
MessageBox.Show( "The output folder does not exists...\n\n" + System.IO.Path.GetDirectoryName( saveFileDialog1.FileName ), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
return;
}
// begin generating html // begin generating html
Cursor.Current = Cursors.WaitCursor;
this.Text = "Snap2HTML (Working... Press Escape to Cancel)";
tabControl1.Enabled = false;
var settings = new SnapSettings() var settings = new SnapSettings()
{ {
rootFolder = txtRoot.Text, rootFolder = txtRoot.Text,
@ -214,16 +199,48 @@ namespace Snap2HTML
linkFiles = chkLinkFiles.Checked, linkFiles = chkLinkFiles.Checked,
linkRoot = txtLinkRoot.Text, linkRoot = txtLinkRoot.Text,
}; };
backgroundWorker.RunWorkerAsync(argument: settings); StartProcessing(settings);
} }
private void backgroundWorker_ProgressChanged( object sender, ProgressChangedEventArgs e ) private void StartProcessing(SnapSettings settings)
{
// ensure source path format
settings.rootFolder = System.IO.Path.GetFullPath(settings.rootFolder);
if (settings.rootFolder.EndsWith(@"\")) settings.rootFolder = settings.rootFolder.Substring(0, settings.rootFolder.Length - 1);
if (Utils.IsWildcardMatch("?:", settings.rootFolder, false)) settings.rootFolder += @"\"; // add backslash to path if only letter and colon eg "c:"
// add slash or backslash to end of link (in cases where it is clear that we we can)
if (settings.linkFiles)
{
if (!settings.linkRoot.EndsWith(@"/"))
{
if (settings.linkRoot.ToLower().StartsWith(@"http")) // web site
{
settings.linkRoot += @"/";
}
if (Utils.IsWildcardMatch("?:*", settings.linkRoot, false)) // local disk
{
settings.linkRoot += @"\";
}
if (settings.linkRoot.StartsWith(@"\\")) // unc path
{
settings.linkRoot += @"\";
}
}
}
Cursor.Current = Cursors.WaitCursor;
this.Text = "Snap2HTML (Working... Press Escape to Cancel)";
tabControl1.Enabled = false;
backgroundWorker.RunWorkerAsync(argument: settings);
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{ {
toolStripStatusLabel1.Text = e.UserState.ToString(); toolStripStatusLabel1.Text = e.UserState.ToString();
} }
private void backgroundWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{ {
GC.Collect(); GC.Collect();
GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();
@ -233,7 +250,7 @@ namespace Snap2HTML
this.Text = "Snap2HTML"; this.Text = "Snap2HTML";
// Quit when finished if automated via command line // Quit when finished if automated via command line
if( outFile != "" ) if (this.runningAutomated)
{ {
Application.Exit(); Application.Exit();
} }
@ -248,31 +265,35 @@ namespace Snap2HTML
} }
// Link Label handlers // Link Label handlers
private void linkLabel1_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
System.Diagnostics.Process.Start( @"http://www.rlvision.com" ); System.Diagnostics.Process.Start(@"http://www.rlvision.com");
} }
private void linkLabel3_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
System.Diagnostics.Process.Start( @"http://www.rlvision.com/snap2img/about.asp" ); System.Diagnostics.Process.Start(@"https://rlvision.com/exif/about.php");
} }
private void linkLabel2_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
System.Diagnostics.Process.Start( @"http://www.rlvision.com/flashren/about.asp" ); System.Diagnostics.Process.Start(@"http://www.rlvision.com/flashren/about.php");
} }
private void linkLabel4_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) private void linkLabel4_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
System.Diagnostics.Process.Start( "notepad.exe", System.IO.Path.GetDirectoryName( Application.ExecutablePath ) + "\\template.html" ); System.Diagnostics.Process.Start("notepad.exe", System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\template.html");
} }
private void linkLabel5_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) private void linkLabel5_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
System.Diagnostics.Process.Start( @"http://www.rlvision.com/contact.asp" ); System.Diagnostics.Process.Start(@"http://www.rlvision.com/contact.php");
}
private void pictureBoxDonate_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(@"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=U3E4HE8HMY9Q4&item_name=Snap2HTML&currency_code=USD&source=url");
} }
// Drag & Drop handlers // Drag & Drop handlers
private void DragEnterHandler( object sender, DragEventArgs e ) private void DragEnterHandler(object sender, DragEventArgs e)
{ {
if( e.Data.GetDataPresent( DataFormats.FileDrop ) ) if (e.Data.GetDataPresent(DataFormats.FileDrop))
{ {
e.Effect = DragDropEffects.Copy; e.Effect = DragDropEffects.Copy;
} }
@ -281,46 +302,46 @@ namespace Snap2HTML
e.Effect = DragDropEffects.None; e.Effect = DragDropEffects.None;
} }
} }
private void DragDropHandler( object sender, DragEventArgs e ) private void DragDropHandler(object sender, DragEventArgs e)
{ {
if( e.Data.GetDataPresent( DataFormats.FileDrop ) ) if (e.Data.GetDataPresent(DataFormats.FileDrop))
{ {
string[] files = (string[])e.Data.GetData( DataFormats.FileDrop ); string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if( files.Length == 1 && System.IO.Directory.Exists( files[0] ) ) if (files.Length == 1 && System.IO.Directory.Exists(files[0]))
{ {
SetRootPath( files[0] ); SetRootPath(files[0]);
} }
} }
} }
// Escape to cancel // Escape to cancel
private void frmMain_KeyUp( object sender, KeyEventArgs e ) private void frmMain_KeyUp(object sender, KeyEventArgs e)
{ {
if( backgroundWorker.IsBusy ) if (backgroundWorker.IsBusy)
{ {
if( e.KeyCode == Keys.Escape ) if (e.KeyCode == Keys.Escape)
{ {
backgroundWorker.CancelAsync(); backgroundWorker.CancelAsync();
} }
} }
else else
{ {
if( e.KeyCode == Keys.F1 ) if (e.KeyCode == Keys.F1)
{ {
System.Diagnostics.Process.Start( System.IO.Path.GetDirectoryName( Application.ExecutablePath ) + "\\ReadMe.txt" ); System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\ReadMe.txt");
} }
} }
} }
// Sets the root path input box and makes related gui parts ready to use // Sets the root path input box and makes related gui parts ready to use
private void SetRootPath( string path, bool pathIsValid = true ) private void SetRootPath(string path, bool pathIsValid = true)
{ {
if( pathIsValid ) if (pathIsValid)
{ {
txtRoot.Text = path; txtRoot.Text = path;
cmdCreate.Enabled = true; cmdCreate.Enabled = true;
toolStripStatusLabel1.Text = ""; toolStripStatusLabel1.Text = "";
if( initDone ) if (initDone)
{ {
txtLinkRoot.Text = txtRoot.Text; txtLinkRoot.Text = txtRoot.Text;
txtTitle.Text = "Snapshot of " + txtRoot.Text; txtTitle.Text = "Snapshot of " + txtRoot.Text;
@ -331,7 +352,7 @@ namespace Snap2HTML
txtRoot.Text = ""; txtRoot.Text = "";
cmdCreate.Enabled = false; cmdCreate.Enabled = false;
toolStripStatusLabel1.Text = ""; toolStripStatusLabel1.Text = "";
if( initDone ) if (initDone)
{ {
txtLinkRoot.Text = txtRoot.Text; txtLinkRoot.Text = txtRoot.Text;
txtTitle.Text = ""; txtTitle.Text = "";

View File

@ -494,6 +494,35 @@
jTImu2uXMzlKjrHmOMi2HdX5XuWSJmvKfmgyh+cNp8H6sf+27Lsm+y3Dfgvqr611T/8VtDTJLpqNOUXr jTImu2uXMzlKjrHmOMi2HdX5XuWSJmvKfmgyh+cNp8H6sf+27Lsm+y3Dfgvqr611T/8VtDTJLpqNOUXr
pv6L5CL5mS0+oHBCISJ/spaaoiaNUoPpu7oB1TR69G3yfkUeX0J/vgj+zvwzMC20NMkumo3v+d9Bs/E9 pv6L5CL5mS0+oHBCISJ/spaaoiaNUoPpu7oB1TR69G3yfkUeX0J/vgj+zvwzMC20NMkumo3v+d9Bs/E9
/ztoNr7nfwfNxvf8rwDl/wALZf6ZRmxttQAAAABJRU5ErkJggg== /ztoNr7nfwfNxvf8rwDl/wALZf6ZRmxttQAAAABJRU5ErkJggg==
</value>
</data>
<data name="pictureBoxDonate.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
R0lGODlhSgAVAIfPAP7DOf7DONqnMf7EOSgeCNmmMAgGAeCsMmNMFv/DOfC4NfzBOOqzNP/EOvS7Nv/F
PgkGAgEAAAIBAAUDAVlEE+mzNP/GQf7COZx3IiAYB0AxDg4KAwMCAPe9NyIaB//aguGsMv/QYdimMPO6
NTYpDPvLWOizN9qoMP/OW9yoMf3CON+rMtyoMPO6NkMzDiogCe21NP/LU+iyM//JSv7TcPC4NlVBExgS
BfjCRO64OOKtM2JLFQcFAcucLSEZB0k4EPzJTvvAOCUcCAYEATAkCv/ciRUQBP7QZv3FQvi+N/rCQT8w
DrmOKfTHV1xGFOKvMvm/N/m+N6Z/JfjBPlpFFDImC+y0NZNwIPrAN66FJv7PYdelMJVyIcycLfq/OBsU
BvzEP39hHHdbGtWjL3NYGU88Ee62Nf/DOu22Nf3QZfG5NRENA0o4EGRMFjUoC+eyNOWwNDkrDM6eLrCH
J7uPKf/ISDwuDXldG/W+PvG9Q0U1DwoHAnpdG29VGDstDXZaGjElCtuoMBwVBpd0IWFKFfW8Nt6qMmhP
FzosDCwhCffETey1NVdCE//XeYNkHZl1IqF7I+WwMriNKYdnHhQPBPfAPuy1NNakL/q/N+u0NJ96I+22
NuWwM9GgLnxfGxkTBcWXLPK9RPfETt+rMfvDP3teG8OVK7yQKj0uDUExDkc2D/7PXw8LAwsIAoBiHAQD
ANCfLt6pMsmaLJFvIP3COZRxIfa+P1E+Ev/HQZBuIP/JSf/Wd96qMS0iCr6SKlZCE+eyMx8XBnVZGrqO
Kf7QZW1TGGVNFtOiL//Wdv/YesiZLNqnMP/cigAAAP/EOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ACH/C05FVFNDQVBFMi4wAwEBAAAh+QQBAADPACwAAAAASgAVAAAI/wCfCRz4DEUdC2cAKAQwgGHDhgCc
RZQocaHCAAACYMTI0GGAARozKnw4wFlJZw1w6UJBsOVAIEi07PpQhJnNmzhz6tzJs+fOIh+QrUICxOVA
MGkahZhhoYGzp1CjSp1KtapVqg0szAiRjBgpo0poxLhKtqzZs09j0FDSstKRB2jjyo374MiUgaJKOJ3L
t2/VBiUUCcQDtyyBZs1u/OjiN+olWY0f2HrWBMdZAhO4/BrCwVTjpxokfMbRJM+CywaeKmtG4qkkIhv0
LHvKR4gYD4CYOAvQxwcEErCcHYLQTEiip3N6rWHk4OyCUDkuoH4agNIELJ04fNoBQVBzBM2qGP/jQcRZ
kFZsCE245UxKhghhHDnrEQEVmSHFzl7IgQYtgdRPxdGMDG0004MzuTQDiTPgHeCMKs0o4AwUzijghwEU
hgbVDgYcoIYLHqC1ySK0TOdMBwbsEcASHAThDCjNeMJgMw5S0AwDzmiSQTMRROiMhk8tgRhiRuhnBQNe
mJhFMz8440QzWziDQTOPzFjjjXJEYAMINviYigQBPOXEBGM44EAhZ2FSgQkjXPZKKVTwAMExzgzTDCJX
BMOKDFY6YyMDTDQjzCkv+PhHM65MkgkdzbiBwSCznDWCCc+8kYBZhzXzRRkiQFXLBs1k4MtTDfp54wIu
NOODHc2A4IwIhd6AwImURjSzwR1mJQCMQJG08JkKFZhlBlWWSFWBCme1AMdAT0Tx2bN8RfFESzokAe21
ZiWhg1Gj1HAptuBGlUANvBglkCErwNDBAt+G61cCC3QAwwqxmEvQCSmwEEgByxTAL7/LCBCwwAIvY/DB
BxNMsMEKB2zwv/8ifDALKZxgVEAAOw==
</value> </value>
</data> </data>
<data name="pictureBox3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="pictureBox3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@ -552,110 +581,62 @@
</data> </data>
<data name="pictureBox2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="pictureBox2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
</value> </value>
</data> </data>
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

View File

@ -2,32 +2,32 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Data; using System.Data;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using CommandLine.Utility; using CommandLine.Utility;
using System.IO;
using System.Diagnostics;
namespace Snap2HTML namespace Snap2HTML
{ {
public partial class frmMain : Form public partial class frmMain : Form
{ {
// This runs on a separate thread from the GUI // This runs on a separate thread from the GUI
private void backgroundWorker_DoWork( object sender, DoWorkEventArgs e ) private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{ {
var settings = (SnapSettings)e.Argument; var settings = (SnapSettings)e.Argument;
// Get files & folders // Get files & folders
var content = GetContent( settings, backgroundWorker ); var content = GetContent(settings, backgroundWorker);
if( backgroundWorker.CancellationPending ) if (backgroundWorker.CancellationPending)
{ {
backgroundWorker.ReportProgress( 0, "User cancelled" ); backgroundWorker.ReportProgress(0, "User cancelled");
return; return;
} }
if( content == null ) if (content == null)
{ {
backgroundWorker.ReportProgress( 0, "Error reading source" ); backgroundWorker.ReportProgress(0, "Error reading source");
return; return;
} }
@ -35,114 +35,121 @@ namespace Snap2HTML
int totDirs = 0; int totDirs = 0;
int totFiles = 0; int totFiles = 0;
long totSize = 0; long totSize = 0;
foreach( var folder in content ) foreach (var folder in content)
{ {
totDirs++; totDirs++;
foreach( var file in folder.Files ) foreach (var file in folder.Files)
{ {
totFiles++; totFiles++;
totSize += Utils.ParseLong( file.GetProp( "Size" ) ); totSize += Utils.ParseLong(file.GetProp("Size"));
} }
} }
// Let's generate the output // Let's generate the output
backgroundWorker.ReportProgress( 0, "Generating HTML file..." ); backgroundWorker.ReportProgress(0, "Generating HTML file...");
// Read template // Read template
var sbTemplate = new StringBuilder(); var sbTemplate = new StringBuilder();
try try
{ {
using( System.IO.StreamReader reader = new System.IO.StreamReader( System.IO.Path.GetDirectoryName( Application.ExecutablePath ) + System.IO.Path.DirectorySeparatorChar + "template.html" ) ) using (System.IO.StreamReader reader = new System.IO.StreamReader(System.IO.Path.GetDirectoryName(Application.ExecutablePath) + System.IO.Path.DirectorySeparatorChar + "template.html", Encoding.UTF8))
{ {
sbTemplate.Append(reader.ReadToEnd()); sbTemplate.Append(reader.ReadToEnd());
} }
} }
catch( System.Exception ex ) catch (System.Exception ex)
{ {
MessageBox.Show( "Failed to open 'Template.html' for reading...", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); MessageBox.Show("Failed to open 'Template.html' for reading:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
backgroundWorker.ReportProgress( 0, "An error occurred..." ); backgroundWorker.ReportProgress(0, "An error occurred...");
return; return;
} }
// Build HTML // Build HTML
sbTemplate.Replace( "[TITLE]", settings.title ); sbTemplate.Replace("[TITLE]", settings.title);
sbTemplate.Replace( "[APP LINK]", "http://www.rlvision.com" ); sbTemplate.Replace("[APP LINK]", "http://www.rlvision.com");
sbTemplate.Replace( "[APP NAME]", Application.ProductName ); sbTemplate.Replace("[APP NAME]", Application.ProductName);
sbTemplate.Replace( "[APP VER]", Application.ProductVersion.Split( '.' )[0] + "." + Application.ProductVersion.Split( '.' )[1] ); sbTemplate.Replace("[APP VER]", Application.ProductVersion.Split('.')[0] + "." + Application.ProductVersion.Split('.')[1]);
sbTemplate.Replace( "[GEN TIME]", DateTime.Now.ToString( "t" ) ); sbTemplate.Replace("[GEN TIME]", DateTime.Now.ToString("t"));
sbTemplate.Replace( "[GEN DATE]", DateTime.Now.ToString( "d" ) ); sbTemplate.Replace("[GEN DATE]", DateTime.Now.ToString("d"));
sbTemplate.Replace( "[NUM FILES]", totFiles.ToString() ); sbTemplate.Replace("[NUM FILES]", totFiles.ToString());
sbTemplate.Replace( "[NUM DIRS]", totDirs.ToString() ); sbTemplate.Replace("[NUM DIRS]", totDirs.ToString());
sbTemplate.Replace( "[TOT SIZE]", totSize.ToString() ); sbTemplate.Replace("[TOT SIZE]", totSize.ToString());
if( chkLinkFiles.Checked ) if (settings.linkFiles)
{ {
sbTemplate.Replace( "[LINK FILES]", "true" ); sbTemplate.Replace("[LINK FILES]", "true");
sbTemplate.Replace( "[LINK ROOT]", settings.linkRoot.Replace( @"\", "/" ) ); sbTemplate.Replace("[LINK ROOT]", settings.linkRoot.Replace(@"\", "/"));
sbTemplate.Replace( "[SOURCE ROOT]", settings.rootFolder.Replace( @"\", "/" ) ); sbTemplate.Replace("[SOURCE ROOT]", settings.rootFolder.Replace(@"\", "/"));
string link_root = settings.linkRoot.Replace( @"\", "/" ); string link_root = settings.linkRoot.Replace(@"\", "/");
if( Utils.IsWildcardMatch( @"?:/*", link_root, false ) ) // "file://" is needed in the browser if path begins with drive letter, else it should not be used if (Utils.IsWildcardMatch(@"?:/*", link_root, false)) // "file://" is needed in the browser if path begins with drive letter, else it should not be used
{ {
sbTemplate.Replace( "[LINK PROTOCOL]", @"file://" ); sbTemplate.Replace("[LINK PROTOCOL]", @"file://");
}
else if (link_root.StartsWith("//")) // for UNC paths e.g. \\server\path
{
sbTemplate.Replace("[LINK PROTOCOL]", @"file://///");
} }
else else
{ {
sbTemplate.Replace( "[LINK PROTOCOL]", "" ); sbTemplate.Replace("[LINK PROTOCOL]", "");
} }
} }
else else
{ {
sbTemplate.Replace( "[LINK FILES]", "false" ); sbTemplate.Replace("[LINK FILES]", "false");
sbTemplate.Replace( "[LINK PROTOCOL]", "" ); sbTemplate.Replace("[LINK PROTOCOL]", "");
sbTemplate.Replace( "[LINK ROOT]", "" ); sbTemplate.Replace("[LINK ROOT]", "");
sbTemplate.Replace( "[SOURCE ROOT]", settings.rootFolder.Replace( @"\", "/" ) ); sbTemplate.Replace("[SOURCE ROOT]", settings.rootFolder.Replace(@"\", "/"));
} }
// Write output file // Write output file
try try
{ {
using( System.IO.StreamWriter writer = new System.IO.StreamWriter( settings.outputFile ) ) using (System.IO.StreamWriter writer = new System.IO.StreamWriter(settings.outputFile, false, Encoding.UTF8))
{ {
writer.AutoFlush = true;
var template = sbTemplate.ToString(); var template = sbTemplate.ToString();
var startOfData = template.IndexOf( "[DIR DATA]" ); var startOfData = template.IndexOf("[DIR DATA]");
writer.Write(template.Substring(0, startOfData)); writer.Write(template.Substring(0, startOfData));
BuildJavascriptContentArray( content, 0, writer, backgroundWorker ); BuildJavascriptContentArray(content, 0, writer, backgroundWorker);
if( backgroundWorker.CancellationPending ) if (backgroundWorker.CancellationPending)
{ {
backgroundWorker.ReportProgress( 0, "User cancelled" ); backgroundWorker.ReportProgress(0, "User cancelled");
return; return;
} }
writer.Write( template.Substring( startOfData + 10) ); writer.Write(template.Substring(startOfData + 10));
} }
sbTemplate = null; sbTemplate = null;
if( settings.openInBrowser ) if (settings.openInBrowser)
{ {
System.Diagnostics.Process.Start( settings.outputFile ); System.Diagnostics.Process.Start(settings.outputFile);
} }
} }
catch( Exception ex ) catch (Exception ex)
{ {
MessageBox.Show( "Failed to open file for writing:\n\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); MessageBox.Show("Failed to open file for writing:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
backgroundWorker.ReportProgress( 0, "An error occurred..." ); backgroundWorker.ReportProgress(0, "An error occurred...");
return; return;
} }
// Ready! // Ready!
Cursor.Current = Cursors.Default; Cursor.Current = Cursors.Default;
backgroundWorker.ReportProgress( 100, "Ready!" ); backgroundWorker.ReportProgress(100, "Ready!");
} }
// --- Helper functions (must be static to avoid thread problems) --- // --- Helper functions (must be static to avoid thread problems) ---
private static List<SnappedFolder> GetContent( SnapSettings settings, BackgroundWorker bgWorker ) private static List<SnappedFolder> GetContent(SnapSettings settings, BackgroundWorker bgWorker)
{ {
var stopwatch = new Stopwatch(); var stopwatch = new Stopwatch();
stopwatch.Start(); stopwatch.Start();
@ -151,11 +158,11 @@ namespace Snap2HTML
// Get all folders // Get all folders
var dirs = new List<string>(); var dirs = new List<string>();
dirs.Insert( 0, settings.rootFolder ); dirs.Insert(0, settings.rootFolder);
DirSearch( settings.rootFolder, dirs, settings.skipHiddenItems, settings.skipSystemItems, stopwatch, bgWorker ); DirSearch(settings.rootFolder, dirs, settings.skipHiddenItems, settings.skipSystemItems, stopwatch, bgWorker);
dirs = Utils.SortDirList( dirs ); dirs = Utils.SortDirList(dirs);
if( bgWorker.CancellationPending ) if (bgWorker.CancellationPending)
{ {
return null; return null;
} }
@ -170,137 +177,137 @@ namespace Snap2HTML
string created_date; string created_date;
// Parse each folder // Parse each folder
for( int d = 0; d < dirs.Count; d++ ) for (int d = 0; d < dirs.Count; d++)
{ {
// Get folder properties // Get folder properties
var dirName = dirs[d]; var dirName = dirs[d];
var currentDir = new SnappedFolder( Path.GetFileName( dirName ), Path.GetDirectoryName( dirName ) ); var currentDir = new SnappedFolder(Path.GetFileName(dirName), Path.GetDirectoryName(dirName));
if( dirName == Path.GetPathRoot( dirName ) ) if (dirName == Path.GetPathRoot(dirName))
{ {
currentDir = new SnappedFolder( "", dirName ); currentDir = new SnappedFolder("", dirName);
} }
modified_date = ""; modified_date = "";
created_date = ""; created_date = "";
try try
{ {
modified_date = Utils.ToUnixTimestamp( System.IO.Directory.GetLastWriteTime( dirName ).ToLocalTime() ).ToString(); modified_date = Utils.ToUnixTimestamp(System.IO.Directory.GetLastWriteTime(dirName).ToLocalTime()).ToString();
created_date = Utils.ToUnixTimestamp( System.IO.Directory.GetCreationTime( dirName ).ToLocalTime() ).ToString(); created_date = Utils.ToUnixTimestamp(System.IO.Directory.GetCreationTime(dirName).ToLocalTime()).ToString();
} }
catch( Exception ex ) catch (Exception ex)
{ {
Console.WriteLine( "{0} Exception caught.", ex ); Console.WriteLine("{0} Exception caught.", ex);
} }
currentDir.Properties.Add( "Modified", modified_date ); currentDir.Properties.Add("Modified", modified_date);
currentDir.Properties.Add( "Created", created_date ); currentDir.Properties.Add("Created", created_date);
// Get files in folder // Get files in folder
List<string> files; List<string> files;
try try
{ {
files = new List<string>( System.IO.Directory.GetFiles( dirName, "*.*", System.IO.SearchOption.TopDirectoryOnly ) ); files = new List<string>(System.IO.Directory.GetFiles(dirName, "*.*", System.IO.SearchOption.TopDirectoryOnly));
} }
catch( Exception ex ) catch (Exception ex)
{ {
Console.WriteLine( "{0} Exception caught.", ex ); Console.WriteLine("{0} Exception caught.", ex);
result.Add( currentDir ); result.Add(currentDir);
continue; continue;
} }
files.Sort(); files.Sort();
// Get file properties // Get file properties
foreach( string sFile in files ) foreach (string sFile in files)
{ {
totFiles++; totFiles++;
if(stopwatch.ElapsedMilliseconds >= 50) if (stopwatch.ElapsedMilliseconds >= 50)
{ {
bgWorker.ReportProgress( 0, "Reading files... " + totFiles + " (" + sFile + ")" ); bgWorker.ReportProgress(0, "Reading files... " + totFiles + " (" + sFile + ")");
stopwatch.Restart(); stopwatch.Restart();
} }
if( bgWorker.CancellationPending ) if (bgWorker.CancellationPending)
{ {
return null; return null;
} }
var currentFile = new SnappedFile( Path.GetFileName( sFile ) ); var currentFile = new SnappedFile(Path.GetFileName(sFile));
try try
{ {
System.IO.FileInfo fi = new System.IO.FileInfo( sFile ); System.IO.FileInfo fi = new System.IO.FileInfo(sFile);
var isHidden = ( fi.Attributes & System.IO.FileAttributes.Hidden ) == System.IO.FileAttributes.Hidden; var isHidden = (fi.Attributes & System.IO.FileAttributes.Hidden) == System.IO.FileAttributes.Hidden;
var isSystem = ( fi.Attributes & System.IO.FileAttributes.System ) == System.IO.FileAttributes.System; var isSystem = (fi.Attributes & System.IO.FileAttributes.System) == System.IO.FileAttributes.System;
if( ( isHidden && settings.skipHiddenItems ) || ( isSystem && settings.skipSystemItems ) ) if ((isHidden && settings.skipHiddenItems) || (isSystem && settings.skipSystemItems))
{ {
continue; continue;
} }
currentFile.Properties.Add( "Size", fi.Length.ToString() ); currentFile.Properties.Add("Size", fi.Length.ToString());
modified_date = "-"; modified_date = "-";
created_date = "-"; created_date = "-";
try try
{ {
modified_date = Utils.ToUnixTimestamp( fi.LastWriteTime.ToLocalTime() ).ToString(); modified_date = Utils.ToUnixTimestamp(fi.LastWriteTime.ToLocalTime()).ToString();
created_date = Utils.ToUnixTimestamp( fi.CreationTime.ToLocalTime() ).ToString(); created_date = Utils.ToUnixTimestamp(fi.CreationTime.ToLocalTime()).ToString();
} }
catch( Exception ex ) catch (Exception ex)
{ {
Console.WriteLine( "{0} Exception caught.", ex ); Console.WriteLine("{0} Exception caught.", ex);
} }
currentFile.Properties.Add( "Modified", modified_date ); currentFile.Properties.Add("Modified", modified_date);
currentFile.Properties.Add( "Created", created_date ); currentFile.Properties.Add("Created", created_date);
} }
catch( Exception ex ) catch (Exception ex)
{ {
Console.WriteLine( "{0} Exception caught.", ex ); Console.WriteLine("{0} Exception caught.", ex);
} }
currentDir.Files.Add( currentFile ); currentDir.Files.Add(currentFile);
} }
result.Add( currentDir ); result.Add(currentDir);
} }
} }
catch( System.Exception ex ) catch (System.Exception ex)
{ {
Console.WriteLine( "{0} exception caught: {1}", ex, ex.Message ); Console.WriteLine("{0} exception caught: {1}", ex, ex.Message);
} }
return result; return result;
} }
// Recursive function to get all folders and subfolders of given path path // Recursive function to get all folders and subfolders of given path path
private static void DirSearch( string sDir, List<string> lstDirs, bool skipHidden, bool skipSystem, Stopwatch stopwatch, BackgroundWorker backgroundWorker ) private static void DirSearch(string sDir, List<string> lstDirs, bool skipHidden, bool skipSystem, Stopwatch stopwatch, BackgroundWorker backgroundWorker)
{ {
if( backgroundWorker.CancellationPending ) return; if (backgroundWorker.CancellationPending) return;
try try
{ {
foreach( string d in System.IO.Directory.GetDirectories( sDir ) ) foreach (string d in System.IO.Directory.GetDirectories(sDir))
{ {
bool includeThisFolder = true; bool includeThisFolder = true;
//if( d.ToUpper().EndsWith( "SYSTEM VOLUME INFORMATION" ) ) includeThisFolder = false; //if( d.ToUpper().EndsWith( "SYSTEM VOLUME INFORMATION" ) ) includeThisFolder = false;
// exclude folders that have the system or hidden attr set (if required) // exclude folders that have the system or hidden attr set (if required)
if( skipHidden || skipSystem ) if (skipHidden || skipSystem)
{ {
var attr = new DirectoryInfo( d ).Attributes; var attr = new DirectoryInfo(d).Attributes;
if( skipHidden ) if (skipHidden)
{ {
if( ( attr & FileAttributes.Hidden ) == FileAttributes.Hidden ) if ((attr & FileAttributes.Hidden) == FileAttributes.Hidden)
{ {
includeThisFolder = false; includeThisFolder = false;
} }
} }
if( skipSystem ) if (skipSystem)
{ {
if( ( attr & FileAttributes.System ) == FileAttributes.System ) if ((attr & FileAttributes.System) == FileAttributes.System)
{ {
includeThisFolder = false; includeThisFolder = false;
} }
@ -308,27 +315,27 @@ namespace Snap2HTML
} }
if( includeThisFolder ) if (includeThisFolder)
{ {
lstDirs.Add( d ); lstDirs.Add(d);
if( stopwatch.ElapsedMilliseconds >= 50 ) if (stopwatch.ElapsedMilliseconds >= 50)
{ {
backgroundWorker.ReportProgress( 0, "Getting folders... " + lstDirs.Count + " (" + d + ")" ); backgroundWorker.ReportProgress(0, "Getting folders... " + lstDirs.Count + " (" + d + ")");
stopwatch.Restart(); stopwatch.Restart();
} }
DirSearch( d, lstDirs, skipHidden, skipSystem, stopwatch, backgroundWorker ); DirSearch(d, lstDirs, skipHidden, skipSystem, stopwatch, backgroundWorker);
} }
} }
} }
catch( System.Exception ex ) catch (System.Exception ex)
{ {
Console.WriteLine( "ERROR in DirSearch():" + ex.Message ); Console.WriteLine("ERROR in DirSearch():" + ex.Message);
} }
} }
private static void BuildJavascriptContentArray( List<SnappedFolder> content, int startIndex, StreamWriter writer, BackgroundWorker bgWorker ) private static void BuildJavascriptContentArray(List<SnappedFolder> content, int startIndex, StreamWriter writer, BackgroundWorker bgWorker)
{ {
// Data format: // Data format:
// Each index in "dirs" array is an array representing a directory: // Each index in "dirs" array is an array representing a directory:
@ -344,30 +351,33 @@ namespace Snap2HTML
// Assign an ID to each folder. This is equal to the index in the JS data array // Assign an ID to each folder. This is equal to the index in the JS data array
var dirIndexes = new Dictionary<string, string>(); var dirIndexes = new Dictionary<string, string>();
for( var i = 0; i < content.Count; i++ ) for (var i = 0; i < content.Count; i++)
{ {
dirIndexes.Add( content[i].FullPath, ( i + startIndex ).ToString() ); dirIndexes.Add(content[i].GetFullPath(), (i + startIndex).ToString());
} }
// Build a lookup table with subfolder IDs for each folder // Build a lookup table with subfolder IDs for each folder
var subdirs = new Dictionary<string, List<string>>(); var subdirs = new Dictionary<string, List<string>>();
foreach( var dir in content ) foreach (var dir in content)
{ {
subdirs.Add( dir.FullPath, new List<string>() ); // add all folders as keys
subdirs.Add(dir.GetFullPath(), new List<string>());
} }
if( !subdirs.ContainsKey( content[0].Path ) && content[0].Name != "" ) if (!subdirs.ContainsKey(content[0].Path) && content[0].Name != "")
{ {
subdirs.Add( content[0].Path, new List<string>() ); // ensure that root folder is not missed missed
subdirs.Add(content[0].Path, new List<string>());
} }
foreach( var dir in content ) foreach (var dir in content)
{ {
if( dir.Name != "" ) if (dir.Name != "")
{ {
try try
{ {
subdirs[dir.Path].Add( dirIndexes[dir.FullPath] ); // for each folder, add its index to its parent folder list of subdirs
subdirs[dir.Path].Add(dirIndexes[dir.GetFullPath()]);
} }
catch( Exception ex ) catch (Exception)
{ {
// orphan file or folder? // orphan file or folder?
} }
@ -376,45 +386,45 @@ namespace Snap2HTML
// Generate the data array // Generate the data array
var result = new StringBuilder(); var result = new StringBuilder();
foreach( var currentDir in content ) foreach (var currentDir in content)
{ {
result.Append( "D.p([" + lineBreakSymbol ); result.Append("D.p([" + lineBreakSymbol);
var sDirWithForwardSlash = currentDir.FullPath.Replace( @"\", "/" ); var sDirWithForwardSlash = currentDir.GetFullPath().Replace(@"\", "/");
result.Append( "\"" ).Append( Utils.MakeCleanJsString( sDirWithForwardSlash ) ).Append( "*" ).Append( "0" ).Append( "*" ).Append( currentDir.GetProp( "Modified" ) ).Append( "\"," + lineBreakSymbol ); result.Append("\"").Append(Utils.MakeCleanJsString(sDirWithForwardSlash)).Append("*").Append("0").Append("*").Append(currentDir.GetProp("Modified")).Append("\"," + lineBreakSymbol);
long dirSize = 0; long dirSize = 0;
foreach( var currentFile in currentDir.Files ) foreach (var currentFile in currentDir.Files)
{ {
result.Append( "\"" ).Append( Utils.MakeCleanJsString( currentFile.Name ) ).Append( "*" ).Append( currentFile.GetProp( "Size" ) ).Append( "*" ).Append( currentFile.GetProp( "Modified" ) ).Append( "\"," + lineBreakSymbol ); result.Append("\"").Append(Utils.MakeCleanJsString(currentFile.Name)).Append("*").Append(currentFile.GetProp("Size")).Append("*").Append(currentFile.GetProp("Modified")).Append("\"," + lineBreakSymbol);
dirSize += Utils.ParseLong( currentFile.GetProp( "Size" ) ); dirSize += Utils.ParseLong(currentFile.GetProp("Size"));
} }
// Add total dir size // Add total dir size
result.Append( "" ).Append( dirSize ).Append( "," + lineBreakSymbol ); result.Append("").Append(dirSize).Append("," + lineBreakSymbol);
// Add reference to subdirs // Add reference to subdirs
result.Append( "\"" ).Append( String.Join( "*", subdirs[currentDir.FullPath].ToArray() ) ).Append( "\"" + lineBreakSymbol ); // subdirs result.Append("\"").Append(String.Join("*", subdirs[currentDir.GetFullPath()].ToArray())).Append("\"" + lineBreakSymbol);
// Finalize // Finalize
result.Append( "])" ); result.Append("])");
result.Append( "\n" ); result.Append("\n");
// Write result in chunks to limit memory consumtion // Write result in chunks to limit memory consumption
if( result.Length > 10240 ) if (result.Length > 10240)
{ {
writer.Write( result.ToString() ); writer.Write(result.ToString());
result.Clear(); result.Clear();
} }
if( bgWorker.CancellationPending ) if (bgWorker.CancellationPending)
{ {
return; return;
} }
} }
writer.Write( result.ToString() ); writer.Write(result.ToString());
return; return;
} }

View File

@ -1,4 +1,4 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<!-- saved from url=(0016)http://localhost --> <!-- saved from url=(0016)http://localhost -->
<!-- This file was generated by [APP NAME] [APP VER] at [GEN DATE] [GEN TIME]. See [APP LINK] for more information --> <!-- This file was generated by [APP NAME] [APP VER] at [GEN DATE] [GEN TIME]. See [APP LINK] for more information -->
<html> <html>
@ -172,6 +172,22 @@
.list_files { .list_files {
overflow: auto; overflow: auto;
position: relative;
}
.search_indicator {
position: absolute;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
background-color: white;
opacity: 0.7;
text-align: center;
padding-top: 100px;
font-size: 18px;
display: none;
z-index: 99;
} }
/* --- Splitter --- */ /* --- Splitter --- */
@ -188,6 +204,7 @@
font-family:arial; font-family:arial;
background-color: #cdcdcd; background-color: #cdcdcd;
font-size: 8pt; font-size: 8pt;
line-height: 1.25em;
width: 100%; width: 100%;
text-align: left; text-align: left;
border-spacing: 0px; border-spacing: 0px;
@ -216,7 +233,11 @@
border-top: 1px solid #e0e0e0; border-top: 1px solid #e0e0e0;
padding: 3px 4px 3px 4px; padding: 3px 4px 3px 4px;
} }
#files.tablesorter tbody tr:nth-child(even) td {
#files.tablesorter:not(.has-parent-folder) tbody tr:nth-child(even) td {
background-color: #f8f8f8;
}
#files.tablesorter.has-parent-folder tbody tr:nth-child(odd) td {
background-color: #f8f8f8; background-color: #f8f8f8;
} }
@ -276,6 +297,28 @@
} }
/* make room for [..] */
#files.tablesorter.has-parent-folder th {
border-bottom: 1px solid #ccc;
}
#files.tablesorter.has-parent-folder tbody tr:first-child td {
border-top: 20px solid white;
}
#parent_folder {
position: absolute;
top: 24px;
left: 4px;
}
#parent_folder_border {
background-color: #e0e0e0;
height: 1px;
position: absolute;
width: 100%;
top: 42px;
}
/* --- Breadcrumb --- */ /* --- Breadcrumb --- */
.list_header { .list_header {
@ -369,7 +412,7 @@
} }
.export_text { .export_text {
width: 100%; width: 100%;
height: calc(100% - 5em); /* two .export_options => 4em + save link*/ height: calc(100% - 5.25em); /* two .export_options => 4em + save link*/
} }
.export_close:link, .export_close:visited { .export_close:link, .export_close:visited {
float: right; float: right;
@ -773,6 +816,7 @@
var originalHash = location.hash.replace(/#/,""); var originalHash = location.hash.replace(/#/,"");
var SelectedFolderID = "-1"; var SelectedFolderID = "-1";
var currentView; var currentView;
var onlyLinkExtensions = []; // example: ["jpg","png"]
/* --- Init --- */ /* --- Init --- */
@ -942,13 +986,17 @@
return; return;
} }
var showLocationColumn = true;
if( numberOfFiles > 5000 ) { if( numberOfFiles > 5000 ) {
$("#list_header").html( "Searching..." ); $("#search_indicator").show();
//$("#list_header").html( "Searching..." );
showLocationColumn = false;
} }
location.hash = ""; location.hash = "";
setTimeout(function(){ // timeout allows redrawing screen before possible timeconsuming search setTimeout(function(){ // timeout allows redrawing screen before possible time consuming search
if( SelectedFolderID != -1 ) if( SelectedFolderID != -1 )
{ {
@ -1005,9 +1053,15 @@
} }
} }
var locationHtml = "";
if(showLocationColumn) locationHtml = "<th>Folder</th>";
currentView = []; currentView = [];
var table_html = ""; var table_html = "";
table_html += "<table id='files' class='tablesorter'><thead><tr><th>Name</th><th>Folder</th><th>Size</th><th>Modified</th></tr></thead><tbody>\n"; table_html += "<table id='files' class='tablesorter'><thead><tr><th>Name</th>" +
locationHtml +
"<th>Size</th><th>Modified</th></tr></thead><tbody>";
var countFiles = 0; var countFiles = 0;
var countDirs = 0; var countDirs = 0;
@ -1051,18 +1105,23 @@
sizeDirs += SearchFilenames[index][1]; sizeDirs += SearchFilenames[index][1];
var subdir_id = parent_folders[ SearchLocationsID[index] ]; var subdir_id = parent_folders[ SearchLocationsID[index] ];
var timestamp = timestampToDate(SearchFilenames[index][2]);
locationHtml = "";
if(showLocationColumn) {
var located_in = SearchLocations[index]; var located_in = SearchLocations[index];
if( located_in === "" ) located_in = "[.]" if( located_in === "" ) located_in = "[.]"
located_in = located_in.substring( 0, located_in.lastIndexOf("\\") ); located_in = located_in.substring( 0, located_in.lastIndexOf("\\") );
var timestamp = timestampToDate(SearchFilenames[index][2]); locationHtml = "<td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + subdir_id + "\"> " + located_in + "</a></span></td>";
}
table_html += table_html +=
"<tr>" + "<tr>" +
"<td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + SearchLocationsID[index] + "\"> " + SearchFilenames[index][3] + "</a></span></td>" + "<td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + SearchLocationsID[index] + "\"> " + SearchFilenames[index][3] + "</a></span></td>" +
"<td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + subdir_id + "\"> " + located_in + "</a></span></td>" + locationHtml +
"<td class='size' data-sort='" + SearchFilenames[index][1] + "'>" + bytesToSize( SearchFilenames[index][1] ) + "</td>" + "<td class='size' data-sort='" + SearchFilenames[index][1] + "'>" + bytesToSize( SearchFilenames[index][1] ) + "</td>" +
"<td class='date' data-sort='" + SearchFilenames[index][2] + "'>" + timestamp + "</td>" + "<td class='date' data-sort='" + SearchFilenames[index][2] + "'>" + timestamp + "</td>" +
"</tr>\n"; "</tr>";
currentView.push( { "name": SearchFilenames[index][3], "path": SearchLocationsRaw[index].replace(/\//g,"\\"), "type": "dir", "size": SearchFilenames[index][1], "date": SearchFilenames[index][2] } ); currentView.push( { "name": SearchFilenames[index][3], "path": SearchLocationsRaw[index].replace(/\//g,"\\"), "type": "dir", "size": SearchFilenames[index][1], "date": SearchFilenames[index][2] } );
} }
else // files else // files
@ -1074,6 +1133,9 @@
if( linkFiles ) if( linkFiles )
{ {
var ext = file_tmp.split('.').pop();
if(onlyLinkExtensions.length === 0 || onlyLinkExtensions.indexOf(ext) !== -1) {
file_tmp = linkProtocol + linkRoot + dir_tmp.replace("\\","/") + SearchFilenames[index][3] + "\">"; file_tmp = linkProtocol + linkRoot + dir_tmp.replace("\\","/") + SearchFilenames[index][3] + "\">";
if( navigator.userAgent.toLowerCase().indexOf("msie") !== -1 && linkProtocol.indexOf("file:") !== -1 ) if( navigator.userAgent.toLowerCase().indexOf("msie") !== -1 && linkProtocol.indexOf("file:") !== -1 )
{ {
@ -1098,17 +1160,24 @@
file_tmp = "<a href=\"" + file_tmp + SearchFilenames[index][3] + "</a>"; file_tmp = "<a href=\"" + file_tmp + SearchFilenames[index][3] + "</a>";
} }
}
locationHtml = "";
if(showLocationColumn) {
var located_in = SearchLocations[index]; var located_in = SearchLocations[index];
if( located_in === "" ) located_in = "[.]" if( located_in === "" ) located_in = "[.]"
locationHtml = "<td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + SearchLocationsID[index] + "\"> " + located_in + "</a></span></td>";
}
var timestamp = timestampToDate(SearchFilenames[index][2]); var timestamp = timestampToDate(SearchFilenames[index][2]);
table_html += table_html +=
"<tr>" + "<tr>" +
"<td><span class='file'>" + file_tmp + "</span></td>" + "<td><span class='file'>" + file_tmp + "</span></td>" +
"<td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + SearchLocationsID[index] + "\"> " + located_in + "</a></span></td>" + locationHtml +
"<td class='size' data-sort='" + SearchFilenames[index][1] + "'>" + bytesToSize( SearchFilenames[index][1] ) + "</td>" + "<td class='size' data-sort='" + SearchFilenames[index][1] + "'>" + bytesToSize( SearchFilenames[index][1] ) + "</td>" +
"<td class='date' data-sort='" + SearchFilenames[index][2] + "'>" + timestamp + "</td>" + "<td class='date' data-sort='" + SearchFilenames[index][2] + "'>" + timestamp + "</td>" +
"</tr>\n"; "</tr>";
currentView.push( { "name": SearchFilenames[index][3], "path": SearchLocationsRaw[index].replace(/\//g,"\\"), "type": "file", "size": SearchFilenames[index][1], "date": SearchFilenames[index][2] } ); currentView.push( { "name": SearchFilenames[index][3], "path": SearchLocationsRaw[index].replace(/\//g,"\\"), "type": "file", "size": SearchFilenames[index][1], "date": SearchFilenames[index][2] } );
@ -1138,24 +1207,28 @@
} }
} }
table_html += "</tbody></table>\n"; table_html += "</tbody></table>";
$("#list_header").html( "Search Results <span class='path_divider'></span>" ); $("#list_header").html( "Search Results <span class='path_divider'></span>" );
document.getElementById("list_files").innerHTML = table_html; document.getElementById("list_files").innerHTML = table_html;
$("#search_indicator").hide();
addFolderClickEventHandlers(); addFolderClickEventHandlers();
var tablesorterHeaders = { 1 : { sorter: 'datasort' }, 2 : { sorter: 'datasort' } }
if(showLocationColumn) {
tablesorterHeaders = { 2 : { sorter: 'datasort' }, 3 : { sorter: 'datasort' } }
}
$("#files").tablesorter({ $("#files").tablesorter({
sortInitialOrder: "desc", sortInitialOrder: "desc",
headers: { headers: tablesorterHeaders
2 : { sorter: 'datasort' },
3 : { sorter: 'datasort' }
}
}); });
var sFiles = " files"; if(countFiles===1) sFiles = " file"; var sFiles = " files"; if(countFiles===1) sFiles = " file";
var sDirs = " folders"; if(countDirs===1) sDirs = " folder"; var sDirs = " folders"; if(countDirs===1) sDirs = " folder";
$("#list_footer_info_label").html( countDirs + sDirs + " (" + bytesToSize( sizeDirs , 0 ) + "), " + countFiles + sFiles + " (" + bytesToSize( sizeFiles , 0 ) + ")" ); $("#list_footer_info_label").html( countDirs + sDirs + " (" + bytesToSize( sizeDirs , 0 ) + "), " + countFiles + sFiles + " (" + bytesToSize( sizeFiles , 0 ) + ")" );
}, 1); // end setTimeout before search }, 50); // end setTimeout before search
}; // end doSearch() }; // end doSearch()
@ -1192,14 +1265,20 @@
$("#list_header").html( breadcrumbs ); $("#list_header").html( breadcrumbs );
var table_html = ""; var table_html = "";
table_html += "<table id='files' class='tablesorter'><thead><th>Name</th><th>Size</th><th>Modified</th></tr></thead><tbody>\n"; var showParentFolderClass = "";
if( FolderID != 0 ) {
showParentFolderClass = " has-parent-folder"
table_html += "<span id='parent_folder' class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + parent_folders[FolderID] + "\"> [..]</a></span>\n";
table_html += "<div id='parent_folder_border'></div>";
}
table_html += "<table id='files' class='tablesorter" + showParentFolderClass + "'><thead><th>Name</th><th>Size</th><th>Modified</th></tr></thead><tbody>\n";
currentView = []; currentView = [];
var countFiles = 0; var countFiles = 0;
var countDirs = 0; var countDirs = 0;
var subdirTotSizes = 0; var subdirTotSizes = 0;
// folders // folders
if( FolderID != 0 ) table_html += "<tr><td><span class='file_folder'><a href=\"#\" class=\"folder_link\" id=\"" + parent_folders[FolderID] + "\"> [..]</a></span></td><td></td><td></td></tr>\n";
var subdirs = getSubdirs( SelectedFolderID ); var subdirs = getSubdirs( SelectedFolderID );
if( subdirs != "" ) if( subdirs != "" )
{ {
@ -1231,6 +1310,9 @@
if( dir_tmp != "" ) dir_tmp += "/"; if( dir_tmp != "" ) dir_tmp += "/";
if( linkFiles ) if( linkFiles )
{ {
var ext = file_tmp.split('.').pop();
if(onlyLinkExtensions.length === 0 || onlyLinkExtensions.indexOf(ext) !== -1) {
file_tmp = linkProtocol + linkRoot + dir_tmp + sTmp[0] + "\">"; file_tmp = linkProtocol + linkRoot + dir_tmp + sTmp[0] + "\">";
if( navigator.userAgent.toLowerCase().indexOf("msie") !== -1 && linkProtocol.indexOf("file:") !== -1 ) if( navigator.userAgent.toLowerCase().indexOf("msie") !== -1 && linkProtocol.indexOf("file:") !== -1 )
{ {
@ -1255,6 +1337,7 @@
file_tmp = "<a href=\"" + file_tmp + sTmp[0] + "</a>"; file_tmp = "<a href=\"" + file_tmp + sTmp[0] + "</a>";
} }
}
var timestamp = timestampToDate(sTmp[2]); var timestamp = timestampToDate(sTmp[2]);
@ -1600,7 +1683,6 @@
}; };
}; };
// Save export to local file. Based on https://stackoverflow.com/a/29304414/1087811 // Save export to local file. Based on https://stackoverflow.com/a/29304414/1087811
function downloadToFile(content, fileName, mimeType) { function downloadToFile(content, fileName, mimeType) {
var a = document.createElement('a'); var a = document.createElement('a');
@ -1648,10 +1730,12 @@
<div id="loading" class="loading"><b>Loading...</b><p class="loading_info">(if nothing happens, make sure javascript is enabled and allowed to execute, or try another browser)</p></div> <div id="loading" class="loading"><b>Loading...</b><p class="loading_info">(if nothing happens, make sure javascript is enabled and allowed to execute, or try another browser)</p></div>
<div id="content" class="content"> <div id="content" class="content">
<div id="treeview" class="treeview"></div> <div id="treeview" class="treeview"></div>
<div id="list_container" class="list_container"> <div id="list_container" class="list_container">
<div id="search_indicator" class="search_indicator">
Searching...
</div>
<div id="list_header" class="list_header"></div> <div id="list_header" class="list_header"></div>
<div id="list_files" class="list_files"></div> <div id="list_files" class="list_files"></div>
<div id="list_footer" class='list_footer'> <div id="list_footer" class='list_footer'>
@ -1659,7 +1743,6 @@
<span id="list_footer_info_label"></span> <span id="list_footer_info_label"></span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>