OSDN Git Service

Add shared notebook editing & syncing logic.
authorRandy Baumgarte <randy@fbn.cx>
Wed, 15 Dec 2010 14:21:23 +0000 (09:21 -0500)
committerRandy Baumgarte <randy@fbn.cx>
Wed, 15 Dec 2010 15:17:10 +0000 (10:17 -0500)
23 files changed:
lib/evernote.jar
nevernote-osx
nevernote.bat
nevernote.sh
src/cx/fbn/nevernote/Global.java
src/cx/fbn/nevernote/NeverNote.java
src/cx/fbn/nevernote/dialog/TagAssign.java
src/cx/fbn/nevernote/filters/FilterEditorNotebooks.java [new file with mode: 0644]
src/cx/fbn/nevernote/filters/FilterEditorTags.java [new file with mode: 0644]
src/cx/fbn/nevernote/gui/BrowserWindow.java
src/cx/fbn/nevernote/gui/MainMenuBar.java
src/cx/fbn/nevernote/gui/NotebookTreeWidget.java
src/cx/fbn/nevernote/gui/TagLineEdit.java
src/cx/fbn/nevernote/gui/TagTreeWidget.java
src/cx/fbn/nevernote/sql/DatabaseConnection.java
src/cx/fbn/nevernote/sql/LinkedNotebookTable.java
src/cx/fbn/nevernote/sql/NoteTable.java
src/cx/fbn/nevernote/sql/NotebookTable.java
src/cx/fbn/nevernote/sql/SharedNotebookTable.java
src/cx/fbn/nevernote/sql/TagTable.java
src/cx/fbn/nevernote/threads/SyncRunner.java
src/cx/fbn/nevernote/utilities/ListManager.java
src/cx/fbn/nevernote/xml/NoteFormatter.java

index 11b8960..7c1cfae 100644 (file)
Binary files a/lib/evernote.jar and b/lib/evernote.jar differ
index a8f109c..f9969bf 100644 (file)
@@ -85,15 +85,31 @@ done
 # Setup environment #
 #####################
 NN_CLASSPATH=$NEVERNOTE/nevernote.jar
+
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/PDFRenderer.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/apache-mime4j-0.6.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-codec-1.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-compress-1.1.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-lang-2.4.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-logging-1.1.1.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/evernote.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/h2-1.2.136.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/httpclient-4.0.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/httpcore-4.0.1.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/httpmime-4.0.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jaxen-1.1.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jazzy.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jtidy-r938.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/libthrift.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/log4j-1.2.14.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/PDFRenderer.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-lang-2.4.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jtidy-r938.jar 
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/qtjambi-macosx-4.5.2_01.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/qtjambi-macosx-gcc-4.5.2_01.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/pdfbox-app-1.3.1.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-3.7-20101029.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-ooxml-3.7.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-ooxml-schemas-3.7-20101029.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-scratchpad-3.7-20101029.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/tika.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/xmlbeans-2.3.0.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/xsdlib-20060615.jar
 
 
 ###################
index c2ea159..dbfea29 100644 (file)
@@ -76,13 +76,32 @@ rem #####################
 rem # Setup environment #\r
 rem #####################\r
 set NN_CLASSPATH=%NEVERNOTE%nevernote.jar\r
-set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\evernote.jar\r
-set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\libthrift.jar\r
-set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\log4j-1.2.14.jar\r
-set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\h2-1.2.136.jar\r
+\r
 set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\PDFRenderer.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\apache-mime4j-0.6.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\commons-codec-1.3.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\commons-compress-1.1.jar\r
 set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\commons-lang-2.4.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\commons-logging-1.1.1.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\evernote.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\h2-1.2.136.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\httpclient-4.0.3.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\httpcore-4.0.1.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\httpmime-4.0.3.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\jaxen-1.1.3.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\jazzy.jar\r
 set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\jtidy-r938.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\libthrift.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\log4j-1.2.14.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\pdfbox-app-1.3.1.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\poi-3.7-20101029.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\poi-ooxml-3.7.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\poi-ooxml-schemas-3.7-20101029.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\poi-scratchpad-3.7-20101029.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\tika.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\xmlbeans-2.3.0.jar\r
+set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\xsdlib-20060615.jar\r
+\r
 if exist "%NEVERNOTE%lib\qtjambi-win32-4.5.2_01.jar" set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\qtjambi-win32-4.5.2_01.jar\r
 if exist "%NEVERNOTE%lib\qtjambi-win32-msvc2005-4.5.2_01.jar" set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\qtjambi-win32-msvc2005-4.5.2_01.jar\r
 if exist "%NEVERNOTE%lib\qtjambi-win64-4.5.2_01.jar" set NN_CLASSPATH=%NN_CLASSPATH%;%NEVERNOTE%lib\qtjambi-win64-4.5.2_01.jar\r
index 9ba24ea..8652ee3 100755 (executable)
@@ -80,17 +80,33 @@ done
 # Setup environment #
 #####################
 NN_CLASSPATH=$NEVERNOTE/nevernote.jar
+
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/PDFRenderer.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/apache-mime4j-0.6.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-codec-1.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-compress-1.1.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-lang-2.4.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-logging-1.1.1.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/evernote.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/h2-1.2.136.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/httpclient-4.0.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/httpcore-4.0.1.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/httpmime-4.0.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jaxen-1.1.3.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jazzy.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jtidy-r938.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/libthrift.jar
 NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/log4j-1.2.14.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/PDFRenderer.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/commons-lang-2.4.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/jtidy-r938.jar 
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/qtjambi-linux32-4.5.2_01.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/qtjambi-linux32-gcc-4.5.2_01.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/qtjambi-linux64-4.5.2_01.jar
-NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/qtjambi-linux64-gcc-4.5.2_01.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/pdfbox-app-1.3.1.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-3.7-20101029.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-ooxml-3.7.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-ooxml-schemas-3.7-20101029.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/poi-scratchpad-3.7-20101029.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/tika.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/xmlbeans-2.3.0.jar
+NN_CLASSPATH=$NN_CLASSPATH:$NEVERNOTE/lib/xsdlib-20060615.jar
+
+
 
 
 ###################
