diff --git a/.gitignore b/.gitignore
index 43ee5b8..1c664be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
bin/
obj/
TestData/
-.vs/
\ No newline at end of file
+.vs/
+.DS_Store
diff --git a/App.config b/App.config
index 4bfa005..fe44faf 100644
--- a/App.config
+++ b/App.config
@@ -1,6 +1,24 @@
+
+
+
+
+
+
+
+
+ 0, 0, -1, -1
+
+
+ False
+
+
+ True
+
+
+
diff --git a/LoxStatEdit.csproj b/LoxStatEdit.csproj
index 34555b6..0d03b0f 100644
--- a/LoxStatEdit.csproj
+++ b/LoxStatEdit.csproj
@@ -75,6 +75,11 @@
+
+ True
+ True
+ Settings.settings
+
MiniserverForm.cs
@@ -88,6 +93,10 @@
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
@@ -100,4 +109,4 @@
-->
-
+
\ No newline at end of file
diff --git a/LoxStatFileForm.cs b/LoxStatFileForm.cs
index 3f7aa20..38a5312 100644
--- a/LoxStatFileForm.cs
+++ b/LoxStatFileForm.cs
@@ -636,6 +636,12 @@ private static DialogResult ShowInputDialog(ref string input, Form parentForm)
private void MainForm_Load(object sender, EventArgs e)
{
+ // if not remote desktop session then enable double-buffering optimization
+ if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
+ {
+ typeof(DataGridView).InvokeMember("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.SetProperty, null, _dataGridView, new object[] { true });
+ }
+
if((_args != null) && (_args.Length > 0))
{
_fileNameTextBox.Text = _args[0];
diff --git a/MiniserverForm.Designer.cs b/MiniserverForm.Designer.cs
index fc58080..2ac2ef3 100644
--- a/MiniserverForm.Designer.cs
+++ b/MiniserverForm.Designer.cs
@@ -51,10 +51,14 @@ private void InitializeComponent()
this._nameCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
this._descriptionCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
this._yearMonthCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this._dateModifiedCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this._sizeCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
this._statusCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
this._downloadCol = new System.Windows.Forms.DataGridViewButtonColumn();
this._editCol = new System.Windows.Forms.DataGridViewButtonColumn();
this._uploadCol = new System.Windows.Forms.DataGridViewButtonColumn();
+ this._convertCol = new System.Windows.Forms.DataGridViewButtonColumn();
+ this._deleteCol = new System.Windows.Forms.DataGridViewButtonColumn();
this.githubLabel = new System.Windows.Forms.LinkLabel();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this._filterTextBox = new System.Windows.Forms.TextBox();
@@ -79,6 +83,7 @@ private void InitializeComponent()
// urlLabel
//
urlLabel.Location = new System.Drawing.Point(12, 17);
+ urlLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
urlLabel.Name = "urlLabel";
urlLabel.Size = new System.Drawing.Size(70, 18);
urlLabel.TabIndex = 0;
@@ -88,6 +93,7 @@ private void InitializeComponent()
//
refreshFolderButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
refreshFolderButton.Location = new System.Drawing.Point(882, 38);
+ refreshFolderButton.Margin = new System.Windows.Forms.Padding(6);
refreshFolderButton.Name = "refreshFolderButton";
refreshFolderButton.Size = new System.Drawing.Size(75, 23);
refreshFolderButton.TabIndex = 6;
@@ -100,6 +106,7 @@ private void InitializeComponent()
//
refreshMsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
refreshMsButton.Location = new System.Drawing.Point(882, 12);
+ refreshMsButton.Margin = new System.Windows.Forms.Padding(6);
refreshMsButton.Name = "refreshMsButton";
refreshMsButton.Size = new System.Drawing.Size(75, 23);
refreshMsButton.TabIndex = 2;
@@ -111,6 +118,7 @@ private void InitializeComponent()
// folderLabel
//
folderLabel.Location = new System.Drawing.Point(12, 42);
+ folderLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
folderLabel.Name = "folderLabel";
folderLabel.Size = new System.Drawing.Size(70, 18);
folderLabel.TabIndex = 3;
@@ -120,6 +128,7 @@ private void InitializeComponent()
//
downloadButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
downloadButton.Location = new System.Drawing.Point(729, 527);
+ downloadButton.Margin = new System.Windows.Forms.Padding(6);
downloadButton.Name = "downloadButton";
downloadButton.Size = new System.Drawing.Size(111, 23);
downloadButton.TabIndex = 9;
@@ -132,6 +141,7 @@ private void InitializeComponent()
//
uploadButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
uploadButton.Location = new System.Drawing.Point(846, 527);
+ uploadButton.Margin = new System.Windows.Forms.Padding(6);
uploadButton.Name = "uploadButton";
uploadButton.Size = new System.Drawing.Size(111, 23);
uploadButton.TabIndex = 10;
@@ -144,15 +154,18 @@ private void InitializeComponent()
//
aboutLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
aboutLabel.Location = new System.Drawing.Point(12, 532);
+ aboutLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
aboutLabel.Name = "aboutLabel";
aboutLabel.Size = new System.Drawing.Size(171, 18);
aboutLabel.TabIndex = 100;
- aboutLabel.Text = "LoxStatEdit v1.0.5.1 (2024.07.19)";
+ aboutLabel.Text = "LoxStatEdit v1.0.6.2 (2025.01.14)";
+ aboutLabel.Click += new System.EventHandler(this.aboutLabel_Click);
//
// openFolderButton
//
openFolderButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
openFolderButton.Location = new System.Drawing.Point(801, 38);
+ openFolderButton.Margin = new System.Windows.Forms.Padding(6);
openFolderButton.Name = "openFolderButton";
openFolderButton.Size = new System.Drawing.Size(75, 23);
openFolderButton.TabIndex = 5;
@@ -165,6 +178,7 @@ private void InitializeComponent()
//
browseFolderButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
browseFolderButton.Location = new System.Drawing.Point(720, 38);
+ browseFolderButton.Margin = new System.Windows.Forms.Padding(6);
browseFolderButton.Name = "browseFolderButton";
browseFolderButton.Size = new System.Drawing.Size(75, 23);
browseFolderButton.TabIndex = 4;
@@ -176,6 +190,7 @@ private void InitializeComponent()
// filterLabel
//
filterLabel.Location = new System.Drawing.Point(12, 68);
+ filterLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
filterLabel.Name = "filterLabel";
filterLabel.Size = new System.Drawing.Size(70, 18);
filterLabel.TabIndex = 105;
@@ -185,10 +200,12 @@ private void InitializeComponent()
//
filterButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
filterButton.Location = new System.Drawing.Point(882, 64);
+ filterButton.Margin = new System.Windows.Forms.Padding(6);
filterButton.Name = "filterButton";
filterButton.Size = new System.Drawing.Size(75, 23);
filterButton.TabIndex = 8;
filterButton.Text = "Filter";
+ this.toolTip.SetToolTip(filterButton, "Filter the displayed entries");
filterButton.UseVisualStyleBackColor = true;
filterButton.Click += new System.EventHandler(this.FilterButton_Click);
//
@@ -197,6 +214,7 @@ private void InitializeComponent()
this._urlTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._urlTextBox.Location = new System.Drawing.Point(88, 14);
+ this._urlTextBox.Margin = new System.Windows.Forms.Padding(6);
this._urlTextBox.Name = "_urlTextBox";
this._urlTextBox.Size = new System.Drawing.Size(788, 20);
this._urlTextBox.TabIndex = 1;
@@ -209,6 +227,7 @@ private void InitializeComponent()
this._folderTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._folderTextBox.Location = new System.Drawing.Point(88, 40);
+ this._folderTextBox.Margin = new System.Windows.Forms.Padding(6);
this._folderTextBox.Name = "_folderTextBox";
this._folderTextBox.Size = new System.Drawing.Size(626, 20);
this._folderTextBox.TabIndex = 3;
@@ -227,11 +246,16 @@ private void InitializeComponent()
this._nameCol,
this._descriptionCol,
this._yearMonthCol,
+ this._dateModifiedCol,
+ this._sizeCol,
this._statusCol,
this._downloadCol,
this._editCol,
- this._uploadCol});
+ this._uploadCol,
+ this._convertCol,
+ this._deleteCol});
this._dataGridView.Location = new System.Drawing.Point(12, 93);
+ this._dataGridView.Margin = new System.Windows.Forms.Padding(6);
this._dataGridView.Name = "_dataGridView";
this._dataGridView.RowHeadersWidth = 30;
this._dataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
@@ -240,24 +264,25 @@ private void InitializeComponent()
this._dataGridView.VirtualMode = true;
this._dataGridView.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.DataGridView_CellContentClick);
this._dataGridView.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.DataGridView_CellValueNeeded);
- this._dataGridView.CellFormatting += DataGridView_CellFormatting;
//
// _nameCol
//
this._nameCol.DataPropertyName = "Name";
this._nameCol.HeaderText = "Name";
- this._nameCol.MinimumWidth = 8;
+ this._nameCol.MinimumWidth = 10;
this._nameCol.Name = "_nameCol";
this._nameCol.ReadOnly = true;
+ this._nameCol.ToolTipText = "Name of the file";
this._nameCol.Width = 250;
//
// _descriptionCol
//
this._descriptionCol.DataPropertyName = "Description";
this._descriptionCol.HeaderText = "Description";
- this._descriptionCol.MinimumWidth = 8;
+ this._descriptionCol.MinimumWidth = 10;
this._descriptionCol.Name = "_descriptionCol";
this._descriptionCol.ReadOnly = true;
+ this._descriptionCol.ToolTipText = "Defined in Loxone Config";
this._descriptionCol.Width = 250;
//
// _yearMonthCol
@@ -266,18 +291,39 @@ private void InitializeComponent()
dataGridViewCellStyle1.Format = "yyyy-MM";
this._yearMonthCol.DefaultCellStyle = dataGridViewCellStyle1;
this._yearMonthCol.HeaderText = "Year/Month";
- this._yearMonthCol.MinimumWidth = 8;
+ this._yearMonthCol.MinimumWidth = 10;
this._yearMonthCol.Name = "_yearMonthCol";
this._yearMonthCol.ReadOnly = true;
+ this._yearMonthCol.ToolTipText = "From filename extension";
this._yearMonthCol.Width = 90;
//
+ // _dateModifiedCol
+ //
+ this._dateModifiedCol.HeaderText = "Date modified";
+ this._dateModifiedCol.MinimumWidth = 70;
+ this._dateModifiedCol.Name = "_dateModifiedCol";
+ this._dateModifiedCol.ReadOnly = true;
+ this._dateModifiedCol.ToolTipText = "Date when the file was modified. NOTE: file that were downloaded via FTP have a d" +
+ "ate with tiis or last year.";
+ this._dateModifiedCol.Width = 100;
+ //
+ // _sizeCol
+ //
+ this._sizeCol.HeaderText = "Size";
+ this._sizeCol.MinimumWidth = 60;
+ this._sizeCol.Name = "_sizeCol";
+ this._sizeCol.ReadOnly = true;
+ this._sizeCol.ToolTipText = "Size of file on FS (local system)";
+ this._sizeCol.Width = 90;
+ //
// _statusCol
//
- this._statusCol.DataPropertyName = "Status";
+ this._statusCol.DataPropertyName = "StatusString";
this._statusCol.HeaderText = "Status";
- this._statusCol.MinimumWidth = 8;
+ this._statusCol.MinimumWidth = 10;
this._statusCol.Name = "_statusCol";
this._statusCol.ReadOnly = true;
+ this._statusCol.ToolTipText = "Result of comparision between file on Loxone MS and FS (local system)";
this._statusCol.Width = 100;
//
// _downloadCol
@@ -287,26 +333,49 @@ private void InitializeComponent()
this._downloadCol.Name = "_downloadCol";
this._downloadCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this._downloadCol.Text = "Download";
+ this._downloadCol.ToolTipText = "Copy file from Loxone MS to FS (local system)";
this._downloadCol.Width = 60;
//
// _editCol
//
this._editCol.HeaderText = "Edit";
- this._editCol.MinimumWidth = 8;
+ this._editCol.MinimumWidth = 20;
this._editCol.Name = "_editCol";
this._editCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this._editCol.Text = "Edit";
+ this._editCol.ToolTipText = "Edit entries of this file on FS (local system)";
this._editCol.Width = 50;
//
// _uploadCol
//
this._uploadCol.HeaderText = "Upload";
- this._uploadCol.MinimumWidth = 8;
+ this._uploadCol.MinimumWidth = 20;
this._uploadCol.Name = "_uploadCol";
- this._uploadCol.Resizable = System.Windows.Forms.DataGridViewTriState.True;
+ this._uploadCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this._uploadCol.Text = "Upload";
+ this._uploadCol.ToolTipText = "Copy file from FS (local system) to Loxone MS";
this._uploadCol.Width = 60;
//
+ // _convertCol
+ //
+ this._convertCol.HeaderText = "Convert";
+ this._convertCol.MinimumWidth = 20;
+ this._convertCol.Name = "_convertCol";
+ this._convertCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this._convertCol.Text = "Convert";
+ this._convertCol.ToolTipText = "Convert data from old meter function block to new style";
+ this._convertCol.Width = 60;
+ //
+ // _deleteCol
+ //
+ this._deleteCol.HeaderText = "Delete";
+ this._deleteCol.MinimumWidth = 20;
+ this._deleteCol.Name = "_deleteCol";
+ this._deleteCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this._deleteCol.Text = "Delete";
+ this._deleteCol.ToolTipText = "Delete file on Loxone MS or FS (local system) after confirmation";
+ this._deleteCol.Width = 60;
+ //
// githubLabel
//
this.githubLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@@ -314,6 +383,7 @@ private void InitializeComponent()
this.githubLabel.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.githubLabel.LinkColor = System.Drawing.Color.Blue;
this.githubLabel.Location = new System.Drawing.Point(184, 533);
+ this.githubLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
this.githubLabel.Name = "githubLabel";
this.githubLabel.Size = new System.Drawing.Size(42, 18);
this.githubLabel.TabIndex = 101;
@@ -327,6 +397,7 @@ private void InitializeComponent()
this._filterTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._filterTextBox.Location = new System.Drawing.Point(88, 66);
+ this._filterTextBox.Margin = new System.Windows.Forms.Padding(6);
this._filterTextBox.Name = "_filterTextBox";
this._filterTextBox.Size = new System.Drawing.Size(788, 20);
this._filterTextBox.TabIndex = 7;
@@ -340,6 +411,7 @@ private void InitializeComponent()
this.donateLabel.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.donateLabel.LinkColor = System.Drawing.Color.Blue;
this.donateLabel.Location = new System.Drawing.Point(232, 533);
+ this.donateLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
this.donateLabel.Name = "donateLabel";
this.donateLabel.Size = new System.Drawing.Size(96, 18);
this.donateLabel.TabIndex = 102;
@@ -352,6 +424,7 @@ private void InitializeComponent()
//
this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.progressBar.Location = new System.Drawing.Point(563, 527);
+ this.progressBar.Margin = new System.Windows.Forms.Padding(6);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(160, 23);
this.progressBar.TabIndex = 103;
@@ -362,6 +435,7 @@ private void InitializeComponent()
this.progressLabel.AutoSize = true;
this.progressLabel.BackColor = System.Drawing.Color.Transparent;
this.progressLabel.Location = new System.Drawing.Point(568, 532);
+ this.progressLabel.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
this.progressLabel.Name = "progressLabel";
this.progressLabel.Size = new System.Drawing.Size(24, 13);
this.progressLabel.TabIndex = 104;
@@ -393,10 +467,13 @@ private void InitializeComponent()
this.Controls.Add(folderLabel);
this.Controls.Add(this._folderTextBox);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.Margin = new System.Windows.Forms.Padding(6);
this.MinimumSize = new System.Drawing.Size(750, 270);
this.Name = "MiniserverForm";
this.Text = "Loxone Stats Editor - Miniserver Browser";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MiniserverForm_Closing);
this.Load += new System.EventHandler(this.MiniserverForm_Load);
+ this.ResizeEnd += new System.EventHandler(this.MiniserverForm_ResizEnd);
((System.ComponentModel.ISupportInitialize)(this._dataGridView)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -411,16 +488,20 @@ private void InitializeComponent()
private LinkLabel githubLabel;
private ToolTip toolTip;
private LinkLabel donateLabel;
+ private ProgressBar progressBar;
+ private Label progressLabel;
+ private FolderBrowserDialog folderBrowserDialog;
+ private TextBox _filterTextBox;
private DataGridViewTextBoxColumn _nameCol;
private DataGridViewTextBoxColumn _descriptionCol;
private DataGridViewTextBoxColumn _yearMonthCol;
+ private DataGridViewTextBoxColumn _dateModifiedCol;
+ private DataGridViewTextBoxColumn _sizeCol;
private DataGridViewTextBoxColumn _statusCol;
private DataGridViewButtonColumn _downloadCol;
private DataGridViewButtonColumn _editCol;
private DataGridViewButtonColumn _uploadCol;
- private ProgressBar progressBar;
- private Label progressLabel;
- private FolderBrowserDialog folderBrowserDialog;
- private TextBox _filterTextBox;
+ private DataGridViewButtonColumn _convertCol;
+ private DataGridViewButtonColumn _deleteCol;
}
}
\ No newline at end of file
diff --git a/MiniserverForm.cs b/MiniserverForm.cs
index 252ca39..1340f98 100644
--- a/MiniserverForm.cs
+++ b/MiniserverForm.cs
@@ -1,10 +1,13 @@
-using System;
+using LoxStatEdit.Properties;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
+using System.Reflection;
+using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -27,6 +30,28 @@ public string FileName
return (MsFileInfo != null) ? MsFileInfo.FileName : FileInfo.Name;
}
}
+ public bool IsValidMsStatsFile
+ {
+ get
+ {
+ var fileName = (MsFileInfo != null) ? MsFileInfo.FileName : FileInfo.Name;
+
+ // verify if file has valid Loxone stats format with UUID and .yyyyMM extension
+ var pattern = @"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{16})(_[1-9])?\.([12][0-9]{3})([01][0-9])";
+ // 1st group (): UUID
+ // 2nd group (): yyyy
+ // 3rd group (): MM
+ var result = Regex.Match(fileName, pattern);
+
+ // no further evaluation of Regex so far
+
+ var validFormat = false;
+ if (result.Success)
+ validFormat = true;
+
+ return (validFormat);
+ }
+ }
public string Name
{
@@ -78,41 +103,106 @@ public DateTime YearMonth
}
}
- public string Status
+ public DateTime DateModified
+ {
+ get
+ {
+ return (FileInfo != null) ? FileInfo.LastWriteTime : MsFileInfo.Date;
+ }
+ }
+
+ public long Size
+ {
+ get
+ {
+ return (FileInfo != null) ? FileInfo.Length : MsFileInfo.Size;
+ }
+ }
+
+ public const int IDStatusOnlyOnMS = 1;
+
+ public const int IDStatusOnlyOnFS = 2;
+
+ public const int IDStatusNewerOnMS = 3;
+
+ public const int IDStatusNewerOnFS = 4;
+
+ public const int IDStatusLargerOnMS = 5;
+
+ public const int IDStatusLargerOnFS = 6;
+
+ public const int IDStatusSame = 7;
+ public int Status
{
get
{
- if(FileInfo == null)
+ if (FileInfo == null)
{
- return "Only on MS";
+ return IDStatusOnlyOnMS;
}
- if(MsFileInfo == null)
+ if (MsFileInfo == null)
{
- return "Only on FS";
+ return IDStatusOnlyOnFS;
}
- if(FileInfo.LastWriteTime > MsFileInfo.Date)
+ if (FileInfo.LastWriteTime < MsFileInfo.Date)
{
- return "Newer on FS";
+ return IDStatusNewerOnMS;
}
- if(FileInfo.LastWriteTime < MsFileInfo.Date)
+ if (FileInfo.LastWriteTime > MsFileInfo.Date)
{
- return "Newer on MS";
+ return IDStatusNewerOnFS;
}
- if(FileInfo.Length > MsFileInfo.Size)
+ if (FileInfo.Length < MsFileInfo.Size)
{
- return "Larger on FS";
+ return IDStatusLargerOnMS;
}
- if(FileInfo.Length < MsFileInfo.Size)
+ if (FileInfo.Length > MsFileInfo.Size)
{
- return "Larger on MS";
+ return IDStatusLargerOnFS;
}
- return "Same date/size";
+ return IDStatusSame;
+ }
+ }
+
+ public string StatusString
+ {
+ get
+ {
+ string statusString;
+
+ switch (Status)
+ {
+ case IDStatusOnlyOnMS:
+ statusString = "Only on MS";
+ break;
+ case IDStatusOnlyOnFS:
+ statusString = "Only on FS";
+ break;
+ case IDStatusNewerOnMS:
+ statusString = "Newer on MS";
+ break;
+ case IDStatusNewerOnFS:
+ statusString = "Older on MS";
+ break;
+ case IDStatusLargerOnMS:
+ statusString = "Larger on MS";
+ break;
+ case IDStatusLargerOnFS:
+ statusString = "Smaller on MS";
+ break;
+ default:
+ // IDStatusSame
+ statusString = "Same date/size";
+ break;
+ }
+
+ return statusString;
}
}
public override string ToString()
{
- return string.Format("{0} ({1})", Name, Status);
+ return string.Format("{0} ({1})", Name, StatusString);
}
public int CompareTo(FileItem other)
@@ -215,43 +305,104 @@ private void RefreshGridView()
// Clear existing columns
_dataGridView.Columns.Clear();
+ // Add Cell Formatting
+ _dataGridView.CellFormatting += DataGridView_CellFormatting;
+
+ // Add Tool Tips
+ _dataGridView.CellToolTipTextNeeded += DataGridView_CellToolTipTextNeeded;
+
// Add columns manually in the order you want
_dataGridView.Columns.Add(new DataGridViewTextBoxColumn {
DataPropertyName = "FileName",
- HeaderText = "File",
- Width = 250
+ HeaderText = "FileName",
+ Width = 250,
+ ToolTipText = "Name of the file on the Loxone MS and local file system (FS).\n"+
+ "NOTE: This is typically an UUID plus extension with .yyyyMM",
});
_dataGridView.Columns.Add(new DataGridViewTextBoxColumn {
DataPropertyName = "Name",
HeaderText = "Description",
MinimumWidth = 250,
+ ToolTipText = "Defined in Loxone Config and retrieved from statistics data.",
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
});
- _dataGridView.Columns.Add(new DataGridViewTextBoxColumn {
+ _dataGridView.Columns.Add(new DataGridViewTextBoxColumn
+ {
DataPropertyName = "YearMonth",
HeaderText = "Year/Month",
Width = 90,
+ ToolTipText = "Year and month from file extension on MS. \n"+
+ "NOTE: This date is used on MS to fetch statistics data from a specific year and month.",
DefaultCellStyle = { Format = "yyyy-MM" }
});
+ _dataGridView.Columns.Add(new DataGridViewTextBoxColumn
+ {
+ DataPropertyName = "DateModified",
+ HeaderText = "Date modified",
+ Width = 120,
+ ToolTipText = "Date and time when the file was modified.\n\nThe date and time is from the local file system (FS), if the file is found there.\n"+
+ "If the file is not found on the local FS,\nit's the date and time that is received from the MS via FTP.\n"+
+ "If there is any difference the 'status' column will give you more information.\n\n"+
+ "NOTE: files that were downloaded via FTP always have a date with this or last year.\n"+
+ "The reason is that the Loxone MS does not transmit any year in directory listings via FTP.",
+ DefaultCellStyle = { Format = "dd.MM.yyyy - HH:mm:ss" }
+ });
_dataGridView.Columns.Add(new DataGridViewTextBoxColumn {
- DataPropertyName = "Status",
+ DataPropertyName = "Size",
+ HeaderText = "Size",
+ Width = 90,
+ ToolTipText = "Size of the file on the local file system (FS) or MS.\n\n"+
+ "The size is from the local FS, if the file is found there.\n"+
+ "If the file is not found on the local FS,\\nit's the size that is received from the MS via FTP.\n"+
+ "If there is any difference for files with same modification date/time,\n"+
+ "the 'status' column will give you more information.",
+ DefaultCellStyle = new DataGridViewCellStyle()
+ {
+ Alignment = DataGridViewContentAlignment.MiddleRight,
+ ForeColor = System.Drawing.Color.Black
+ },
+ //AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
+ });
+ _dataGridView.Columns.Add(new DataGridViewTextBoxColumn {
+ DataPropertyName = "StatusString",
HeaderText = "Status",
- Width = 100
+ Width = 100,
+ ToolTipText = "Result of a comparision between the file on Loxone MS and local file system (FS).",
+ DefaultCellStyle = new DataGridViewCellStyle()
+ {
+ BackColor = System.Drawing.Color.White,
+ ForeColor = System.Drawing.Color.Black
+ },
});
_dataGridView.Columns.Add(new DataGridViewButtonColumn {
DataPropertyName = "Download",
HeaderText = "Download",
- Width = 60
+ Width = 60,
+ ToolTipText = "Copy a file from Loxone MS to local file system."
});
_dataGridView.Columns.Add(new DataGridViewButtonColumn {
DataPropertyName = "Edit",
HeaderText = "Edit",
- Width = 50
+ Width = 50,
+ ToolTipText = "Edit statistical data (entries) in the file on the local file system (FS)."
});
_dataGridView.Columns.Add(new DataGridViewButtonColumn {
DataPropertyName = "Upload",
HeaderText = "Upload",
- Width = 60
+ Width = 60,
+ ToolTipText = "Copy a file from local file system (FS) to Loxone MS."
+ });
+ _dataGridView.Columns.Add(new DataGridViewButtonColumn {
+ DataPropertyName = "Convert",
+ HeaderText = "Convert",
+ Width = 60,
+ ToolTipText = "Convert data from old meter function block to new style.\n\nNOTE: UNDER CONSTRUCTION, not working yet!"
+ });
+ _dataGridView.Columns.Add(new DataGridViewButtonColumn {
+ DataPropertyName = "Delete",
+ HeaderText = "Delete",
+ Width = 60,
+ ToolTipText = "Delete a file on both, the Loxone MS and the local file system, after confirmation."
});
// Bind the SortableBindingList to the DataGridView
@@ -401,7 +552,8 @@ private bool Download(FileItem fileItem)
}
catch (Exception ex)
{
- MessageBox.Show($"# Message\n{ex.Message}\n\n# Data\n{ex.Data}\n\n# StackTrace\n{ex.StackTrace}", "Error - IList", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show($"# Message\n{ex.Message}\n\n# Data\n{ex.Data}\n\n# StackTrace\n{ex.StackTrace}",
+ "Error - IList", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
@@ -433,12 +585,58 @@ private bool Upload(FileItem fileItem)
}
catch (Exception ex)
{
- MessageBox.Show($"# Message\n{ex.Message}\n\n# Data\n{ex.Data}\n\n# StackTrace\n{ex.StackTrace}", "Error - IList", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show($"# Message\n{ex.Message}\n\n# Data\n{ex.Data}\n\n# StackTrace\n{ex.StackTrace}",
+ "Error - IList", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
+ private bool Convert(FileItem fileItem)
+ {
+ // ToDo: Code missing
+ System.Threading.Thread.Sleep(50);
+ return true;
+ }
+
+ private bool Delete(FileItem fileItem)
+ {
+ try
+ {
+ // Delete file on Loxone MS
+ FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(GetFileNameUri(fileItem.FileName));
+ ftpWebRequest.Method = WebRequestMethods.Ftp.DeleteFile;
+ FtpWebResponse ftpWebResponse = (FtpWebResponse)ftpWebRequest.GetResponse();
+ //Console.WriteLine("Delete status: {0}", ftpWebResponse.StatusDescription);
+ ftpWebResponse.Close();
+
+ // Delete file on local file system
+ var fileNameWithPath = Path.Combine(_folderTextBox.Text, fileItem.FileName);
+ if (File.Exists(fileNameWithPath))
+ {
+ File.Delete(fileNameWithPath);
+ }
+
+ return true;
+ }
+ catch (WebException ex)
+ {
+ var response = ex.Response as FtpWebResponse;
+ if (response != null)
+ {
+ MessageBox.Show(ex.Message, "Error - FTP connection", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ return false;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"# Message\n{ex.Message}\n\n# Data\n{ex.Data}\n\n# StackTrace\n{ex.StackTrace}",
+ "Error - local file system", MessageBoxButtons.OK, MessageBoxIcon.Error);
+
+ return false;
+ }
+ }
#endregion
#region Events
@@ -489,6 +687,34 @@ private void _filterTextBox_KeyDown(object sender, System.Windows.Forms.KeyEvent
private void MiniserverForm_Load(object sender, EventArgs e)
{
+
+ // if not remote desktop session then enable double-buffering optimization
+ if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
+ {
+ typeof(DataGridView).InvokeMember("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
+ System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.SetProperty, null, _dataGridView, new object[] { true });
+ }
+
+ // Load screen sizes and settings from user config if found, otherwise use defaults
+
+ //Existing user config does not exist, so load settings from previous assembly
+ if (Settings.Default.IsSettingsUpgradeRequired) //this defaults to true when a new version of this software has been released
+ {
+ Settings.Default.Upgrade(); //upgrade the settings to the newer version
+ Settings.Default.Reload();
+ Settings.Default.IsSettingsUpgradeRequired = false;
+ Settings.Default.Save();
+ }
+
+ if (Properties.Settings.Default.IsMaximized)
+ WindowState = FormWindowState.Maximized;
+ else if (Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(Properties.Settings.Default.WindowPosition)))
+ {
+ StartPosition = FormStartPosition.Manual;
+ DesktopBounds = Properties.Settings.Default.WindowPosition;
+ WindowState = FormWindowState.Normal;
+ }
+
_folderTextBox.Text = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments), "LoxStatEdit");
if(_args.Length >= 1)
@@ -502,9 +728,39 @@ private void MiniserverForm_Load(object sender, EventArgs e)
RefreshGridView();
}
+ private void MiniserverForm_Closing(object sender, FormClosingEventArgs e)
+ {
+ this.SaveWindowPosition(sender, e);
+ }
+
+ private void MiniserverForm_ResizEnd(object sender, EventArgs e)
+ {
+ this.SaveWindowPosition(sender, e);
+ }
+
+ private void SaveWindowPosition(object sender, EventArgs e)
+ {
+ Properties.Settings.Default.IsMaximized = WindowState == FormWindowState.Maximized;
+ Properties.Settings.Default.WindowPosition = DesktopBounds;
+ Properties.Settings.Default.Save();
+ }
+
private void DataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
- if (e.ColumnIndex == 1) // The Name column is at index 1
+ if ((e.RowIndex < 0) || (e.RowIndex >= _fileItems.Count))
+ {
+ e.Value = null;
+ return;
+ }
+ if (e.ColumnIndex == 0) // The FileName column is at index 0
+ {
+ var fileItem = _fileItems[e.RowIndex];
+ if (!fileItem.IsValidMsStatsFile)
+ {
+ e.CellStyle.BackColor = System.Drawing.Color.Red;
+ }
+ }
+ if (e.ColumnIndex == 1) // The Description / Name column is at index 1
{
var fileItem = _fileItems[e.RowIndex];
if (fileItem.Name == "Download to view description")
@@ -516,30 +772,31 @@ private void DataGridView_CellFormatting(object sender, DataGridViewCellFormatti
e.CellStyle.Font = new System.Drawing.Font(e.CellStyle.Font, System.Drawing.FontStyle.Regular);
}
}
- if (e.ColumnIndex == 3) // The Status column is at index 3
+ if (e.ColumnIndex == 5) // The Status column is at index 5
{
var fileItem = _fileItems[e.RowIndex];
switch (fileItem.Status)
{
- case "Only on MS":
+ case FileItem.IDStatusOnlyOnMS:
e.CellStyle.BackColor = System.Drawing.Color.LightGray;
break;
- case "Only on FS":
+ case FileItem.IDStatusOnlyOnFS:
e.CellStyle.BackColor = System.Drawing.Color.LightGoldenrodYellow;
break;
- case "Newer on MS":
+ case FileItem.IDStatusNewerOnMS:
e.CellStyle.BackColor = System.Drawing.Color.LightGreen;
break;
- case "Newer on FS":
+ case FileItem.IDStatusNewerOnFS:
e.CellStyle.BackColor = System.Drawing.Color.LightSkyBlue;
break;
- case "Larger on MS":
+ case FileItem.IDStatusLargerOnMS:
e.CellStyle.BackColor = System.Drawing.Color.LightGreen;
break;
- case "Larger on FS":
+ case FileItem.IDStatusLargerOnFS:
e.CellStyle.BackColor = System.Drawing.Color.LightSkyBlue;
break;
default:
+ // IDStatusSame:
e.CellStyle.BackColor = System.Drawing.Color.White;
break;
}
@@ -551,16 +808,25 @@ private void DataGridView_CellValueNeeded(object sender, DataGridViewCellValueEv
{
try
{
+ if ((e.RowIndex < 0) || (e.RowIndex >= _fileItems.Count))
+ {
+ e.Value = null;
+ return;
+ }
var fileItem = _fileItems[e.RowIndex];
switch(e.ColumnIndex)
{
case 0: e.Value = fileItem.FileName; break;
case 1: e.Value = fileItem.Name; break;
case 2: e.Value = fileItem.YearMonth; break;
- case 3: e.Value = fileItem.Status; break;
- case 4: e.Value = "Download"; break;
- case 5: e.Value = "Edit"; break;
- case 6: e.Value = "Upload"; break;
+ case 3: e.Value = fileItem.DateModified; break;
+ case 4: e.Value = fileItem.Size; break;
+ case 5: e.Value = fileItem.StatusString; break;
+ case 6: e.Value = "Download"; break;
+ case 7: e.Value = "Edit"; break;
+ case 8: e.Value = "Upload"; break;
+ case 9: e.Value = "Convert"; break;
+ case 10: e.Value = "Delete"; break;
default: e.Value = null; break;
}
}
@@ -573,13 +839,56 @@ private void DataGridView_CellValueNeeded(object sender, DataGridViewCellValueEv
}
}
+ private void DataGridView_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
+ {
+ try
+ {
+ if ((e.RowIndex < 0) || (e.RowIndex >= _fileItems.Count))
+ {
+ //e.ToolTipText = null;
+ return;
+ }
+
+ var fileItem = _fileItems[e.RowIndex];
+ switch (e.ColumnIndex)
+ {
+ case 0: // fileItem.FileName;
+ if (!fileItem.IsValidMsStatsFile)
+ {
+ e.ToolTipText = "The UUID and/or file extension looks to be malformed.\n\n"+
+ "Please check, if it is used by the MS. If not, you may consider to remove the file.";
+ }
+ break;
+ case 1: // fileItem.Name;
+ break;
+ case 2: // fileItem.YearMonth;
+ break;
+ case 3: // fileItem.DateModified;
+ break;
+ case 4: // fileItem.Size;
+ break;
+ case 5: // fileItem.StatusString;
+ break;
+ default:
+ break;
+ }
+ }
+ catch
+ {
+#if DEBUG
+ Debugger.Break();
+#endif
+ e.ToolTipText = "";
+ }
+ }
+
private void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
- if(e.RowIndex < 0) return; //When clicking the header row
+ if (e.RowIndex < 0) return; //When clicking the header row
var fileItem = _fileItems[e.RowIndex];
- switch(e.ColumnIndex)
+ switch (e.ColumnIndex)
{
- case 4: //Download
+ case 6: //Download
progressBar.Maximum = 1;
progressBar.Value = 0;
progressBar.SetState(1);
@@ -598,11 +907,12 @@ private void DataGridView_CellContentClick(object sender, DataGridViewCellEventA
progressLabel.Text = "Download failed!";
}
break;
- case 5: //Edit
+ case 7: //Edit
// show error message, if file is not downloaded yet
if (fileItem.FileInfo == null)
{
- MessageBox.Show($"The file \"{fileItem.FileName}\" cannot be edited, since it's not available on the filesystem.\n\nPlease download it first.", "Error - File not downloaded", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show($"The file \"{fileItem.FileName}\" cannot be edited, since it's not available on the filesystem.\n\n"+
+ "Please download it first.", "Error - File not downloaded", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
@@ -621,11 +931,12 @@ private void DataGridView_CellContentClick(object sender, DataGridViewCellEventA
RefreshLocal();
RefreshGridView();
break;
- case 6: //Upload
+ case 8: //Upload
// show error message, if there is no file to upload
if (fileItem.FileInfo == null)
{
- MessageBox.Show($"The file \"{fileItem.FileName}\" cannot be uploaded, since it's not available on the filesystem.\n\nPlease download it first.", "Error - File not downloaded", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show($"The file \"{fileItem.FileName}\" cannot be uploaded, since it's not available on the filesystem.\n\n"+
+ "Please download it first.", "Error - File not downloaded", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
@@ -633,7 +944,7 @@ private void DataGridView_CellContentClick(object sender, DataGridViewCellEventA
progressBar.Value = 0;
progressBar.SetState(1);
progressLabel.Text = "Starting upload...";
- if(Upload(fileItem))
+ if (Upload(fileItem))
{
progressBar.Value = 1;
progressLabel.Text = "Upload complete!";
@@ -647,6 +958,63 @@ private void DataGridView_CellContentClick(object sender, DataGridViewCellEventA
progressLabel.Text = "Upload failed!";
}
break;
+ case 9: //Convert
+ // Ask user
+ if (fileItem.FileInfo != null)
+ {
+ // ToDo: ask for UUID of new meter
+ DialogResult result = MessageBox.Show($"Do you want to convert the file \"{fileItem.FileName}\" from the old meter format to the new one?\n"+
+ "NOTE: Under constructtion! Currently without any function.", "Question - Convert Stats File", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ if (result == DialogResult.Yes)
+ {
+ progressBar.Maximum = 1;
+ progressBar.Value = 0;
+ progressBar.SetState(1);
+ progressLabel.Text = "Starting converting...";
+ if (Convert(fileItem))
+ {
+ progressBar.Value = 1;
+ progressLabel.Text = "Converting complete!";
+ RefreshMs();
+ RefreshGridView();
+ }
+ else
+ {
+ progressBar.Value = 1;
+ progressBar.SetState(2);
+ progressLabel.Text = "Converting failed!";
+ }
+ }
+ }
+ break;
+ case 10: //Delete
+ // show error message, if there is no file to upload
+ if ((fileItem.FileInfo != null) || (fileItem.MsFileInfo != null))
+ {
+ DialogResult result = MessageBox.Show($"Do you want to delete the file \"{fileItem.FileName}\" from the Loxone MS and local file system?", "Question - Delete Stats File from", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ if (result == DialogResult.Yes)
+ {
+ progressBar.Maximum = 1;
+ progressBar.Value = 0;
+ progressBar.SetState(1);
+ progressLabel.Text = "Starting delete...";
+ if (Delete(fileItem))
+ {
+ progressBar.Value = 1;
+ progressLabel.Text = "Deleting complete!";
+ RefreshMs();
+ RefreshLocal();
+ RefreshGridView();
+ }
+ else
+ {
+ progressBar.Value = 1;
+ progressBar.SetState(2);
+ progressLabel.Text = "Deleting failed!";
+ }
+ }
+ }
+ break;
}
}
@@ -727,5 +1095,9 @@ private void donateLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArg
#endregion
+ private void aboutLabel_Click(object sender, EventArgs e)
+ {
+
+ }
}
}
diff --git a/MiniserverForm.resx b/MiniserverForm.resx
index 2138d86..68e0c41 100644
--- a/MiniserverForm.resx
+++ b/MiniserverForm.resx
@@ -162,6 +162,9 @@
True
+
+ True
+
True
@@ -174,6 +177,12 @@
True
+
+ True
+
+
+ True
+
108, 17
diff --git a/MsFileInfo.cs b/MsFileInfo.cs
index eec8bc5..5ec9a8e 100644
--- a/MsFileInfo.cs
+++ b/MsFileInfo.cs
@@ -3,9 +3,11 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.ListView;
namespace LoxStatEdit
{
@@ -14,6 +16,7 @@ public class MsFileInfo
public string FileName { get; private set; }
public DateTime Date { get; private set; }
public int Size { get; private set; }
+ public bool Valid { get; private set; }
public static IList Load(Uri uri)
{
@@ -37,7 +40,15 @@ public static IList Load(Uri uri)
// File.AppendAllText("./custom.log", $"{line}\n");
// string pattern that matches Miniserver Gen 1 and Miniserver Gen 2
- string pattern = @"[-rwx]{10}\s+[0-9]+\s+[0-9]+\s+[0-9]+\s+([0-9]+)\s+([A-Za-z]{3}\s+[0-9]{1,2}\s+[0-9:]+)\s+([0-9a-z_\-\.]+)";
+ string pattern = @"[-rwx]{10}\s+[0-9]+\s+[0-9]+\s+[0-9]+\s+([0-9]+)\s+([A-Za-z]{3}\s+[0-9]{1,2}\s+[0-9:]+)\s+([0-9A-Za-z_\-\.]+)";
+ // Regex to parse entries from FTP LIST command - Loxone miniserver Gen.1 is using the following format for files in /stats directory
+ // examples:
+ // -rw-rw-rw- 1 0 0 691248 Nov 08 21:01 0c542aec-0252-e271-ffff9d266de2d576.201809
+ // -rw-rw-rw- 1 0 0 66896 Feb 29 23:00 1482ee72-032f-a20a-ffffa5f1a53e2e44.202402
+ // -rw-rw-rw- 1 0 0 1168 May 01 00:00 1ccec2f9-011e-ac27-ffffefc088fafadd_1.202404
+ // 1st group (): file size
+ // 2nd group (): date and time in one of the following formats: MMM dd HH:mm, MMM d HH:mm, MMM dd yyyy, MMM d yyyy
+ // 3th group (): filename
var result = Regex.Match(line, pattern);
if (result.Success)
@@ -45,20 +56,41 @@ public static IList Load(Uri uri)
var groups = result.Groups;
int.TryParse(groups[1].Value, out int size);
+ var isFeb29 = false;
DateTime dateTime;
string dateString = Regex.Replace(groups[2].Value, @"\s+", " ");
string[] formats = { "MMM dd HH:mm", "MMM dd yyyy", "MMM d HH:mm", "MMM d yyyy" };
- if (!DateTime.TryParseExact(dateString, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
+ // special handling for Feb 29 to avoid invalid parsing without a year: add a day that will be subtracted later
+ if (dateString.StartsWith("Feb 29"))
{
- // Handle the case where none of the formats match
- MessageBox.Show($"The date \"{dateString}\" could not be matched with one of the following formats:\n{string.Join("\n", formats)}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ dateString = $"Mar 01 {groups[2].Value.Substring(7)}";
+ isFeb29 = true;
+ }
+ if (!DateTime.TryParseExact(dateString, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
+ {
+ // Handle the case where none of the formats matches
+ MessageBox.Show($"The date \"{dateString}\" could not be matched with one of the following formats:\n{string.Join("\n", formats)}",
+ "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
+ // time is in UTC, but we need local time
+ dateTime += TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
+
+ if(isFeb29)
+ {
+ // Removing the day that was added before
+ dateTime = dateTime.AddDays(-1);
+ }
+ if (dateTime >= DateTime.Now)
+ {
+ //filedate newer than now is not possible ... date must be from the last year
+ dateTime = dateTime.AddYears(-1);
+ }
var fileName = groups[3].Value;
-
+
list.Add(new MsFileInfo
{
FileName = fileName,
diff --git a/Program.cs b/Program.cs
index d03d426..7632cf7 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,4 +1,5 @@
-using System;
+using LoxStatEdit.Properties;
+using System;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 1d42413..8f6c41b 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.5.1")]
-[assembly: AssemblyFileVersion("1.0.5.1")]
+[assembly: AssemblyVersion("1.0.6.2")]
+[assembly: AssemblyFileVersion("1.0.6.2")]
diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..71e4193
--- /dev/null
+++ b/Properties/Settings.Designer.cs
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.42000
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace LoxStatEdit.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("0, 0, -1, -1")]
+ public global::System.Drawing.Rectangle WindowPosition {
+ get {
+ return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+ }
+ set {
+ this["WindowPosition"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool IsMaximized {
+ get {
+ return ((bool)(this["IsMaximized"]));
+ }
+ set {
+ this["IsMaximized"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool IsSettingsUpgradeRequired {
+ get {
+ return ((bool)(this["IsSettingsUpgradeRequired"]));
+ }
+ set {
+ this["IsSettingsUpgradeRequired"] = value;
+ }
+ }
+ }
+}
diff --git a/Properties/Settings.settings b/Properties/Settings.settings
new file mode 100644
index 0000000..b1213d7
--- /dev/null
+++ b/Properties/Settings.settings
@@ -0,0 +1,15 @@
+
+
+
+
+
+ 0, 0, -1, -1
+
+
+ False
+
+
+ True
+
+
+
\ No newline at end of file