diff --git a/CHANGELOG.md b/CHANGELOG.md index 52af0484..8a12522c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] ### Added +- #1476: Configurable backups. Can now edit/set backup frequency, backup path, and max number of backup files. - #1427: Fix RDP local desktop scale not taking effect on remote - #1770: Added missing RDP performance settings - #1332: Added option to hide menu strip container diff --git a/mRemoteNG/App/Runtime.cs b/mRemoteNG/App/Runtime.cs index 23d0e3aa..bf34daf5 100644 --- a/mRemoteNG/App/Runtime.cs +++ b/mRemoteNG/App/Runtime.cs @@ -102,6 +102,10 @@ namespace mRemoteNG.App if (Settings.Default.UseSQLServer) { ConnectionsService.LastSqlUpdate = DateTime.Now; + } + else + { + ConnectionsService.LastFileUpdate = System.IO.File.GetLastWriteTime(connectionFileName); } // re-enable sql update checking after updates are loaded diff --git a/mRemoteNG/App/Shutdown.cs b/mRemoteNG/App/Shutdown.cs index dd06609e..0c99155c 100644 --- a/mRemoteNG/App/Shutdown.cs +++ b/mRemoteNG/App/Shutdown.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; using System.Windows.Forms; +using mRemoteNG.Config.Connections; using mRemoteNG.Config.Putty; using mRemoteNG.Properties; using mRemoteNG.Resources.Language; @@ -60,8 +61,34 @@ namespace mRemoteNG.App private static void SaveConnections() { - if (Settings.Default.SaveConsOnExit) + DateTime lastUpdate; + DateTime updateDate; + DateTime currentDate = DateTime.Now; + + //OBSOLETE: Settings.Default.SaveConsOnExit is obsolete and should be removed in a future release + if (Settings.Default.SaveConsOnExit || (Settings.Default.SaveConnectionsFrequency == (int)ConnectionsBackupFrequencyEnum.OnExit)) + { Runtime.ConnectionsService.SaveConnections(); + return; + } + lastUpdate = Runtime.ConnectionsService.UsingDatabase ? Runtime.ConnectionsService.LastSqlUpdate : Runtime.ConnectionsService.LastFileUpdate; + + switch (Settings.Default.SaveConnectionsFrequency) + { + case (int)ConnectionsBackupFrequencyEnum.Daily: + updateDate = lastUpdate.AddDays(1); + break; + case (int)ConnectionsBackupFrequencyEnum.Weekly: + updateDate = lastUpdate.AddDays(7); + break; + default: + return; + } + + if (currentDate >= updateDate) + { + Runtime.ConnectionsService.SaveConnections(); + } } private static void SaveSettings(Control quickConnectToolStrip, diff --git a/mRemoteNG/Config/Connections/ConnectionsBackupFrequencyEnum.cs b/mRemoteNG/Config/Connections/ConnectionsBackupFrequencyEnum.cs new file mode 100644 index 00000000..03967d3e --- /dev/null +++ b/mRemoteNG/Config/Connections/ConnectionsBackupFrequencyEnum.cs @@ -0,0 +1,13 @@ +namespace mRemoteNG.Config.Connections +{ + public enum ConnectionsBackupFrequencyEnum + { + Unassigned = 0, + Never = 1, + OnEdit = 2, + OnExit = 3, + Daily = 4, + Weekly = 5, + Custom = 6 + } +} \ No newline at end of file diff --git a/mRemoteNG/Config/Connections/SaveConnectionsOnEdit.cs b/mRemoteNG/Config/Connections/SaveConnectionsOnEdit.cs index e8a31d5e..168d42c9 100644 --- a/mRemoteNG/Config/Connections/SaveConnectionsOnEdit.cs +++ b/mRemoteNG/Config/Connections/SaveConnectionsOnEdit.cs @@ -3,6 +3,7 @@ using System.Collections.Specialized; using System.ComponentModel; using mRemoteNG.Connection; using mRemoteNG.UI.Forms; +using mRemoteNG.Properties; namespace mRemoteNG.Config.Connections { @@ -48,12 +49,14 @@ namespace mRemoteNG.Config.Connections private void SaveConnectionOnEdit(string propertyName = "") { - if (!Properties.Settings.Default.SaveConnectionsAfterEveryEdit) - return; - if (FrmMain.Default.IsClosing) - return; + //OBSOLETE: mRemoteNG.Settings.Default.SaveConnectionsAfterEveryEdit is obsolete and should be removed in a future release + if (mRemoteNG.Properties.Settings.Default.SaveConnectionsAfterEveryEdit || (mRemoteNG.Properties.Settings.Default.SaveConnectionsFrequency == (int)ConnectionsBackupFrequencyEnum.OnEdit)) + { + if (FrmMain.Default.IsClosing) + return; - _connectionsService.SaveConnectionsAsync(propertyName); + _connectionsService.SaveConnectionsAsync(propertyName); + } } } } \ No newline at end of file diff --git a/mRemoteNG/Connection/ConnectionsService.cs b/mRemoteNG/Connection/ConnectionsService.cs index ced89190..bb26bd68 100644 --- a/mRemoteNG/Connection/ConnectionsService.cs +++ b/mRemoteNG/Connection/ConnectionsService.cs @@ -37,6 +37,7 @@ namespace mRemoteNG.Connection public string ConnectionFileName { get; private set; } public RemoteConnectionsSyncronizer RemoteConnectionsSyncronizer { get; set; } public DateTime LastSqlUpdate { get; set; } + public DateTime LastFileUpdate { get; set; } public ConnectionTreeModel ConnectionTreeModel { get; private set; } diff --git a/mRemoteNG/Properties/Resources.Designer.cs b/mRemoteNG/Properties/Resources.Designer.cs index a047b0d3..ce1c38bf 100644 --- a/mRemoteNG/Properties/Resources.Designer.cs +++ b/mRemoteNG/Properties/Resources.Designer.cs @@ -8,7 +8,10 @@ // //------------------------------------------------------------------------------ -namespace mRemoteNG.Properties { +namespace mRemoteNG { + using System; + + using System; diff --git a/mRemoteNG/Properties/Resources.resx b/mRemoteNG/Properties/Resources.resx index 14830220..406baadf 100644 --- a/mRemoteNG/Properties/Resources.resx +++ b/mRemoteNG/Properties/Resources.resx @@ -331,4 +331,7 @@ ..\Resources\StartupProject_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\test.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/mRemoteNG/Properties/Settings.Designer.cs b/mRemoteNG/Properties/Settings.Designer.cs index 15db67a9..f1b63a70 100644 --- a/mRemoteNG/Properties/Settings.Designer.cs +++ b/mRemoteNG/Properties/Settings.Designer.cs @@ -2915,6 +2915,18 @@ namespace mRemoteNG.Properties { } } + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int SaveConnectionsFrequency { + get { + return ((int)(this["SaveConnectionsFrequency"])); + } + set { + this["SaveConnectionsFrequency"] = value; + } + } + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("Highest")] diff --git a/mRemoteNG/Properties/Settings.settings b/mRemoteNG/Properties/Settings.settings index 6fb5fd1e..e0552004 100644 --- a/mRemoteNG/Properties/Settings.settings +++ b/mRemoteNG/Properties/Settings.settings @@ -725,6 +725,9 @@ False + + 0 + Highest diff --git a/mRemoteNG/Resources/Backup_Icon.ico b/mRemoteNG/Resources/Backup_Icon.ico new file mode 100644 index 00000000..8aa98e51 Binary files /dev/null and b/mRemoteNG/Resources/Backup_Icon.ico differ diff --git a/mRemoteNG/Resources/Icons/Backup_Icon.ico b/mRemoteNG/Resources/Icons/Backup_Icon.ico new file mode 100644 index 00000000..86340997 Binary files /dev/null and b/mRemoteNG/Resources/Icons/Backup_Icon.ico differ diff --git a/mRemoteNG/Resources/Language/Language.Designer.cs b/mRemoteNG/Resources/Language/Language.Designer.cs index e96f1fe6..40091eb1 100644 --- a/mRemoteNG/Resources/Language/Language.Designer.cs +++ b/mRemoteNG/Resources/Language/Language.Designer.cs @@ -8,7 +8,11 @@ // //------------------------------------------------------------------------------ -namespace mRemoteNG.Resources.Language { +namespace mRemoteNG.Resources.Language +{ + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -85,7 +89,7 @@ namespace mRemoteNG.Resources.Language { } /// - /// Looks up a localized string similar to &Warn me when closing connections. + /// Looks up a localized string similar to Warn me when closing connections. /// internal static string _CloseWarnAll { get { @@ -1287,6 +1291,51 @@ namespace mRemoteNG.Resources.Language { } } + /// + /// Looks up a localized string similar to Daily. + /// + internal static string ConnectionsBackupFrequencyDaily { + get { + return ResourceManager.GetString("ConnectionsBackupFrequencyDaily", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Never backup connections. + /// + internal static string ConnectionsBackupFrequencyNever { + get { + return ResourceManager.GetString("ConnectionsBackupFrequencyNever", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On Edit. + /// + internal static string ConnectionsBackupFrequencyOnEdit { + get { + return ResourceManager.GetString("ConnectionsBackupFrequencyOnEdit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On Exit. + /// + internal static string ConnectionsBackupFrequencyOnExit { + get { + return ResourceManager.GetString("ConnectionsBackupFrequencyOnExit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Weekly. + /// + internal static string ConnectionsBackupFrequencyWeekly { + get { + return ResourceManager.GetString("ConnectionsBackupFrequencyWeekly", resourceCulture); + } + } + /// /// Looks up a localized string similar to Couldn't set default port!. /// @@ -4219,7 +4268,7 @@ namespace mRemoteNG.Resources.Language { } /// - /// Looks up a localized string similar to Start Program. + /// Looks up a localized string similar to Start Program/alternate shell. /// internal static string PropertyDescriptionStartProgram { get { @@ -5364,15 +5413,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Save connections on exit. - /// - internal static string SaveConsOnExit { - get { - return ResourceManager.GetString("SaveConsOnExit", resourceCulture); - } - } - /// /// Looks up a localized string similar to Graphics Interchange Format File (.gif)|*.gif|Joint Photographic Experts Group File (.jpeg)|*.jpeg|Joint Photographic Experts Group File (.jpg)|*.jpg|Portable Network Graphics File (.png)|*.png. /// @@ -5625,15 +5665,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Start Program. - /// - internal static string StartProgram { - get { - return ResourceManager.GetString("StartProgram", resourceCulture); - } - } - /// /// Looks up a localized string similar to Socks 5. /// @@ -5849,18 +5880,16 @@ namespace mRemoteNG.Resources.Language { return ResourceManager.GetString("StartMinimized", resourceCulture); } } - + /// - /// Looks up a localized string similar to Start minimized. + /// Looks up a localized string similar to Start Program. /// - internal static string StartFullScreen - { - get - { - return ResourceManager.GetString("StartFullScreen", resourceCulture); + internal static string StartProgram { + get { + return ResourceManager.GetString("StartProgram", resourceCulture); } } - + /// /// Looks up a localized string similar to Startup/Exit. /// @@ -5879,6 +5908,51 @@ namespace mRemoteNG.Resources.Language { } } + /// + /// Looks up a localized string similar to Backup. + /// + internal static string strBackup { + get { + return ResourceManager.GetString("strBackup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Browse.... + /// + internal static string strBrowse { + get { + return ResourceManager.GetString("strBrowse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection Backup Frequency. + /// + internal static string strConnectionBackupFrequency { + get { + return ResourceManager.GetString("strConnectionBackupFrequency", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum number of backups. + /// + internal static string strConnectionsBackupMaxCount { + get { + return ResourceManager.GetString("strConnectionsBackupMaxCount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Location of connection file backup. + /// + internal static string strConnectionsBackupPath { + get { + return ResourceManager.GetString("strConnectionsBackupPath", resourceCulture); + } + } + /// /// Looks up a localized string similar to Support Forum. /// diff --git a/mRemoteNG/Resources/Language/Language.resx b/mRemoteNG/Resources/Language/Language.resx index 62289db3..429b03c5 100644 --- a/mRemoteNG/Resources/Language/Language.resx +++ b/mRemoteNG/Resources/Language/Language.resx @@ -1313,7 +1313,7 @@ If you run into such an error, please create a new connection file! Creating quick connect failed - &Warn me when closing connections + Warn me when closing connections Warn me only when e&xiting mRemoteNG @@ -1483,8 +1483,35 @@ If you run into such an error, please create a new connection file! Do you want to save the current connections file before loading another? - - Save connections on exit + + Daily + + + Connection Backup Frequency + + + Weekly + + + Maximum number of backups + + + Location of connection file backup + + + On Edit + + + On Exit + + + Never backup connections + + + Browse... + + + Backup Graphics Interchange Format File (.gif)|*.gif|Joint Photographic Experts Group File (.jpeg)|*.jpeg|Joint Photographic Experts Group File (.jpg)|*.jpg|Portable Network Graphics File (.png)|*.png diff --git a/mRemoteNG/Resources/test.ico b/mRemoteNG/Resources/test.ico new file mode 100644 index 00000000..5d06b9f2 Binary files /dev/null and b/mRemoteNG/Resources/test.ico differ diff --git a/mRemoteNG/UI/Forms/OptionsPages/BackupPage.Designer.cs b/mRemoteNG/UI/Forms/OptionsPages/BackupPage.Designer.cs new file mode 100644 index 00000000..2e28e94d --- /dev/null +++ b/mRemoteNG/UI/Forms/OptionsPages/BackupPage.Designer.cs @@ -0,0 +1,164 @@ + + +namespace mRemoteNG.UI.Forms.OptionsPages +{ + + public sealed partial class BackupPage : OptionsPage + { + + //UserControl overrides dispose to clean up the component list. + [System.Diagnostics.DebuggerNonUserCode()]protected override void Dispose(bool disposing) + { + try + { + if (disposing && components != null) + { + components.Dispose(); + } + } + finally + { + base.Dispose(disposing); + } + } + + //Required by the Windows Form Designer + private System.ComponentModel.Container components = null; + + //NOTE: The following procedure is required by the Windows Form Designer + //It can be modified using the Windows Form Designer. + //Do not modify it using the code editor. + [System.Diagnostics.DebuggerStepThrough()]private void InitializeComponent() + { + this.tableLayoutPanelBackupFile = new System.Windows.Forms.TableLayoutPanel(); + this.textBoxConnectionBackupPath = new System.Windows.Forms.TextBox(); + this.lblConnectionsBackupPath = new System.Windows.Forms.Label(); + this.lblConnectionsBackupFrequency = new System.Windows.Forms.Label(); + this.lblConnectionsBackupMaxCount = new System.Windows.Forms.Label(); + this.cmbConnectionBackupFrequency = new System.Windows.Forms.ComboBox(); + this.buttonBrowsePath = new System.Windows.Forms.Button(); + this.numMaxBackups = new System.Windows.Forms.NumericUpDown(); + this.tableLayoutPanelBackupFile.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numMaxBackups)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanelBackupFile + // + this.tableLayoutPanelBackupFile.ColumnCount = 4; + this.tableLayoutPanelBackupFile.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanelBackupFile.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanelBackupFile.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanelBackupFile.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanelBackupFile.Controls.Add(this.textBoxConnectionBackupPath, 1, 2); + this.tableLayoutPanelBackupFile.Controls.Add(this.lblConnectionsBackupPath, 0, 2); + this.tableLayoutPanelBackupFile.Controls.Add(this.lblConnectionsBackupFrequency, 0, 0); + this.tableLayoutPanelBackupFile.Controls.Add(this.lblConnectionsBackupMaxCount, 0, 1); + this.tableLayoutPanelBackupFile.Controls.Add(this.cmbConnectionBackupFrequency, 1, 0); + this.tableLayoutPanelBackupFile.Controls.Add(this.buttonBrowsePath, 2, 2); + this.tableLayoutPanelBackupFile.Controls.Add(this.numMaxBackups, 1, 1); + this.tableLayoutPanelBackupFile.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanelBackupFile.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanelBackupFile.Name = "tableLayoutPanelBackupFile"; + this.tableLayoutPanelBackupFile.RowCount = 4; + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanelBackupFile.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanelBackupFile.Size = new System.Drawing.Size(630, 412); + this.tableLayoutPanelBackupFile.TabIndex = 15; + // + // textBoxConnectionBackupPath + // + this.textBoxConnectionBackupPath.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxConnectionBackupPath.Location = new System.Drawing.Point(195, 58); + this.textBoxConnectionBackupPath.Name = "textBoxConnectionBackupPath"; + this.textBoxConnectionBackupPath.Size = new System.Drawing.Size(250, 22); + this.textBoxConnectionBackupPath.TabIndex = 14; + // + // lblConnectionsBackupPath + // + this.lblConnectionsBackupPath.AutoSize = true; + this.lblConnectionsBackupPath.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblConnectionsBackupPath.Location = new System.Drawing.Point(3, 55); + this.lblConnectionsBackupPath.Name = "lblConnectionsBackupPath"; + this.lblConnectionsBackupPath.Size = new System.Drawing.Size(186, 29); + this.lblConnectionsBackupPath.TabIndex = 13; + this.lblConnectionsBackupPath.Text = "Location of connection file backup"; + this.lblConnectionsBackupPath.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // lblConnectionsBackupFrequency + // + this.lblConnectionsBackupFrequency.AutoSize = true; + this.lblConnectionsBackupFrequency.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblConnectionsBackupFrequency.Location = new System.Drawing.Point(3, 0); + this.lblConnectionsBackupFrequency.Name = "lblConnectionsBackupFrequency"; + this.lblConnectionsBackupFrequency.Size = new System.Drawing.Size(186, 27); + this.lblConnectionsBackupFrequency.TabIndex = 14; + this.lblConnectionsBackupFrequency.Text = "Connection Backup Frequency"; + this.lblConnectionsBackupFrequency.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // lblConnectionsBackupMaxCount + // + this.lblConnectionsBackupMaxCount.AutoSize = true; + this.lblConnectionsBackupMaxCount.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblConnectionsBackupMaxCount.Location = new System.Drawing.Point(3, 27); + this.lblConnectionsBackupMaxCount.Name = "lblConnectionsBackupMaxCount"; + this.lblConnectionsBackupMaxCount.Size = new System.Drawing.Size(186, 28); + this.lblConnectionsBackupMaxCount.TabIndex = 13; + this.lblConnectionsBackupMaxCount.Text = "Maximum number of backups"; + this.lblConnectionsBackupMaxCount.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // cmbConnectionBackupFrequency + // + this.cmbConnectionBackupFrequency.Dock = System.Windows.Forms.DockStyle.Fill; + this.cmbConnectionBackupFrequency.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbConnectionBackupFrequency.FormattingEnabled = true; + this.cmbConnectionBackupFrequency.Location = new System.Drawing.Point(195, 3); + this.cmbConnectionBackupFrequency.Name = "cmbConnectionBackupFrequency"; + this.cmbConnectionBackupFrequency.Size = new System.Drawing.Size(250, 21); + this.cmbConnectionBackupFrequency.TabIndex = 13; + // + // buttonBrowsePath + // + this.buttonBrowsePath.Location = new System.Drawing.Point(451, 58); + this.buttonBrowsePath.Name = "buttonBrowsePath"; + this.buttonBrowsePath.Size = new System.Drawing.Size(75, 23); + this.buttonBrowsePath.TabIndex = 15; + this.buttonBrowsePath.Text = "Browse"; + this.buttonBrowsePath.UseVisualStyleBackColor = true; + this.buttonBrowsePath.Click += new System.EventHandler(this.ButtonBrowsePath_Click); + // + // numMaxBackups + // + this.numMaxBackups.Location = new System.Drawing.Point(195, 30); + this.numMaxBackups.Name = "numMaxBackups"; + this.numMaxBackups.Size = new System.Drawing.Size(60, 22); + this.numMaxBackups.TabIndex = 16; + // + // BackupPage + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.Controls.Add(this.tableLayoutPanelBackupFile); + this.Name = "BackupPage"; + this.Size = new System.Drawing.Size(630, 412); + this.tableLayoutPanelBackupFile.ResumeLayout(false); + this.tableLayoutPanelBackupFile.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numMaxBackups)).EndInit(); + this.ResumeLayout(false); + + } + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanelBackupFile; + private System.Windows.Forms.TextBox textBoxConnectionBackupPath; + private System.Windows.Forms.Label lblConnectionsBackupPath; + private System.Windows.Forms.Label lblConnectionsBackupFrequency; + private System.Windows.Forms.Label lblConnectionsBackupMaxCount; + private System.Windows.Forms.ComboBox cmbConnectionBackupFrequency; + private System.Windows.Forms.Button buttonBrowsePath; + private System.Windows.Forms.NumericUpDown numMaxBackups; + } +} \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/BackupPage.cs b/mRemoteNG/UI/Forms/OptionsPages/BackupPage.cs new file mode 100644 index 00000000..6e85520c --- /dev/null +++ b/mRemoteNG/UI/Forms/OptionsPages/BackupPage.cs @@ -0,0 +1,149 @@ +using mRemoteNG.Config; +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using mRemoteNG.App; +using mRemoteNG.Config.Connections; +using mRemoteNG.Security; +using mRemoteNG.Properties; +using mRemoteNG.Resources.Language; + +namespace mRemoteNG.UI.Forms.OptionsPages +{ + public sealed partial class BackupPage + { + private readonly FrmMain _frmMain = FrmMain.Default; + private List _connectionBackup; + + public BackupPage() + { + InitializeComponent(); + ApplyTheme(); + PageIcon = Properties.Resources.Backup_Icon; + } + + public override string PageName + { + get => Language.strBackup; + set { } + } + + public override void ApplyLanguage() + { + base.ApplyLanguage(); + + buttonBrowsePath.Text = Language.strBrowse; + + _connectionBackup = new List + { + { + new DropdownList((int) ConnectionsBackupFrequencyEnum.Never, + Language.ConnectionsBackupFrequencyNever) + }, + { + new DropdownList((int) ConnectionsBackupFrequencyEnum.OnEdit, + Language.ConnectionsBackupFrequencyOnEdit) + }, + { + new DropdownList((int) ConnectionsBackupFrequencyEnum.OnExit, + Language.ConnectionsBackupFrequencyOnExit) + }, + { + new DropdownList((int) ConnectionsBackupFrequencyEnum.Daily, + Language.ConnectionsBackupFrequencyDaily) + }, + { + new DropdownList((int) ConnectionsBackupFrequencyEnum.Weekly, + Language.ConnectionsBackupFrequencyWeekly) + }, + //{ new DropdownList( (int)ConnectionsBackupFrequencyEnum.Custom, Language.ConnectionsBackupFrequencyCustom)} + }; + + cmbConnectionBackupFrequency.DataSource = _connectionBackup; + cmbConnectionBackupFrequency.DisplayMember = "DisplayString"; + cmbConnectionBackupFrequency.ValueMember = "Index"; + + lblConnectionsBackupFrequency.Text = Language.strConnectionBackupFrequency; + lblConnectionsBackupMaxCount.Text = Language.strConnectionsBackupMaxCount; + lblConnectionsBackupPath.Text = Language.strConnectionsBackupPath; + } + + public override void LoadSettings() + { + numMaxBackups.Value = Convert.ToDecimal(Settings.Default.BackupFileKeepCount); + + if (Settings.Default.SaveConnectionsFrequency == (int) ConnectionsBackupFrequencyEnum.Unassigned) + { + if (Settings.Default.SaveConnectionsAfterEveryEdit) + { + Settings.Default.SaveConnectionsFrequency = (int) ConnectionsBackupFrequencyEnum.OnEdit; + } + else if (Settings.Default.SaveConsOnExit) + { + Settings.Default.SaveConnectionsFrequency = (int) ConnectionsBackupFrequencyEnum.OnExit; + } + else + { + Settings.Default.SaveConnectionsFrequency = (int) ConnectionsBackupFrequencyEnum.Never; + } + } + + cmbConnectionBackupFrequency.SelectedValue = Settings.Default.SaveConnectionsFrequency; + textBoxConnectionBackupPath.Text = Settings.Default.CustomConsPath; + + } + + public override void SaveSettings() + { + Settings.Default.BackupFileKeepCount = (int) numMaxBackups.Value; + + if (Settings.Default.AutoSaveEveryMinutes > 0) + { + _frmMain.tmrAutoSave.Interval = Settings.Default.AutoSaveEveryMinutes * 60000; + _frmMain.tmrAutoSave.Enabled = true; + } + else + { + _frmMain.tmrAutoSave.Enabled = false; + } + + Settings.Default.SaveConnectionsFrequency = (int) cmbConnectionBackupFrequency.SelectedValue; + + if (textBoxConnectionBackupPath.Text.Trim().Length <= 0) + { + Settings.Default.LoadConsFromCustomLocation = false; + Settings.Default.CustomConsPath = String.Empty; + } + else + { + var newFileName = textBoxConnectionBackupPath.Text; + + Runtime.ConnectionsService.SaveConnections(Runtime.ConnectionsService.ConnectionTreeModel, false, + new SaveFilter(), newFileName); + + if (newFileName == Runtime.ConnectionsService.GetDefaultStartupConnectionFileName()) + { + Settings.Default.LoadConsFromCustomLocation = false; + } + else + { + Settings.Default.LoadConsFromCustomLocation = true; + Settings.Default.CustomConsPath = newFileName; + } + } + + //Obsolete. Set to false + Settings.Default.SaveConnectionsAfterEveryEdit = false; + Settings.Default.SaveConsOnExit = false; + } + + private void ButtonBrowsePath_Click(object sender, EventArgs e) + { + var saveDialog = DialogFactory.ConnectionsSaveAsDialog(); + + var dialogResult = saveDialog.ShowDialog(this); + + textBoxConnectionBackupPath.Text = dialogResult == DialogResult.OK ? saveDialog.FileName : string.Empty; + } + } +} \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/BackupPage.resx b/mRemoteNG/UI/Forms/OptionsPages/BackupPage.resx new file mode 100644 index 00000000..392a4fa0 --- /dev/null +++ b/mRemoteNG/UI/Forms/OptionsPages/BackupPage.resx @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs b/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs index 2df46cbe..6649cbcb 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs @@ -1,5 +1,7 @@ using mRemoteNG.Config; using System; +using System.Collections.Generic; +using mRemoteNG.Config.Connections; using mRemoteNG.Properties; using mRemoteNG.Resources.Language; @@ -8,6 +10,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages public sealed partial class ConnectionsPage { private readonly FrmMain _frmMain = FrmMain.Default; + private List _connectionWarning; public ConnectionsPage() { @@ -25,12 +28,23 @@ namespace mRemoteNG.UI.Forms.OptionsPages public override void ApplyLanguage() { base.ApplyLanguage(); + + _connectionWarning = new List + { + { new DropdownList((int)ConfirmCloseEnum.Never, Language.RadioCloseWarnMultiple)}, + { new DropdownList((int)ConfirmCloseEnum.Exit, Language.RadioCloseWarnExit)}, + { new DropdownList((int)ConfirmCloseEnum.Multiple, Language.RadioCloseWarnMultiple)}, + { new DropdownList((int)ConfirmCloseEnum.All, Language._CloseWarnAll)} + }; + + //comboBoxConnectionWarning.DataSource = _connectionWarning; + //comboBoxConnectionWarning.DisplayMember = "DisplayString"; + //comboBoxConnectionWarning.ValueMember = "Index"; chkSingleClickOnConnectionOpensIt.Text = Language.SingleClickOnConnectionOpensIt; chkSingleClickOnOpenedConnectionSwitchesToIt.Text = Language.SingleClickOnOpenConnectionSwitchesToIt; chkConnectionTreeTrackActiveConnection.Text = Language.TrackActiveConnectionInConnectionTree; chkHostnameLikeDisplayName.Text = Language.SetHostnameLikeDisplayName; - chkSaveConnectionsAfterEveryEdit.Text = Language.SaveConnectionsAfterEveryEdit; chkUseFilterSearch.Text = Language.FilterSearchMatchesInConnectionTree; chkPlaceSearchBarAboveConnectionTree.Text = Language.PlaceSearchBarAboveConnectionTree; chkDoNotTrimUsername.Text = Language.DoNotTrimUsername; @@ -38,12 +52,8 @@ namespace mRemoteNG.UI.Forms.OptionsPages lblRdpReconnectionCount.Text = Language.RdpReconnectCount; lblRDPConTimeout.Text = Language.RdpOverallConnectionTimeout; lblAutoSave1.Text = Language.AutoSaveEvery; + //ngLabel1.Text = Language.strLabelClosingConnections; - lblClosingConnections.Text = Language.ClosingConnections; - radCloseWarnAll.Text = Language._CloseWarnAll; - radCloseWarnMultiple.Text = Language.RadioCloseWarnMultiple; - radCloseWarnExit.Text = Language.RadioCloseWarnExit; - radCloseWarnNever.Text = Language.RadioCloseWarnNever; } public override void LoadSettings() @@ -52,7 +62,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkSingleClickOnOpenedConnectionSwitchesToIt.Checked = Settings.Default.SingleClickSwitchesToOpenConnection; chkConnectionTreeTrackActiveConnection.Checked = Settings.Default.TrackActiveConnectionInConnectionTree; chkHostnameLikeDisplayName.Checked = Settings.Default.SetHostnameLikeDisplayName; - chkSaveConnectionsAfterEveryEdit.Checked = Settings.Default.SaveConnectionsAfterEveryEdit; + chkUseFilterSearch.Checked = Settings.Default.UseFilterSearch; chkPlaceSearchBarAboveConnectionTree.Checked = Settings.Default.PlaceSearchBarAboveConnectionTree; chkDoNotTrimUsername.Checked = Settings.Default.DoNotTrimUsername; @@ -61,20 +71,22 @@ namespace mRemoteNG.UI.Forms.OptionsPages numRDPConTimeout.Value = Convert.ToDecimal(Settings.Default.ConRDPOverallConnectionTimeout); numAutoSave.Value = Convert.ToDecimal(Settings.Default.AutoSaveEveryMinutes); - switch (Settings.Default.ConfirmCloseConnection) + //comboBoxConnectionWarning.SelectedValue = Settings.Default.ConfirmCloseConnection; + + if (Settings.Default.SaveConnectionsFrequency == (int)ConnectionsBackupFrequencyEnum.Unassigned) { - case (int)ConfirmCloseEnum.Never: - radCloseWarnNever.Checked = true; - break; - case (int)ConfirmCloseEnum.Exit: - radCloseWarnExit.Checked = true; - break; - case (int)ConfirmCloseEnum.Multiple: - radCloseWarnMultiple.Checked = true; - break; - default: - radCloseWarnAll.Checked = true; - break; + if (Settings.Default.SaveConnectionsAfterEveryEdit) + { + Settings.Default.SaveConnectionsFrequency = (int)ConnectionsBackupFrequencyEnum.OnEdit; + } + else if (Settings.Default.SaveConsOnExit) + { + Settings.Default.SaveConnectionsFrequency = (int)ConnectionsBackupFrequencyEnum.OnExit; + } + else + { + Settings.Default.SaveConnectionsFrequency = (int)ConnectionsBackupFrequencyEnum.Never; + } } } @@ -84,7 +96,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages Settings.Default.SingleClickSwitchesToOpenConnection = chkSingleClickOnOpenedConnectionSwitchesToIt.Checked; Settings.Default.TrackActiveConnectionInConnectionTree = chkConnectionTreeTrackActiveConnection.Checked; Settings.Default.SetHostnameLikeDisplayName = chkHostnameLikeDisplayName.Checked; - Settings.Default.SaveConnectionsAfterEveryEdit = chkSaveConnectionsAfterEveryEdit.Checked; + Settings.Default.UseFilterSearch = chkUseFilterSearch.Checked; Settings.Default.PlaceSearchBarAboveConnectionTree = chkPlaceSearchBarAboveConnectionTree.Checked; Settings.Default.DoNotTrimUsername = chkDoNotTrimUsername.Checked; @@ -102,25 +114,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages _frmMain.tmrAutoSave.Enabled = false; } - if (radCloseWarnAll.Checked) - { - Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.All; - } - - if (radCloseWarnMultiple.Checked) - { - Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Multiple; - } - - if (radCloseWarnExit.Checked) - { - Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Exit; - } - - if (radCloseWarnNever.Checked) - { - Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Never; - } + //Settings.Default.ConfirmCloseConnection = (int)comboBoxConnectionWarning.SelectedValue; } } } \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs b/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs index 550ccf3e..8360424a 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs @@ -64,4 +64,15 @@ namespace mRemoteNG.UI.Forms.OptionsPages ResumeLayout(false); } } + internal class DropdownList + { + public int Index { get; set; } + public string DisplayString { get; set; } + + public DropdownList(int argIndex, string argDisplay) + { + Index = argIndex; + DisplayString = argDisplay; + } + } } \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/StartupExitPage.cs b/mRemoteNG/UI/Forms/OptionsPages/StartupExitPage.cs index 71c76bc5..836dbcb8 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/StartupExitPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/StartupExitPage.cs @@ -23,7 +23,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages { base.ApplyLanguage(); - chkSaveConsOnExit.Text = Language.SaveConsOnExit; chkReconnectOnStart.Text = Language.ReconnectAtStartup; chkSingleInstance.Text = Language.AllowOnlySingleInstance; chkStartMinimized.Text = Language.StartMinimized; @@ -33,7 +32,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages { base.SaveSettings(); - Settings.Default.SaveConsOnExit = chkSaveConsOnExit.Checked; Settings.Default.OpenConsFromLastSession = chkReconnectOnStart.Checked; Settings.Default.SingleInstance = chkSingleInstance.Checked; Settings.Default.StartMinimized = chkStartMinimized.Checked; @@ -42,7 +40,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages private void StartupExitPage_Load(object sender, EventArgs e) { - chkSaveConsOnExit.Checked = Settings.Default.SaveConsOnExit; chkReconnectOnStart.Checked = Settings.Default.OpenConsFromLastSession; chkSingleInstance.Checked = Settings.Default.SingleInstance; chkStartMinimized.Checked = Settings.Default.StartMinimized; diff --git a/mRemoteNG/UI/Forms/frmOptions.cs b/mRemoteNG/UI/Forms/frmOptions.cs index 8743ce10..1b98c03f 100644 --- a/mRemoteNG/UI/Forms/frmOptions.cs +++ b/mRemoteNG/UI/Forms/frmOptions.cs @@ -82,6 +82,8 @@ namespace mRemoteNG.UI.Forms {typeof(ThemePage).Name, new ThemePage {Dock = DockStyle.Fill}}, {typeof(SecurityPage).Name, new SecurityPage {Dock = DockStyle.Fill}}, {typeof(AdvancedPage).Name, new AdvancedPage {Dock = DockStyle.Fill}}, + {typeof(BackupPage).Name, new BackupPage {Dock = DockStyle.Fill}}, + {typeof(ComponentsPage).Name, new ComponentsPage {Dock = DockStyle.Fill}}, }; } diff --git a/mRemoteNG/app.config b/mRemoteNG/app.config index cc4f174b..5519ba5b 100644 --- a/mRemoteNG/app.config +++ b/mRemoteNG/app.config @@ -591,12 +591,6 @@ 20 - - AES - - - GCM - 10000 @@ -747,6 +741,9 @@ False + + 0 + Highest diff --git a/mRemoteNG/mRemoteNG.csproj b/mRemoteNG/mRemoteNG.csproj index c6fff13d..7c6b1e14 100644 --- a/mRemoteNG/mRemoteNG.csproj +++ b/mRemoteNG/mRemoteNG.csproj @@ -74,6 +74,7 @@ + @@ -511,6 +512,15 @@ UserControl + + UserControl + + + BackupPage.cs + + + ComponentsPage.cs + UserControl @@ -876,6 +886,9 @@ AppearancePage.cs + + BackupPage.cs + ConnectionsPage.cs @@ -1088,6 +1101,7 @@ PreserveNewest + PreserveNewest diff --git a/mRemoteNGDocumentation/user_interface/options.rst b/mRemoteNGDocumentation/user_interface/options.rst index 89c28ba8..d1861eb7 100644 --- a/mRemoteNGDocumentation/user_interface/options.rst +++ b/mRemoteNGDocumentation/user_interface/options.rst @@ -18,9 +18,6 @@ Options below are for the various settings for Startup/Exit of mRemoteNG. * - Option - Default - Description - * - Save connection on exit - - On - - Save to connection file/database on exit of mRemoteNG * - Reconnect to previously opened sessions on startup - Off - This option will allow you to open the connection from which you where connected to after last exit of application @@ -109,32 +106,46 @@ Connections * - Set hostname like display name when creating or renaming connections - Off - Will make mRemoteNG try to use the remote host hostname to set the title of the tab in mRemoteNG. - * - Save connections after every exit - - On - - When active mRemoteNG will save the connection tree to the active config after every exit. If inactive then you have to save using **File > Save Connection File** or keyboard shortcut Ctrl+S * - Filter search matches in connection tree - Off - Allows you to filter out the connections to which does not match your filter search in the connection tree. If not active the search will only select the filter to which you do search. * - RDP Reconnect count - 5 - - Value in seconds + - Value in seconds * - RDP Connection Timeout - 20 - - Value in seconds + - Value in seconds * - Auto save time in minutes (0 means disabled) - 0 - Value in minutes - * - When closing connections - - Warn me when closing connections + * - When closing connections Warn me... + - ... when any connection closes - Various options of how mRemoteNG should act when you close connections. The different options are listed below: :: - - Warn me when closing connections - - Warn me only when closing multiple connections - - Warn me only when exiting mRemoteNG - - Do not warn me when closing connections + - ... when any connection closes + - ... when closing multiple connections + - ... only when exiting mRemoteNG + - ... never By default a warning will come up on closing a connection. Change this value based on your prefered settings. + * - Connection Backup Frequency + - On Edit + - Various options of when mRemoteNG should create a backup of the connections file. The different options are listed below: + :: + - Never backup connections + - On Edit + - On Exit + - Daily + - Weekly + By default a backup will be saved every time the connections are edited. Change this value based on your prefered settings. + * - Maximum number of backups + - 10 + - Number of backup copies of the connection file to keep. + * - Location of backup files + - (blank) + - Full path of backup copies of the connection files. + Credentials =========== Options for credentials in mRemoteNG. The main purpose here is that when you have empty username, password or domain field then use below information.