-/*\r
- * This file is part of NeverNote \r
- * Copyright 2009 Randy Baumgarte\r
- * \r
- * This file may be licensed under the terms of of the\r
- * GNU General Public License Version 2 (the ``GPL'').\r
- *\r
- * Software distributed under the License is distributed\r
- * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
- * express or implied. See the GPL for the specific language\r
- * governing rights and limitations.\r
- *\r
- * You should have received a copy of the GPL along with this\r
- * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
- * or write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
- *\r
-*/\r
-\r
-package cx.fbn.nevernote.utilities;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Calendar;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.GregorianCalendar;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Vector;\r
-\r
-import com.evernote.edam.type.Note;\r
-import com.evernote.edam.type.Notebook;\r
-import com.evernote.edam.type.SavedSearch;\r
-import com.evernote.edam.type.Tag;\r
-import com.trolltech.qt.QThread;\r
-import com.trolltech.qt.core.QDateTime;\r
-import com.trolltech.qt.sql.QSqlQuery;\r
-import com.trolltech.qt.xml.QDomAttr;\r
-import com.trolltech.qt.xml.QDomDocument;\r
-import com.trolltech.qt.xml.QDomElement;\r
-import com.trolltech.qt.xml.QDomNodeList;\r
-\r
-import cx.fbn.nevernote.Global;\r
-import cx.fbn.nevernote.filters.EnSearch;\r
-import cx.fbn.nevernote.filters.NotebookCounter;\r
-import cx.fbn.nevernote.filters.TagCounter;\r
-import cx.fbn.nevernote.gui.NoteTableModel;\r
-import cx.fbn.nevernote.signals.NotebookSignal;\r
-import cx.fbn.nevernote.signals.StatusSignal;\r
-import cx.fbn.nevernote.signals.TagSignal;\r
-import cx.fbn.nevernote.signals.ThreadSignal;\r
-import cx.fbn.nevernote.signals.TrashSignal;\r
-import cx.fbn.nevernote.sql.DatabaseConnection;\r
-import cx.fbn.nevernote.threads.CounterRunner;\r
-import cx.fbn.nevernote.threads.SaveRunner;\r
-\r
-\r
-public class ListManager {\r
-\r
- \r
- private final ApplicationLogger logger; \r
- DatabaseConnection conn;\r
- QSqlQuery deleteWords;\r
- QSqlQuery insertWords;\r
- \r
- private List<Tag> tagIndex;\r
- private List<Notebook> notebookIndex;\r
- private List<Notebook> archiveNotebookIndex;\r
- private List<String> localNotebookIndex;\r
-\r
- private List<SavedSearch> searchIndex;\r
-\r
- private List<String> selectedNotebooks;\r
- private final NoteTableModel noteModel;\r
- \r
- \r
- private List<String> selectedTags;\r
- private String selectedSearch;\r
- ThreadSignal signals;\r
- public StatusSignal status;\r
- private final CounterRunner notebookCounterRunner;\r
- private final QThread notebookThread;\r
- private final CounterRunner tagCounterRunner;\r
- private final QThread tagThread;\r
- \r
- private final CounterRunner trashCounterRunner;\r
- private final QThread trashThread;\r
- public TrashSignal trashSignal;\r
- \r
- private List<NotebookCounter> notebookCounter; // count of displayed notes in each notebook\r
- private List<TagCounter> tagCounter; // count of displayed notes for each tag\r
- \r
- private EnSearch enSearch;\r
- private boolean enSearchChanged;\r
- public HashMap<String, String> wordMap;\r
- public TagSignal tagSignal;\r
- public NotebookSignal notebookSignal;\r
- private int trashCount;\r
- SaveRunner saveRunner; // Thread used to save content. Used because the xml conversion is slowwwww\r
- QThread saveThread;\r
- \r
- // Constructor\r
- public ListManager(DatabaseConnection d, ApplicationLogger l) {\r
- conn = d;\r
- logger = l;\r
- \r
- status = new StatusSignal();\r
- signals = new ThreadSignal();\r
- \r
- // setup index locks\r
- enSearchChanged = false;\r
- \r
- // Setup arrays\r
- noteModel = new NoteTableModel(this);\r
- selectedTags = new ArrayList<String>();\r
-\r
- notebookCounter = new ArrayList<NotebookCounter>();\r
- tagCounter = new ArrayList<TagCounter>();\r
- selectedNotebooks = new ArrayList<String>();\r
- \r
- reloadIndexes();\r
- \r
- notebookSignal = new NotebookSignal();\r
- notebookCounterRunner = new CounterRunner("notebook_counter.log", CounterRunner.NOTEBOOK, Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);\r
- notebookCounterRunner.setNoteIndex(getNoteIndex());\r
- notebookCounterRunner.notebookSignal.countsChanged.connect(this, "setNotebookCounter(List)");\r
- notebookThread = new QThread(notebookCounterRunner, "Notebook Counter Thread");\r
- notebookThread.start();\r
- \r
- tagSignal = new TagSignal();\r
- tagCounterRunner = new CounterRunner("tag_counter.log", CounterRunner.TAG, Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);\r
- tagCounterRunner.setNoteIndex(getNoteIndex());\r
- tagCounterRunner.tagSignal.countsChanged.connect(this, "setTagCounter(List)");\r
- tagThread = new QThread(tagCounterRunner, "Tag Counter Thread");\r
- tagThread.start();\r
- \r
- trashSignal = new TrashSignal();\r
- trashCounterRunner = new CounterRunner("trash_counter.log", CounterRunner.TRASH, Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);\r
- trashCounterRunner.trashSignal.countChanged.connect(this, "trashSignalReceiver(Integer)");\r
- trashThread = new QThread(trashCounterRunner, "Trash Counter Thread");\r
- trashThread.start();\r
- reloadTrashCount();\r
- \r
- wordMap = new HashMap<String, String>();\r
- tagSignal = new TagSignal();\r
- \r
- logger.log(logger.EXTREME, "Setting save thread");\r
- saveRunner = new SaveRunner("saveRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);\r
- saveThread = new QThread(saveRunner, "Save Runner Thread");\r
- saveThread.start();\r
-\r
- loadNoteTitleColors();\r
- \r
- }\r
- \r
- public void stop() {\r
- saveRunner.addWork("stop", "");\r
- tagCounterRunner.release(CounterRunner.EXIT);\r
- notebookCounterRunner.release(CounterRunner.EXIT);\r
- trashCounterRunner.release(CounterRunner.EXIT);\r
- \r
- logger.log(logger.MEDIUM, "Waiting for notebookCounterThread to stop"); \r
- try {\r
- notebookThread.join();\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
- \r
- logger.log(logger.MEDIUM, "Waiting for tagCounterThread to stop"); \r
- try {\r
- tagThread.join();\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
-\r
- logger.log(logger.MEDIUM, "Waiting for trashThread to stop"); \r
- try {\r
- trashThread.join();\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
-\r
-\r
- logger.log(logger.MEDIUM, "Waiting for saveThread to stop"); \r
- try {\r
- saveThread.join(0);\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
-\r
-\r
- }\r
-\r
- //***************************************************************\r
- //***************************************************************\r
- //* Refresh lists after a db sync\r
- //***************************************************************\r
- //***************************************************************\r
- public void refreshLists(Note n, boolean dirty, String content) {\r
- if (dirty) {\r
-// conn.getNoteTable().updateNoteContent(n.getGuid(), n.getContent());\r
- saveRunner.addWork(n.getGuid(), content);\r
- conn.getNoteTable().updateNoteTitle(n.getGuid(), n.getTitle());\r
- }\r
- \r
- setSavedSearchIndex(conn.getSavedSearchTable().getAll());\r
- setTagIndex(conn.getTagTable().getAll());\r
- setNotebookIndex(conn.getNotebookTable().getAll());\r
- \r
- List<Notebook> local = conn.getNotebookTable().getAllLocal();\r
- localNotebookIndex = new ArrayList<String>();\r
- for (int i=0; i<local.size(); i++)\r
- localNotebookIndex.add(local.get(i).getGuid());\r
- \r
- noteModel.setMasterNoteIndex(conn.getNoteTable().getAllNotes());\r
- // For performance reasons, we didn't get the tags for every note individually. We now need to \r
- // get them\r
- List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();\r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- List<String> tags = new ArrayList<String>();\r
- List<String> names = new ArrayList<String>();\r
- for (int j=0; j<noteTags.size(); j++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(noteTags.get(j).noteGuid)) {\r
- tags.add(noteTags.get(j).tagGuid);\r
- names.add(getTagNameByGuid(noteTags.get(j).tagGuid));\r
- }\r
- }\r
- \r
- getMasterNoteIndex().get(i).setTagGuids(tags);\r
- getMasterNoteIndex().get(i).setTagNames(names);\r
- }\r
- \r
- \r
- setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());\r
- \r
- enSearchChanged = true;\r
- }\r
-\r
- public void reloadIndexes() {\r
- setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());\r
-\r
- List<Notebook> local = conn.getNotebookTable().getAllLocal();\r
- localNotebookIndex = new ArrayList<String>();\r
- for (int i=0; i<local.size(); i++)\r
- localNotebookIndex.add(local.get(i).getGuid());\r
- \r
- // Load tags\r
- setTagIndex(conn.getTagTable().getAll());\r
- // Load notebooks\r
- setNotebookIndex(conn.getNotebookTable().getAll());\r
- // load archived notebooks (if note using the EN interface)\r
- setArchiveNotebookIndex(conn.getNotebookTable().getAllArchived());\r
- // load saved search index\r
- setSavedSearchIndex(conn.getSavedSearchTable().getAll());\r
- // Load search helper utility\r
- enSearch = new EnSearch(conn, logger, "", getTagIndex(), Global.getMinimumWordLength(), Global.getRecognitionWeight());\r
- logger.log(logger.HIGH, "Building note index");\r
-\r
-// if (getMasterNoteIndex() == null) { \r
- noteModel.setMasterNoteIndex(conn.getNoteTable().getAllNotes());\r
-// }\r
- // For performance reasons, we didn't get the tags for every note individually. We now need to \r
- // get them\r
- List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();\r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- List<String> tags = new ArrayList<String>();\r
- List<String> names = new ArrayList<String>();\r
- for (int j=0; j<noteTags.size(); j++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(noteTags.get(j).noteGuid)) {\r
- tags.add(noteTags.get(j).tagGuid);\r
- names.add(getTagNameByGuid(noteTags.get(j).tagGuid));\r
- }\r
- }\r
- \r
- getMasterNoteIndex().get(i).setTagGuids(tags);\r
- getMasterNoteIndex().get(i).setTagNames(names);\r
- }\r
- \r
- setNoteIndex(getMasterNoteIndex());\r
-\r
- }\r
- \r
- //***************************************************************\r
- //***************************************************************\r
- //* selected notebooks\r
- //***************************************************************\r
- //***************************************************************\r
- // Return the selected notebook(s)\r
- public List<String> getSelectedNotebooks() {\r
- return selectedNotebooks;\r
- }\r
- // Set the current selected notebook(s)\r
- public void setSelectedNotebooks(List <String> s) {\r
- if (s == null) \r
- s = new ArrayList<String>();\r
- selectedNotebooks = s;\r
- }\r
- \r
- \r
- //***************************************************************\r
- //***************************************************************\r
- //** These functions deal with setting & retrieving the master lists\r
- //***************************************************************\r
- //***************************************************************\r
- // Get the note table model\r
- public NoteTableModel getNoteTableModel() {\r
- return noteModel;\r
- }\r
- // save the saved search index\r
- private void setSavedSearchIndex(List<SavedSearch> t) {\r
- searchIndex = t;\r
- }\r
- // Retrieve the Tag index\r
- public List<SavedSearch> getSavedSearchIndex() {\r
- return searchIndex;\r
-\r
- }\r
- // save the tag index\r
- private void setTagIndex(List<Tag> t) {\r
- tagIndex = t;\r
- } \r
- // Retrieve the Tag index\r
- public List<Tag> getTagIndex() {\r
- return tagIndex;\r
- }\r
- private void setNotebookIndex(List<Notebook> t) {\r
- notebookIndex = t;\r
- }\r
- private void setArchiveNotebookIndex(List<Notebook> t) {\r
- archiveNotebookIndex = t;\r
- }\r
- // Retrieve the Notebook index\r
- public List<Notebook> getNotebookIndex() {\r
- return notebookIndex;\r
-\r
- }\r
- public List<Notebook> getArchiveNotebookIndex() {\r
- return archiveNotebookIndex;\r
- }\r
- // Save the current note list\r
- private void setNoteIndex(List<Note> n) {\r
- noteModel.setNoteIndex(n);\r
- }\r
- // Get the note index\r
- public synchronized List<Note> getNoteIndex() {\r
- return noteModel.getNoteIndex();\r
- }\r
- // Save the count of notes per notebook\r
- public void setNotebookCounter(List<NotebookCounter> n) {\r
- notebookCounter = n;\r
- notebookSignal.refreshNotebookTreeCounts.emit(getNotebookIndex(), notebookCounter);\r
- }\r
- public List<NotebookCounter> getNotebookCounter() {\r
- return notebookCounter;\r
- }\r
- // Save the count of notes for each tag\r
- public void setTagCounter(List<TagCounter> n) {\r
- tagCounter = n;\r
- tagSignal.refreshTagTreeCounts.emit(tagCounter);\r
- }\r
- public List<TagCounter> getTagCounter() {\r
- return tagCounter;\r
- }\r
- public List<String> getLocalNotebooks() {\r
- return localNotebookIndex;\r
- }\r
- // Unsynchronized Note List\r
- public List<String> getUnsynchronizedNotes() {\r
- return noteModel.getUnsynchronizedNotes();\r
- }\r
- public void setUnsynchronizedNotes(List<String> l) {\r
- noteModel.setUnsynchronizedNotes(l);\r
- }\r
- // Return a count of items in the trash\r
- public int getTrashCount() {\r
- return trashCount;\r
- }\r
- // get the EnSearch variable\r
- public EnSearch getEnSearch() {\r
- return enSearch;\r
- }\r
- public List<Note> getMasterNoteIndex() {\r
- return noteModel.getMasterNoteIndex();\r
- }\r
- \r
- //***************************************************************\r
- //***************************************************************\r
- //** These functions deal with setting & retrieving filters\r
- //***************************************************************\r
- //***************************************************************\r
- public void setEnSearch(String t) {\r
- enSearch = new EnSearch(conn,logger, t, getTagIndex(), Global.getMinimumWordLength(), Global.getRecognitionWeight());\r
- enSearchChanged = true;\r
- }\r
- // Save search tags\r
- public void setSelectedTags(List<String> selectedTags) {\r
- this.selectedTags = selectedTags;\r
- }\r
- // Save seleceted search\r
- public void setSelectedSavedSearch(String s) {\r
- this.selectedSearch = s;\r
- }\r
- // Get search tags\r
- public List<String> getSelectedTags() {\r
- return selectedTags;\r
- }\r
- // Get saved search\r
- public String getSelectedSearch() {\r
- return selectedSearch;\r
- }\r
- \r
- \r
- \r
- \r
- //***************************************************************\r
- //***************************************************************\r
- //** Note functions\r
- //***************************************************************\r
- //***************************************************************\r
- // Save Note Tags\r
- public void saveNoteTags(String noteGuid, List<String> tags) {\r
- logger.log(logger.HIGH, "Entering ListManager.saveNoteTags");\r
- String tagName;\r
- conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);\r
- List<String> tagGuids = new ArrayList<String>();\r
- boolean newTagCreated = false;\r
- \r
- for (int i=0; i<tags.size(); i++) {\r
- tagName = tags.get(i);\r
- boolean found = false;\r
- for (int j=0; j<tagIndex.size(); j++) {\r
- if (tagIndex.get(j).getName().equalsIgnoreCase(tagName)) {\r
- conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, tagIndex.get(j).getGuid());\r
- tagGuids.add(tagIndex.get(j).getGuid());\r
- j=tagIndex.size()+1;\r
- found = true;\r
- }\r
- }\r
- if (!found) {\r
- Tag nTag = new Tag();\r
- nTag.setName(tagName);\r
- Calendar currentTime = new GregorianCalendar();\r
- Long l = new Long(currentTime.getTimeInMillis());\r
- long prevTime = l;\r
- while (l==prevTime) {\r
- currentTime = new GregorianCalendar();\r
- l=currentTime.getTimeInMillis();\r
- }\r
- String randint = new String(Long.toString(l));\r
- \r
- nTag.setUpdateSequenceNum(0);\r
- nTag.setGuid(randint);\r
- conn.getTagTable().addTag(nTag, true);\r
- getTagIndex().add(nTag);\r
- conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, nTag.getGuid());\r
- tagGuids.add(nTag.getGuid());\r
- newTagCreated = true;\r
- }\r
- }\r
- \r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(noteGuid)) {\r
- getNoteIndex().get(i).setTagNames(tags);\r
- getNoteIndex().get(i).setTagGuids(tagGuids);\r
- i=getNoteIndex().size()+1;\r
- }\r
- }\r
- if (newTagCreated)\r
- tagSignal.listChanged.emit();\r
- logger.log(logger.HIGH, "Leaving ListManager.saveNoteTags");\r
- }\r
- // Delete a note\r
- public void deleteNote(String guid) {\r
- trashCounterRunner.abortCount = true;\r
- Calendar currentTime = new GregorianCalendar();\r
- Long l = new Long(currentTime.getTimeInMillis());\r
- long prevTime = l;\r
- while (l==prevTime) {\r
- currentTime = new GregorianCalendar();\r
- l=currentTime.getTimeInMillis();\r
- }\r
- \r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {\r
- getMasterNoteIndex().get(i).setActive(false);\r
- getMasterNoteIndex().get(i).setDeleted(l);\r
- i=getMasterNoteIndex().size();\r
- }\r
- }\r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(guid)) {\r
- getNoteIndex().get(i).setActive(false);\r
- getNoteIndex().get(i).setDeleted(l);\r
- i=getNoteIndex().size();\r
- }\r
- }\r
- conn.getNoteTable().deleteNote(guid);\r
- reloadTrashCount();\r
- }\r
- // Delete a note\r
- public void restoreNote(String guid) {\r
- trashCounterRunner.abortCount = true;\r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {\r
- getMasterNoteIndex().get(i).setActive(true);\r
- getMasterNoteIndex().get(i).setDeleted(0);\r
- i=getMasterNoteIndex().size();\r
- }\r
- }\r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(guid)) {\r
- getNoteIndex().get(i).setActive(true);\r
- getNoteIndex().get(i).setDeleted(0);\r
- i=getNoteIndex().size();\r
- }\r
- }\r
- conn.getNoteTable().restoreNote(guid);\r
- reloadTrashCount();\r
- }\r
- public void updateNote(Note n) {\r
- \r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(n.getGuid())) {\r
- getMasterNoteIndex().remove(i);\r
- getMasterNoteIndex().add(n);\r
- }\r
- }\r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {\r
- getNoteIndex().get(i).setActive(true);\r
- getNoteIndex().get(i).setDeleted(0);\r
- i=getNoteIndex().size();\r
- }\r
- }\r
- conn.getNoteTable().updateNote(n, true);\r
- }\r
- // Add a note. \r
- public void addNote(Note n) {\r
- noteModel.addNote(n);\r
- }\r
- // Expunge a note\r
- public void expungeNote(String guid) {\r
- trashCounterRunner.abortCount = true;\r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {\r
- getMasterNoteIndex().remove(i);\r
- i=getMasterNoteIndex().size();\r
- }\r
- }\r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(guid)) {\r
- getNoteIndex().remove(i);\r
- i=getNoteIndex().size();\r
- }\r
- }\r
- conn.getNoteTable().expungeNote(guid, false, true);\r
- reloadTrashCount();\r
- }\r
- // Expunge a note\r
- public void emptyTrash() {\r
- trashCounterRunner.abortCount = true; \r
- for (int i=getMasterNoteIndex().size()-1; i>=0; i--) {\r
- if (!getMasterNoteIndex().get(i).isActive()) {\r
- getMasterNoteIndex().remove(i);\r
- }\r
- }\r
- \r
- for (int i=getNoteIndex().size()-1; i>=0; i--) {\r
- if (!getNoteIndex().get(i).isActive()) {\r
- getNoteIndex().remove(i);\r
- } \r
- }\r
-\r
- conn.getNoteTable().expungeAllDeletedNotes();\r
- reloadTrashCount();\r
- }\r
- // The trash counter thread has produced a result\r
- @SuppressWarnings("unused")\r
- private void trashSignalReceiver(Integer i) {\r
- trashCount = i;\r
- trashSignal.countChanged.emit(i);\r
- }\r
- // Update note contents\r
- public void updateNoteContent(String guid, String content) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");\r
-// EnmlConverter enml = new EnmlConverter(logger);\r
-// String text = enml.convert(guid, content);\r
- \r
- // Update the list tables \r
-/* for (int i=0; i<masterNoteIndex.size(); i++) {\r
- if (masterNoteIndex.get(i).getGuid().equals(guid)) {\r
- masterNoteIndex.get(i).setContent(text);\r
- i = masterNoteIndex.size();\r
- }\r
- }\r
- // Update the list tables \r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(guid)) {\r
- getNoteIndex().get(i).setContent(text);\r
- i = getNoteIndex().size();\r
- }\r
- }\r
-*/ \r
- // Check if any new tags were encountered\r
-/* if (enml.saveInvalidXML) {\r
- List<String> elements = Global.invalidElements;\r
- for (int i=0; i<elements.size(); i++) {\r
- conn.getInvalidXMLTable().addInvalidElement(elements.get(i));\r
- }\r
- for (String key : Global.invalidAttributes.keySet()) {\r
- ArrayList<String> attributes = Global.invalidAttributes.get(key);\r
- for (int i=0; i<attributes.size(); i++) {\r
- conn.getInvalidXMLTable().addInvalidAttribute(key, attributes.get(i));\r
- }\r
- }\r
- }\r
-*/\r
- saveRunner.addWork(guid, content);\r
-// conn.getNoteTable().updateNoteContent(guid, content);\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");\r
- }\r
- // Update a note creation date\r
- public void updateNoteCreatedDate(String guid, QDateTime date) {\r
- noteModel.updateNoteCreatedDate(guid, date);\r
- conn.getNoteTable().updateNoteCreatedDate(guid, date);\r
- }\r
- // Subject date has been changed\r
- public void updateNoteSubjectDate(String guid, QDateTime date) {\r
- noteModel.updateNoteSubjectDate(guid, date);\r
- conn.getNoteTable().updateNoteSubjectDate(guid, date);\r
- }\r
- // Author has changed\r
- public void updateNoteAuthor(String guid, String author) {\r
- noteModel.updateNoteAuthor(guid, author);\r
- conn.getNoteTable().updateNoteAuthor(guid, author);\r
- }\r
- // Author has changed\r
- public void updateNoteGeoTag(String guid, Double lon, Double lat, Double alt) {\r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {\r
- getMasterNoteIndex().get(i).getAttributes().setLongitude(lon);\r
- getMasterNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);\r
- getMasterNoteIndex().get(i).getAttributes().setLatitude(lat);\r
- getMasterNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);\r
- getMasterNoteIndex().get(i).getAttributes().setAltitude(alt);\r
- getMasterNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);\r
- i = getMasterNoteIndex().size();\r
- } \r
- }\r
- // Update the list tables \r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(guid)) {\r
- getNoteIndex().get(i).getAttributes().setLongitude(lon);\r
- getNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);\r
- getNoteIndex().get(i).getAttributes().setLatitude(lat);\r
- getNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);\r
- getNoteIndex().get(i).getAttributes().setAltitude(alt);\r
- getNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);\r
- i = getNoteIndex().size();\r
- }\r
- }\r
- conn.getNoteTable().updateNoteGeoTags(guid, lon, lat, alt);\r
- }\r
- // Source URL changed\r
- public void updateNoteSourceUrl(String guid, String url) {\r
- noteModel.updateNoteSourceUrl(guid, url);\r
- conn.getNoteTable().updateNoteSourceUrl(guid, url);\r
- }\r
- // Update a note last changed date\r
- public void updateNoteAlteredDate(String guid, QDateTime date) {\r
- noteModel.updateNoteChangedDate(guid, date);\r
- conn.getNoteTable().updateNoteAlteredDate(guid, date);\r
- }\r
- // Update a note title\r
- public void updateNoteTitle(String guid, String title) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNoteTitle");\r
- conn.getNoteTable().updateNoteTitle(guid, title);\r
- noteModel.updateNoteTitle(guid, title);\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNoteTitle");\r
- }\r
- // Update a note's notebook\r
- public void updateNoteNotebook(String guid, String notebookGuid) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNoteNotebook");\r
- noteModel.updateNoteNotebook(guid, notebookGuid);\r
- conn.getNoteTable().updateNoteNotebook(guid, notebookGuid, true);\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNoteNotebook");\r
- }\r
- // Update a note sequence number\r
- public void updateNoteSequence(String guid, int sequence) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNoteSequence");\r
-\r
- conn.getNoteTable().updateNoteSequence(guid, sequence);\r
- \r
- for (int i=0; i<noteModel.getMasterNoteIndex().size(); i++) {\r
- if (noteModel.getMasterNoteIndex().get(i).getGuid().equals(guid)) {\r
- noteModel.getMasterNoteIndex().get(i).setUpdateSequenceNum(sequence);\r
- i=noteModel.getMasterNoteIndex().size()+1;\r
- }\r
- }\r
- \r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(guid)) {\r
- getNoteIndex().get(i).setUpdateSequenceNum(sequence);\r
- i=getNoteIndex().size()+1;\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNoteSequence");\r
- }\r
- public void updateNoteGuid(String oldGuid, String newGuid, boolean updateDatabase) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNoteGuid");\r
- if (updateDatabase) \r
- conn.getNoteTable().updateNoteGuid(oldGuid, newGuid);\r
- noteModel.updateNoteGuid(oldGuid, newGuid);\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNoteGuid");\r
-\r
- }\r
-\r
- \r
- //************************************************************************************\r
- //************************************************************************************\r
- //** Tag functions\r
- //************************************************************************************\r
- //************************************************************************************ \r
- // Update a tag sequence number\r
- public void updateTagSequence(String guid, int sequence) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateTagSequence");\r
-\r
- conn.getTagTable().updateTagSequence(guid, sequence); \r
- for (int i=0; i<tagIndex.size(); i++) {\r
- if (tagIndex.get(i).getGuid().equals(guid)) {\r
- getTagIndex().get(i).setUpdateSequenceNum(sequence);\r
- i=tagIndex.size()+1;\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving ListManager.updateTagSequence");\r
- }\r
- // Update a tag guid number\r
- public void updateTagGuid(String oldGuid, String newGuid) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateTagGuid");\r
-\r
- conn.getTagTable().updateTagGuid(oldGuid, newGuid); \r
- for (int i=0; i<tagIndex.size(); i++) {\r
- if (tagIndex.get(i).getGuid().equals(oldGuid)) {\r
- tagIndex.get(i).setGuid(newGuid);\r
- i=tagIndex.size()+1;\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving ListManager.updateTagGuid");\r
-\r
- }\r
-\r
-\r
- //************************************************************************************\r
- //************************************************************************************\r
- //** Notebook functions\r
- //************************************************************************************\r
- //************************************************************************************ \r
- // Delete a notebook\r
- public void deleteNotebook(String guid) {\r
- for (int i=0; i<getNotebookIndex().size(); i++) {\r
- if (getNotebookIndex().get(i).getGuid().equals(guid)) {\r
- getNotebookIndex().remove(i);\r
- i=getMasterNoteIndex().size();\r
- }\r
- }\r
- conn.getNotebookTable().expungeNotebook(guid, true); \r
- }\r
- // Update a notebook sequence number\r
- public void updateNotebookSequence(String guid, int sequence) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNotebookSequence");\r
-\r
- conn.getNotebookTable().updateNotebookSequence(guid, sequence);\r
- \r
- for (int i=0; i<notebookIndex.size(); i++) {\r
- if (notebookIndex.get(i).getGuid().equals(guid)) {\r
- notebookIndex.get(i).setUpdateSequenceNum(sequence);\r
- i=notebookIndex.size()+1;\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNotebookSequence");\r
-\r
- }\r
- // Update a notebook Guid number\r
- public void updateNotebookGuid(String oldGuid, String newGuid) {\r
- logger.log(logger.HIGH, "Entering ListManager.updateNotebookGuid");\r
-\r
- conn.getNotebookTable().updateNotebookGuid(oldGuid, newGuid);\r
- \r
- for (int i=0; i<notebookIndex.size(); i++) {\r
- if (notebookIndex.get(i).getGuid().equals(oldGuid)) {\r
- notebookIndex.get(i).setGuid(newGuid);\r
- i=notebookIndex.size()+1;\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving ListManager.updateNotebookGuid");\r
-\r
- }\r
- \r
- \r
- //************************************************************************************\r
- //************************************************************************************\r
- //** Load and filter the note index\r
- //************************************************************************************\r
- //************************************************************************************\r
- \r
- public void noteDownloaded(Note n) {\r
- boolean found = false;\r
- for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
- if (getMasterNoteIndex().get(i).getGuid().equals(n.getGuid())) {\r
- getMasterNoteIndex().set(i,n);\r
- found = true;\r
- i=getMasterNoteIndex().size();\r
- }\r
- }\r
- \r
- if (!found)\r
- getMasterNoteIndex().add(n);\r
- \r
- for (int i=0; i<getNoteIndex().size(); i++) {\r
- if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {\r
- if (filterRecord(getNoteIndex().get(i)))\r
- getNoteIndex().add(n);\r
- getNoteIndex().remove(i);\r
- i=getNoteIndex().size();\r
- }\r
- }\r
- \r
- if (filterRecord(n))\r
- getNoteIndex().add(n);\r
- \r
- }\r
- // Check if a note matches the currently selected notebooks, tags, or attribute searches.\r
- public boolean filterRecord(Note n) {\r
- \r
- boolean goodNotebook = false;\r
- boolean goodTag = false;\r
- boolean goodStatus = false;\r
- \r
- // Check note status\r
- if (!n.isActive() && Global.showDeleted)\r
- return true;\r
- else {\r
- if (n.isActive() && !Global.showDeleted)\r
- goodStatus = true;\r
- // Begin filtering results\r
- if (goodStatus)\r
- goodNotebook = filterByNotebook(n.getNotebookGuid());\r
- if (goodNotebook) \r
- goodTag = filterByTag(n.getTagGuids());\r
- if (goodTag) {\r
- boolean goodCreatedBefore = false;\r
- boolean goodCreatedSince = false;\r
- boolean goodChangedBefore = false;\r
- boolean goodChangedSince = false;\r
- boolean goodContains = false;\r
- \r
- if (!Global.createdBeforeFilter.hasSelection())\r
- goodCreatedBefore = true;\r
- else\r
- goodCreatedBefore = Global.createdBeforeFilter.check(n);\r
- \r
- if (!Global.createdSinceFilter.hasSelection())\r
- goodCreatedSince = true;\r
- else\r
- goodCreatedSince = Global.createdSinceFilter.check(n);\r
- \r
- if (!Global.changedBeforeFilter.hasSelection())\r
- goodChangedBefore = true;\r
- else\r
- goodChangedBefore = Global.changedBeforeFilter.check(n);\r
- if (!Global.changedSinceFilter.hasSelection())\r
- goodChangedSince = true;\r
- else\r
- goodChangedSince = Global.changedSinceFilter.check(n);\r
- if (!Global.containsFilter.hasSelection())\r
- goodContains = true;\r
- else\r
- goodContains = Global.containsFilter.check(conn.getNoteTable(), n);\r
- \r
- if (goodCreatedSince && goodCreatedBefore && goodChangedSince && goodChangedBefore && goodContains)\r
- return true;\r
- }\r
- } \r
- return false;\r
- }\r
- \r
- // Load the note index based upon what the user wants.\r
- public void loadNotesIndex() {\r
- logger.log(logger.EXTREME, "Entering ListManager.loadNotesIndex()");\r
- tagCounterRunner.abortCount = true;\r
- notebookCounterRunner.abortCount = true;\r
- trashCounterRunner.abortCount = true;\r
- \r
- List<Note> matches;\r
- if (enSearchChanged || getMasterNoteIndex() == null)\r
- matches = enSearch.matchWords();\r
- else\r
- matches = getMasterNoteIndex();\r
- \r
- if (matches == null)\r
- matches = getMasterNoteIndex();\r
- \r
- setNoteIndex(new ArrayList<Note>());\r
- for (int i=0; i<matches.size(); i++) {\r
- if (filterRecord(matches.get(i)))\r
- getNoteIndex().add(matches.get(i));\r
- }\r
- countNotebookResults(getNoteIndex());\r
- countTagResults(getNoteIndex());\r
- enSearchChanged = false;\r
- reloadTrashCount();\r
- logger.log(logger.EXTREME, "Leaving ListManager.loadNotesIndex()");\r
- }\r
- public void countNotebookResults(List<Note> index) {\r
- logger.log(logger.EXTREME, "Entering ListManager.countNotebookResults()");\r
- if (!Global.mimicEvernoteInterface) {\r
- notebookCounterRunner.setNoteIndex(index);\r
- notebookCounterRunner.release(CounterRunner.NOTEBOOK);\r
- } else {\r
- notebookCounterRunner.setNoteIndex(getMasterNoteIndex());\r
- notebookCounterRunner.release(CounterRunner.NOTEBOOK_ALL);\r
- }\r
- logger.log(logger.EXTREME, "Leaving ListManager.countNotebookResults()");\r
- }\r
- public void countTagResults(List<Note> index) {\r
- logger.log(logger.EXTREME, "Entering ListManager.countTagResults");\r
- if (!Global.tagBehavior().equalsIgnoreCase("DoNothing")) {\r
- tagCounterRunner.setNoteIndex(index);\r
- tagCounterRunner.release(CounterRunner.TAG);\r
- } else {\r
- tagCounterRunner.setNoteIndex(null);\r
- tagCounterRunner.release(CounterRunner.TAG_ALL);\r
- }\r
- logger.log(logger.EXTREME, "Leaving ListManager.countTagResults()");\r
- }\r
- // Update the count of items in the trash\r
- public void reloadTrashCount() {\r
- logger.log(logger.EXTREME, "Entering ListManager.reloadTrashCount");\r
- trashCounterRunner.setNoteIndex(getNoteIndex());\r
- trashCounterRunner.release(CounterRunner.TRASH);\r
- logger.log(logger.EXTREME, "Leaving ListManager.reloadTrashCount");\r
- } \r
- \r
- private boolean filterByNotebook(String guid) {\r
- boolean good = false;\r
- if (selectedNotebooks.size() == 0)\r
- good = true;\r
- if (!good && selectedNotebooks.contains(guid)) \r
- good = true;\r
-\r
- for (int i=0; i<getArchiveNotebookIndex().size() && good; i++) {\r
- if (guid.equals(getArchiveNotebookIndex().get(i).getGuid())) {\r
- good = false;\r
- return good;\r
- }\r
- }\r
- return good;\r
- }\r
- private boolean filterByTag(List<String> noteTags) {\r
- if (noteTags == null || selectedTags == null)\r
- return true;\r
- \r
- if (selectedTags.size() == 0) \r
- return true;\r
- \r
- for (int i=0; i<selectedTags.size(); i++) {\r
- String selectedGuid = selectedTags.get(i);\r
- if (noteTags.contains(selectedGuid))\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- \r
- \r
- public void updateNoteTitleColor(String guid, Integer color) {\r
- noteModel.updateNoteTitleColor(guid, color);\r
- conn.getNoteTable().setNoteTitleColor(guid, color);\r
- }\r
- public void loadNoteTitleColors() {\r
- List<Pair<String,Integer>> colors = conn.getNoteTable().getNoteTitleColors();\r
- if (noteModel.getTitleColors() == null)\r
- noteModel.setTitleColors(new HashMap<String,Integer>());\r
- else\r
- noteModel.getTitleColors().clear();\r
- for (int i=0; i<colors.size(); i++) {\r
- noteModel.getTitleColors().put(colors.get(i).getFirst(), colors.get(i).getSecond());\r
- }\r
- }\r
- \r
- //********************************************************************************\r
- //********************************************************************************\r
- //* Support signals from the index thread\r
- //********************************************************************************\r
- //********************************************************************************\r
- // Reset a flag if an index is needed\r
- public void setIndexNeeded(String guid, String type, Boolean b) {\r
- if (Global.keepRunning && type.equalsIgnoreCase("content"))\r
- conn.getNoteTable().setIndexNeeded(guid, false);\r
- if (Global.keepRunning && type.equalsIgnoreCase("resource")) {\r
- conn.getNoteTable().noteResourceTable.setIndexNeeded(guid, b);\r
- }\r
- }\r
- \r
- public boolean threadCheck(int id) {\r
- if (id == Global.notebookCounterThreadId) \r
- return notebookThread.isAlive();\r
- if (id == Global.tagCounterThreadId) \r
- return tagThread.isAlive();\r
- if (id == Global.trashCounterThreadId) \r
- return trashThread.isAlive();\r
- if (id == Global.saveThreadId) \r
- return saveThread.isAlive();\r
- return false;\r
- }\r
- \r
- \r
- \r
- //********************************************************************************\r
- //********************************************************************************\r
- //* Utility Functions\r
- //********************************************************************************\r
- //********************************************************************************\r
- public void compactDatabase() {\r
- conn.compactDatabase();\r
-// IndexConnection idx = new IndexConnection(logger, "nevernote-compact");\r
-// idx.dbSetup();\r
-// idx.dbShutdown();\r
- }\r
-\r
- // Rebuild the note HTML to something usable\r
- public List<String> scanNoteForResources(Note n) {\r
- logger.log(logger.HIGH, "Entering ListManager.scanNoteForResources");\r
- logger.log(logger.EXTREME, "Note guid: " +n.getGuid());\r
- QDomDocument doc = new QDomDocument();\r
- QDomDocument.Result result = doc.setContent(n.getContent());\r
- if (!result.success) {\r
- logger.log(logger.MEDIUM, "Parse error when scanning note for resources.");\r
- logger.log(logger.MEDIUM, "Note guid: " +n.getGuid());\r
- return null;\r
- }\r
- \r
- List<String> returnArray = new ArrayList<String>();\r
- QDomNodeList anchors = doc.elementsByTagName("en-media");\r
- for (int i=0; i<anchors.length(); i++) {\r
- QDomElement enmedia = anchors.at(i).toElement();\r
- if (enmedia.hasAttribute("type")) {\r
- QDomAttr hash = enmedia.attributeNode("hash");\r
- returnArray.add(hash.value().toString());\r
- }\r
- }\r
- logger.log(logger.HIGH, "Leaving ListManager.scanNoteForResources");\r
- return returnArray;\r
- }\r
- // Given a list of tags, produce a string list of tag names\r
- public String getTagNamesForNote(Note n) {\r
- StringBuffer buffer = new StringBuffer(100);\r
- Vector<String> v = new Vector<String>();\r
- List<String> guids = n.getTagGuids();\r
- \r
- if (guids == null) \r
- return "";\r
- \r
- for (int i=0; i<guids.size(); i++) {\r
- v.add(getTagNameByGuid(guids.get(i)));\r
- }\r
- Comparator<String> comparator = Collections.reverseOrder();\r
- Collections.sort(v,comparator);\r
- Collections.reverse(v);\r
- \r
- for (int i = 0; i<v.size(); i++) {\r
- if (i>0) \r
- buffer.append(", ");\r
- buffer.append(v.get(i));\r
- }\r
- \r
- return buffer.toString();\r
- }\r
- // Get a tag name when given a tag guid\r
- public String getTagNameByGuid(String guid) {\r
- for (int i=0; i<getTagIndex().size(); i++) {\r
- String s = getTagIndex().get(i).getGuid();\r
- if (s.equals(guid)) { \r
- return getTagIndex().get(i).getName();\r
- }\r
- }\r
- return "";\r
- }\r
- // For a notebook guid, return the name\r
- public String getNotebookNameByGuid(String guid) {\r
- if (notebookIndex == null)\r
- return null;\r
- for (int i=0; i<notebookIndex.size(); i++) {\r
- String s = notebookIndex.get(i).getGuid();\r
- if (s.equals(guid)) { \r
- return notebookIndex.get(i).getName();\r
- }\r
- }\r
- return "";\r
- }\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.utilities;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Vector;
+
+import com.evernote.edam.type.LinkedNotebook;
+import com.evernote.edam.type.Note;
+import com.evernote.edam.type.Notebook;
+import com.evernote.edam.type.SavedSearch;
+import com.evernote.edam.type.Tag;
+import com.trolltech.qt.QThread;
+import com.trolltech.qt.core.QDateTime;
+import com.trolltech.qt.gui.QImage;
+import com.trolltech.qt.gui.QPixmap;
+import com.trolltech.qt.sql.QSqlQuery;
+import com.trolltech.qt.xml.QDomAttr;
+import com.trolltech.qt.xml.QDomDocument;
+import com.trolltech.qt.xml.QDomElement;
+import com.trolltech.qt.xml.QDomNodeList;
+
+import cx.fbn.nevernote.Global;
+import cx.fbn.nevernote.evernote.NoteMetadata;
+import cx.fbn.nevernote.filters.EnSearch;
+import cx.fbn.nevernote.filters.NotebookCounter;
+import cx.fbn.nevernote.filters.TagCounter;
+import cx.fbn.nevernote.gui.NoteTableModel;
+import cx.fbn.nevernote.signals.NotebookSignal;
+import cx.fbn.nevernote.signals.StatusSignal;
+import cx.fbn.nevernote.signals.TagSignal;
+import cx.fbn.nevernote.signals.ThreadSignal;
+import cx.fbn.nevernote.signals.TrashSignal;
+import cx.fbn.nevernote.sql.DatabaseConnection;
+import cx.fbn.nevernote.threads.CounterRunner;
+import cx.fbn.nevernote.threads.SaveRunner;
+
+
+public class ListManager {
+
+
+ private final ApplicationLogger logger;
+ DatabaseConnection conn;
+ QSqlQuery deleteWords;
+ QSqlQuery insertWords;
+
+ private List<Tag> tagIndex;
+ private List<Notebook> notebookIndex;
+ private List<Notebook> archiveNotebookIndex;
+ private List<String> localNotebookIndex;
+ private List<LinkedNotebook> linkedNotebookIndex;
+
+ private List<SavedSearch> searchIndex;
+
+ private List<String> selectedNotebooks;
+ private final NoteTableModel noteModel;
+
+
+ private List<String> selectedTags;
+ private String selectedSearch;
+ ThreadSignal signals;
+ public StatusSignal status;
+ private final CounterRunner notebookCounterRunner;
+ private final QThread notebookThread;
+ private final CounterRunner tagCounterRunner;
+ private final QThread tagThread;
+
+ private final CounterRunner trashCounterRunner;
+ private final QThread trashThread;
+ public TrashSignal trashSignal;
+
+ private List<NotebookCounter> notebookCounter; // count of displayed notes in each notebook
+ private List<TagCounter> tagCounter; // count of displayed notes for each tag
+
+ private EnSearch enSearch;
+ private boolean enSearchChanged;
+ public HashMap<String, String> wordMap;
+ public TagSignal tagSignal;
+ public NotebookSignal notebookSignal;
+ public boolean refreshCounters; // Used to control when to recount lists
+ private int trashCount;
+ public SaveRunner saveRunner; // Thread used to save content. Used because the xml conversion is slowwwww
+ QThread saveThread;
+
+// private final HashMap<String, QImage> thumbnailList;
+
+ // Constructor
+ public ListManager(DatabaseConnection d, ApplicationLogger l) {
+ conn = d;
+ logger = l;
+
+ conn.getTagTable().cleanupTags();
+ status = new StatusSignal();
+ signals = new ThreadSignal();
+
+ // setup index locks
+ enSearchChanged = false;
+
+ // Setup arrays
+ noteModel = new NoteTableModel(this);
+ selectedTags = new ArrayList<String>();
+
+ notebookCounter = new ArrayList<NotebookCounter>();
+ tagCounter = new ArrayList<TagCounter>();
+ selectedNotebooks = new ArrayList<String>();
+
+ reloadIndexes();
+
+ notebookSignal = new NotebookSignal();
+ // ICHANGED Global.getBehaviorDatabaseUrl()を追加
+ notebookCounterRunner = new CounterRunner("notebook_counter.log", CounterRunner.NOTEBOOK,
+ Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
+ Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
+ notebookCounterRunner.setNoteIndex(getNoteIndex());
+ notebookCounterRunner.notebookSignal.countsChanged.connect(this, "setNotebookCounter(List)");
+ notebookThread = new QThread(notebookCounterRunner, "Notebook Counter Thread");
+ notebookThread.start();
+
+ tagSignal = new TagSignal();
+ // ICHANGED Global.getBehaviorDatabaseUrl()を追加
+ tagCounterRunner = new CounterRunner("tag_counter.log", CounterRunner.TAG,
+ Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
+ Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
+ tagCounterRunner.setNoteIndex(getNoteIndex());
+ tagCounterRunner.tagSignal.countsChanged.connect(this, "setTagCounter(List)");
+ tagThread = new QThread(tagCounterRunner, "Tag Counter Thread");
+ tagThread.start();
+
+ trashSignal = new TrashSignal();
+ // ICHANGED Global.getBehaviorDatabaseUrl()を追加
+ trashCounterRunner = new CounterRunner("trash_counter.log", CounterRunner.TRASH,
+ Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
+ Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
+ trashCounterRunner.trashSignal.countChanged.connect(this, "trashSignalReceiver(Integer)");
+ trashThread = new QThread(trashCounterRunner, "Trash Counter Thread");
+ trashThread.start();
+// reloadTrashCount();
+
+ wordMap = new HashMap<String, String>();
+ tagSignal = new TagSignal();
+
+ logger.log(logger.EXTREME, "Setting save thread");
+ // ICHANGED Global.getBehaviorDatabaseUrl()を追加
+ saveRunner = new SaveRunner("saveRunner.log",
+ Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
+ Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
+ saveThread = new QThread(saveRunner, "Save Runner Thread");
+ saveThread.start();
+
+// thumbnailList = conn.getNoteTable().getThumbnails();
+// thumbnailList = new HashMap<String,QImage>();
+
+ linkedNotebookIndex = conn.getLinkedNotebookTable().getAll();
+ loadNoteTitleColors();
+ refreshCounters = true;
+ refreshCounters();
+
+ }
+
+ public void stop() {
+ saveRunner.addWork("stop", "");
+ tagCounterRunner.release(CounterRunner.EXIT);
+ notebookCounterRunner.release(CounterRunner.EXIT);
+ trashCounterRunner.release(CounterRunner.EXIT);
+
+ logger.log(logger.MEDIUM, "Waiting for notebookCounterThread to stop");
+ try {
+ notebookThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ logger.log(logger.MEDIUM, "Waiting for tagCounterThread to stop");
+ try {
+ tagThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ logger.log(logger.MEDIUM, "Waiting for trashThread to stop");
+ try {
+ trashThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+
+ logger.log(logger.MEDIUM, "Waiting for saveThread to stop");
+ try {
+ saveThread.join(0);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ //***************************************************************
+ //***************************************************************
+ //* Refresh lists after a db sync
+ //***************************************************************
+ //***************************************************************
+ // ICHANGED
+ public void saveUpdatedNotes(HashMap<Integer, Note> notes, HashMap<Integer, String> contents) {
+ for (int i = 0; i < notes.size(); i++) {
+ Note n = notes.get(i);
+ String content = contents.get(i);
+ saveRunner.addWork(n.getGuid(), content);
+ conn.getNoteTable().updateNoteTitle(n.getGuid(), n.getTitle());
+ }
+ }
+
+ // ICHANGED
+ public void refreshLists() {
+ setSavedSearchIndex(conn.getSavedSearchTable().getAll());
+ setTagIndex(conn.getTagTable().getAll());
+ setNotebookIndex(conn.getNotebookTable().getAll());
+
+ List<Notebook> local = conn.getNotebookTable().getAllLocal();
+ localNotebookIndex = new ArrayList<String>();
+ for (int i=0; i<local.size(); i++)
+ localNotebookIndex.add(local.get(i).getGuid());
+
+ noteModel.setMasterNoteIndex(conn.getNoteTable().getAllNotes());
+ // For performance reasons, we didn't get the tags for every note individually. We now need to
+ // get them
+ List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ List<String> tags = new ArrayList<String>();
+ List<String> names = new ArrayList<String>();
+ for (int j=0; j<noteTags.size(); j++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
+ tags.add(noteTags.get(j).tagGuid);
+ names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
+ }
+ }
+
+ getMasterNoteIndex().get(i).setTagGuids(tags);
+ getMasterNoteIndex().get(i).setTagNames(names);
+ }
+
+
+ //setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
+
+ linkedNotebookIndex = conn.getLinkedNotebookTable().getAll();
+
+ enSearchChanged = true;
+ }
+
+ public void reloadTagIndex() {
+ setTagIndex(conn.getTagTable().getAll());
+ }
+ public void reloadIndexes() {
+ //setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
+
+ List<Notebook> local = conn.getNotebookTable().getAllLocal();
+ localNotebookIndex = new ArrayList<String>();
+ for (int i=0; i<local.size(); i++)
+ localNotebookIndex.add(local.get(i).getGuid());
+
+ reloadTagIndex();
+ // Load notebooks
+ setNotebookIndex(conn.getNotebookTable().getAll());
+ // load archived notebooks (if note using the EN interface)
+ setArchiveNotebookIndex(conn.getNotebookTable().getAllArchived());
+ // load saved search index
+ setSavedSearchIndex(conn.getSavedSearchTable().getAll());
+ // Load search helper utility
+ enSearch = new EnSearch(conn, logger, "", getTagIndex(), Global.getRecognitionWeight());
+ logger.log(logger.HIGH, "Building note index");
+
+// if (getMasterNoteIndex() == null) {
+ noteModel.setMasterNoteIndex(conn.getNoteTable().getAllNotes());
+// }
+ // For performance reasons, we didn't get the tags for every note individually. We now need to
+ // get them
+ List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ List<String> tags = new ArrayList<String>();
+ List<String> names = new ArrayList<String>();
+ for (int j=0; j<noteTags.size(); j++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
+ tags.add(noteTags.get(j).tagGuid);
+ names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
+ }
+ }
+
+ getMasterNoteIndex().get(i).setTagGuids(tags);
+ getMasterNoteIndex().get(i).setTagNames(names);
+ }
+
+ setNoteIndex(getMasterNoteIndex());
+
+ }
+
+ //***************************************************************
+ //***************************************************************
+ //* selected notebooks
+ //***************************************************************
+ //***************************************************************
+ // Return the selected notebook(s)
+ public List<String> getSelectedNotebooks() {
+ return selectedNotebooks;
+ }
+ // Set the current selected notebook(s)
+ public void setSelectedNotebooks(List <String> s) {
+ if (s == null)
+ s = new ArrayList<String>();
+ selectedNotebooks = s;
+ }
+
+
+ //***************************************************************
+ //***************************************************************
+ //** These functions deal with setting & retrieving the master lists
+ //***************************************************************
+ //***************************************************************
+ // Get the note table model
+ public NoteTableModel getNoteTableModel() {
+ return noteModel;
+ }
+ // save the saved search index
+ private void setSavedSearchIndex(List<SavedSearch> t) {
+ searchIndex = t;
+ }
+ // Retrieve the Tag index
+ public List<SavedSearch> getSavedSearchIndex() {
+ return searchIndex;
+
+ }
+ // save the tag index
+ private void setTagIndex(List<Tag> t) {
+ tagIndex = t;
+ }
+ // Retrieve the Tag index
+ public List<Tag> getTagIndex() {
+ return tagIndex;
+ }
+ private void setNotebookIndex(List<Notebook> t) {
+ notebookIndex = t;
+ }
+ private void setArchiveNotebookIndex(List<Notebook> t) {
+ archiveNotebookIndex = t;
+ }
+ // Retrieve the Notebook index
+ public List<Notebook> getNotebookIndex() {
+ return notebookIndex;
+
+ }
+ public List<LinkedNotebook> getLinkedNotebookIndex() {
+ return linkedNotebookIndex;
+ }
+ public List<Notebook> getArchiveNotebookIndex() {
+ return archiveNotebookIndex;
+ }
+ // Save the current note list
+ private void setNoteIndex(List<Note> n) {
+ noteModel.setNoteIndex(n);
+ refreshNoteMetadata();
+ }
+ public void refreshNoteMetadata() {
+ noteModel.setNoteMetadata(conn.getNoteTable().getNotesMetaInformation());
+ }
+ // Update a note's meta data
+ public void updateNoteMetadata(NoteMetadata meta) {
+ noteModel.metaData.remove(meta);
+ noteModel.metaData.put(meta.getGuid(), meta);
+ conn.getNoteTable().updateNoteMetadata(meta);
+ }
+ // Get the note index
+ public synchronized List<Note> getNoteIndex() {
+ return noteModel.getNoteIndex();
+ }
+ // Save the count of notes per notebook
+ public void setNotebookCounter(List<NotebookCounter> n) {
+ notebookCounter = n;
+ notebookSignal.refreshNotebookTreeCounts.emit(getNotebookIndex(), notebookCounter);
+ }
+ public List<NotebookCounter> getNotebookCounter() {
+ return notebookCounter;
+ }
+ // Save the count of notes for each tag
+ public void setTagCounter(List<TagCounter> n) {
+ tagCounter = n;
+ tagSignal.refreshTagTreeCounts.emit(tagCounter);
+ }
+ public List<TagCounter> getTagCounter() {
+ return tagCounter;
+ }
+ public List<String> getLocalNotebooks() {
+ return localNotebookIndex;
+ }
+
+// public void setUnsynchronizedNotes(List<String> l) {
+// noteModel.setUnsynchronizedNotes(l);
+// }
+ // Return a count of items in the trash
+ public int getTrashCount() {
+ return trashCount;
+ }
+ // get the EnSearch variable
+ public EnSearch getEnSearch() {
+ return enSearch;
+ }
+ public List<Note> getMasterNoteIndex() {
+ return noteModel.getMasterNoteIndex();
+ }
+ // Thumbnails
+// public HashMap<String, QImage> getThumbnails() {
+// return thumbnailList;
+// }
+ public HashMap<String, NoteMetadata> getNoteMetadata() {
+ return noteModel.metaData;
+ }
+ public QImage getThumbnail(String guid) {
+// if (getThumbnails().containsKey(guid))
+// return getThumbnails().get(guid);
+
+ QImage img = new QImage();
+ img = QImage.fromData(conn.getNoteTable().getThumbnail(guid));
+ if (img == null || img.isNull())
+ return null;
+ //getThumbnails().put(guid, img);
+ return img;
+ }
+ public QPixmap getThumbnailPixmap(String guid) {
+// if (getThumbnails().containsKey(guid))
+// return getThumbnails().get(guid);
+
+ QPixmap img = new QPixmap();
+ img.loadFromData(conn.getNoteTable().getThumbnail(guid));
+ if (img == null || img.isNull())
+ return null;
+ //getThumbnails().put(guid, img);
+ return img;
+ }
+ //***************************************************************
+ //***************************************************************
+ //** These functions deal with setting & retrieving filters
+ //***************************************************************
+ //***************************************************************
+ public void setEnSearch(String t) {
+ enSearch = new EnSearch(conn,logger, t, getTagIndex(), Global.getRecognitionWeight());
+ enSearchChanged = true;
+ }
+ // Save search tags
+ public void setSelectedTags(List<String> selectedTags) {
+ this.selectedTags = selectedTags;
+ }
+ // Save seleceted search
+ public void setSelectedSavedSearch(String s) {
+ this.selectedSearch = s;
+ }
+ // Get search tags
+ public List<String> getSelectedTags() {
+ return selectedTags;
+ }
+ // Get saved search
+ public String getSelectedSearch() {
+ return selectedSearch;
+ }
+
+
+
+
+ //***************************************************************
+ //***************************************************************
+ //** Note functions
+ //***************************************************************
+ //***************************************************************
+ // Save Note Tags
+ public void saveNoteTags(String noteGuid, List<String> tags, boolean isDirty) {\r
+ logger.log(logger.HIGH, "Entering ListManager.saveNoteTags");
+ // ICHANGED 同じタグが付けられた履歴を記録(必ずdeleteNoteTagの前にやる)
+ for (int i = 0; i < tags.size(); i++) {
+ String tagName = tags.get(i);
+ for (int j = 0; j < tagIndex.size(); j++) {
+ if (tagIndex.get(j).getName().equalsIgnoreCase(tagName)) {
+ conn.getHistoryTable().addSameTagHistory(noteGuid, tagIndex.get(j).getGuid());
+ }
+ }
+ }
+
+ String tagName;
+ conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
+ List<String> tagGuids = new ArrayList<String>();
+ boolean newTagCreated = false;
+
+ for (int i=0; i<tags.size(); i++) {
+ tagName = tags.get(i);
+ boolean found = false;
+ for (int j=0; j<tagIndex.size(); j++) {
+ if (tagIndex.get(j).getName().equalsIgnoreCase(tagName)) {
+ conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, tagIndex.get(j).getGuid(), isDirty);\r
+ tagGuids.add(tagIndex.get(j).getGuid());
+ j=tagIndex.size()+1;
+ found = true;
+ }
+ }
+ if (!found) {
+ Tag nTag = new Tag();
+ nTag.setName(tagName);
+ Calendar currentTime = new GregorianCalendar();
+ Long l = new Long(currentTime.getTimeInMillis());
+ long prevTime = l;
+ while (l==prevTime) {
+ currentTime = new GregorianCalendar();
+ l=currentTime.getTimeInMillis();
+ }
+ String randint = new String(Long.toString(l));
+
+ nTag.setUpdateSequenceNum(0);
+ nTag.setGuid(randint);
+ conn.getTagTable().addTag(nTag, true);
+ getTagIndex().add(nTag);
+ conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, nTag.getGuid(), isDirty);\r
+ tagGuids.add(nTag.getGuid());
+ newTagCreated = true;
+ }
+ }
+
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(noteGuid)) {
+ getNoteIndex().get(i).setTagNames(tags);
+ getNoteIndex().get(i).setTagGuids(tagGuids);
+ i=getNoteIndex().size()+1;
+ }
+ }
+ if (newTagCreated)
+ tagSignal.listChanged.emit();
+ logger.log(logger.HIGH, "Leaving ListManager.saveNoteTags");
+ }
+ // Delete a note
+ public void deleteNote(String guid) {
+ trashCounterRunner.abortCount = true;
+ Calendar currentTime = new GregorianCalendar();
+ Long l = new Long(currentTime.getTimeInMillis());
+ long prevTime = l;
+ while (l==prevTime) {
+ currentTime = new GregorianCalendar();
+ l=currentTime.getTimeInMillis();
+ }
+
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
+ getMasterNoteIndex().get(i).setActive(false);
+ getMasterNoteIndex().get(i).setDeleted(l);
+ i=getMasterNoteIndex().size();
+ }
+ }
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(guid)) {
+ getNoteIndex().get(i).setActive(false);
+ getNoteIndex().get(i).setDeleted(l);
+ i=getNoteIndex().size();
+ }
+ }
+ conn.getNoteTable().deleteNote(guid);
+ reloadTrashCount();
+ }
+ // Delete a note
+ public void restoreNote(String guid) {
+ trashCounterRunner.abortCount = true;
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
+ getMasterNoteIndex().get(i).setActive(true);
+ getMasterNoteIndex().get(i).setDeleted(0);
+ i=getMasterNoteIndex().size();
+ }
+ }
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(guid)) {
+ getNoteIndex().get(i).setActive(true);
+ getNoteIndex().get(i).setDeleted(0);
+ i=getNoteIndex().size();
+ }
+ }
+ conn.getNoteTable().restoreNote(guid);
+ reloadTrashCount();
+ }
+ public void updateNote(Note n) {
+
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(n.getGuid())) {
+ getMasterNoteIndex().remove(i);
+ getMasterNoteIndex().add(n);
+ }
+ }
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {
+ getNoteIndex().get(i).setActive(true);
+ getNoteIndex().get(i).setDeleted(0);
+ i=getNoteIndex().size();
+ }
+ }
+ conn.getNoteTable().updateNote(n);
+ }
+ // Add a note.
+ public void addNote(Note n, NoteMetadata meta) {
+ noteModel.addNote(n, meta);
+ noteModel.metaData.put(n.getGuid(), meta);
+ }
+ // Expunge a note
+ public void expungeNote(String guid) {
+ trashCounterRunner.abortCount = true;
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
+ getMasterNoteIndex().remove(i);
+ i=getMasterNoteIndex().size();
+ }
+ }
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(guid)) {
+ getNoteIndex().remove(i);
+ i=getNoteIndex().size();
+ }
+ }
+ conn.getNoteTable().expungeNote(guid, false, true);
+ reloadTrashCount();
+ }
+ // Expunge a note
+ public void emptyTrash() {
+ trashCounterRunner.abortCount = true;
+ for (int i=getMasterNoteIndex().size()-1; i>=0; i--) {
+ if (!getMasterNoteIndex().get(i).isActive()) {
+ getMasterNoteIndex().remove(i);
+ }
+ }
+
+ for (int i=getNoteIndex().size()-1; i>=0; i--) {
+ if (!getNoteIndex().get(i).isActive()) {
+ getNoteIndex().remove(i);
+ }
+ }
+
+ conn.getNoteTable().expungeAllDeletedNotes();
+ reloadTrashCount();
+ }
+ // The trash counter thread has produced a result
+ @SuppressWarnings("unused")
+ private void trashSignalReceiver(Integer i) {
+ trashCount = i;
+ trashSignal.countChanged.emit(i);
+ }
+ // Update note contents
+ public void updateNoteContent(String guid, String content) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");
+// EnmlConverter enml = new EnmlConverter(logger);
+// String text = enml.convert(guid, content);
+
+ // Update the list tables
+/* for (int i=0; i<masterNoteIndex.size(); i++) {
+ if (masterNoteIndex.get(i).getGuid().equals(guid)) {
+ masterNoteIndex.get(i).setContent(text);
+ i = masterNoteIndex.size();
+ }
+ }
+ // Update the list tables
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(guid)) {
+ getNoteIndex().get(i).setContent(text);
+ i = getNoteIndex().size();
+ }
+ }
+*/
+ // Check if any new tags were encountered
+/* if (enml.saveInvalidXML) {
+ List<String> elements = Global.invalidElements;
+ for (int i=0; i<elements.size(); i++) {
+ conn.getInvalidXMLTable().addInvalidElement(elements.get(i));
+ }
+ for (String key : Global.invalidAttributes.keySet()) {
+ ArrayList<String> attributes = Global.invalidAttributes.get(key);
+ for (int i=0; i<attributes.size(); i++) {
+ conn.getInvalidXMLTable().addInvalidAttribute(key, attributes.get(i));
+ }
+ }
+ }
+*/
+ saveRunner.addWork(guid, content);
+// conn.getNoteTable().updateNoteContent(guid, content);
+ logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");
+ }
+ // Update a note creation date
+ public void updateNoteCreatedDate(String guid, QDateTime date) {
+ noteModel.updateNoteCreatedDate(guid, date);
+ conn.getNoteTable().updateNoteCreatedDate(guid, date);
+ }
+ // Subject date has been changed
+ public void updateNoteSubjectDate(String guid, QDateTime date) {
+ noteModel.updateNoteSubjectDate(guid, date);
+ conn.getNoteTable().updateNoteSubjectDate(guid, date);
+ }
+ // Author has changed
+ public void updateNoteAuthor(String guid, String author) {
+ noteModel.updateNoteAuthor(guid, author);
+ conn.getNoteTable().updateNoteAuthor(guid, author);
+ }
+ // Author has changed
+ public void updateNoteGeoTag(String guid, Double lon, Double lat, Double alt) {
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
+ getMasterNoteIndex().get(i).getAttributes().setLongitude(lon);
+ getMasterNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);
+ getMasterNoteIndex().get(i).getAttributes().setLatitude(lat);
+ getMasterNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);
+ getMasterNoteIndex().get(i).getAttributes().setAltitude(alt);
+ getMasterNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);
+ i = getMasterNoteIndex().size();
+ }
+ }
+ // Update the list tables
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(guid)) {
+ getNoteIndex().get(i).getAttributes().setLongitude(lon);
+ getNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);
+ getNoteIndex().get(i).getAttributes().setLatitude(lat);
+ getNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);
+ getNoteIndex().get(i).getAttributes().setAltitude(alt);
+ getNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);
+ i = getNoteIndex().size();
+ }
+ }
+ conn.getNoteTable().updateNoteGeoTags(guid, lon, lat, alt);
+ }
+ // Source URL changed
+ public void updateNoteSourceUrl(String guid, String url) {
+ noteModel.updateNoteSourceUrl(guid, url);
+ conn.getNoteTable().updateNoteSourceUrl(guid, url);
+ }
+ // Update a note last changed date
+ public void updateNoteAlteredDate(String guid, QDateTime date) {
+ noteModel.updateNoteChangedDate(guid, date);
+ conn.getNoteTable().updateNoteAlteredDate(guid, date);
+ }
+ // Update a note title
+ public void updateNoteTitle(String guid, String title) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNoteTitle");
+ conn.getNoteTable().updateNoteTitle(guid, title);
+ noteModel.updateNoteTitle(guid, title);
+ logger.log(logger.HIGH, "Leaving ListManager.updateNoteTitle");
+ }
+ // Update a note's notebook
+ public void updateNoteNotebook(String guid, String notebookGuid) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNoteNotebook");
+ noteModel.updateNoteNotebook(guid, notebookGuid);
+ conn.getNoteTable().updateNoteNotebook(guid, notebookGuid, true);
+ logger.log(logger.HIGH, "Leaving ListManager.updateNoteNotebook");
+ }
+ // Update a note sequence number
+ public void updateNoteSequence(String guid, int sequence) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNoteSequence");
+
+ conn.getNoteTable().updateNoteSequence(guid, sequence);
+
+ for (int i=0; i<noteModel.getMasterNoteIndex().size(); i++) {
+ if (noteModel.getMasterNoteIndex().get(i).getGuid().equals(guid)) {
+ noteModel.getMasterNoteIndex().get(i).setUpdateSequenceNum(sequence);
+ i=noteModel.getMasterNoteIndex().size()+1;
+ }
+ }
+
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(guid)) {
+ getNoteIndex().get(i).setUpdateSequenceNum(sequence);
+ i=getNoteIndex().size()+1;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.updateNoteSequence");
+ }
+ public void updateNoteGuid(String oldGuid, String newGuid, boolean updateDatabase) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNoteGuid");
+ if (updateDatabase)
+ conn.getNoteTable().updateNoteGuid(oldGuid, newGuid);
+ noteModel.updateNoteGuid(oldGuid, newGuid);
+ logger.log(logger.HIGH, "Leaving ListManager.updateNoteGuid");
+
+ }
+
+
+ //************************************************************************************
+ //************************************************************************************
+ //** Tag functions
+ //************************************************************************************
+ //************************************************************************************
+ // Update a tag sequence number
+ public void updateTagSequence(String guid, int sequence) {
+ logger.log(logger.HIGH, "Entering ListManager.updateTagSequence");
+
+ conn.getTagTable().updateTagSequence(guid, sequence);
+ for (int i=0; i<tagIndex.size(); i++) {
+ if (tagIndex.get(i).getGuid().equals(guid)) {
+ getTagIndex().get(i).setUpdateSequenceNum(sequence);
+ i=tagIndex.size()+1;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.updateTagSequence");
+ }
+ // Update a tag guid number
+ public void updateTagGuid(String oldGuid, String newGuid) {
+ logger.log(logger.HIGH, "Entering ListManager.updateTagGuid");
+
+ conn.getTagTable().updateTagGuid(oldGuid, newGuid);
+ for (int i=0; i<tagIndex.size(); i++) {
+ if (tagIndex.get(i).getGuid().equals(oldGuid)) {
+ tagIndex.get(i).setGuid(newGuid);
+ i=tagIndex.size()+1;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.updateTagGuid");
+
+ }
+ // Find all children for a tag
+ public List<Tag> findAllChildren(String guid) {
+ List<Tag> tags = new ArrayList<Tag>();
+ return findAllChildrenRecursive(guid, tags);
+ }
+ public List<Tag> findAllChildrenRecursive(String guid, List<Tag> tags) {
+
+ // Start looping through the tags. If we find a tag which has a parent that
+ // matches guid, then we add it to the list of tags & search for its children.
+ for (int i=0; i<getTagIndex().size(); i++) {
+ if (getTagIndex().get(i).getParentGuid() != null && getTagIndex().get(i).getParentGuid().equals(guid)) {
+ tags.add(getTagIndex().get(i));
+ tags = findAllChildrenRecursive(getTagIndex().get(i).getGuid(), tags);
+ }
+ }
+ return tags;
+ }
+ // Give a list of tags, does any of them match a child tag?
+ public boolean checkNoteForChildTags(String guid, List<String> noteTags) {
+ boolean returnValue = false;
+ List<Tag> children = findAllChildren(guid);
+ for (int i=0; i<noteTags.size(); i++) {
+ String noteTag = noteTags.get(i);
+ for (int j=0; j<children.size(); j++) {
+ if (noteTag.equals(children.get(j).getGuid()))
+ return true;
+ }
+ }
+ return returnValue;
+ }
+
+
+ //************************************************************************************
+ //************************************************************************************
+ //** Notebook functions
+ //************************************************************************************
+ //************************************************************************************
+ // Delete a notebook
+ public void deleteNotebook(String guid) {
+ for (int i=0; i<getNotebookIndex().size(); i++) {
+ if (getNotebookIndex().get(i).getGuid().equals(guid)) {
+ getNotebookIndex().remove(i);
+ i=getMasterNoteIndex().size();
+ }
+ }
+ conn.getNotebookTable().expungeNotebook(guid, true);
+ }
+ // Rename a stack
+ public void renameStack(String oldName, String newName) {
+ for (int i=0; i<getNotebookIndex().size(); i++) {
+ if (getNotebookIndex().get(i).getStack() != null &&
+ getNotebookIndex().get(i).getStack().equalsIgnoreCase(oldName)) {
+ getNotebookIndex().get(i).setStack(newName);
+ }
+ }
+ }
+ // Update a notebook sequence number
+ public void updateNotebookSequence(String guid, int sequence) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNotebookSequence");
+
+ conn.getNotebookTable().updateNotebookSequence(guid, sequence);
+
+ for (int i=0; i<notebookIndex.size(); i++) {
+ if (notebookIndex.get(i).getGuid().equals(guid)) {
+ notebookIndex.get(i).setUpdateSequenceNum(sequence);
+ i=notebookIndex.size()+1;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.updateNotebookSequence");
+
+ }
+ // Update a notebook Guid number
+ public void updateNotebookGuid(String oldGuid, String newGuid) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNotebookGuid");
+
+ conn.getNotebookTable().updateNotebookGuid(oldGuid, newGuid);
+
+ for (int i=0; i<notebookIndex.size(); i++) {
+ if (notebookIndex.get(i).getGuid().equals(oldGuid)) {
+ notebookIndex.get(i).setGuid(newGuid);
+ i=notebookIndex.size()+1;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.updateNotebookGuid");
+
+ }
+ // Update a notebook Guid number
+ public void updateNotebookStack(String oldGuid, String stack) {
+ logger.log(logger.HIGH, "Entering ListManager.updateNotebookGuid");
+
+ conn.getNotebookTable().setStack(oldGuid, stack);
+
+ for (int i=0; i<notebookIndex.size(); i++) {
+ if (notebookIndex.get(i).getGuid().equals(oldGuid)) {
+ notebookIndex.get(i).setStack(stack);
+ i=notebookIndex.size()+1;
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.updateNotebookGuid");
+
+ }
+
+
+ //************************************************************************************
+ //************************************************************************************
+ //** Load and filter the note index
+ //************************************************************************************
+ //************************************************************************************
+
+ public void noteDownloaded(Note n) {
+ boolean found = false;
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ if (getMasterNoteIndex().get(i).getGuid().equals(n.getGuid())) {
+ getMasterNoteIndex().set(i,n);
+ found = true;
+ i=getMasterNoteIndex().size();
+ }
+ }
+
+ if (!found)
+ getMasterNoteIndex().add(n);
+
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {
+ if (filterRecord(getNoteIndex().get(i)))
+ getNoteIndex().add(n);
+ getNoteIndex().remove(i);
+ i=getNoteIndex().size();
+ }
+ }
+
+ if (filterRecord(n))
+ getNoteIndex().add(n);
+
+ }
+ // Check if a note matches the currently selected notebooks, tags, or attribute searches.
+ public boolean filterRecord(Note n) {
+
+ boolean goodNotebook = false;
+ boolean goodTag = false;
+ boolean goodStatus = false;
+
+ // Check note status
+ if (!n.isActive() && Global.showDeleted)
+ return true;
+ else {
+ if (n.isActive() && !Global.showDeleted)
+ goodStatus = true;
+ }
+
+ // Begin filtering results
+ if (goodStatus)
+ goodNotebook = filterByNotebook(n.getNotebookGuid());
+ if (goodNotebook)
+ goodTag = filterByTag(n.getTagGuids());
+ if (goodTag) {
+ boolean goodCreatedBefore = false;
+ boolean goodCreatedSince = false;
+ boolean goodChangedBefore = false;
+ boolean goodChangedSince = false;
+ boolean goodContains = false;
+ if (!Global.createdBeforeFilter.hasSelection())
+ goodCreatedBefore = true;
+ else
+ goodCreatedBefore = Global.createdBeforeFilter.check(n);
+
+ if (!Global.createdSinceFilter.hasSelection())
+ goodCreatedSince = true;
+ else
+ goodCreatedSince = Global.createdSinceFilter.check(n);
+
+ if (!Global.changedBeforeFilter.hasSelection())
+ goodChangedBefore = true;
+ else
+ goodChangedBefore = Global.changedBeforeFilter.check(n);
+ if (!Global.changedSinceFilter.hasSelection())
+ goodChangedSince = true;
+ else
+ goodChangedSince = Global.changedSinceFilter.check(n);
+ if (!Global.containsFilter.hasSelection())
+ goodContains = true;
+ else
+ goodContains = Global.containsFilter.check(conn.getNoteTable(), n);
+
+ if (goodCreatedSince && goodCreatedBefore && goodChangedSince && goodChangedBefore && goodContains)
+ return true;
+ }
+ return false;
+ }
+
+ // Trigger a recount of counters
+ public void refreshCounters() {
+// refreshCounters= false;
+ if (!refreshCounters)
+ return;
+ refreshCounters = false;
+ tagCounterRunner.abortCount = true;
+ notebookCounterRunner.abortCount = true;
+ trashCounterRunner.abortCount = true;
+ countNotebookResults(getNoteIndex());
+ countTagResults(getNoteIndex());
+ reloadTrashCount();
+
+ }
+ // Load the note index based upon what the user wants.
+ public void loadNotesIndex() {
+ logger.log(logger.EXTREME, "Entering ListManager.loadNotesIndex()");
+
+ List<Note> matches;
+ if (enSearchChanged || getMasterNoteIndex() == null)
+ matches = enSearch.matchWords();
+ else
+ matches = getMasterNoteIndex();
+
+ if (matches == null)
+ matches = getMasterNoteIndex();
+
+ setNoteIndex(new ArrayList<Note>());
+ for (int i=0; i<matches.size(); i++) {
+ if (filterRecord(matches.get(i)))
+ getNoteIndex().add(matches.get(i));
+ }
+ refreshCounters = true;
+ enSearchChanged = false;
+ logger.log(logger.EXTREME, "Leaving ListManager.loadNotesIndex()");
+ }
+ public void countNotebookResults(List<Note> index) {
+ logger.log(logger.EXTREME, "Entering ListManager.countNotebookResults()");
+ notebookCounterRunner.abortCount = true;
+ if (!Global.mimicEvernoteInterface)
+ notebookCounterRunner.setNoteIndex(index);
+ else
+ notebookCounterRunner.setNoteIndex(getMasterNoteIndex());
+ notebookCounterRunner.release(CounterRunner.NOTEBOOK);
+ logger.log(logger.EXTREME, "Leaving ListManager.countNotebookResults()");
+ }
+ public void countTagResults(List<Note> index) {
+ logger.log(logger.EXTREME, "Entering ListManager.countTagResults");
+ trashCounterRunner.abortCount = true;
+ if (!Global.tagBehavior().equalsIgnoreCase("DoNothing"))
+ tagCounterRunner.setNoteIndex(index);
+ else
+ tagCounterRunner.setNoteIndex(getMasterNoteIndex());
+ tagCounterRunner.release(CounterRunner.TAG);
+ logger.log(logger.EXTREME, "Leaving ListManager.countTagResults()");
+ }
+ // Update the count of items in the trash
+ public void reloadTrashCount() {
+ logger.log(logger.EXTREME, "Entering ListManager.reloadTrashCount");
+ trashCounterRunner.abortCount = true;
+ trashCounterRunner.setNoteIndex(getMasterNoteIndex());
+ trashCounterRunner.release(CounterRunner.TRASH);
+ logger.log(logger.EXTREME, "Leaving ListManager.reloadTrashCount");
+ }
+
+ private boolean filterByNotebook(String guid) {
+ boolean good = false;
+ if (selectedNotebooks.size() == 0)
+ good = true;
+ if (!good && selectedNotebooks.contains(guid))
+ good = true;
+
+ for (int i=0; i<getArchiveNotebookIndex().size() && good; i++) {
+ if (guid.equals(getArchiveNotebookIndex().get(i).getGuid())) {
+ good = false;
+ return good;
+ }
+ }
+ return good;
+ }
+ private boolean filterByTag(List<String> noteTags) {
+ // If either the note has no tags or there are
+ // no selected tags, then any note is good.
+ if (noteTags == null || selectedTags == null)
+ return true;
+
+ // If there are no tags selected, then any note is good
+ if (selectedTags.size() == 0)
+ return true;
+
+ // If ALL tags must be matched, then check ALL note tags,
+ // otherwise we match on any criteria.
+ if (!Global.anyTagSelectionMatch()) {
+ for (int i=0; i<selectedTags.size(); i++) {
+ String selectedGuid = selectedTags.get(i);
+ boolean childMatch = false;
+ // If we should include children in the results
+ if (Global.includeTagChildren()) {
+ childMatch = checkNoteForChildTags(selectedGuid, noteTags);
+ // Do we have a match with this tag or any children
+ if (!noteTags.contains(selectedGuid)&& !childMatch)
+ return false;
+ } else {
+ // Does this note have a matching tag
+ if (!noteTags.contains(selectedGuid))
+ return false;
+ }
+ }
+ return true;
+ } else {
+ // Any match is displayed.
+ for (int i=0; i<selectedTags.size(); i++) {
+ String selectedGuid = selectedTags.get(i);
+ // If we have a simple match, then we're good
+ if (noteTags.contains(selectedGuid))
+ return true;
+ // If we have a match with one of the children tags && we should include child tags
+ if (Global.includeTagChildren() && checkNoteForChildTags(selectedGuid, noteTags))
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public void setNoteSynchronized(String guid, boolean value) {
+ getNoteTableModel().updateNoteSyncStatus(guid, value);
+ }
+
+ public void updateNoteTitleColor(String guid, Integer color) {
+ NoteMetadata meta = getNoteMetadata().get(guid);
+ if (meta != null) {
+ noteModel.updateNoteTitleColor(guid, color);
+ meta.setColor(color);
+ conn.getNoteTable().updateNoteMetadata(meta);
+ }
+ }
+ public void loadNoteTitleColors() {
+ noteModel.setMetaData(getNoteMetadata());
+ }
+
+ //********************************************************************************
+ //********************************************************************************
+ //* Support signals from the index thread
+ //********************************************************************************
+ //********************************************************************************
+ // Reset a flag if an index is needed
+ public void setIndexNeeded(String guid, String type, Boolean b) {
+ if (Global.keepRunning && type.equalsIgnoreCase("content"))
+ conn.getNoteTable().setIndexNeeded(guid, false);
+ if (Global.keepRunning && type.equalsIgnoreCase("resource")) {
+ conn.getNoteTable().noteResourceTable.setIndexNeeded(guid, b);
+ }
+ }
+
+ public boolean threadCheck(int id) {
+ if (id == Global.notebookCounterThreadId)
+ return notebookThread.isAlive();
+ if (id == Global.tagCounterThreadId)
+ return tagThread.isAlive();
+ if (id == Global.trashCounterThreadId)
+ return trashThread.isAlive();
+ if (id == Global.saveThreadId)
+ return saveThread.isAlive();
+ return false;
+ }
+
+
+
+ //********************************************************************************
+ //********************************************************************************
+ //* Utility Functions
+ //********************************************************************************
+ //********************************************************************************
+ public void compactDatabase() {
+ conn.compactDatabase();
+// IndexConnection idx = new IndexConnection(logger, "nevernote-compact");
+// idx.dbSetup();
+// idx.dbShutdown();
+ }
+
+ // Rebuild the note HTML to something usable
+ public List<String> scanNoteForResources(Note n) {
+ logger.log(logger.HIGH, "Entering ListManager.scanNoteForResources");
+ logger.log(logger.EXTREME, "Note guid: " +n.getGuid());
+ QDomDocument doc = new QDomDocument();
+ QDomDocument.Result result = doc.setContent(n.getContent());
+ if (!result.success) {
+ logger.log(logger.MEDIUM, "Parse error when scanning note for resources.");
+ logger.log(logger.MEDIUM, "Note guid: " +n.getGuid());
+ return null;
+ }
+
+ List<String> returnArray = new ArrayList<String>();
+ QDomNodeList anchors = doc.elementsByTagName("en-media");
+ for (int i=0; i<anchors.length(); i++) {
+ QDomElement enmedia = anchors.at(i).toElement();
+ if (enmedia.hasAttribute("type")) {
+ QDomAttr hash = enmedia.attributeNode("hash");
+ returnArray.add(hash.value().toString());
+ }
+ }
+ logger.log(logger.HIGH, "Leaving ListManager.scanNoteForResources");
+ return returnArray;
+ }
+ // Given a list of tags, produce a string list of tag names
+ public String getTagNamesForNote(Note n) {
+ StringBuffer buffer = new StringBuffer(100);
+ Vector<String> v = new Vector<String>();
+ List<String> guids = n.getTagGuids();
+
+ if (guids == null)
+ return "";
+
+ for (int i=0; i<guids.size(); i++) {
+ v.add(getTagNameByGuid(guids.get(i)));
+ }
+ Comparator<String> comparator = Collections.reverseOrder();
+ Collections.sort(v,comparator);
+ Collections.reverse(v);
+
+ for (int i = 0; i<v.size(); i++) {
+ if (i>0)
+ buffer.append(", ");
+ buffer.append(v.get(i));
+ }
+
+ return buffer.toString();
+ }
+ // Get a tag name when given a tag guid
+ public String getTagNameByGuid(String guid) {
+ for (int i=0; i<getTagIndex().size(); i++) {
+ String s = getTagIndex().get(i).getGuid();
+ if (s.equals(guid)) {
+ return getTagIndex().get(i).getName();
+ }
+ }
+ return "";
+ }
+ // For a notebook guid, return the name
+ public String getNotebookNameByGuid(String guid) {
+ if (notebookIndex == null)
+ return null;
+ for (int i=0; i<notebookIndex.size(); i++) {
+ String s = notebookIndex.get(i).getGuid();
+ if (s.equals(guid)) {
+ return notebookIndex.get(i).getName();
+ }
+ }
+ return "";
+ }
+
+
+ // Reload the note's tag names. This is called when a tag's name changes by
+ // the user. It updates all notes with that tag to the new tag name.
+ public void reloadNoteTagNames(String tagGuid, String newName) {
+
+ // Set the master index
+ for (int i=0; i<getMasterNoteIndex().size(); i++) {
+ for (int j=0; j<getMasterNoteIndex().get(i).getTagGuids().size(); j++) {
+ if (getMasterNoteIndex().get(i).getTagGuids().get(j).equals(tagGuid)) {
+ getMasterNoteIndex().get(i).getTagNames().set(j, newName);
+ }
+ }
+ }
+
+ // Set the current index
+ for (int i=0; i<getNoteIndex().size(); i++) {
+ for (int j=0; j<getNoteIndex().get(i).getTagGuids().size(); j++) {
+ if (getNoteIndex().get(i).getTagGuids().get(j).equals(tagGuid)) {
+ getNoteIndex().get(i).getTagNames().set(j, newName);
+ }
+ }
+ }
+ }
+
+}