/// <summary> /// create/update note and return new note data /// </summary> internal static NoteData pushNote(NoteItem note, SQLiteConnection sql) { var js = new JavaScriptSerializer(); var node = new NoteDataUser(); node.deleted = (note.Deleted) ? (byte)1 : (byte)0; node.modifydate = note.ModifyDate.ToString("R").Replace(',', '.'); node.tags = new string[note.Tags.Count]; for (int i = 0; i < note.Tags.Count; i++) { node.tags[i] = note.Tags[i].Name; } //read additional info from db var systemtags = ""; using (SQLiteCommand cmd = new SQLiteCommand(sql)) { cmd.CommandText = "SELECT content, createdate, systemtags, version FROM notes WHERE id=" + note.Id; using (SQLiteDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { node.content = rdr.GetString(0); node.createdate = rdr.GetDouble(1).ToString("R").Replace(',', '.');; if (!rdr.IsDBNull(2)) { systemtags = rdr.GetString(2); } if (!rdr.IsDBNull(3)) { node.version = rdr.GetInt32(3); } } } } // fill systemtags if (note.Pinned) { systemtags += " pinned"; } if (note.Unread) { systemtags += " unread"; } if (!string.IsNullOrEmpty(note.Lexer)) { systemtags += " sn-lexer=" + note.Lexer; } node.systemtags = systemtags.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var data = js.Serialize(node); var url = (string.IsNullOrEmpty(note.Key)) ? "/api2/data" : "/api2/data/" + note.Key; // create/update var s = RequestRetry(url, "POST", data); return(js.Deserialize <NoteData>(s)); }
//draw found result private void drawFound(Graphics g, Rectangle r, NoteItem note) { //note title r.X += 3; //padding r.Y += 3; var ctag = this.GetForegroundColor(); var cnote = Color.FromArgb(100, 100, 100); if (ctag == SystemColors.HighlightText) { cnote = ControlPaint.Dark(ctag, 90); } else ctag = SystemColors.HotTrack; var stringSize = g.MeasureString(note.DateShort, this.Font); var offset = (int)stringSize.Height + 1; var r2 = new Rectangle(r.X + 3, offset + 2, r.Width, r.Height - offset); //rect search result using (StringFormat fmt = new StringFormat(StringFormatFlags.NoWrap)) { fmt.LineAlignment = StringAlignment.Near; fmt.Trimming = StringTrimming.EllipsisCharacter; //modify date using (SolidBrush b = new SolidBrush(Color.FromArgb(128, this.GetForegroundColor()))) { fmt.Alignment = StringAlignment.Far; g.DrawString(note.DateShort, this.Font, b, r, fmt); } //note title fmt.Alignment = StringAlignment.Near; r.Width -= (int)stringSize.Width - 1; using (var f = new Font(this.Font, FontStyle.Bold)) using (var b = new SolidBrush(ctag)) { g.DrawString(this.GetText(), f, b, r, fmt); } //pinned if (note.Pinned) { r.Height = offset; stringSize = g.MeasureString(this.GetText(), this.Font); offset = (int)stringSize.Width; r.X += offset + 3; r.Y -= 3; if (this.IsItemSelected) this.DrawImage(g, r, 7); //inverted else this.DrawImage(g, r, 6); } } //search result to rtf var s = note.Snippet.Replace("\n", " ").Replace("\r", " "); while (s.Contains(" ")) s = s.Replace(" ", " "); s = s.Replace(@"\", @"\\") .Replace("{", @"\{") .Replace("}", @"\}") .Replace(@"<b>", @"\b ") .Replace(@"</b>", @"\b0 "); g.DrawRtfText(@"{\rtf\b0 " + s + " }", r2, cnote, this.Font); }
/// <summary> /// creates new note under selected tag and make it active /// </summary> private void createNote() { // get parent tag if something selected TagItem tag; if (tree.SelectedObject != null) { if (tree.SelectedObject is TagItem) tag = (TagItem)tree.SelectedObject; else tag = (TagItem)tree.GetParent(tree.SelectedObject); if (tag == tagDeleted) tag = tagAll; //don't create new deleted notes } else tag = tagAll; //add new note to db var node = new NoteItem(); node.ModifyDate = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; node.Name = "New Note"; if(!tag.System) node.Tags.Add(tag); using (SQLiteTransaction tr = sql.BeginTransaction()) { using (SQLiteCommand cmd = new SQLiteCommand(sql)) { cmd.CommandText = "INSERT INTO notes(modifydate, createdate, title, content) VALUES(@mdate, @mdate, @title, @title)"; cmd.Parameters.AddWithValue("@mdate", node.ModifyDate); cmd.Parameters.AddWithValue("@title", node.Name); cmd.ExecuteNonQuery(); node.Id = sql.LastInsertRowId; if (!tag.System) { cmd.CommandText = "INSERT INTO nt(note,tag) VALUES(" + node.Id + "," + tag.Id + ")"; cmd.ExecuteNonQuery(); } } tr.Commit(); } // refresh tree root, select new leaf notes.Add(node); tree.RefreshObject(tag); tree.Expand(tag); tree.Reveal(node, true); scEdit.Focus(); }
/// <summary> /// get notes from db with tags /// </summary> static List<NoteItem> readNotes(SQLiteConnection sql, List<TagItem> tags, string query="") { List<NoteItem> result = new List<NoteItem>(); string s; if (query.Length > 0) s = @"SELECT n.id, n.title, n.modifydate, n.deleted, c.tag, n.lexer, n.pinned, snippet(fts, '<b>', '</b>', '...'), matchinfo(fts)" + " FROM fts s LEFT JOIN notes n ON s.docid=n.id LEFT JOIN nt c ON c.note=n.id LEFT JOIN tags t ON t.id=c.tag" + " WHERE NOT n.deleted AND fts MATCH ?"+ " ORDER BY n.id, t.`index`"; else s = "SELECT n.id, n.title, n.modifydate, n.deleted, c.tag, n.lexer, n.pinned, n.key, n.syncnum" + " FROM notes n LEFT JOIN nt c ON c.note=n.id LEFT JOIN tags t ON t.id=c.tag" + " ORDER BY n.id, t.`index`"; NoteItem node = new NoteItem(); int id = -1; int tmp; using (SQLiteCommand cmd = new SQLiteCommand(s, sql)) { if (query.Length > 0) cmd.Parameters.AddWithValue(null, query); using (SQLiteDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { tmp = rdr.GetInt32(0); if (tmp != id) { id = tmp; node = new NoteItem(); node.Id = id; node.Name = rdr.GetString(1); node.ModifyDate = rdr.GetDouble(2); node.Deleted = rdr.GetBoolean(3); node.Tags = new List<TagItem>(); if (!rdr.IsDBNull(4)) node.Tags.Add(tags.Find(x => x.Id == rdr.GetInt32(4))); if (!rdr.IsDBNull(5)) node.Lexer = rdr.GetString(5); node.Pinned = rdr.GetBoolean(6); if (query.Length > 0) { // search results node.Snippet = rdr.GetString(7); node.Relevance = getRelevance(rdr,8); } else { // sync attrs if (!rdr.IsDBNull(7)) node.Key = rdr.GetString(7); if (!rdr.IsDBNull(8)) node.SyncNum = rdr.GetInt32(8); } result.Add(node); } else node.Tags.Add(tags.Find(x => x.Id == rdr.GetInt32(4))); } } } return result; }
/// <summary> /// Update note in DB with sync result /// </summary> /// <param name="n">Note to update, could be null = create new</param> /// <param name="raw">Data from sync to update with</param> /// <param name="ui">Scheduler for UI thread to display changes</param> private void UpdateNote(NoteItem n, NoteData raw, TaskScheduler ui) { bool update = true; if (n == null) { n = new NoteItem(); update = false; } n.Deleted = raw.deleted == 1; n.Key = raw.key; n.ModifyDate = double.Parse(raw.modifydate, System.Globalization.CultureInfo.InvariantCulture); if (raw.content!=null) n.Name = note.GetTitle(raw.content); n.SyncNum = raw.syncnum; // read system tags string systemtags=""; //unparsed tags to save foreach (var tag in raw.systemtags) { if (tag == "pinned") n.Pinned = true; else if (tag == "unread") n.Unread = true; else if (tag.StartsWith("sn-lexer=")) { var lexer = tag.Substring(9); if (Glob.Lexers.Contains(lexer)) n.Lexer = lexer; } else systemtags += tag + " "; } // create new connection as it is another thread var conn = new SQLiteConnection(ConnString); conn.Open(); using (SQLiteTransaction tr = conn.BeginTransaction()) { using (SQLiteCommand cmd = new SQLiteCommand(conn)) { if (raw.content == null) { // no content after push note and no merges cmd.CommandText = (update) ? "UPDATE notes SET key=?, deleted=?, modifydate=?, createdate=?, syncnum=?, version=?, systemtags=?, pinned=?, unread=?, lexer=? WHERE id=?" : "INSERT INTO notes(key, deleted, modifydate, createdate, syncnum, version, systemtags, pinned, unread, lexer) VALUES(?,?,?,?,?,?,?,?,?,?)"; } else { // update content when push & merge, or just a new remote note cmd.CommandText = (update) ? "UPDATE notes SET key=?, deleted=?, modifydate=?, createdate=?, syncnum=?, version=?, systemtags=?, pinned=?, unread=?, title=?, content=?, lexer=? WHERE id=?" : "INSERT INTO notes(key, deleted, modifydate, createdate, syncnum, version, systemtags, pinned, unread, title, content, lexer) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"; } cmd.Parameters.AddWithValue(null, n.Key); cmd.Parameters.AddWithValue(null, n.Deleted); cmd.Parameters.AddWithValue(null, n.ModifyDate); cmd.Parameters.AddWithValue(null, double.Parse(raw.createdate, System.Globalization.CultureInfo.InvariantCulture)); cmd.Parameters.AddWithValue(null, n.SyncNum); cmd.Parameters.AddWithValue(null, raw.version); cmd.Parameters.AddWithValue(null, systemtags.Trim()); cmd.Parameters.AddWithValue(null, n.Pinned); cmd.Parameters.AddWithValue(null, n.Unread); if (raw.content != null) { cmd.Parameters.AddWithValue(null, n.Name); cmd.Parameters.AddWithValue(null, raw.content); } cmd.Parameters.AddWithValue(null, n.Lexer); if(update) cmd.Parameters.AddWithValue(null, n.Id); cmd.ExecuteNonQuery(); if (!update) n.Id = conn.LastInsertRowId; } tr.Commit(); } conn.Close(); // sync with ui Task t1 = new Task(() => { if (!update) notes.Add(n); if (raw.tags.Length > 0 || n.Tags.Count > 0) { var tmp = tree.SelectedObject; var tags = string.Join(" ", raw.tags); note.ParseTags(tags, n); // read tags (and create if not exist) if (tmp != null && tree.SelectedObject != tmp) tree.SelectedObject = tmp; //restore selected position } tree.RefreshObject(tagAll); tree.RefreshObject(tagDeleted); }); t1.Start(ui); }
//draw note title with modify date private void drawNote(Graphics g, Rectangle r, NoteItem note) { //note indent r.X += 32; r.Width -= 32; //note title using (StringFormat fmt = new StringFormat(StringFormatFlags.NoWrap)) { fmt.LineAlignment = StringAlignment.Center; fmt.Trimming = StringTrimming.EllipsisCharacter; //modify date var stringSize = g.MeasureString(note.DateShort, this.Font); var offset = (int)stringSize.Width + 1; r.Width -= offset; var daterect = new Rectangle(r.X + r.Width, r.Y, offset, r.Height); using (SolidBrush b = new SolidBrush(Color.FromArgb(128, this.GetForegroundColor()))) { fmt.Alignment = StringAlignment.Far; g.DrawString(note.DateShort, this.Font, b, daterect, fmt); } //note title fmt.Alignment = StringAlignment.Near; g.DrawString(this.GetText(), this.Font, this.TextBrush, r, fmt); } //pinned if (note.Pinned) { var stringSize = g.MeasureString(this.GetText(), this.Font); var offset = (int)stringSize.Width; r.X += offset; r.Width -= offset; if (this.IsItemSelected) this.DrawImage(g, r, 7); //inverted else this.DrawImage(g, r, 6); } }
// purge note private void purgeNote(NoteItem i, bool doSync = true) { using (SQLiteCommand cmd = new SQLiteCommand(sql)) { cmd.CommandText = "DELETE FROM notes WHERE id=" + i.Id; // no need to cleanup `nt` because of cascade cmd.ExecuteNonQuery(); } notes.Remove(i); // refresh tags if (tree.RowHeight == -1) { if (i.Deleted) tree.RefreshObject(tagDeleted); else i.Tags.ForEach(x => tree.RefreshObject(x)); if ((note.Item == null || note.Item.Id == i.Id) && notes.Count > 0) tree.Reveal(notes[0], true); } else treeAsList(tbSearch.Text); // task to sync deletion if (doSync && Sync.Freq > 0 && !string.IsNullOrEmpty(i.Key)) { try { Task.Factory.StartNew(() => { Sync.delNote(i); }); } catch { statusText.Text = "Unable to sync delete"; } } }
/// <summary> /// show note for selected item /// </summary> public void ShowSelected() { if (Item != null && f.tree.RowHeight < 0) Item.TopLine = f.scEdit.FirstVisibleLine; //not search, save previous note top line var n = f.tree.SelectedObject as NoteItem; if (n == null) return; if (n != Item || syncnum != n.SyncNum) { Item = n; syncnum = n.SyncNum; } else return; // don't redraw same note (in search mode) f.scEdit.SavePointLeft -= f.scEdit_SavePointLeft; //don't save on new content loaded using (SQLiteCommand cmd = new SQLiteCommand(f.sql)) { cmd.CommandText = "SELECT content, lexer, topline FROM notes WHERE id=" + Item.Id; using (SQLiteDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { f.scEdit.Text = rdr.GetString(0); if (rdr.IsDBNull(1)) { //use tag's lexer var lex = "Bash"; foreach (var tag in Item.Tags) if (!String.IsNullOrEmpty(tag.Lexer)) { lex = tag.Lexer; break; } SetLanguage(lex); f.btnLexer.Text = "^" + lex; Item.Lexer = null; } else { Item.Lexer = rdr.GetString(1); SetLanguage(Item.Lexer); f.btnLexer.Text = Item.Lexer; } if (Item.TopLine == -1 && !rdr.IsDBNull(2) ) Item.TopLine = rdr.GetInt32(2); f.scEdit.FirstVisibleLine = Item.TopLine; } } } f.scEdit.SetSavePoint(); f.scEdit.SavePointLeft += f.scEdit_SavePointLeft; //save on change f.Text = GetTitle(); drawTags(); //highlight search term and scroll to it if (f.tbSearch.ForeColor == SystemColors.WindowText && f.tbSearch.Text.Length > 0) { f.HighlightText(f.tbSearch.Text, true); } }
/// <summary> /// parse textbox for tags to list /// </summary> public void ParseTags(String tagstr=null, NoteItem note=null) { bool draw = false; //called not for current item, don't draw tags/autocompl if (tagstr == null) { tagstr = f.tagBox.Text; f.tagBox.Text = ""; draw = true; } if (note == null) note = Item; var isSearch = f.tree.RowHeight > 0; using (SQLiteTransaction tr = f.sql.BeginTransaction()) { using (SQLiteCommand cmd = new SQLiteCommand(f.sql)) { //cleanup existing tags, as it is replace if (!draw) { cmd.CommandText = "DELETE FROM nt WHERE note=" + note.Id; cmd.ExecuteNonQuery(); note.Tags.Clear(); } var added = false; foreach (var tag in tagstr.Split(new char[] { ' ', ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) { if (String.IsNullOrEmpty(tag)) continue; if (note.Tags.Exists(x => x.Name.ToLower() == tag.ToLower())) continue; //skip already assigned var tagItem = f.tags.Find(x => !x.System && x.Name.ToLower() == tag.ToLower()); //search if exist if (tagItem==null) { //create tag in db if it is new cmd.Parameters.Clear(); cmd.CommandText = "INSERT INTO tags(name,`index`) VALUES(?,?)"; cmd.Parameters.AddWithValue(null, tag); cmd.Parameters.AddWithValue(null, f.tags.Count - 1); cmd.ExecuteNonQuery(); //refresh tree tagItem = new TagItem(f.notes); tagItem.Name = tag; tagItem.Id = f.sql.LastInsertRowId; tagItem.Index = f.tags.Count - 1; if (!isSearch) { f.tree.AddObject(tagItem); f.cName.Renderer = f.fancyRenderer; //OLV drop renderer when Roots refreshed if (draw) f.tree.SelectedObject = note; } f.tags.Add(tagItem); } cmd.CommandText = "INSERT INTO nt(note,tag) VALUES(" + note.Id + "," + tagItem.Id + ")"; cmd.ExecuteNonQuery(); note.Tags.Add(tagItem); if (!isSearch) f.tree.RefreshObject(tagItem); if (draw) drawTag(tagItem.Name); added = true; } if (draw && added) { // there was some tags actually added, update modifydate for sync note.ModifyDate = (DateTime.UtcNow.Subtract(Glob.Epoch)).TotalSeconds; cmd.CommandText = "UPDATE notes SET modifydate=? WHERE id=" + note.Id; cmd.Parameters.AddWithValue(null, note.ModifyDate); cmd.ExecuteNonQuery(); } } tr.Commit(); } if (draw) FillAutocomplete(); //refill autocomplete except for parsed tags }
/// <summary> /// parse textbox for tags to list /// </summary> public void ParseTags(String tagstr = null, NoteItem note = null) { bool draw = false; //called not for current item, don't draw tags/autocompl if (tagstr == null) { tagstr = f.tagBox.Text; f.tagBox.Text = ""; draw = true; } if (note == null) { note = Item; } var isSearch = f.tree.RowHeight > 0; using (SQLiteTransaction tr = f.sql.BeginTransaction()) { using (SQLiteCommand cmd = new SQLiteCommand(f.sql)) { //cleanup existing tags, as it is replace if (!draw) { cmd.CommandText = "DELETE FROM nt WHERE note=" + note.Id; cmd.ExecuteNonQuery(); note.Tags.Clear(); } var added = false; foreach (var tag in tagstr.Split(new char[] { ' ', ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) { if (String.IsNullOrEmpty(tag)) { continue; } if (note.Tags.Exists(x => x.Name.ToLower() == tag.ToLower())) { continue; //skip already assigned } var tagItem = f.tags.Find(x => !x.System && x.Name.ToLower() == tag.ToLower()); //search if exist if (tagItem == null) { //create tag in db if it is new cmd.Parameters.Clear(); cmd.CommandText = "INSERT INTO tags(name,`index`) VALUES(?,?)"; cmd.Parameters.AddWithValue(null, tag); cmd.Parameters.AddWithValue(null, f.tags.Count - 1); cmd.ExecuteNonQuery(); //refresh tree tagItem = new TagItem(f.notes); tagItem.Name = tag; tagItem.Id = f.sql.LastInsertRowId; tagItem.Index = f.tags.Count - 1; if (!isSearch) { f.tree.AddObject(tagItem); f.cName.Renderer = f.fancyRenderer; //OLV drop renderer when Roots refreshed if (draw) { f.tree.SelectedObject = note; } } f.tags.Add(tagItem); } cmd.CommandText = "INSERT INTO nt(note,tag) VALUES(" + note.Id + "," + tagItem.Id + ")"; cmd.ExecuteNonQuery(); note.Tags.Add(tagItem); if (!isSearch) { f.tree.RefreshObject(tagItem); } if (draw) { drawTag(tagItem.Name); } added = true; } if (draw && added) // there was some tags actually added, update modifydate for sync { note.ModifyDate = (DateTime.UtcNow.Subtract(Glob.Epoch)).TotalSeconds; cmd.CommandText = "UPDATE notes SET modifydate=? WHERE id=" + note.Id; cmd.Parameters.AddWithValue(null, note.ModifyDate); cmd.ExecuteNonQuery(); } } tr.Commit(); } if (draw) { FillAutocomplete(); //refill autocomplete except for parsed tags } }
/// <summary> /// show note for selected item /// </summary> public void ShowSelected() { if (Item != null && f.tree.RowHeight < 0) { Item.TopLine = f.scEdit.FirstVisibleLine; //not search, save previous note top line } var n = f.tree.SelectedObject as NoteItem; if (n == null) { return; } if (n != Item || syncnum != n.SyncNum) { Item = n; syncnum = n.SyncNum; } else { return; // don't redraw same note (in search mode) } f.scEdit.SavePointLeft -= f.scEdit_SavePointLeft; //don't save on new content loaded using (SQLiteCommand cmd = new SQLiteCommand(f.sql)) { cmd.CommandText = "SELECT content, lexer, topline FROM notes WHERE id=" + Item.Id; using (SQLiteDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { f.scEdit.Text = rdr.GetString(0); if (rdr.IsDBNull(1)) //use tag's lexer { var lex = "Bash"; foreach (var tag in Item.Tags) { if (!String.IsNullOrEmpty(tag.Lexer)) { lex = tag.Lexer; break; } } SetLanguage(lex); f.btnLexer.Text = "^" + lex; Item.Lexer = null; } else { Item.Lexer = rdr.GetString(1); SetLanguage(Item.Lexer); f.btnLexer.Text = Item.Lexer; } if (Item.TopLine == -1 && !rdr.IsDBNull(2)) { Item.TopLine = rdr.GetInt32(2); } f.scEdit.FirstVisibleLine = Item.TopLine; } } } f.scEdit.SetSavePoint(); f.scEdit.SavePointLeft += f.scEdit_SavePointLeft; //save on change f.Text = GetTitle(); drawTags(); //highlight search term and scroll to it if (f.tbSearch.ForeColor == SystemColors.WindowText && f.tbSearch.Text.Length > 0) { f.HighlightText(f.tbSearch.Text, true); } }
/// <summary> /// show note for selected item /// </summary> public void ShowSelected() { if (Item != null && f.tree.RowHeight < 0) Item.TopLine = f.scEdit.Lines.FirstVisibleIndex; //not search, save previous note top line var n = f.tree.SelectedObject as NoteItem; if (n == null) return; if (n != Item || syncnum != n.SyncNum) { Item = n; syncnum = n.SyncNum; } else return; // don't redraw same note (in search mode) f.scEdit.DocumentChange -= f.scEdit_DocumentChange; using (SQLiteCommand cmd = new SQLiteCommand(f.sql)) { cmd.CommandText = "SELECT content, lexer, topline FROM notes WHERE id=" + Item.Id; using (SQLiteDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { f.scEdit.Text = rdr.GetString(0); if (rdr.IsDBNull(1)) { //use tag's lexer var lex = "Bash"; foreach (var tag in Item.Tags) if (!String.IsNullOrEmpty(tag.Lexer)) { lex = tag.Lexer; break; } SetLanguage(lex); f.btnLexer.Text = "^" + lex; Item.Lexer = null; } else { Item.Lexer = rdr.GetString(1); SetLanguage(Item.Lexer); f.btnLexer.Text = Item.Lexer; } if (Item.TopLine == -1 && !rdr.IsDBNull(2) ) Item.TopLine = rdr.GetInt32(2); f.scEdit.Lines.FirstVisibleIndex = Item.TopLine; } } } f.scEdit.Modified = false; f.scEdit.DocumentChange += f.scEdit_DocumentChange; f.Text = GetTitle(); drawTags(); //highlight search term and scroll to it if (f.tbSearch.ForeColor == SystemColors.WindowText && f.tbSearch.Text.Length > 0) { var top = f.scEdit.Lines.Count; foreach (var item in f.tbSearch.Text.Split(' ')) { if (item.Length == 0) continue; foreach (Range r in f.scEdit.FindReplace.FindAll(item)) { r.SetIndicator(0); if (r.StartingLine.Number < top) top = r.StartingLine.Number; } } f.scEdit.Lines.FirstVisibleIndex = top; } }
/// <summary> /// create/update note and return new note data /// </summary> internal static NoteData pushNote(NoteItem note, SQLiteConnection sql) { var js = new JavaScriptSerializer(); var node = new NoteDataUser(); node.deleted = (note.Deleted) ? (byte)1 : (byte)0; node.modifydate = note.ModifyDate.ToString("R").Replace(',','.'); node.tags = new string[note.Tags.Count]; for (int i = 0; i < note.Tags.Count; i++) node.tags[i] = note.Tags[i].Name; //read additional info from db var systemtags=""; using (SQLiteCommand cmd = new SQLiteCommand(sql)) { cmd.CommandText = "SELECT content, createdate, systemtags, version FROM notes WHERE id=" + note.Id; using (SQLiteDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { node.content = rdr.GetString(0); node.createdate = rdr.GetDouble(1).ToString("R").Replace(',','.');; if (!rdr.IsDBNull(2)) systemtags = rdr.GetString(2); if (!rdr.IsDBNull(3)) node.version = rdr.GetInt32(3); } } } // fill systemtags if (note.Pinned) systemtags += " pinned"; if (note.Unread) systemtags += " unread"; if (!string.IsNullOrEmpty(note.Lexer)) systemtags += " sn-lexer=" + note.Lexer; node.systemtags = systemtags.Trim().Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); var data = js.Serialize(node); var url = (string.IsNullOrEmpty(note.Key)) ? "/api2/data" : "/api2/data/"+note.Key; // create/update var s = RequestRetry(url, "POST", data); return js.Deserialize<NoteData>(s); }
/// <summary> /// delete note permanently /// </summary> internal static void delNote(NoteItem note) { RequestRetry("/api2/data/" + note.Key, "DELETE"); }