index ab17364..c7b2abe 100644 (file)
@@ -51,7 +51,7 @@ import cx.fbn.nevernote.utilities.ApplicationLogger;
 import cx.fbn.nevernote.utilities.Pair;\r
 \r
 public class Global {\r
-       public static String version = "0.94";\r
+       public static String version = "0.95";\r
     public static String username = ""; \r
     public static String password = "";     \r
     \r
index abf8534..bc58d73 100644 (file)
@@ -54,6 +54,7 @@ import com.evernote.edam.error.EDAMUserException;
 import com.evernote.edam.notestore.NoteFilter;
 import com.evernote.edam.notestore.NoteVersionId;
 import com.evernote.edam.type.Data;
+import com.evernote.edam.type.LinkedNotebook;
 import com.evernote.edam.type.Note;
 import com.evernote.edam.type.NoteAttributes;
 import com.evernote.edam.type.Notebook;
@@ -150,6 +151,8 @@ import cx.fbn.nevernote.dialog.StackNotebook;
 import cx.fbn.nevernote.dialog.TagEdit;
 import cx.fbn.nevernote.dialog.ThumbnailViewer;
 import cx.fbn.nevernote.dialog.WatchFolder;
+import cx.fbn.nevernote.filters.FilterEditorNotebooks;
+import cx.fbn.nevernote.filters.FilterEditorTags;
 import cx.fbn.nevernote.gui.AttributeTreeWidget;
 import cx.fbn.nevernote.gui.BrowserWindow;
 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
@@ -219,7 +222,9 @@ public class NeverNote extends QMainWindow{
     String                                     currentNoteGuid;                        // GUID of the current note 
     Note                                       currentNote;                            // The currently viewed note
     boolean                                    noteDirty;                                      // Has the note been changed?
-    boolean                            inkNote;                    // if this is an ink note, it is read only
+    boolean                            inkNote;                   // if this is an ink note, it is read only
+    boolean                                    readOnly;                                       // Is this note read-only?
+       
   
     ListManager                                listManager;                                    // DB runnable task
     
@@ -292,7 +297,8 @@ public class NeverNote extends QMainWindow{
     int                                saveThreadDeadCount=0;          // number of consecutive dead times for the save thread
     
     HashMap<String, String>            noteCache;                      // Cash of note content 
-    HashMap<String, Boolean>   readOnlyCache;          // List of cash notes that are read-only
+    HashMap<String, Boolean>   readOnlyCache;          // List of cashe notes that are read-only
+    HashMap<String, Boolean>   inkNoteCache;           // List of cache notes that are ink notes 
     List<String>               historyGuids;                           // GUIDs of previously viewed items
     int                                        historyPosition;                        // Position within the viewed items
     boolean                            fromHistory;                            // Is this from the history queue?
@@ -471,6 +477,7 @@ public class NeverNote extends QMainWindow{
         // Setup the browser window
         noteCache = new HashMap<String,String>();
         readOnlyCache = new HashMap<String, Boolean>();
+        inkNoteCache = new HashMap<String, Boolean>();
         browserWindow = new BrowserWindow(conn);
 
         mainLeftRightSplitter.addWidget(leftSplitter1);
@@ -534,6 +541,8 @@ public class NeverNote extends QMainWindow{
                notebookTree.setShareAction(menuBar.notebookShareAction);
                notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
                notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
+               notebookTree.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
+           notebookTree.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
                menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
 
                savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
@@ -1076,6 +1085,7 @@ public class NeverNote extends QMainWindow{
 //                     !timeFormat.equals(Global.getTimeFormat())) {
                noteCache.clear();
                readOnlyCache.clear();
+               inkNoteCache.clear();
                noteIndexUpdated(true);
 //        }
         
@@ -1451,6 +1461,11 @@ public class NeverNote extends QMainWindow{
                                        conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
                                }
                                conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
+                               if (conn.getNotebookTable().isLinked(listManager.getNotebookIndex().get(i).getGuid())) {
+                                       LinkedNotebook linkedNotebook = conn.getLinkedNotebookTable().getByNotebookGuid(listManager.getNotebookIndex().get(i).getGuid());
+                                       linkedNotebook.setShareName(edit.getNotebook());
+                                       conn.getLinkedNotebookTable().updateNotebook(linkedNotebook, true);
+                               }
                                i=listManager.getNotebookIndex().size();
                        }
                }
@@ -1681,6 +1696,7 @@ public class NeverNote extends QMainWindow{
                listManager.loadNotesIndex();
                notebookIndexUpdated();
                noteIndexUpdated(false);
+               reloadTagTree(true);
 //             noteIndexUpdated(false);
                
                // Build a list of non-closed notebooks
@@ -1961,7 +1977,8 @@ public class NeverNote extends QMainWindow{
        logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
                if (selectedTagGUIDs == null)
                        selectedTagGUIDs = new ArrayList<String>();
-//             selectedTagGUIDs.clear();  // clear out old entries
+               if (reload)
+                       listManager.reloadTagIndex();
 
                tagTree.blockSignals(true);
                if (reload) {
@@ -2502,6 +2519,7 @@ public class NeverNote extends QMainWindow{
                // This is done because we want to force a reload of
                // images.  Some images we may want to highlight the text.
                readOnlyCache.clear();
+               inkNoteCache.clear();
                noteCache.clear();
                QWebSettings.setMaximumPagesInCache(0);
                QWebSettings.setObjectCacheCapacities(0, 0, 0);
@@ -2529,6 +2547,7 @@ public class NeverNote extends QMainWindow{
                                // images.  Some images we may want to highlight the text.
                                noteCache.clear();
                                readOnlyCache.clear();
+                               inkNoteCache.clear();
                                QWebSettings.setMaximumPagesInCache(0);
                                QWebSettings.setObjectCacheCapacities(0, 0, 0);
                                
@@ -2545,6 +2564,7 @@ public class NeverNote extends QMainWindow{
        logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
        noteCache.clear();
        readOnlyCache.clear();
+       inkNoteCache.clear();
        saveNoteColumnPositions();
        saveNoteIndexWidth();
        String text = searchField.currentText();
@@ -3906,13 +3926,15 @@ public class NeverNote extends QMainWindow{
     // Get a note from Evernote (and put it in the browser)
        private void refreshEvernoteNote(boolean reload) {
                logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote");
+               
                if (Global.disableViewing) {
                        browserWindow.setEnabled(false);
                        return;
                }
                inkNote = false;
-               if (!Global.showDeleted)
-                       browserWindow.setReadOnly(false);
+               readOnly = false;
+               if (Global.showDeleted)
+                       readOnly = true;
                Global.cryptCounter =0;
                if (currentNoteGuid.equals("")) {
                        browserWindow.setReadOnly(true);
@@ -3957,25 +3979,45 @@ public class NeverNote extends QMainWindow{
 
                        if (formatter.resourceError)
                                resourceErrorMessage();
-                       inkNote = formatter.readOnly;
-                       if (inkNote)
+                       readOnly = formatter.readOnly;
+                       inkNote = formatter.inkNote;
+                       if (readOnly)
                                readOnlyCache.put(currentNoteGuid, true);
+                       if (inkNote)
+                               inkNoteCache.put(currentNoteGuid, true);
                } else {
                        logger.log(logger.HIGH, "Note content is being pulled from the cache");
                        String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(currentNoteGuid));
                        js = new QByteArray(cachedContent);
                        browser.getBrowser().setContent(js);
                        if (readOnlyCache.containsKey(currentNoteGuid))
+                                       readOnly = true;
+                       if (inkNoteCache.containsKey(currentNoteGuid))
                                        inkNote = true;
                }
                if (conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
                        thumbnailHTMLReady(currentNoteGuid, js, Global.calculateThumbnailZoom(js.toString()));
                }
 
-               
-               browser.getBrowser().page().setContentEditable(!inkNote);  // We don't allow editing of ink notes
+               if (readOnly || inkNote)
+                       browser.getBrowser().page().setContentEditable(false);  // We don't allow editing of ink notes
+               else
+                       browser.getBrowser().page().setContentEditable(true);
+               browser.setReadOnly(readOnly);
+               deleteButton.setEnabled(!readOnly);
+               tagButton.setEnabled(!readOnly);
+               menuBar.noteDelete.setEnabled(!readOnly);
+               menuBar.noteTags.setEnabled(!readOnly);
                browser.setNote(currentNote);
                
+               if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
+                       deleteButton.setEnabled(false);
+                       menuBar.notebookDeleteAction.setEnabled(false);
+               } else {
+                       deleteButton.setEnabled(true);
+                       menuBar.notebookDeleteAction.setEnabled(true);
+               }
+               
                // Build a list of non-closed notebooks
                List<Notebook> nbooks = new ArrayList<Notebook>();
                for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
@@ -3988,7 +4030,11 @@ public class NeverNote extends QMainWindow{
                                nbooks.add(listManager.getNotebookIndex().get(i));
                }
                
-               browser.setNotebookList(nbooks);
+//             browser.setNotebookList(nbooks);
+               
+               FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
+               browserWindow.setNotebookList(notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex()));
+
                browser.setTitle(currentNote.getTitle());
                browser.setTag(getTagNamesForNote(currentNote));
                browser.setAuthor(currentNote.getAttributes().getAuthor());
@@ -4000,7 +4046,12 @@ public class NeverNote extends QMainWindow{
                else
                        browser.setSubjectDate(currentNote.getCreated());
                browser.setUrl(currentNote.getAttributes().getSourceURL());
-               browser.setAllTags(listManager.getTagIndex());
+               
+//             browser.setAllTags(listManager.getTagIndex());
+               FilterEditorTags tagFilter = new FilterEditorTags(conn, logger);
+               List<Tag> tagList = tagFilter.getValidTags(currentNote);
+               browser.setAllTags(tagList);
+               
                browser.setCurrentTags(currentNote.getTagNames());
                noteDirty = false;
                scrollToGuid(currentNoteGuid);
@@ -4891,9 +4942,11 @@ public class NeverNote extends QMainWindow{
                logger.log(logger.EXTREME, "Leaving neverNote index timer");
        }
 
+       @SuppressWarnings("unused")
        private void indexStarted() {
                setMessage(tr("Indexing notes"));
        }
+       @SuppressWarnings("unused")
        private void indexComplete() {
                setMessage(tr("Index complete"));
        }
index 3152569..4b0b7e9 100644 (file)
@@ -43,7 +43,7 @@ public class TagAssign extends QDialog {
        private final List<String>              tags;\r
        private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");\r
        \r
-       public TagAssign(List<Tag> allTags, List<String> selectedTags) {\r
+       public TagAssign(List<Tag> allTags, List<String> selectedTags, boolean permitNew) {\r
                okClicked = false;\r
                tags = new ArrayList<String>();\r
                setWindowIcon(new QIcon(iconPath+"tag.png"));\r
@@ -63,6 +63,11 @@ public class TagAssign extends QDialog {
                addLayout.setStretch(0, 10);\r
                addLayout.addWidget(newTagButton);\r
                \r
+               if (!permitNew) {\r
+                       newTagButton.setVisible(false);\r
+                       newTag.setVisible(false);\r
+               }\r
+               \r
                okButton = new QPushButton();\r
                okButton.setText(tr("OK"));\r
                okButton.pressed.connect(this, "onClicked()");\r
diff --git a/src/cx/fbn/nevernote/filters/FilterEditorNotebooks.java b/src/cx/fbn/nevernote/filters/FilterEditorNotebooks.java
new file mode 100644 (file)
index 0000000..4e32354
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+package cx.fbn.nevernote.filters;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import com.evernote.edam.type.Note;\r
+import com.evernote.edam.type.Notebook;\r
+\r
+import cx.fbn.nevernote.sql.DatabaseConnection;\r
+import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+\r
+public class FilterEditorNotebooks {\r
+       DatabaseConnection conn;\r
+       ApplicationLogger logger;\r
+       \r
+       public FilterEditorNotebooks(DatabaseConnection conn, ApplicationLogger logger) {\r
+               this.logger = logger;\r
+               this.conn = conn;\r
+       }\r
+       \r
+       \r
+       public List<Notebook> getValidNotebooks(Note note, List<Notebook> notebooks) {\r
+               \r
+               List<Notebook> books = new ArrayList<Notebook>();\r
+               for (int i=0; i<notebooks.size(); i++) \r
+                       books.add(notebooks.get(i));\r
+               \r
+               // If this is a new note, it isn't tied to any particular notebook.h\r
+               if (note == null || note.getUpdateSequenceNum() == 0) {\r
+                       for (int i=books.size()-1; i>=0; i--) {\r
+                               if (conn.getNotebookTable().isReadOnly(books.get(i).getGuid()))\r
+                                       books.remove(i);\r
+                       }\r
+                       return books;\r
+               }\r
+               \r
+               boolean linked = conn.getNotebookTable().isLinked(note.getNotebookGuid());\r
+               \r
+               // If the notebook is linked, then we really only need to return the one notebookd\r
+               if (linked) {\r
+                       List<Notebook> newList = new ArrayList<Notebook>();\r
+                       for (int i=0; i<books.size(); i++) {\r
+                               if (books.get(i).getGuid().equals(note.getNotebookGuid())) {\r
+                                       newList.add(books.get(i));\r
+                                       return newList;\r
+                               }\r
+                       }\r
+               } \r
+               // If the note's notebook isn't linked, then we need to return any non-linked notebook\r
+               List<Notebook> newList = new ArrayList<Notebook>();\r
+               for (int i=0; i<books.size(); i++) {\r
+                       if (!conn.getNotebookTable().isLinked(books.get(i).getGuid())) {\r
+                               newList.add(books.get(i));\r
+                       }\r
+               }\r
+               return newList;\r
+       }\r
+\r
+}\r
diff --git a/src/cx/fbn/nevernote/filters/FilterEditorTags.java b/src/cx/fbn/nevernote/filters/FilterEditorTags.java
new file mode 100644 (file)
index 0000000..0ed9c3d
--- /dev/null
@@ -0,0 +1,55 @@
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+package cx.fbn.nevernote.filters;\r
+\r
+import java.util.List;\r
+\r
+import com.evernote.edam.type.Note;\r
+import com.evernote.edam.type.Tag;\r
+\r
+import cx.fbn.nevernote.sql.DatabaseConnection;\r
+import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+\r
+public class FilterEditorTags {\r
+       DatabaseConnection conn;\r
+       ApplicationLogger logger;\r
+       public boolean permitNew;\r
+       \r
+       public FilterEditorTags(DatabaseConnection conn, ApplicationLogger logger) {\r
+               this.logger = logger;\r
+               this.conn = conn;\r
+       }\r
+       \r
+       \r
+       public List<Tag> getValidTags(Note note) {\r
+               // Reset permit new flag\r
+               permitNew = true;\r
+               \r
+               boolean linked = conn.getNotebookTable().isLinked(note.getNotebookGuid());\r
+               \r
+               // If the notebook is linked, then we really only need to return the one notebookd\r
+               if (linked) {\r
+                       permitNew = false;\r
+                       return conn.getTagTable().getTagsForNotebook(note.getNotebookGuid());\r
+               } else\r
+                       return conn.getTagTable().getTagsForNotebook("");\r
+       }\r
+\r
+}\r
index 51ea0ea..28120fc 100644 (file)
@@ -92,6 +92,8 @@ import com.trolltech.qt.gui.QLineEdit;
 import com.trolltech.qt.gui.QListWidgetItem;\r
 import com.trolltech.qt.gui.QMatrix;\r
 import com.trolltech.qt.gui.QMessageBox;\r
+import com.trolltech.qt.gui.QPalette;\r
+import com.trolltech.qt.gui.QPalette.ColorRole;\r
 import com.trolltech.qt.gui.QPushButton;\r
 import com.trolltech.qt.gui.QShortcut;\r
 import com.trolltech.qt.gui.QTimeEdit;\r
@@ -114,6 +116,7 @@ import cx.fbn.nevernote.dialog.SpellCheck;
 import cx.fbn.nevernote.dialog.TableDialog;\r
 import cx.fbn.nevernote.dialog.TagAssign;\r
 import cx.fbn.nevernote.evernote.EnCrypt;\r
+import cx.fbn.nevernote.filters.FilterEditorTags;\r
 import cx.fbn.nevernote.signals.NoteResourceSignal;\r
 import cx.fbn.nevernote.signals.NoteSignal;\r
 import cx.fbn.nevernote.sql.DatabaseConnection;\r
@@ -568,6 +571,24 @@ public class BrowserWindow extends QWidget {
                \r
                browser.page().microFocusChanged.connect(this, "microFocusChanged()");\r
                \r
+               //Setup colors\r
+               \r
+               QPalette pal = new QPalette();\r
+               pal.setColor(ColorRole.Text, QColor.black);\r
+               titleLabel.setPalette(pal);\r
+               authorText.setPalette(pal);\r
+               authorLabel.setPalette(pal);\r
+               urlLabel.setPalette(pal);\r
+               urlText.setPalette(pal);\r
+               createdDate.setPalette(pal);\r
+               createdTime.setPalette(pal);\r
+               alteredDate.setPalette(pal);\r
+               alteredTime.setPalette(pal);\r
+               subjectDate.setPalette(pal);\r
+               subjectTime.setPalette(pal);\r
+               tagEdit.setPalette(pal);\r
+               notebookBox.setPalette(pal);\r
+               \r
                logger.log(logger.HIGH, "Browser setup complete");\r
        }\r
 \r
@@ -620,6 +641,10 @@ public class BrowserWindow extends QWidget {
                createdDate.setEnabled(!v);\r
                subjectDate.setEnabled(!v);\r
                alteredDate.setEnabled(!v);\r
+               authorText.setEnabled(!v);\r
+               createdTime.setEnabled(!v);\r
+               alteredTime.setEnabled(!v);\r
+               subjectTime.setEnabled(!v);\r
                getBrowser().setEnabled(true);\r
        }\r
        \r
@@ -1420,7 +1445,7 @@ public class BrowserWindow extends QWidget {
        // Modify a note's tags\r
        @SuppressWarnings("unused")\r
        private void modifyTags() {\r
-               TagAssign tagWindow = new TagAssign(allTags, currentTags);\r
+               TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));\r
                tagWindow.exec();\r
                if (tagWindow.okClicked()) {\r
                        currentTags.clear();\r
@@ -1496,6 +1521,20 @@ public class BrowserWindow extends QWidget {
                        if (!newTagArray[i].trim().equals(""))\r
                                newTagList.add(newTagArray[i]);\r
 \r
+               if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {\r
+                       for (int i=newTagList.size()-1; i>=0; i--) {\r
+                               boolean found = false;\r
+                               for (int j=0; j<allTags.size(); j++) {\r
+                                       if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {\r
+                                               found = true;\r
+                                               j=allTags.size();\r
+                                       }\r
+                               }\r
+                               if (!found)\r
+                                       newTagList.remove(i);\r
+                       }\r
+               }\r
+\r
                // Let's cleanup the appearance of the tag list\r
                Collections.sort(newTagList);\r
                String newDisplay = "";\r
@@ -1632,6 +1671,13 @@ public class BrowserWindow extends QWidget {
                for (int i = 0; i < notebookList.size(); i++) {\r
                        if (n.equals(notebookList.get(i).getName())) {\r
                                if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {\r
+                                       String guid = conn.getNotebookTable().findNotebookByName(n);\r
+                                       if (conn.getNotebookTable().isLinked(guid)) {\r
+                                               tagEdit.setText("");\r
+                                               noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());\r
+                                               FilterEditorTags t = new FilterEditorTags(conn, logger);\r
+                                               setAllTags(t.getValidTags(currentNote));\r
+                                       }\r
                                        currentNote.setNotebookGuid(notebookList.get(i).getGuid());\r
                                        changed = true;\r
                                }\r
index 4cd82f4..39ede05 100644 (file)
@@ -454,6 +454,7 @@ public class MainMenuBar extends QMenuBar {
                \r
                notebookPublishAction = new QAction(tr("Share With The World"), this);\r
                notebookPublishAction.setEnabled(false);\r
+               notebookPublishAction.setVisible(false);\r
                notebookPublishAction.triggered.connect(parent, "publishNotebook()");\r
                setupShortcut(notebookPublishAction, "File_Notebook_Publish");\r
 \r
index cd69f97..197b258 100644 (file)
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.HashMap;\r
 import java.util.List;\r
 \r
+import com.evernote.edam.type.Note;\r
 import com.evernote.edam.type.Notebook;\r
 import com.trolltech.qt.core.QByteArray;\r
 import com.trolltech.qt.core.QMimeData;\r
@@ -377,6 +378,8 @@ public class NotebookTreeWidget extends QTreeWidget {
                        return false;\r
                }\r
                \r
+               // This is really dead code.  it is the beginning of logic to create stacks by\r
+               // dragging.\r
                if (data.hasFormat("application/x-nevernote-notebook")) {\r
                        QByteArray d = data.data("application/x-nevernote-notebook");\r
                        String current = d.toString();\r
@@ -439,13 +442,29 @@ public class NotebookTreeWidget extends QTreeWidget {
                \r
                // If we are dropping a note onto a notebook\r
                if (data.hasFormat("application/x-nevernote-note")) {\r
+                       // If we are dropping onto a read-only notebook, we are done.\r
+                       if (db.getNotebookTable().isReadOnly(parent.text(2)))\r
+                                       return false;\r
+                       \r
                        QByteArray d = data.data("application/x-nevernote-note");\r
                        String s = d.toString();\r
                        String noteGuidArray[] = s.split(" ");\r
                        for (String element : noteGuidArray) {\r
-                               if (!parent.text(0).equalsIgnoreCase("All Notebooks") && \r
-                                               !parent.text(2).equalsIgnoreCase("STACK"))\r
+                               Note n = db.getNoteTable().getNote(element.trim(), false, false, false, false, true);\r
+                               \r
+                               // We  need to be sure that...\r
+                               // 1.) We are not dropping onto the "All Notebooks" stack\r
+                               // 2.) We are not dropping onto a stack\r
+                               // 3.) We are actually dropping onto a different notebook.\r
+                               if (!parent.text(2).equalsIgnoreCase("") && \r
+                                               !parent.text(2).equalsIgnoreCase(tr("STACK")) &&\r
+                                               !(n.getNotebookGuid().equalsIgnoreCase(parent.text(2))\r
+                                       )) {\r
                                        noteSignal.notebookChanged.emit(element.trim(), parent.text(2));\r
+                                       if (db.getNotebookTable().isLinked(parent.text(2))) {\r
+                                               noteSignal.tagsChanged.emit(element.trim(), new ArrayList<String>());\r
+                                       }\r
+                               }\r
                        }\r
                        return true;\r
                }\r
index 8af1664..78a6f62 100644 (file)
@@ -48,6 +48,7 @@ public class TagLineEdit extends QLineEdit {
                currentCompleterSelection = null;\r
        }\r
        \r
+\r
        public boolean hasChanged() {\r
                return changed;\r
        }\r
index c3a803d..1b215bb 100644 (file)
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.HashMap;\r
 import java.util.List;\r
 \r
+import com.evernote.edam.type.Note;\r
 import com.evernote.edam.type.Tag;\r
 import com.trolltech.qt.core.QByteArray;\r
 import com.trolltech.qt.core.QMimeData;\r
@@ -309,12 +310,23 @@ public class TagTreeWidget extends QTreeWidget {
                        sortItems(0, SortOrder.AscendingOrder);\r
                        return true;\r
                }\r
+               \r
+               // If we are dropping a note\r
                if (data.hasFormat("application/x-nevernote-note")) {\r
+                       String notebookGuid = db.getTagTable().getNotebookGuid(parent.text(2));\r
                        QByteArray d = data.data("application/x-nevernote-note");\r
                        String s = d.toString();\r
                        String noteGuidArray[] = s.split(" ");\r
                        for (String element : noteGuidArray) {\r
-                               if (!db.getNoteTable().noteTagsTable.checkNoteNoteTags(element.trim(), parent.text(2))) {\r
+                               Note n = db.getNoteTable().getNote(element.trim(), false, false, false, false, false);\r
+                               \r
+                               // Check that...\r
+                               // 1.) Check that tag isn't already assigned to that note\r
+                               // 2.) Check that that tag is valid for that notebook or the tag isn't notebook specific\r
+                               // 3.) Check that the notebook isn't read only.\r
+                               if (!db.getNoteTable().noteTagsTable.checkNoteNoteTags(element.trim(), parent.text(2)) &&\r
+                                               (notebookGuid == null || n.getNotebookGuid().equalsIgnoreCase(notebookGuid) || notebookGuid.equals("")) &&\r
+                                               !db.getNotebookTable().isReadOnly(n.getNotebookGuid())) {\r
                                        db.getNoteTable().noteTagsTable.saveNoteTag(element.trim(), parent.text(2));\r
                                        noteSignal.tagsAdded.emit(element.trim(), parent.text(2));\r
                                }\r
index 807282b..da715cd 100644 (file)
@@ -152,17 +152,25 @@ public class DatabaseConnection {
                        executeSql("alter table notebook add column stack varchar");
                        executeSql("alter table notebook add column icon blob");
                        executeSql("alter table notebook add column readOnly boolean");
+                       executeSql("alter table notebook add column linked boolean");
+                       
+                       executeSql("alter table tag add column realname varchar");
+                       executeSql("alter table tag add column linked boolean");
                        executeSql("alter table tag add column icon blob");
+                       executeSql("alter table tag add column notebookguid varchar");
                        executeSql("alter table SavedSearch add column icon blob");
 
                        executeSql("create index NOTE_THUMBNAIL_INDEX on note (thumbnailneeded, guid);");
                        executeSql("create index NOTE_EXPUNGED_INDEX on note (isExpunged, guid);");
                        executeSql("create index NOTE_DUEDATE_INDEX on note (attributeSubjectDate, guid);");
                        executeSql("create index RESOURCES_GUID_INDEX on noteresources (noteGuid, guid);");
+                       executeSql("create index TAG_NOTEBOOK_INDEX on tag (notebookGuid);");
+                       
                        executeSql("update note set thumbnailneeded=true, thumbnail=null;");
                        executeSql("update notebook set publishingUri='', " +
                                        "publishingAscending=false, stack='', readonly=false, publishingOrder=1, " +
-                                       "publishingPublicDescription=''");
+                                       "publishingPublicDescription='', linked=false");
+                       executeSql("update tag set linked=false, realname='', notebookguid=''");
                        
                        sharedNotebookTable.createTable();
                        linkedNotebookTable.createTable();
@@ -263,4 +271,5 @@ public class DatabaseConnection {
        public InkImagesTable getInkImagesTable() {
                return inkImagesTable;
        }
+
 }
index b5a32bb..937dca2 100644 (file)
@@ -49,9 +49,9 @@ public class LinkedNotebookTable {
                        "shareKey VarChar, " +\r
                        "uri VarChar, " +\r
                        "updateSequenceNumber Long," +\r
-                       "lastSequenceNumber Long," +\r
-                       "lastSequenceDate timestamp," +\r
-                       "icon blob, " +\r
+                       "lastSequenceNumber Integer," +\r
+                       "lastSequenceDate Long," +\r
+                       "notebookGuid VarChar," +\r
                        "isDirty boolean)"))                            \r
                logger.log(logger.HIGH, "Table LinkedNotebook creation FAILED!!!");   \r
        }\r
@@ -61,16 +61,16 @@ public class LinkedNotebookTable {
                query.exec("Drop table LinkedNotebook");\r
        }\r
        // Save an individual notebook\r
-       public void addNotebook(LinkedNotebook tempNotebook, boolean isDirty) {\r
+       public void addNotebook(LinkedNotebook tempNotebook,  boolean isDirty) {\r
                boolean check;\r
                \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                check = query.prepare("Insert Into LinkedNotebook (guid, shareName, username,  "\r
                                +"shardId, shareKey, uri, updateSequenceNumber, isDirty, lastSequenceNumber, "\r
-                               + "lastSequenceDate) "   \r
+                               + "lastSequenceDate, notebookGuid) "   \r
                                + " Values("\r
                                +":guid, :shareName, :username, "\r
-                               +":shardId, :shareKey, :uri,:usn, :isDirty, 0, '1969-12-31 19.00.00')");\r
+                               +":shardId, :shareKey, :uri,:usn, :isDirty, 0, 0, :notebookGuid)");\r
                query.bindValue(":guid", tempNotebook.getGuid());\r
                query.bindValue(":shareName", tempNotebook.getShareName());\r
                query.bindValue(":username", tempNotebook.getUsername());\r
@@ -78,6 +78,7 @@ public class LinkedNotebookTable {
                query.bindValue(":shareKey", tempNotebook.getShareKey());\r
                query.bindValue(":usn", tempNotebook.getUpdateSequenceNum());\r
                query.bindValue(":uri", tempNotebook.getUri());\r
+               query.bindValue(":notebookGuid", "");\r
                \r
                if (isDirty)\r
                        query.bindValue(":isDirty", true);\r
@@ -88,13 +89,28 @@ public class LinkedNotebookTable {
                if (!check) {\r
                        logger.log(logger.MEDIUM, "LinkedNotebook Table insert failed.");\r
                        logger.log(logger.MEDIUM, query.lastError().toString());\r
+                       return;\r
                }\r
        }\r
        // Delete the notebook based on a guid\r
        public void expungeNotebook(String id, boolean needsSync) {\r
                boolean check;\r
+               \r
+               // First, delete any tags associated with this notebook\r
+               String notebookGuid = getNotebookGuid(id);\r
+               db.getNotebookTable().deleteLinkedTags(notebookGuid);\r
+               \r
+               // Now, delete any notes associated with this notebook\r
+               List<String> notes = db.getNoteTable().getNotesByNotebook(notebookGuid);\r
+               for (int i=0; i<notes.size(); i++) {\r
+                       db.getNoteTable().expungeNote(notes.get(i), true, needsSync);\r
+               }\r
+               \r
+               // Delete the notebook record\r
+               db.getNotebookTable().expungeNotebook(notebookGuid, needsSync);\r
+               \r
+               // Finally, delete the linked notebook object itself\r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
-\r
                check = query.prepare("delete from LinkedNotebook "\r
                                +"where guid=:guid");\r
                if (!check) {\r
@@ -106,7 +122,6 @@ public class LinkedNotebookTable {
                if (!check) \r
                        logger.log(logger.MEDIUM, "LinkedNotebook delete failed.");\r
                \r
-               // Signal the parent that work needs to be done\r
                if  (needsSync) {\r
                        DeletedTable deletedTable = new DeletedTable(logger, db);\r
                        deletedTable.addDeletedItem(new Long(id).toString(), "LinkedNotebook");\r
@@ -136,8 +151,10 @@ public class LinkedNotebookTable {
                \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                check = query.prepare("Update LinkedNotebook set guid=:guid, shareName=:shareName, " +\r
-                               "username=:username, shardID=:shardID, shareKey=:shareKey, uri=:uri, updateSequenceNumber=:usn, isDirty=:isDirty");\r
+                               "username=:username, shardID=:shardID, shareKey=:shareKey, uri=:uri, updateSequenceNumber=:usn, isDirty=:isDirty "+\r
+                               "where guid=:keyGuid");\r
                query.bindValue(":guid", tempNotebook.getGuid());\r
+               query.bindValue(":keyGuid", tempNotebook.getGuid());\r
                query.bindValue(":shareName", tempNotebook.getShareName());\r
                query.bindValue(":username", tempNotebook.getUsername());\r
                query.bindValue(":shardID", tempNotebook.getShardId());\r
@@ -161,22 +178,124 @@ public class LinkedNotebookTable {
                                        \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                                        \r
-               check = query.exec("Select guid, shareName, username, shardID, shareKey uri, " +\r
+               check = query.exec("Select guid, shareName, username, shardID, shareKey, uri " +\r
                                " from LinkedNotebook");\r
                if (!check)\r
                        logger.log(logger.EXTREME, "Notebook SQL retrieve has failed.");\r
                while (query.next()) {\r
                        tempNotebook = new LinkedNotebook();\r
                        tempNotebook.setGuid(query.valueString(0));\r
-                       tempNotebook.setUsername(query.valueString(1));\r
-                       tempNotebook.setShardId(query.valueString(2));\r
-                       tempNotebook.setShareKey(query.valueString(3));\r
-                       tempNotebook.setUri(query.valueString(4));\r
+                       tempNotebook.setShareName(query.valueString(1));\r
+                       tempNotebook.setUsername(query.valueString(2));\r
+                       tempNotebook.setShardId(query.valueString(3));\r
+                       tempNotebook.setShareKey(query.valueString(4));\r
+                       tempNotebook.setUri(query.valueString(5));\r
 \r
                        index.add(tempNotebook); \r
                }       \r
                return index;\r
        }                       \r
+       // Load notebooks from the database\r
+       public LinkedNotebook getNotebook(String guid) {\r
+               LinkedNotebook tempNotebook;\r
+               boolean check;\r
+                                       \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select guid, shareName, username, shardID, shareKey, uri " +\r
+                               " from LinkedNotebook where guid=:guid");\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL retrieve notebook prepare has failed.");\r
+               query.bindValue(":guid", guid);\r
+               query.exec();\r
+               while (query.next()) {\r
+                       tempNotebook = new LinkedNotebook();\r
+                       tempNotebook.setGuid(query.valueString(0));\r
+                       tempNotebook.setShareName(query.valueString(1));\r
+                       tempNotebook.setUsername(query.valueString(2));\r
+                       tempNotebook.setShardId(query.valueString(3));\r
+                       tempNotebook.setShareKey(query.valueString(4));\r
+                       tempNotebook.setUri(query.valueString(5));\r
+                       return tempNotebook;\r
+               }       \r
+               return null;\r
+       }       \r
+       // Load notebooks from the database\r
+       public LinkedNotebook getByNotebookGuid(String guid) {\r
+               LinkedNotebook tempNotebook;\r
+               boolean check;\r
+                                       \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select guid, shareName, username, shardID, shareKey, uri " +\r
+                               " from LinkedNotebook where notebookguid=:guid");\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL retrieve notebook prepare has failed.");\r
+               query.bindValue(":guid", guid);\r
+               query.exec();\r
+               while (query.next()) {\r
+                       tempNotebook = new LinkedNotebook();\r
+                       tempNotebook.setGuid(query.valueString(0));\r
+                       tempNotebook.setShareName(query.valueString(1));\r
+                       tempNotebook.setUsername(query.valueString(2));\r
+                       tempNotebook.setShardId(query.valueString(3));\r
+                       tempNotebook.setShareKey(query.valueString(4));\r
+                       tempNotebook.setUri(query.valueString(5));\r
+                       return tempNotebook;\r
+               }       \r
+               return null;\r
+       }\r
+       // Get last sequence date for the notebook\r
+       public long getLastSequenceDate(String guid) {\r
+               boolean check;\r
+                                       \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select LastSequenceDate " \r
+                               +"from LinkedNotebook where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "LinkedNotebook SQL retrieve last sequence date has failed.");\r
+               if (query.next()) {\r
+                       return query.valueLong(0);\r
+               }       \r
+               return 0;\r
+       }                       \r
+       // Get a guid by uri\r
+       public String getNotebookGuid(String guid) {\r
+               boolean check;\r
+                                       \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select notebookGuid " \r
+                               +"from LinkedNotebook where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "LinkedNotebook SQL retrieve of notebookguid by guidhas failed.");\r
+               if (query.next()) {\r
+                       return query.valueString(0);\r
+               }       \r
+               return null;\r
+       }       \r
+       // get last sequence numeber\r
+       public int getLastSequenceNumber(String guid) {\r
+               boolean check;\r
+                                       \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select LastSequenceNumber " \r
+                               +"from LinkedNotebook where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL retrieve has failed.");\r
+               while (query.next()) {\r
+                       return query.valueInteger(0);\r
+               }       \r
+               return 0;\r
+       }                       \r
 \r
        // does a record exist?\r
        public String findNotebookByShareName(String name) {\r
@@ -193,6 +312,51 @@ public class LinkedNotebookTable {
                return val;\r
        }\r
 \r
+       // does a record exist?\r
+       public String setNotebookGuid(String shareKey, String notebookGuid) {\r
+               \r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.prepare("Update LinkedNotebook set notebookGuid=:notebookGuid where shareKey=:shareKey");\r
+               query.bindValue(":notebookGuid", notebookGuid);\r
+               query.bindValue(":shareKey", shareKey);\r
+               if (!query.exec())\r
+                       logger.log(logger.EXTREME, "Linked notebook SQL retrieve by share name has failed.");\r
+               String val = null;\r
+               if (query.next())\r
+                       val = query.valueString(0);\r
+               return val;\r
+       }\r
+       // set sync date\r
+       public String setLastSequenceDate(String guid, long date) {\r
+               \r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.prepare("Update LinkedNotebook set lastsequencedate=:date where guid=:guid");\r
+               query.bindValue(":date", date);\r
+               query.bindValue(":guid", guid);\r
+               if (!query.exec())\r
+                       logger.log(logger.EXTREME, "Linked notebook SQL retrieve by share name has failed.");\r
+               String val = null;\r
+               if (query.next())\r
+                       val = query.valueString(0);\r
+               return val;\r
+       }\r
+       // set sync number\r
+       public String setLastSequenceNumber(String guid, int number) {\r
+               \r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.prepare("Update LinkedNotebook set lastsequencenumber=:number where guid=:guid");\r
+               query.bindValue(":number", number);\r
+               query.bindValue(":guid", guid);\r
+               if (!query.exec())\r
+                       logger.log(logger.EXTREME, "Linked notebook SQL retrieve by share name has failed.");\r
+               String val = null;\r
+               if (query.next())\r
+                       val = query.valueString(0);\r
+               return val;\r
+       }\r
        \r
        // Get a list of linked notebooks that need to be updated\r
        public List<String> getDirtyGuids() {\r
@@ -200,7 +364,7 @@ public class LinkedNotebookTable {
                boolean check;  \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                                        \r
-               check = query.exec("Select id from LinkedNotebook where isDirty = true");\r
+               check = query.exec("Select guid from LinkedNotebook where isDirty = true");\r
                if (!check) \r
                        logger.log(logger.EXTREME, "LinkedNotebook SQL retrieve has failed in getdirtyIds.");\r
                while (query.next()) {\r
index 59446da..38948cc 100644 (file)
@@ -732,7 +732,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
@@ -751,6 +751,57 @@ public class NoteTable {
                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
@@ -779,7 +830,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
@@ -843,7 +894,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
@@ -1191,7 +1242,6 @@ public class NoteTable {
        }\r
 \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
                Note n = getNote(guid, true, false, false, false,false);\r
index 332c100..bf60602 100644 (file)
@@ -53,6 +53,13 @@ public class NotebookTable {
                db = d;\r
                dbName = "Notebook";\r
        }\r
+       // Constructor\r
+       public NotebookTable(ApplicationLogger l, DatabaseConnection d, String name) {\r
+               logger = l;\r
+               db = d;\r
+               dbName = name;\r
+       }\r
+\r
        // Create the table\r
        public void createTable(boolean addDefaulte) {\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
@@ -118,6 +125,10 @@ public class NotebookTable {
        }\r
        // Save an individual notebook\r
        public void addNotebook(Notebook tempNotebook, boolean isDirty, boolean local) {\r
+               addNotebook(tempNotebook, isDirty, local, false, false);\r
+       }\r
+       // Save an individual notebook\r
+       public void addNotebook(Notebook tempNotebook, boolean isDirty, boolean local, boolean linked, boolean readOnly) {\r
                boolean check;\r
                \r
                SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");\r
@@ -126,12 +137,12 @@ public class NotebookTable {
                                +"serviceCreated, serviceUpdated, published, "   \r
                                + "publishingUri, publishingOrder, publishingAscending, publishingPublicDescription, "\r
                                + "isDirty, autoEncrypt, stack, " \r
-                               + "local, archived, readOnly) Values("\r
+                               + "local, archived, readOnly, linked) Values("\r
                                +":guid, :sequence, :name, :defaultNotebook,  "\r
                                +":serviceCreated, :serviceUpdated, :published, "\r
                                +":publishingUri, :publishingOrder, :publishingAscending, :publishingPublicDescription, "\r
                                +":isDirty, :autoEncrypt, "\r
-                               +":stack, :local, false, false)");\r
+                               +":stack, :local, false, :readOnly, :linked)");\r
                query.bindValue(":guid", tempNotebook.getGuid());\r
                query.bindValue(":sequence", tempNotebook.getUpdateSequenceNum());\r
                query.bindValue(":name", tempNotebook.getName());\r
@@ -144,6 +155,8 @@ public class NotebookTable {
                query.bindValue(":serviceCreated", serviceCreated.toString());\r
                query.bindValue(":serviceUpdated", serviceCreated.toString());\r
                query.bindValue(":published",tempNotebook.isPublished());\r
+               query.bindValue(":linked", linked);\r
+               query.bindValue(":readOnly", readOnly);\r
                \r
                if (tempNotebook.isPublished() && tempNotebook.getPublishing() != null) {\r
                        Publishing p = tempNotebook.getPublishing();\r
@@ -388,10 +401,23 @@ public class NotebookTable {
                boolean returnValue = query.valueBoolean(0, false);\r
                return returnValue;\r
        }\r
+       // Check for a local/remote notebook\r
+       public boolean isNotebookLinked(String guid) {\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.prepare("Select linked from "+dbName+" where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               query.exec();\r
+               if (!query.next()) {\r
+                       return false;\r
+               }\r
+               boolean returnValue = query.valueBoolean(0, false);\r
+               return returnValue;\r
+       }\r
        public boolean isReadOnly(String guid) {\r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                \r
-               query.prepare("Select readOnly from "+dbName+" where guid=:guid and readOnly='true'");\r
+               query.prepare("Select readOnly from "+dbName+" where guid=:guid and readOnly=true");\r
                query.bindValue(":guid", guid);\r
                query.exec();\r
                if (!query.next()) {\r
@@ -441,7 +467,7 @@ public class NotebookTable {
                if (!query.exec()) {\r
                        logger.log(logger.MEDIUM, "Update WatchFolder notebook failed.");\r
                        logger.log(logger.MEDIUM, query.lastError().toString());\r
-               }               \r
+               }\r
        }\r
        // Get a list of notes that need to be updated\r
        public List <Notebook> getDirty() {\r
@@ -449,14 +475,13 @@ public class NotebookTable {
                List<Notebook> index = new ArrayList<Notebook>();\r
                boolean check;\r
                                                \r
-               \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                                        \r
                check = query.exec("Select guid, sequence, name, defaultNotebook, " +\r
                                "serviceCreated, serviceUpdated, published, stack, "+\r
                                "publishinguri, publishingascending, publishingPublicDescription, "+\r
                                "publishingOrder " +\r
-                               "from "+dbName+" where isDirty = true and local=false");\r
+                               "from "+dbName+" where isDirty=true and local=false and linked=false");\r
                if (!check) \r
                        logger.log(logger.EXTREME, dbName+" SQL retrieve has failed.");\r
                while (query.next()) {\r
@@ -467,7 +492,6 @@ public class NotebookTable {
                        tempNotebook.setName(query.valueString(2));\r
                        \r
                        DateFormat indfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");\r
-//                     indfm = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");\r
                        try {\r
                                tempNotebook.setServiceCreated(indfm.parse(query.valueString(4)).getTime());\r
                                tempNotebook.setServiceUpdated(indfm.parse(query.valueString(5)).getTime());\r
@@ -500,6 +524,14 @@ public class NotebookTable {
                }\r
                updateNotebook(notebook, isDirty);\r
        }\r
+       // This is a convience method to check if a tag exists & update/create based upon it\r
+       public void syncLinkedNotebook(Notebook notebook, boolean isDirty, boolean readOnly) {\r
+               if (!exists(notebook.getGuid())) {\r
+                       addNotebook(notebook, isDirty, false, true, readOnly);\r
+                       return;\r
+               }\r
+               updateNotebook(notebook, isDirty);\r
+       }\r
        // does a record exist?\r
        private boolean exists(String guid) {\r
                \r
@@ -525,10 +557,10 @@ public class NotebookTable {
        public void setDefaultNotebook(String guid) {\r
                NSqlQuery query = new NSqlQuery(db.getConnection());\r
                \r
-               query.prepare("Update "+dbName+" set defaultNotebook=false");\r
+               query.prepare("Update "+dbName+" set defaultNotebook=false where linked=false");\r
                if (!query.exec())\r
                        logger.log(logger.EXTREME, "Error removing default "+dbName+".");\r
-               query.prepare("Update "+dbName+" set defaultNotebook=true where guid = :guid");\r
+               query.prepare("Update "+dbName+" set defaultNotebook=true where guid=:guid where linked=false");\r
                query.bindValue(":guid", guid);\r
                if (!query.exec())\r
                        logger.log(logger.EXTREME, "Error setting default "+dbName+".");\r
@@ -748,5 +780,88 @@ public class NotebookTable {
                if (!query.exec())\r
                        logger.log(logger.EXTREME, "Error setting "+dbName+" stack.");\r
        }\r
+       // Get a notebook by uri\r
+       public String getNotebookByUri(String uri) {\r
+               boolean check;\r
+                                       \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select guid " \r
+                               +"from "+dbName+" where publishingUri=:uri");\r
+               query.bindValue(":uri", uri);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL retrieve guid by uri has failed.");\r
+               if (query.next()) {\r
+                       return query.valueString(0);\r
+               }       \r
+               return null;\r
+       }       \r
+       // Is a notebook a linked notebook?\r
+       public boolean isLinked(String guid) {\r
+               boolean check;\r
+               \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("Select guid " \r
+                               +"from "+dbName+" where guid=:guid and linked=true");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL isLinked failed.");\r
+               if (query.next()) {\r
+                       return true;\r
+               }       \r
+               return false;\r
+       }\r
+\r
+       // Given a notebook, what tags are valid for it?\r
+       public List<String> getValidLinkedTags(String guid) {\r
+               boolean check;\r
+               List<String> tags = new ArrayList<String>();\r
+               \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());                                   \r
+               check = query.prepare("select distinct tagGuid from noteTags " +\r
+                               "where noteGuid in " +\r
+                               "(SELECT guid from note where notebookguid=:guid)");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL getValidLinedTags failed.");\r
+               while (query.next()) {\r
+                       tags.add(query.valueString(0));\r
+               }       \r
+               return tags;\r
+               \r
+               \r
+       }\r
+       // Given a notebook, what tags are valid for it?\r
+       public void deleteLinkedTags(String guid) {\r
+               \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());                                   \r
+               query.prepare("select distinct tagguid from noteTags " +\r
+                               "where noteGuid in " +\r
+                               "(SELECT guid from note where notebookguid=:guid)");\r
+               query.bindValue(":guid", guid);\r
+               boolean check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL getValidLinedTags failed.");\r
+               while(query.next()) {\r
+                       db.getTagTable().expungeTag(query.valueString(0), false);\r
+               }\r
+               \r
+               \r
+               query.prepare("delete from note " +\r
+                               "where notebookguid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check)\r
+                       logger.log(logger.EXTREME, "Notebook SQL getValidLinedTags failed.");\r
+\r
+               \r
+               return;\r
+               \r
+               \r
+       }\r
 }\r
 \r
index 4a5857e..d14e34d 100644 (file)
@@ -135,6 +135,28 @@ public class SharedNotebookTable {
                        deletedTable.addDeletedItem(new Long(id).toString(), "SharedNotebook");\r
                }\r
        }\r
+       // Delete the notebook based on a id\r
+       public void expungeNotebookByGuid(String id, boolean needsSync) {\r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+\r
+               check = query.prepare("delete from SharedNotebook "\r
+                               +"where guid=:id");\r
+               if (!check) {\r
+                       logger.log(logger.EXTREME, "SharedNotebook SQL delete by notebook guid prepare has failed.");\r
+                       logger.log(logger.EXTREME, query.lastError().toString());\r
+               }\r
+               query.bindValue(":id", id);\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.MEDIUM, "SharedNotebook delete by notebook guid failed.");\r
+               \r
+               // Signal the parent that work needs to be done\r
+               if  (needsSync) {\r
+                       DeletedTable deletedTable = new DeletedTable(logger, db);\r
+                       deletedTable.addDeletedItem(new Long(id).toString(), "SharedNotebook");\r
+               }\r
+       }\r
 \r
        \r
        // Update a notebook\r
index 102e5cc..8eed134 100644 (file)
@@ -60,6 +60,39 @@ public class TagTable {
                query.exec("Drop table Tag");\r
                \r
        }\r
+       // Get tags for a specific notebook\r
+       // get all tags\r
+       public List<Tag> getTagsForNotebook(String notebookGuid) {\r
+               \r
+               Tag tempTag;\r
+               List<Tag> index = new ArrayList<Tag>();\r
+               boolean check;\r
+                                               \r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                               \r
+               check = query.prepare("Select guid, parentGuid, sequence, name"\r
+                               +" from Tag where notebookGuid=:notebookGuid");\r
+               if (!check) {\r
+                       logger.log(logger.EXTREME, "Tag SQL prepare getTagsForNotebook has failed.");\r
+                       logger.log(logger.EXTREME, query.lastError());\r
+               }\r
+               query.bindValue(":notebookGuid", notebookGuid);\r
+               query.exec();\r
+               while (query.next()) {\r
+                       tempTag = new Tag();\r
+                       tempTag.setGuid(query.valueString(0));\r
+                       if (query.valueString(1) != null)\r
+                               tempTag.setParentGuid(query.valueString(1));\r
+                       else\r
+                               tempTag.setParentGuid(null);\r
+                       int sequence = new Integer(query.valueString(2)).intValue();\r
+                       tempTag.setUpdateSequenceNum(sequence);\r
+                       tempTag.setName(query.valueString(3));\r
+                       index.add(tempTag); \r
+               }       \r
+               \r
+               return index;\r
+       }\r
        // get all tags\r
        public List<Tag> getAll() {\r
                \r
@@ -70,7 +103,7 @@ public class TagTable {
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
                                                \r
                check = query.exec("Select guid, parentGuid, sequence, name"\r
-                               +" from Tag");\r
+                               +" from Tag where notebookguid not in (select guid from notebook where archived=true)");\r
                if (!check) {\r
                        logger.log(logger.EXTREME, "Tag SQL retrieve has failed.");\r
                        logger.log(logger.EXTREME, query.lastError());\r
@@ -115,6 +148,10 @@ public class TagTable {
        }\r
        // Update a tag\r
        public void updateTag(Tag tempTag, boolean isDirty) {\r
+               updateTag(tempTag, isDirty, "");\r
+       }\r
+       // Update a tag\r
+       public void updateTag(Tag tempTag, boolean isDirty, String realName) {\r
                boolean check;\r
                \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
@@ -176,11 +213,15 @@ public class TagTable {
        }\r
        // Save a tag\r
        public void addTag(Tag tempTag, boolean isDirty) {\r
+               addTag(tempTag, isDirty, false, "", "");\r
+       }\r
+       // Save a tag\r
+       public void addTag(Tag tempTag, boolean isDirty, boolean isLinked, String realName, String notebookGuid) {\r
                boolean check;\r
                \r
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
-               check = query.prepare("Insert Into Tag (guid, parentGuid, sequence, hashCode, name, isDirty)"\r
-                               +" Values(:guid, :parentGuid, :sequence, :hashCode, :name, :isDirty)");\r
+               check = query.prepare("Insert Into Tag (guid, parentGuid, sequence, hashCode, name, isDirty, linked, realName, notebookGuid)"\r
+                               +" Values(:guid, :parentGuid, :sequence, :hashCode, :name, :isDirty, :linked, :realName, :notebookGuid)");\r
                if (!check) {\r
                        logger.log(logger.EXTREME, "Tag SQL insert prepare has failed.");\r
                        logger.log(logger.EXTREME, query.lastError());\r
@@ -191,6 +232,9 @@ public class TagTable {
                query.bindValue(":hashCode", tempTag.hashCode());\r
                query.bindValue(":name", tempTag.getName());\r
                query.bindValue(":isDirty", isDirty);\r
+               query.bindValue(":linked", isLinked);\r
+               query.bindValue(":realName", realName);\r
+               query.bindValue(":notebookGuid", notebookGuid);\r
                \r
                check = query.exec();\r
                if (!check) {\r
@@ -314,6 +358,20 @@ public class TagTable {
                        val = query.valueString(0);\r
                return val;\r
        }\r
+       // Get the linked notebook guid for this tag\r
+       public String getNotebookGuid(String guid) {\r
+               \r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.prepare("Select notebookguid from tag where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               if (!query.exec())\r
+                       logger.log(logger.EXTREME, "Tag SQL retrieve has failed.");\r
+               String val = null;\r
+               if (query.next())\r
+                       val = query.valueString(0);\r
+               return val;\r
+       }\r
        // given a guid, does the tag exist\r
        public boolean exists(String guid) {\r
                \r
@@ -327,6 +385,18 @@ public class TagTable {
                return retval;\r
        }\r
        // This is a convience method to check if a tag exists & update/create based upon it\r
+       public void syncLinkedTag(Tag tag, String notebookGuid, boolean isDirty) {\r
+               if (exists(tag.getGuid())) {\r
+                       Tag t = getTag(tag.getGuid());\r
+                       String realName = tag.getName();\r
+                       tag.setName(t.getName());\r
+                       updateTag(tag, isDirty, realName);\r
+               }\r
+               else\r
+                       addTag(tag, isDirty, true, tag.getName(), notebookGuid);\r
+       }\r
+\r
+       // This is a convience method to check if a tag exists & update/create based upon it\r
        public void syncTag(Tag tag, boolean isDirty) {\r
                if (exists(tag.getGuid()))\r
                        updateTag(tag, isDirty);\r
@@ -407,4 +477,16 @@ public class TagTable {
                return values;\r
        }\r
 \r
+       // Remove unused tags that are linked tags\r
+       public void removeUnusedLinkedTags() {\r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.exec("Delete from tag where linked=true and guid not in (select distinct tagguid from notetags);");\r
+       }\r
+       \r
+       public void cleanupTags() {\r
+               NSqlQuery query = new NSqlQuery(db.getConnection());\r
+               \r
+               query.exec("Update tag set parentguid=null where parentguid not in (select distinct guid from tag);");  \r
+       }\r
 }\r
index 912e63a..bce4fa8 100644 (file)
@@ -120,6 +120,7 @@ public class SyncRunner extends QObject implements Runnable {
            private THttpClient userStoreTrans;\r
            private TBinaryProtocol userStoreProt;\r
            private AuthenticationResult authResult;\r
+           private AuthenticationResult linkedAuthResult;\r
            private User user; \r
            private long authTimeRemaining;\r
            public long authRefreshTime;\r
@@ -346,7 +347,7 @@ public class SyncRunner extends QObject implements Runnable {
                        if (syncInkNoteImages != null) {\r
                                List<String> guids = conn.getNoteTable().noteResourceTable.findInkNotes();\r
                                for (int i=0; i<guids.size(); i++) {\r
-                                       downloadInkNoteImage(guids.get(i));\r
+                                       downloadInkNoteImage(guids.get(i), authToken);\r
                                }\r
                                conn.getSyncTable().deleteRecord("FullInkNoteImageSync");\r
                        }\r
@@ -362,6 +363,11 @@ public class SyncRunner extends QObject implements Runnable {
                                syncRemoteToLocal();\r
                        }\r
                        \r
+                       //*****************************************\r
+                       //* Sync linked/shared notebooks \r
+                       //*****************************************\r
+                       syncLinkedNotebooks();\r
+                       \r
                        if (!disableUploads) {\r
                                logger.log(logger.EXTREME, "Uploading changes");\r
                                // Synchronize remote changes\r
@@ -371,6 +377,8 @@ public class SyncRunner extends QObject implements Runnable {
                                        syncLocalTags();\r
                                if (!error)\r
                                        syncLocalNotebooks();\r
+                               if (!error)\r
+                                       syncLocalLinkedNotebooks();\r
                                if (!error) \r
                                        syncDeletedNotes();\r
                                if (!error)\r
@@ -378,6 +386,10 @@ public class SyncRunner extends QObject implements Runnable {
                                if (!error)\r
                                        syncLocalSavedSearches();\r
                        }\r
+                       \r
+                       //*****************************************\r
+                       //* End of synchronization\r
+                       //*****************************************\r
                        if (refreshNeeded)\r
                                syncSignal.refreshLists.emit();\r
                        \r
@@ -523,76 +535,84 @@ public class SyncRunner extends QObject implements Runnable {
                List<Note> notes = conn.getNoteTable().getDirty();\r
                // Sync the local notebooks with Evernote's\r
                for (int i=0; i<notes.size() && keepRunning; i++) {\r
+                       syncLocalNote(notes.get(i), authToken);\r
+               }\r
+               logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
+\r
+       }\r
+       // Sync notes with Evernote\r
+       private void syncLocalNote(Note enNote, String token) {\r
+               logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
+               status.message.emit(tr("Sending local notes."));\r
+\r
+               if (authRefreshNeeded)\r
+                       refreshConnection();\r
                        \r
-                       if (authRefreshNeeded)\r
-                               refreshConnection();\r
-                       \r
-                       Note enNote = notes.get(i);\r
-                       if (enNote.isActive()) {\r
-                               try {\r
-                                       logger.log(logger.EXTREME, "Active dirty note found - non new");\r
-                                       if (enNote.getUpdateSequenceNum() > 0) {\r
-                                               enNote = getNoteContent(enNote);\r
-                                               logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
-                                               enNote = noteStore.updateNote(authToken, enNote);\r
-                                       } else { \r
-                                               logger.log(logger.EXTREME, "Active dirty found - new note");\r
-                                               logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
-                                               String oldGuid = enNote.getGuid();\r
-                                               enNote = getNoteContent(enNote);\r
-                                               enNote = noteStore.createNote(authToken, enNote);\r
-                                               noteSignal.guidChanged.emit(oldGuid, enNote.getGuid());\r
-                                               conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid());\r
-                                       }\r
-                                       updateSequenceNumber = enNote.getUpdateSequenceNum();\r
-                                       logger.log(logger.EXTREME, "Saving note");\r
-                                       conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
-                                       List<Resource> rl = enNote.getResources();\r
-                                       logger.log(logger.EXTREME, "Getting note resources");\r
-                                       for (int j=0; j<enNote.getResourcesSize() && keepRunning; j++) {\r
-                                               Resource newRes = rl.get(j);\r
-                                               Data d = newRes.getData();\r
-                                               if (d!=null) {  \r
-                                                       logger.log(logger.EXTREME, "Calculating resource hash");\r
-                                                       String hash = byteArrayToHexString(d.getBodyHash());\r
-                                                       logger.log(logger.EXTREME, "updating resources by hash");\r
-                                                       String oldGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(enNote.getGuid(), hash);\r
-                                                       conn.getNoteTable().updateNoteResourceGuidbyHash(enNote.getGuid(), newRes.getGuid(), hash);\r
-                                                       resourceSignal.resourceGuidChanged.emit(enNote.getGuid(), oldGuid, newRes.getGuid());\r
-                                               }\r
+               if (enNote.isActive()) {\r
+                       try {\r
+                               logger.log(logger.EXTREME, "Active dirty note found - non new");\r
+                               if (enNote.getUpdateSequenceNum() > 0) {\r
+                                       enNote = getNoteContent(enNote);\r
+                                       logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
+                                       enNote = noteStore.updateNote(token, enNote);\r
+                               } else { \r
+                                       logger.log(logger.EXTREME, "Active dirty found - new note");\r
+                                       logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
+                                       String oldGuid = enNote.getGuid();\r
+                                       enNote = getNoteContent(enNote);\r
+                                       enNote = noteStore.createNote(token, enNote);\r
+                                       noteSignal.guidChanged.emit(oldGuid, enNote.getGuid());\r
+                                       conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid());\r
+                               }\r
+                               updateSequenceNumber = enNote.getUpdateSequenceNum();\r
+                               logger.log(logger.EXTREME, "Saving note");\r
+                               conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
+                               List<Resource> rl = enNote.getResources();\r
+                               logger.log(logger.EXTREME, "Getting note resources");\r
+                               for (int j=0; j<enNote.getResourcesSize() && keepRunning; j++) {\r
+                                       Resource newRes = rl.get(j);\r
+                                       Data d = newRes.getData();\r
+                                       if (d!=null) {  \r
+                                               logger.log(logger.EXTREME, "Calculating resource hash");\r
+                                               String hash = byteArrayToHexString(d.getBodyHash());\r
+                                               logger.log(logger.EXTREME, "updating resources by hash");\r
+                                               String oldGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(enNote.getGuid(), hash);\r
+                                               conn.getNoteTable().updateNoteResourceGuidbyHash(enNote.getGuid(), newRes.getGuid(), hash);\r
+                                               resourceSignal.resourceGuidChanged.emit(enNote.getGuid(), oldGuid, newRes.getGuid());\r
                                        }\r
-                                       logger.log(logger.EXTREME, "Resetting note dirty flag");\r
-                                       conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
-                                       updateSequenceNumber = enNote.getUpdateSequenceNum();\r
-                                       logger.log(logger.EXTREME, "Emitting note sequence number change");\r
-                                       conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
-\r
-                               } catch (EDAMUserException e) {\r
-                                       logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
-                                       status.message.emit(tr("Error sending local note: ")     +e.getParameter());\r
-                                       logger.log(logger.LOW, e.toString());   \r
-                                       error = true;\r
-                               } catch (EDAMSystemException e) {\r
-                                       logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);\r
-                                       status.message.emit(tr("Error: ") +e);\r
-                                       logger.log(logger.LOW, e.toString());           \r
-                                       error = true;\r
-                               } catch (EDAMNotFoundException e) {\r
-                                       logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
-                                       status.message.emit(tr("Error sending local note: ") +e);\r
-                                       logger.log(logger.LOW, e.toString());   \r
-                                       error = true;\r
-                               } catch (TException e) {\r
-                                       logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);\r
-                                       status.message.emit(tr("Error sending local note: ") +e);\r
-                                       logger.log(logger.LOW, e.toString());   \r
-                                       error = true;\r
                                }\r
+                               logger.log(logger.EXTREME, "Resetting note dirty flag");\r
+                               conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
+                               updateSequenceNumber = enNote.getUpdateSequenceNum();\r
+                               logger.log(logger.EXTREME, "Emitting note sequence number change");\r
+                               conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+\r
+                       } catch (EDAMUserException e) {\r
+                               logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
+                               status.message.emit(tr("Error sending local note: ")     +e.getParameter());\r
+                               logger.log(logger.LOW, e.toString());   \r
+                               error = true;\r
+                       } catch (EDAMSystemException e) {\r
+                               logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);\r
+                               status.message.emit(tr("Error: ") +e);\r
+                               logger.log(logger.LOW, e.toString());           \r
+                               error = true;\r
+                       } catch (EDAMNotFoundException e) {\r
+                               logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
+                               status.message.emit(tr("Error sending local note: ") +e);\r
+                               logger.log(logger.LOW, e.toString());   \r
+                               error = true;\r
+                       } catch (TException e) {\r
+                               logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);\r
+                               status.message.emit(tr("Error sending local note: ") +e);\r
+                               logger.log(logger.LOW, e.toString());   \r
+                               error = true;\r
                        }\r
                }\r
-               logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
+               logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNote");\r
 \r
        }\r
+\r
        // Sync Notebooks with Evernote\r
        private void syncLocalNotebooks() {\r
                logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks");\r
@@ -775,7 +795,43 @@ public class SyncRunner extends QObject implements Runnable {
                }\r
                logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalTags");\r
        }\r
-       // Sync Tags with Evernote\r
+       private void syncLocalLinkedNotebooks() {\r
+               logger.log(logger.HIGH, "Entering SyncRunner.syncLocalLinkedNotebooks");\r
+               \r
+               List<String> list = conn.getLinkedNotebookTable().getDirtyGuids();\r
+               for (int i=0; i<list.size(); i++) {\r
+                       LinkedNotebook book = conn.getLinkedNotebookTable().getNotebook(list.get(i));\r
+                       try {\r
+                               noteStore.updateLinkedNotebook(authToken, book);\r
+                       } catch (EDAMUserException e) {\r
+                               logger.log(logger.LOW, "*** EDAM User Excepton syncLocalLinkedNotebooks");\r
+                               status.message.emit(tr("Error: ") +e);\r
+                               logger.log(logger.LOW, e.toString());           \r
+                               error = true;\r
+                               e.printStackTrace();\r
+                       } catch (EDAMNotFoundException e) {\r
+                               logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalLinkedNotebooks");\r
+                               status.message.emit(tr("Error: ") +e);\r
+                               logger.log(logger.LOW, e.toString());           \r
+                               error = true;\r
+                               e.printStackTrace();\r
+                       } catch (EDAMSystemException e) {\r
+                               logger.log(logger.LOW, "*** EDAM System Excepton syncLocalLinkedNotebooks");\r
+                               status.message.emit(tr("Error: ") +e);\r
+                               logger.log(logger.LOW, e.toString());           \r
+                               error = true;\r
+                               e.printStackTrace();\r
+                       } catch (TException e) {\r
+                               logger.log(logger.LOW, "*** EDAM TExcepton syncLocalLinkedNotebooks");\r
+                               status.message.emit(tr("Error: ") +e);\r
+                               logger.log(logger.LOW, e.toString());           \r
+                               error = true;\r
+                               e.printStackTrace();\r
+                       }\r
+               }\r
+               logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalLinkedNotebooks");\r
+       }\r
+       // Sync Saved Searches with Evernote\r
        private void syncLocalSavedSearches() {\r
                logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
                List<SavedSearch> remoteList = new ArrayList<SavedSearch>();\r
@@ -915,52 +971,11 @@ public class SyncRunner extends QObject implements Runnable {
                        syncRemoteTags(chunk.getTags());\r
                        syncRemoteSavedSearches(chunk.getSearches());\r
                        syncRemoteNotebooks(chunk.getNotebooks());\r
-                       syncRemoteNotes(chunk.getNotes(), fullSync);\r
+                       syncRemoteNotes(chunk.getNotes(), fullSync, authToken);\r
                        syncRemoteResources(chunk.getResources());\r
                        syncRemoteLinkedNotebooks(chunk.getLinkedNotebooks());\r
+                       syncExpungedNotes(chunk);\r
                        \r
-                       // Do the local deletes\r
-                       logger.log(logger.EXTREME, "Doing local deletes");\r
-                       List<String> guid = chunk.getExpungedNotes();\r
-                       if (guid != null) {\r
-                               for (int i=0; i<guid.size() && keepRunning; i++) {\r
-                                       String notebookGuid = "";\r
-                                       Note localNote = conn.getNoteTable().getNote(guid.get(i), false, false, false, false, false);\r
-                                       if (localNote != null) {\r
-                                               conn.getNoteTable().updateNoteSequence(guid.get(i), 0);\r
-                                               notebookGuid = localNote.getNotebookGuid();\r
-                                       }\r
-                                       if (!conn.getNotebookTable().isNotebookLocal(notebookGuid)) {\r
-                                               logger.log(logger.EXTREME, "Expunging local note from database");\r
-                                               conn.getNoteTable().expungeNote(guid.get(i), true, false);\r
-                                       }\r
-                               }\r
-                       }\r
-                       guid = chunk.getExpungedNotebooks();\r
-                       if (guid != null)\r
-                               for (int i=0; i<guid.size() && keepRunning; i++) {\r
-                                       logger.log(logger.EXTREME, "Expunging local notebook from database");\r
-                                       conn.getNotebookTable().expungeNotebook(guid.get(i), false);\r
-                               }\r
-                       guid = chunk.getExpungedTags();\r
-                       if (guid != null)\r
-                               for (int i=0; i<guid.size() && keepRunning; i++) {\r
-                                       logger.log(logger.EXTREME, "Expunging tags from local database");\r
-                                       conn.getTagTable().expungeTag(guid.get(i), false);\r
-                               }\r
-                       guid = chunk.getExpungedSearches();\r
-                       if (guid != null) \r
-                               for (int i=0; i<guid.size() && keepRunning; i++) {\r
-                                       logger.log(logger.EXTREME, "Expunging saved search from local database");\r
-                                       conn.getSavedSearchTable().expungeSavedSearch(guid.get(i), false);\r
-                               }\r
-                       guid = chunk.getExpungedLinkedNotebooks();\r
-                       if (guid != null) \r
-                               for (int i=0; i<guid.size() && keepRunning; i++) {\r
-                                       logger.log(logger.EXTREME, "Expunging linked notebook from local database");\r
-                                       conn.getLinkedNotebookTable().expungeNotebook(guid.get(i), false);\r
-                               }\r
-\r
                        \r
                        // Check for more notes\r
                        if (chunk.getChunkHighUSN() <= updateSequenceNumber) \r
@@ -989,6 +1004,51 @@ public class SyncRunner extends QObject implements Runnable {
 \r
                logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal");\r
        }\r
+       // Sync expunged notes\r
+       private void syncExpungedNotes(SyncChunk chunk) {\r
+               // Do the local deletes\r
+               logger.log(logger.EXTREME, "Doing local deletes");\r
+               List<String> guid = chunk.getExpungedNotes();\r
+               if (guid != null) {\r
+                       for (int i=0; i<guid.size() && keepRunning; i++) {\r
+                               String notebookGuid = "";\r
+                               Note localNote = conn.getNoteTable().getNote(guid.get(i), false, false, false, false, false);\r
+                               if (localNote != null) {\r
+                                       conn.getNoteTable().updateNoteSequence(guid.get(i), 0);\r
+                                       notebookGuid = localNote.getNotebookGuid();\r
+                               }\r
+                               if (!conn.getNotebookTable().isNotebookLocal(notebookGuid)) {\r
+                                       logger.log(logger.EXTREME, "Expunging local note from database");\r
+                                       conn.getNoteTable().expungeNote(guid.get(i), true, false);\r
+                               }\r
+                       }\r
+               }\r
+               guid = chunk.getExpungedNotebooks();\r
+               if (guid != null)\r
+                       for (int i=0; i<guid.size() && keepRunning; i++) {\r
+                               logger.log(logger.EXTREME, "Expunging local notebook from database");\r
+                               conn.getNotebookTable().expungeNotebook(guid.get(i), false);\r
+                       }\r
+               guid = chunk.getExpungedTags();\r
+               if (guid != null)\r
+                       for (int i=0; i<guid.size() && keepRunning; i++) {\r
+                               logger.log(logger.EXTREME, "Expunging tags from local database");\r
+                               conn.getTagTable().expungeTag(guid.get(i), false);\r
+                       }\r
+               guid = chunk.getExpungedSearches();\r
+               if (guid != null) \r
+                       for (int i=0; i<guid.size() && keepRunning; i++) {\r
+                               logger.log(logger.EXTREME, "Expunging saved search from local database");\r
+                               conn.getSavedSearchTable().expungeSavedSearch(guid.get(i), false);\r
+                       }\r
+               guid = chunk.getExpungedLinkedNotebooks();\r
+               if (guid != null) \r
+                       for (int i=0; i<guid.size() && keepRunning; i++) {\r
+                               logger.log(logger.EXTREME, "Expunging linked notebook from local database");\r
+                               conn.getLinkedNotebookTable().expungeNotebook(guid.get(i), false);\r
+                       }\r
+\r
+       }\r
        // Sync remote tags\r
        private void syncRemoteTags(List<Tag> tags) {\r
                logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");\r
@@ -1019,13 +1079,13 @@ public class SyncRunner extends QObject implements Runnable {
        }\r
        // Sync remote linked notebooks\r
        private void syncRemoteLinkedNotebooks(List<LinkedNotebook> books) {\r
-               logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches");\r
+               logger.log(logger.EXTREME, "Entering SyncRunner.syncLinkedNotebooks");\r
                if (books != null) {\r
                        for (int i=0; i<books.size() && keepRunning; i++) {\r
                                conn.getLinkedNotebookTable().updateNotebook(books.get(i), false); \r
                        }\r
                }\r
-               logger.log(logger.EXTREME, "Leaving SyncRunner.syncSavedSearches");\r
+               logger.log(logger.EXTREME, "Leaving SyncRunner.syncLinkedNotebooks");\r
        }\r
        // Sync remote Notebooks 2\r
        private void syncRemoteNotebooks(List<Notebook> notebooks) {\r
@@ -1037,103 +1097,122 @@ public class SyncRunner extends QObject implements Runnable {
                                if (oldGuid != null && !conn.getNotebookTable().isNotebookLocal(oldGuid) && !notebooks.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
                                        conn.getNotebookTable().updateNotebookGuid(oldGuid, notebooks.get(i).getGuid());\r
                                conn.getNotebookTable().syncNotebook(notebooks.get(i), false); \r
+                               \r
+                               // Synchronize shared notebook information\r
+//                             if (notebooks.get(i).getSharedNotebookIdsSize() > 0) {\r
+//                                     conn.getSharedNotebookTable().expungeNotebookByGuid(notebooks.get(i).getGuid(), false);\r
+//                                     for (int j=0; j<notebooks.get(i).getSharedNotebookIdsSize(); j++) {\r
+//                                             syncRemoteSharedNotebook(notebooks.get(i).getGuid(), notebooks.get(i).getSharedNotebookIds().get(j), authToken);\r
+//                                     }\r
+//                             }\r
                        }\r
                }                       \r
                logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");\r
        }\r
+       // Sync remote shared notebook\r
+//     private void syncRemoteSharedNotebook(String guid, Long id, String token) {\r
+//             List<SharedNotebook> books = noteStore.getSharedNotebookByAuth(authToken);\r
+//     }\r
        // Sync remote Resources\r
        private void syncRemoteResources(List<Resource> resource) {\r
+               logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources");\r
+               if (resource != null) {\r
+                       for (int i=0; i<resource.size() && keepRunning; i++) {\r
+                               syncRemoteResource(resource.get(i), authToken);\r
+                       }\r
+               }\r
+               logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
+       }\r
+       // Sync remote resource\r
+       private void syncRemoteResource(Resource resource, String authToken) {\r
                // This is how the logic for this works.\r
                // 1.) If the resource is not in the local database, we add it.\r
                // 2.) If a copy of the resource is in the local database and the note isn't dirty, we update the local copy\r
                // 3.) If a copy of the resource is in the local databbase and it is dirty and the hash doesn't match, we ignore it because there\r
                //     is a conflict.  The note conflict should get a copy of the resource at that time.\r
                \r
-               logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources");\r
-               if (resource != null) {\r
-                       for (int i=0; i<resource.size() && keepRunning; i++) {\r
-                               boolean saveNeeded = false;\r
-/* #1 */               Resource r = getEvernoteResource(resource.get(i).getGuid(), true,true,true);\r
-                               Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);\r
-                               if (l == null) {\r
-                                       saveNeeded = true;\r
-                               } else {\r
-/* #2 */                       boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());\r
-                                       if (!isNoteDirty)\r
-                                               saveNeeded = true;\r
-                                       else {\r
-/* #3 */                               String remoteHash = "";\r
-                                               if (r != null && r.getData() != null && r.getData().getBodyHash() != null)\r
-                                                       remoteHash = byteArrayToHexString(r.getData().getBodyHash());\r
-                                               String localHash = "";\r
-                                               if (l != null && l.getData() != null && l.getData().getBodyHash() != null)\r
-                                                       remoteHash = byteArrayToHexString(l.getData().getBodyHash());\r
-                               \r
-                                               if (localHash.equalsIgnoreCase(remoteHash))\r
+               boolean saveNeeded = false;\r
+               /* #1 */                Resource r = getEvernoteResource(resource.getGuid(), true,true,true, authToken);\r
+                                               Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);\r
+                                               if (l == null) {\r
                                                        saveNeeded = true;\r
-                                       }\r
-                               }\r
-                               \r
-                               if (saveNeeded) \r
-                                       conn.getNoteTable().noteResourceTable.updateNoteResource(r, false);\r
-                               if (r.getMime().equalsIgnoreCase("application/vnd.evernote.ink"))\r
-                                       downloadInkNoteImage(r.getGuid());\r
+                                               } else {\r
+               /* #2 */                        boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());\r
+                                                       if (!isNoteDirty)\r
+                                                               saveNeeded = true;\r
+                                                       else {\r
+               /* #3 */                                String remoteHash = "";\r
+                                                               if (r != null && r.getData() != null && r.getData().getBodyHash() != null)\r
+                                                                       remoteHash = byteArrayToHexString(r.getData().getBodyHash());\r
+                                                               String localHash = "";\r
+                                                               if (l != null && l.getData() != null && l.getData().getBodyHash() != null)\r
+                                                                       remoteHash = byteArrayToHexString(l.getData().getBodyHash());\r
+                                               \r
+                                                               if (localHash.equalsIgnoreCase(remoteHash))\r
+                                                                       saveNeeded = true;\r
+                                                       }\r
+                                               }\r
+                                               \r
+                                               if (saveNeeded) \r
+                                                       conn.getNoteTable().noteResourceTable.updateNoteResource(r, false);\r
+                                               if (r.getMime().equalsIgnoreCase("application/vnd.evernote.ink"))\r
+                                                       downloadInkNoteImage(r.getGuid(), authToken);\r
 \r
-                       }\r
-               }\r
-               logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
        }\r
        // Sync remote notes\r
-       private void syncRemoteNotes(List<Note> note, boolean fullSync) {\r
+       private void syncRemoteNotes(List<Note> note, boolean fullSync, String token) {\r
                logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes");\r
                if (note != null) {\r
                        for (int i=0; i<note.size() && keepRunning; i++) {\r
-                               Note n = getEvernoteNote(note.get(i).getGuid(), true, fullSync, true,true);\r
-                               if (n!=null) {\r
-                                       \r
-                                       // Basically, this is how the sync logic for a note works.\r
-                                       // If the remote note has changed and the local has not, we\r
-                                       // accept the change.\r
-                                       // If both the local & remote have changed but the sequence\r
-                                       // numbers are the same, we don't accept the change.  This\r
-                                       // seems to happen when attachments are indexed by the server.\r
-                                       // If both the local & remote have changed and the sequence numbers\r
-                                       // are different we move the local copy to a local notebook (making sure\r
-                                       // to copy all resources) and we accept the new one.                    \r
-                                       boolean conflictingNote = true;\r
-                                       logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid());\r
-                                       if (dirtyNoteGuids.contains(n.getGuid())) { \r
-                                               logger.log(logger.EXTREME, "Conflict check beginning");\r
-                                               conflictingNote = checkForConflict(n);\r
-                                               logger.log(logger.EXTREME, "Conflict check results " +conflictingNote);\r
-                                               if (conflictingNote)\r
-                                                       moveConflictingNote(n.getGuid());\r
-                                       }\r
-                                       if (conflictingNote || fullSync) {\r
-                                               logger.log(logger.EXTREME, "Saving Note");\r
-                                               conn.getNoteTable().syncNote(n, false);\r
-                                               noteSignal.noteChanged.emit(n.getGuid(), null);   // Signal to ivalidate note cache\r
-                                               noteSignal.noteDownloaded.emit(n, true);                // Signal to add note to index\r
-                                               logger.log(logger.EXTREME, "Note Saved");\r
-                                               if (fullSync && n.getResources() != null) {\r
-                                                       for (int q=0; q<n.getResources().size() && keepRunning; q++) {\r
-                                                               logger.log(logger.EXTREME, "Getting note resources.");\r
-                                                               conn.getNoteTable().noteResourceTable.updateNoteResource(n.getResources().get(q), false);\r
-                                                               if (n.getResources().get(q).getMime().equalsIgnoreCase("application/vnd.evernote.ink"))\r
-                                                                       downloadInkNoteImage(n.getResources().get(q).getGuid());\r
-                                                       }\r
-                                               }\r
+                               Note n = getEvernoteNote(note.get(i).getGuid(), true, fullSync, true,true, token);\r
+                               syncRemoteNote(n, fullSync, token);\r
+                       }\r
+               }\r
+               logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotes");\r
+       }\r
+       private void syncRemoteNote(Note n, boolean fullSync, String token) {\r
+               if (n!=null) {\r
+                       \r
+                       // Basically, this is how the sync logic for a note works.\r
+                       // If the remote note has changed and the local has not, we\r
+                       // accept the change.\r
+                       // If both the local & remote have changed but the sequence\r
+                       // numbers are the same, we don't accept the change.  This\r
+                       // seems to happen when attachments are indexed by the server.\r
+                       // If both the local & remote have changed and the sequence numbers\r
+                       // are different we move the local copy to a local notebook (making sure\r
+                       // to copy all resources) and we accept the new one.                    \r
+                       boolean conflictingNote = true;\r
+                       logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid());\r
+                       if (dirtyNoteGuids != null && dirtyNoteGuids.contains(n.getGuid())) { \r
+                               logger.log(logger.EXTREME, "Conflict check beginning");\r
+                               conflictingNote = checkForConflict(n);\r
+                               logger.log(logger.EXTREME, "Conflict check results " +conflictingNote);\r
+                               if (conflictingNote)\r
+                                       moveConflictingNote(n.getGuid());\r
+                       }\r
+                       if (conflictingNote || fullSync) {\r
+                               logger.log(logger.EXTREME, "Saving Note");\r
+                               conn.getNoteTable().syncNote(n, false);\r
+                               noteSignal.noteChanged.emit(n.getGuid(), null);   // Signal to ivalidate note cache\r
+                               noteSignal.noteDownloaded.emit(n, true);                // Signal to add note to index\r
+                                       logger.log(logger.EXTREME, "Note Saved");\r
+                               if (fullSync && n.getResources() != null) {\r
+                                       for (int q=0; q<n.getResources().size() && keepRunning; q++) {\r
+                                               logger.log(logger.EXTREME, "Getting note resources.");\r
+                                               conn.getNoteTable().noteResourceTable.updateNoteResource(n.getResources().get(q), false);\r
+                                               if (n.getResources().get(q).getMime().equalsIgnoreCase("application/vnd.evernote.ink"))\r
+                                                       downloadInkNoteImage(n.getResources().get(q).getGuid(), token);\r
                                        }\r
                                }\r
                        }\r
                }\r
-               logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotes");\r
        }\r
-       private Note getEvernoteNote(String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData) { \r
+       private Note getEvernoteNote(String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData, String token) { \r
                Note n = null;\r
                try {\r
                        logger.log(logger.EXTREME, "Retrieving note " +guid);\r
-                       n = noteStore.getNote(authToken, guid, withContent, withResourceData, withResourceRecognition, withResourceAlternateData);\r
+                       n = noteStore.getNote(token, guid, withContent, withResourceData, withResourceRecognition, withResourceAlternateData);\r
                        logger.log(logger.EXTREME, "Note " +guid +" has been retrieved.");\r
                } catch (EDAMUserException e) {\r
                        logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");\r
@@ -1158,11 +1237,11 @@ public class SyncRunner extends QObject implements Runnable {
                }\r
                return n;\r
        }\r
-       private Resource getEvernoteResource(String guid, boolean withData, boolean withRecognition, boolean withAttributes) { \r
+       private Resource getEvernoteResource(String guid, boolean withData, boolean withRecognition, boolean withAttributes, String token) { \r
                Resource n = null;\r
                try {\r
                        logger.log(logger.EXTREME, "Retrieving resource " +guid);\r
-                       n = noteStore.getResource(authToken, guid, withData, withRecognition, withAttributes, withAttributes);\r
+                       n = noteStore.getResource(token, guid, withData, withRecognition, withAttributes, withAttributes);\r
                        logger.log(logger.EXTREME, "Resource " +guid +" has been retrieved.");\r
                } catch (EDAMUserException e) {\r
                        logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");\r
@@ -1263,7 +1342,7 @@ public class SyncRunner extends QObject implements Runnable {
                noteSignal.guidChanged.emit(guid,newGuid);\r
        }\r
        \r
-       \r
+\r
 \r
        \r
        //******************************************************\r
@@ -1350,7 +1429,6 @@ public class SyncRunner extends QObject implements Runnable {
                \r
            boolean versionOk = false;\r
                try {\r
-//                     versionOk = userStore.checkVersion("Dave's EDAMDemo (Java)", \r
                        versionOk = userStore.checkVersion("NeverNote", \r
                    com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, \r
                      com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR);\r
@@ -1579,7 +1657,7 @@ public class SyncRunner extends QObject implements Runnable {
     }\r
 \r
     \r
-    private void downloadInkNoteImage(String guid) {\r
+    private void downloadInkNoteImage(String guid, String authToken) {\r
                String urlBase = noteStoreUrl.replace("/edam/note/", "/shard/") + "/res/"+guid+".ink?slice=";\r
 //             urlBase = "https://www.evernote.com/shard/s1/res/52b567a9-54ae-4a08-afc5-d5bae275b2a8.ink?slice=";\r
                Integer slice = 1;\r
@@ -1645,4 +1723,181 @@ public class SyncRunner extends QObject implements Runnable {
            return data;\r
     }\r
     \r
+    \r
+       //******************************************\r
+       //* Begin syncing shared notebooks \r
+       //******************************************\r
+    private void syncLinkedNotebooks() {\r
+       logger.log(logger.MEDIUM, "Authenticating Shared Notebooks");\r
+       status.message.emit(tr("Synchronizing shared notebooks."));\r
+       List<LinkedNotebook> books = conn.getLinkedNotebookTable().getAll();\r
+       for (int i=0; i<books.size(); i++) {\r
+               try {\r
+                       long lastSyncDate = conn.getLinkedNotebookTable().getLastSequenceDate(books.get(i).getGuid());\r
+                       int lastSequenceNumber = conn.getLinkedNotebookTable().getLastSequenceNumber(books.get(i).getGuid());\r
+                       linkedAuthResult = noteStore.authenticateToSharedNotebook(books.get(i).getShareKey(), authToken);\r
+                       SyncState linkedSyncState = \r
+                               noteStore.getLinkedNotebookSyncState(linkedAuthResult.getAuthenticationToken(), books.get(i));\r
+                       if (linkedSyncState.getUpdateCount() > lastSequenceNumber) {\r
+                               if (lastSyncDate < linkedSyncState.getFullSyncBefore()) {\r
+                                       lastSequenceNumber = 0;\r
+                               }\r
+                                       syncLinkedNotebook(books.get(i), lastSequenceNumber, linkedSyncState.getUpdateCount());\r
+                       }\r
+                       \r
+                       // Synchronize local changes\r
+                       syncLocalLinkedNoteChanges(books.get(i));\r
+                               \r
+               } catch (EDAMUserException e) {\r
+                       // TODO Auto-generated catch block\r
+                       e.printStackTrace();\r
+               } catch (EDAMNotFoundException e) {\r
+                       status.message.emit(tr("Error synchronizing \" " +\r
+                                       books.get(i).getShareName()+"\". Please verify you still have access to that shared notebook."));\r
+                       error = true;\r
+                       e.printStackTrace();\r
+               } catch (EDAMSystemException e) {\r
+                       // TODO Auto-generated catch block\r
+                       e.printStackTrace();\r
+               } catch (TException e) {\r
+                       // TODO Auto-generated catch block\r
+                       e.printStackTrace();\r
+               }\r
+       }\r
+       \r
+       // Cleanup tags\r
+       conn.getTagTable().removeUnusedLinkedTags();\r
+       conn.getTagTable().cleanupTags();\r
+       tagSignal.listChanged.emit();\r
+       }\r
+\r
+    \r
+    //**************************************************************\r
+    //* Linked notebook contents (from someone else's account)\r
+    //*************************************************************\r
+       private void syncLinkedNotebook(LinkedNotebook book, int usn, int highSequence) {\r
+               boolean fullSync = false;\r
+               if (usn == 0)\r
+                       fullSync = true;\r
+               while (usn < highSequence) {\r
+                       try {\r
+                               SyncChunk chunk = \r
+                                       noteStore.getLinkedNotebookSyncChunk(authToken, book, usn, 10, fullSync);\r
+//                                     noteStore.getLinkedNotebookSyncChunk(linkedAuthResult.getAuthenticationToken(), book, usn, 10, fullSync);\r
+\r
+                               syncRemoteNotes(chunk.getNotes(), fullSync, linkedAuthResult.getAuthenticationToken());\r
+                               findNewLinkedTags(chunk.getNotes(), linkedAuthResult.getAuthenticationToken());\r
+                               for (int i=0; i<chunk.getResourcesSize(); i++) {\r
+                                       syncRemoteResource(chunk.getResources().get(i), linkedAuthResult.getAuthenticationToken());\r
+                               }\r
+                               syncRemoteLinkedNotebooks(chunk.getNotebooks(), false, book);\r
+//                             String notebookGuid = conn.getLinkedNotebookTable().getNotebookGuid(book.getGuid());\r
+                               SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());\r
+                               syncLinkedTags(chunk.getTags(), s.getNotebookGuid());\r
+                               \r
+                               \r
+                               // Expunge records\r
+                               for (int i=0; i<chunk.getExpungedLinkedNotebooksSize(); i++) {\r
+                                       conn.getLinkedNotebookTable().expungeNotebook(chunk.getExpungedLinkedNotebooks().get(i), false);\r
+                               }\r
+                               usn = chunk.getChunkHighUSN();\r
+                               conn.getLinkedNotebookTable().setLastSequenceDate(book.getGuid(),chunk.getCurrentTime());\r
+                               conn.getLinkedNotebookTable().setLastSequenceNumber(book.getGuid(),chunk.getChunkHighUSN());\r
+                       } catch (EDAMUserException e) {\r
+                               // TODO Auto-generated catch block\r
+                               e.printStackTrace();\r
+                       } catch (EDAMSystemException e) {\r
+                               // TODO Auto-generated catch block\r
+                               e.printStackTrace();\r
+                       } catch (EDAMNotFoundException e) {\r
+                               // TODO Auto-generated catch block\r
+                               e.printStackTrace();\r
+                       } catch (TException e) {\r
+                               // TODO Auto-generated catch block\r
+                               e.printStackTrace();\r
+                       }\r
+               }\r
+       }\r
+       // Sync remote tags\r
+       private void syncLinkedTags(List<Tag> tags, String notebookGuid) {\r
+               logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");\r
+               if (tags != null) {\r
+                       for (int i=0; i<tags.size() && keepRunning; i++) {\r
+                               conn.getTagTable().syncLinkedTag(tags.get(i), notebookGuid, false);\r
+                       }\r
+               }\r
+               logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");\r
+       }\r
+       \r
+       // Sync notebooks from a linked notebook\r
+       private void syncRemoteLinkedNotebooks(List<Notebook> notebooks, boolean readOnly, LinkedNotebook linked) {\r
+               logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");\r
+               if (notebooks != null) {\r
+                       for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
+                               try {\r
+                                       SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());\r
+                                       conn.getLinkedNotebookTable().setNotebookGuid(s.getShareKey(), s.getNotebookGuid());\r
+                                       readOnly = !s.isNotebookModifiable();\r
+                                       notebooks.get(i).setName(linked.getShareName());\r
+                                       notebooks.get(i).setDefaultNotebook(false);\r
+                                       conn.getNotebookTable().syncLinkedNotebook(notebooks.get(i), false, readOnly); \r
+                               } catch (EDAMUserException e) {\r
+                                       readOnly = true;\r
+                                       e.printStackTrace();\r
+                               } catch (EDAMNotFoundException e) {\r
+                                       readOnly = true;\r
+                                       e.printStackTrace();\r
+                               } catch (EDAMSystemException e) {\r
+                                       readOnly = true;\r
+                                       e.printStackTrace();\r
+                               } catch (TException e) {\r
+                                       readOnly = true;\r
+                                       e.printStackTrace();\r
+                               }\r
+\r
+                       }\r
+               }                       \r
+               logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");\r
+       }\r
+\r
+       private void findNewLinkedTags(List<Note> newNotes, String token) {\r
+               if (newNotes == null)\r
+                       return;\r
+               for (int i=0; i<newNotes.size(); i++) {\r
+                       Note n = newNotes.get(i);\r
+                       for (int j=0; j<n.getTagGuidsSize(); j++) {\r
+                               String tag = n.getTagGuids().get(j);\r
+                               if (!conn.getTagTable().exists(tag)) {\r
+                                       Tag newTag;\r
+                                       try {\r
+                                               newTag = noteStore.getTag(token, tag);\r
+                                               conn.getTagTable().addTag(newTag, false);\r
+                                       } catch (EDAMUserException e) {\r
+                                               // TODO Auto-generated catch block\r
+                                               e.printStackTrace();\r
+                                       } catch (EDAMSystemException e) {\r
+                                               // TODO Auto-generated catch block\r
+                                               e.printStackTrace();\r
+                                       } catch (EDAMNotFoundException e) {\r
+                                               // TODO Auto-generated catch block\r
+                                               e.printStackTrace();\r
+                                       } catch (TException e) {\r
+                                               // TODO Auto-generated catch block\r
+                                               e.printStackTrace();\r
+                                       }\r
+                                       \r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Synchronize changes locally done to linked notes\r
+       private void syncLocalLinkedNoteChanges(LinkedNotebook book) {\r
+               String notebookGuid = conn.getLinkedNotebookTable().getNotebookGuid(book.getGuid());\r
+               List<Note> notes = conn.getNoteTable().getDirtyLinked(notebookGuid);\r
+               for (int i=0; i<notes.size(); i++) {\r
+                       syncLocalNote(notes.get(i), linkedAuthResult.getAuthenticationToken());\r
+               }\r
+       }\r
+\r
 }\r
index 6e0696b..c8246a0 100644 (file)
@@ -28,6 +28,7 @@ import java.util.HashMap;
 import java.util.List;\r
 import java.util.Vector;\r
 \r
+import com.evernote.edam.type.LinkedNotebook;\r
 import com.evernote.edam.type.Note;\r
 import com.evernote.edam.type.Notebook;\r
 import com.evernote.edam.type.SavedSearch;\r
@@ -69,6 +70,8 @@ public class ListManager  {
        private List<Notebook>                  notebookIndex;\r
        private List<Notebook>                  archiveNotebookIndex;\r
        private List<String>                    localNotebookIndex;\r
+       \r
+       private List<LinkedNotebook>    linkedNotebookIndex;\r
 \r
        private List<SavedSearch>               searchIndex;\r
 \r
@@ -156,6 +159,7 @@ public class ListManager  {
 //             thumbnailList = conn.getNoteTable().getThumbnails();\r
 //             thumbnailList = new HashMap<String,QImage>();\r
                \r
+               linkedNotebookIndex = conn.getLinkedNotebookTable().getAll();\r
                loadNoteTitleColors();\r
                                \r
        }\r
@@ -240,9 +244,14 @@ public class ListManager  {
                \r
                setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());\r
                \r
+               linkedNotebookIndex = conn.getLinkedNotebookTable().getAll();\r
+               \r
                enSearchChanged = true;\r
        }\r
 \r
+       public void reloadTagIndex() {\r
+               setTagIndex(conn.getTagTable().getAll());       \r
+       }\r
        public void reloadIndexes() {\r
                setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());\r
 \r
@@ -251,8 +260,7 @@ public class ListManager  {
                for (int i=0; i<local.size(); i++)\r
                        localNotebookIndex.add(local.get(i).getGuid());\r
                \r
-               // Load tags\r
-               setTagIndex(conn.getTagTable().getAll());\r
+               reloadTagIndex();\r
                // Load notebooks\r
                setNotebookIndex(conn.getNotebookTable().getAll());\r
                // load archived notebooks (if note using the EN interface)\r
@@ -292,7 +300,7 @@ public class ListManager  {
        //* selected notebooks\r
        //***************************************************************\r
        //***************************************************************\r
-       // Return the selected notebook(s)\r
+       // Return the selected notebook(s)\r
        public List<String> getSelectedNotebooks() {\r
                return selectedNotebooks;\r
        }\r
@@ -341,6 +349,9 @@ public class ListManager  {
                return notebookIndex;\r
 \r
        }\r
+       public List<LinkedNotebook> getLinkedNotebookIndex() {\r
+               return linkedNotebookIndex;\r
+       }\r
        public List<Notebook> getArchiveNotebookIndex() {\r
                return archiveNotebookIndex;\r
        }\r
index 191a827..5867b53 100644 (file)
@@ -34,7 +34,8 @@ public class NoteFormatter {
        private final ApplicationLogger logger;\r
        private final DatabaseConnection conn;\r
        public boolean resourceError = false;\r
-       public boolean readOnly = false;\r
+       public boolean readOnly = false; \r
+       public boolean inkNote = false;\r
        public boolean addHighlight = true;\r
        private Note currentNote;\r
        private String currentNoteGuid;\r
@@ -53,11 +54,12 @@ public class NoteFormatter {
        public void setNote(Note note, boolean pdfPreview) {\r
                currentNote = note;\r
                this.pdfPreview = pdfPreview;\r
-               if (note != null)\r
-                       currentNoteGuid = note.getGuid();\r
-               else\r
-                       currentNoteGuid = null;\r
                readOnly = false;\r
+               currentNoteGuid = null;\r
+               if (note != null) {\r
+                       currentNoteGuid = note.getGuid();\r
+                       readOnly = conn.getNotebookTable().isReadOnly(note.getNotebookGuid());\r
+               } \r
                resourceError = false;\r
        }\r
        \r
@@ -203,8 +205,10 @@ public class NoteFormatter {
                Resource r = null;\r
                if (resGuid != null)\r
                        r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid,true);\r
-                       if (r==null || r.getData() == null || r.getData().getBody().length == 0)\r
-                               resourceError = true;;\r
+                       if (r==null || r.getData() == null || r.getData().getBody().length == 0) {\r
+                               resourceError = true;\r
+                               readOnly = true;\r
+                       }\r
                        if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {\r
                                tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
                                QByteArray binData = new QByteArray(r.getData().getBody());\r
@@ -358,7 +362,7 @@ public class NoteFormatter {
     private void modifyApplicationTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
        logger.log(logger.HIGH, "Entering NeverNote.modifyApplicationTags");\r
        if (appl.equalsIgnoreCase("vnd.evernote.ink")) {\r
-               readOnly = true;\r
+               inkNote = true;\r
            if (buildInkNote(doc, docElem, enmedia, hash, appl))\r
                return;\r
        }\r