OSDN Git Service

Unicode fix for editing source HTML.
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / sql / NoteTable.java
index 6ee42cb..bd27b1d 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- * This file is part of NeverNote \r
+ * This file is part of NixNote \r
  * Copyright 2009 Randy Baumgarte\r
  * \r
  * This file may be licensed under the terms of of the\r
@@ -24,8 +24,11 @@ import java.text.DateFormat;
 import java.text.ParseException;\r
 import java.text.SimpleDateFormat;\r
 import java.util.ArrayList;\r
+import java.util.HashMap;\r
 import java.util.List;\r
 \r
+import org.apache.commons.lang.StringEscapeUtils;\r
+\r
 import com.evernote.edam.type.Note;\r
 import com.evernote.edam.type.NoteAttributes;\r
 import com.evernote.edam.type.Resource;\r
@@ -33,6 +36,7 @@ import com.evernote.edam.type.Tag;
 import com.trolltech.qt.core.QByteArray;\r
 import com.trolltech.qt.core.QDateTime;\r
 import com.trolltech.qt.core.QTextCodec;\r
+import com.trolltech.qt.gui.QPixmap;\r
 \r
 import cx.fbn.nevernote.Global;\r
 import cx.fbn.nevernote.evernote.EnmlConverter;\r
@@ -61,12 +65,11 @@ public class NoteTable {
                noteTagsTable = new NoteTagsTable(logger, db);\r
                getQueryWithContent = null;\r
                getQueryWithoutContent = null;\r
-               \r
        }\r
        // Create the table\r
        public void createTable() {\r
-               getQueryWithContent = new NSqlQuery(db.getConnection());\r
-               getQueryWithoutContent = new NSqlQuery(db.getConnection());\r
+               //getQueryWithContent = new NSqlQuery(db.getConnection());\r
+               //getQueryWithoutContent = new NSqlQuery(db.getConnection());\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
         logger.log(logger.HIGH, "Creating table Note...");\r
         if (!query.exec("Create table Note (guid varchar primary key, " +\r
@@ -83,7 +86,7 @@ public class NoteTable {
         if (!query.exec("CREATE INDEX unsynchronized_notes on note (isDirty desc, guid);"))\r
                logger.log(logger.HIGH, "note unsynchronized_notes index creation FAILED!!!");  \r
         noteTagsTable.createTable();\r
-        noteResourceTable.createTable();     \r
+//        noteResourceTable.createTable();     \r
        }\r
        // Drop the table\r
        public void dropTable() {\r
@@ -118,12 +121,17 @@ public class NoteTable {
                StringBuilder updated = new StringBuilder(simple.format(n.getUpdated()));                       \r
                StringBuilder deleted = new StringBuilder(simple.format(n.getDeleted()));\r
 \r
-               EnmlConverter enml = new EnmlConverter(logger);\r
+               \r
                \r
                query.bindValue(":guid", n.getGuid());\r
                query.bindValue(":updateSequenceNumber", n.getUpdateSequenceNum());\r
                query.bindValue(":title", n.getTitle());\r
-               query.bindValue(":content", enml.fixEnXMLCrap(enml.fixEnMediaCrap(n.getContent())));\r
+               if (isDirty) {\r
+                       EnmlConverter enml = new EnmlConverter(logger);\r
+                       query.bindValue(":content", enml.fixEnXMLCrap(enml.fixEnMediaCrap(n.getContent())));\r
+               }\r
+               else\r
+                       query.bindValue(":content", n.getContent());\r
                query.bindValue(":contentHash", n.getContentHash());\r
                query.bindValue(":contentLength", n.getContentLength());\r
                query.bindValue(":created", created.toString());\r
@@ -160,43 +168,51 @@ public class NoteTable {
        } \r
        // Setup queries for get to save time later\r
        private void prepareQueries() {\r
-               getQueryWithContent = new NSqlQuery(db.getConnection());\r
-               getQueryWithoutContent = new NSqlQuery(db.getConnection());\r
-               getAllQueryWithoutContent = new NSqlQuery(db.getConnection());\r
-               \r
-               if (!getQueryWithContent.prepare("Select "\r
-                               +"guid, updateSequenceNumber, title, "\r
-                               +"created, updated, deleted, active, notebookGuid, "\r
-                               +"attributeSubjectDate, attributeLatitude, attributeLongitude, attributeAltitude, "\r
-                               +"attributeAuthor, attributeSource, attributeSourceUrl, attributeSourceApplication, "\r
-                               +"content, contentHash, contentLength"\r
-                               +" from Note where guid=:guid and isExpunged=false")) {\r
-                                       logger.log(logger.EXTREME, "Note SQL select prepare with content has failed.");\r
-                                       logger.log(logger.MEDIUM, getQueryWithContent.lastError());\r
+               if (getQueryWithContent == null) {\r
+                       getQueryWithContent = new NSqlQuery(db.getConnection());\r
+                       if (!getQueryWithContent.prepare("Select "\r
+                                       +"guid, updateSequenceNumber, title, "\r
+                                       +"created, updated, deleted, active, notebookGuid, "\r
+                                       +"attributeSubjectDate, attributeLatitude, attributeLongitude, attributeAltitude, "\r
+                                       +"attributeAuthor, attributeSource, attributeSourceUrl, attributeSourceApplication, "\r
+                                       +"content, contentHash, contentLength"\r
+                                       +" from Note where guid=:guid and isExpunged=false")) {\r
+                                               logger.log(logger.EXTREME, "Note SQL select prepare with content has failed.");\r
+                                               logger.log(logger.MEDIUM, getQueryWithContent.lastError());\r
+                       }\r
                }\r
                \r
-               if (!getQueryWithoutContent.prepare("Select "\r
-                               +"guid, updateSequenceNumber, title, "\r
-                               +"created, updated, deleted, active, notebookGuid, "\r
-                               +"attributeSubjectDate, attributeLatitude, attributeLongitude, attributeAltitude, "\r
-                               +"attributeAuthor, attributeSource, attributeSourceUrl, attributeSourceApplication "\r
-                               +" from Note where guid=:guid and isExpunged=false")) {\r
-                                       logger.log(logger.EXTREME, "Note SQL select prepare without content has failed.");\r
-                                       logger.log(logger.MEDIUM, getQueryWithoutContent.lastError());\r
+               if (getQueryWithoutContent == null) {\r
+                       getQueryWithoutContent = new NSqlQuery(db.getConnection());\r
+                       if (!getQueryWithoutContent.prepare("Select "\r
+                                       +"guid, updateSequenceNumber, title, "\r
+                                       +"created, updated, deleted, active, notebookGuid, "\r
+                                       +"attributeSubjectDate, attributeLatitude, attributeLongitude, attributeAltitude, "\r
+                                       +"attributeAuthor, attributeSource, attributeSourceUrl, attributeSourceApplication "\r
+                                       +" from Note where guid=:guid and isExpunged=false")) {\r
+                                               logger.log(logger.EXTREME, "Note SQL select prepare without content has failed.");\r
+                                               logger.log(logger.MEDIUM, getQueryWithoutContent.lastError());\r
+                       }\r
                }\r
-               if (!getAllQueryWithoutContent.prepare("Select "\r
+                       \r
+               if (getAllQueryWithoutContent == null) {\r
+                       getAllQueryWithoutContent = new NSqlQuery(db.getConnection());\r
+               \r
+                       if (!getAllQueryWithoutContent.prepare("Select "\r
                                +"guid, updateSequenceNumber, title, "\r
                                +"created, updated, deleted, active, notebookGuid, "\r
                                +"attributeSubjectDate, attributeLatitude, attributeLongitude, attributeAltitude, "\r
                                +"attributeAuthor, attributeSource, attributeSourceUrl, attributeSourceApplication "\r
                                +" from Note where isExpunged = false")) {\r
-                                       logger.log(logger.EXTREME, "Note SQL select prepare without content has failed.");\r
+                               logger.log(logger.EXTREME, "Note SQL select prepare without content has failed.");\r
                                        logger.log(logger.MEDIUM, getQueryWithoutContent.lastError());\r
+                       }\r
                }\r
        }\r
 \r
-       // Get a note's content in raw, binary format for the sync.\r
-       public String getNoteContentBinary(String guid) {\r
+\r
+       // Get a note's content in blob format for index.\r
+       public String getNoteContentNoUTFConversion(String guid) {\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
                query.prepare("Select content from note where guid=:guid");\r
                query.bindValue(":guid", guid);\r
@@ -240,7 +256,6 @@ public class NoteTable {
                DateFormat indfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");\r
 //             indfm = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");\r
 \r
-               \r
                Note n = new Note();\r
                NoteAttributes na = new NoteAttributes();\r
                n.setAttributes(na);\r
@@ -278,7 +293,7 @@ public class NoteTable {
                if (loadTags) {\r
                        n.setTagGuids(noteTagsTable.getNoteTags(n.getGuid()));\r
                        List<String> tagNames = new ArrayList<String>();\r
-                       TagTable tagTable = new TagTable(logger, db);\r
+                       TagTable tagTable = db.getTagTable();\r
                        for (int i=0; i<n.getTagGuids().size(); i++) {\r
                                String currentGuid = n.getTagGuids().get(i);\r
                                Tag tag = tagTable.getTag(currentGuid);\r
@@ -288,11 +303,41 @@ public class NoteTable {
                }\r
                \r
                if (loadContent) {\r
-                                               \r
                        QTextCodec codec = QTextCodec.codecForLocale();\r
                        codec = QTextCodec.codecForName("UTF-8");\r
                String unicode =  codec.fromUnicode(query.valueString(16)).toString();\r
-                       n.setContent(unicode);\r
+\r
+               // This is a hack.  Basically I need to convert HTML Entities to "normal" text, but if I\r
+               // convert the &lt; character to < it will mess up the XML parsing.  So, to get around this\r
+               // I am "bit stuffing" the &lt; to &&lt; so StringEscapeUtils doesn't unescape it.  After\r
+               // I'm done I convert it back.\r
+               StringBuffer buffer = new StringBuffer(unicode);\r
+               if (Global.enableHTMLEntitiesFix && unicode.indexOf("&#") > 0) {\r
+                       unicode = query.valueString(16);\r
+                       //System.out.println(unicode);\r
+                       //unicode = unicode.replace("&lt;", "&_lt;");\r
+                       //unicode = codec.fromUnicode(StringEscapeUtils.unescapeHtml(unicode)).toString();\r
+                       //unicode = unicode.replace("&_lt;", "&lt;");\r
+                       //System.out.println("************************");\r
+                       int j=1;\r
+                       for (int i=buffer.indexOf("&#"); i != -1 && buffer.indexOf("&#", i)>0; i=buffer.indexOf("&#",i+1)) {\r
+                               j = buffer.indexOf(";",i)+1;\r
+                               if (i<j) {\r
+                                       String entity = buffer.substring(i,j).toString();\r
+                                       int len = entity.length()-1;\r
+                                       String tempEntity = entity.substring(2, len);\r
+                                       try {\r
+                                               Integer.parseInt(tempEntity);\r
+                                               entity = codec.fromUnicode(StringEscapeUtils.unescapeHtml(entity)).toString();\r
+                                               buffer.delete(i, j);\r
+                                               buffer.insert(i, entity);\r
+                                       } catch (Exception e){ }\r
+                                       \r
+                               }\r
+                       } \r
+               } \r
+                       \r
+               n.setContent(unicode);\r
 //                     n.setContent(query.valueString(16).toString());\r
                        \r
                        String contentHash = query.valueString(17);\r
@@ -482,14 +527,16 @@ public class NoteTable {
        // Update a note's title\r
        public void updateNoteContent(String guid, String content) {\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
-               boolean check = query.prepare("Update Note set content=:content, updated=CURRENT_TIMESTAMP(), isDirty=true, indexNeeded=true " +\r
-                               " where guid=:guid");\r
+               boolean check = query.prepare("Update Note set content=:content, updated=CURRENT_TIMESTAMP(), isDirty=true, indexNeeded=true, " +\r
+                               " thumbnailneeded=true where guid=:guid");\r
                if (!check) {\r
                        logger.log(logger.EXTREME, "Update note content sql prepare has failed.");\r
                        logger.log(logger.MEDIUM, query.lastError());\r
                }\r
                \r
-               query.bindValue(":content", content);\r
+               QTextCodec codec = QTextCodec.codecForLocale();\r
+               codec = QTextCodec.codecForName("UTF-8");\r
+               query.bindValue(":content", codec.fromUnicode(content).toString());\r
                query.bindValue(":guid", guid);\r
 \r
                check = query.exec();\r
@@ -499,19 +546,6 @@ public class NoteTable {
                }\r
        }\r
 \r
-/*     \r
-       // Check a note to see if it passes the attribute selection criteria\r
-       public boolean checkAttributeSelection(Note n) {\r
-               if (Global.createdSinceFilter.check(n) &&\r
-                       Global.createdBeforeFilter.check(n) && \r
-                       Global.changedSinceFilter.check(n) &&\r
-                       Global.changedBeforeFilter.check(n) &&\r
-                       Global.containsFilter.check(this, n))\r
-                               return true;\r
-               \r
-               return false;\r
-       }\r
-*/\r
        // Delete a note\r
        public void deleteNote(String guid) {\r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
@@ -542,9 +576,9 @@ public class NoteTable {
                \r
                \r
         NSqlQuery note = new NSqlQuery(db.getConnection());\r
-        NSqlQuery resources = new NSqlQuery(db.getConnection());\r
+        NSqlQuery resources = new NSqlQuery(db.getResourceConnection());\r
         NSqlQuery tags = new NSqlQuery(db.getConnection());\r
-        NSqlQuery words = new NSqlQuery(db.getConnection());\r
+        NSqlQuery words = new NSqlQuery(db.getIndexConnection());\r
         \r
                note.prepare("Delete from Note where guid=:guid");\r
                resources.prepare("Delete from NoteResources where noteGuid=:guid");\r
@@ -569,6 +603,7 @@ public class NoteTable {
                        logger.log(logger.MEDIUM, "Note tags delete failed.");\r
                        logger.log(logger.MEDIUM, tags.lastError());\r
                }\r
+\r
                if (!words.exec()) {\r
                        logger.log(logger.MEDIUM, "Word delete failed.");\r
                        logger.log(logger.MEDIUM, words.lastError());\r
@@ -579,17 +614,25 @@ public class NoteTable {
                }\r
 \r
        }\r
+       // Purge a bunch of notes based upon the notebook\r
+       public void expungeNotesByNotebook(String notebookGuid, boolean permanentExpunge, boolean needsSync) {\r
+               List<String> notes = getNotesByNotebook(notebookGuid);\r
+               for (int i=0; i<notes.size(); i++) {\r
+                       expungeNote(notes.get(i), permanentExpunge, needsSync);\r
+               }\r
+       }\r
+\r
        // Purge a note (actually delete it instead of just marking it deleted)\r
        public void hideExpungedNote(String guid, boolean needsSync) {\r
         NSqlQuery note = new NSqlQuery(db.getConnection());\r
-        NSqlQuery resources = new NSqlQuery(db.getConnection());\r
+        NSqlQuery resources = new NSqlQuery(db.getResourceConnection());\r
         NSqlQuery tags = new NSqlQuery(db.getConnection());\r
-        NSqlQuery words = new NSqlQuery(db.getConnection());\r
+        NSqlQuery words = new NSqlQuery(db.getIndexConnection());\r
         \r
                note.prepare("Update Note set isExpunged=true where guid=:guid");\r
                resources.prepare("Delete from NoteResources where noteGuid=:guid");\r
                tags.prepare("Delete from NoteTags where noteGuid=:guid");\r
-               words.prepare("Delete from words where guid=:guid");\r
+//             words.prepare("Delete from words where guid=:guid");\r
 \r
                note.bindValue(":guid", guid);\r
                resources.bindValue(":guid", guid);\r
@@ -609,10 +652,11 @@ public class NoteTable {
                        logger.log(logger.MEDIUM, "Note tags delete failed.");\r
                        logger.log(logger.MEDIUM, tags.lastError());\r
                }\r
-               if (!words.exec()) {\r
-                       logger.log(logger.MEDIUM, "Word delete failed.");\r
-                       logger.log(logger.MEDIUM, words.lastError());\r
-               }\r
+//             System.out.println("Hiding Note: Deleting words");\r
+//             if (!words.exec()) {\r
+//                     logger.log(logger.MEDIUM, "Word delete failed.");\r
+//                     logger.log(logger.MEDIUM, words.lastError());\r
+//             }\r
                if (needsSync) {\r
                        DeletedTable deletedTable = new DeletedTable(logger, db);\r
                        deletedTable.addDeletedItem(guid, "Note");\r
@@ -624,9 +668,17 @@ public class NoteTable {
        public void expungeAllDeletedNotes() {\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
                query.exec("select guid, updateSequenceNumber from note where active = false");\r
+               List<String> guids = new ArrayList<String>();\r
+               List<Integer> usns = new ArrayList<Integer>();\r
                while (query.next()) {\r
-                       String guid = query.valueString(0);\r
+                       guids.add(query.valueString(0));\r
                        Integer usn = new Integer(query.valueString(1));\r
+                       usns.add(usn);\r
+               }\r
+               \r
+               for (int i=0; i<guids.size(); i++) {\r
+                       Integer usn = usns.get(i);\r
+                       String guid = guids.get(i);\r
                        if (usn == 0)\r
                                expungeNote(guid, true, false);\r
                        else\r
@@ -652,8 +704,11 @@ public class NoteTable {
        public void updateNoteGuid(String oldGuid, String newGuid) {\r
                boolean check;\r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
-               query.prepare("Update Note set guid=:newGuid where guid=:oldGuid");\r
+        NSqlQuery resQuery = new NSqlQuery(db.getResourceConnection());\r
+        NSqlQuery wordQuery = new NSqlQuery(db.getIndexConnection());\r
+               query.prepare("Update Note set guid=:newGuid, original_guid=:original_guid where guid=:oldGuid");\r
 \r
+               query.bindValue(":original_guid", oldGuid);\r
                query.bindValue(":newGuid", newGuid);\r
                query.bindValue(":oldGuid", oldGuid);\r
 \r
@@ -672,29 +727,35 @@ public class NoteTable {
                        logger.log(logger.MEDIUM, query.lastError());\r
                }\r
                \r
-               query.prepare("Update words set guid=:newGuid where guid=:oldGuid");\r
-               query.bindValue(":newGuid", newGuid);\r
-               query.bindValue(":oldGuid", oldGuid);\r
-               query.exec();\r
+               wordQuery.prepare("Update words set guid=:newGuid where guid=:oldGuid");\r
+               wordQuery.bindValue(":newGuid", newGuid);\r
+               wordQuery.bindValue(":oldGuid", oldGuid);\r
+               wordQuery.exec();\r
                if (!check) {\r
                        logger.log(logger.MEDIUM, "Note guid update failed for Words.");\r
-                       logger.log(logger.MEDIUM, query.lastError());\r
+                       logger.log(logger.MEDIUM, wordQuery.lastError());\r
                }\r
-               query.prepare("Update noteresources set noteguid=:newGuid where noteguid=:oldGuid");\r
-               query.bindValue(":newGuid", newGuid);\r
-               query.bindValue(":oldGuid", oldGuid);\r
-               query.exec();\r
+               resQuery.prepare("Update noteresources set noteguid=:newGuid where noteguid=:oldGuid");\r
+               resQuery.bindValue(":newGuid", newGuid);\r
+               resQuery.bindValue(":oldGuid", oldGuid);\r
+               resQuery.exec();\r
                if (!check) {\r
                        logger.log(logger.MEDIUM, "Note guid update failed for noteresources.");\r
-                       logger.log(logger.MEDIUM, query.lastError());\r
+                       logger.log(logger.MEDIUM, resQuery.lastError());\r
                }\r
        }\r
        // Update a note\r
        public void updateNote(Note n, boolean isNew) {\r
-               boolean isExpunged = isNoteExpunged(n.getGuid());\r
-               \r
-               expungeNote(n.getGuid(), !isExpunged, false);\r
+               int titleColor = getNoteTitleColor(n.getGuid());\r
+               String originalGuid = findAlternateGuid(n.getGuid());\r
+               expungeNote(n.getGuid(), true, false);\r
                addNote(n, false);\r
+               if (titleColor != -1)\r
+                       setNoteTitleColor(n.getGuid(), titleColor);\r
+               if (originalGuid != null) {\r
+                       updateNoteGuid(n.getGuid(), originalGuid);\r
+                       updateNoteGuid(originalGuid, n.getGuid());\r
+               }\r
        }\r
        // Does a note exist?\r
        public boolean exists(String guid) {\r
@@ -741,7 +802,7 @@ public class NoteTable {
                boolean check;                  \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                                        \r
-               check = query.exec("Select guid from Note where isDirty = true and isExpunged = false and notebookGuid not in (select guid from notebook where local = true)");\r
+               check = query.exec("Select guid from Note where isDirty = true and isExpunged = false and notebookGuid not in (select guid from notebook where local = true or linked = true)");\r
                if (!check) \r
                        logger.log(logger.EXTREME, "Note SQL retrieve has failed: " +query.lastError().toString());\r
                \r
@@ -760,6 +821,85 @@ public class NoteTable {
                return notes;   \r
        }\r
        // Get a list of notes that need to be updated\r
+       public List <Note> getDirtyLinkedNotes() {\r
+               String guid;\r
+               Note tempNote;\r
+               List<Note> notes = new ArrayList<Note>();\r
+               List<String> index = new ArrayList<String>();\r
+               \r
+               boolean check;                  \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.exec("Select guid from Note where isDirty = true and isExpunged = false and notebookGuid in (select guid from notebook where linked = true)");\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL retrieve has failed: " +query.lastError().toString());\r
+               \r
+               // Get a list of the notes\r
+               while (query.next()) {\r
+                       guid = new String();\r
+                       guid = query.valueString(0);\r
+                       index.add(guid); \r
+               }       \r
+               \r
+               // Start getting notes\r
+               for (int i=0; i<index.size(); i++) {\r
+                       tempNote = getNote(index.get(i), true,true,false,true,true);\r
+                       notes.add(tempNote);\r
+               }\r
+               return notes;   \r
+       }\r
+       // Get a list of notes that need to be updated\r
+       public List <Note> getDirtyLinked(String notebookGuid) {\r
+               String guid;\r
+               Note tempNote;\r
+               List<Note> notes = new ArrayList<Note>();\r
+               List<String> index = new ArrayList<String>();\r
+               \r
+               boolean check;                  \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               query.prepare("Select guid from Note where isDirty = true and isExpunged = false and notebookGuid=:notebookGuid");\r
+               query.bindValue(":notebookGuid", notebookGuid);\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL retrieve has failed getting dirty linked notes: " +query.lastError().toString());\r
+               \r
+               // Get a list of the notes\r
+               while (query.next()) {\r
+                       guid = new String();\r
+                       guid = query.valueString(0);\r
+                       index.add(guid); \r
+               }       \r
+               \r
+               // Start getting notes\r
+               for (int i=0; i<index.size(); i++) {\r
+                       tempNote = getNote(index.get(i), true,true,false,true,true);\r
+                       notes.add(tempNote);\r
+               }\r
+               return notes;   \r
+       }\r
+       // Get a list of notes that need to be updated\r
+       public List <String> getNotesByNotebook(String notebookGuid) {\r
+               List<String> notes = new ArrayList<String>();\r
+               List<String> index = new ArrayList<String>();\r
+               \r
+               boolean check;                  \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select guid from Note where notebookguid=:notebookguid");\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL retrieve has failed: " +query.lastError().toString());\r
+               query.bindValue(":notebookguid", notebookGuid);\r
+               query. exec();\r
+               \r
+               // Get a list of the notes\r
+               while (query.next()) {\r
+                       index.add(query.valueString(0)); \r
+               }       \r
+               \r
+               return notes;   \r
+       }\r
+       // Get a list of notes that need to be updated\r
        public boolean isNoteDirty(String guid) {\r
                \r
                boolean check;                  \r
@@ -788,7 +928,7 @@ public class NoteTable {
                boolean check;                  \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                                        \r
-               check = query.exec("Select guid from Note where isDirty = true");\r
+               check = query.exec("Select guid from Note where isDirty=true");\r
                if (!check) \r
                        logger.log(logger.EXTREME, "Note SQL retrieve has failed: " +query.lastError().toString());\r
                \r
@@ -830,7 +970,9 @@ public class NoteTable {
        public List<Note> getAllNotes() {\r
                List<Note> notes = new ArrayList<Note>();\r
                prepareQueries();\r
-               boolean check;                                  \r
+               boolean check;  \r
+               if (getAllQueryWithoutContent == null) \r
+                       prepareQueries();\r
         NSqlQuery query = getAllQueryWithoutContent;\r
                check = query.exec();\r
                if (!check)\r
@@ -852,7 +994,7 @@ public class NoteTable {
        // Count unsynchronized notes\r
        public int getDirtyCount() {\r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
-               query.exec("select count(*) from note where isDirty=true and isExpunged = false");\r
+               query.exec("select count(guid) from note where isDirty=true and isExpunged = false");\r
                query.next(); \r
                int returnValue = new Integer(query.valueString(0));\r
                return returnValue;\r
@@ -893,7 +1035,7 @@ public class NoteTable {
        \r
        // Update a note resource by the hash\r
        public void updateNoteResourceGuidbyHash(String noteGuid, String resGuid, String hash) {\r
-               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               NSqlQuery query = new NSqlQuery(db.getResourceConnection());\r
 /*             query.prepare("Select guid from NoteResources where noteGuid=:noteGuid and datahash=:hex");\r
                query.bindValue(":noteGuid", noteGuid);\r
                query.bindValue(":hex", hash);\r
@@ -924,6 +1066,77 @@ public class NoteTable {
                return note.replace("<div/>", "<div>&nbsp;</div>");\r
        }\r
        \r
+       // Expunge notes that we don't want to synchronize\r
+       public List<String> expungeIgnoreSynchronizedNotes(List<String> notebooks, List<String>tags, List<String> linked) {\r
+               \r
+               List<String> noteGuids = new ArrayList<String>();\r
+               for (int i=0; i<notebooks.size(); i++) {\r
+                       List<String> notes = findNotesByNotebook(notebooks.get(i));\r
+                       for (int j=0; j<notes.size(); j++) {\r
+                               if (!isNoteDirty(notes.get(j))) {\r
+                                       expungeNote(notes.get(j), true, false);\r
+                                       noteGuids.add(notes.get(j));\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               for (int i=0; i<tags.size(); i++) {\r
+                       List<String> notes = findNotesByTag(tags.get(i));\r
+                       for (int j=0; j<notes.size(); j++) {\r
+                               if (!isNoteDirty(notes.get(j))) {\r
+                                       expungeNote(notes.get(j), true, false);\r
+                                       noteGuids.add(notes.get(j));\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               for (int i=0; i<linked.size(); i++) {\r
+                       String notebookGuid = db.getLinkedNotebookTable().getNotebookGuid(linked.get(i));\r
+                       if (notebookGuid != null && !notebookGuid.trim().equals("")) {\r
+                               List<Tag> linkedTags = db.getTagTable().getTagsForNotebook(notebookGuid);\r
+                               for (int j=0; j<linkedTags.size(); j++)\r
+                                       db.getTagTable().expungeTag(linkedTags.get(j).getGuid(), false);\r
+                               \r
+                               List<String> notes = findNotesByNotebook(notebookGuid);\r
+                               for (int j=0; j<notes.size(); j++) {\r
+                                       if (!isNoteDirty(notes.get(j))) {\r
+                                               expungeNote(notes.get(j), true, false);\r
+                                               noteGuids.add(notes.get(j));\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               return noteGuids;\r
+       }\r
+       \r
+       // Find a note by its notebook\r
+       // Expunge notes that we don't want to synchronize\r
+       public List<String> findNotesByNotebook(String notebook) {\r
+               List<String> values = new ArrayList<String>();\r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               query.prepare("Select guid from note where notebookguid=:notebook");\r
+\r
+               query.bindValue(":notebook", notebook);\r
+               query.exec();\r
+               while (query.next()) {\r
+                       values.add(query.valueString(0));\r
+               }\r
+               return values;\r
+       }\r
+       \r
+       public List<String> findNotesByTag(String tag) {\r
+               List<String> values = new ArrayList<String>();\r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               query.prepare("Select distinct noteguid from notetags where tagguid=:tag");\r
+\r
+               query.bindValue(":tag", tag);\r
+               query.exec();\r
+               while (query.next()) {\r
+                       values.add(query.valueString(0));\r
+               }\r
+               return values;\r
+       }\r
+       \r
        \r
        \r
        //********************************************************************************\r
@@ -945,6 +1158,10 @@ public class NoteTable {
                        logger.log(logger.MEDIUM, "Note indexNeeded update failed.");\r
                        logger.log(logger.MEDIUM, query.lastError());\r
                } \r
+               List<Resource> r = noteResourceTable.getNoteResources(guid, false);\r
+               for (int i=0; r!= null && i<r.size(); i++) {\r
+                       noteResourceTable.setIndexNeeded(r.get(i).getGuid(), true);\r
+               }\r
        }\r
        // Set all notes to be reindexed\r
        public void reindexAllNotes() {\r
@@ -1015,12 +1232,9 @@ public class NoteTable {
                        returnValue.add(pair); \r
                }       \r
 \r
-               \r
-               \r
                return returnValue;\r
        }\r
        // Set a title color\r
-       // Reset the dirty bit\r
        public void  setNoteTitleColor(String guid, int color) {\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
                \r
@@ -1030,7 +1244,32 @@ public class NoteTable {
                if (!query.exec())\r
                        logger.log(logger.EXTREME, "Error updating title color.");\r
        }\r
+       // Get in individual note's title color\r
+       // Get the title color of all notes\r
+       public Integer getNoteTitleColor(String guid) {\r
+               List<Pair<String,Integer>> returnValue = new ArrayList<Pair<String,Integer>>();\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+        query.prepare("Select titleColor from Note where titleColor != -1 and guid=:guid");\r
+        query.bindValue(":guid", guid);\r
+               if (!query.exec())\r
+                       logger.log(logger.EXTREME, "Note SQL retrieve has failed on getNoteTitleColor(guid).");\r
 \r
+               Integer color = -1;\r
+               \r
+               // Get a list of the notes\r
+               while (query.next()) {\r
+                       Pair<String, Integer> pair = new Pair<String,Integer>();\r
+                       guid = query.valueString(0);\r
+                       color = query.valueInteger(1);\r
+                       pair.setFirst(guid);\r
+                       pair.setSecond(color);\r
+                       returnValue.add(pair); \r
+               }       \r
+\r
+               \r
+               return color;\r
+       }\r
        \r
        \r
        //**********************************************************************************\r
@@ -1097,12 +1336,117 @@ public class NoteTable {
                if (!check) \r
                        logger.log(logger.EXTREME, "Note SQL get thumbail failed: " +query.lastError().toString());\r
                // Get a list of the notes\r
-               if (query.next()) \r
-                       if (query.getBlob(0) != null)\r
-                               return new QByteArray(query.getBlob(0)); \r
+               if (query.next())  {\r
+                       try {\r
+                               if (query.getBlob(0) != null) {\r
+                                       return new QByteArray(query.getBlob(0)); \r
+                               }\r
+                       } catch (java.lang.IllegalArgumentException e) {\r
+                               return null;\r
+                       }\r
+               }\r
                return null;\r
        }\r
+       // Get all thumbnails\r
+       public HashMap<String, QPixmap> getThumbnails() {\r
+               boolean check;                  \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+        HashMap<String, QPixmap> map = new HashMap<String,QPixmap>();\r
+                                       \r
+               check = query.prepare("Select guid,thumbnail from note where thumbnailneeded=false and isExpunged=false");\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL get thumbail failed: " +query.lastError().toString());\r
+               // Get a list of the notes\r
+               while (query.next())  {\r
+                       try {\r
+                               if (query.getBlob(1) != null) {\r
+                                       QByteArray data = new QByteArray(query.getBlob(1));\r
+                                       QPixmap img = new QPixmap();\r
+                                       if (img.loadFromData(data)) {\r
+                                               img = img.scaled(Global.largeThumbnailSize);\r
+                                               map.put(query.valueString(0), img);\r
+                                       }\r
+                               }       \r
+                       } catch (java.lang.IllegalArgumentException e) {\r
+                               logger.log(logger.HIGH, "Error retrieving thumbnail " +e.getMessage());\r
+                       }\r
+               }\r
+               return map;\r
+       }\r
+       // Get a list of notes that need thumbnails\r
+       public List<String> findThumbnailsNeeded() {\r
+               \r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("select guid from note where thumbnailneeded=true and isExpunged=false and DATEDIFF('MINUTE',updated,CURRENT_TIMESTAMP)>5 limit 5");\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL findThumbnailsNeeded query failed: " +query.lastError().toString());\r
+               \r
+\r
+               // Get a list of the notes\r
+               List<String> values = new ArrayList<String>();\r
+               while (query.next()) {\r
+                       values.add(query.valueString(0)); \r
+               }\r
+\r
+               return values;  \r
+       }\r
+       // Get a count of thumbnails needed\r
+       public int getThumbnailNeededCount() {\r
+               \r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("select count(guid) from note where thumbnailneeded=true and isExpunged=false and DATEDIFF('MINUTE',updated,CURRENT_TIMESTAMP)>5 limit 2");\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL findThumbnailNeededCount query failed: " +query.lastError().toString());\r
+               \r
+               if (query.next()) {\r
+                       return query.valueInteger(0); \r
+               }\r
+\r
+               return 0;       \r
+       }\r
+\r
+       //***********************************************************************************\r
+       public String findAlternateGuid(String guid) {\r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("select guid from note where original_guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL findAlternateguid query failed: " +query.lastError().toString());\r
+               \r
+               if (query.next()) {\r
+                       return query.valueString(0); \r
+               }\r
+\r
+               return null;    \r
+       }\r
        \r
+       //* Check if a note guid exists\r
+       public boolean guidExists(String guid) {\r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("select guid from note where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL guidExists query failed: " +query.lastError().toString());\r
+               \r
+               if (query.next()) {\r
+                       return true; \r
+               }\r
+\r
+               return false;                   \r
+       }\r
        \r
        // Update a note content's hash.  This happens if a resource is edited outside of NN\r
        public void updateResourceContentHash(String guid, String oldHash, String newHash) {\r
@@ -1121,7 +1465,7 @@ public class NoteTable {
                                                 newSegment +\r
                                                 n.getContent().substring(endPos);\r
                                NSqlQuery query = new NSqlQuery(db.getConnection());\r
-                               query.prepare("update note set isdirty=true, content=:content where guid=:guid");\r
+                               query.prepare("update note set isdirty=true, thumbnailneeded=true, content=:content where guid=:guid");\r
                                query.bindValue(":content", content);\r
                                query.bindValue(":guid", n.getGuid());\r
                                query.exec();\r
@@ -1130,4 +1474,9 @@ public class NoteTable {
                        position = n.getContent().indexOf("<en-media", position+1);\r
                }\r
        }\r
+\r
 }      \r
+\r
+\r
+\r
+\r