From f439eb651364975bce2c07a432b6977d2a5987c2 Mon Sep 17 00:00:00 2001 From: Michael Becker Date: Sat, 9 Jan 2021 22:41:27 -0500 Subject: [PATCH] actually implement AutoSave plugin, and add NonSerializedProperty where appropriate to FileSystem objects --- .../NonSerializedPropertyAttribute.cs | 36 +++ .../ObjectModels/FileSystem/File.cs | 63 ++--- .../FileSystem/FileSystemObjectModel.cs | 7 +- .../ObjectModels/FileSystem/Folder.cs | 5 +- .../FileSystem/IFileSystemContainer.cs | 5 +- .../FileSystem/IFileSystemObject.cs | 1 + .../AutoSaveDataFormat.cs | 251 ++++++++++++++++++ .../AutoSaveKnownType.cs | 23 ++ .../AutoSaveObjectModel.cs | 39 +++ .../AutoSavePlugin.cs | 74 +++++- .../Dialogs/AutoSaveDialog.cs | 46 ++++ .../Dialogs/AutoSaveDialog.glade | 175 ++++++++++++ .../UniversalEditor.Plugins.AutoSave.csproj | 18 ++ 13 files changed, 697 insertions(+), 46 deletions(-) create mode 100644 Libraries/UniversalEditor.Core/NonSerializedPropertyAttribute.cs create mode 100644 Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveDataFormat.cs create mode 100644 Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveKnownType.cs create mode 100644 Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveObjectModel.cs create mode 100644 Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.cs create mode 100644 Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.glade diff --git a/Libraries/UniversalEditor.Core/NonSerializedPropertyAttribute.cs b/Libraries/UniversalEditor.Core/NonSerializedPropertyAttribute.cs new file mode 100644 index 00000000..81b51428 --- /dev/null +++ b/Libraries/UniversalEditor.Core/NonSerializedPropertyAttribute.cs @@ -0,0 +1,36 @@ +// +// NonSerializedPropertyAttribute.cs - indicates that a particular property should not be serialized +// +// Author: +// Michael Becker +// +// Copyright (c) 2011-2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; + +namespace UniversalEditor +{ + /// + /// Indicates that a particular property should not be serialized. Used in + /// place of because that does + /// not allow use on property declarations. + /// + [AttributeUsage(AttributeTargets.Property)] + public class NonSerializedPropertyAttribute : Attribute + { + + } +} \ No newline at end of file diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/File.cs b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/File.cs index 2870ea65..76256c71 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/File.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/File.cs @@ -126,23 +126,20 @@ namespace UniversalEditor.ObjectModels.FileSystem } } - private FileAttributes mvarAttributes = FileAttributes.None; - public FileAttributes Attributes { get { return mvarAttributes; } set { mvarAttributes = value; } } - - private string mvarName = String.Empty; + public FileAttributes Attributes { get; set; } = FileAttributes.None; /// /// The name of this file. /// - public string Name { get { return mvarName; } set { mvarName = value; } } + public string Name { get; set; } = String.Empty; public void SetData(byte[] data) { - mvarSource = new MemoryFileSource(data); + Source = new MemoryFileSource(data); } public byte[] GetData() { - if (mvarSource != null) return mvarSource.GetData(); + if (Source != null) return Source.GetData(); if (DataRequest != null) { DataRequestEventArgs e = new DataRequestEventArgs(); @@ -150,15 +147,15 @@ namespace UniversalEditor.ObjectModels.FileSystem return e.Data; } - Console.WriteLine("DataRequest: " + mvarName + ": No source associated with this file"); + Console.WriteLine("DataRequest: " + Name + ": No source associated with this file"); return new byte[0]; } public byte[] GetData(long offset, long length) { - if (mvarSource != null) return mvarSource.GetDataInternal(offset, length); + if (Source != null) return Source.GetDataInternal(offset, length); - Console.WriteLine("DataRequest: " + mvarName + ": No source associated with this file"); + Console.WriteLine("DataRequest: " + Name + ": No source associated with this file"); return new byte[length]; } @@ -170,7 +167,7 @@ namespace UniversalEditor.ObjectModels.FileSystem } public void SetData(System.IO.Stream stream) { - mvarSource = new AccessorFileSource(new StreamAccessor(stream)); + Source = new AccessorFileSource(new StreamAccessor(stream)); } public void SetData(string value) @@ -185,14 +182,14 @@ namespace UniversalEditor.ObjectModels.FileSystem public object Clone() { File clone = new File(); - clone.Name = mvarName; - clone.Source = mvarSource; + clone.Name = Name; + clone.Source = Source; if (DataRequest != null) { clone.DataRequest += DataRequest; } clone.Source = Source; - foreach (KeyValuePair kvp in mvarProperties) + foreach (KeyValuePair kvp in Properties) { clone.Properties.Add(kvp.Key, kvp.Value); } @@ -200,7 +197,7 @@ namespace UniversalEditor.ObjectModels.FileSystem { clone.AdditionalDetails.Add(kvp.Key, kvp.Value); } - clone.Parent = mvarParent; + clone.Parent = Parent; return clone; } @@ -266,7 +263,7 @@ namespace UniversalEditor.ObjectModels.FileSystem strSize = "?"; } } - return mvarName + " [" + strSize + "]"; + return Name + " [" + strSize + "]"; } public void Save() @@ -281,7 +278,7 @@ namespace UniversalEditor.ObjectModels.FileSystem System.IO.Directory.CreateDirectory(FileDirectory); } - FileSource source = mvarSource; + FileSource source = Source; long blockSize = (System.Environment.WorkingSet / 8); long blockCount = (blockSize / source.GetLength()); long offset = 0; @@ -310,9 +307,9 @@ namespace UniversalEditor.ObjectModels.FileSystem } else { - if (mvarSource != null) + if (Source != null) { - return mvarSource.GetLength(); + return Source.GetLength(); } return 0; } @@ -328,31 +325,23 @@ namespace UniversalEditor.ObjectModels.FileSystem mvarSize = null; } - #region Metadata - private string mvarTitle = null; - public string Title { get { return mvarTitle; } set { mvarTitle = value; } } - - private string mvarDescription = null; - public string Description { get { return mvarDescription; } set { mvarDescription = value; } } - #endregion + public string Title { get; set; } = null; + public string Description { get; set; } = null; public event DataRequestEventHandler DataRequest; - private Dictionary mvarProperties = new Dictionary(); - public Dictionary Properties { get { return mvarProperties; } } + public Dictionary Properties { get; } = new Dictionary(); + public DateTime ModificationTimestamp { get; set; } = DateTime.Now; - private DateTime mvarModificationTimestamp = DateTime.Now; - public DateTime ModificationTimestamp { get { return mvarModificationTimestamp; } set { mvarModificationTimestamp = value; } } - - private FileSource mvarSource = null; /// /// Determines where this gets its data from. /// - public FileSource Source { get { return mvarSource; } set { mvarSource = value; } } + public FileSource Source { get; set; } = null; - private IFileSystemContainer mvarParent = null; - public IFileSystemContainer Parent { get { return mvarParent; } internal set { mvarParent = value; } } + [NonSerializedProperty] + public IFileSystemContainer Parent { get; internal set; } = null; + [NonSerializedProperty] public FileSystemObjectModel FileSystem { get; private set; } = null; // The amount of working set to allocate to each block. @@ -370,7 +359,7 @@ namespace UniversalEditor.ObjectModels.FileSystem long blockSize = (System.Environment.SystemPageSize / BLOCK_FRACTION); long offset = 0; - double dbl = ((double)mvarSource.GetLength() / (double)blockSize); + double dbl = ((double)Source.GetLength() / (double)blockSize); long blockCount = (long)Math.Ceiling(dbl); if (transformations != null) @@ -380,7 +369,7 @@ namespace UniversalEditor.ObjectModels.FileSystem for (long i = 0; i < blockCount; i++) { - byte[] data = mvarSource.GetDataInternal(offset, blockSize); + byte[] data = Source.GetDataInternal(offset, blockSize); offset += blockSize; bw.WriteBytes(data); diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/FileSystemObjectModel.cs b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/FileSystemObjectModel.cs index 9b534da8..1d6ad0da 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/FileSystemObjectModel.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/FileSystemObjectModel.cs @@ -66,7 +66,10 @@ namespace UniversalEditor.ObjectModels.FileSystem } } + [NonSerializedProperty] public FileSystemObjectModel FileSystem { get { return this; } } + [NonSerializedProperty] + public IFileSystemContainer Parent { get { return null; } } public static FileSystemObjectModel FromFiles(string[] fileNames) { @@ -192,9 +195,9 @@ namespace UniversalEditor.ObjectModels.FileSystem } } - public object FindObject(string name) + public IFileSystemObject FindObject(string name) { - string[] path = name.Split(new char[] { '/' }); + string[] path = name.Split(new char[] { '/', '\\' }); Folder parent = null; for (int i = 0; i < path.Length - 1; i++) { diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/Folder.cs b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/Folder.cs index bb77845c..c3bdc293 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/Folder.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/Folder.cs @@ -106,6 +106,7 @@ namespace UniversalEditor.ObjectModels.FileSystem mvarFiles = new File.FileCollection(this); } + [NonSerializedProperty] public FileSystemObjectModel FileSystem { get; private set; } = null; private FolderCollection _parentCollection = null; @@ -113,8 +114,8 @@ namespace UniversalEditor.ObjectModels.FileSystem private string mvarName = String.Empty; public string Name { get { return mvarName; } set { mvarName = value; } } - private IFileSystemContainer mvarParent = null; - public IFileSystemContainer Parent { get { return mvarParent; } private set { mvarParent = value; } } + [NonSerializedProperty] + public IFileSystemContainer Parent { get; private set; } = null; private FolderCollection mvarFolders = null; public FolderCollection Folders { get { return mvarFolders; } } diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemContainer.cs b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemContainer.cs index 84b0571c..489f021f 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemContainer.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemContainer.cs @@ -24,15 +24,12 @@ namespace UniversalEditor.ObjectModels.FileSystem /// /// The interface which defines the base functionality for an object which contains s and s. /// - public interface IFileSystemContainer + public interface IFileSystemContainer : IFileSystemObject { File.FileCollection Files { get; } Folder.FolderCollection Folders { get; } string GetNewFolderName(); File AddFile(string name, byte[] fileData = null); - - FileSystemObjectModel FileSystem { get; } - string Name { get; set; } } } diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemObject.cs b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemObject.cs index 5e40d71e..22baa300 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemObject.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/FileSystem/IFileSystemObject.cs @@ -29,6 +29,7 @@ namespace UniversalEditor.ObjectModels.FileSystem string Name { get; set; } FileSystemObjectModel FileSystem { get; } + IFileSystemContainer Parent { get; } } /// /// Represents a of s. diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveDataFormat.cs b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveDataFormat.cs new file mode 100644 index 00000000..4eee53e2 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveDataFormat.cs @@ -0,0 +1,251 @@ +using System; +using System.Reflection; +using UniversalEditor.Accessors; +using UniversalEditor.IO; + +namespace UniversalEditor.Plugins.AutoSave +{ + internal class AutoSaveDataFormat : DataFormat + { + public float Version { get; set; } = 1.0f; + + public static float MAX_SUPPORTED_VERSION = 1.0f; + + protected override void LoadInternal(ref ObjectModel objectModel) + { + Reader r = Accessor.Reader; + AutoSaveObjectModel autosave = (objectModel as AutoSaveObjectModel); + + string signature = r.ReadFixedLengthString(12); + if (!signature.Equals("UE4 AutoSave")) + throw new InvalidDataFormatException("file does not begin with 'UE4 AutoSave'"); + + Version = r.ReadSingle(); + if (Version > MAX_SUPPORTED_VERSION) + { + throw new InvalidDataFormatException(String.Format("format version {0} not supported!", Version)); + } + + autosave.OriginalFileName = r.ReadNullTerminatedString(); + autosave.LastUpdateDateTime = r.ReadDateTime(); + + long offsetToStringTable = r.ReadInt64(); + r.Accessor.SavePosition(); + + r.Seek(offsetToStringTable, SeekOrigin.Begin); + int stringTableCount = r.ReadInt32(); + for (int i = 0; i < stringTableCount; i++) + { + string value = r.ReadNullTerminatedString(); + _StringTable.Add(value); + } + + r.Accessor.LoadPosition(); + + object om = ReadObject(r); + if (om is ObjectModel) + { + autosave.ObjectModel = (om as ObjectModel); + } + } + + protected override void SaveInternal(ObjectModel objectModel) + { + Writer w = Accessor.Writer; + AutoSaveObjectModel autosave = (objectModel as AutoSaveObjectModel); + + w.AutoFlush = true; // should be removed for release + + w.WriteFixedLengthString("UE4 AutoSave"); + w.WriteSingle(Version); + + if (autosave.OriginalFileName != null) + { + w.WriteNullTerminatedString(autosave.OriginalFileName); + } + else + { + w.WriteByte(0); + } + + // last update date time + w.WriteDateTime(DateTime.Now); + + MemoryAccessor ma = new MemoryAccessor(); + WriteObject(ma.Writer, autosave.ObjectModel); + + ma.Flush(); + ma.Close(); + + w.WriteInt64(ma.Length); // offset to string table + w.WriteBytes(ma.ToArray()); + + w.WriteInt32(_StringTable.Count); + for (int i = 0; i < _StringTable.Count; i++) + { + w.WriteNullTerminatedString(_StringTable[i]); + } + } + + private System.Collections.Specialized.StringCollection _StringTable = new System.Collections.Specialized.StringCollection(); + private int MakeStringTableEntry(string value) + { + if (!_StringTable.Contains(value)) + _StringTable.Add(value); + + return _StringTable.IndexOf(value); + } + + private object ReadObject(Reader r) + { + AutoSaveKnownType typeId = (AutoSaveKnownType) r.ReadInt32(); + switch (typeId) + { + case AutoSaveKnownType.Null: return null; + case AutoSaveKnownType.Object: + { + int index = r.ReadInt32(); + string typeName = _StringTable[index]; + break; + } + } + return null; + } + + private void WriteObject(Writer w, object o) + { + if (o == null) + { + w.WriteInt32((int)AutoSaveKnownType.Null); // null + return; + } + + w.WriteInt32((int)AutoSaveKnownType.Object); + + Type t = o.GetType(); + + w.WriteInt32(MakeStringTableEntry(t.FullName)); + + // public instance properties are really the only things we care about + System.Reflection.PropertyInfo[] pis = t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + + System.Collections.Generic.List list = new System.Collections.Generic.List(); + for (int i = 0; i < pis.Length; i++) + { + if (pis[i].GetCustomAttribute() != null) + { + continue; + } + list.Add(pis[i]); + } + w.WriteInt32(list.Count); + for (int i = 0; i < list.Count; i++) + { + WriteProperty(w, list[i], o); + } + } + + private void WriteProperty(Writer w, PropertyInfo propertyInfo, object obj) + { + w.WriteInt32(MakeStringTableEntry(propertyInfo.Name)); + w.WriteInt32(MakeStringTableEntry(propertyInfo.PropertyType.FullName)); + + object val = propertyInfo.GetValue(obj); + + if (val == obj) + return; + + WriteValue(w, val); + } + + private void WriteValue(Writer w, object val) + { + if (val is string) + { + w.WriteInt32((int)AutoSaveKnownType.String); + w.WriteInt32(MakeStringTableEntry(val as string)); + } + else if (val is byte) + { + w.WriteInt32((int)AutoSaveKnownType.Byte); + w.WriteByte((byte)val); + } + else if (val is sbyte) + { + w.WriteInt32((int)AutoSaveKnownType.SByte); + w.WriteSByte((sbyte)val); + } + else if (val is char) + { + w.WriteInt32((int)AutoSaveKnownType.Char); + w.WriteChar((char)val); + } + else if (val is short) + { + w.WriteInt32((int)AutoSaveKnownType.Int16); + w.WriteInt16((short)val); + } + else if (val is int) + { + w.WriteInt32((int)AutoSaveKnownType.Int32); + w.WriteInt32((int)val); + } + else if (val is long) + { + w.WriteInt32((int)AutoSaveKnownType.Int64); + w.WriteInt64((long)val); + } + else if (val is ushort) + { + w.WriteInt32((int)AutoSaveKnownType.UInt16); + w.WriteUInt16((ushort)val); + } + else if (val is uint) + { + w.WriteInt32((int)AutoSaveKnownType.UInt32); + w.WriteUInt32((uint)val); + } + else if (val is ulong) + { + w.WriteInt32((int)AutoSaveKnownType.UInt64); + w.WriteUInt64((ulong)val); + } + else if (val is float) + { + w.WriteInt32((int)AutoSaveKnownType.Single); + w.WriteSingle((float)val); + } + else if (val is double) + { + w.WriteInt32((int)AutoSaveKnownType.Double); + w.WriteDouble((double)val); + } + else if (val is decimal) + { + w.WriteInt32((int)AutoSaveKnownType.Decimal); + w.WriteDecimal((decimal)val); + } + else if (val is Guid) + { + w.WriteInt32((int)AutoSaveKnownType.Guid); + w.WriteGuid((Guid)val); + } + else if (val is System.Collections.IList) + { + w.WriteInt32((int)AutoSaveKnownType.List); + + System.Collections.IList il = (val as System.Collections.IList); + w.WriteInt32(il.Count); + for (int i = 0; i < il.Count; i++) + { + WriteValue(w, il[i]); + } + } + else + { + w.WriteInt32((int)AutoSaveKnownType.Object); + WriteObject(w, val); + } + } + } +} \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveKnownType.cs b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveKnownType.cs new file mode 100644 index 00000000..1c1294c7 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveKnownType.cs @@ -0,0 +1,23 @@ +namespace UniversalEditor.Plugins.AutoSave +{ + public enum AutoSaveKnownType + { + Object = -1, + Null = 0, + String, + Char, + Byte, + SByte, + Int16, + Int32, + Int64, + UInt16, + UInt32, + UInt64, + Single, + Double, + Decimal, + Guid, + List + } +} \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveObjectModel.cs b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveObjectModel.cs new file mode 100644 index 00000000..4c1fbe78 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSaveObjectModel.cs @@ -0,0 +1,39 @@ +// +// AutoSaveObjectModel.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2021 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.Plugins.AutoSave +{ + public class AutoSaveObjectModel : ObjectModel + { + public ObjectModel ObjectModel { get; set; } = null; + + public string OriginalFileName { get; set; } = null; + public DateTime LastUpdateDateTime { get; set; } = DateTime.Now; + + public override void Clear() + { + } + + public override void CopyTo(ObjectModel where) + { + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/AutoSavePlugin.cs b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSavePlugin.cs index 169fe311..78ba264f 100644 --- a/Plugins/UniversalEditor.Plugins.AutoSave/AutoSavePlugin.cs +++ b/Plugins/UniversalEditor.Plugins.AutoSave/AutoSavePlugin.cs @@ -19,7 +19,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; +using System.Collections.Generic; +using MBS.Framework; using MBS.Framework.UserInterface; +using UniversalEditor.Accessors; +using UniversalEditor.Plugins.AutoSave.Dialogs; +using UniversalEditor.UserInterface; namespace UniversalEditor.Plugins.AutoSave { @@ -27,19 +32,86 @@ namespace UniversalEditor.Plugins.AutoSave { private Timer tmr = new Timer(); + private AutoSaveDataFormat asdf = new AutoSaveDataFormat(); + + private string GetAutosavePath() + { + return String.Format("/tmp/autosave/{0}", Application.Instance.ShortName); + } + private void tmr_Tick(object sender, EventArgs e) { Console.WriteLine("autosave: looking for dirty documents..."); + + IHostApplication ha = (Application.Instance as IHostApplication); + + string path = System.IO.Path.Combine(new string[] { GetAutosavePath(), DateTime.Now.ToString("yyyyMMdd") }); Console.WriteLine("autosave: saving dirty documents in /tmp/autosave/universal-editor/..."); + + for (int i = 0; i < ha.CurrentWindow.Editors.Count; i++) + { + Editor ed = ha.CurrentWindow.Editors[i]; + if (ed.Changed || !ed.Document.IsSaved) + { + string filename = System.IO.Path.Combine(new string[] { path, String.Format("{0}{1}.tmp", DateTime.Now.ToString("HHmmss"), i.ToString().PadLeft(2, '0')) }); + + string dir = System.IO.Path.GetDirectoryName(filename); + if (!System.IO.Directory.Exists(dir)) + System.IO.Directory.CreateDirectory(dir); + + if (!fas.ContainsKey(ed)) + { + fas[ed] = new FileAccessor(filename, true, true); + } + + AutoSaveObjectModel autosave = new AutoSaveObjectModel(); + autosave.ObjectModel = ed.ObjectModel; + if (ed.Document.IsSaved) + { + autosave.OriginalFileName = ed.Document.Accessor.GetFileName(); + } + else + { + autosave.OriginalFileName = null; + } + Document.Save(autosave, asdf, fas[ed]); + + i++; + } + } + Console.WriteLine("autosave: going back to sleep"); } + private System.Collections.Generic.Dictionary fas = new System.Collections.Generic.Dictionary(); + protected override void InitializeInternal() { base.InitializeInternal(); - tmr.Duration = 5 /*minutes*/ * 60 /*seconds in a minute*/ * 1000 /*milliseconds in a second*/; + // check to see if we have any dirty documents + Console.WriteLine("autosave: checking for existing dirty documents..."); + + string path = GetAutosavePath(); + if (!System.IO.Directory.Exists(path)) + { + return; + } + + string[] autosaves = System.IO.Directory.GetFiles(path, "*.tmp", System.IO.SearchOption.AllDirectories); + + if (autosaves.Length > 0) + { + AutoSaveDialog dlg = new AutoSaveDialog(); + dlg.FileNames.AddRange(autosaves); + if (dlg.ShowDialog() == DialogResult.OK) + { + + } + } + + tmr.Duration = 10000; // 5 /*minutes*/ * 60 /*seconds in a minute*/ * 1000 /*milliseconds in a second*/; tmr.Tick += tmr_Tick; tmr.Enabled = true; } diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.cs b/Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.cs new file mode 100644 index 00000000..c5dabde1 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.cs @@ -0,0 +1,46 @@ +using System; +using System.Reflection; +using MBS.Framework; +using MBS.Framework.Drawing; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Controls; +using MBS.Framework.UserInterface.Controls.ListView; +using UniversalEditor.Accessors; +using UniversalEditor.IO; + +namespace UniversalEditor.Plugins.AutoSave.Dialogs +{ + [ContainerLayout(typeof(AutoSaveDialog), "UniversalEditor.Plugins.AutoSave.Dialogs.AutoSaveDialog.glade")] + public class AutoSaveDialog : CustomDialog + { + private Label lblPrompt; + private ListViewControl lv; + + public System.Collections.Specialized.StringCollection FileNames { get; } = new System.Collections.Specialized.StringCollection(); + + protected override void OnCreated(EventArgs e) + { + base.OnCreated(e); + + lblPrompt.Text = lblPrompt.Text.Replace("${Application.Title}", Application.Instance.Title); + + Document[] ds = new Document[FileNames.Count]; + for (int i = 0; i < ds.Length; i++) + { + ds[i] = new Document(new AutoSaveObjectModel(), new AutoSaveDataFormat(), new FileAccessor(FileNames[i], false, false, true)); + ds[i].Load(); + + string fn = (ds[i].ObjectModel as AutoSaveObjectModel).OriginalFileName; + fn = String.IsNullOrEmpty(fn) ? "(untitled)" : fn; + + string dts = String.Format("{0} {1}", (ds[i].ObjectModel as AutoSaveObjectModel).LastUpdateDateTime.ToLongDateString(), (ds[i].ObjectModel as AutoSaveObjectModel).LastUpdateDateTime.ToLongTimeString()); + lv.Model.Rows.Add(new TreeModelRow(new TreeModelRowColumn[] + { + new TreeModelRowColumn(lv.Model.Columns[0], fn), + new TreeModelRowColumn(lv.Model.Columns[1], dts) + })); + } + } + + } +} \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.glade b/Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.glade new file mode 100644 index 00000000..a8a31130 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.AutoSave/Dialogs/AutoSaveDialog.glade @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + False + 600 + 400 + dialog + + + + + + False + vertical + 2 + + + False + end + + + gtk-ok + True + True + True + True + + + + True + True + 0 + + + + + gtk-cancel + True + True + True + True + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + vertical + + + True + False + 16 + 16 + 16 + 16 + + + True + False + 16 + gtk-dialog-info + 6 + + + False + True + 0 + + + + + True + False + ${Application.Title} has recovered the following files. Save the ones you wish to keep. + True + 0 + + + False + True + 1 + + + + + False + True + 0 + + + + + True + True + in + + + True + True + tmFiles + + + + + + True + File name + True + True + + + + 0 + + + + + + + True + Last modified + True + + + + 1 + + + + + + + + + True + True + 1 + + + + + True + True + 1 + + + + + + diff --git a/Plugins/UniversalEditor.Plugins.AutoSave/UniversalEditor.Plugins.AutoSave.csproj b/Plugins/UniversalEditor.Plugins.AutoSave/UniversalEditor.Plugins.AutoSave.csproj index 0fe4e2cb..da7ab37e 100644 --- a/Plugins/UniversalEditor.Plugins.AutoSave/UniversalEditor.Plugins.AutoSave.csproj +++ b/Plugins/UniversalEditor.Plugins.AutoSave/UniversalEditor.Plugins.AutoSave.csproj @@ -33,6 +33,10 @@ + + + + @@ -43,6 +47,20 @@ {29E1C1BB-3EA5-4062-B62F-85EEC703FE07} MBS.Framework.UserInterface + + {8622EBC4-8E20-476E-B284-33D472081F5C} + UniversalEditor.UserInterface + + + {2D4737E6-6D95-408A-90DB-8DFF38147E85} + UniversalEditor.Core + + + + + + + \ No newline at end of file