-/*\r
- * This file is part of NixNote \r
- * Copyright 2009 Randy Baumgarte\r
- * \r
- * This file may be licensed under the terms of of the\r
- * 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;\r
-\r
-\r
-import java.io.ByteArrayInputStream;\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.IOException;\r
-import java.io.ObjectInputStream;\r
-import java.io.ObjectOutputStream;\r
-import java.text.SimpleDateFormat;\r
-import java.util.ArrayList;\r
-import java.util.Calendar;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-\r
-import org.apache.commons.lang3.StringEscapeUtils;\r
-\r
-import com.evernote.edam.type.Accounting;\r
-import com.evernote.edam.type.PrivilegeLevel;\r
-import com.evernote.edam.type.User;\r
-import com.evernote.edam.type.UserAttributes;\r
-import com.swabunga.spell.engine.Configuration;\r
-import com.trolltech.qt.core.QByteArray;\r
-import com.trolltech.qt.core.QSettings;\r
-import com.trolltech.qt.core.QSize;\r
-import com.trolltech.qt.gui.QPalette;\r
-import com.trolltech.qt.gui.QSystemTrayIcon;\r
-\r
-import cx.fbn.nevernote.config.FileManager;\r
-import cx.fbn.nevernote.config.InitializationException;\r
-import cx.fbn.nevernote.config.StartupConfig;\r
-import cx.fbn.nevernote.gui.ContainsAttributeFilterTable;\r
-import cx.fbn.nevernote.gui.DateAttributeFilterTable;\r
-import cx.fbn.nevernote.gui.ShortcutKeys;\r
-import cx.fbn.nevernote.utilities.ApplicationLogger;\r
-import cx.fbn.nevernote.utilities.Pair;\r
-\r
-\r
-//*****************************************************\r
-//*****************************************************\r
-//* Global constants & static functions used by \r
-//* multiple threads.\r
-//*****************************************************\r
-//*****************************************************\r
-\r
-public class Global {\r
- // Set current version and the known versions.\r
- public static String version = "1.6";\r
- public static String[] validVersions = {"1.6", "1.5", "1.4", "1.3", "1.2", "1.1", "1.0", "0.99", "0.98", "0.97", "0.96"};\r
- public static String username = ""; \r
- //public static String password = ""; \r
- \r
-\r
- // Each thread has an ID. This is used primarily to check the status\r
- // of running threads.\r
- public static final int mainThreadId=0;\r
- public static final int syncThreadId=1;\r
- public static final int tagCounterThreadId=2;\r
- public static final int trashCounterThreadId=3; // This should always be the highest thread ID\r
- public static final int indexThreadId=4; // Thread for indexing words\r
- public static final int saveThreadId=5; // Thread used for processing data to saving content\r
- public static final int notebookCounterThreadId=6; // Notebook Thread\r
- public static final int indexThread03Id=7; // unused\r
- public static final int indexThread04Id=8; // unused\r
- public static final int dbThreadId=9; // This should always be the highest thread ID\r
- public static final int threadCount = 10;\r
- \r
- \r
- // These variables deal with where the list of notes appears\r
- // They will either be vertical (View_List_Narrow) or will be\r
- // on top of the note (View_List_Wide). It also has the size of\r
- // thumbnails displayed in each view\r
- public static int View_List_Wide = 1;\r
- public static int View_List_Narrow = 2;\r
- public static QSize smallThumbnailSize = new QSize(100,75);\r
- public static QSize largeThumbnailSize = new QSize(300,225);\r
-\r
- // This is used to keep a running list of passwords that the user\r
- // wants us to remember.\r
- public static HashMap<String,Pair<String,String>> passwordSafe = new HashMap<String, Pair<String,String>>();\r
- public static List<Pair<String,String>> passwordRemember = new ArrayList<Pair<String,String>>();\r
- \r
- \r
- //public static String currentNotebookGuid;\r
- \r
- // These deal with Evernote user settings\r
- public static User user; \r
- public static long authTimeRemaining;\r
- public static long authRefreshTime;\r
- public static long failedRefreshes = 0; \r
- public static String userStoreUrl;\r
- public static String noteStoreUrl;\r
- public static String noteStoreUrlBase;\r
-\r
- // When we want to shut down we set this to true to short\r
- // circut other threads\r
- public static boolean keepRunning;\r
- \r
- // In the note list, these are the column numbers\r
- // so I don't need to hard code numbers.\r
- public static int noteTableCreationPosition = 0;\r
- public static int noteTableTitlePosition = 1;\r
- public static int noteTableTagPosition = 2;\r
- public static int noteTableNotebookPosition = 3;\r
- public static int noteTableChangedPosition = 4;\r
- public static int noteTableGuidPosition = 5;\r
- public static int noteTableAuthorPosition = 6;\r
- public static int noteTableSourceUrlPosition = 7;\r
- public static int noteTableSubjectDatePosition = 8;\r
- public static int noteTableSynchronizedPosition = 9;\r
- public static int noteTableThumbnailPosition = 10;\r
- public static int noteTablePinnedPosition = 11;\r
- public static int noteTableColumnCount = 12;\r
- public static Integer cryptCounter = 0;\r
- \r
- //public static int minimumWordCount = 2;\r
- \r
- // Regular expression to parse text with when indexing\r
- private static String wordRegex;\r
- \r
- // Experimental fixes. Set via Edit/Preferences/Debugging\r
- public static boolean enableCarriageReturnFix = false;\r
- public static boolean enableHTMLEntitiesFix = false;\r
- \r
- // Used to set & retrieve ini & Windows registry settings\r
- public static QSettings settings; // Set & get ini settings\r
- public static boolean isConnected; // Are we connected to Evernote\r
- public static boolean showDeleted = false; // Show deleted notes?\r
- public static boolean disableUploads = false; // Should we disable uploads (used in testing features)\r
- public static int messageLevel; // The level of messages to write to the log files\r
- public static String tagDelimeter = ","; // This is used to separate out tag names when entering above note\r
- public static String attachmentNameDelimeter = "------"; // Used to separate out attachment names in the res directory\r
- \r
- \r
- //* Database fields\r
- public static String databaseName = new String("NeverNote"); // database name. used for multiple databases to separate settings.\r
- public static String indexDatabaseName = new String("Index"); // searchable words database\r
- public static String resourceDatabaseName = new String("Resources"); // attachments database\r
- public static DateAttributeFilterTable createdSinceFilter;\r
- public static DateAttributeFilterTable createdBeforeFilter;\r
- public static DateAttributeFilterTable changedSinceFilter;\r
- public static DateAttributeFilterTable changedBeforeFilter;\r
- public static ContainsAttributeFilterTable containsFilter;\r
- \r
- // Log file used for debugging\r
- public static ApplicationLogger logger;\r
- //PrintStream stdoutStream;\r
- \r
- // Application key shortcuts & appearance\r
- public static QPalette originalPalette;\r
- public static ShortcutKeys shortcutKeys;\r
- \r
- public static boolean disableViewing; // used to disable the editor\r
- \r
- // When saving a note, this is a list of things we strip out because Evernote hates them\r
- public static List<String> invalidElements = new ArrayList<String>();\r
- public static HashMap<String, ArrayList<String>> invalidAttributes = new HashMap<String, ArrayList<String>>();\r
- \r
- public static boolean mimicEvernoteInterface; // Try to mimic Evernote or allow multiple notebook selection\r
- public static HashMap<String,String> resourceMap; // List of attachments for a note.\r
- public static String cipherPassword = ""; // If the database is encrypted, this stores the password\r
- public static String databaseCache = "16384"; // Default DB cache size\r
- \r
- // These are used for performance testing\r
- static Calendar startTraceTime; \r
- static Calendar intervalTraceTime;\r
- \r
- static boolean syncOnly;\r
- \r
- private static FileManager fileManager; // Used to access files & directories\r
- \r
- // Do initial setup \r
- public static void setup(StartupConfig startupConfig) throws InitializationException {\r
- settings = new QSettings("fbn.cx", startupConfig.getName());\r
- disableViewing = startupConfig.getDisableViewing();\r
- syncOnly = startupConfig.isSyncOnly();\r
-\r
- fileManager = new FileManager(startupConfig.getHomeDirPath(), startupConfig.getProgramDirPath());\r
-\r
-\r
- getServer(); // Setup URL to connect to\r
- \r
- // Get regular expressions used to parse out words\r
- settings.beginGroup("General");\r
- String regex = (String) settings.value("regex", "[,\\s]+");\r
- setWordRegex(regex);\r
- settings.endGroup();\r
- \r
- //Setup debugging information\r
- settings.beginGroup("Debug");\r
- String msglevel = (String) settings.value("messageLevel", "Low");\r
- settings.endGroup();\r
- \r
- \r
- //messageLevel = 1;\r
- setMessageLevel(msglevel);\r
- keepRunning = true; // Make sure child threads stay running\r
- disableUploads = disableUploads(); // Should we upload anything? Normally false.\r
- //disableUploads = true; //***** DELETE THIS LINE *******\r
- enableCarriageReturnFix = enableCarriageReturnFix(); // Enable test fix?\r
- enableHTMLEntitiesFix = enableHtmlEntitiesFix(); // Enable test fix?\r
- \r
- logger = new ApplicationLogger("global.log"); // Setup log for this class \r
- shortcutKeys = new ShortcutKeys(); // Setup keyboard shortcuts.\r
- mimicEvernoteInterface = getMimicEvernoteInterface(); // Should we mimic Evernote's notebook behavior\r
- resourceMap = new HashMap<String,String>(); // Setup resource map used to store attachments when editing\r
- \r
- databaseCache = getDatabaseCacheSize(); // Set database cache size \r
- \r
- Global.username = getUserInformation().getUsername();\r
- }\r
-\r
- // Get/Set word parsing regular expression\r
- public static String getWordRegex() {\r
- return wordRegex;\r
- }\r
- public static void setWordRegex(String r) {\r
- wordRegex = r;\r
- }\r
-\r
- // Set the debug message level\r
- public static void setMessageLevel(String msglevel) {\r
- if (msglevel.equalsIgnoreCase("low")) \r
- messageLevel = 1;\r
- if (msglevel.equalsIgnoreCase("medium")) \r
- messageLevel = 2;\r
- if (msglevel.equalsIgnoreCase("high")) \r
- messageLevel = 3;\r
- if (msglevel.equalsIgnoreCase("extreme")) \r
- messageLevel = 4;\r
- settings.beginGroup("Debug");\r
- settings.setValue("messageLevel", msglevel);\r
- settings.endGroup(); \r
- }\r
-\r
- //****************************************************\r
- //****************************************************\r
- //** Save user account information from Evernote\r
- //****************************************************\r
- //****************************************************\r
- public static void saveUserInformation(User user) {\r
- settings.beginGroup("User");\r
- settings.setValue("id", user.getId());\r
- settings.setValue("username", user.getUsername());\r
- settings.setValue("email", user.getEmail());\r
- settings.setValue("name", user.getName());\r
- settings.setValue("timezone", user.getTimezone());\r
- settings.setValue("privilege", user.getPrivilege().getValue());\r
- settings.setValue("created", user.getCreated());\r
- settings.setValue("updated", user.getUpdated());\r
- settings.setValue("deleted", user.getDeleted());\r
- settings.setValue("shard", user.getShardId());\r
- settings.endGroup();\r
- isPremium();\r
- if (user.getAttributes()!=null)\r
- saveUserAttributes(user.getAttributes());\r
- if (user.getAccounting()!=null)\r
- saveUserAccounting(user.getAccounting());\r
-\r
- }\r
- public static User getUserInformation() {\r
- User user = new User();\r
- settings.beginGroup("User");\r
- try { \r
- user.setId((Integer)settings.value("id", 0)); \r
- } catch (java.lang.ClassCastException e) {\r
- user.setId(new Integer((String)settings.value("id", "0")));\r
- }\r
- String username = (String)settings.value("username", "");\r
- String email = (String)settings.value("email", "");\r
- String name = (String)settings.value("name", "");\r
- String timezone = (String)settings.value("timezone", "");\r
- Integer privilege = 0;\r
- try { \r
- privilege = new Integer((String)settings.value("privilege", "0")); \r
- } catch (java.lang.ClassCastException e) {\r
- privilege = (Integer)settings.value("privilege", 0);\r
- }\r
-\r
- try { \r
- String date = (String)settings.value("created", "0");\r
- user.setCreated(new Long(date));\r
- date = (String)settings.value("updated", "0");\r
- user.setUpdated(new Long(date));\r
- date = (String)settings.value("deleted", "0");\r
- user.setDeleted(new Long(date));\r
- } catch (java.lang.ClassCastException e) {\r
- Long date = (Long)settings.value("created", 0);\r
- user.setCreated(date);\r
- date = (Long)settings.value("updated", 0);\r
- user.setUpdated(date);\r
- date = (Long)settings.value("deleted", 0);\r
- user.setDeleted(date);\r
- }\r
-\r
- String shard = (String)settings.value("shard", "");\r
- settings.endGroup();\r
- \r
- user.setUsername(username);\r
- user.setEmail(email);\r
- user.setName(name);\r
- user.setTimezone(timezone);\r
- PrivilegeLevel userLevel = PrivilegeLevel.findByValue(privilege);\r
- user.setPrivilege(userLevel);\r
- user.setShardId(shard);\r
- return user;\r
- }\r
- \r
- public static void saveUserAttributes(UserAttributes attrib) {\r
- settings.beginGroup("UserAttributes");\r
- settings.setValue("defaultLocationName", attrib.getDefaultLocationName());\r
- settings.setValue("defaultLatitude", attrib.getDefaultLocationName());\r
- settings.setValue("defaultLongitude", attrib.getDefaultLocationName());\r
- settings.setValue("incomingEmailAddress", attrib.getIncomingEmailAddress());\r
- settings.endGroup();\r
- }\r
- public static UserAttributes getUserAttributes() {\r
- settings.beginGroup("UserAttributes");\r
- UserAttributes attrib = new UserAttributes();\r
- attrib.setDefaultLocationName((String)settings.value("defaultLocationName",""));\r
- attrib.setDefaultLatitudeIsSet(false);\r
- attrib.setDefaultLongitudeIsSet(false);\r
- attrib.setIncomingEmailAddress((String)settings.value("incomingEmailAddress", ""));\r
- settings.endGroup();\r
- return attrib;\r
- }\r
- public static void saveUserAccounting(Accounting acc) {\r
- settings.beginGroup("UserAccounting");\r
- settings.setValue("uploadLimit", acc.getUploadLimit());\r
- settings.setValue("uploadLimitEnd", acc.getUploadLimitEnd());\r
- settings.setValue("uploadLimitNextMonth", acc.getUploadLimitNextMonth());\r
- settings.setValue("premiumServiceStart", acc.getPremiumServiceStart());\r
- settings.setValue("nextPaymentDue", acc.getNextPaymentDue());\r
- settings.setValue("uploadAmount", acc.getUpdated());\r
- settings.endGroup();\r
- }\r
- public static long getUploadLimitEnd() {\r
- Long limit;\r
- settings.beginGroup("UserAccounting");\r
- \r
- // Upload limit\r
- try {\r
- String val = (String)settings.value("uploadLimitEnd", "0");\r
- limit = new Long(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- limit = (Long)settings.value("uploadLimitEnd", 0);\r
- } catch (Exception e1) {\r
- limit = new Long(0);\r
- }\r
- }\r
- \r
- // return value\r
- settings.endGroup();\r
- return limit;\r
- }\r
- public static void saveUploadAmount(long amount) {\r
- settings.beginGroup("UserAccounting");\r
- settings.setValue("uploadAmount", amount);\r
- settings.endGroup();\r
- }\r
- public static long getUploadAmount() {\r
- long amt=0;\r
- settings.beginGroup("UserAccounting");\r
- try {\r
- String num = (String)settings.value("uploadAmount", "0");\r
- amt = new Long(num.trim());\r
- } catch (Exception e) {\r
- try {\r
- amt = (Integer)settings.value("uploadAmount", 0);\r
- } catch (Exception e1) {\r
- amt = 0;\r
- }\r
- }\r
- settings.endGroup();\r
- return amt;\r
- }\r
- public static void saveEvernoteUpdateCount(long amount) {\r
- settings.beginGroup("UserAccounting");\r
- settings.setValue("updateCount", amount);\r
- settings.endGroup();\r
- }\r
- public static long getEvernoteUpdateCount() {\r
- long amt;\r
- settings.beginGroup("UserAccounting");\r
- try {\r
- String num = (String)settings.value("updateCount", new Long(0).toString());\r
- amt = new Long(num.trim());\r
- } catch (java.lang.ClassCastException e) {\r
- amt = 0;\r
- }\r
- settings.endGroup();\r
- return amt;\r
- }\r
- public static boolean isPremium() {\r
- int level;\r
- settings.beginGroup("User");\r
- try {\r
- String num = (String)settings.value("privilege", "1");\r
- level = new Integer(num.trim());\r
- } catch (java.lang.ClassCastException e) {\r
- try {\r
- level = (Integer)settings.value("privilege", 1);\r
- } catch (Exception e1) {\r
- level = 1;\r
- }\r
- }\r
- settings.endGroup();\r
- PrivilegeLevel userLevel = PrivilegeLevel.findByValue(level);\r
- if (userLevel == PrivilegeLevel.NORMAL)\r
- return false;\r
- return true;\r
- \r
- }\r
- public static long getUploadLimit() {\r
- settings.beginGroup("UserAccounting");\r
- long limit;\r
- try {\r
- String num = (String)settings.value("uploadLimit", new Long(0).toString());\r
- limit = new Long(num.trim());\r
- } catch (java.lang.ClassCastException e) {\r
- limit = 0;\r
- }\r
- settings.endGroup();\r
- return limit;\r
- }\r
-\r
- \r
- \r
- //****************************************************\r
- //****************************************************\r
- //** View settings. Used to restore settings \r
- //** when starting and to control how the program\r
- //** behaves.\r
- //****************************************************\r
- //****************************************************\r
- \r
- //* Get/Set if we should show a tray icon\r
- public static boolean showTrayIcon() {\r
- settings.beginGroup("General");\r
- try {\r
- String max = (String) settings.value("showTrayIcon", "false");\r
- settings.endGroup();\r
- if (!max.equalsIgnoreCase("true") || !QSystemTrayIcon.isSystemTrayAvailable())\r
- return false;\r
- else\r
- return true; \r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("showTrayIcon", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setShowTrayIcon(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("showTrayIcon", "true");\r
- else\r
- settings.setValue("showTrayIcon", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Get/Set window maximized when closed last\r
- public static boolean wasWindowMaximized() {\r
- try {\r
- settings.beginGroup("General");\r
- String max = (String) settings.value("isMaximized", "true");\r
- settings.endGroup();\r
- if (!max.equalsIgnoreCase("true"))\r
- return false;\r
- return true; \r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("isMaximized", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveWindowMaximized(boolean isMax) {\r
- settings.beginGroup("General");\r
- if (isMax)\r
- settings.setValue("isMaximized", "true");\r
- else\r
- settings.setValue("isMaximized", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Get/set currently viewed note Guid\r
- public static String getLastViewedNoteGuid() {\r
- settings.beginGroup("General");\r
- String guid = (String) settings.value("lastViewedNote", "");\r
- settings.endGroup();\r
- return guid; \r
- }\r
- public static void saveCurrentNoteGuid(String guid) {\r
- settings.beginGroup("General");\r
- if (guid != null)\r
- settings.setValue("lastViewedNote", guid);\r
- else\r
- settings.setValue("lastViewedNote", "");\r
- settings.endGroup();\r
- }\r
- \r
- // Get/Set the note column we are sorted on and the order\r
- public static void setSortColumn(int i) {\r
- int view = Global.getListView();\r
- settings.beginGroup("General");\r
- if (view == Global.View_List_Wide)\r
- settings.setValue("sortColumn", i);\r
- else\r
- settings.setValue("sortColumn-Narrow", i);\r
- settings.endGroup();\r
- }\r
- public static int getSortColumn() {;\r
- String key;\r
- if (Global.getListView() == Global.View_List_Wide)\r
- key = "sortColumn";\r
- else\r
- key = "sortColumn-Narrow";\r
-\r
- settings.beginGroup("General");\r
- int order; \r
- try {\r
- String val = settings.value(key, new Integer(0)).toString();\r
- order = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- order = (Integer)settings.value(key, 0);\r
- } catch (Exception e1) {\r
- order = 0;\r
- }\r
- }\r
- \r
- settings.endGroup();\r
- return order;\r
- }\r
- public static void setSortOrder(int i) {\r
- int view = Global.getListView();\r
- settings.beginGroup("General");\r
- if (view == Global.View_List_Wide)\r
- settings.setValue("sortOrder", i);\r
- else\r
- settings.setValue("sortOrder-Narrow", i);\r
- settings.endGroup();\r
- }\r
- public static int getSortOrder() {\r
- int view = Global.getListView();\r
- settings.beginGroup("General");\r
- String key;\r
- if (view == Global.View_List_Wide)\r
- key = "sortOrder";\r
- else\r
- key = "sortOrder-Narrow";\r
-\r
- int order; \r
- try {\r
- String val = settings.value(key, new Integer(0)).toString();\r
- order = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- order = (Integer)settings.value(key, 0);\r
- } catch (Exception e1) {\r
- order = 0;\r
- }\r
- }\r
- \r
- settings.endGroup();\r
- return order;\r
- }\r
- \r
- // Should we automatically log in to Evernote when starting?\r
- public static boolean automaticLogin() {\r
- try {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("automaticLogin", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false; \r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("automaticLogin", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setAutomaticLogin(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("automaticLogin", "true");\r
- else\r
- settings.setValue("automaticLogin", "false");\r
- settings.endGroup();\r
- }\r
-\r
- // Get/set the Evernote server Url. \r
- public static void setServer(String server) {\r
- settings.beginGroup("General");\r
- settings.setValue("server", server);\r
- settings.endGroup(); \r
- }\r
- public static String getServer() {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("server", "www.evernote.com");\r
- if (text.equals("www.evernote.com")) {\r
- userStoreUrl = "https://www.evernote.com/edam/user";\r
- noteStoreUrlBase = "www.evernote.com/edam/note/"; \r
- } else {\r
- userStoreUrl = "https://sandbox.evernote.com/edam/user";\r
- noteStoreUrlBase = "sandbox.evernote.com/edam/note/";\r
- }\r
- settings.endGroup();\r
-// if (isPremium())\r
- noteStoreUrlBase = "https://" + noteStoreUrlBase;\r
-// else\r
-// noteStoreUrlBase = "http://" + noteStoreUrlBase;\r
- return text;\r
- }\r
-\r
- // Get/Set if we should disable uploads to Evernote\r
- public static boolean disableUploads() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("disableUploads", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("disableUploads", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setDisableUploads(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("disableUploads", "true");\r
- else\r
- settings.setValue("disableUploads", "false");\r
- settings.endGroup();\r
- disableUploads = val;\r
- }\r
- \r
- // Should we view PDF documents inline?\r
- public static boolean pdfPreview() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("pdfPreview", "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("pdfPreview", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setPdfPreview(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("pdfPreview", "true");\r
- else\r
- settings.setValue("pdfPreview", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // When creating a new note, should it inherit tags that are currently selected?\r
- public static boolean newNoteWithSelectedTags() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("newNoteWithSelectedTags", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("newNoteWithSelectedTags", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setNewNoteWithSelectedTags(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("newNoteWithSelectedTags", "true");\r
- else\r
- settings.setValue("newNoteWithSelectedTags", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Minimum weight for text OCRed from Evernote. Anything below this\r
- // Won't be shown to the user when they search\r
- public static void setRecognitionWeight(int len) {\r
- settings.beginGroup("General");\r
- settings.setValue("recognitionWeight", len);\r
- settings.endGroup(); \r
- }\r
- public static int getRecognitionWeight() {\r
- settings.beginGroup("General");\r
- Integer len;\r
- try {\r
- len = (Integer)settings.value("recognitionWeight", 30);\r
- } catch (Exception e) {\r
- len = 80;\r
- }\r
- settings.endGroup();\r
- return len;\r
- }\r
- \r
- // get/set current debug message level\r
- public static String getMessageLevel() {\r
- settings.beginGroup("Debug");\r
- String text = (String)settings.value("messageLevel", "Low");\r
- settings.endGroup();\r
- setMessageLevel(text);\r
- return text;\r
- }\r
- public static void setDateFormat(String format) {\r
- settings.beginGroup("General");\r
- settings.setValue("dateFormat", format);\r
- settings.endGroup(); \r
- }\r
- \r
- // Get/Set user date/time formats\r
- public static String getDateFormat() {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("dateFormat", "MM/dd/yyyy");\r
- settings.endGroup();\r
- return text;\r
- }\r
- public static void setTimeFormat(String format) {\r
- settings.beginGroup("General");\r
- settings.setValue("timeFormat", format);\r
- settings.endGroup(); \r
- }\r
- public static String getTimeFormat() {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("timeFormat", "HH:mm:ss");\r
- settings.endGroup();\r
- return text;\r
- }\r
- \r
- // How often should we sync with Evernote?\r
- public static String getSyncInterval() {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("syncInterval", "15 minutes");\r
- settings.endGroup();\r
- return text; \r
- }\r
- public static void setSyncInterval(String format) {\r
- settings.beginGroup("General");\r
- settings.setValue("syncInterval", format);\r
- settings.endGroup(); \r
- }\r
- \r
- // Get/Set the width of columns and their position for the \r
- // next start.\r
- public static void setColumnWidth(String col, int width) {\r
- if (Global.getListView() == Global.View_List_Wide)\r
- settings.beginGroup("ColumnWidths");\r
- else \r
- settings.beginGroup("ColumnWidths-Narrow");\r
- settings.setValue(col, width);\r
- settings.endGroup();\r
- }\r
- public static int getColumnWidth(String col) {\r
- int view = Global.getListView();\r
- if (view == Global.View_List_Wide)\r
- settings.beginGroup("ColumnWidths");\r
- else\r
- settings.beginGroup("ColumnWidths-Narrow");\r
- Integer width;\r
- try {\r
- String val = (String)settings.value(col, "0");\r
- width = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- width = (Integer)settings.value(col, 0);\r
- } catch (Exception e1) {\r
- width = 0;\r
- }\r
- }\r
- settings.endGroup();\r
- return width;\r
- }\r
- public static void setColumnPosition(String col, int width) {\r
- if (Global.getListView() == Global.View_List_Wide)\r
- settings.beginGroup("ColumnPosition");\r
- else\r
- settings.beginGroup("ColumnPosition-Narrow");\r
- settings.setValue(col, width);\r
- settings.endGroup();\r
- }\r
- public static int getColumnPosition(String col) {\r
- if (Global.getListView() == Global.View_List_Wide)\r
- settings.beginGroup("ColumnPosition");\r
- else\r
- settings.beginGroup("ColumnPosition-Narrow");\r
- Integer width;\r
- try {\r
- String val = (String)settings.value(col, "-1");\r
- width = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- width = (Integer)settings.value(col, 0);\r
- } catch (Exception e1) {\r
- width = 0;\r
- }\r
- }\r
- settings.endGroup();\r
- return width;\r
- }\r
- \r
- // Ping the user when they try to delete or just do it.\r
- public static boolean verifyDelete() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("verifyDelete", "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("verifyDelete", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setVerifyDelete(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("verifyDelete", "true");\r
- else\r
- settings.setValue("verifyDelete", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Should it start minimized?\r
- public static boolean startMinimized() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("startMinimized", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("startMinimized", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setStartMinimized(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("startMinimized", "true");\r
- else\r
- settings.setValue("startMinimized", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Should we upload the content of any deleted notes\r
- public static boolean synchronizeDeletedContent() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("syncDeletedContent", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("syncDeletedContent", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- } \r
- public static void setSynchronizeDeletedContent(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("syncDeletedContent", "true");\r
- else\r
- settings.setValue("syncDeletedContent", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Is a section of the window visible? Used to hide things people don't\r
- // want to see.\r
- public static boolean isWindowVisible(String window) {\r
- settings.beginGroup("WindowsVisible");\r
- try {\r
- String defaultValue = "true";\r
- if (window.equalsIgnoreCase("noteInformation"))\r
- defaultValue = "false";\r
- String text = (String)settings.value(window, defaultValue);\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false; \r
- } catch (java.lang.ClassCastException e) {\r
- boolean defaultValue = true;\r
- if (window.equalsIgnoreCase("noteInformation"))\r
- defaultValue = false;\r
- Boolean value = (Boolean) settings.value("showTrayIcon", defaultValue);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveWindowVisible(String window, boolean val) {\r
- settings.beginGroup("WindowsVisible");\r
- if (val)\r
- settings.setValue(window, "true");\r
- else\r
- settings.setValue(window, "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Is a list in the column in the note list visible? \r
- public static boolean isColumnVisible(String window) {\r
- String defaultValue = "true";\r
- int view = Global.getListView();\r
- if (Global.getListView() == Global.View_List_Wide)\r
- settings.beginGroup("ColumnsVisible");\r
- else\r
- settings.beginGroup("ColumnsVisible-Narrow"); \r
- if (window.equalsIgnoreCase("thumbnail") && view == Global.View_List_Wide)\r
- defaultValue = "false";\r
- if (window.equalsIgnoreCase("thumbnail"))\r
- defaultValue = "false";\r
- if (window.equalsIgnoreCase("Guid"))\r
- defaultValue = "false";\r
- try {\r
- String text = (String)settings.value(window, defaultValue);\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- boolean defBool = false;\r
- if (window.equalsIgnoreCase("true"))\r
- defBool = true;\r
- else\r
- defBool = false;\r
- Boolean value = (Boolean) settings.value(window, defBool);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveColumnVisible(String column, boolean val) {\r
- if (Global.getListView() == Global.View_List_Wide)\r
- settings.beginGroup("ColumnsVisible");\r
- else\r
- settings.beginGroup("ColumnsVisible-Narrow"); \r
- if (val)\r
- settings.setValue(column, "true");\r
- else\r
- settings.setValue(column, "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Is a particular editor button visible?\r
- public static boolean isEditorButtonVisible(String window) {\r
- settings.beginGroup("EditorButtonsVisible");\r
- try {\r
- String text = (String)settings.value(window, "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value(window, true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveEditorButtonsVisible(String column, boolean val) {\r
- settings.beginGroup("EditorButtonsVisible");\r
- if (val)\r
- settings.setValue(column, "true");\r
- else\r
- settings.setValue(column, "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Should the test fixes be enabled\r
- public static boolean enableCarriageReturnFix() {\r
- try {\r
- settings.beginGroup("Debug");\r
- String text = (String)settings.value("enableCarriageReturnFix", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("enableCarriageReturnFix", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveCarriageReturnFix(boolean val) {\r
- settings.beginGroup("Debug");\r
- if (val)\r
- settings.setValue("enableCarriageReturnFix", "true");\r
- else\r
- settings.setValue("enableCarriageReturnFix", "false");\r
- settings.endGroup();\r
- }\r
- public static boolean enableHtmlEntitiesFix() {\r
- try {\r
- settings.beginGroup("Debug");\r
- String text = (String)settings.value("enableHtmlEntitiesFix", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("enableHtmlEntitiesFix", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveHtmlEntitiesFix(boolean val) {\r
- settings.beginGroup("Debug");\r
- if (val)\r
- settings.setValue("enableHtmlEntitiesFix", "true");\r
- else\r
- settings.setValue("enableHtmlEntitiesFix", "false");\r
- settings.endGroup();\r
- }\r
-\r
-// public static void setIndexThreads(int val) {\r
-// settings.beginGroup("General");\r
-// settings.setValue("indexThreads", val);\r
-// settings.endGroup();\r
-// }\r
-// public static int getIndexThreads() {\r
-// settings.beginGroup("General");\r
-// Integer threads;\r
-// try {\r
-// String val = (String)settings.value("indexThreads", "1");\r
-// threads = new Integer(val.trim());\r
-// } catch (Exception e) {\r
-// try {\r
-// threads = (Integer)settings.value("indexThreads", 1);\r
-// } catch (Exception e1) {\r
-// threads = 1;\r
-// }\r
-// }\r
-// settings.endGroup();\r
-// threads = 1;\r
-// return threads;\r
- \r
- // Get/Set text zoom factor\r
-// }\r
- public static void setZoomFactor(double val) {\r
- settings.beginGroup("General");\r
- settings.setValue("zoomFactor", val);\r
- settings.endGroup();\r
- }\r
- public static double getZoomFactor() {\r
- settings.beginGroup("General");\r
- Double threads;\r
- try {\r
- String val = (String)settings.value("zoomFactor", "1.0");\r
- threads = new Double(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- threads = (Double)settings.value("zoomFactor", 1.0);\r
- } catch (Exception e1) {\r
- threads = new Double(1);\r
- }\r
- }\r
- settings.endGroup();\r
- return threads;\r
- }\r
- public static void setTextSizeMultiplier(double val) {\r
- settings.beginGroup("General");\r
- settings.setValue("textMultiplier", val);\r
- settings.endGroup();\r
- }\r
- public static double getTextSizeMultiplier() {\r
- settings.beginGroup("General");\r
- Double threads;\r
- try {\r
- String val = (String)settings.value("textMultiplier", "1");\r
- threads = new Double(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- threads = (Double)settings.value("textMultiplier", 1);\r
- } catch (Exception e1) {\r
- threads = new Double(1);\r
- }\r
- }\r
- settings.endGroup();\r
- return threads;\r
- }\r
- \r
- \r
- // Should we mimic Evernote and restrict the notebooks selected?\r
- public static boolean getMimicEvernoteInterface() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("mimicEvernoteInterface", "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("mimicEvernoteInterface", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setMimicEvernoteInterface(boolean value) {\r
- settings.beginGroup("General");\r
- if (value)\r
- settings.setValue("mimicEvernoteInterface", "true");\r
- else\r
- settings.setValue("mimicEvernoteInterface", "false"); \r
- settings.endGroup();\r
- }\r
- \r
- \r
- // Synchronize with Evernote when closing?\r
- public static boolean synchronizeOnClose() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("synchronizeOnClose", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("synchronizeOnClose", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setSynchronizeOnClose(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("synchronizeOnClose", "true");\r
- else\r
- settings.setValue("synchronizeOnClose", "false");\r
- settings.endGroup();\r
- }\r
-\r
- // Get/set the database version. Not really used any more, but kept\r
- // for compatibility.\r
- public static void setDatabaseVersion(String version) {\r
- settings.beginGroup("General");\r
- settings.setValue("databaseVersion", version);\r
- settings.endGroup();\r
- }\r
- public static String getDatabaseVersion() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("databaseVersion", "0.70");\r
- settings.endGroup();\r
- return val;\r
- }\r
-\r
- // Get the URL (full path) of the main database\r
- public static String getDatabaseUrl() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("DatabaseURL", "");\r
- settings.endGroup();\r
- if (val.equals(""))\r
- val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.databaseName);\r
- return val;\r
- }\r
- \r
- // get the url (full path) of the searchable word database\r
- public static String getIndexDatabaseUrl() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("IndexDatabaseURL", "");\r
- settings.endGroup();\r
- if (val.equals(""))\r
- val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.indexDatabaseName);\r
- return val;\r
- }\r
- \r
- // Get the url (full path) of the attachment database\r
- public static String getResourceDatabaseUrl() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("ResourceDatabaseURL", "");\r
- settings.endGroup();\r
- if (val.equals(""))\r
- val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.resourceDatabaseName);\r
- return val;\r
- }\r
- public static void setDatabaseUrl(String value) {\r
- settings.beginGroup("General");\r
- settings.setValue("DatabaseURL", value);\r
- settings.endGroup();\r
- }\r
- public static void setIndexDatabaseUrl(String value) {\r
- settings.beginGroup("General");\r
- settings.setValue("IndexDatabaseURL", value);\r
- settings.endGroup();\r
- }\r
- public static void setResourceDatabaseUrl(String value) {\r
- settings.beginGroup("General");\r
- settings.setValue("ResourceDatabaseURL", value);\r
- settings.endGroup();\r
- }\r
- public static String getDatabaseUserid() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("databaseUserid", "");\r
- settings.endGroup();\r
- return val;\r
- }\r
- public static String getDatabaseUserPassword() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("databaseUserPassword", "");\r
- settings.endGroup();\r
- return val;\r
- }\r
- \r
- // get/Set the style sheet and the palette to control the look & feel\r
- public static void setStyle(String style) {\r
- settings.beginGroup("General");\r
- settings.setValue("style", style);\r
- settings.endGroup();\r
- }\r
- public static String getStyle() {\r
- settings.beginGroup("General");\r
- String val = (String)settings.value("style", "Cleanlooks");\r
- settings.endGroup();\r
- return val;\r
- }\r
- public static boolean useStandardPalette() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("standardPalette", "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("standardPalette", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setStandardPalette(boolean val) {\r
- settings.beginGroup("General");\r
- if (val)\r
- settings.setValue("standardPalette", "true");\r
- else\r
- settings.setValue("standardPalette", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Set the amount of time to wait between indexing\r
- // Get/Set interval when the index thread wakes up.\r
- public static void setIndexThreadSleepInterval(int sleep) {\r
- settings.beginGroup("General");\r
- settings.setValue("IndexThreadSleepInterval", sleep);\r
- settings.endGroup();\r
- }\r
- public static int getIndexThreadSleepInterval() {\r
- settings.beginGroup("General");\r
- Integer sleep;\r
- try {\r
- String val = (String)settings.value("IndexThreadSleepInterval", "300");\r
- sleep = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- sleep = (Integer)settings.value("IndexThreadSleepInterval", 0);\r
- } catch (Exception e1) {\r
- sleep = 300;\r
- }\r
- }\r
- settings.endGroup();\r
- return sleep;\r
- }\r
- \r
- \r
- // Get/Set a window state for later restoring\r
- public static void saveState(String name, QByteArray state) {\r
- int view = Global.getListView();\r
- if (view == Global.View_List_Narrow)\r
- name = name +"Narrow";\r
- settings.beginGroup("SaveState");\r
- settings.setValue(name, state);\r
- settings.endGroup();\r
- }\r
- \r
- public static QByteArray restoreState(String name) {\r
- int view = Global.getListView();\r
- if (view == Global.View_List_Narrow)\r
- name = name +"Narrow";\r
- settings.beginGroup("SaveState");\r
- QByteArray state = (QByteArray)settings.value(name);\r
- settings.endGroup();\r
- return state;\r
- }\r
- public static void saveGeometry(String name, QByteArray state) {\r
- int view = Global.getListView();\r
- if (view == Global.View_List_Narrow)\r
- settings.beginGroup("SaveGeometryNarrow");\r
- else\r
- settings.beginGroup("SaveGeometry");\r
- settings.setValue(name, state);\r
- settings.endGroup();\r
- }\r
- \r
- public static QByteArray restoreGeometry(String name) {\r
- int view = Global.getListView();\r
- if (view == Global.View_List_Narrow)\r
- settings.beginGroup("SaveGeometryNarrow");\r
- else\r
- settings.beginGroup("SaveGeometry");\r
- QByteArray state = (QByteArray)settings.value(name);\r
- settings.endGroup();\r
- return state;\r
- }\r
- \r
- \r
- // Set how often to do an automatic save\r
- public static void setAutoSaveInterval(int interval) {\r
- settings.beginGroup("General");\r
- settings.setValue("autoSaveInterval", interval);\r
- settings.endGroup();\r
- }\r
- public static int getAutoSaveInterval() {\r
- settings.beginGroup("General");\r
- Integer value;\r
- try {\r
- String val = (String)settings.value("autoSaveInterval", "5");\r
- value = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- value = (Integer)settings.value("autoSaveInterval", 5);\r
- } catch (Exception e1) {\r
- value = 5;\r
- }\r
- }\r
- settings.endGroup();\r
- return value;\r
- }\r
- \r
- // Add an invalid attribute & element to the database so we don't bother parsing it in the future\r
- // These values we automatically remove from any note.\r
- // Add invalid attributes\r
- public static void addInvalidAttribute(String element, String attribute) {\r
- \r
- List<String> attributes = invalidAttributes.get(element);\r
- if (attributes != null) {\r
- for (int i=0; i<attributes.size(); i++)\r
- if (attribute.equalsIgnoreCase(attributes.get(i))) {\r
- return;\r
- }\r
- }\r
- \r
- ArrayList<String> attributeList;\r
- if (!invalidAttributes.containsKey(element)) {\r
- attributeList = new ArrayList<String>();\r
- attributeList.add(attribute);\r
- invalidAttributes.put(element, attributeList);\r
- }\r
- else {\r
- attributeList = invalidAttributes.get(element);\r
- attributeList.add(attribute);\r
- invalidAttributes.put(element,attributeList);\r
- }\r
- }\r
- \r
- // Add invalid attributes\r
- public static void addInvalidElement(String element) {\r
- for (int i=0; i<invalidElements.size(); i++) {\r
- if (element.equalsIgnoreCase(invalidElements.get(i)))\r
- return;\r
- }\r
- invalidElements.add(element);\r
- }\r
- \r
- // Get/Set proxy information\r
- // Proxy settings\r
- public static String getProxyValue(String key) {\r
- settings.beginGroup("Proxy");\r
- String val = (String)settings.value(key, "");\r
- settings.endGroup();\r
- return val;\r
- }\r
- public static void setProxyValue(String key, String value) {\r
- settings.beginGroup("Proxy");\r
- settings.setValue(key, value);\r
- settings.endGroup();\r
- }\r
- \r
- // Change a byte array to a hex string\r
- // Convert a byte array to a hex string\r
- public static String byteArrayToHexString(byte data[]) {\r
- StringBuffer buf = new StringBuffer();\r
- for (byte element : data) {\r
- int halfbyte = (element >>> 4) & 0x0F;\r
- int two_halfs = 0;\r
- do {\r
- if ((0 <= halfbyte) && (halfbyte <= 9))\r
- buf.append((char) ('0' + halfbyte));\r
- else\r
- buf.append((char) ('a' + (halfbyte - 10)));\r
- halfbyte = element & 0x0F;\r
- } while(two_halfs++ < 1);\r
- }\r
- return buf.toString(); \r
- }\r
-\r
- \r
- // Get/Set spelling settings\r
- public static boolean getSpellSetting(String value) {\r
- settings.beginGroup("Spell");\r
- String text = (String)settings.value(value, "");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- if (text.equalsIgnoreCase("false"))\r
- return false;\r
- if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREDIGITWORDS))\r
- return true;\r
- if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREINTERNETADDRESSES))\r
- return true;\r
- if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREUPPERCASE))\r
- return true;\r
- if (value.equalsIgnoreCase(Configuration.SPELL_IGNORESENTENCECAPITALIZATION))\r
- return true;\r
- return false;\r
- }\r
- public static void setSpellSetting(String setting, boolean val) {\r
- settings.beginGroup("Spell");\r
- if (val)\r
- settings.setValue(setting, "true");\r
- else\r
- settings.setValue(setting, "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Get/Set how we should display tags (color them, hide unused, or do nothing)\r
- // What to do with inactive tags?\r
- public static String tagBehavior() {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("tagBehavior", "DoNothing");\r
- settings.endGroup();\r
- return text;\r
- }\r
- // What to do with inactive tags?\r
- public static void setTagBehavior(String value) {\r
- settings.beginGroup("General");\r
- settings.setValue("tagBehavior", value);\r
- settings.endGroup();\r
- }\r
-\r
- \r
- // Should the toolbar be visible?\r
- public static boolean isToolbarButtonVisible(String window) {\r
- settings.beginGroup("ToolbarButtonsVisible");\r
- try {\r
- String text = (String)settings.value(window, "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false; \r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value(window, true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void saveToolbarButtonsVisible(String column, boolean val) {\r
- settings.beginGroup("ToolbarButtonsVisible");\r
- if (val)\r
- settings.setValue(column, "true");\r
- else\r
- settings.setValue(column, "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Are thumbnails enabled?\r
- \r
- public static boolean enableThumbnails() {\r
- settings.beginGroup("Debug");\r
- try {\r
- String text = (String)settings.value("thumbnails", "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("thumbnails", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setEnableThumbnails(boolean val) {\r
- settings.beginGroup("Debug");\r
- if (val)\r
- settings.setValue("thumbnails", "true");\r
- else\r
- settings.setValue("thumbnails", "false");\r
- settings.endGroup();\r
- }\r
- \r
- // Trace used for performance tuning. Not normally used in production.\r
- // Print date/time. Used mainly for performance tracing\r
- public static void trace(boolean resetInterval) {\r
- String fmt = "MM/dd/yy HH:mm:ss.SSSSSS";\r
- String dateTimeFormat = new String(fmt);\r
- SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);\r
- Calendar cal = Calendar.getInstance();\r
- if (intervalTraceTime == null) \r
- intervalTraceTime = Calendar.getInstance();\r
- if (startTraceTime == null)\r
- startTraceTime = Calendar.getInstance();\r
- \r
- float interval = (cal.getTimeInMillis() - intervalTraceTime.getTimeInMillis());\r
- float total = (cal.getTimeInMillis() - startTraceTime.getTimeInMillis());\r
- \r
-// if (interval > 00.0) {\r
- StackTraceElement[] exceptions = Thread.currentThread().getStackTrace();\r
- System.out.println("------------------------------------------");\r
-\r
- System.out.println("Date/Time " +simple.format(cal.getTime()));\r
- System.out.format("Interval Time: %-10.6f%n", interval);\r
- System.out.format("Total Time: %-10.6f%n", total);\r
- for (int i=2; i<5 && i<exceptions.length; i++) {\r
- System.out.println(exceptions[i]);\r
- }\r
-// }\r
- if (resetInterval)\r
- intervalTraceTime = cal;\r
- }\r
- public static void traceReset() {\r
- intervalTraceTime = null;\r
- startTraceTime = null;\r
- }\r
-\r
- \r
- // Get the FileManager class to manage local files & directories\r
- public static FileManager getFileManager() {\r
- return fileManager;\r
- }\r
- \r
- // Should the note editor be disabled?\r
- public static boolean getDisableViewing() {\r
- return disableViewing;\r
- }\r
-\r
- //**********************\r
- //* Thumbnail zoom level\r
- //**********************\r
- public static int calculateThumbnailZoom(String content) {\r
- int zoom = 1;\r
- if (content.indexOf("application/pdf") == -1) {\r
- if (content.indexOf("image/") == -1) {\r
- String text = StringEscapeUtils.unescapeHtml4(content.replaceAll("\\<.*?\\>", ""));\r
- zoom = 2;\r
- if (text.length() < 500) \r
- zoom = 2;\r
- if (text.length() < 250)\r
- zoom = 3;\r
- if (text.length() < 100)\r
- zoom = 4;\r
- if (text.length() < 50)\r
- zoom = 5;\r
- if (text.length() < 10)\r
- zoom = 6;\r
- }\r
- }\r
- return zoom;\r
- }\r
- \r
- //**********************\r
- //* List View settings \r
- //**********************\r
- public static void setListView(int view) {\r
- settings.beginGroup("General");\r
- settings.setValue("listView", view);\r
- settings.endGroup();\r
- }\r
- public static int getListView() {\r
- settings.beginGroup("General");\r
- Integer value;\r
- try {\r
- String val = (String)settings.value("listView", View_List_Wide);\r
- value = new Integer(val.trim());\r
- } catch (Exception e) {\r
- try {\r
- value = (Integer)settings.value("listView", View_List_Wide);\r
- } catch (Exception e1) {\r
- value = View_List_Wide;\r
- }\r
- }\r
- settings.endGroup();\r
- return value;\r
- }\r
-\r
- \r
- \r
- //*******************\r
- // Font Settings\r
- //*******************\r
- public static boolean overrideDefaultFont() {\r
- settings.beginGroup("Font");\r
- try {\r
- String text = (String)settings.value("overrideFont", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false; \r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("overrideFont", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
-\r
- }\r
- \r
- //****************************************************\r
- // Get/Set the default font settings for a new note\r
- //****************************************************\r
- public static void setOverrideDefaultFont(boolean value) {\r
- settings.beginGroup("Font");\r
- settings.setValue("overrideFont", value);\r
- settings.endGroup(); \r
- }\r
- public static String getDefaultFont() {\r
- settings.beginGroup("Font");\r
- String val = (String)settings.value("font", "");\r
- settings.endGroup();\r
- return val;\r
- }\r
- public static void setDefaultFont(String value) {\r
- settings.beginGroup("Font");\r
- settings.setValue("font", value);\r
- settings.endGroup();\r
- }\r
- public static String getDefaultFontSize() {\r
- settings.beginGroup("Font");\r
- String val = (String)settings.value("fontSize", "");\r
- settings.endGroup();\r
- return val;\r
- }\r
- public static void setDefaultFontSize(String value) {\r
- settings.beginGroup("Font");\r
- settings.setValue("fontSize", value);\r
- settings.endGroup();\r
- }\r
- \r
- \r
- //*******************************************\r
- // Override the close & minimize instead.\r
- //*******************************************\r
- public static boolean minimizeOnClose() {\r
- settings.beginGroup("General");\r
- try {\r
- String text = (String)settings.value("minimizeOnClose", "false");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true") && QSystemTrayIcon.isSystemTrayAvailable())\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("minimizeOnClose", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setMinimizeOnClose(boolean value) {\r
- settings.beginGroup("General");\r
- settings.setValue("minimizeOnClose", value);\r
- settings.endGroup(); \r
- }\r
-\r
- //*********************************\r
- // Check version information\r
- //*********************************\r
- public static boolean checkVersionUpgrade() {\r
- settings.beginGroup("Upgrade");\r
- try {\r
- String text = (String)settings.value("checkForUpdates", "true");\r
- settings.endGroup();\r
- if (text.equalsIgnoreCase("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("checkForUpdates", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setCheckVersionUpgrade(boolean value) {\r
- settings.beginGroup("Upgrade");\r
- settings.setValue("checkForUpdates", value);\r
- settings.endGroup(); \r
- }\r
- public static String getUpdatesAvailableUrl() {\r
- settings.beginGroup("Upgrade");\r
- String text = (String)settings.value("avialableUrl", "http://nevernote.sourceforge.net/versions.txt");\r
- settings.endGroup(); \r
- return text;\r
- }\r
- public static String getUpdateAnnounceUrl() {\r
- settings.beginGroup("Upgrade");\r
- String text = (String)settings.value("announceUrl", "http://nevernote.sourceforge.net/upgrade.html");\r
- settings.endGroup(); \r
- return text;\r
- }\r
- \r
- //*******************\r
- // Index settings\r
- //*******************\r
- // Set/Get if we should index the text of a note\r
- public static boolean indexNoteBody() {\r
- settings.beginGroup("Index");\r
- try {\r
- String value = (String)settings.value("indexNoteBody", "true");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("indexNoteBody", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setIndexNoteTitle(boolean value) {\r
- settings.beginGroup("Index");\r
- settings.setValue("indexNoteTitle", value);\r
- settings.endGroup(); \r
- }\r
- // Set/Get if we should index the title of a note\r
- public static boolean indexNoteTitle() {\r
- settings.beginGroup("Index");\r
- try {\r
- String value = (String)settings.value("indexNoteTitle", "true");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("indexNoteTitle", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setIndexNoteBody(boolean value) {\r
- settings.beginGroup("Index");\r
- settings.setValue("indexNoteBody", value);\r
- settings.endGroup(); \r
- }\r
- // Set/Get if we should index any attachments\r
- public static boolean indexAttachmentsLocally() {\r
- settings.beginGroup("Index");\r
- try {\r
- String value = (String)settings.value("indexAttachmentsLocally", "true");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("indexAttachmentsLocally", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setIndexImageRecognition(boolean value) {\r
- settings.beginGroup("Index");\r
- settings.setValue("indexImageRecognition", value);\r
- settings.endGroup(); \r
- }\r
- public static boolean indexImageRecognition() {\r
- settings.beginGroup("Index");\r
- try {\r
- String value = (String)settings.value("indexImageRecognition", "true");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("indexImageRecognition", true);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setIndexAttachmentsLocally(boolean value) {\r
- settings.beginGroup("Index");\r
- settings.setValue("indexAttachmentsLocally", value);\r
- settings.endGroup(); \r
- }\r
- // Get/Set characters that shouldn't be removed from a word\r
- public static String getSpecialIndexCharacters() {\r
- settings.beginGroup("Index");\r
- String text = (String)settings.value("specialCharacters", "");\r
- settings.endGroup(); \r
- return text;\r
- }\r
- public static void setSpecialIndexCharacters(String value) {\r
- settings.beginGroup("Index");\r
- settings.setValue("specialCharacters", value);\r
- settings.endGroup(); \r
- databaseCache = value;\r
- }\r
- \r
- //*****************************************************************************\r
- // Control how tag selection behaves (should they be "and" or "or" selections\r
- //*****************************************************************************\r
- public static boolean anyTagSelectionMatch() {\r
- settings.beginGroup("General");\r
- try {\r
- String value = (String)settings.value("anyTagSelectionMatch", "false");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("anyTagSelectionMatch", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setAnyTagSelectionMatch(boolean value) {\r
- settings.beginGroup("General");\r
- settings.setValue("anyTagSelectionMatch", value);\r
- settings.endGroup(); \r
- }\r
-\r
- //*****************************************************************************\r
- // Control if a user receives a warning when trying to create a note-to-note link\r
- // when the DB is not synchronized.\r
- //*****************************************************************************\r
- public static boolean bypassSynchronizationWarning() {\r
- settings.beginGroup("User");\r
- try {\r
- String value = (String)settings.value("bypassSynchronizationWarning", "false");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("bypassSynchronizationWarning", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
- }\r
- public static void setBypassSynchronizationWarning(boolean value) {\r
- settings.beginGroup("User");\r
- settings.setValue("bypassSynchronizationWarning", value);\r
- settings.endGroup(); \r
- }\r
-\r
- \r
- //***********************\r
- //* Database cache size\r
- //***********************\r
- public static String getDatabaseCacheSize() {\r
- settings.beginGroup("Debug");\r
- String text = (String)settings.value("databaseCache", "16384");\r
- settings.endGroup(); \r
- return text;\r
- }\r
- public static void setDatabaseCache(String value) {\r
- settings.beginGroup("Debug");\r
- settings.setValue("databaseCache", value);\r
- settings.endGroup(); \r
- databaseCache = value;\r
- }\r
-\r
- \r
- // This is used to copy a class since Java's normal deep copy is wacked\r
- public static Object deepCopy(Object oldObj) \r
- {\r
- ObjectOutputStream oos = null;\r
- ObjectInputStream ois = null;\r
- try\r
- {\r
- ByteArrayOutputStream bos = \r
- new ByteArrayOutputStream(); // A\r
- oos = new ObjectOutputStream(bos); // B\r
- // serialize and pass the object\r
- oos.writeObject(oldObj); // C\r
- oos.flush(); // D\r
- ByteArrayInputStream bin = \r
- new ByteArrayInputStream(bos.toByteArray()); // E\r
- ois = new ObjectInputStream(bin); // F\r
- // return the new object\r
- return ois.readObject(); // G\r
- }\r
- catch(Exception e)\r
- {\r
- Global.logger.log(logger.LOW, "Exception in ObjectCloner = " + e);\r
- }\r
- try {\r
- oos.close();\r
- ois.close();\r
- } catch (IOException e) {\r
- Global.logger.log(logger.LOW, "Exception in ObjectCloner = " + e);\r
- e.printStackTrace();\r
- }\r
-\r
- return null;\r
- }\r
-\r
- // If we should automatically select the children of any tag\r
- public static boolean includeTagChildren() {\r
- settings.beginGroup("General");\r
- try {\r
- String value = (String)settings.value("includeTagChildren", "false");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("includeTagChildren", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
-\r
- }\r
- public static void setIncludeTagChildren(boolean value) {\r
- settings.beginGroup("General");\r
- settings.setValue("includeTagChildren", value);\r
- settings.endGroup(); \r
- }\r
- \r
- // If we should automatically wildcard searches\r
- public static boolean automaticWildcardSearches() {\r
- settings.beginGroup("General");\r
- try {\r
- String value = (String)settings.value("automaticWildcard", "false");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("automaticWildcard", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
-\r
- }\r
- public static void setAutomaticWildcardSearches(boolean value) {\r
- settings.beginGroup("General");\r
- settings.setValue("automaticWildcard", value);\r
- settings.endGroup(); \r
- }\r
-\r
- // If we should automatically select the children of any tag\r
- public static boolean displayRightToLeft() {\r
- settings.beginGroup("General");\r
- try {\r
- String value = (String)settings.value("displayRightToLeft", "false");\r
- settings.endGroup();\r
- if (value.equals("true"))\r
- return true;\r
- else\r
- return false;\r
- } catch (java.lang.ClassCastException e) {\r
- Boolean value = (Boolean) settings.value("displayRightToLeft", false);\r
- settings.endGroup();\r
- return value;\r
- }\r
-\r
- }\r
- public static void setDisplayRightToLeft(boolean value) {\r
- settings.beginGroup("General");\r
- settings.setValue("displayRightToLeft", value);\r
- settings.endGroup(); \r
- }\r
-\r
-\r
- //***********************\r
- //* Startup Notebook\r
- //***********************\r
- public static String getStartupNotebook() {\r
- settings.beginGroup("General");\r
- String text = (String)settings.value("startupNotebook", "");\r
- settings.endGroup(); \r
- return text;\r
- }\r
- public static void setStartupNotebook(String value) {\r
- settings.beginGroup("General");\r
- settings.setValue("startupNotebook", value);\r
- settings.endGroup(); \r
- databaseCache = value;\r
- }\r
-}\r
-\r
+/*
+ * This file is part of NixNote/NeighborNote
+ * Copyright 2009 Randy Baumgarte
+ * Copyright 2013 Yuki Takahashi
+ *
+ * This file may be licensed under the terms of of the
+ * GNU General Public License Version 2 (the ``GPL'').
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the GPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the GPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+*/
+
+package cx.fbn.nevernote;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import com.evernote.edam.type.Accounting;
+import com.evernote.edam.type.PrivilegeLevel;
+import com.evernote.edam.type.User;
+import com.evernote.edam.type.UserAttributes;
+import com.swabunga.spell.engine.Configuration;
+import com.trolltech.qt.core.QByteArray;
+import com.trolltech.qt.core.QFile;
+import com.trolltech.qt.core.QSettings;
+import com.trolltech.qt.core.QSize;
+import com.trolltech.qt.gui.QPalette;
+import com.trolltech.qt.gui.QSystemTrayIcon;
+
+import cx.fbn.nevernote.config.FileManager;
+import cx.fbn.nevernote.config.InitializationException;
+import cx.fbn.nevernote.config.StartupConfig;
+import cx.fbn.nevernote.gui.ContainsAttributeFilterTable;
+import cx.fbn.nevernote.gui.DateAttributeFilterTable;
+import cx.fbn.nevernote.gui.ShortcutKeys;
+import cx.fbn.nevernote.sql.DatabaseConnection;
+import cx.fbn.nevernote.sql.driver.NSqlQuery;
+import cx.fbn.nevernote.utilities.ApplicationLogger;
+import cx.fbn.nevernote.utilities.Pair;
+
+
+//*****************************************************
+//*****************************************************
+//* Global constants & static functions used by
+//* multiple threads.
+//*****************************************************
+//*****************************************************
+
+public class Global {
+ // Set current version and the known versions.
+ public static String version = "0.3";
+ public static String[] validVersions = {"0.3", "0.2", "0.1.3", "0.1.2", "0.1.1", "0.1"};
+
+ public static String username = "";
+ //public static String password = "";
+
+
+ // Each thread has an ID. This is used primarily to check the status
+ // of running threads.
+ public static final int mainThreadId=0;
+ public static final int syncThreadId=1;
+ public static final int tagCounterThreadId=2;
+ public static final int trashCounterThreadId=3; // This should always be the highest thread ID
+ public static final int indexThreadId=4; // Thread for indexing words
+ public static final int saveThreadId=5; // Thread used for processing data to saving content
+ public static final int notebookCounterThreadId=6; // Notebook Thread
+ public static final int indexThread03Id=7; // unused
+ public static final int indexThread04Id=8; // unused
+ public static final int dbThreadId=9; // This should always be the highest thread ID
+ public static final int threadCount = 10;
+
+
+ // These variables deal with where the list of notes appears
+ // They will either be vertical (View_List_Narrow) or will be
+ // on top of the note (View_List_Wide). It also has the size of
+ // thumbnails displayed in each view
+ public static int View_List_Wide = 1;
+ public static int View_List_Narrow = 2;
+ public static QSize smallThumbnailSize = new QSize(100,75);
+ public static QSize largeThumbnailSize = new QSize(300,225);
+
+ // This is used to keep a running list of passwords that the user
+ // wants us to remember.
+ public static HashMap<String,Pair<String,String>> passwordSafe = new HashMap<String, Pair<String,String>>();
+ public static List<Pair<String,String>> passwordRemember = new ArrayList<Pair<String,String>>();
+
+
+ //public static String currentNotebookGuid;
+
+ // These deal with Evernote user settings
+ public static User user;
+ public static long authTimeRemaining;
+ public static long authRefreshTime;
+ public static long failedRefreshes = 0;
+ public static String userStoreUrl;
+ public static String noteStoreUrl;
+ public static String noteStoreUrlBase;
+
+ // When we want to shut down we set this to true to short
+ // circut other threads
+ public static boolean keepRunning;
+
+ // In the note list, these are the column numbers
+ // so I don't need to hard code numbers.
+ public static int noteTableCreationPosition = 0;
+ public static int noteTableTitlePosition = 1;
+ public static int noteTableTagPosition = 2;
+ public static int noteTableNotebookPosition = 3;
+ public static int noteTableChangedPosition = 4;
+ public static int noteTableGuidPosition = 5;
+ public static int noteTableAuthorPosition = 6;
+ public static int noteTableSourceUrlPosition = 7;
+ public static int noteTableSubjectDatePosition = 8;
+ public static int noteTableSynchronizedPosition = 9;
+ public static int noteTableThumbnailPosition = 10;
+ public static int noteTablePinnedPosition = 11;
+ public static int noteTableColumnCount = 12;
+ public static Integer cryptCounter = 0;
+
+ //public static int minimumWordCount = 2;
+
+ // Regular expression to parse text with when indexing
+// private static String wordRegex;
+
+ // Experimental fixes. Set via Edit/Preferences/Debugging
+ public static boolean enableCarriageReturnFix = false;
+ public static boolean enableHTMLEntitiesFix = false;
+
+ // Used to set & retrieve ini & Windows registry settings
+ public static QSettings settings; // Set & get ini settings
+ public static boolean isConnected; // Are we connected to Evernote
+ public static boolean showDeleted = false; // Show deleted notes?
+ public static boolean disableUploads = false; // Should we disable uploads (used in testing features)
+ public static int messageLevel; // The level of messages to write to the log files
+ public static String tagDelimeter = ","; // This is used to separate out tag names when entering above note
+ public static String attachmentNameDelimeter = "------"; // Used to separate out attachment names in the res directory
+
+
+ //* Database fields
+ public static String databaseName = new String("NeverNote"); // database name. used for multiple databases to separate settings.
+ public static String indexDatabaseName = new String("Index"); // searchable words database
+ public static String resourceDatabaseName = new String("Resources"); // attachments database
+ public static String behaviorDatabaseName = new String("Behavior"); // 操作履歴データベース
+
+ public static DateAttributeFilterTable createdSinceFilter;
+ public static DateAttributeFilterTable createdBeforeFilter;
+ public static DateAttributeFilterTable changedSinceFilter;
+ public static DateAttributeFilterTable changedBeforeFilter;
+ public static ContainsAttributeFilterTable containsFilter;
+
+ // Log file used for debugging
+ public static ApplicationLogger logger;
+ //PrintStream stdoutStream;
+
+ // Application key shortcuts & appearance
+ public static QPalette originalPalette;
+ public static ShortcutKeys shortcutKeys;
+
+ public static boolean disableViewing; // used to disable the editor
+
+ // When saving a note, this is a list of things we strip out because Evernote hates them
+ public static List<String> invalidElements = new ArrayList<String>();
+ public static HashMap<String, ArrayList<String>> invalidAttributes = new HashMap<String, ArrayList<String>>();
+
+ public static boolean mimicEvernoteInterface; // Try to mimic Evernote or allow multiple notebook selection
+ public static HashMap<String,String> resourceMap; // List of attachments for a note.
+ public static String cipherPassword = ""; // If the database is encrypted, this stores the password
+ public static String databaseCache = "16384"; // Default DB cache size
+
+ // These are used for performance testing
+ static Calendar startTraceTime;
+ static Calendar intervalTraceTime;
+
+ static boolean syncOnly;
+
+ private static FileManager fileManager; // Used to access files & directories
+
+ // Do initial setup
+ public static void setup(StartupConfig startupConfig) throws InitializationException {
+ String settingFileName = new String("NeighborNote.ini");
+
+ // バージョン0.1.2以下で作成された古い設定ファイルを見つけたら、ホームディレクトリに移動させる。
+ String oldSettingPath = new QSettings(settingFileName, QSettings.Format.IniFormat).fileName();
+ File homeDir = new File(FileManager.toPlatformPathSeparator(startupConfig.getHomeDirPath()));
+ String homePath = FileManager.slashTerminatePath(homeDir.getPath());
+ if (QFile.exists(oldSettingPath)) {
+ QFile file = new QFile(oldSettingPath);
+ file.copy(homePath + settingFileName);
+ file.remove();
+ }
+
+ settings = new QSettings(homePath + settingFileName, QSettings.Format.IniFormat);
+
+ disableViewing = startupConfig.getDisableViewing();
+ syncOnly = startupConfig.isSyncOnly();
+
+ fileManager = new FileManager(startupConfig.getHomeDirPath(), startupConfig.getProgramDirPath());
+
+
+ getServer(); // Setup URL to connect to
+
+ // Get regular expressions used to parse out words
+// settings.beginGroup("General");
+// String regex = (String) settings.value("regex", "[,\\s]+");
+// setWordRegex(regex);
+// settings.endGroup();
+
+ //Setup debugging information
+ settings.beginGroup("Debug");
+ String msglevel = (String) settings.value("messageLevel", "Low");
+ settings.endGroup();
+
+
+ //messageLevel = 1;
+ setMessageLevel(msglevel);
+ keepRunning = true; // Make sure child threads stay running
- disableUploads = disableUploads(); // Should we upload anything? Normally false.\r
- //disableUploads = true; //***** DELETE THIS LINE *******\r
++ disableUploads = disableUploads(); // Should we upload anything? Normally false.
++ //disableUploads = true; //***** DELETE THIS LINE *******
+ enableCarriageReturnFix = enableCarriageReturnFix(); // Enable test fix?
+ enableHTMLEntitiesFix = enableHtmlEntitiesFix(); // Enable test fix?
+
+ logger = new ApplicationLogger("global.log"); // Setup log for this class
+ shortcutKeys = new ShortcutKeys(); // Setup keyboard shortcuts.
+ mimicEvernoteInterface = getMimicEvernoteInterface(); // Should we mimic Evernote's notebook behavior
+ resourceMap = new HashMap<String,String>(); // Setup resource map used to store attachments when editing
+
+ databaseCache = getDatabaseCacheSize(); // Set database cache size
+
+ Global.username = getUserInformation().getUsername();
+ }
+
+ // Get/Set word parsing regular expression
+// public static String getWordRegex() {
+// return wordRegex;
+// }
+// public static void setWordRegex(String r) {
+// wordRegex = r;
+// }
+
+ // Set the debug message level
+ public static void setMessageLevel(String msglevel) {
+ if (msglevel.equalsIgnoreCase("low"))
+ messageLevel = 1;
+ if (msglevel.equalsIgnoreCase("medium"))
+ messageLevel = 2;
+ if (msglevel.equalsIgnoreCase("high"))
+ messageLevel = 3;
+ if (msglevel.equalsIgnoreCase("extreme"))
+ messageLevel = 4;
+ settings.beginGroup("Debug");
+ settings.setValue("messageLevel", msglevel);
+ settings.endGroup();
+ }
+
+ //****************************************************
+ //****************************************************
+ //** Save user account information from Evernote
+ //****************************************************
+ //****************************************************
+ public static void saveUserInformation(User user) {
+ settings.beginGroup("User");
+ settings.setValue("id", user.getId());
+ settings.setValue("username", user.getUsername());
+ settings.setValue("email", user.getEmail());
+ settings.setValue("name", user.getName());
+ settings.setValue("timezone", user.getTimezone());
+ settings.setValue("privilege", user.getPrivilege().getValue());
+ settings.setValue("created", user.getCreated());
+ settings.setValue("updated", user.getUpdated());
+ settings.setValue("deleted", user.getDeleted());
+ settings.setValue("shard", user.getShardId());
+ settings.endGroup();
+ isPremium();
+ if (user.getAttributes()!=null)
+ saveUserAttributes(user.getAttributes());
+ if (user.getAccounting()!=null)
+ saveUserAccounting(user.getAccounting());
+
+ }
+ public static User getUserInformation() {
+ User user = new User();
+ settings.beginGroup("User");
+ try {
+ user.setId((Integer)settings.value("id", 0));
+ } catch (java.lang.ClassCastException e) {
+ user.setId(new Integer((String)settings.value("id", "0")));
+ }
+ String username = (String)settings.value("username", "");
+ String email = (String)settings.value("email", "");
+ String name = (String)settings.value("name", "");
+ String timezone = (String)settings.value("timezone", "");
+ Integer privilege = 0;
+ try {
+ privilege = new Integer((String)settings.value("privilege", "0"));
+ } catch (java.lang.ClassCastException e) {
+ privilege = (Integer)settings.value("privilege", 0);
+ }
+
+ try {
+ String date = (String)settings.value("created", "0");
+ user.setCreated(new Long(date));
+ date = (String)settings.value("updated", "0");
+ user.setUpdated(new Long(date));
+ date = (String)settings.value("deleted", "0");
+ user.setDeleted(new Long(date));
+ } catch (java.lang.ClassCastException e) {
+ Long date = (Long)settings.value("created", 0);
+ user.setCreated(date);
+ date = (Long)settings.value("updated", 0);
+ user.setUpdated(date);
+ date = (Long)settings.value("deleted", 0);
+ user.setDeleted(date);
+ }
+
+ String shard = (String)settings.value("shard", "");
+ settings.endGroup();
+
+ user.setUsername(username);
+ user.setEmail(email);
+ user.setName(name);
+ user.setTimezone(timezone);
+ PrivilegeLevel userLevel = PrivilegeLevel.findByValue(privilege);
+ user.setPrivilege(userLevel);
+ user.setShardId(shard);
+ return user;
+ }
+
+ public static void saveUserAttributes(UserAttributes attrib) {
+ settings.beginGroup("UserAttributes");
+ settings.setValue("defaultLocationName", attrib.getDefaultLocationName());
+ settings.setValue("defaultLatitude", attrib.getDefaultLocationName());
+ settings.setValue("defaultLongitude", attrib.getDefaultLocationName());
+ settings.setValue("incomingEmailAddress", attrib.getIncomingEmailAddress());
+ settings.endGroup();
+ }
+ public static UserAttributes getUserAttributes() {
+ settings.beginGroup("UserAttributes");
+ UserAttributes attrib = new UserAttributes();
+ attrib.setDefaultLocationName((String)settings.value("defaultLocationName",""));
+ attrib.setDefaultLatitudeIsSet(false);
+ attrib.setDefaultLongitudeIsSet(false);
+ attrib.setIncomingEmailAddress((String)settings.value("incomingEmailAddress", ""));
+ settings.endGroup();
+ return attrib;
+ }
+ public static void saveUserAccounting(Accounting acc) {
+ settings.beginGroup("UserAccounting");
+ settings.setValue("uploadLimit", acc.getUploadLimit());
+ settings.setValue("uploadLimitEnd", acc.getUploadLimitEnd());
+ settings.setValue("uploadLimitNextMonth", acc.getUploadLimitNextMonth());
+ settings.setValue("premiumServiceStart", acc.getPremiumServiceStart());
+ settings.setValue("nextPaymentDue", acc.getNextPaymentDue());
+ settings.setValue("uploadAmount", acc.getUpdated());
+ settings.endGroup();
+ }
+ public static long getUploadLimitEnd() {
+ Long limit;
+ settings.beginGroup("UserAccounting");
+
+ // Upload limit
+ try {
+ String val = (String)settings.value("uploadLimitEnd", "0");
+ limit = new Long(val.trim());
+ } catch (Exception e) {
+ try {
+ limit = (Long)settings.value("uploadLimitEnd", 0);
+ } catch (Exception e1) {
+ limit = new Long(0);
+ }
+ }
+
+ // return value
+ settings.endGroup();
+ return limit;
+ }
+ public static void saveUploadAmount(long amount) {
+ settings.beginGroup("UserAccounting");
+ settings.setValue("uploadAmount", amount);
+ settings.endGroup();
+ }
+ public static long getUploadAmount() {
+ long amt=0;
+ settings.beginGroup("UserAccounting");
+ try {
+ String num = (String)settings.value("uploadAmount", "0");
+ amt = new Long(num.trim());
+ } catch (Exception e) {
+ try {
+ amt = (Integer)settings.value("uploadAmount", 0);
+ } catch (Exception e1) {
+ amt = 0;
+ }
+ }
+ settings.endGroup();
+ return amt;
+ }
+ public static void saveEvernoteUpdateCount(long amount) {
+ settings.beginGroup("UserAccounting");
+ settings.setValue("updateCount", amount);
+ settings.endGroup();
+ }
+ public static long getEvernoteUpdateCount() {
+ long amt;
+ settings.beginGroup("UserAccounting");
+ try {
+ String num = (String)settings.value("updateCount", new Long(0).toString());
+ amt = new Long(num.trim());
+ } catch (java.lang.ClassCastException e) {
+ amt = 0;
+ }
+ settings.endGroup();
+ return amt;
+ }
+ public static boolean isPremium() {
+ int level;
+ settings.beginGroup("User");
+ try {
+ String num = (String)settings.value("privilege", "1");
+ level = new Integer(num.trim());
+ } catch (java.lang.ClassCastException e) {
+ try {
+ level = (Integer)settings.value("privilege", 1);
+ } catch (Exception e1) {
+ level = 1;
+ }
+ }
+ settings.endGroup();
+ PrivilegeLevel userLevel = PrivilegeLevel.findByValue(level);
+ if (userLevel == PrivilegeLevel.NORMAL)
+ return false;
+ return true;
+
+ }
+ public static long getUploadLimit() {
+ settings.beginGroup("UserAccounting");
+ long limit;
+ try {
+ String num = (String)settings.value("uploadLimit", new Long(0).toString());
+ limit = new Long(num.trim());
+ } catch (java.lang.ClassCastException e) {
+ limit = 0;
+ }
+ settings.endGroup();
+ return limit;
+ }
+
+
+
+ //****************************************************
+ //****************************************************
+ //** View settings. Used to restore settings
+ //** when starting and to control how the program
+ //** behaves.
+ //****************************************************
+ //****************************************************
+
+ //* Get/Set if we should show a tray icon
+ public static boolean showTrayIcon() {
+ settings.beginGroup("General");
+ try {
+ String max = (String) settings.value("showTrayIcon", "false");
+ settings.endGroup();
+ if (!max.equalsIgnoreCase("true") || !QSystemTrayIcon.isSystemTrayAvailable())
+ return false;
+ else
+ return true;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("showTrayIcon", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setShowTrayIcon(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("showTrayIcon", "true");
+ else
+ settings.setValue("showTrayIcon", "false");
+ settings.endGroup();
+ }
+
+ // Get/Set window maximized when closed last
+ public static boolean wasWindowMaximized() {
+ try {
+ settings.beginGroup("General");
+ String max = (String) settings.value("isMaximized", "true");
+ settings.endGroup();
+ if (!max.equalsIgnoreCase("true"))
+ return false;
+ return true;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("isMaximized", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveWindowMaximized(boolean isMax) {
+ settings.beginGroup("General");
+ if (isMax)
+ settings.setValue("isMaximized", "true");
+ else
+ settings.setValue("isMaximized", "false");
+ settings.endGroup();
+ }
+
+ // Get/set currently viewed note Guid
+ public static String getLastViewedNoteGuid() {
+ settings.beginGroup("General");
+ String guid = (String) settings.value("lastViewedNote", "");
+ settings.endGroup();
+ return guid;
+ }
+ public static void saveCurrentNoteGuid(String guid) {
+ settings.beginGroup("General");
+ if (guid != null)
+ settings.setValue("lastViewedNote", guid);
+ else
+ settings.setValue("lastViewedNote", "");
+ settings.endGroup();
+ }
+
+ // Get/Set the note column we are sorted on and the order
+ public static void setSortColumn(int i) {
+ int view = Global.getListView();
+ settings.beginGroup("General");
+ if (view == Global.View_List_Wide)
+ settings.setValue("sortColumn", i);
+ else
+ settings.setValue("sortColumn-Narrow", i);
+ settings.endGroup();
+ }
+ public static int getSortColumn() {;
+ String key;
+ if (Global.getListView() == Global.View_List_Wide)
+ key = "sortColumn";
+ else
+ key = "sortColumn-Narrow";
+
+ settings.beginGroup("General");
+ int order;
+ try {
+ String val = settings.value(key, new Integer(0)).toString();
+ order = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ order = (Integer)settings.value(key, 0);
+ } catch (Exception e1) {
+ order = 0;
+ }
+ }
+
+ settings.endGroup();
+ return order;
+ }
+ public static void setSortOrder(int i) {
+ int view = Global.getListView();
+ settings.beginGroup("General");
+ if (view == Global.View_List_Wide)
+ settings.setValue("sortOrder", i);
+ else
+ settings.setValue("sortOrder-Narrow", i);
+ settings.endGroup();
+ }
+ public static int getSortOrder() {
+ int view = Global.getListView();
+ settings.beginGroup("General");
+ String key;
+ if (view == Global.View_List_Wide)
+ key = "sortOrder";
+ else
+ key = "sortOrder-Narrow";
+
+ int order;
+ try {
+ String val = settings.value(key, new Integer(0)).toString();
+ order = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ order = (Integer)settings.value(key, 0);
+ } catch (Exception e1) {
+ order = 0;
+ }
+ }
+
+ settings.endGroup();
+ return order;
+ }
+
+ // Should we automatically log in to Evernote when starting?
+ public static boolean automaticLogin() {
+ try {
+ settings.beginGroup("General");
+ String text = (String)settings.value("automaticLogin", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("automaticLogin", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setAutomaticLogin(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("automaticLogin", "true");
+ else
+ settings.setValue("automaticLogin", "false");
+ settings.endGroup();
+ }
+
+ // Get/set the Evernote server Url.
+ public static void setServer(String server) {
+ settings.beginGroup("General");
+ settings.setValue("server", server);
+ settings.endGroup();
+ }
+ public static String getServer() {
+ settings.beginGroup("General");
+ String text = (String)settings.value("server", "www.evernote.com");
+ if (text.equals("www.evernote.com")) {
+ userStoreUrl = "https://www.evernote.com/edam/user";
+ noteStoreUrlBase = "www.evernote.com/edam/note/";
+ } else {
+ userStoreUrl = "https://sandbox.evernote.com/edam/user";
+ noteStoreUrlBase = "sandbox.evernote.com/edam/note/";
+ }
+ settings.endGroup();
+// if (isPremium())
+ noteStoreUrlBase = "https://" + noteStoreUrlBase;
+// else
+// noteStoreUrlBase = "http://" + noteStoreUrlBase;
+ return text;
+ }
+
+ // Get/Set if we should disable uploads to Evernote
+ public static boolean disableUploads() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("disableUploads", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("disableUploads", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setDisableUploads(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("disableUploads", "true");
+ else
+ settings.setValue("disableUploads", "false");
+ settings.endGroup();
+ disableUploads = val;
+ }
+
+ // Should we view PDF documents inline?
+ public static boolean pdfPreview() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("pdfPreview", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("pdfPreview", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setPdfPreview(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("pdfPreview", "true");
+ else
+ settings.setValue("pdfPreview", "false");
+ settings.endGroup();
+ }
+
+ // When creating a new note, should it inherit tags that are currently selected?
+ public static boolean newNoteWithSelectedTags() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("newNoteWithSelectedTags", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("newNoteWithSelectedTags", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setNewNoteWithSelectedTags(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("newNoteWithSelectedTags", "true");
+ else
+ settings.setValue("newNoteWithSelectedTags", "false");
+ settings.endGroup();
+ }
+
+ // Minimum weight for text OCRed from Evernote. Anything below this
+ // Won't be shown to the user when they search
+ public static void setRecognitionWeight(int len) {
+ settings.beginGroup("General");
+ settings.setValue("recognitionWeight", len);
+ settings.endGroup();
+ }
+ public static int getRecognitionWeight() {
+ settings.beginGroup("General");
+ Integer len;
+ try {
- len = (Integer)settings.value("recognitionWeight", 30);\r
++ len = (Integer)settings.value("recognitionWeight", 30);
+ } catch (Exception e) {
- len = 80;\r
++ len = 80;
+ }
+ settings.endGroup();
+ return len;
+ }
+
+ // get/set current debug message level
+ public static String getMessageLevel() {
+ settings.beginGroup("Debug");
+ String text = (String)settings.value("messageLevel", "Low");
+ settings.endGroup();
+ setMessageLevel(text);
+ return text;
+ }
+ public static void setDateFormat(String format) {
+ settings.beginGroup("General");
+ settings.setValue("dateFormat", format);
+ settings.endGroup();
+ }
+
+ // Get/Set user date/time formats
+ public static String getDateFormat() {
+ settings.beginGroup("General");
+ String text = (String)settings.value("dateFormat", "MM/dd/yyyy");
+ settings.endGroup();
+ return text;
+ }
+ public static void setTimeFormat(String format) {
+ settings.beginGroup("General");
+ settings.setValue("timeFormat", format);
+ settings.endGroup();
+ }
+ public static String getTimeFormat() {
+ settings.beginGroup("General");
+ String text = (String)settings.value("timeFormat", "HH:mm:ss");
+ settings.endGroup();
+ return text;
+ }
+
+ // How often should we sync with Evernote?
+ public static String getSyncInterval() {
+ settings.beginGroup("General");
+ String text = (String)settings.value("syncInterval", "15 minutes");
+ settings.endGroup();
+ return text;
+ }
+ public static void setSyncInterval(String format) {
+ settings.beginGroup("General");
+ settings.setValue("syncInterval", format);
+ settings.endGroup();
+ }
+
+ // Get/Set the width of columns and their position for the
+ // next start.
+ public static void setColumnWidth(String col, int width) {
+ if (Global.getListView() == Global.View_List_Wide)
+ settings.beginGroup("ColumnWidths");
+ else
+ settings.beginGroup("ColumnWidths-Narrow");
+ settings.setValue(col, width);
+ settings.endGroup();
+ }
+ public static int getColumnWidth(String col) {
+ int view = Global.getListView();
+ if (view == Global.View_List_Wide)
+ settings.beginGroup("ColumnWidths");
+ else
+ settings.beginGroup("ColumnWidths-Narrow");
+ Integer width;
+ try {
+ String val = (String)settings.value(col, "0");
+ width = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ width = (Integer)settings.value(col, 0);
+ } catch (Exception e1) {
+ width = 0;
+ }
+ }
+ settings.endGroup();
+ return width;
+ }
+ public static void setColumnPosition(String col, int width) {
+ if (Global.getListView() == Global.View_List_Wide)
+ settings.beginGroup("ColumnPosition");
+ else
+ settings.beginGroup("ColumnPosition-Narrow");
+ settings.setValue(col, width);
+ settings.endGroup();
+ }
+ public static int getColumnPosition(String col) {
+ if (Global.getListView() == Global.View_List_Wide)
+ settings.beginGroup("ColumnPosition");
+ else
+ settings.beginGroup("ColumnPosition-Narrow");
+ Integer width;
+ try {
+ String val = (String)settings.value(col, "-1");
+ width = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ width = (Integer)settings.value(col, 0);
+ } catch (Exception e1) {
+ width = 0;
+ }
+ }
+ settings.endGroup();
+ return width;
+ }
+
+ // Ping the user when they try to delete or just do it.
+ public static boolean verifyDelete() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("verifyDelete", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("verifyDelete", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setVerifyDelete(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("verifyDelete", "true");
+ else
+ settings.setValue("verifyDelete", "false");
+ settings.endGroup();
+ }
+
+ // Should it start minimized?
+ public static boolean startMinimized() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("startMinimized", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("startMinimized", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setStartMinimized(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("startMinimized", "true");
+ else
+ settings.setValue("startMinimized", "false");
+ settings.endGroup();
+ }
+
+ // Should we upload the content of any deleted notes
+ public static boolean synchronizeDeletedContent() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("syncDeletedContent", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("syncDeletedContent", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setSynchronizeDeletedContent(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("syncDeletedContent", "true");
+ else
+ settings.setValue("syncDeletedContent", "false");
+ settings.endGroup();
+ }
+
+ // Is a section of the window visible? Used to hide things people don't
+ // want to see.
+ public static boolean isWindowVisible(String window) {
+ settings.beginGroup("WindowsVisible");
+ try {
+ String defaultValue = "true";
+ if (window.equalsIgnoreCase("noteInformation"))
+ defaultValue = "false";
+ String text = (String)settings.value(window, defaultValue);
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ boolean defaultValue = true;
+ if (window.equalsIgnoreCase("noteInformation"))
+ defaultValue = false;
+ Boolean value = (Boolean) settings.value("showTrayIcon", defaultValue);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveWindowVisible(String window, boolean val) {
+ settings.beginGroup("WindowsVisible");
+ if (val)
+ settings.setValue(window, "true");
+ else
+ settings.setValue(window, "false");
+ settings.endGroup();
+ }
+
+ // Is a list in the column in the note list visible?
+ public static boolean isColumnVisible(String window) {
+ String defaultValue = "true";
+ int view = Global.getListView();
+ if (Global.getListView() == Global.View_List_Wide)
+ settings.beginGroup("ColumnsVisible");
+ else
+ settings.beginGroup("ColumnsVisible-Narrow");
+ if (window.equalsIgnoreCase("thumbnail") && view == Global.View_List_Wide)
+ defaultValue = "false";
+ if (window.equalsIgnoreCase("thumbnail"))
+ defaultValue = "false";
+ if (window.equalsIgnoreCase("Guid"))
+ defaultValue = "false";
+ try {
+ String text = (String)settings.value(window, defaultValue);
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ boolean defBool = false;
+ if (window.equalsIgnoreCase("true"))
+ defBool = true;
+ else
+ defBool = false;
+ Boolean value = (Boolean) settings.value(window, defBool);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveColumnVisible(String column, boolean val) {
+ if (Global.getListView() == Global.View_List_Wide)
+ settings.beginGroup("ColumnsVisible");
+ else
+ settings.beginGroup("ColumnsVisible-Narrow");
+ if (val)
+ settings.setValue(column, "true");
+ else
+ settings.setValue(column, "false");
+ settings.endGroup();
+ }
+
+ // Is a particular editor button visible?
+ public static boolean isEditorButtonVisible(String window) {
+ settings.beginGroup("EditorButtonsVisible");
+ try {
+ String text = (String)settings.value(window, "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value(window, true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveEditorButtonsVisible(String column, boolean val) {
+ settings.beginGroup("EditorButtonsVisible");
+ if (val)
+ settings.setValue(column, "true");
+ else
+ settings.setValue(column, "false");
+ settings.endGroup();
+ }
+
+ // Should the test fixes be enabled
+ public static boolean enableCarriageReturnFix() {
+ try {
+ settings.beginGroup("Debug");
+ String text = (String)settings.value("enableCarriageReturnFix", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("enableCarriageReturnFix", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveCarriageReturnFix(boolean val) {
+ settings.beginGroup("Debug");
+ if (val)
+ settings.setValue("enableCarriageReturnFix", "true");
+ else
+ settings.setValue("enableCarriageReturnFix", "false");
+ settings.endGroup();
+ }
+ public static boolean enableHtmlEntitiesFix() {
+ try {
+ settings.beginGroup("Debug");
+ String text = (String)settings.value("enableHtmlEntitiesFix", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("enableHtmlEntitiesFix", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveHtmlEntitiesFix(boolean val) {
+ settings.beginGroup("Debug");
+ if (val)
+ settings.setValue("enableHtmlEntitiesFix", "true");
+ else
+ settings.setValue("enableHtmlEntitiesFix", "false");
+ settings.endGroup();
+ }
+
+// public static void setIndexThreads(int val) {
+// settings.beginGroup("General");
+// settings.setValue("indexThreads", val);
+// settings.endGroup();
+// }
+// public static int getIndexThreads() {
+// settings.beginGroup("General");
+// Integer threads;
+// try {
+// String val = (String)settings.value("indexThreads", "1");
+// threads = new Integer(val.trim());
+// } catch (Exception e) {
+// try {
+// threads = (Integer)settings.value("indexThreads", 1);
+// } catch (Exception e1) {
+// threads = 1;
+// }
+// }
+// settings.endGroup();
+// threads = 1;
+// return threads;
+
+ // Get/Set text zoom factor
+// }
+ public static void setZoomFactor(double val) {
+ settings.beginGroup("General");
+ settings.setValue("zoomFactor", val);
+ settings.endGroup();
+ }
+ public static double getZoomFactor() {
+ settings.beginGroup("General");
+ Double threads;
+ try {
+ String val = (String)settings.value("zoomFactor", "1.0");
+ threads = new Double(val.trim());
+ } catch (Exception e) {
+ try {
+ threads = (Double)settings.value("zoomFactor", 1.0);
+ } catch (Exception e1) {
+ threads = new Double(1);
+ }
+ }
+ settings.endGroup();
+ return threads;
+ }
+ public static void setTextSizeMultiplier(double val) {
+ settings.beginGroup("General");
+ settings.setValue("textMultiplier", val);
+ settings.endGroup();
+ }
+ public static double getTextSizeMultiplier() {
+ settings.beginGroup("General");
+ Double threads;
+ try {
+ String val = (String)settings.value("textMultiplier", "1");
+ threads = new Double(val.trim());
+ } catch (Exception e) {
+ try {
+ threads = (Double)settings.value("textMultiplier", 1);
+ } catch (Exception e1) {
+ threads = new Double(1);
+ }
+ }
+ settings.endGroup();
+ return threads;
+ }
+
+
+ // Should we mimic Evernote and restrict the notebooks selected?
+ public static boolean getMimicEvernoteInterface() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("mimicEvernoteInterface", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("mimicEvernoteInterface", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setMimicEvernoteInterface(boolean value) {
+ settings.beginGroup("General");
+ if (value)
+ settings.setValue("mimicEvernoteInterface", "true");
+ else
+ settings.setValue("mimicEvernoteInterface", "false");
+ settings.endGroup();
+ }
+
+
+ // Synchronize with Evernote when closing?
+ public static boolean synchronizeOnClose() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("synchronizeOnClose", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("synchronizeOnClose", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setSynchronizeOnClose(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("synchronizeOnClose", "true");
+ else
+ settings.setValue("synchronizeOnClose", "false");
+ settings.endGroup();
+ }
+
+ // Get/set the database version. Not really used any more, but kept
+ // for compatibility.
+ public static void setDatabaseVersion(String version) {
+ settings.beginGroup("General");
+ settings.setValue("databaseVersion", version);
+ settings.endGroup();
+ }
+ public static String getDatabaseVersion() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("databaseVersion", "0.70");
+ settings.endGroup();
+ return val;
+ }
+
+ // Get the URL (full path) of the main database
+ public static String getDatabaseUrl() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("DatabaseURL", "");
+ settings.endGroup();
+ if (val.equals(""))
+ val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.databaseName);
+ return val;
+ }
+
+ // get the url (full path) of the searchable word database
+ public static String getIndexDatabaseUrl() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("IndexDatabaseURL", "");
+ settings.endGroup();
+ if (val.equals(""))
+ val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.indexDatabaseName);
+ return val;
+ }
+
+ // Get the url (full path) of the attachment database
+ public static String getResourceDatabaseUrl() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("ResourceDatabaseURL", "");
+ settings.endGroup();
+ if (val.equals(""))
+ val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.resourceDatabaseName);
+ return val;
+ }
+
+ // 操作履歴データベースのURL(フルパス)をゲット
+ public static String getBehaviorDatabaseUrl() {
+ settings.beginGroup("General");
+ String val = (String) settings.value("BehaviorDatabaseURL", "");
+ settings.endGroup();
+ if (val.equals(""))
+ val = "jdbc:h2:"
+ + Global.getFileManager().getDbDirPath(
+ Global.behaviorDatabaseName);
+ return val;
+ }
+
+ public static void setDatabaseUrl(String value) {
+ settings.beginGroup("General");
+ settings.setValue("DatabaseURL", value);
+ settings.endGroup();
+ }
+ public static void setIndexDatabaseUrl(String value) {
+ settings.beginGroup("General");
+ settings.setValue("IndexDatabaseURL", value);
+ settings.endGroup();
+ }
+ public static void setResourceDatabaseUrl(String value) {
+ settings.beginGroup("General");
+ settings.setValue("ResourceDatabaseURL", value);
+ settings.endGroup();
+ }
+
+ public static void setBehaviorDatabaseUrl(String value) {
+ settings.beginGroup("General");
+ settings.setValue("BehaviorDatabaseURL", value);
+ settings.endGroup();
+ }
+
+ public static String getDatabaseUserid() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("databaseUserid", "");
+ settings.endGroup();
+ return val;
+ }
+ public static String getDatabaseUserPassword() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("databaseUserPassword", "");
+ settings.endGroup();
+ return val;
+ }
+
+ // get/Set the style sheet and the palette to control the look & feel
+ public static void setStyle(String style) {
+ settings.beginGroup("General");
+ settings.setValue("style", style);
+ settings.endGroup();
+ }
+ public static String getStyle() {
+ settings.beginGroup("General");
+ String val = (String)settings.value("style", "Cleanlooks");
+ settings.endGroup();
+ return val;
+ }
+ public static boolean useStandardPalette() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("standardPalette", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("standardPalette", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setStandardPalette(boolean val) {
+ settings.beginGroup("General");
+ if (val)
+ settings.setValue("standardPalette", "true");
+ else
+ settings.setValue("standardPalette", "false");
+ settings.endGroup();
+ }
+
+ // Set the amount of time to wait between indexing
+ // Get/Set interval when the index thread wakes up.
+ public static void setIndexThreadSleepInterval(int sleep) {
+ settings.beginGroup("General");
+ settings.setValue("IndexThreadSleepInterval", sleep);
+ settings.endGroup();
+ }
+ public static int getIndexThreadSleepInterval() {
+ settings.beginGroup("General");
+ Integer sleep;
+ try {
+ String val = (String)settings.value("IndexThreadSleepInterval", "300");
+ sleep = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ sleep = (Integer)settings.value("IndexThreadSleepInterval", 0);
+ } catch (Exception e1) {
+ sleep = 300;
+ }
+ }
+ settings.endGroup();
+ return sleep;
+ }
+
+
+ // Get/Set a window state for later restoring
+ public static void saveState(String name, QByteArray state) {
+ int view = Global.getListView();
+ if (view == Global.View_List_Narrow)
+ name = name +"Narrow";
+ settings.beginGroup("SaveState");
+ settings.setValue(name, state);
+ settings.endGroup();
+ }
+
+ public static QByteArray restoreState(String name) {
+ int view = Global.getListView();
+ if (view == Global.View_List_Narrow)
+ name = name +"Narrow";
+ settings.beginGroup("SaveState");
+ QByteArray state = (QByteArray)settings.value(name);
+ settings.endGroup();
+ return state;
+ }
+ public static void saveGeometry(String name, QByteArray state) {
+ int view = Global.getListView();
+ if (view == Global.View_List_Narrow)
+ settings.beginGroup("SaveGeometryNarrow");
+ else
+ settings.beginGroup("SaveGeometry");
+ settings.setValue(name, state);
+ settings.endGroup();
+ }
+
+ public static QByteArray restoreGeometry(String name) {
+ int view = Global.getListView();
+ if (view == Global.View_List_Narrow)
+ settings.beginGroup("SaveGeometryNarrow");
+ else
+ settings.beginGroup("SaveGeometry");
+ QByteArray state = (QByteArray)settings.value(name);
+ settings.endGroup();
+ return state;
+ }
+
+
+ // Set how often to do an automatic save
+ public static void setAutoSaveInterval(int interval) {
+ settings.beginGroup("General");
+ settings.setValue("autoSaveInterval", interval);
+ settings.endGroup();
+ }
+ public static int getAutoSaveInterval() {
+ settings.beginGroup("General");
+ Integer value;
+ try {
+ String val = (String)settings.value("autoSaveInterval", "5");
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("autoSaveInterval", 5);
+ } catch (Exception e1) {
+ value = 5;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // Add an invalid attribute & element to the database so we don't bother parsing it in the future
+ // These values we automatically remove from any note.
+ // Add invalid attributes
+ public static void addInvalidAttribute(String element, String attribute) {
+
+ List<String> attributes = invalidAttributes.get(element);
+ if (attributes != null) {
+ for (int i=0; i<attributes.size(); i++)
+ if (attribute.equalsIgnoreCase(attributes.get(i))) {
+ return;
+ }
+ }
+
+ ArrayList<String> attributeList;
+ if (!invalidAttributes.containsKey(element)) {
+ attributeList = new ArrayList<String>();
+ attributeList.add(attribute);
+ invalidAttributes.put(element, attributeList);
+ }
+ else {
+ attributeList = invalidAttributes.get(element);
+ attributeList.add(attribute);
+ invalidAttributes.put(element,attributeList);
+ }
+ }
+
+ // Add invalid attributes
+ public static void addInvalidElement(String element) {
+ for (int i=0; i<invalidElements.size(); i++) {
+ if (element.equalsIgnoreCase(invalidElements.get(i)))
+ return;
+ }
+ invalidElements.add(element);
+ }
+
+ // Get/Set proxy information
+ // Proxy settings
+ public static String getProxyValue(String key) {
+ settings.beginGroup("Proxy");
+ String val = (String)settings.value(key, "");
+ settings.endGroup();
+ return val;
+ }
+ public static void setProxyValue(String key, String value) {
+ settings.beginGroup("Proxy");
+ settings.setValue(key, value);
+ settings.endGroup();
+ }
+
+ // Change a byte array to a hex string
+ // Convert a byte array to a hex string
+ public static String byteArrayToHexString(byte data[]) {
+ StringBuffer buf = new StringBuffer();
+ for (byte element : data) {
+ int halfbyte = (element >>> 4) & 0x0F;
+ int two_halfs = 0;
+ do {
+ if ((0 <= halfbyte) && (halfbyte <= 9))
+ buf.append((char) ('0' + halfbyte));
+ else
+ buf.append((char) ('a' + (halfbyte - 10)));
+ halfbyte = element & 0x0F;
+ } while(two_halfs++ < 1);
+ }
+ return buf.toString();
+ }
+
+
+ // Get/Set spelling settings
+ public static boolean getSpellSetting(String value) {
+ settings.beginGroup("Spell");
+ String text = (String)settings.value(value, "");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ if (text.equalsIgnoreCase("false"))
+ return false;
+ if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREDIGITWORDS))
+ return true;
+ if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREINTERNETADDRESSES))
+ return true;
+ if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREUPPERCASE))
+ return true;
+ if (value.equalsIgnoreCase(Configuration.SPELL_IGNORESENTENCECAPITALIZATION))
+ return true;
+ return false;
+ }
+ public static void setSpellSetting(String setting, boolean val) {
+ settings.beginGroup("Spell");
+ if (val)
+ settings.setValue(setting, "true");
+ else
+ settings.setValue(setting, "false");
+ settings.endGroup();
+ }
+
+ // Get/Set how we should display tags (color them, hide unused, or do nothing)
+ // What to do with inactive tags?
+ public static String tagBehavior() {
+ settings.beginGroup("General");
+ String text = (String)settings.value("tagBehavior", "DoNothing");
+ settings.endGroup();
+ return text;
+ }
+ // What to do with inactive tags?
+ public static void setTagBehavior(String value) {
+ settings.beginGroup("General");
+ settings.setValue("tagBehavior", value);
+ settings.endGroup();
+ }
+
+
+ // Should the toolbar be visible?
+ public static boolean isToolbarButtonVisible(String window, Boolean val) {
+ settings.beginGroup("ToolbarButtonsVisible");
+ try {
+ String text = (String)settings.value(window, val.toString());
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value(window, val);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveToolbarButtonsVisible(String column, boolean val) {
+ settings.beginGroup("ToolbarButtonsVisible");
+ if (val)
+ settings.setValue(column, "true");
+ else
+ settings.setValue(column, "false");
+ settings.endGroup();
+ }
+
+ // Are thumbnails enabled?
+
+ public static boolean enableThumbnails() {
+ settings.beginGroup("Debug");
+ try {
+ String text = (String)settings.value("thumbnails", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("thumbnails", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setEnableThumbnails(boolean val) {
+ settings.beginGroup("Debug");
+ if (val)
+ settings.setValue("thumbnails", "true");
+ else
+ settings.setValue("thumbnails", "false");
+ settings.endGroup();
+ }
+
+ // Trace used for performance tuning. Not normally used in production.
+ // Print date/time. Used mainly for performance tracing
+ public static void trace(boolean resetInterval) {
+ String fmt = "MM/dd/yy HH:mm:ss.SSSSSS";
+ String dateTimeFormat = new String(fmt);
+ SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
+ Calendar cal = Calendar.getInstance();
+ if (intervalTraceTime == null)
+ intervalTraceTime = Calendar.getInstance();
+ if (startTraceTime == null)
+ startTraceTime = Calendar.getInstance();
+
+ float interval = (cal.getTimeInMillis() - intervalTraceTime.getTimeInMillis());
+ float total = (cal.getTimeInMillis() - startTraceTime.getTimeInMillis());
+
+// if (interval > 00.0) {
+ StackTraceElement[] exceptions = Thread.currentThread().getStackTrace();
+ System.out.println("------------------------------------------");
+
+ System.out.println("Date/Time " +simple.format(cal.getTime()));
+ System.out.format("Interval Time: %-10.6f%n", interval);
+ System.out.format("Total Time: %-10.6f%n", total);
+ for (int i=2; i<5 && i<exceptions.length; i++) {
+ System.out.println(exceptions[i]);
+ }
+// }
+ if (resetInterval)
+ intervalTraceTime = cal;
+ }
+ public static void traceReset() {
+ intervalTraceTime = null;
+ startTraceTime = null;
+ }
+
+
+ // Get the FileManager class to manage local files & directories
+ public static FileManager getFileManager() {
+ return fileManager;
+ }
+
+ // Should the note editor be disabled?
+ public static boolean getDisableViewing() {
+ return disableViewing;
+ }
+
+ //**********************
+ //* Thumbnail zoom level
+ //**********************
+ public static int calculateThumbnailZoom(String content) {
+ int zoom = 1;
+ if (content.indexOf("application/pdf") == -1) {
+ if (content.indexOf("image/") == -1) {
+ String text = StringEscapeUtils.unescapeHtml4(content.replaceAll("\\<.*?\\>", ""));
+ zoom = 2;
+ if (text.length() < 500)
+ zoom = 2;
+ if (text.length() < 250)
+ zoom = 3;
+ if (text.length() < 100)
+ zoom = 4;
+ if (text.length() < 50)
+ zoom = 5;
+ if (text.length() < 10)
+ zoom = 6;
+ }
+ }
+ return zoom;
+ }
+
+ //**********************
+ //* List View settings
+ //**********************
+ public static void setListView(int view) {
+ settings.beginGroup("General");
+ settings.setValue("listView", view);
+ settings.endGroup();
+ }
+ public static int getListView() {
+ settings.beginGroup("General");
+ Integer value;
+ try {
+ String val = (String)settings.value("listView", View_List_Wide);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("listView", View_List_Wide);
+ } catch (Exception e1) {
+ value = View_List_Wide;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+
+
+ //*******************
+ // Font Settings
+ //*******************
+ public static boolean overrideDefaultFont() {
+ settings.beginGroup("Font");
+ try {
+ String text = (String)settings.value("overrideFont", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("overrideFont", false);
+ settings.endGroup();
+ return value;
+ }
+
+ }
+
+ //****************************************************
+ // Get/Set the default font settings for a new note
+ //****************************************************
+ public static void setOverrideDefaultFont(boolean value) {
+ settings.beginGroup("Font");
+ settings.setValue("overrideFont", value);
+ settings.endGroup();
+ }
+ public static String getDefaultFont() {
+ settings.beginGroup("Font");
+ String val = (String)settings.value("font", "");
+ settings.endGroup();
+ return val;
+ }
+ public static void setDefaultFont(String value) {
+ settings.beginGroup("Font");
+ settings.setValue("font", value);
+ settings.endGroup();
+ }
+ public static String getDefaultFontSize() {
+ settings.beginGroup("Font");
+ String val = (String)settings.value("fontSize", "");
+ settings.endGroup();
+ return val;
+ }
+ public static void setDefaultFontSize(String value) {
+ settings.beginGroup("Font");
+ settings.setValue("fontSize", value);
+ settings.endGroup();
+ }
+
+
+ //*******************************************
+ // Override the close & minimize instead.
+ //*******************************************
+ public static boolean minimizeOnClose() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("minimizeOnClose", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true") && QSystemTrayIcon.isSystemTrayAvailable())
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("minimizeOnClose", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setMinimizeOnClose(boolean value) {
+ settings.beginGroup("General");
+ settings.setValue("minimizeOnClose", value);
+ settings.endGroup();
+ }
+
+ //*********************************
+ // Check version information
+ //*********************************
+ public static boolean checkVersionUpgrade() {
+ settings.beginGroup("Upgrade");
+ try {
+ String text = (String)settings.value("checkForUpdates", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("checkForUpdates", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setCheckVersionUpgrade(boolean value) {
+ settings.beginGroup("Upgrade");
+ settings.setValue("checkForUpdates", value);
+ settings.endGroup();
+ }
+ public static String getUpdatesAvailableUrl() {
+ settings.beginGroup("Upgrade");
+ String text = (String)settings.value("avialableUrl", "http://puma.cis.ibaraki.ac.jp/products/neighbornote/develop/versions.txt");
+ settings.endGroup();
+ return text;
+ }
+ public static String getUpdateAnnounceUrl() {
+ settings.beginGroup("Upgrade");
+ String text = (String)settings.value("announceUrl", "http://puma.cis.ibaraki.ac.jp/products/neighbornote/develop/upgrade.html");
+ settings.endGroup();
+ return text;
+ }
+ public static String getUpdateDownloadUrl() {
+ settings.beginGroup("Upgrade");
+ String text = (String)settings.value("downloadUrl", "http://puma.cis.ibaraki.ac.jp/products/neighbornote/download.html");
+ settings.endGroup();
+ return text;
+ }
+
+ //*******************
+ // Index settings
+ //*******************
+ // Set/Get if we should index the text of a note
+ public static boolean indexNoteBody() {
+ settings.beginGroup("Index");
+ try {
+ String value = (String)settings.value("indexNoteBody", "true");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("indexNoteBody", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setIndexNoteTitle(boolean value) {
+ settings.beginGroup("Index");
+ settings.setValue("indexNoteTitle", value);
+ settings.endGroup();
+ }
+ // Set/Get if we should index the title of a note
+ public static boolean indexNoteTitle() {
+ settings.beginGroup("Index");
+ try {
+ String value = (String)settings.value("indexNoteTitle", "true");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("indexNoteTitle", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setIndexNoteBody(boolean value) {
+ settings.beginGroup("Index");
+ settings.setValue("indexNoteBody", value);
+ settings.endGroup();
+ }
+ // Set/Get if we should index any attachments
+ public static boolean indexAttachmentsLocally() {
+ settings.beginGroup("Index");
+ try {
+ String value = (String)settings.value("indexAttachmentsLocally", "true");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("indexAttachmentsLocally", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setIndexImageRecognition(boolean value) {
+ settings.beginGroup("Index");
+ settings.setValue("indexImageRecognition", value);
+ settings.endGroup();
+ }
+ public static boolean indexImageRecognition() {
+ settings.beginGroup("Index");
+ try {
+ String value = (String)settings.value("indexImageRecognition", "true");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("indexImageRecognition", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setIndexAttachmentsLocally(boolean value) {
+ settings.beginGroup("Index");
+ settings.setValue("indexAttachmentsLocally", value);
+ settings.endGroup();
+ }
+ // Get/Set characters that shouldn't be removed from a word
+// public static String getSpecialIndexCharacters() {
+// settings.beginGroup("Index");
+// String text = (String)settings.value("specialCharacters", "");
+// settings.endGroup();
+// return text;
+// }
+// public static void setSpecialIndexCharacters(String value) {
+// settings.beginGroup("Index");
+// settings.setValue("specialCharacters", value);
+// settings.endGroup();
+// databaseCache = value;
+// }
+
+ //*****************************************************************************
+ // Control how tag selection behaves (should they be "and" or "or" selections
+ //*****************************************************************************
+ public static boolean anyTagSelectionMatch() {
+ settings.beginGroup("General");
+ try {
+ String value = (String)settings.value("anyTagSelectionMatch", "false");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("anyTagSelectionMatch", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setAnyTagSelectionMatch(boolean value) {
+ settings.beginGroup("General");
+ settings.setValue("anyTagSelectionMatch", value);
+ settings.endGroup();
+ }
+
+ //*****************************************************************************
+ // Control if a user receives a warning when trying to create a note-to-note link
+ // when the DB is not synchronized.
+ //*****************************************************************************
+ public static boolean bypassSynchronizationWarning() {
+ settings.beginGroup("User");
+ try {
+ String value = (String)settings.value("bypassSynchronizationWarning", "false");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("bypassSynchronizationWarning", false);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setBypassSynchronizationWarning(boolean value) {
+ settings.beginGroup("User");
+ settings.setValue("bypassSynchronizationWarning", value);
+ settings.endGroup();
+ }
+
+
+ //***********************
+ //* Database cache size
+ //***********************
+ public static String getDatabaseCacheSize() {
+ settings.beginGroup("Debug");
+ String text = (String)settings.value("databaseCache", "16384");
+ settings.endGroup();
+ return text;
+ }
+ public static void setDatabaseCache(String value) {
+ settings.beginGroup("Debug");
+ settings.setValue("databaseCache", value);
+ settings.endGroup();
+ databaseCache = value;
+ }
+
+
+ // This is used to copy a class since Java's normal deep copy is wacked
+ public static Object deepCopy(Object oldObj)
+ {
+ ObjectOutputStream oos = null;
+ ObjectInputStream ois = null;
+ try
+ {
+ ByteArrayOutputStream bos =
+ new ByteArrayOutputStream(); // A
+ oos = new ObjectOutputStream(bos); // B
+ // serialize and pass the object
+ oos.writeObject(oldObj); // C
+ oos.flush(); // D
+ ByteArrayInputStream bin =
+ new ByteArrayInputStream(bos.toByteArray()); // E
+ ois = new ObjectInputStream(bin); // F
+ // return the new object
+ return ois.readObject(); // G
+ }
+ catch(Exception e)
+ {
+ Global.logger.log(logger.LOW, "Exception in ObjectCloner = " + e);
+ }
+ try {
+ oos.close();
+ ois.close();
+ } catch (IOException e) {
+ Global.logger.log(logger.LOW, "Exception in ObjectCloner = " + e);
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ // If we should automatically select the children of any tag
+ public static boolean includeTagChildren() {
+ settings.beginGroup("General");
+ try {
+ String value = (String)settings.value("includeTagChildren", "false");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("includeTagChildren", false);
+ settings.endGroup();
+ return value;
+ }
+
+ }
+ public static void setIncludeTagChildren(boolean value) {
+ settings.beginGroup("General");
+ settings.setValue("includeTagChildren", value);
+ settings.endGroup();
+ }
+
+ // If we should automatically wildcard searches
+// public static boolean automaticWildcardSearches() {
+// settings.beginGroup("General");
+// try {
+// String value = (String)settings.value("automaticWildcard", "false");
+// settings.endGroup();
+// if (value.equals("true"))
+// return true;
+// else
+// return false;
+// } catch (java.lang.ClassCastException e) {
+// Boolean value = (Boolean) settings.value("automaticWildcard", false);
+// settings.endGroup();
+// return value;
+// }
+//
+// }
+// public static void setAutomaticWildcardSearches(boolean value) {
+// settings.beginGroup("General");
+// settings.setValue("automaticWildcard", value);
+// settings.endGroup();
+// }
+
+ // If we should automatically select the children of any tag
+ public static boolean displayRightToLeft() {
+ settings.beginGroup("General");
+ try {
+ String value = (String)settings.value("displayRightToLeft", "false");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("displayRightToLeft", false);
+ settings.endGroup();
+ return value;
+ }
+
+ }
+ public static void setDisplayRightToLeft(boolean value) {
+ settings.beginGroup("General");
+ settings.setValue("displayRightToLeft", value);
+ settings.endGroup();
+ }
+
+
+ //***********************
+ //* Startup Notebook
+ //***********************
+ public static String getStartupNotebook() {
+ settings.beginGroup("General");
+ String text = (String)settings.value("startupNotebook", "");
+ settings.endGroup();
+ return text;
+ }
+ public static void setStartupNotebook(String value) {
+ settings.beginGroup("General");
+ settings.setValue("startupNotebook", value);
+ settings.endGroup();
+ databaseCache = value;
+ }
+
+ // 複数ノート同時閲覧操作に対する重み付け
+ public static void setBrowseWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("browseWeight", weight);
+ settings.endGroup();
+ }
+ public static int getBrowseWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("browseWeight", 1);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("browseWeight", 1);
+ } catch (Exception e1) {
+ value = 1;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // ノート内容のコピー&ペースト操作に対する重み付け
+ public static void setCopyPasteWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("copyPasteWeight", weight);
+ settings.endGroup();
+ }
+ public static int getCopyPasteWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("copyPasteWeight", 3);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("copyPasteWeight", 3);
+ } catch (Exception e1) {
+ value = 3;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // 新規ノート追加操作に対する重み付け
+ public static void setAddNewNoteWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("addNewNoteWeight", weight);
+ settings.endGroup();
+ }
+ public static int getAddNewNoteWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("addNewNoteWeight", 3);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("addNewNoteWeight", 3);
+ } catch (Exception e1) {
+ value = 1;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // 連想ノートクリック操作に対する重み付け
+ public static void setRensoItemClickWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("rensoItemClickWeight", weight);
+ settings.endGroup();
+ }
+ public static int getRensoItemClickWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("rensoItemClickWeight", 10);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("rensoItemClickWeight", 10);
+ } catch (Exception e1) {
+ value = 10;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // タグ付け操作に対する重み付け
+ public static void setSameTagWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("sameTagWeight", weight);
+ settings.endGroup();
+ }
+ public static int getSameTagWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("sameTagWeight", 2);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("sameTagWeight", 2);
+ } catch (Exception e1) {
+ value = 2;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // ノートブック変更操作に対する重み付け
+ public static void setSameNotebookWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("sameNotebookWeight", weight);
+ settings.endGroup();
+ }
+ public static int getSameNotebookWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("sameNotebookWeight", 2);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("sameNotebookWeight", 2);
+ } catch (Exception e1) {
+ value = 2;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // Evernote関連ノート機能統合に対する重み付け
+ public static void setENRelatedNotesWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("enRelatedNotesWeight", weight);
+ settings.endGroup();
+ }
+ public static int getENRelatedNotesWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("enRelatedNotesWeight", 5);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("enRelatedNotesWeight", 5);
+ } catch (Exception e1) {
+ value = 10;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ //*******************
+ // ノートのマージ・複製の関連ノートリストへの適用
+ //*******************
+ public static void setMergeRensoNote(boolean value) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("mergeRensoNoteList", value);
+ settings.endGroup();
+ }
+
+ public static boolean getMergeRensoNote() {
+ settings.beginGroup("RensoNoteList");
+ try {
+ String value = (String)settings.value("mergeRensoNoteList", "true");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("mergeRensoNoteList", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+
+ public static void setDuplicateRensoNote(boolean value) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("duplicateRensoNoteList", value);
+ settings.endGroup();
+ }
+
+ public static boolean getDuplicateRensoNote() {
+ settings.beginGroup("RensoNoteList");
+ try {
+ String value = (String)settings.value("duplicateRensoNoteList", "true");
+ settings.endGroup();
+ if (value.equals("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("duplicateRensoNoteList", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+
+ // 連想ノートリストからノートを除外するときに確認メッセージを表示するかどうか
+ public static boolean verifyExclude() {
+ settings.beginGroup("RensoNoteList");
+ try {
+ String text = (String)settings.value("verifyExclude", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("verifyExclude", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+
+ public static void setVerifyExclude(boolean val) {
+ settings.beginGroup("RensoNoteList");
+ if (val)
+ settings.setValue("verifyExclude", "true");
+ else
+ settings.setValue("verifyExclude", "false");
+ settings.endGroup();
+ }
+
+ // 連想ノートリスト最大表示アイテム数
+ public static void setRensoListItemMaximum(int maximum) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("rensoListMaximum", maximum);
+ settings.endGroup();
+ }
+ public static int getRensoListItemMaximum() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("rensoListMaximum", 10);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("rensoListMaximum", 10);
+ } catch (Exception e1) {
+ value = 10;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+
+ // タグを排除してプレーンテキストを抽出
+ public static String extractPlainText(String sourceText) {
+ String plainText = sourceText.replaceAll("<.+?>", ""); // タグを除去
+ plainText = plainText.replaceAll("\\s{2,}", " "); // 2個以上の空白文字を1文字の空白に変換
+ String kaigyo = System.getProperty("line.separator");
+ plainText = plainText.replaceAll(kaigyo, ""); // 改行を除去
+// plainText = plainText.replaceAll("<.+?>", ""); // <で始まり>で終わる文字列を除去
+
+ // HTML特殊文字のサニタイジングを解除
+ plainText = plainText.replaceAll("'", "'");
+ plainText = plainText.replaceAll(""", "\"");
+ plainText = plainText.replaceAll(">", ">");
+ plainText = plainText.replaceAll("<", "<");
+ plainText = plainText.replaceAll("&", "&");
+
+ plainText = plainText.replaceAll("&.+?;", ""); // その他HTML特殊文字があれば除去
+
+ return plainText;
+ }
+
+ // 全文検索機能の対象となるテーブルとカラムを再構築
+ public static boolean rebuildFullTextNoteTarget(DatabaseConnection dbConn) {
+ NSqlQuery nQuery = new NSqlQuery(dbConn.getConnection());
+ StringBuilder noteTableTarget = new StringBuilder();
+ boolean success = true;
+
+ if (Global.indexNoteBody()) {
+ noteTableTarget.append("CONTENTTEXT");
+ }
+ if (Global.indexNoteTitle()) {
+ if (noteTableTarget.length() > 0) {
+ noteTableTarget.append(", ");
+ }
+ noteTableTarget.append("TITLE");
+ }
+
+ if (noteTableTarget.length() > 0) {
+ nQuery.prepare("CALL FTL_CREATE_INDEX('PUBLIC', 'NOTE', :column);");
+ nQuery.bindValue(":column", noteTableTarget.toString());
+ if (!nQuery.exec()) {
+ success = false;
+ }
+ }
+
+ return success;
+ }
+
+ public static boolean rebuildFullTextResourceTarget(DatabaseConnection dbConn) {
+ NSqlQuery rQuery = new NSqlQuery(dbConn.getResourceConnection());
+ StringBuilder resourceTableTarget = new StringBuilder();
+ boolean success = true;
+
+ if (Global.indexAttachmentsLocally()) {
+ resourceTableTarget.append("RESOURCETEXT");
+ }
+
+ if (resourceTableTarget.length() > 0) {
+ rQuery.prepare("CALL FTL_CREATE_INDEX('PUBLIC', 'NOTERESOURCES', :column);");
+ rQuery.bindValue(":column", resourceTableTarget.toString());
+ if (!rQuery.exec()) {
+ success = false;
+ }
+ }
+
+ return success;
+ }
+
+ // 操作ログを取らないモードのボタン状態
+ public static boolean isHaltLogButton() {
+ settings.beginGroup("RensoNoteList");
+ try {
+ String text = (String)settings.value("haltOperationLog", "false");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("haltOperationLog", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void saveHaltLogButton(boolean val) {
+ settings.beginGroup("RensoNoteList");
+ if (val)
+ settings.setValue("haltOperationLog", "true");
+ else
+ settings.setValue("haltOperationLog", "false");
+ settings.endGroup();
+ }
+
+ // 連想ノートリストの重み付けモードの状態
+ public static String rensoWeightingSelect() {
+ settings.beginGroup("RensoNoteList");
+ String text = (String)settings.value("rensoWeightingSelect", "Standard");
+ settings.endGroup();
+ return text;
+ }
+ public static void saveRensoWeightingSelect(String val) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("rensoWeightingSelect", val);
+ settings.endGroup();
+ }
+
+ // ordinal から指定した Enum の要素に変換する汎用関数
+ public static <E extends Enum<E>> E fromOrdinal(Class<E> enumClass, int ordinal) {
+ E[] enumArray = enumClass.getEnumConstants();
+ return enumArray[ordinal];
+ }
+
+ // 連想ノートリスト重み付けモード:カスタムの設定値(同時閲覧)
+ public static int customBrowseWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customBrowseWeight", 1);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customBrowseWeight", 1);
+ } catch (Exception e1) {
+ value = 1;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomBrowseWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customBrowseWeight", weight);
+ settings.endGroup();
+ }
+ // 連想ノートリスト重み付けモード:カスタムの設定値(コピー&ペースト)
+ public static int customCopyPasteWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customCopyPasteWeight", 3);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customCopyPasteWeight", 3);
+ } catch (Exception e1) {
+ value = 3;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomCopyPasteWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customCopyPasteWeight", weight);
+ settings.endGroup();
+ }
+ // 連想ノートリスト重み付けモード:カスタムの設定値(新規ノート追加)
+ public static int customAddNewNoteWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customAddNewNoteWeight", 3);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customAddNewNoteWeight", 3);
+ } catch (Exception e1) {
+ value = 3;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomAddNewNoteWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customAddNewNoteWeight", weight);
+ settings.endGroup();
+ }
+ // 連想ノートリスト重み付けモード:カスタムの設定値(連想ノートクリック)
+ public static int customRensoItemClickWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customRensoItemClickWeight", 10);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customRensoItemClickWeight", 10);
+ } catch (Exception e1) {
+ value = 10;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomRensoItemClickWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customRensoItemClickWeight", weight);
+ settings.endGroup();
+ }
+ // 連想ノートリスト重み付けモード:カスタムの設定値(同じタグ)
+ public static int customSameTagWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customSameTagWeight", 2);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customSameTagWeight", 2);
+ } catch (Exception e1) {
+ value = 2;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomSameTagWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customSameTagWeight", weight);
+ settings.endGroup();
+ }
+ // 連想ノートリスト重み付けモード:カスタムの設定値(同じノートブック)
+ public static int customSameNotebookWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customSameNotebookWeight", 2);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customSameNotebookWeight", 2);
+ } catch (Exception e1) {
+ value = 2;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomSameNotebookWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customSameNotebookWeight", weight);
+ settings.endGroup();
+ }
+ // 連想ノートリスト重み付けモード:カスタムの設定値(Evernote関連ノート)
+ public static int customENRelatedNotesWeight() {
+ settings.beginGroup("RensoNoteList");
+ Integer value;
+ try {
+ String val = (String)settings.value("customENRelatedNotesWeight", 5);
+ value = new Integer(val.trim());
+ } catch (Exception e) {
+ try {
+ value = (Integer)settings.value("customENRelatedNotesWeight", 5);
+ } catch (Exception e1) {
+ value = 5;
+ }
+ }
+ settings.endGroup();
+ return value;
+ }
+ public static void saveCustomENRelatedNotesWeight(int weight) {
+ settings.beginGroup("RensoNoteList");
+ settings.setValue("customENRelatedNotesWeight", weight);
+ settings.endGroup();
+ }
+
+ // ツールバーの「新規」ボタンを押した時、新規ノートをタブで開くかどうか
+ public static boolean toolBarNewAction() {
+ settings.beginGroup("General");
+ try {
+ String text = (String)settings.value("toolBarNewAction", "true");
+ settings.endGroup();
+ if (text.equalsIgnoreCase("true"))
+ return true;
+ else
+ return false;
+ } catch (java.lang.ClassCastException e) {
+ Boolean value = (Boolean) settings.value("toolBarNewAction", true);
+ settings.endGroup();
+ return value;
+ }
+ }
+ public static void setToolBarNewAction(boolean value) {
+ settings.beginGroup("General");
+ settings.setValue("toolBarNewAction", value);
+ settings.endGroup();
+ }
+}
+
-/*\r
- * This file is part of NixNote \r
- * Copyright 2009 Randy Baumgarte\r
- * \r
- * This file may be licensed under the terms of of the\r
- * 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
-package cx.fbn.nevernote.threads;\r
-\r
-import java.io.BufferedOutputStream;\r
-import java.io.File;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.UnsupportedEncodingException;\r
-import java.net.UnknownHostException;\r
-import java.util.ArrayList;\r
-import java.util.Calendar;\r
-import java.util.Date;\r
-import java.util.GregorianCalendar;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.TreeSet;\r
-import java.util.concurrent.LinkedBlockingQueue;\r
-\r
-import org.apache.http.HttpEntity;\r
-import org.apache.http.HttpResponse;\r
-import org.apache.http.NameValuePair;\r
-import org.apache.http.client.ClientProtocolException;\r
-import org.apache.http.client.HttpClient;\r
-import org.apache.http.client.entity.UrlEncodedFormEntity;\r
-import org.apache.http.client.methods.HttpPost;\r
-import org.apache.http.impl.client.DefaultHttpClient;\r
-import org.apache.http.message.BasicNameValuePair;\r
-import org.apache.http.protocol.HTTP;\r
-import org.apache.thrift.TException;\r
-import org.apache.thrift.protocol.TBinaryProtocol;\r
-import org.apache.thrift.transport.THttpClient;\r
-import org.apache.thrift.transport.TTransportException;\r
-\r
-import com.evernote.edam.error.EDAMNotFoundException;\r
-import com.evernote.edam.error.EDAMSystemException;\r
-import com.evernote.edam.error.EDAMUserException;\r
-import com.evernote.edam.notestore.NoteStore;\r
-import com.evernote.edam.notestore.NoteStore.Client;\r
-import com.evernote.edam.notestore.SyncChunk;\r
-import com.evernote.edam.notestore.SyncState;\r
-import com.evernote.edam.type.Data;\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.Resource;\r
-import com.evernote.edam.type.SavedSearch;\r
-import com.evernote.edam.type.SharedNotebook;\r
-import com.evernote.edam.type.Tag;\r
-import com.evernote.edam.type.User;\r
-import com.evernote.edam.userstore.AuthenticationResult;\r
-import com.evernote.edam.userstore.UserStore;\r
-import com.trolltech.qt.core.QByteArray;\r
-import com.trolltech.qt.core.QFile;\r
-import com.trolltech.qt.core.QIODevice.OpenModeFlag;\r
-import com.trolltech.qt.core.QObject;\r
-import com.trolltech.qt.core.QTextCodec;\r
-import com.trolltech.qt.gui.QMessageBox;\r
-\r
-import cx.fbn.nevernote.signals.NoteIndexSignal;\r
-import cx.fbn.nevernote.signals.NoteResourceSignal;\r
-import cx.fbn.nevernote.signals.NoteSignal;\r
-import cx.fbn.nevernote.signals.NotebookSignal;\r
-import cx.fbn.nevernote.signals.SavedSearchSignal;\r
-import cx.fbn.nevernote.signals.StatusSignal;\r
-import cx.fbn.nevernote.signals.SyncSignal;\r
-import cx.fbn.nevernote.signals.TagSignal;\r
-import cx.fbn.nevernote.sql.DatabaseConnection;\r
-import cx.fbn.nevernote.sql.DeletedItemRecord;\r
-import cx.fbn.nevernote.utilities.ApplicationLogger;\r
-\r
-public class SyncRunner extends QObject implements Runnable {\r
- \r
- private final ApplicationLogger logger;\r
- private DatabaseConnection conn;\r
- private boolean idle;\r
- public boolean error;\r
- public volatile List<String> errorSharedNotebooks;\r
- public volatile HashMap<String,String> errorSharedNotebooksIgnored;\r
- public volatile boolean isConnected;\r
- public volatile boolean keepRunning;\r
- public volatile String authToken;\r
- private long evernoteUpdateCount;\r
- private final String userAgent = "NixNote/" + System.getProperty("os.name")\r
- +"/"+System.getProperty("java.vendor") + "/"\r
- + System.getProperty("java.version") +";";\r
- \r
- public volatile NoteStore.Client localNoteStore;\r
- private UserStore.Client userStore;\r
- \r
- public volatile StatusSignal status;\r
- public volatile TagSignal tagSignal;\r
- public volatile NotebookSignal notebookSignal;\r
- public volatile NoteIndexSignal noteIndexSignal;\r
- public volatile NoteSignal noteSignal;\r
- public volatile SavedSearchSignal searchSignal;\r
- public volatile NoteResourceSignal resourceSignal;\r
- public volatile SyncSignal syncSignal;\r
- public volatile boolean authRefreshNeeded;\r
- public volatile boolean syncNeeded;\r
- public volatile boolean disableUploads;\r
- public volatile boolean syncDeletedContent;\r
- private volatile List<String> dirtyNoteGuids;\r
- \r
- public volatile String username = ""; \r
- public volatile String password = ""; \r
- public volatile String userStoreUrl;\r
-// private final static String consumerKey = "baumgarte"; \r
-// private final static String consumerSecret = "eb8b5740e17cb55f";\r
- public String noteStoreUrlBase;\r
- 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
- public long failedRefreshes = 0;\r
- public THttpClient noteStoreTrans;\r
- public TBinaryProtocol noteStoreProt;\r
- public String noteStoreUrl;\r
- public long sequenceDate;\r
- public int updateSequenceNumber;\r
- private boolean refreshNeeded;\r
- private volatile LinkedBlockingQueue<String> workQueue;\r
- private static int MAX_QUEUED_WAITING = 1000;\r
- String dbuid;\r
- String dburl;\r
- String indexUrl;\r
- String resourceUrl;\r
- String dbpswd;\r
- String dbcpswd;\r
- private final TreeSet<String> ignoreTags;\r
- private final TreeSet<String> ignoreNotebooks;\r
- private final TreeSet<String> ignoreLinkedNotebooks;\r
- private HashMap<String,String> badTagSync;\r
- \r
- \r
- \r
- public SyncRunner(String logname, String u, String i, String r, String uid, String pswd, String cpswd) {\r
- logger = new ApplicationLogger(logname);\r
- \r
- noteSignal = new NoteSignal();\r
- status = new StatusSignal();\r
- tagSignal = new TagSignal();\r
- notebookSignal = new NotebookSignal();\r
- noteIndexSignal = new NoteIndexSignal();\r
- noteSignal = new NoteSignal();\r
- searchSignal = new SavedSearchSignal();\r
- syncSignal = new SyncSignal();\r
- resourceSignal = new NoteResourceSignal();\r
- resourceUrl = r;\r
- indexUrl = i;\r
- dbuid = uid;\r
- dburl = u;\r
- dbpswd = pswd;\r
- dbcpswd = cpswd;\r
-// this.setAutoDelete(false);\r
- \r
- isConnected = false;\r
- syncNeeded = false;\r
- authRefreshNeeded = false;\r
- keepRunning = true;\r
- idle = true;\r
- disableUploads = false;\r
- ignoreTags = new TreeSet<String>();\r
- ignoreNotebooks = new TreeSet<String>();\r
- ignoreLinkedNotebooks = new TreeSet<String>();\r
- \r
-// setAutoDelete(false);\r
- workQueue=new LinkedBlockingQueue<String>(MAX_QUEUED_WAITING);\r
- }\r
- @Override\r
- public void run() {\r
- errorSharedNotebooks = new ArrayList<String>();\r
- errorSharedNotebooksIgnored = new HashMap<String,String>();\r
- try {\r
- logger.log(logger.EXTREME, "Starting thread");\r
- conn = new DatabaseConnection(logger, dburl, indexUrl, resourceUrl, dbuid, dbpswd, dbcpswd, 200);\r
- while(keepRunning) {\r
- logger.log(logger.EXTREME, "Blocking until work is found");\r
- String work = workQueue.take();\r
- logger.log(logger.LOW, "Dirty Notes Before Sync: " +new Integer(conn.getNoteTable().getDirtyCount()).toString());\r
- logger.log(logger.EXTREME, "Work found: " +work);\r
- if (work.equalsIgnoreCase("stop")) {\r
- idle=false;\r
- return;\r
- }\r
- conn.getNoteTable().dumpDirtyNotes(); // Debugging statement\r
- idle=false;\r
- error=false;\r
- if (syncNeeded) {\r
- logger.log(logger.EXTREME, "SyncNeeded is true");\r
- refreshNeeded=false;\r
- sequenceDate = conn.getSyncTable().getLastSequenceDate();\r
- updateSequenceNumber = conn.getSyncTable().getUpdateSequenceNumber();\r
- try {\r
- logger.log(logger.EXTREME, "Beginning sync");\r
- evernoteSync(localNoteStore);\r
- logger.log(logger.EXTREME, "Sync finished");\r
- } catch (UnknownHostException e) {\r
- status.message.emit(e.getMessage());\r
- }\r
- }\r
- idle=true;\r
- logger.log(logger.EXTREME, "Signaling refresh finished. refreshNeeded=" +refreshNeeded);\r
- syncSignal.finished.emit(refreshNeeded);\r
- if (error) {\r
- syncSignal.errorDisconnect.emit();\r
- status.message.emit(tr("Error synchronizing - see log for details."));\r
- }\r
- logger.log(logger.LOW, "Dirty Notes After Sync: " +new Integer(conn.getNoteTable().getDirtyCount()).toString());\r
- conn.getNoteTable().dumpDirtyNotes();\r
- logger.log(logger.LOW, "---");\r
- }\r
- } \r
- catch (InterruptedException e1) {\r
- e1.printStackTrace();\r
- }\r
- conn.dbShutdown();\r
- }\r
-\r
- \r
- public DatabaseConnection getConnection() {\r
- return conn;\r
- }\r
-\r
- public boolean isIdle() {\r
- return idle;\r
- }\r
-\r
-\r
- public void setConnected(boolean c) {\r
- isConnected = c;\r
- }\r
- public void setKeepRunning(boolean r) {\r
- logger.log(logger.EXTREME, "Setting keepRunning=" +r);\r
- keepRunning = r;\r
- }\r
- public void setNoteStore(NoteStore.Client c) {\r
- logger.log(logger.EXTREME, "Setting NoteStore in sync thread");\r
- localNoteStore = c;\r
- }\r
- public void setUserStore(UserStore.Client c) {\r
- logger.log(logger.EXTREME, "Setting UserStore in sync thread");\r
- userStore = c;\r
- }\r
-\r
- public void setEvernoteUpdateCount(long s) {\r
- logger.log(logger.EXTREME, "Setting Update Count in sync thread");\r
- evernoteUpdateCount = s;\r
- }\r
- \r
- //***************************************************************\r
- //***************************************************************\r
- //** These functions deal with Evernote communications\r
- //***************************************************************\r
- //***************************************************************\r
- // Synchronize changes with Evernote\r
- @SuppressWarnings("unused")\r
- private void evernoteSync(Client noteStore) throws java.net.UnknownHostException {\r
- logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync");\r
- \r
- // Rebuild list of tags & notebooks to ignore\r
- ignoreNotebooks.clear();\r
- List<String> ignore = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");\r
- for (int i=0; i<ignore.size(); i++) \r
- ignoreNotebooks.add(ignore.get(i));\r
- \r
- ignore.clear();\r
- ignore = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");\r
- for (int i=0; i<ignore.size(); i++) \r
- ignoreLinkedNotebooks.add(ignore.get(i));\r
- \r
- ignoreTags.clear();\r
- ignore = conn.getSyncTable().getIgnoreRecords("TAG");\r
- for (int i=0; i<ignore.size(); i++) \r
- ignoreTags.add(ignore.get(i));\r
-\r
- // Make sure we are connected & should keep running\r
- if (isConnected && keepRunning) {\r
- error = false;\r
- logger.log(logger.EXTREME, "Synchronizing with Evernote");\r
- status.message.emit(tr("Synchronizing with Evernote"));\r
- \r
- // Get user information\r
- try {\r
- logger.log(logger.EXTREME, "getting user from userstore");\r
- User user = userStore.getUser(authToken);\r
- logger.log(logger.EXTREME, "Saving user information");\r
- syncSignal.saveUserInformation.emit(user);\r
- } catch (EDAMUserException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("User exception getting user account information. Aborting sync and disconnecting"));\r
- syncSignal.errorDisconnect.emit();\r
- error = true;\r
- enDisconnect();\r
- return;\r
- } catch (EDAMSystemException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("System error user account information. Aborting sync and disconnecting!"));\r
- syncSignal.errorDisconnect.emit();\r
- error = true;\r
- enDisconnect();\r
- return;\r
- } catch (TException e1) {\r
- e1.printStackTrace();\r
- syncSignal.errorDisconnect.emit();\r
- error = true;\r
- status.message.emit(tr("Transaction error getting user account information. Aborting sync and disconnecting!"));\r
- enDisconnect();\r
- return;\r
- }\r
- \r
- // Get sync state\r
- SyncState syncState = null;\r
- try { \r
- logger.log(logger.EXTREME, "Getting sync state");\r
- syncState = noteStore.getSyncState(authToken); \r
- syncSignal.saveUploadAmount.emit(syncState.getUploaded());\r
- syncSignal.saveEvernoteUpdateCount.emit(syncState.getUpdateCount());\r
- evernoteUpdateCount = syncState.getUpdateCount();\r
- } catch (EDAMUserException e) {\r
- e.printStackTrace();\r
- status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));\r
- syncSignal.errorDisconnect.emit();\r
- enDisconnect();\r
- return;\r
- } catch (EDAMSystemException e) {\r
- e.printStackTrace();\r
- status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));\r
- syncSignal.errorDisconnect.emit();\r
- enDisconnect();\r
- return;\r
- } catch (TException e) {\r
- e.printStackTrace();\r
- status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));\r
- syncSignal.errorDisconnect.emit();\r
- enDisconnect();\r
- return;\r
- }\r
- \r
- if (syncState == null) {\r
- logger.log(logger.EXTREME, "Sync State is null");\r
- status.message.emit(tr("Syncronization Error!"));\r
- return;\r
- }\r
-\r
- // Determine what to do. \r
- // If we need to do a full sync.\r
- logger.log(logger.LOW, "Full Sequence Before: " +syncState.getFullSyncBefore());\r
- logger.log(logger.LOW, "Last Sequence Date: " +sequenceDate);\r
- logger.log(logger.LOW, "Var Last Sequence Number: " +updateSequenceNumber);\r
- logger.log(logger.LOW, "DB Last Sequence Number: " + conn.getSyncTable().getUpdateSequenceNumber());\r
- if (syncState.getFullSyncBefore() > sequenceDate) {\r
- logger.log(logger.EXTREME, "Full sequence date has expired");\r
- sequenceDate = 0;\r
- conn.getSyncTable().setLastSequenceDate(0);\r
- updateSequenceNumber = 0;\r
- conn.getSyncTable().setUpdateSequenceNumber(0);\r
- }\r
- // Check for "special" sync instructions\r
- String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
- String syncShared = conn.getSyncTable().getRecord("FullSharedNotebookSync");\r
- String syncNotebooks = conn.getSyncTable().getRecord("FullNotebookSync");\r
- String syncInkNoteImages = conn.getSyncTable().getRecord("FullInkNoteImageSync");\r
- if (syncLinked != null) {\r
- downloadAllLinkedNotebooks(localNoteStore);\r
- }\r
- if (syncShared != null) {\r
- downloadAllSharedNotebooks(localNoteStore);\r
- }\r
- if (syncNotebooks != null) {\r
- downloadAllNotebooks(localNoteStore);\r
- }\r
- \r
- 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), authToken);\r
- }\r
- conn.getSyncTable().deleteRecord("FullInkNoteImageSync");\r
- }\r
- \r
- // If there are remote changes\r
- logger.log(logger.LOW, "Update Count: " +syncState.getUpdateCount());\r
- logger.log(logger.LOW, "Last Update Count: " +updateSequenceNumber);\r
- \r
- if (syncState.getUpdateCount() > updateSequenceNumber) {\r
- logger.log(logger.EXTREME, "Refresh needed is true");\r
- refreshNeeded = true;\r
- logger.log(logger.EXTREME, "Downloading changes");\r
- syncRemoteToLocal(localNoteStore);\r
- }\r
- \r
- //*****************************************\r
- //* Sync linked/shared notebooks \r
- //*****************************************\r
- syncLinkedNotebooks();\r
- //conn.getNoteTable().getDirty();\r
- //disableUploads = true; /// DELETE THIS LINE!!!!\r
- if (!disableUploads) {\r
- logger.log(logger.EXTREME, "Uploading changes");\r
- // Synchronize remote changes\r
- if (!error)\r
- syncExpunged(localNoteStore);\r
- if (!error)\r
- syncLocalTags(localNoteStore);\r
- if (!error)\r
- syncLocalNotebooks(localNoteStore);\r
- if (!error)\r
- syncLocalLinkedNotebooks(localNoteStore);\r
- if (!error) \r
- syncDeletedNotes(localNoteStore);\r
- if (!error)\r
- syncLocalNotes();\r
- if (!error)\r
- syncLocalSavedSearches(localNoteStore);\r
- }\r
- \r
- status.message.emit(tr("Cleaning up"));\r
- List<String> notes = conn.getNoteTable().expungeIgnoreSynchronizedNotes(conn.getSyncTable().getIgnoreRecords("NOTEBOOK"), \r
- conn.getSyncTable().getIgnoreRecords("TAG"), conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"));\r
- if (notes.size() > 0)\r
- syncSignal.refreshLists.emit();\r
- \r
- //*****************************************\r
- //* End of synchronization\r
- //*****************************************\r
- if (refreshNeeded)\r
- syncSignal.refreshLists.emit();\r
- \r
- if (!error) {\r
- logger.log(logger.LOW, "Sync completed. Errors=" +error);\r
- if (!disableUploads) \r
- status.message.emit(tr("Synchronizing complete"));\r
- else\r
- status.message.emit(tr("Download syncronization complete. Uploads have been disabled."));\r
- \r
- logger.log(logger.EXTREME, "Saving sync time");\r
- if (syncState.getCurrentTime() > sequenceDate)\r
- sequenceDate = syncState.getCurrentTime();\r
- if (syncState.getUpdateCount() > updateSequenceNumber)\r
- updateSequenceNumber = syncState.getUpdateCount();\r
- conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving SyncRunner.evernoteSync");\r
- }\r
- \r
- // Sync deleted items with Evernote\r
- private void syncExpunged(Client noteStore) {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncExpunged");\r
- \r
- List<DeletedItemRecord> expunged = conn.getDeletedTable().getAllDeleted();\r
- boolean error = false;\r
- for (int i=0; i<expunged.size() && keepRunning; i++) {\r
-\r
-// if (authRefreshNeeded)\r
-// if (!refreshConnection())\r
-// return;\r
-\r
- try {\r
- if (expunged.get(i).type.equalsIgnoreCase("TAG")) {\r
- logger.log(logger.EXTREME, "Tag expunged");\r
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "TAG"); \r
- updateSequenceNumber = noteStore.expungeTag(authToken, expunged.get(i).guid);\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); \r
- }\r
- if (expunged.get(i).type.equalsIgnoreCase("NOTEBOOK")) {\r
- logger.log(logger.EXTREME, "Notebook expunged");\r
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTEBOOK");\r
- updateSequenceNumber = noteStore.expungeNotebook(authToken, expunged.get(i).guid);\r
- conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- }\r
- if (expunged.get(i).type.equalsIgnoreCase("NOTE")) {\r
- logger.log(logger.EXTREME, "Note expunged");\r
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTE");\r
- updateSequenceNumber = noteStore.deleteNote(authToken, expunged.get(i).guid);\r
- refreshNeeded = true;\r
- conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- }\r
- if (expunged.get(i).type.equalsIgnoreCase("SAVEDSEARCH")) {\r
- logger.log(logger.EXTREME, "saved search expunged");\r
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "SAVEDSEARCH");\r
- updateSequenceNumber = noteStore.expungeSearch(authToken, expunged.get(i).guid);\r
- conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- }\r
- } catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "EDAM User Excepton in syncExpunged: " +expunged.get(i).guid); // This can happen if we try to delete a deleted note\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "EDAM System Excepton in syncExpunged: "+expunged.get(i).guid);\r
- logger.log(logger.LOW, e.getStackTrace());\r
- error=true;\r
- } catch (EDAMNotFoundException e) {\r
- logger.log(logger.LOW, "EDAM Not Found Excepton in syncExpunged: "+expunged.get(i).guid);\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "EDAM TExcepton in syncExpunged: "+expunged.get(i).guid);\r
- logger.log(logger.LOW, e.getStackTrace());\r
- error=true;\r
- }\r
- }\r
- if (!error)\r
- conn.getDeletedTable().expungeAllDeletedRecords();\r
- \r
- logger.log(logger.HIGH, "Leaving SyncRunner.syncExpunged");\r
-\r
- }\r
- private void syncDeletedNotes(Client noteStore) {\r
- if (syncDeletedContent)\r
- return;\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncDeletedNotes");\r
- status.message.emit(tr("Synchronizing deleted notes."));\r
-\r
- 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
- \r
-// if (authRefreshNeeded)\r
-// if (!refreshConnection())\r
-// return;\r
- \r
- Note enNote = notes.get(i);\r
- try {\r
- if (enNote.getUpdateSequenceNum() > 0 && (enNote.isActive() == false || enNote.getDeleted() > 0)) {\r
- // Check that the note is valid. \r
- if (enNote.isActive() == true || enNote.getDeleted() == 0) {\r
- conn.getNoteTable().deleteNote(enNote.getGuid());\r
- enNote = conn.getNoteTable().getNote(enNote.getGuid(), false, false, false, false, false);\r
- }\r
- if (syncDeletedContent) {\r
- logger.log(logger.EXTREME, "Deleted note found & synch content selected");\r
- Note delNote = conn.getNoteTable().getNote(enNote.getGuid(), true, true, true, true, true);\r
- delNote = getNoteContent(delNote);\r
- delNote = noteStore.updateNote(authToken, delNote);\r
- enNote.setUpdateSequenceNum(delNote.getUpdateSequenceNum());\r
- conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
- } else {\r
- logger.log(logger.EXTREME, "Deleted note found & sync content not selected");\r
- int usn = noteStore.deleteNote(authToken, enNote.getGuid());\r
- enNote.setUpdateSequenceNum(usn);\r
- conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); \r
- }\r
- logger.log(logger.EXTREME, "Resetting deleted dirty flag");\r
- conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
- updateSequenceNumber = enNote.getUpdateSequenceNum();\r
- logger.log(logger.EXTREME, "Saving sequence number");\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- } \r
- } catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
- //status.message.emit("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("Error deleting local note: " +e +" - Continuing");\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
- }\r
- // Sync notes with Evernote\r
- private void syncLocalNotes() {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
- logger.log(logger.LOW, "Dirty local notes found: " +new Integer(conn.getNoteTable().getDirtyCount()).toString());\r
- status.message.emit(tr("Sending local notes."));\r
-\r
- 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(localNoteStore, notes.get(i), authToken);\r
- }\r
- logger.log(logger.HIGH, "Leaving SyncRunner.syncNotes");\r
-\r
- }\r
- // Sync notes with Evernote\r
- private void syncLocalNote(Client noteStore, Note enNote, String token) {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
- status.message.emit(tr("Sending local notes."));\r
- \r
- if (enNote.isActive()) {\r
- try {\r
- if (enNote.getUpdateSequenceNum() > 0) {\r
- logger.log(logger.EXTREME, "Active dirty note found - non new - " +enNote.getGuid());\r
- logger.log(logger.EXTREME, "Fetching note content");\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 " +enNote.getGuid());\r
- String oldGuid = enNote.getGuid();\r
- logger.log(logger.MEDIUM, "Fetching note content");\r
- enNote = getNoteContent(enNote);\r
- logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
- enNote = noteStore.createNote(token, enNote);\r
- logger.log(logger.MEDIUM, "New note Guid : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\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
- }\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, "Leaving SyncRunner.syncLocalNote");\r
-\r
- }\r
-\r
- // Sync Notebooks with Evernote\r
- private void syncLocalNotebooks(Client noteStore) {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks");\r
- \r
- status.message.emit(tr("Sending local notebooks."));\r
- List<Notebook> remoteList = new ArrayList<Notebook>();\r
- try {\r
- logger.log(logger.EXTREME, "Getting remote notebooks to compare with local");\r
- remoteList = noteStore.listNotebooks(authToken);\r
- } catch (EDAMUserException e1) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks getting remote Notebook List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } catch (EDAMSystemException e1) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks getting remote Notebook List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } catch (TException e1) {\r
- logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalNotebooks getting remote Notebook List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- }\r
- logger.log(logger.EXTREME, "Getting local dirty notebooks");\r
- List<Notebook> notebooks = conn.getNotebookTable().getDirty();\r
- int sequence;\r
- // Sync the local notebooks with Evernote's\r
- for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
- \r
-// if (authRefreshNeeded)\r
-// if (!refreshConnection())\r
-// return;\r
- \r
- Notebook enNotebook = notebooks.get(i);\r
- try {\r
- if (enNotebook.getUpdateSequenceNum() > 0) {\r
- logger.log(logger.EXTREME, "Existing notebook is dirty");\r
- sequence = noteStore.updateNotebook(authToken, enNotebook);\r
- } else {\r
- logger.log(logger.EXTREME, "New dirty notebook found");\r
- String oldGuid = enNotebook.getGuid();\r
- boolean found = false;\r
- \r
- // Look for a notebook with the same name. If one is found, we don't need \r
- // to create another one\r
- logger.log(logger.EXTREME, "Looking for matching notebook name");\r
- for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {\r
- if (remoteList.get(k).getName().equalsIgnoreCase(enNotebook.getName())) {\r
- enNotebook = remoteList.get(k);\r
- logger.log(logger.EXTREME, "Matching notebook found");\r
- found = true;\r
- }\r
- }\r
- if (!found)\r
- enNotebook = noteStore.createNotebook(authToken, enNotebook);\r
- \r
- logger.log(logger.EXTREME, "Updating notebook in database");\r
- conn.getNotebookTable().updateNotebookGuid(oldGuid, enNotebook.getGuid());\r
- sequence = enNotebook.getUpdateSequenceNum();\r
- }\r
- logger.log(logger.EXTREME, "Updating notebook sequence in database");\r
- conn.getNotebookTable().updateNotebookSequence(enNotebook.getGuid(), sequence);\r
- logger.log(logger.EXTREME, "Resetting dirty flag in notebook");\r
- conn.getNotebookTable().resetDirtyFlag(enNotebook.getGuid());\r
- updateSequenceNumber = sequence;\r
- logger.log(logger.EXTREME, "Emitting sequence number to main thread");\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- } catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks");\r
- logger.log(logger.LOW, e.toString() + ": Stack : " +enNotebook.getStack()); \r
- error = true;\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (EDAMNotFoundException e) {\r
- logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotebooks");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotebooks");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } \r
- }\r
- logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNotebooks");\r
-\r
- }\r
- // Sync Tags with Evernote\r
- private void syncLocalTags(Client noteStore) {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncLocalTags");\r
- List<Tag> remoteList = new ArrayList<Tag>();\r
- status.message.emit(tr("Sending local tags."));\r
- \r
- try {\r
- logger.log(logger.EXTREME, "Getting remote tags to compare names with the local tags");\r
- remoteList = noteStore.listTags(authToken);\r
- } catch (EDAMUserException e1) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote Tag List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } catch (EDAMSystemException e1) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote Tag List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } catch (TException e1) {\r
- logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote Tag List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } \r
- \r
- int sequence;\r
- \r
- if (badTagSync == null)\r
- badTagSync = new HashMap<String,String>();\r
- else\r
- badTagSync.clear();\r
- \r
- Tag enTag = findNextTag();\r
- \r
- // This is a hack. Sometimes this function goes flookey and goes into a \r
- // perpetual loop. This causes NeverNote to flood Evernote's servers.\r
- // This is a safety valve to prevent unlimited loops.\r
- int maxCount = conn.getTagTable().getDirty().size()+10;\r
- int loopCount = 0;\r
- \r
- while(enTag!=null && loopCount < maxCount) {\r
- loopCount++;\r
-// if (authRefreshNeeded)\r
-// if (!refreshConnection())\r
-// return;\r
-\r
- try {\r
- if (enTag.getUpdateSequenceNum() > 0) {\r
- logger.log(logger.EXTREME, "Updating tag");\r
- sequence = noteStore.updateTag(authToken, enTag);\r
- } else {\r
- \r
- // Look for a tag with the same name. If one is found, we don't need \r
- // to create another one\r
- logger.log(logger.EXTREME, "New tag. Comparing with remote names");\r
- boolean found = false;\r
- String oldGuid = enTag.getGuid();\r
- for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {\r
- if (remoteList.get(k).getName().equalsIgnoreCase(enTag.getName())) {\r
- conn.getTagTable().updateTagGuid(enTag.getGuid(), remoteList.get(k).getGuid());\r
- enTag = remoteList.get(k);\r
- logger.log(logger.EXTREME, "Matching tag name found");\r
- found = true;\r
- }\r
- }\r
- if (!found)\r
- enTag = noteStore.createTag(authToken, enTag);\r
- else\r
- enTag.setUpdateSequenceNum(noteStore.updateTag(authToken,enTag));\r
- sequence = enTag.getUpdateSequenceNum();\r
- if (!oldGuid.equals(enTag.getGuid())) {\r
- logger.log(logger.EXTREME, "Updating tag guid");\r
- conn.getTagTable().updateTagGuid(oldGuid, enTag.getGuid());\r
- }\r
- }\r
- logger.log(logger.EXTREME, "Updating tag sequence number");\r
- conn.getTagTable().updateTagSequence(enTag.getGuid(), sequence);\r
- logger.log(logger.EXTREME, "Resetting tag dirty flag");\r
- conn.getTagTable().resetDirtyFlag(enTag.getGuid());\r
- logger.log(logger.EXTREME, "Emitting sequence number to the main thread.");\r
- updateSequenceNumber = sequence;\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- } catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags: " +enTag.getName());\r
- logger.log(logger.LOW, e.toString());\r
- badTagSync.put(enTag.getGuid(),null);\r
- error = true;\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags: " +enTag.getName());\r
- logger.log(logger.LOW, e.toString()); \r
- badTagSync.put(enTag.getGuid(),null);\r
- error = true;\r
- } catch (EDAMNotFoundException e) {\r
- logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags: " +enTag.getName());\r
- logger.log(logger.LOW, e.toString());\r
- badTagSync.put(enTag.getGuid(),null);\r
- error = true;\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags: " +enTag.getName());\r
- logger.log(logger.LOW, e.toString());\r
- badTagSync.put(enTag.getGuid(),null);\r
- error = true;\r
- } \r
- \r
- // Find the next tag\r
- logger.log(logger.EXTREME, "Finding next tag");\r
- enTag = findNextTag();\r
- }\r
- logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalTags");\r
- }\r
- private void syncLocalLinkedNotebooks(Client noteStore) {\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(Client noteStore) {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
- List<SavedSearch> remoteList = new ArrayList<SavedSearch>();\r
- status.message.emit(tr("Sending saved searches."));\r
- \r
- logger.log(logger.EXTREME, "Getting saved searches to compare with local");\r
- try {\r
- remoteList = noteStore.listSearches(authToken);\r
- } catch (EDAMUserException e1) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote saved search List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } catch (EDAMSystemException e1) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote saved search List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } catch (TException e1) {\r
- logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote saved search List");\r
- status.message.emit(tr("Error: ") +e1);\r
- logger.log(logger.LOW, e1.toString()); \r
- error = true;\r
- } \r
- \r
- List<SavedSearch> searches = conn.getSavedSearchTable().getDirty();\r
- int sequence;\r
- // Sync the local notebooks with Evernote's\r
- logger.log(logger.EXTREME, "Beginning to send saved searches");\r
- for (int i=0; i<searches.size() && keepRunning; i++) {\r
- \r
-// if (authRefreshNeeded)\r
-// if (!refreshConnection())\r
-// return;\r
- \r
- SavedSearch enSearch = searches.get(i);\r
- try {\r
- if (enSearch.getUpdateSequenceNum() > 0) \r
- sequence = noteStore.updateSearch(authToken, enSearch);\r
- else {\r
- logger.log(logger.EXTREME, "New saved search found.");\r
- // Look for a tag with the same name. If one is found, we don't need \r
- // to create another one\r
- boolean found = false;\r
- logger.log(logger.EXTREME, "Matching remote saved search names with local");\r
- for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {\r
- if (remoteList.get(k).getName().equalsIgnoreCase(enSearch.getName())) {\r
- enSearch = remoteList.get(k);\r
- found = true;\r
- logger.log(logger.EXTREME, "Matching saved search found");\r
- sequence = enSearch.getUpdateSequenceNum();\r
- }\r
- }\r
-\r
- String oldGuid = enSearch.getGuid();\r
- if (!found)\r
- enSearch = noteStore.createSearch(authToken, enSearch);\r
- sequence = enSearch.getUpdateSequenceNum();\r
- logger.log(logger.EXTREME, "Updating tag guid in local database");\r
- conn.getSavedSearchTable().updateSavedSearchGuid(oldGuid, enSearch.getGuid());\r
- }\r
- logger.log(logger.EXTREME, "Updating tag sequence in local database");\r
- conn.getSavedSearchTable().updateSavedSearchSequence(enSearch.getGuid(), sequence);\r
- logger.log(logger.EXTREME, "Resetting tag dirty flag");\r
- conn.getSavedSearchTable().resetDirtyFlag(enSearch.getGuid());\r
- logger.log(logger.EXTREME, "Emitting sequence number to the main thread.");\r
- updateSequenceNumber = sequence;\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- } catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (EDAMNotFoundException e) {\r
- logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } \r
- }\r
-\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
- } \r
-\r
- // Sync evernote changes with local database\r
- private void syncRemoteToLocal(Client noteStore) {\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncRemoteToLocal");\r
-\r
- List<Note> dirtyNotes = conn.getNoteTable().getDirty();\r
- dirtyNoteGuids = new ArrayList<String>();\r
- for (int i=0; i<dirtyNotes.size() && keepRunning; i++) {\r
- dirtyNoteGuids.add(dirtyNotes.get(i).getGuid());\r
- }\r
- \r
- int chunkSize = 10;\r
- SyncChunk chunk = null;\r
- boolean fullSync = false;\r
- boolean more = true;\r
- \r
- if (updateSequenceNumber == 0)\r
- fullSync = true;\r
- \r
- status.message.emit(tr("Downloading 0% complete."));\r
- \r
- while(more && keepRunning) {\r
- \r
-// if (authRefreshNeeded)\r
-// if (!refreshConnection())\r
-// return;\r
- \r
- int sequence = updateSequenceNumber;\r
- try {\r
-// conn.beginTransaction();\r
- logger.log(logger.EXTREME, "Getting chunk from Evernote");\r
- chunk = noteStore.getSyncChunk(authToken, sequence, chunkSize, fullSync);\r
- logger.log(logger.LOW, "Chunk High Sequence: " +chunk.getChunkHighUSN());\r
- } catch (EDAMUserException e) {\r
- error = true;\r
- e.printStackTrace();\r
- status.message.emit(e.getMessage());\r
- } catch (EDAMSystemException e) {\r
- error = true;\r
- e.printStackTrace();\r
- status.message.emit(e.getMessage());\r
- } catch (TException e) {\r
- error = true;\r
- e.printStackTrace();\r
- status.message.emit(e.getMessage());\r
- } \r
- if (error || chunk == null) \r
- return;\r
- \r
- \r
- \r
- syncRemoteTags(chunk.getTags());\r
- syncRemoteSavedSearches(chunk.getSearches());\r
- syncRemoteNotebooks(chunk.getNotebooks());\r
- syncRemoteNotes(noteStore, chunk.getNotes(), fullSync, authToken);\r
- syncRemoteResources(noteStore, chunk.getResources());\r
- syncRemoteLinkedNotebooks(chunk.getLinkedNotebooks());\r
- \r
- // Signal about any updated notes to invalidate the cache\r
- for (int i=0; i<chunk.getNotesSize(); i++) \r
- noteSignal.noteChanged.emit(chunk.getNotes().get(i).getGuid(), null); \r
- syncExpungedNotes(chunk);\r
- \r
- \r
- // Check for more notes\r
- if (chunk.getChunkHighUSN() <= updateSequenceNumber) \r
- more = false;\r
- if (error)\r
- more = false;\r
- logger.log(logger.EXTREME, "More notes? " +more);\r
-\r
- \r
- // Save the chunk sequence number\r
- if (!error && chunk.getChunkHighUSN() > 0 && keepRunning) {\r
- logger.log(logger.EXTREME, "emitting sequence number to main thread");\r
- updateSequenceNumber = chunk.getChunkHighUSN();\r
- conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
-// conn.commitTransaction();\r
- }\r
- \r
- \r
- if (more) {\r
- long pct = chunk.getChunkHighUSN() * 100;\r
- conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());\r
- pct = pct/evernoteUpdateCount;\r
- status.message.emit(tr("Downloading ") +new Long(pct).toString()+tr("% complete."));\r
- }\r
-// conn.commitTransaction();\r
- }\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 the note is in a local notebook (which means we moved it) or if the \r
- // note returned is null (which means it is already deleted or flagged expunged) \r
- // we delete it.\r
- if (!conn.getNotebookTable().isNotebookLocal(notebookGuid) || localNote == null) {\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
- if (tags != null) {\r
- for (int i=0; i<tags.size() && keepRunning; i++) {\r
- String oldGuid;\r
- oldGuid = conn.getTagTable().findTagByName(tags.get(i).getName());\r
- if (oldGuid != null && !tags.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
- conn.getTagTable().updateTagGuid(oldGuid, tags.get(i).getGuid());\r
- conn.getTagTable().syncTag(tags.get(i), false);\r
- }\r
- }\r
- logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");\r
- }\r
- // Sync remote saved searches\r
- private void syncRemoteSavedSearches(List<SavedSearch> searches) {\r
- logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches");\r
- if (searches != null) {\r
- for (int i=0; i<searches.size() && keepRunning; i++) {\r
- String oldGuid;\r
- oldGuid = conn.getSavedSearchTable().findSavedSearchByName(searches.get(i).getName());\r
- if (oldGuid != null && !searches.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
- conn.getSavedSearchTable().updateSavedSearchGuid(oldGuid, searches.get(i).getGuid());\r
- conn.getSavedSearchTable().syncSavedSearch(searches.get(i), false);\r
- }\r
- }\r
- logger.log(logger.EXTREME, "Leaving SyncRunner.syncSavedSearches");\r
- }\r
- // Sync remote linked notebooks\r
- private void syncRemoteLinkedNotebooks(List<LinkedNotebook> books) {\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.syncLinkedNotebooks");\r
- }\r
- // Sync remote Notebooks 2\r
- private void syncRemoteNotebooks(List<Notebook> notebooks) {\r
- logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");\r
- if (notebooks != null) {\r
- for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
- String oldGuid;\r
- oldGuid = conn.getNotebookTable().findNotebookByName(notebooks.get(i).getName());\r
- 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(Client noteStore, 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(noteStore, resource.get(i), authToken);\r
- }\r
- }\r
- logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
- }\r
- // Sync remote resource\r
- private void syncRemoteResource(Client noteStore, 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
- Note n = conn.getNoteTable().getNote(resource.getNoteGuid(), false, false, false, false, false);\r
- if (n!=null) {\r
- logger.log(logger.HIGH, "Resource for note " +n.getGuid() +" : " +n.getTitle());\r
- }\r
- boolean saveNeeded = false;\r
- /* #1 */ Resource r = getEvernoteResource(noteStore, resource.getGuid(), true,true,true, authToken);\r
- Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);\r
- if (l == null) {\r
- logger.log(logger.HIGH, "Local resource not found");\r
- saveNeeded = true;\r
- } else {\r
- /* #2 */ boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());\r
- if (!isNoteDirty) {\r
- logger.log(logger.HIGH, "Local resource found, but is not dirty");\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
- logger.log(logger.HIGH, "Resource save needed: " +saveNeeded);\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
- // Sync remote notes\r
- private void syncRemoteNotes(Client noteStore, List<Note> note, boolean fullSync, String token) {\r
-\r
- if (note != null) {\r
- \r
- logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes");\r
- logger.log(logger.LOW, "Local Dirty Notes: ");\r
- logger.log(logger.LOW, "Remote Dirty Notes:");\r
- for (int i=0; i<note.size();i++) {\r
- logger.log(logger.LOW, i +" : " +note.get(i).getGuid() + " : " +note.get(i).getTitle() );\r
- }\r
- logger.log(logger.LOW, "---");\r
- \r
- for (int i=0; i<note.size() && keepRunning; i++) {\r
- Note n = getEvernoteNote(noteStore, 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() +" : " +n.getTitle());\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
- boolean ignoreNote = false;\r
- if (ignoreNotebooks.contains(n.getNotebookGuid()))\r
- ignoreNote = true;\r
- for (int i=0; i<n.getTagGuidsSize(); i++) {\r
- if (ignoreTags.contains(n.getTagGuids().get(i))) {\r
- ignoreNote = true;\r
- i=n.getTagGuidsSize();\r
- }\r
- }\r
- \r
- if ((conflictingNote || fullSync) && !ignoreNote) {\r
- logger.log(logger.EXTREME, "Saving Note");\r
- conn.getNoteTable().syncNote(n);\r
- // The following was commented out because it caused a race condition on the database where resources \r
- // may be lost. We do the same thing elsewhere;.\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
- }\r
- private Note getEvernoteNote(Client noteStore, 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(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
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- e.printStackTrace();\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton getEvernoteNote");\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 getEvernoteNote");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- e.printStackTrace();\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton getEvernoteNote");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- e.printStackTrace();\r
- }\r
- return n;\r
- }\r
- private Resource getEvernoteResource(Client noteStore, 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(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
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- e.printStackTrace();\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton getEvernoteNote");\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 getEvernoteNote");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- e.printStackTrace();\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton getEvernoteNote");\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- e.printStackTrace();\r
- }\r
- return n;\r
- }\r
-\r
- \r
- private boolean checkForConflict(Note n) {\r
- logger.log(logger.EXTREME, "Checking note sequence number " +n.getGuid());\r
- Note oldNote = conn.getNoteTable().getNote(n.getGuid(), false, false, false, false, false);\r
- logger.log(logger.EXTREME, "Local/Remote sequence numbers: " +oldNote.getUpdateSequenceNum()+"/"+n.getUpdateSequenceNum());\r
- logger.log(logger.LOW, "Remote Note Title:" +n.getTitle());\r
- logger.log(logger.LOW, "Local Note Title:" +oldNote.getTitle());\r
- if (oldNote.getUpdateSequenceNum() == n.getUpdateSequenceNum()) {\r
- return false;\r
- } \r
- boolean oldIsDirty = conn.getNoteTable().isNoteDirty(n.getGuid());\r
- if (!oldIsDirty) \r
- return false;\r
- return true;\r
- }\r
- \r
- private void moveConflictingNote(String guid) {\r
- logger.log(logger.EXTREME, "Conflicting change found for note " +guid);\r
- List<Notebook> books = conn.getNotebookTable().getAllLocal();\r
- String notebookGuid = null;\r
- for (int i=0; i<books.size() && keepRunning; i++) {\r
- if (books.get(i).getName().equalsIgnoreCase("Conflicting Changes (local)") ||\r
- books.get(i).getName().equalsIgnoreCase("Conflicting Changes")) {\r
- notebookGuid = books.get(i).getGuid();\r
- i=books.size();\r
- }\r
- }\r
- \r
- if (notebookGuid == null) {\r
- logger.log(logger.EXTREME, "Building conflicting change notebook " +guid);\r
- Calendar currentTime = new GregorianCalendar();\r
- Long l = new Long(currentTime.getTimeInMillis());\r
- long prevTime = l;\r
- while (prevTime==l) {\r
- currentTime = new GregorianCalendar();\r
- l=currentTime.getTimeInMillis();\r
- }\r
- String randint = new String(Long.toString(l));\r
- \r
- Notebook newBook = new Notebook();\r
- newBook.setUpdateSequenceNum(0);\r
- newBook.setGuid(randint);\r
- newBook.setName("Conflicting Changes");\r
- newBook.setServiceCreated(new Date().getTime());\r
- newBook.setServiceUpdated(new Date().getTime());\r
- newBook.setDefaultNotebook(false);\r
- newBook.setPublished(false);\r
- \r
- conn.getNotebookTable().addNotebook(newBook, false, true);\r
- notebookSignal.listChanged.emit();\r
- notebookGuid = newBook.getGuid();\r
- refreshNeeded = true;\r
- }\r
- \r
- // Now that we have a good notebook guid, we need to move the conflicting note\r
- // to the local notebook\r
- logger.log(logger.EXTREME, "Moving conflicting note " +guid);\r
- Calendar currentTime = new GregorianCalendar();\r
- Long l = new Long(currentTime.getTimeInMillis());\r
- long prevTime = l;\r
- while (prevTime==l) {\r
- currentTime = new GregorianCalendar();\r
- l = currentTime.getTimeInMillis();\r
- }\r
- String newGuid = new String(Long.toString(l));\r
- \r
- Note oldNote = conn.getNoteTable().getNote(guid, true, true, false, false, false);\r
- for (int i=0; i<oldNote.getResources().size() && keepRunning; i++) {\r
- l = new Long(currentTime.getTimeInMillis());\r
- String newResG = new String(Long.toString(l));\r
- String oldResG = oldNote.getResources().get(i).getGuid();\r
- conn.getNoteTable().noteResourceTable.resetUpdateSequenceNumber(oldResG, true);\r
- conn.getNoteTable().noteResourceTable.updateNoteResourceGuid(oldResG, newResG, true);\r
- }\r
- \r
- conn.getNoteTable().resetNoteSequence(guid);\r
- conn.getNoteTable().updateNoteGuid(guid, newGuid);\r
- conn.getNoteTable().updateNoteNotebook(newGuid, notebookGuid, true);\r
- \r
- noteSignal.notebookChanged.emit(newGuid, notebookGuid);\r
- refreshNeeded = true;\r
- noteSignal.guidChanged.emit(guid,newGuid);\r
- }\r
- \r
-\r
-\r
- \r
- //******************************************************\r
- //******************************************************\r
- //** Utility Functions\r
- //******************************************************\r
- //******************************************************\r
- // Convert a byte array to a hex string\r
- private static String byteArrayToHexString(byte data[]) {\r
- StringBuffer buf = new StringBuffer();\r
- for (byte element : data) {\r
- int halfbyte = (element >>> 4) & 0x0F;\r
- int two_halfs = 0;\r
- do {\r
- if ((0 <= halfbyte) && (halfbyte <= 9))\r
- buf.append((char) ('0' + halfbyte));\r
- else\r
- buf.append((char) ('a' + (halfbyte - 10)));\r
- halfbyte = element & 0x0F;\r
- } while(two_halfs++ < 1);\r
- }\r
- return buf.toString(); \r
- }\r
-\r
- \r
- \r
- //*******************************************************\r
- //* Find dirty tags, which do not have newly created parents\r
- //*******************************************************\r
- private Tag findNextTag() {\r
- logger.log(logger.HIGH, "Entering SyncRunner.findNextTag");\r
- Tag nextTag = null;\r
- List<Tag> tags = conn.getTagTable().getDirty();\r
- \r
- // Find the parent. If the parent has a sequence > 0 then it is a good\r
- // parent.\r
- for (int i=0; i<tags.size() && keepRunning; i++) {\r
- if (!badTagSync.containsKey(tags.get(i).getGuid())) {\r
- if (tags.get(i).getParentGuid() == null) {\r
- logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found without parent");\r
- return tags.get(i);\r
- }\r
- Tag parentTag = conn.getTagTable().getTag(tags.get(i).getParentGuid());\r
- if (parentTag.getUpdateSequenceNum() > 0) {\r
- logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found");\r
- return tags.get(i);\r
- }\r
- }\r
- }\r
- \r
- logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - no tags returned");\r
- return nextTag;\r
- }\r
- \r
- \r
- // Connect to Evernote\r
- public boolean enConnect() {\r
- try {\r
- userStoreTrans = new THttpClient(userStoreUrl);\r
- userStoreTrans.setCustomHeader("User-Agent", userAgent);\r
- } catch (TTransportException e) {\r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
- mb.exec();\r
- e.printStackTrace();\r
- }\r
- userStoreProt = new TBinaryProtocol(userStoreTrans);\r
- userStore = new UserStore.Client(userStoreProt, userStoreProt);\r
- syncSignal.saveUserStore.emit(userStore);\r
- try {\r
- //authResult = userStore.authenticate(username, password, consumerKey, consumerSecret);\r
- user = userStore.getUser(authToken);\r
- } catch (EDAMUserException e) {\r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Error", "Invalid Authorization");\r
- mb.exec();\r
- isConnected = false;\r
- return false;\r
- } catch (EDAMSystemException e) {\r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "EDAM System Excepton", e.getLocalizedMessage());\r
- mb.exec();\r
- e.printStackTrace();\r
- isConnected = false;\r
- } catch (TException e) {\r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
- mb.exec();\r
- e.printStackTrace();\r
- isConnected = false;\r
- }\r
- \r
- boolean versionOk = false;\r
- try {\r
- versionOk = userStore.checkVersion("NixNote", \r
- com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, \r
- com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR);\r
- } catch (TException e) {\r
- e.printStackTrace();\r
- isConnected = false;\r
- } \r
- if (!versionOk) { \r
- System.err.println("Incomatible EDAM client protocol version"); \r
- isConnected = false;\r
- }\r
- //if (authResult != null) {\r
- //user = authResult.getUser(); \r
- //authToken = authResult.getAuthenticationToken(); \r
- if (user == null || noteStoreUrlBase == null) {\r
- logger.log(logger.LOW, "Error retrieving user information. Aborting.");\r
- System.err.println("Error retrieving user information.");\r
- isConnected = false; \r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, tr("Connection Error"), tr("Error retrieving user information. Synchronization not complete"));\r
- mb.exec();\r
- return false;\r
- \r
- }\r
- noteStoreUrl = noteStoreUrlBase + user.getShardId();\r
- syncSignal.saveAuthToken.emit(authToken);\r
- syncSignal.saveNoteStore.emit(localNoteStore);\r
- \r
- \r
- try {\r
- noteStoreTrans = new THttpClient(noteStoreUrl);\r
- noteStoreTrans.setCustomHeader("User-Agent", userAgent);\r
- } catch (TTransportException e) {\r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
- mb.exec();\r
- e.printStackTrace();\r
- isConnected = false;\r
- } \r
- noteStoreProt = new TBinaryProtocol(noteStoreTrans);\r
- localNoteStore = \r
- new NoteStore.Client(noteStoreProt, noteStoreProt); \r
- isConnected = true;\r
- //authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();\r
- //authRefreshTime = authTimeRemaining / 2;\r
- //}\r
- \r
- // Get user information\r
- try {\r
- User user = userStore.getUser(authToken);\r
- syncSignal.saveUserInformation.emit(user);\r
- } catch (EDAMUserException e1) {\r
- e1.printStackTrace();\r
- } catch (EDAMSystemException e1) {\r
- e1.printStackTrace();\r
- } catch (TException e1) {\r
- e1.printStackTrace();\r
- }\r
- \r
- return isConnected;\r
- }\r
- // Disconnect from the database \r
- public void enDisconnect() {\r
- isConnected = false;\r
- }\r
- \r
- /*\r
- // Refresh the connection\r
- private synchronized boolean refreshConnection() {\r
- \r
- logger.log(logger.EXTREME, "Entering SyncRunner.refreshConnection()");\r
-// Calendar cal = Calendar.getInstance();\r
- \r
- // If we are not connected let's get out of here\r
- if (!isConnected)\r
- return false;\r
- \r
- // If we fail too many times, then let's give up.\r
- if (failedRefreshes >=5) {\r
- logger.log(logger.EXTREME, "Refresh attempts have failed. Disconnecting.");\r
- isConnected = false;\r
- status.message.emit(tr("Unable to synchronize - Authentication failed"));\r
- return false;\r
- }\r
- \r
- // If this is the first time through, then we need to set this\r
-// if (authRefreshTime == 0 || cal.getTimeInMillis() > authRefreshTime) \r
-// authRefreshTime = cal.getTimeInMillis();\r
- \r
- // // Default to checking again in 5 min. This in case we fail.\r
- // authRefreshTime = authRefreshTime +(5*60*1000); \r
-\r
- // Try to get a new token\r
- AuthenticationResult newAuth = null; \r
- logger.log(logger.EXTREME, "Beginning to try authentication refresh");\r
- try {\r
- if (userStore != null && authToken != null) \r
- newAuth = userStore.refreshAuthentication(authToken); \r
- else\r
- return false;\r
- logger.log(logger.EXTREME, "UserStore.refreshAuthentication has succeeded.");\r
- } catch (EDAMUserException e) {\r
- e.printStackTrace();\r
- syncSignal.authRefreshComplete.emit(false);\r
- failedRefreshes++;\r
- return false;\r
- } catch (EDAMSystemException e) {\r
- e.printStackTrace();\r
- syncSignal.authRefreshComplete.emit(false);\r
- failedRefreshes++;\r
- return false; \r
- } catch (TException e) { \r
- e.printStackTrace();\r
- syncSignal.authRefreshComplete.emit(false);\r
- failedRefreshes++;\r
- return false;\r
- }\r
- \r
- // If we didn't get a good auth, then we've failed\r
- if (newAuth == null) {\r
- failedRefreshes++;\r
- status.message.emit(tr("Unable to synchronize - Authentication failed"));\r
- logger.log(logger.EXTREME, "Authentication failure #" +failedRefreshes);\r
- status.message.emit(tr("Unable to synchronize - Authentication failed"));\r
- syncSignal.authRefreshComplete.emit(false);\r
- return false;\r
- }\r
- \r
- // We got a good token. Now we need to setup the time to renew it.\r
- logger.log(logger.EXTREME, "Saving authentication tokens");\r
- authResult = newAuth;\r
- authToken = new String(newAuth.getAuthenticationToken());\r
-// authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();\r
-// authRefreshTime = cal.getTimeInMillis() + (authTimeRemaining/4); \r
- failedRefreshes=0;\r
- syncSignal.authRefreshComplete.emit(true);\r
- authRefreshNeeded = false;\r
- \r
- // This should never happen, but if it does we consider this a faild attempt.\r
-// if (authTimeRemaining <= 0) {\r
-// failedRefreshes++;\r
-// syncSignal.authRefreshComplete.emit(false);\r
-// }\r
- \r
- return true;\r
- }\r
- \r
- */\r
- \r
- public synchronized boolean addWork(String request) {\r
- if (workQueue.offer(request))\r
- return true;\r
- return false;\r
- }\r
- \r
- private Note getNoteContent(Note n) {\r
- QTextCodec codec = QTextCodec.codecForLocale();\r
- codec = QTextCodec.codecForName("UTF-8");\r
- n.setContent(codec.toUnicode(new QByteArray(n.getContent())));\r
- return n;\r
- }\r
-\r
-\r
-\r
- //*********************************************************\r
- //* Special download instructions. Used for DB upgrades\r
- //*********************************************************\r
- private void downloadAllSharedNotebooks(Client noteStore) {\r
- try {\r
- List<SharedNotebook> books = noteStore.listSharedNotebooks(authToken);\r
- logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
- for (int i=0; i<books.size(); i++) {\r
- conn.getSharedNotebookTable().updateNotebook(books.get(i), false);\r
- }\r
- conn.getSyncTable().deleteRecord("FullSharedNotebookSync");\r
- } catch (EDAMUserException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("User exception Listing shared notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (EDAMSystemException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("System exception Listing shared notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (TException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("Transaction exception Listing shared notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (EDAMNotFoundException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("EDAM Not Found exception Listing shared notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- }\r
- }\r
- private void downloadAllNotebooks(Client noteStore) {\r
- try {\r
- List<Notebook> books = noteStore.listNotebooks(authToken);\r
- logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
- for (int i=0; i<books.size(); i++) {\r
- conn.getNotebookTable().updateNotebook(books.get(i), false);\r
- }\r
- conn.getSyncTable().deleteRecord("FullNotebookSync");\r
- } catch (EDAMUserException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("User exception Listing notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (EDAMSystemException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("System exception Listing notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (TException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("Transaction exception Listing notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- }\r
- }\r
- private void downloadAllLinkedNotebooks(Client noteStore) {\r
- try {\r
- List<LinkedNotebook> books = noteStore.listLinkedNotebooks(authToken);\r
- logger.log(logger.LOW, "Linked notebooks found = " +books.size());\r
- for (int i=0; i<books.size(); i++) {\r
- conn.getLinkedNotebookTable().updateNotebook(books.get(i), false);\r
- }\r
- conn.getSyncTable().deleteRecord("FullLinkedNotebookSync");\r
- } catch (EDAMUserException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("User exception Listing linked notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (EDAMSystemException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("System exception Listing linked notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (TException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("Transaction exception Listing lineked notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- return;\r
- } catch (EDAMNotFoundException e1) {\r
- e1.printStackTrace();\r
- status.message.emit(tr("EDAM Not Found exception Listing linked notebooks."));\r
- logger.log(logger.LOW, e1.getMessage());\r
- }\r
- }\r
-\r
- \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
- Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, false);\r
- conn.getInkImagesTable().expungeImage(r.getGuid());\r
- int sliceCount = 1+((r.getHeight()-1)/480);\r
- HttpClient http = new DefaultHttpClient();\r
- for (int i=0; i<sliceCount; i++) {\r
- String url = urlBase + slice.toString();\r
- HttpPost post = new HttpPost(url);\r
- post.getParams().setParameter("auth", authToken);\r
- List <NameValuePair> nvps = new ArrayList <NameValuePair>();\r
- nvps.add(new BasicNameValuePair("auth", authToken));\r
-\r
- try {\r
- post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));\r
- } catch (UnsupportedEncodingException e1) {\r
- e1.printStackTrace();\r
- }\r
- try {\r
- HttpResponse response = http.execute(post);\r
- HttpEntity resEntity = response.getEntity();\r
- InputStream is = resEntity.getContent();\r
- QByteArray data = writeToFile(is);\r
- conn.getInkImagesTable().saveImage(guid, slice, data);\r
- } catch (ClientProtocolException e) {\r
- e.printStackTrace();\r
- } catch (IOException e) {\r
- e.printStackTrace();\r
- }\r
-\r
- slice++;\r
- }\r
- http.getConnectionManager().shutdown(); \r
- noteSignal.noteChanged.emit(r.getNoteGuid(), null); // Signal to ivalidate note cache\r
- }\r
- \r
- \r
- public QByteArray writeToFile(InputStream iStream) throws IOException {\r
-\r
- File temp = File.createTempFile("nn-inknote-temp", ".png");\r
-\r
- // Save InputStream to the file.\r
- BufferedOutputStream fOut = null;\r
- try {\r
- fOut = new BufferedOutputStream(new FileOutputStream(temp));\r
- byte[] buffer = new byte[32 * 1024];\r
- int bytesRead = 0;\r
- while ((bytesRead = iStream.read(buffer)) != -1) {\r
- fOut.write(buffer, 0, bytesRead);\r
- }\r
- }\r
- finally {\r
- iStream.close();\r
- fOut.close();\r
- }\r
- QFile tempFile = new QFile(temp.getAbsoluteFile().toString());\r
- tempFile.open(OpenModeFlag.ReadOnly);\r
- QByteArray data = tempFile.readAll();\r
- tempFile.close();\r
- tempFile.remove();\r
- return data;\r
- }\r
- \r
- \r
- //******************************************\r
- //* Begin syncing shared notebooks \r
- //******************************************\r
- private void syncLinkedNotebooks() {\r
- logger.log(logger.MEDIUM, "Authenticating linked Notebooks");\r
- status.message.emit(tr("Synchronizing shared notebooks."));\r
- List<LinkedNotebook> books = conn.getLinkedNotebookTable().getAll();\r
- \r
- errorSharedNotebooks.clear();\r
- \r
- for (int i=0; i<books.size(); i++) {\r
- if (errorSharedNotebooksIgnored.containsKey(books.get(i).getGuid()))\r
- break;\r
- try {\r
- logger.log(logger.EXTREME, "Checking notebook: " +books.get(i).getShareName());\r
- long lastSyncDate = conn.getLinkedNotebookTable().getLastSequenceDate(books.get(i).getGuid());\r
- int lastSequenceNumber = conn.getLinkedNotebookTable().getLastSequenceNumber(books.get(i).getGuid());\r
-\r
- logger.log(logger.EXTREME, "Last Sequence Number on file: " +lastSequenceNumber);\r
- \r
- // Authenticate to the owner's shard\r
- String linkedNoteStoreUrl = noteStoreUrlBase + books.get(i).getShardId();\r
- logger.log(logger.EXTREME, "linkedNoteStoreURL: " +linkedNoteStoreUrl);\r
- THttpClient linkedNoteStoreTrans = new THttpClient(linkedNoteStoreUrl);\r
- TBinaryProtocol linkedNoteStoreProt = new TBinaryProtocol(linkedNoteStoreTrans);\r
- Client linkedNoteStore = new NoteStore.Client(linkedNoteStoreProt, linkedNoteStoreProt); \r
-\r
- linkedAuthResult = null;\r
- if (books.get(i).getShareKey() != null) {\r
- logger.log(logger.EXTREME, "Share Key Not Null: " +books.get(i).getShareKey());\r
- linkedAuthResult = linkedNoteStore.authenticateToSharedNotebook(books.get(i).getShareKey(), authToken);\r
- logger.log(logger.EXTREME, "Authentication Token" +linkedAuthResult.getAuthenticationToken());\r
- } else {\r
- logger.log(logger.EXTREME, "Share key is null");\r
- linkedAuthResult = new AuthenticationResult();\r
- linkedAuthResult.setAuthenticationToken("");\r
- }\r
- SyncState linkedSyncState = \r
- linkedNoteStore.getLinkedNotebookSyncState(linkedAuthResult.getAuthenticationToken(), books.get(i));\r
- if (linkedSyncState.getUpdateCount() > lastSequenceNumber) {\r
- logger.log(logger.EXTREME, "Remote changes found");\r
- if (lastSyncDate < linkedSyncState.getFullSyncBefore()) {\r
- lastSequenceNumber = 0;\r
- } \r
- logger.log(logger.EXTREME, "Calling syncLinkedNotebook for " +books.get(i).getShareName());\r
- syncLinkedNotebook(linkedNoteStore, books.get(i), \r
- lastSequenceNumber, linkedSyncState.getUpdateCount(), authToken);\r
- }\r
- \r
- // Synchronize local changes\r
- syncLocalLinkedNoteChanges(linkedNoteStore, books.get(i));\r
- \r
- } catch (EDAMUserException e) {\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
- errorSharedNotebooks.add(books.get(i).getGuid());\r
- errorSharedNotebooksIgnored.put(books.get(i).getGuid(), books.get(i).getGuid());\r
- logger.log(logger.LOW, "Error synchronizing shared notebook. EDAMNotFound: "+e.getMessage());\r
- logger.log(logger.LOW, e.getStackTrace());\r
- error = true;\r
- e.printStackTrace();\r
- } catch (EDAMSystemException e) {\r
- error = true;\r
- logger.log(logger.LOW, "System error authenticating against shared notebook. "+\r
- "Key: "+books.get(i).getShareKey() +" Error:" +e.getMessage());\r
- e.printStackTrace();\r
- } catch (TException e) {\r
- error = true;\r
- e.printStackTrace();\r
- }\r
- }\r
- \r
- // Cleanup tags\r
- conn.getTagTable().removeUnusedLinkedTags();\r
- conn.getTagTable().cleanupTags();\r
- tagSignal.listChanged.emit();\r
- return;\r
- }\r
-\r
- \r
- //**************************************************************\r
- //* Linked notebook contents (from someone else's account)\r
- //*************************************************************\r
- private void syncLinkedNotebook(Client linkedNoteStore, LinkedNotebook book, int usn, int highSequence, String token) {\r
- logger.log(logger.EXTREME, "Entering syncLinkedNotebook");\r
- if (ignoreLinkedNotebooks.contains(book.getGuid()))\r
- return;\r
- List<Note> dirtyNotes = conn.getNoteTable().getDirtyLinkedNotes();\r
- if (dirtyNoteGuids == null) \r
- dirtyNoteGuids = new ArrayList<String>();\r
-\r
- for (int i=0; i<dirtyNotes.size() && keepRunning; i++) {\r
- dirtyNoteGuids.add(dirtyNotes.get(i).getGuid());\r
- }\r
- boolean fullSync = false;\r
- if (usn == 0)\r
- fullSync = true;\r
- boolean syncError = false;\r
- while (usn < highSequence && !syncError) {\r
- refreshNeeded = true;\r
- try {\r
- SyncChunk chunk = \r
- linkedNoteStore.getLinkedNotebookSyncChunk(token, book, usn, 10, fullSync);\r
- \r
- // Expunge notes\r
- syncExpungedNotes(chunk);\r
-\r
- logger.log(logger.EXTREME, "Syncing remote notes: " +chunk.getNotesSize());\r
- syncRemoteNotes(linkedNoteStore, chunk.getNotes(), fullSync, linkedAuthResult.getAuthenticationToken());\r
- logger.log(logger.EXTREME, "Finding new linked tags");\r
- findNewLinkedTags(linkedNoteStore, chunk.getNotes(), linkedAuthResult.getAuthenticationToken());\r
- // Sync resources\r
- logger.log(logger.EXTREME, "Synchronizing tags: " +chunk.getTagsSize());\r
- for (int i=0; i<chunk.getResourcesSize(); i++) {\r
- syncRemoteResource(linkedNoteStore, chunk.getResources().get(i), linkedAuthResult.getAuthenticationToken());\r
- }\r
- logger.log(logger.EXTREME, "Synchronizing linked notebooks: " +chunk.getNotebooksSize());\r
- syncRemoteLinkedNotebooks(linkedNoteStore, chunk.getNotebooks(), false, book);\r
- syncLinkedTags(chunk.getTags(), book.getGuid());\r
- \r
- // Go through & signal any notes that have changed so we can refresh the user's view\r
- for (int i=0; i<chunk.getNotesSize(); i++) \r
- noteSignal.noteChanged.emit(chunk.getNotes().get(i).getGuid(), null);\r
-\r
- // Expunge Notebook records\r
- logger.log(logger.EXTREME, "Expunging linked notebooks: " +chunk.getExpungedLinkedNotebooksSize());\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
- syncError = true;\r
- status.message.emit(tr("EDAM UserException synchronizing linked notbook. See the log for datails."));\r
- e.printStackTrace();\r
- logger.log(logger.LOW, tr("EDAM UserException synchronizing linked notbook ")+ e.getMessage());\r
- } catch (EDAMSystemException e) {\r
- syncError = true;\r
- status.message.emit(tr("EDAM SystemException synchronizing linked notbook. See the log for datails."));\r
- e.printStackTrace();\r
- logger.log(logger.LOW, tr("EDAM SystemException synchronizing linked notbook. See the log for datails") +e.getMessage());\r
- } catch (EDAMNotFoundException e) {\r
- syncError = true;\r
- status.message.emit(tr("Notebook URL not found. Removing notobook ") +book.getShareName());\r
- conn.getNotebookTable().deleteLinkedTags(book.getGuid());\r
- conn.getLinkedNotebookTable().expungeNotebook(book.getGuid(), false);\r
- logger.log(logger.LOW, tr("Notebook URL not found. Removing notobook ") +e.getMessage());\r
- } catch (TException e) {\r
- syncError = true;\r
- status.message.emit(tr("EDAM TException synchronizing linked notbook. See the log for datails."));\r
- e.printStackTrace();\r
- logger.log(logger.LOW, tr("EDAM TException synchronizing linked notbook. See the log for datails." )+e.getMessage());\r
- }\r
- }\r
- logger.log(logger.EXTREME, "leaving syncLinkedNotebook");\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(Client noteStore, 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
- logger.log(logger.EXTREME, "auth token:" +linkedAuthResult.getAuthenticationToken());\r
- if (!linkedAuthResult.getAuthenticationToken().equals("")) {\r
- SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());\r
- logger.log(logger.EXTREME, "share key:"+s.getShareKey() +" notebookGuid" +s.getNotebookGuid());\r
- conn.getLinkedNotebookTable().setNotebookGuid(s.getShareKey(), s.getNotebookGuid());\r
- readOnly = !s.isNotebookModifiable();\r
- } else {\r
- readOnly = true;\r
- }\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(Client noteStore, 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
- e.printStackTrace();\r
- } catch (EDAMSystemException e) {\r
- e.printStackTrace();\r
- } catch (EDAMNotFoundException e) {\r
- e.printStackTrace();\r
- } catch (TException e) {\r
- e.printStackTrace();\r
- }\r
- \r
- }\r
- }\r
- }\r
- }\r
-\r
- // Synchronize changes locally done to linked notes\r
- private void syncLocalLinkedNoteChanges(Client noteStore, LinkedNotebook book) {\r
- logger.log(logger.EXTREME, "Entering SyncRunner.synclocalLinkedNoteChanges");\r
- String notebookGuid = conn.getLinkedNotebookTable().getNotebookGuid(book.getGuid());\r
- logger.log(logger.EXTREME, "Finding changes for " +book.getShareName() +":" +book.getGuid() + ":" +notebookGuid);\r
- List<Note> notes = conn.getNoteTable().getDirtyLinked(notebookGuid);\r
- logger.log(logger.EXTREME, "Number of changes found: " +notes.size());\r
- for (int i=0; i<notes.size(); i++) {\r
- logger.log(logger.EXTREME, "Calling syncLocalNote with key " +linkedAuthResult.getAuthenticationToken());\r
- syncLocalNote(noteStore, notes.get(i), linkedAuthResult.getAuthenticationToken());\r
- }\r
- logger.log(logger.EXTREME, "Leaving SyncRunner.synclocalLinkedNoteChanges");\r
- }\r
-\r
-}\r
+/*
+ * This file is part of NixNote/NeighborNote
+ * Copyright 2009 Randy Baumgarte
+ * Copyright 2013 Yuki Takahashi
+ *
+ * This file may be licensed under the terms of of the
+ * GNU General Public License Version 2 (the ``GPL'').
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the GPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the GPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+*/
+package cx.fbn.nevernote.threads;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.HTTP;
+
+import com.evernote.edam.error.EDAMErrorCode;
+import com.evernote.edam.error.EDAMNotFoundException;
+import com.evernote.edam.error.EDAMSystemException;
+import com.evernote.edam.error.EDAMUserException;
+import com.evernote.edam.notestore.NoteStore;
+import com.evernote.edam.notestore.NoteStore.Client;
+import com.evernote.edam.notestore.SyncChunk;
+import com.evernote.edam.notestore.SyncState;
+import com.evernote.edam.type.Data;
+import com.evernote.edam.type.LinkedNotebook;
+import com.evernote.edam.type.Note;
+import com.evernote.edam.type.Notebook;
+import com.evernote.edam.type.Resource;
+import com.evernote.edam.type.SavedSearch;
+import com.evernote.edam.type.SharedNotebook;
+import com.evernote.edam.type.Tag;
+import com.evernote.edam.type.User;
+import com.evernote.edam.userstore.AuthenticationResult;
+import com.evernote.edam.userstore.UserStore;
+import com.evernote.thrift.TException;
+import com.evernote.thrift.protocol.TBinaryProtocol;
+import com.evernote.thrift.transport.THttpClient;
+import com.evernote.thrift.transport.TTransportException;
+import com.trolltech.qt.core.QByteArray;
+import com.trolltech.qt.core.QFile;
+import com.trolltech.qt.core.QIODevice.OpenModeFlag;
+import com.trolltech.qt.core.QObject;
+import com.trolltech.qt.core.QTextCodec;
+import com.trolltech.qt.gui.QMessageBox;
+
+import cx.fbn.nevernote.signals.LimitSignal;
+import cx.fbn.nevernote.signals.NoteIndexSignal;
+import cx.fbn.nevernote.signals.NoteResourceSignal;
+import cx.fbn.nevernote.signals.NoteSignal;
+import cx.fbn.nevernote.signals.NotebookSignal;
+import cx.fbn.nevernote.signals.SavedSearchSignal;
+import cx.fbn.nevernote.signals.StatusSignal;
+import cx.fbn.nevernote.signals.SyncSignal;
+import cx.fbn.nevernote.signals.TagSignal;
+import cx.fbn.nevernote.sql.DatabaseConnection;
+import cx.fbn.nevernote.sql.DeletedItemRecord;
+import cx.fbn.nevernote.utilities.ApplicationLogger;
+
+
+public class SyncRunner extends QObject implements Runnable {
+
+ private final ApplicationLogger logger;
+ private DatabaseConnection conn;
+ private boolean idle;
+ public boolean error;
+ public volatile List<String> errorSharedNotebooks;
+ public volatile HashMap<String,String> errorSharedNotebooksIgnored;
+ public volatile boolean isConnected;
+ public volatile boolean keepRunning;
+ public volatile String authToken;
+ private long evernoteUpdateCount;
+ private final String userAgent = "NeighborNote/" + System.getProperty("os.name")
+ +"/"+System.getProperty("java.vendor") + "/"
+ + System.getProperty("java.version") +";";
+
+ public volatile NoteStore.Client localNoteStore;
+ private UserStore.Client userStore;
+
+ public volatile StatusSignal status;
+ public volatile TagSignal tagSignal;
+ public volatile NotebookSignal notebookSignal;
+ public volatile NoteIndexSignal noteIndexSignal;
+ public volatile NoteSignal noteSignal;
+ public volatile SavedSearchSignal searchSignal;
+ public volatile NoteResourceSignal resourceSignal;
+ public volatile SyncSignal syncSignal;
+ public volatile LimitSignal limitSignal;
+ public volatile boolean authRefreshNeeded;
+ public volatile boolean syncNeeded;
+ public volatile boolean disableUploads;
+ public volatile boolean syncDeletedContent;
+ private volatile List<String> dirtyNoteGuids;
+
+ public volatile String username = "";
+ public volatile String password = "";
+ public volatile String userStoreUrl;
+ public String noteStoreUrlBase;
+ private THttpClient userStoreTrans;
+ private TBinaryProtocol userStoreProt;
+ //private AuthenticationResult authResult;
+ private AuthenticationResult linkedAuthResult;
+ private User user;
+// private long authTimeRemaining;
+ public long authRefreshTime;
+ public long failedRefreshes = 0;
+ public THttpClient noteStoreTrans;
+ public TBinaryProtocol noteStoreProt;
+ public String noteStoreUrl;
+ public long sequenceDate;
+ public int updateSequenceNumber;
+ private boolean refreshNeeded;
+ private volatile LinkedBlockingQueue<String> workQueue;
+ private static int MAX_QUEUED_WAITING = 1000;
+ String dbuid;
+ String dburl;
+ String indexUrl;
+ String resourceUrl;
+ String behaviorUrl;
+
+ String dbpswd;
+ String dbcpswd;
+ private final TreeSet<String> ignoreTags;
+ private final TreeSet<String> ignoreNotebooks;
+ private final TreeSet<String> ignoreLinkedNotebooks;
+ private HashMap<String,String> badTagSync;
+
+
+ public SyncRunner(String logname, String u, String i, String r, String b, String uid, String pswd, String cpswd) {
+ logger = new ApplicationLogger(logname);
+
+ noteSignal = new NoteSignal();
+ status = new StatusSignal();
+ tagSignal = new TagSignal();
+ notebookSignal = new NotebookSignal();
+ noteIndexSignal = new NoteIndexSignal();
+ noteSignal = new NoteSignal();
+ searchSignal = new SavedSearchSignal();
+ syncSignal = new SyncSignal();
+ resourceSignal = new NoteResourceSignal();
+ limitSignal = new LimitSignal();
+ resourceUrl = r;
+ indexUrl = i;
+ behaviorUrl = b;
+
+ dbuid = uid;
+ dburl = u;
+ dbpswd = pswd;
+ dbcpswd = cpswd;
+// this.setAutoDelete(false);
+
+ isConnected = false;
+ syncNeeded = false;
+ authRefreshNeeded = false;
+ keepRunning = true;
+ idle = true;
+ disableUploads = false;
+ ignoreTags = new TreeSet<String>();
+ ignoreNotebooks = new TreeSet<String>();
+ ignoreLinkedNotebooks = new TreeSet<String>();
+
+// setAutoDelete(false);
+ workQueue=new LinkedBlockingQueue<String>(MAX_QUEUED_WAITING);
+ }
+ @Override
+ public void run() {
+ errorSharedNotebooks = new ArrayList<String>();
+ errorSharedNotebooksIgnored = new HashMap<String,String>();
+ try {
+ logger.log(logger.EXTREME, "Starting thread");
+ conn = new DatabaseConnection(logger, dburl, indexUrl, resourceUrl, behaviorUrl, dbuid, dbpswd, dbcpswd, 200);
+ while(keepRunning) {
+ logger.log(logger.EXTREME, "Blocking until work is found");
+ String work = workQueue.take();
+ logger.log(logger.LOW, "Dirty Notes Before Sync: " +new Integer(conn.getNoteTable().getDirtyCount()).toString());
+ logger.log(logger.EXTREME, "Work found: " +work);
+ if (work.equalsIgnoreCase("stop")) {
+ idle=false;
+ return;
+ }
+ conn.getNoteTable().dumpDirtyNotes(); // Debugging statement
+ idle=false;
+ error=false;
+ if (syncNeeded) {
+ logger.log(logger.EXTREME, "SyncNeeded is true");
+ refreshNeeded=false;
+ sequenceDate = conn.getSyncTable().getLastSequenceDate();
+ updateSequenceNumber = conn.getSyncTable().getUpdateSequenceNumber();
+ try {
+ logger.log(logger.EXTREME, "Beginning sync");
+ evernoteSync(localNoteStore);
+ logger.log(logger.EXTREME, "Sync finished");
+ } catch (UnknownHostException e) {
+ status.message.emit(e.getMessage());
+ }
+ }
+ idle=true;
+ logger.log(logger.EXTREME, "Signaling refresh finished. refreshNeeded=" +refreshNeeded);
+ syncSignal.finished.emit(refreshNeeded);
+ if (error) {
+ syncSignal.errorDisconnect.emit();
+ status.message.emit(tr("Error synchronizing - see log for details."));
+ }
+ logger.log(logger.LOW, "Dirty Notes After Sync: " +new Integer(conn.getNoteTable().getDirtyCount()).toString());
+ conn.getNoteTable().dumpDirtyNotes();
+ logger.log(logger.LOW, "---");
+ }
+ }
+ catch (InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ conn.dbShutdown();
+ }
+
+
+ public DatabaseConnection getConnection() {
+ return conn;
+ }
+
+ public boolean isIdle() {
+ return idle;
+ }
+
+
+ public void setConnected(boolean c) {
+ isConnected = c;
+ }
+ public void setKeepRunning(boolean r) {
+ logger.log(logger.EXTREME, "Setting keepRunning=" +r);
+ keepRunning = r;
+ }
+ public void setNoteStore(NoteStore.Client c) {
+ logger.log(logger.EXTREME, "Setting NoteStore in sync thread");
+ localNoteStore = c;
+ }
+ public void setUserStore(UserStore.Client c) {
+ logger.log(logger.EXTREME, "Setting UserStore in sync thread");
+ userStore = c;
+ }
+
+ public void setEvernoteUpdateCount(long s) {
+ logger.log(logger.EXTREME, "Setting Update Count in sync thread");
+ evernoteUpdateCount = s;
+ }
+
+ //***************************************************************
+ //***************************************************************
+ //** These functions deal with Evernote communications
+ //***************************************************************
+ //***************************************************************
+ // Synchronize changes with Evernote
+ @SuppressWarnings("unused")
+ private void evernoteSync(Client noteStore) throws java.net.UnknownHostException {
+ logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync");
+
+ // Rebuild list of tags & notebooks to ignore
+ ignoreNotebooks.clear();
+ List<String> ignore = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
+ for (int i=0; i<ignore.size(); i++)
+ ignoreNotebooks.add(ignore.get(i));
+
+ ignore.clear();
+ ignore = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
+ for (int i=0; i<ignore.size(); i++)
+ ignoreLinkedNotebooks.add(ignore.get(i));
+
+ ignoreTags.clear();
+ ignore = conn.getSyncTable().getIgnoreRecords("TAG");
+ for (int i=0; i<ignore.size(); i++)
+ ignoreTags.add(ignore.get(i));
+
+ // Make sure we are connected & should keep running
+ if (isConnected && keepRunning) {
+ error = false;
+ logger.log(logger.EXTREME, "Synchronizing with Evernote");
+ status.message.emit(tr("Synchronizing with Evernote"));
+
+ // Get user information
+ try {
+ logger.log(logger.EXTREME, "getting user from userstore");
+ User user = userStore.getUser(authToken);
+ logger.log(logger.EXTREME, "Saving user information");
+ syncSignal.saveUserInformation.emit(user);
+ } catch (EDAMUserException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("User exception getting user account information. Aborting sync and disconnecting"));
+ syncSignal.errorDisconnect.emit();
+ error = true;
+ enDisconnect();
+ return;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+
+ e1.printStackTrace();
+ status.message.emit(tr("System error user account information. Aborting sync and disconnecting!"));
+ syncSignal.errorDisconnect.emit();
+ error = true;
+ enDisconnect();
+ return;
+ } catch (TException e1) {
+ e1.printStackTrace();
+ syncSignal.errorDisconnect.emit();
+ error = true;
+ status.message.emit(tr("Transaction error getting user account information. Aborting sync and disconnecting!"));
+ enDisconnect();
+ return;
+ }
+
+ // Get sync state
+ SyncState syncState = null;
+ try {
+ logger.log(logger.EXTREME, "Getting sync state");
+ syncState = noteStore.getSyncState(authToken);
+ syncSignal.saveUploadAmount.emit(syncState.getUploaded());
+ syncSignal.saveEvernoteUpdateCount.emit(syncState.getUpdateCount());
+ evernoteUpdateCount = syncState.getUpdateCount();
+ } catch (EDAMUserException e) {
+ e.printStackTrace();
+ status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));
+ syncSignal.errorDisconnect.emit();
+ enDisconnect();
+ return;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ e.printStackTrace();
+ status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));
+ syncSignal.errorDisconnect.emit();
+ enDisconnect();
+ return;
+ } catch (TException e) {
+ e.printStackTrace();
+ status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));
+ syncSignal.errorDisconnect.emit();
+ enDisconnect();
+ return;
+ }
+
+ if (syncState == null) {
+ logger.log(logger.EXTREME, "Sync State is null");
+ status.message.emit(tr("Syncronization Error!"));
+ return;
+ }
+
+ // Determine what to do.
+ // If we need to do a full sync.
+ logger.log(logger.LOW, "Full Sequence Before: " +syncState.getFullSyncBefore());
+ logger.log(logger.LOW, "Last Sequence Date: " +sequenceDate);
+ logger.log(logger.LOW, "Var Last Sequence Number: " +updateSequenceNumber);
+ logger.log(logger.LOW, "DB Last Sequence Number: " + conn.getSyncTable().getUpdateSequenceNumber());
+ if (syncState.getFullSyncBefore() > sequenceDate) {
+ logger.log(logger.EXTREME, "Full sequence date has expired");
+ sequenceDate = 0;
+ conn.getSyncTable().setLastSequenceDate(0);
+ updateSequenceNumber = 0;
+ conn.getSyncTable().setUpdateSequenceNumber(0);
+ }
+ // Check for "special" sync instructions
+ String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync");
+ String syncShared = conn.getSyncTable().getRecord("FullSharedNotebookSync");
+ String syncNotebooks = conn.getSyncTable().getRecord("FullNotebookSync");
+ String syncInkNoteImages = conn.getSyncTable().getRecord("FullInkNoteImageSync");
+ if (syncLinked != null) {
+ downloadAllLinkedNotebooks(localNoteStore);
+ }
+ if (syncShared != null) {
+ downloadAllSharedNotebooks(localNoteStore);
+ }
+ if (syncNotebooks != null) {
+ downloadAllNotebooks(localNoteStore);
+ }
+
+ if (syncInkNoteImages != null) {
+ List<String> guids = conn.getNoteTable().noteResourceTable.findInkNotes();
+ for (int i=0; i<guids.size(); i++) {
+ downloadInkNoteImage(guids.get(i), authToken);
+ }
+ conn.getSyncTable().deleteRecord("FullInkNoteImageSync");
+ }
+
+ // If there are remote changes
+ logger.log(logger.LOW, "Update Count: " +syncState.getUpdateCount());
+ logger.log(logger.LOW, "Last Update Count: " +updateSequenceNumber);
+
+ if (syncState.getUpdateCount() > updateSequenceNumber) {
+ logger.log(logger.EXTREME, "Refresh needed is true");
+ refreshNeeded = true;
+ logger.log(logger.EXTREME, "Downloading changes");
+ syncRemoteToLocal(localNoteStore);
+ }
+
+ //*****************************************
+ //* Sync linked/shared notebooks
+ //*****************************************
- //syncLinkedNotebooks();
++ syncLinkedNotebooks();
+ //conn.getNoteTable().getDirty();
+ //disableUploads = true; /// DELETE THIS LINE!!!!
+ if (!disableUploads) {
+ logger.log(logger.EXTREME, "Uploading changes");
+ // Synchronize remote changes
+ if (!error)
+ syncExpunged(localNoteStore);
+ if (!error)
+ syncLocalTags(localNoteStore);
+ if (!error)
+ syncLocalNotebooks(localNoteStore);
+ if (!error)
+ syncLocalLinkedNotebooks(localNoteStore);
+ if (!error)
+ syncDeletedNotes(localNoteStore);
+ if (!error)
+ syncLocalNotes();
+ if (!error)
+ syncLocalSavedSearches(localNoteStore);
+ }
+
+ status.message.emit(tr("Cleaning up"));
+ List<String> notes = conn.getNoteTable().expungeIgnoreSynchronizedNotes(conn.getSyncTable().getIgnoreRecords("NOTEBOOK"),
+ conn.getSyncTable().getIgnoreRecords("TAG"), conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"));
+ if (notes.size() > 0)
+ syncSignal.refreshLists.emit();
+
+ //*****************************************
+ //* End of synchronization
+ //*****************************************
+ if (refreshNeeded)
+ syncSignal.refreshLists.emit();
+
+ if (!error) {
+ logger.log(logger.LOW, "Sync completed. Errors=" +error);
+ if (!disableUploads)
+ status.message.emit(tr("Synchronizing complete"));
+ else
+ status.message.emit(tr("Download syncronization complete. Uploads have been disabled."));
+
+ logger.log(logger.EXTREME, "Saving sync time");
+ if (syncState.getCurrentTime() > sequenceDate)
+ sequenceDate = syncState.getCurrentTime();
+ if (syncState.getUpdateCount() > updateSequenceNumber)
+ updateSequenceNumber = syncState.getUpdateCount();
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ }
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.evernoteSync");
+ }
+
+ // Sync deleted items with Evernote
+ private void syncExpunged(Client noteStore) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncExpunged");
+
+ List<DeletedItemRecord> expunged = conn.getDeletedTable().getAllDeleted();
+ boolean error = false;
+ for (int i=0; i<expunged.size() && keepRunning; i++) {
+
+// if (authRefreshNeeded)
+// if (!refreshConnection())
+// return;
+
+ try {
+ if (expunged.get(i).type.equalsIgnoreCase("TAG")) {
+ logger.log(logger.EXTREME, "Tag expunged");
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "TAG"); \r
++ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "TAG");
+ updateSequenceNumber = noteStore.expungeTag(authToken, expunged.get(i).guid);
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); \r
++ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ }
+ if (expunged.get(i).type.equalsIgnoreCase("NOTEBOOK")) {
+ logger.log(logger.EXTREME, "Notebook expunged");
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTEBOOK");\r
++ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTEBOOK");
+ updateSequenceNumber = noteStore.expungeNotebook(authToken, expunged.get(i).guid);
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ }
+ if (expunged.get(i).type.equalsIgnoreCase("NOTE")) {
+ logger.log(logger.EXTREME, "Note expunged");
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTE");\r
++ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTE");
+ updateSequenceNumber = noteStore.deleteNote(authToken, expunged.get(i).guid);
+ refreshNeeded = true;
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ }
+ if (expunged.get(i).type.equalsIgnoreCase("SAVEDSEARCH")) {
+ logger.log(logger.EXTREME, "saved search expunged");
- conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "SAVEDSEARCH");\r
++ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "SAVEDSEARCH");
+ updateSequenceNumber = noteStore.expungeSearch(authToken, expunged.get(i).guid);
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ }
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "EDAM User Excepton in syncExpunged: " +expunged.get(i).guid); // This can happen if we try to delete a deleted note
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "EDAM System Excepton in syncExpunged: "+expunged.get(i).guid);
+ logger.log(logger.LOW, e.getStackTrace());
+ error=true;
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "EDAM Not Found Excepton in syncExpunged: "+expunged.get(i).guid);
+ } catch (TException e) {
+ logger.log(logger.LOW, "EDAM TExcepton in syncExpunged: "+expunged.get(i).guid);
+ logger.log(logger.LOW, e.getStackTrace());
+ error=true;
+ }
+ }
+ if (!error)
+ conn.getDeletedTable().expungeAllDeletedRecords();
+
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncExpunged");
+
+ }
+ private void syncDeletedNotes(Client noteStore) {
+ if (syncDeletedContent)
+ return;
+ logger.log(logger.HIGH, "Entering SyncRunner.syncDeletedNotes");
+ status.message.emit(tr("Synchronizing deleted notes."));
+
+ List<Note> notes = conn.getNoteTable().getDirty();
+ // Sync the local notebooks with Evernote's
+ for (int i=0; i<notes.size() && keepRunning; i++) {
+
+// if (authRefreshNeeded)
+// if (!refreshConnection())
+// return;
+
+ Note enNote = notes.get(i);
+ try {
+ if (enNote.getUpdateSequenceNum() > 0 && (enNote.isActive() == false || enNote.getDeleted() > 0)) {
- // Check that the note is valid. \r
- if (enNote.isActive() == true || enNote.getDeleted() == 0) {\r
- conn.getNoteTable().deleteNote(enNote.getGuid());\r
- enNote = conn.getNoteTable().getNote(enNote.getGuid(), false, false, false, false, false);\r
- }\r
++ // Check that the note is valid.
++ if (enNote.isActive() == true || enNote.getDeleted() == 0) {
++ conn.getNoteTable().deleteNote(enNote.getGuid());
++ enNote = conn.getNoteTable().getNote(enNote.getGuid(), false, false, false, false, false);
++ }
+ if (syncDeletedContent) {
+ logger.log(logger.EXTREME, "Deleted note found & synch content selected");
+ Note delNote = conn.getNoteTable().getNote(enNote.getGuid(), true, true, true, true, true);
+ delNote = getNoteContent(delNote);
+ delNote = noteStore.updateNote(authToken, delNote);
+ enNote.setUpdateSequenceNum(delNote.getUpdateSequenceNum());
+ conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());
+ } else {
+ logger.log(logger.EXTREME, "Deleted note found & sync content not selected");
+ int usn = noteStore.deleteNote(authToken, enNote.getGuid());
+ enNote.setUpdateSequenceNum(usn);
+ conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());
+ }
+ logger.log(logger.EXTREME, "Resetting deleted dirty flag");
+ conn.getNoteTable().resetDirtyFlag(enNote.getGuid());
+ updateSequenceNumber = enNote.getUpdateSequenceNum();
+ logger.log(logger.EXTREME, "Saving sequence number");
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ }
+ } catch (EDAMUserException e) {
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
++ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);
+ //status.message.emit("Error sending local note: " +e.getParameter());
+ //logger.log(logger.LOW, e.toString());
+ //error = true;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);
+ status.message.emit(tr("Error: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (EDAMNotFoundException e) {
- logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
++ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);
+ //status.message.emit("Error deleting local note: " +e +" - Continuing");
+ //logger.log(logger.LOW, e.toString());
+ //error = true;
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);
+ status.message.emit(tr("Error sending local note: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ }
+ }
+ }
+ // Sync notes with Evernote
+ private void syncLocalNotes() {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");
+ logger.log(logger.LOW, "Dirty local notes found: " +new Integer(conn.getNoteTable().getDirtyCount()).toString());
+ status.message.emit(tr("Sending local notes."));
+
+ List<Note> notes = conn.getNoteTable().getDirty();
+ // Sync the local notebooks with Evernote's
+ for (int i=0; i<notes.size() && keepRunning; i++) {
+ syncLocalNote(localNoteStore, notes.get(i), authToken);
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncNotes");
+
+ }
+ // Sync notes with Evernote
+ private void syncLocalNote(Client noteStore, Note enNote, String token) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");
+ status.message.emit(tr("Sending local notes."));
+
+ if (enNote.isActive()) {
+ try {
+ if (enNote.getUpdateSequenceNum() > 0) {
+ logger.log(logger.EXTREME, "Active dirty note found - non new - " +enNote.getGuid());
+ logger.log(logger.EXTREME, "Fetching note content");
+ enNote = getNoteContent(enNote);
+ logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");
+ enNote = noteStore.updateNote(token, enNote);
+ } else {
+ logger.log(logger.EXTREME, "Active dirty found - new note " +enNote.getGuid());
+ String oldGuid = enNote.getGuid();
+ logger.log(logger.MEDIUM, "Fetching note content");
+ enNote = getNoteContent(enNote);
+ logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");
+ enNote = noteStore.createNote(token, enNote);
+ logger.log(logger.MEDIUM, "New note Guid : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");
+ noteSignal.guidChanged.emit(oldGuid, enNote.getGuid());
+ conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid());
+ }
+ updateSequenceNumber = enNote.getUpdateSequenceNum();
+ logger.log(logger.EXTREME, "Saving note");
+ conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());
+ List<Resource> rl = enNote.getResources();
+ logger.log(logger.EXTREME, "Getting note resources");
+ for (int j=0; j<enNote.getResourcesSize() && keepRunning; j++) {
+ Resource newRes = rl.get(j);
+ Data d = newRes.getData();
+ if (d!=null) {
+ logger.log(logger.EXTREME, "Calculating resource hash");
+ String hash = byteArrayToHexString(d.getBodyHash());
+ logger.log(logger.EXTREME, "updating resources by hash");
+ String oldGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(enNote.getGuid(), hash);
+ conn.getNoteTable().updateNoteResourceGuidbyHash(enNote.getGuid(), newRes.getGuid(), hash);
+ resourceSignal.resourceGuidChanged.emit(enNote.getGuid(), oldGuid, newRes.getGuid());
+ }
+ }
+ logger.log(logger.EXTREME, "Resetting note dirty flag");
+ conn.getNoteTable().resetDirtyFlag(enNote.getGuid());
+ updateSequenceNumber = enNote.getUpdateSequenceNum();
+ logger.log(logger.EXTREME, "Emitting note sequence number change");
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);
+ status.message.emit(tr("Error sending local note: ") +e.getParameter());
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);
+ status.message.emit(tr("Error: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);
+ status.message.emit(tr("Error sending local note: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);
+ status.message.emit(tr("Error sending local note: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNote");
+
+ }
+
+ // Sync Notebooks with Evernote
+ private void syncLocalNotebooks(Client noteStore) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks");
+
+ status.message.emit(tr("Sending local notebooks."));
+ List<Notebook> remoteList = new ArrayList<Notebook>();
+ try {
+ logger.log(logger.EXTREME, "Getting remote notebooks to compare with local");
+ remoteList = noteStore.listNotebooks(authToken);
+ } catch (EDAMUserException e1) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks getting remote Notebook List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks getting remote Notebook List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ } catch (TException e1) {
+ logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalNotebooks getting remote Notebook List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ }
+ logger.log(logger.EXTREME, "Getting local dirty notebooks");
+ List<Notebook> notebooks = conn.getNotebookTable().getDirty();
+ int sequence;
+ // Sync the local notebooks with Evernote's
+ for (int i=0; i<notebooks.size() && keepRunning; i++) {
+
+// if (authRefreshNeeded)
+// if (!refreshConnection())
+// return;
+
+ Notebook enNotebook = notebooks.get(i);
+ try {
+ if (enNotebook.getUpdateSequenceNum() > 0) {
+ logger.log(logger.EXTREME, "Existing notebook is dirty");
+ sequence = noteStore.updateNotebook(authToken, enNotebook);
+ } else {
+ logger.log(logger.EXTREME, "New dirty notebook found");
+ String oldGuid = enNotebook.getGuid();
+ boolean found = false;
+
+ // Look for a notebook with the same name. If one is found, we don't need
+ // to create another one
+ logger.log(logger.EXTREME, "Looking for matching notebook name");
+ for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {
+ if (remoteList.get(k).getName().equalsIgnoreCase(enNotebook.getName())) {
+ enNotebook = remoteList.get(k);
+ logger.log(logger.EXTREME, "Matching notebook found");
+ found = true;
+ }
+ }
+ if (!found)
+ enNotebook = noteStore.createNotebook(authToken, enNotebook);
+
+ logger.log(logger.EXTREME, "Updating notebook in database");
+ conn.getNotebookTable().updateNotebookGuid(oldGuid, enNotebook.getGuid());
+ sequence = enNotebook.getUpdateSequenceNum();
+ }
+ logger.log(logger.EXTREME, "Updating notebook sequence in database");
+ conn.getNotebookTable().updateNotebookSequence(enNotebook.getGuid(), sequence);
+ logger.log(logger.EXTREME, "Resetting dirty flag in notebook");
+ conn.getNotebookTable().resetDirtyFlag(enNotebook.getGuid());
+ updateSequenceNumber = sequence;
+ logger.log(logger.EXTREME, "Emitting sequence number to main thread");
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks");
+ logger.log(logger.LOW, e.toString() + ": Stack : " +enNotebook.getStack());
+ error = true;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotebooks");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotebooks");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNotebooks");
+
+ }
+ // Sync Tags with Evernote
+ private void syncLocalTags(Client noteStore) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncLocalTags");
+ List<Tag> remoteList = new ArrayList<Tag>();
+ status.message.emit(tr("Sending local tags."));
+
+ try {
+ logger.log(logger.EXTREME, "Getting remote tags to compare names with the local tags");
+ remoteList = noteStore.listTags(authToken);
+ } catch (EDAMUserException e1) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote Tag List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote Tag List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ } catch (TException e1) {
+ logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote Tag List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ }
+
+ int sequence;
+
+ if (badTagSync == null)
+ badTagSync = new HashMap<String,String>();
+ else
+ badTagSync.clear();
+
+ Tag enTag = findNextTag();
+
+ // This is a hack. Sometimes this function goes flookey and goes into a
+ // perpetual loop. This causes NeverNote to flood Evernote's servers.
+ // This is a safety valve to prevent unlimited loops.
+ int maxCount = conn.getTagTable().getDirty().size()+10;
+ int loopCount = 0;
+
+ while(enTag!=null && loopCount < maxCount) {
+ loopCount++;
+// if (authRefreshNeeded)
+// if (!refreshConnection())
+// return;
+
+ try {
+ if (enTag.getUpdateSequenceNum() > 0) {
+ logger.log(logger.EXTREME, "Updating tag");
+ sequence = noteStore.updateTag(authToken, enTag);
+ } else {
+
+ // Look for a tag with the same name. If one is found, we don't need
+ // to create another one
+ logger.log(logger.EXTREME, "New tag. Comparing with remote names");
+ boolean found = false;
+ String oldGuid = enTag.getGuid();
+ for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {
+ if (remoteList.get(k).getName().equalsIgnoreCase(enTag.getName())) {
+ conn.getTagTable().updateTagGuid(enTag.getGuid(), remoteList.get(k).getGuid());
+ enTag = remoteList.get(k);
+ logger.log(logger.EXTREME, "Matching tag name found");
+ found = true;
+ }
+ }
+ if (!found)
+ enTag = noteStore.createTag(authToken, enTag);
+ else
+ enTag.setUpdateSequenceNum(noteStore.updateTag(authToken,enTag));
+ sequence = enTag.getUpdateSequenceNum();
+ if (!oldGuid.equals(enTag.getGuid())) {
+ logger.log(logger.EXTREME, "Updating tag guid");
+ conn.getTagTable().updateTagGuid(oldGuid, enTag.getGuid());
+ }
+ }
+ logger.log(logger.EXTREME, "Updating tag sequence number");
+ conn.getTagTable().updateTagSequence(enTag.getGuid(), sequence);
+ logger.log(logger.EXTREME, "Resetting tag dirty flag");
+ conn.getTagTable().resetDirtyFlag(enTag.getGuid());
+ logger.log(logger.EXTREME, "Emitting sequence number to the main thread.");
+ updateSequenceNumber = sequence;
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags: " +enTag.getName());
+ logger.log(logger.LOW, e.toString());
+ badTagSync.put(enTag.getGuid(),null);
+ error = true;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags: " +enTag.getName());
+ logger.log(logger.LOW, e.toString());
+ badTagSync.put(enTag.getGuid(),null);
+ error = true;
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags: " +enTag.getName());
+ logger.log(logger.LOW, e.toString());
+ badTagSync.put(enTag.getGuid(),null);
+ error = true;
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags: " +enTag.getName());
+ logger.log(logger.LOW, e.toString());
+ badTagSync.put(enTag.getGuid(),null);
+ error = true;
+ }
+
+ // Find the next tag
+ logger.log(logger.EXTREME, "Finding next tag");
+ enTag = findNextTag();
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalTags");
+ }
+ private void syncLocalLinkedNotebooks(Client noteStore) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncLocalLinkedNotebooks");
+
+ List<String> list = conn.getLinkedNotebookTable().getDirtyGuids();
+ for (int i=0; i<list.size(); i++) {
+ LinkedNotebook book = conn.getLinkedNotebookTable().getNotebook(list.get(i));
+ try {
+ noteStore.updateLinkedNotebook(authToken, book);
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalLinkedNotebooks");
+ status.message.emit(tr("Error: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalLinkedNotebooks");
+ status.message.emit(tr("Error: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalLinkedNotebooks");
+ status.message.emit(tr("Error: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalLinkedNotebooks");
+ status.message.emit(tr("Error: ") +e);
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ }
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalLinkedNotebooks");
+ }
+ // Sync Saved Searches with Evernote
+ private void syncLocalSavedSearches(Client noteStore) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");
+ List<SavedSearch> remoteList = new ArrayList<SavedSearch>();
+ status.message.emit(tr("Sending saved searches."));
+
+ logger.log(logger.EXTREME, "Getting saved searches to compare with local");
+ try {
+ remoteList = noteStore.listSearches(authToken);
+ } catch (EDAMUserException e1) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote saved search List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote saved search List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ } catch (TException e1) {
+ logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote saved search List");
+ status.message.emit(tr("Error: ") +e1);
+ logger.log(logger.LOW, e1.toString());
+ error = true;
+ }
+
+ List<SavedSearch> searches = conn.getSavedSearchTable().getDirty();
+ int sequence;
+ // Sync the local notebooks with Evernote's
+ logger.log(logger.EXTREME, "Beginning to send saved searches");
+ for (int i=0; i<searches.size() && keepRunning; i++) {
+
+// if (authRefreshNeeded)
+// if (!refreshConnection())
+// return;
+
+ SavedSearch enSearch = searches.get(i);
+ try {
+ if (enSearch.getUpdateSequenceNum() > 0)
+ sequence = noteStore.updateSearch(authToken, enSearch);
+ else {
+ logger.log(logger.EXTREME, "New saved search found.");
+ // Look for a tag with the same name. If one is found, we don't need
+ // to create another one
+ boolean found = false;
+ logger.log(logger.EXTREME, "Matching remote saved search names with local");
+ for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {
+ if (remoteList.get(k).getName().equalsIgnoreCase(enSearch.getName())) {
+ enSearch = remoteList.get(k);
+ found = true;
+ logger.log(logger.EXTREME, "Matching saved search found");
+ sequence = enSearch.getUpdateSequenceNum();
+ }
+ }
+
+ String oldGuid = enSearch.getGuid();
+ if (!found)
+ enSearch = noteStore.createSearch(authToken, enSearch);
+ sequence = enSearch.getUpdateSequenceNum();
+ logger.log(logger.EXTREME, "Updating tag guid in local database");
+ conn.getSavedSearchTable().updateSavedSearchGuid(oldGuid, enSearch.getGuid());
+ }
+ logger.log(logger.EXTREME, "Updating tag sequence in local database");
+ conn.getSavedSearchTable().updateSavedSearchSequence(enSearch.getGuid(), sequence);
+ logger.log(logger.EXTREME, "Resetting tag dirty flag");
+ conn.getSavedSearchTable().resetDirtyFlag(enSearch.getGuid());
+ logger.log(logger.EXTREME, "Emitting sequence number to the main thread.");
+ updateSequenceNumber = sequence;
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ }
+ }
+
+ logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");
+ }
+
+ // Sync evernote changes with local database
+ private void syncRemoteToLocal(Client noteStore) {
+ logger.log(logger.HIGH, "Entering SyncRunner.syncRemoteToLocal");
+
+ List<Note> dirtyNotes = conn.getNoteTable().getDirty();
- dirtyNoteGuids = new ArrayList<String>();\r
++ dirtyNoteGuids = new ArrayList<String>();
+ for (int i=0; i<dirtyNotes.size() && keepRunning; i++) {
+ dirtyNoteGuids.add(dirtyNotes.get(i).getGuid());
+ }
+
+ int chunkSize = 10;
+ SyncChunk chunk = null;
+ boolean fullSync = false;
+ boolean more = true;
+
+ if (updateSequenceNumber == 0)
+ fullSync = true;
+
+ status.message.emit(tr("Downloading 0% complete."));
+
+ while(more && keepRunning) {
+
+// if (authRefreshNeeded)
+// if (!refreshConnection())
+// return;
+
+ int sequence = updateSequenceNumber;
+ try {
+// conn.beginTransaction();
+ logger.log(logger.EXTREME, "Getting chunk from Evernote");
+ chunk = noteStore.getSyncChunk(authToken, sequence, chunkSize, fullSync);
+ logger.log(logger.LOW, "Chunk High Sequence: " +chunk.getChunkHighUSN());
+ } catch (EDAMUserException e) {
+ error = true;
+ e.printStackTrace();
+ status.message.emit(e.getMessage());
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ error = true;
+ e.printStackTrace();
+ status.message.emit(e.getMessage());
+ } catch (TException e) {
+ error = true;
+ e.printStackTrace();
+ status.message.emit(e.getMessage());
+ }
+ if (error || chunk == null)
+ return;
+
+
+
+ syncRemoteTags(chunk.getTags());
+ syncRemoteSavedSearches(chunk.getSearches());
+ syncRemoteNotebooks(chunk.getNotebooks());
+ syncRemoteNotes(noteStore, chunk.getNotes(), fullSync, authToken);
+ syncRemoteResources(noteStore, chunk.getResources());
+ syncRemoteLinkedNotebooks(chunk.getLinkedNotebooks());
+
+ // Signal about any updated notes to invalidate the cache
+ for (int i=0; i<chunk.getNotesSize(); i++)
+ noteSignal.noteChanged.emit(chunk.getNotes().get(i).getGuid(), null);
+ syncExpungedNotes(chunk);
+
+
+ // Check for more notes
+ if (chunk.getChunkHighUSN() <= updateSequenceNumber)
+ more = false;
+ if (error)
+ more = false;
+ logger.log(logger.EXTREME, "More notes? " +more);
+
+
+ // Save the chunk sequence number
+ if (!error && chunk.getChunkHighUSN() > 0 && keepRunning) {
+ logger.log(logger.EXTREME, "emitting sequence number to main thread");
+ updateSequenceNumber = chunk.getChunkHighUSN();
+ conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);
+// conn.commitTransaction();
+ }
+
+
+ if (more) {
+ long pct = chunk.getChunkHighUSN() * 100;
+ conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());
+ pct = pct/evernoteUpdateCount;
+ status.message.emit(tr("Downloading ") +new Long(pct).toString()+tr("% complete."));
+ }
+// conn.commitTransaction();
+ }
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal");
+ }
+ // Sync expunged notes
+ private void syncExpungedNotes(SyncChunk chunk) {
+ // Do the local deletes
+ logger.log(logger.EXTREME, "Doing local deletes");
+ List<String> guid = chunk.getExpungedNotes();
+ if (guid != null) {
+ for (int i=0; i<guid.size() && keepRunning; i++) {
+ String notebookGuid = "";
+ Note localNote = conn.getNoteTable().getNote(guid.get(i), false, false, false, false, false);
+ if (localNote != null) {
+ conn.getNoteTable().updateNoteSequence(guid.get(i), 0);
+ notebookGuid = localNote.getNotebookGuid();
+ }
- // If the note is in a local notebook (which means we moved it) or if the \r
- // note returned is null (which means it is already deleted or flagged expunged) \r
- // we delete it.\r
- if (!conn.getNotebookTable().isNotebookLocal(notebookGuid) || localNote == null) {\r
++ // If the note is in a local notebook (which means we moved it) or if the
++ // note returned is null (which means it is already deleted or flagged expunged)
++ // we delete it.
++ if (!conn.getNotebookTable().isNotebookLocal(notebookGuid) || localNote == null) {
+ logger.log(logger.EXTREME, "Expunging local note from database");
+ conn.getNoteTable().expungeNote(guid.get(i), true, false);
+ }
+ }
+ }
+ guid = chunk.getExpungedNotebooks();
+ if (guid != null)
+ for (int i=0; i<guid.size() && keepRunning; i++) {
+ logger.log(logger.EXTREME, "Expunging local notebook from database");
+ conn.getNotebookTable().expungeNotebook(guid.get(i), false);
+ }
+ guid = chunk.getExpungedTags();
+ if (guid != null)
+ for (int i=0; i<guid.size() && keepRunning; i++) {
+ logger.log(logger.EXTREME, "Expunging tags from local database");
+ conn.getTagTable().expungeTag(guid.get(i), false);
+ }
+ guid = chunk.getExpungedSearches();
+ if (guid != null)
+ for (int i=0; i<guid.size() && keepRunning; i++) {
+ logger.log(logger.EXTREME, "Expunging saved search from local database");
+ conn.getSavedSearchTable().expungeSavedSearch(guid.get(i), false);
+ }
+ guid = chunk.getExpungedLinkedNotebooks();
+ if (guid != null)
+ for (int i=0; i<guid.size() && keepRunning; i++) {
+ logger.log(logger.EXTREME, "Expunging linked notebook from local database");
+ conn.getLinkedNotebookTable().expungeNotebook(guid.get(i), false);
+ }
+
+ }
+ // Sync remote tags
+ private void syncRemoteTags(List<Tag> tags) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");
+ if (tags != null) {
+ for (int i=0; i<tags.size() && keepRunning; i++) {
+ String oldGuid;
+ oldGuid = conn.getTagTable().findTagByName(tags.get(i).getName());
+ if (oldGuid != null && !tags.get(i).getGuid().equalsIgnoreCase(oldGuid))
+ conn.getTagTable().updateTagGuid(oldGuid, tags.get(i).getGuid());
+ conn.getTagTable().syncTag(tags.get(i), false);
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");
+ }
+ // Sync remote saved searches
+ private void syncRemoteSavedSearches(List<SavedSearch> searches) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches");
+ if (searches != null) {
+ for (int i=0; i<searches.size() && keepRunning; i++) {
+ String oldGuid;
+ oldGuid = conn.getSavedSearchTable().findSavedSearchByName(searches.get(i).getName());
+ if (oldGuid != null && !searches.get(i).getGuid().equalsIgnoreCase(oldGuid))
+ conn.getSavedSearchTable().updateSavedSearchGuid(oldGuid, searches.get(i).getGuid());
+ conn.getSavedSearchTable().syncSavedSearch(searches.get(i), false);
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncSavedSearches");
+ }
+ // Sync remote linked notebooks
+ private void syncRemoteLinkedNotebooks(List<LinkedNotebook> books) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncLinkedNotebooks");
+ if (books != null) {
+ for (int i=0; i<books.size() && keepRunning; i++) {
+ conn.getLinkedNotebookTable().updateNotebook(books.get(i), false);
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncLinkedNotebooks");
+ }
+ // Sync remote Notebooks 2
+ private void syncRemoteNotebooks(List<Notebook> notebooks) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");
+ if (notebooks != null) {
+ for (int i=0; i<notebooks.size() && keepRunning; i++) {
+ String oldGuid;
+ oldGuid = conn.getNotebookTable().findNotebookByName(notebooks.get(i).getName());
+ if (oldGuid != null && !conn.getNotebookTable().isNotebookLocal(oldGuid) && !notebooks.get(i).getGuid().equalsIgnoreCase(oldGuid))
+ conn.getNotebookTable().updateNotebookGuid(oldGuid, notebooks.get(i).getGuid());
+ conn.getNotebookTable().syncNotebook(notebooks.get(i), false);
+
+ // Synchronize shared notebook information
+// if (notebooks.get(i).getSharedNotebookIdsSize() > 0) {
+// conn.getSharedNotebookTable().expungeNotebookByGuid(notebooks.get(i).getGuid(), false);
+// for (int j=0; j<notebooks.get(i).getSharedNotebookIdsSize(); j++) {
+// syncRemoteSharedNotebook(notebooks.get(i).getGuid(), notebooks.get(i).getSharedNotebookIds().get(j), authToken);
+// }
+// }
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");
+ }
+ // Sync remote shared notebook
+// private void syncRemoteSharedNotebook(String guid, Long id, String token) {
+// List<SharedNotebook> books = noteStore.getSharedNotebookByAuth(authToken);
+// }
+ // Sync remote Resources
+ private void syncRemoteResources(Client noteStore, List<Resource> resource) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources");
+ if (resource != null) {
+ for (int i=0; i<resource.size() && keepRunning; i++) {
+ syncRemoteResource(noteStore, resource.get(i), authToken);
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");
+ }
+ // Sync remote resource
+ private void syncRemoteResource(Client noteStore, Resource resource, String authToken) {
+ // This is how the logic for this works.
+ // 1.) If the resource is not in the local database, we add it.
+ // 2.) If a copy of the resource is in the local database and the note isn't dirty, we update the local copy
+ // 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
+ // is a conflict. The note conflict should get a copy of the resource at that time.
+
+ Note n = conn.getNoteTable().getNote(resource.getNoteGuid(), false, false, false, false, false);
+ if (n!=null) {
+ logger.log(logger.HIGH, "Resource for note " +n.getGuid() +" : " +n.getTitle());
+ }
+ boolean saveNeeded = false;
+ /* #1 */ Resource r = getEvernoteResource(noteStore, resource.getGuid(), true,true,true, authToken);
+ Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);
+ if (l == null) {
+ logger.log(logger.HIGH, "Local resource not found");
+ saveNeeded = true;
+ } else {
+ /* #2 */ boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());
+ if (!isNoteDirty) {
+ logger.log(logger.HIGH, "Local resource found, but is not dirty");
+ saveNeeded = true;
+ } else {
+ /* #3 */ String remoteHash = "";
+ if (r != null && r.getData() != null && r.getData().getBodyHash() != null)
+ remoteHash = byteArrayToHexString(r.getData().getBodyHash());
+ String localHash = "";
+ if (l != null && l.getData() != null && l.getData().getBodyHash() != null)
+ remoteHash = byteArrayToHexString(l.getData().getBodyHash());
+
+ if (localHash.equalsIgnoreCase(remoteHash))
+ saveNeeded = true;
+ }
+ }
+
+ logger.log(logger.HIGH, "Resource save needed: " +saveNeeded);
+ if (saveNeeded)
+ conn.getNoteTable().noteResourceTable.updateNoteResource(r, false);
+ if (r.getMime().equalsIgnoreCase("application/vnd.evernote.ink"))
+ downloadInkNoteImage(r.getGuid(), authToken);
+
+
+ }
+ // Sync remote notes
+ private void syncRemoteNotes(Client noteStore, List<Note> note, boolean fullSync, String token) {
- \r
++
+ if (note != null) {
- \r
- logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes");\r
- logger.log(logger.LOW, "Local Dirty Notes: ");\r
- logger.log(logger.LOW, "Remote Dirty Notes:");\r
- for (int i=0; i<note.size();i++) {\r
- logger.log(logger.LOW, i +" : " +note.get(i).getGuid() + " : " +note.get(i).getTitle() );\r
- }\r
- logger.log(logger.LOW, "---");\r
- \r
++
++ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes");
++ logger.log(logger.LOW, "Local Dirty Notes: ");
++ logger.log(logger.LOW, "Remote Dirty Notes:");
++ for (int i=0; i<note.size();i++) {
++ logger.log(logger.LOW, i +" : " +note.get(i).getGuid() + " : " +note.get(i).getTitle() );
++ }
++ logger.log(logger.LOW, "---");
++
+ for (int i=0; i<note.size() && keepRunning; i++) {
+ Note n = getEvernoteNote(noteStore, note.get(i).getGuid(), true, fullSync, true,true, token);
+ syncRemoteNote(n, fullSync, token);
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotes");
+ }
+ private void syncRemoteNote(Note n, boolean fullSync, String token) {
+ if (n!=null) {
+
+ // Basically, this is how the sync logic for a note works.
+ // If the remote note has changed and the local has not, we
+ // accept the change.
+ // If both the local & remote have changed but the sequence
+ // numbers are the same, we don't accept the change. This
+ // seems to happen when attachments are indexed by the server.
+ // If both the local & remote have changed and the sequence numbers
+ // are different we move the local copy to a local notebook (making sure
+ // to copy all resources) and we accept the new one.
+ boolean conflictingNote = true;
- logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid() +" : " +n.getTitle());\r
++ logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid() +" : " +n.getTitle());
+ if (dirtyNoteGuids != null && dirtyNoteGuids.contains(n.getGuid())) {
+ logger.log(logger.EXTREME, "Conflict check beginning");
+ conflictingNote = checkForConflict(n);
+ logger.log(logger.EXTREME, "Conflict check results " +conflictingNote);
+ if (conflictingNote)
+ moveConflictingNote(n.getGuid());
+ }
+ boolean ignoreNote = false;
+ if (ignoreNotebooks.contains(n.getNotebookGuid()))
+ ignoreNote = true;
+ for (int i=0; i<n.getTagGuidsSize(); i++) {
+ if (ignoreTags.contains(n.getTagGuids().get(i))) {
+ ignoreNote = true;
+ i=n.getTagGuidsSize();
+ }
+ }
+
+ if ((conflictingNote || fullSync) && !ignoreNote) {
+ logger.log(logger.EXTREME, "Saving Note");
+ conn.getNoteTable().syncNote(n);
+ // The following was commented out because it caused a race condition on the database where resources
+ // may be lost. We do the same thing elsewhere;.
+// noteSignal.noteChanged.emit(n.getGuid(), null); // Signal to ivalidate note cache
+ noteSignal.noteDownloaded.emit(n, true); // Signal to add note to index
+ logger.log(logger.EXTREME, "Note Saved");
+ if (fullSync && n.getResources() != null) {
+ for (int q=0; q<n.getResources().size() && keepRunning; q++) {
+ logger.log(logger.EXTREME, "Getting note resources.");
+ conn.getNoteTable().noteResourceTable.updateNoteResource(n.getResources().get(q), false);
+ if (n.getResources().get(q).getMime().equalsIgnoreCase("application/vnd.evernote.ink"))
+ downloadInkNoteImage(n.getResources().get(q).getGuid(), token);
+ }
+ }
+ }
+ }
+ }
+ private Note getEvernoteNote(Client noteStore, String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData, String token) {
+ Note n = null;
+ try {
+ logger.log(logger.EXTREME, "Retrieving note " +guid);
+ n = noteStore.getNote(token, guid, withContent, withResourceData, withResourceRecognition, withResourceAlternateData);
+ logger.log(logger.EXTREME, "Note " +guid +" has been retrieved.");
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ }
+ return n;
+ }
+ private Resource getEvernoteResource(Client noteStore, String guid, boolean withData, boolean withRecognition, boolean withAttributes, String token) {
+ Resource n = null;
+ try {
+ logger.log(logger.EXTREME, "Retrieving resource " +guid);
+ n = noteStore.getResource(token, guid, withData, withRecognition, withAttributes, withAttributes);
+ logger.log(logger.EXTREME, "Resource " +guid +" has been retrieved.");
+ } catch (EDAMUserException e) {
+ logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ logger.log(logger.LOW, "*** EDAM System Excepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMNotFoundException e) {
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ } catch (TException e) {
+ logger.log(logger.LOW, "*** EDAM TExcepton getEvernoteNote");
+ logger.log(logger.LOW, e.toString());
+ error = true;
+ e.printStackTrace();
+ }
+ return n;
+ }
+
+
+ private boolean checkForConflict(Note n) {
+ logger.log(logger.EXTREME, "Checking note sequence number " +n.getGuid());
+ Note oldNote = conn.getNoteTable().getNote(n.getGuid(), false, false, false, false, false);
+ logger.log(logger.EXTREME, "Local/Remote sequence numbers: " +oldNote.getUpdateSequenceNum()+"/"+n.getUpdateSequenceNum());
- logger.log(logger.LOW, "Remote Note Title:" +n.getTitle());\r
- logger.log(logger.LOW, "Local Note Title:" +oldNote.getTitle());\r
- if (oldNote.getUpdateSequenceNum() == n.getUpdateSequenceNum()) {\r
- return false;\r
- } \r
- boolean oldIsDirty = conn.getNoteTable().isNoteDirty(n.getGuid());\r
- if (!oldIsDirty) \r
++ logger.log(logger.LOW, "Remote Note Title:" +n.getTitle());
++ logger.log(logger.LOW, "Local Note Title:" +oldNote.getTitle());
++ if (oldNote.getUpdateSequenceNum() == n.getUpdateSequenceNum()) {
++ return false;
++ }
++ boolean oldIsDirty = conn.getNoteTable().isNoteDirty(n.getGuid());
++ if (!oldIsDirty)
+ return false;
+ return true;
+ }
+
+ private void moveConflictingNote(String guid) {
+ logger.log(logger.EXTREME, "Conflicting change found for note " +guid);
+ List<Notebook> books = conn.getNotebookTable().getAllLocal();
+ String notebookGuid = null;
+ for (int i=0; i<books.size() && keepRunning; i++) {
+ if (books.get(i).getName().equalsIgnoreCase("Conflicting Changes (local)") ||
+ books.get(i).getName().equalsIgnoreCase("Conflicting Changes")) {
+ notebookGuid = books.get(i).getGuid();
+ i=books.size();
+ }
+ }
+
+ if (notebookGuid == null) {
+ logger.log(logger.EXTREME, "Building conflicting change notebook " +guid);
+ Calendar currentTime = new GregorianCalendar();
+ Long l = new Long(currentTime.getTimeInMillis());
+ long prevTime = l;
+ while (prevTime==l) {
+ currentTime = new GregorianCalendar();
+ l=currentTime.getTimeInMillis();
+ }
+ String randint = new String(Long.toString(l));
+
+ Notebook newBook = new Notebook();
+ newBook.setUpdateSequenceNum(0);
+ newBook.setGuid(randint);
+ newBook.setName("Conflicting Changes");
+ newBook.setServiceCreated(new Date().getTime());
+ newBook.setServiceUpdated(new Date().getTime());
+ newBook.setDefaultNotebook(false);
+ newBook.setPublished(false);
+
+ conn.getNotebookTable().addNotebook(newBook, false, true);
+ notebookSignal.listChanged.emit();
+ notebookGuid = newBook.getGuid();
+ refreshNeeded = true;
+ }
+
+ // Now that we have a good notebook guid, we need to move the conflicting note
+ // to the local notebook
+ logger.log(logger.EXTREME, "Moving conflicting note " +guid);
+ Calendar currentTime = new GregorianCalendar();
+ Long l = new Long(currentTime.getTimeInMillis());
+ long prevTime = l;
+ while (prevTime==l) {
+ currentTime = new GregorianCalendar();
+ l = currentTime.getTimeInMillis();
+ }
+ String newGuid = new String(Long.toString(l));
+
+ Note oldNote = conn.getNoteTable().getNote(guid, true, true, false, false, false);
+ for (int i=0; i<oldNote.getResources().size() && keepRunning; i++) {
+ l = new Long(currentTime.getTimeInMillis());
+ String newResG = new String(Long.toString(l));
+ String oldResG = oldNote.getResources().get(i).getGuid();
+ conn.getNoteTable().noteResourceTable.resetUpdateSequenceNumber(oldResG, true);
+ conn.getNoteTable().noteResourceTable.updateNoteResourceGuid(oldResG, newResG, true);
+ }
+
+ conn.getNoteTable().resetNoteSequence(guid);
+ conn.getNoteTable().updateNoteGuid(guid, newGuid);
+ conn.getNoteTable().updateNoteNotebook(newGuid, notebookGuid, true);
+
+ noteSignal.notebookChanged.emit(newGuid, notebookGuid);
+ refreshNeeded = true;
+ noteSignal.guidChanged.emit(guid,newGuid);
+ }
+
+
+
+
+ //******************************************************
+ //******************************************************
+ //** Utility Functions
+ //******************************************************
+ //******************************************************
+ // Convert a byte array to a hex string
+ private static String byteArrayToHexString(byte data[]) {
+ StringBuffer buf = new StringBuffer();
+ for (byte element : data) {
+ int halfbyte = (element >>> 4) & 0x0F;
+ int two_halfs = 0;
+ do {
+ if ((0 <= halfbyte) && (halfbyte <= 9))
+ buf.append((char) ('0' + halfbyte));
+ else
+ buf.append((char) ('a' + (halfbyte - 10)));
+ halfbyte = element & 0x0F;
+ } while(two_halfs++ < 1);
+ }
+ return buf.toString();
+ }
+
+
+
+ //*******************************************************
+ //* Find dirty tags, which do not have newly created parents
+ //*******************************************************
+ private Tag findNextTag() {
+ logger.log(logger.HIGH, "Entering SyncRunner.findNextTag");
+ Tag nextTag = null;
+ List<Tag> tags = conn.getTagTable().getDirty();
+
+ // Find the parent. If the parent has a sequence > 0 then it is a good
+ // parent.
+ for (int i=0; i<tags.size() && keepRunning; i++) {
+ if (!badTagSync.containsKey(tags.get(i).getGuid())) {
+ if (tags.get(i).getParentGuid() == null) {
+ logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found without parent");
+ return tags.get(i);
+ }
+ Tag parentTag = conn.getTagTable().getTag(tags.get(i).getParentGuid());
+ if (parentTag.getUpdateSequenceNum() > 0) {
+ logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found");
+ return tags.get(i);
+ }
+ }
+ }
+
+ logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - no tags returned");
+ return nextTag;
+ }
+
+
+ // Connect to Evernote
+ public boolean enConnect() {
+ try {
+ userStoreTrans = new THttpClient(userStoreUrl);
+ userStoreTrans.setCustomHeader("User-Agent", userAgent);
+ } catch (TTransportException e) {
+ QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());
+ mb.exec();
+ e.printStackTrace();
+ }
+ userStoreProt = new TBinaryProtocol(userStoreTrans);
+ userStore = new UserStore.Client(userStoreProt, userStoreProt);
+
+ syncSignal.saveUserStore.emit(userStore);
+ try {
+ //authResult = userStore.authenticate(username, password, consumerKey, consumerSecret);
+ user = userStore.getUser(authToken);
+ } catch (EDAMUserException e) {
+ QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Error", "Invalid Authorization");
+ mb.exec();
+ isConnected = false;
+ return false;
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "EDAM System Excepton", e.getLocalizedMessage());
+ mb.exec();
+ e.printStackTrace();
+ isConnected = false;
+ } catch (TException e) {
+ QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());
+ mb.exec();
+ e.printStackTrace();
+ isConnected = false;
+ }
+
+ boolean versionOk = false;
+ try {
+ versionOk = userStore.checkVersion("NeighborNote",
+ com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR,
+ com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR);
+ } catch (TException e) {
+ e.printStackTrace();
+ isConnected = false;
+ }
+ if (!versionOk) {
+ System.err.println("Incomatible EDAM client protocol version");
+ isConnected = false;
+ }
+ //if (authResult != null) {
+ //user = authResult.getUser();
+ //authToken = authResult.getAuthenticationToken();
- if (user == null || noteStoreUrlBase == null) {\r
- logger.log(logger.LOW, "Error retrieving user information. Aborting.");\r
- System.err.println("Error retrieving user information.");\r
- isConnected = false; \r
- QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, tr("Connection Error"), tr("Error retrieving user information. Synchronization not complete"));\r
- mb.exec();\r
- return false;\r
- \r
- }\r
++ if (user == null || noteStoreUrlBase == null) {
++ logger.log(logger.LOW, "Error retrieving user information. Aborting.");
++ System.err.println("Error retrieving user information.");
++ isConnected = false;
++ QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, tr("Connection Error"), tr("Error retrieving user information. Synchronization not complete"));
++ mb.exec();
++ return false;
++
++ }
+ noteStoreUrl = noteStoreUrlBase + user.getShardId();
+ syncSignal.saveAuthToken.emit(authToken);
+ syncSignal.saveNoteStore.emit(localNoteStore);
+
+
+ try {
+ noteStoreTrans = new THttpClient(noteStoreUrl);
+ noteStoreTrans.setCustomHeader("User-Agent", userAgent);
+ } catch (TTransportException e) {
+ QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());
+ mb.exec();
+ e.printStackTrace();
+ isConnected = false;
+ }
+ noteStoreProt = new TBinaryProtocol(noteStoreTrans);
+ localNoteStore =
+ new NoteStore.Client(noteStoreProt, noteStoreProt);
+ isConnected = true;
+ //authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();
+ //authRefreshTime = authTimeRemaining / 2;
+ //}
+
+ // Get user information
+ try {
+ User user = userStore.getUser(authToken);
+ syncSignal.saveUserInformation.emit(user);
+ } catch (EDAMUserException e1) {
+ e1.printStackTrace();
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ e1.printStackTrace();
+ } catch (TException e1) {
+ e1.printStackTrace();
+ }
+
+ return isConnected;
+ }
+ // Disconnect from the database
+ public void enDisconnect() {
+ isConnected = false;
+ }
+
+ /*
+ // Refresh the connection
+ private synchronized boolean refreshConnection() {
+
+ logger.log(logger.EXTREME, "Entering SyncRunner.refreshConnection()");
+// Calendar cal = Calendar.getInstance();
+
+ // If we are not connected let's get out of here
+ if (!isConnected)
+ return false;
+
+ // If we fail too many times, then let's give up.
+ if (failedRefreshes >=5) {
+ logger.log(logger.EXTREME, "Refresh attempts have failed. Disconnecting.");
+ isConnected = false;
+ status.message.emit(tr("Unable to synchronize - Authentication failed"));
+ return false;
+ }
+
+ // If this is the first time through, then we need to set this
+// if (authRefreshTime == 0 || cal.getTimeInMillis() > authRefreshTime)
+// authRefreshTime = cal.getTimeInMillis();
+
+ // // Default to checking again in 5 min. This in case we fail.
+ // authRefreshTime = authRefreshTime +(5*60*1000);
+
+ // Try to get a new token
+ AuthenticationResult newAuth = null;
+ logger.log(logger.EXTREME, "Beginning to try authentication refresh");
+ try {
+ if (userStore != null && authToken != null)
+ newAuth = userStore.refreshAuthentication(authToken);
+ else
+ return false;
+ logger.log(logger.EXTREME, "UserStore.refreshAuthentication has succeeded.");
+ } catch (EDAMUserException e) {
+ e.printStackTrace();
+ syncSignal.authRefreshComplete.emit(false);
+ failedRefreshes++;
+ return false;
+ } catch (EDAMSystemException e) {
+ e.printStackTrace();
+ syncSignal.authRefreshComplete.emit(false);
+ failedRefreshes++;
+ return false;
+ } catch (TException e) {
+ e.printStackTrace();
+ syncSignal.authRefreshComplete.emit(false);
+ failedRefreshes++;
+ return false;
+ }
+
+ // If we didn't get a good auth, then we've failed
+ if (newAuth == null) {
+ failedRefreshes++;
+ status.message.emit(tr("Unable to synchronize - Authentication failed"));
+ logger.log(logger.EXTREME, "Authentication failure #" +failedRefreshes);
+ status.message.emit(tr("Unable to synchronize - Authentication failed"));
+ syncSignal.authRefreshComplete.emit(false);
+ return false;
+ }
+
+ // We got a good token. Now we need to setup the time to renew it.
+ logger.log(logger.EXTREME, "Saving authentication tokens");
+ authResult = newAuth;
+ authToken = new String(newAuth.getAuthenticationToken());
+// authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();
+// authRefreshTime = cal.getTimeInMillis() + (authTimeRemaining/4);
+ failedRefreshes=0;
+ syncSignal.authRefreshComplete.emit(true);
+ authRefreshNeeded = false;
+
+ // This should never happen, but if it does we consider this a faild attempt.
+// if (authTimeRemaining <= 0) {
+// failedRefreshes++;
+// syncSignal.authRefreshComplete.emit(false);
+// }
+
+ return true;
+ }
+
+ */
+
+ public synchronized boolean addWork(String request) {
+ if (workQueue.offer(request))
+ return true;
+ return false;
+ }
+
+ private Note getNoteContent(Note n) {
+ QTextCodec codec = QTextCodec.codecForLocale();
+ codec = QTextCodec.codecForName("UTF-8");
+ n.setContent(codec.toUnicode(new QByteArray(n.getContent())));
+ return n;
+ }
+
+
+
+ //*********************************************************
+ //* Special download instructions. Used for DB upgrades
+ //*********************************************************
+ private void downloadAllSharedNotebooks(Client noteStore) {
+ try {
+ List<SharedNotebook> books = noteStore.listSharedNotebooks(authToken);
+ logger.log(logger.LOW, "Shared notebooks found = " +books.size());
+ for (int i=0; i<books.size(); i++) {
+ conn.getSharedNotebookTable().updateNotebook(books.get(i), false);
+ }
+ conn.getSyncTable().deleteRecord("FullSharedNotebookSync");
+ } catch (EDAMUserException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("User exception Listing shared notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ e1.printStackTrace();
+ status.message.emit(tr("System exception Listing shared notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (TException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("Transaction exception Listing shared notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (EDAMNotFoundException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("EDAM Not Found exception Listing shared notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ }
+ }
+ private void downloadAllNotebooks(Client noteStore) {
+ try {
+ List<Notebook> books = noteStore.listNotebooks(authToken);
+ logger.log(logger.LOW, "Shared notebooks found = " +books.size());
+ for (int i=0; i<books.size(); i++) {
+ conn.getNotebookTable().updateNotebook(books.get(i), false);
+ }
+ conn.getSyncTable().deleteRecord("FullNotebookSync");
+ } catch (EDAMUserException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("User exception Listing notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ e1.printStackTrace();
+ status.message.emit(tr("System exception Listing notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (TException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("Transaction exception Listing notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ }
+ }
+ private void downloadAllLinkedNotebooks(Client noteStore) {
+ try {
+ List<LinkedNotebook> books = noteStore.listLinkedNotebooks(authToken);
+ logger.log(logger.LOW, "Linked notebooks found = " +books.size());
+ for (int i=0; i<books.size(); i++) {
+ conn.getLinkedNotebookTable().updateNotebook(books.get(i), false);
+ }
+ conn.getSyncTable().deleteRecord("FullLinkedNotebookSync");
+ } catch (EDAMUserException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("User exception Listing linked notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (EDAMSystemException e1) {
+ if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e1.getRateLimitDuration());
+ }
+ e1.printStackTrace();
+ status.message.emit(tr("System exception Listing linked notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (TException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("Transaction exception Listing lineked notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ return;
+ } catch (EDAMNotFoundException e1) {
+ e1.printStackTrace();
+ status.message.emit(tr("EDAM Not Found exception Listing linked notebooks."));
+ logger.log(logger.LOW, e1.getMessage());
+ }
+ }
+
+
+ private void downloadInkNoteImage(String guid, String authToken) {
+ String urlBase = noteStoreUrl.replace("/edam/note/", "/shard/") + "/res/"+guid+".ink?slice=";
+// urlBase = "https://www.evernote.com/shard/s1/res/52b567a9-54ae-4a08-afc5-d5bae275b2a8.ink?slice=";
+ Integer slice = 1;
+ Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, false);
+ conn.getInkImagesTable().expungeImage(r.getGuid());
+ int sliceCount = 1+((r.getHeight()-1)/480);
+ HttpClient http = new DefaultHttpClient();
+ for (int i=0; i<sliceCount; i++) {
+ String url = urlBase + slice.toString();
+ HttpPost post = new HttpPost(url);
+ post.getParams().setParameter("auth", authToken);
+ List <NameValuePair> nvps = new ArrayList <NameValuePair>();
+ nvps.add(new BasicNameValuePair("auth", authToken));
+
+ try {
+ post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
+ } catch (UnsupportedEncodingException e1) {
+ e1.printStackTrace();
+ }
+ try {
+ HttpResponse response = http.execute(post);
+ HttpEntity resEntity = response.getEntity();
+ InputStream is = resEntity.getContent();
+ QByteArray data = writeToFile(is);
+ conn.getInkImagesTable().saveImage(guid, slice, data);
+ } catch (ClientProtocolException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ slice++;
+ }
+ http.getConnectionManager().shutdown();
+ noteSignal.noteChanged.emit(r.getNoteGuid(), null); // Signal to ivalidate note cache
+ }
+
+
+ public QByteArray writeToFile(InputStream iStream) throws IOException {
+
+ File temp = File.createTempFile("nn-inknote-temp", ".png");
+
+ // Save InputStream to the file.
+ BufferedOutputStream fOut = null;
+ try {
+ fOut = new BufferedOutputStream(new FileOutputStream(temp));
+ byte[] buffer = new byte[32 * 1024];
+ int bytesRead = 0;
+ while ((bytesRead = iStream.read(buffer)) != -1) {
+ fOut.write(buffer, 0, bytesRead);
+ }
+ }
+ finally {
+ iStream.close();
+ fOut.close();
+ }
+ QFile tempFile = new QFile(temp.getAbsoluteFile().toString());
+ tempFile.open(OpenModeFlag.ReadOnly);
+ QByteArray data = tempFile.readAll();
+ tempFile.close();
+ tempFile.remove();
+ return data;
+ }
+
+
+ //******************************************
+ //* Begin syncing shared notebooks
+ //******************************************
+ private void syncLinkedNotebooks() {
+ logger.log(logger.MEDIUM, "Authenticating linked Notebooks");
+ status.message.emit(tr("Synchronizing shared notebooks."));
+ List<LinkedNotebook> books = conn.getLinkedNotebookTable().getAll();
+
+ errorSharedNotebooks.clear();
+
+ for (int i=0; i<books.size(); i++) {
+ if (errorSharedNotebooksIgnored.containsKey(books.get(i).getGuid()))
+ break;
+ try {
+ logger.log(logger.EXTREME, "Checking notebook: " +books.get(i).getShareName());
+ long lastSyncDate = conn.getLinkedNotebookTable().getLastSequenceDate(books.get(i).getGuid());
+ int lastSequenceNumber = conn.getLinkedNotebookTable().getLastSequenceNumber(books.get(i).getGuid());
+
+ logger.log(logger.EXTREME, "Last Sequence Number on file: " +lastSequenceNumber);
+
+ // Authenticate to the owner's shard
+ String linkedNoteStoreUrl = noteStoreUrlBase + books.get(i).getShardId();
+ logger.log(logger.EXTREME, "linkedNoteStoreURL: " +linkedNoteStoreUrl);
+ THttpClient linkedNoteStoreTrans = new THttpClient(linkedNoteStoreUrl);
+ TBinaryProtocol linkedNoteStoreProt = new TBinaryProtocol(linkedNoteStoreTrans);
+ Client linkedNoteStore = new NoteStore.Client(linkedNoteStoreProt, linkedNoteStoreProt);
+
+ linkedAuthResult = null;
+ if (books.get(i).getShareKey() != null) {
+ logger.log(logger.EXTREME, "Share Key Not Null: " +books.get(i).getShareKey());
+ linkedAuthResult = linkedNoteStore.authenticateToSharedNotebook(books.get(i).getShareKey(), authToken);
+ logger.log(logger.EXTREME, "Authentication Token" +linkedAuthResult.getAuthenticationToken());
+ } else {
+ logger.log(logger.EXTREME, "Share key is null");
+ linkedAuthResult = new AuthenticationResult();
+ linkedAuthResult.setAuthenticationToken("");
+ }
+ SyncState linkedSyncState =
+ linkedNoteStore.getLinkedNotebookSyncState(linkedAuthResult.getAuthenticationToken(), books.get(i));
+ if (linkedSyncState.getUpdateCount() > lastSequenceNumber) {
+ logger.log(logger.EXTREME, "Remote changes found");
+ if (lastSyncDate < linkedSyncState.getFullSyncBefore()) {
+ lastSequenceNumber = 0;
+ }
+ logger.log(logger.EXTREME, "Calling syncLinkedNotebook for " +books.get(i).getShareName());
+ syncLinkedNotebook(linkedNoteStore, books.get(i),
+ lastSequenceNumber, linkedSyncState.getUpdateCount(), authToken);
+ }
+
+ // Synchronize local changes
+ syncLocalLinkedNoteChanges(linkedNoteStore, books.get(i));
+
+ } catch (EDAMUserException e) {
+ e.printStackTrace();
+ } catch (EDAMNotFoundException e) {
+ status.message.emit(tr("Error synchronizing \" " +
+ books.get(i).getShareName()+"\". Please verify you still have access to that shared notebook."));
+ errorSharedNotebooks.add(books.get(i).getGuid());
+ errorSharedNotebooksIgnored.put(books.get(i).getGuid(), books.get(i).getGuid());
+ logger.log(logger.LOW, "Error synchronizing shared notebook. EDAMNotFound: "+e.getMessage());
+ logger.log(logger.LOW, e.getStackTrace());
+ error = true;
+ e.printStackTrace();
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ error = true;
+ logger.log(logger.LOW, "System error authenticating against shared notebook. "+
+ "Key: "+books.get(i).getShareKey() +" Error:" +e.getMessage());
+ e.printStackTrace();
+ } catch (TException e) {
+ error = true;
+ e.printStackTrace();
+ }
+ }
+
+ // Cleanup tags
+ conn.getTagTable().removeUnusedLinkedTags();
+ conn.getTagTable().cleanupTags();
+ tagSignal.listChanged.emit();
+ return;
+ }
+
+
+ //**************************************************************
+ //* Linked notebook contents (from someone else's account)
+ //*************************************************************
+ private void syncLinkedNotebook(Client linkedNoteStore, LinkedNotebook book, int usn, int highSequence, String token) {
+ logger.log(logger.EXTREME, "Entering syncLinkedNotebook");
+ if (ignoreLinkedNotebooks.contains(book.getGuid()))
+ return;
+ List<Note> dirtyNotes = conn.getNoteTable().getDirtyLinkedNotes();
+ if (dirtyNoteGuids == null)
- dirtyNoteGuids = new ArrayList<String>();\r
++ dirtyNoteGuids = new ArrayList<String>();
+
+ for (int i=0; i<dirtyNotes.size() && keepRunning; i++) {
+ dirtyNoteGuids.add(dirtyNotes.get(i).getGuid());
+ }
+ boolean fullSync = false;
+ if (usn == 0)
+ fullSync = true;
+ boolean syncError = false;
+ while (usn < highSequence && !syncError) {
+ refreshNeeded = true;
+ try {
+ SyncChunk chunk =
+ linkedNoteStore.getLinkedNotebookSyncChunk(token, book, usn, 10, fullSync);
+
+ // Expunge notes
+ syncExpungedNotes(chunk);
+
+ logger.log(logger.EXTREME, "Syncing remote notes: " +chunk.getNotesSize());
+ syncRemoteNotes(linkedNoteStore, chunk.getNotes(), fullSync, linkedAuthResult.getAuthenticationToken());
+ logger.log(logger.EXTREME, "Finding new linked tags");
+ findNewLinkedTags(linkedNoteStore, chunk.getNotes(), linkedAuthResult.getAuthenticationToken());
+ // Sync resources
+ logger.log(logger.EXTREME, "Synchronizing tags: " +chunk.getTagsSize());
+ for (int i=0; i<chunk.getResourcesSize(); i++) {
+ syncRemoteResource(linkedNoteStore, chunk.getResources().get(i), linkedAuthResult.getAuthenticationToken());
+ }
+ logger.log(logger.EXTREME, "Synchronizing linked notebooks: " +chunk.getNotebooksSize());
+ syncRemoteLinkedNotebooks(linkedNoteStore, chunk.getNotebooks(), false, book);
+ syncLinkedTags(chunk.getTags(), book.getGuid());
+
+ // Go through & signal any notes that have changed so we can refresh the user's view
+ for (int i=0; i<chunk.getNotesSize(); i++)
+ noteSignal.noteChanged.emit(chunk.getNotes().get(i).getGuid(), null);
+
+ // Expunge Notebook records
+ logger.log(logger.EXTREME, "Expunging linked notebooks: " +chunk.getExpungedLinkedNotebooksSize());
+ for (int i=0; i<chunk.getExpungedLinkedNotebooksSize(); i++) {
+ conn.getLinkedNotebookTable().expungeNotebook(chunk.getExpungedLinkedNotebooks().get(i), false);
+ }
+ usn = chunk.getChunkHighUSN();
+ conn.getLinkedNotebookTable().setLastSequenceDate(book.getGuid(),chunk.getCurrentTime());
+ conn.getLinkedNotebookTable().setLastSequenceNumber(book.getGuid(),chunk.getChunkHighUSN());
+ } catch (EDAMUserException e) {
+ syncError = true;
+ status.message.emit(tr("EDAM UserException synchronizing linked notbook. See the log for datails."));
+ e.printStackTrace();
+ logger.log(logger.LOW, tr("EDAM UserException synchronizing linked notbook ")+ e.getMessage());
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ syncError = true;
+ status.message.emit(tr("EDAM SystemException synchronizing linked notbook. See the log for datails."));
+ e.printStackTrace();
+ logger.log(logger.LOW, tr("EDAM SystemException synchronizing linked notbook. See the log for datails") +e.getMessage());
+ } catch (EDAMNotFoundException e) {
+ syncError = true;
+ status.message.emit(tr("Notebook URL not found. Removing notobook ") +book.getShareName());
+ conn.getNotebookTable().deleteLinkedTags(book.getGuid());
+ conn.getLinkedNotebookTable().expungeNotebook(book.getGuid(), false);
+ logger.log(logger.LOW, tr("Notebook URL not found. Removing notobook ") +e.getMessage());
+ } catch (TException e) {
+ syncError = true;
+ status.message.emit(tr("EDAM TException synchronizing linked notbook. See the log for datails."));
+ e.printStackTrace();
+ logger.log(logger.LOW, tr("EDAM TException synchronizing linked notbook. See the log for datails." )+e.getMessage());
+ }
+ }
+ logger.log(logger.EXTREME, "leaving syncLinkedNotebook");
+ }
+ // Sync remote tags
+ private void syncLinkedTags(List<Tag> tags, String notebookGuid) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");
+ if (tags != null) {
+ for (int i=0; i<tags.size() && keepRunning; i++) {
+ conn.getTagTable().syncLinkedTag(tags.get(i), notebookGuid, false);
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");
+ }
+
+ // Sync notebooks from a linked notebook
+ private void syncRemoteLinkedNotebooks(Client noteStore, List<Notebook> notebooks, boolean readOnly, LinkedNotebook linked) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");
+ if (notebooks != null) {
+ for (int i=0; i<notebooks.size() && keepRunning; i++) {
+ try {
+ logger.log(logger.EXTREME, "auth token:" +linkedAuthResult.getAuthenticationToken());
+ if (!linkedAuthResult.getAuthenticationToken().equals("")) {
+ SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());
+ logger.log(logger.EXTREME, "share key:"+s.getShareKey() +" notebookGuid" +s.getNotebookGuid());
+ conn.getLinkedNotebookTable().setNotebookGuid(s.getShareKey(), s.getNotebookGuid());
+ readOnly = !s.isNotebookModifiable();
+ } else {
+ readOnly = true;
+ }
+ notebooks.get(i).setName(linked.getShareName());
+ notebooks.get(i).setDefaultNotebook(false);
+ conn.getNotebookTable().syncLinkedNotebook(notebooks.get(i), false, readOnly);
+ } catch (EDAMUserException e) {
+ readOnly = true;
+ e.printStackTrace();
+ } catch (EDAMNotFoundException e) {
+ readOnly = true;
+ e.printStackTrace();
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ readOnly = true;
+ e.printStackTrace();
+ } catch (TException e) {
+ readOnly = true;
+ e.printStackTrace();
+ }
+
+ }
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");
+ }
+
+ private void findNewLinkedTags(Client noteStore, List<Note> newNotes, String token) {
+ if (newNotes == null)
+ return;
+ for (int i=0; i<newNotes.size(); i++) {
+ Note n = newNotes.get(i);
+ for (int j=0; j<n.getTagGuidsSize(); j++) {
+ String tag = n.getTagGuids().get(j);
+ if (!conn.getTagTable().exists(tag)) {
+ Tag newTag;
+ try {
+ newTag = noteStore.getTag(token, tag);
+ conn.getTagTable().addTag(newTag, false);
+ } catch (EDAMUserException e) {
+ e.printStackTrace();
+ } catch (EDAMSystemException e) {
+ if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
+ limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
+ }
+ e.printStackTrace();
+ } catch (EDAMNotFoundException e) {
+ e.printStackTrace();
+ } catch (TException e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
+ }
+ }
+
+ // Synchronize changes locally done to linked notes
+ private void syncLocalLinkedNoteChanges(Client noteStore, LinkedNotebook book) {
+ logger.log(logger.EXTREME, "Entering SyncRunner.synclocalLinkedNoteChanges");
+ String notebookGuid = conn.getLinkedNotebookTable().getNotebookGuid(book.getGuid());
+ logger.log(logger.EXTREME, "Finding changes for " +book.getShareName() +":" +book.getGuid() + ":" +notebookGuid);
+ List<Note> notes = conn.getNoteTable().getDirtyLinked(notebookGuid);
+ logger.log(logger.EXTREME, "Number of changes found: " +notes.size());
+ for (int i=0; i<notes.size(); i++) {
+ logger.log(logger.EXTREME, "Calling syncLocalNote with key " +linkedAuthResult.getAuthenticationToken());
+ syncLocalNote(noteStore, notes.get(i), linkedAuthResult.getAuthenticationToken());
+ }
+ logger.log(logger.EXTREME, "Leaving SyncRunner.synclocalLinkedNoteChanges");
+ }
+
+}