From cc87812697ccebfc9921eb70d8ed3019d91cce90 Mon Sep 17 00:00:00 2001 From: Jan Wachsmuth Date: Sun, 26 Jan 2025 22:49:11 +1000 Subject: [PATCH] Enhancements and Fixes (#6) * Enhancements and Fixes - Added column for file size and file date - Fixed handling with timestamps in FTP transfers (UTC), adjustment of year - Added marker, if file is not using UUID plus .yyyyMM as filename - Added button to delete file on MS and local file system - Added button to konvert a file (not ready yet) - Fixed calcuation for modification date when file list is retrieved from MS via FTP - handle Feb 29 correctly - translate from UTC to local time - Added tooltip for potentially malformed statistics filename - Stability improvements - At start the window size in main window is restored to previous settings - Enhancements in tool tip messages to explain columns --- .gitignore | 3 +- App.config | 18 ++ LoxStatEdit.csproj | 11 +- LoxStatFileForm.cs | 6 + MiniserverForm.Designer.cs | 111 ++++++-- MiniserverForm.cs | 464 ++++++++++++++++++++++++++++---- MiniserverForm.resx | 9 + MsFileInfo.cs | 42 ++- Program.cs | 3 +- Properties/AssemblyInfo.cs | 4 +- Properties/Settings.Designer.cs | 62 +++++ Properties/Settings.settings | 15 ++ 12 files changed, 677 insertions(+), 71 deletions(-) create mode 100644 Properties/Settings.Designer.cs create mode 100644 Properties/Settings.settings 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