2 * This file is part of NeverNote
\r
3 * Copyright 2009 Randy Baumgarte
\r
5 * This file may be licensed under the terms of of the
\r
6 * GNU General Public License Version 2 (the ``GPL'').
\r
8 * Software distributed under the License is distributed
\r
9 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
\r
10 * express or implied. See the GPL for the specific language
\r
11 * governing rights and limitations.
\r
13 * You should have received a copy of the GPL along with this
\r
14 * program. If not, go to http://www.gnu.org/licenses/gpl.html
\r
15 * or write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
20 package cx.fbn.nevernote.utilities;
\r
22 import java.util.ArrayList;
\r
23 import java.util.Calendar;
\r
24 import java.util.Collections;
\r
25 import java.util.Comparator;
\r
26 import java.util.GregorianCalendar;
\r
27 import java.util.HashMap;
\r
28 import java.util.List;
\r
29 import java.util.Vector;
\r
31 import com.evernote.edam.type.Note;
\r
32 import com.evernote.edam.type.Notebook;
\r
33 import com.evernote.edam.type.SavedSearch;
\r
34 import com.evernote.edam.type.Tag;
\r
35 import com.trolltech.qt.QThread;
\r
36 import com.trolltech.qt.core.QDateTime;
\r
37 import com.trolltech.qt.sql.QSqlQuery;
\r
38 import com.trolltech.qt.xml.QDomAttr;
\r
39 import com.trolltech.qt.xml.QDomDocument;
\r
40 import com.trolltech.qt.xml.QDomElement;
\r
41 import com.trolltech.qt.xml.QDomNodeList;
\r
43 import cx.fbn.nevernote.Global;
\r
44 import cx.fbn.nevernote.filters.EnSearch;
\r
45 import cx.fbn.nevernote.filters.NotebookCounter;
\r
46 import cx.fbn.nevernote.filters.TagCounter;
\r
47 import cx.fbn.nevernote.signals.NotebookSignal;
\r
48 import cx.fbn.nevernote.signals.StatusSignal;
\r
49 import cx.fbn.nevernote.signals.TagSignal;
\r
50 import cx.fbn.nevernote.signals.ThreadSignal;
\r
51 import cx.fbn.nevernote.signals.TrashSignal;
\r
52 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
53 import cx.fbn.nevernote.threads.CounterRunner;
\r
54 import cx.fbn.nevernote.threads.SaveRunner;
\r
57 public class ListManager {
\r
60 private final ApplicationLogger logger;
\r
61 DatabaseConnection conn;
\r
62 QSqlQuery deleteWords;
\r
63 QSqlQuery insertWords;
\r
65 private List<Tag> tagIndex;
\r
66 private List<Notebook> notebookIndex;
\r
67 private List<Notebook> archiveNotebookIndex;
\r
68 private List<String> localNotebookIndex;
\r
69 private List<Note> noteIndex;
\r
70 private List<SavedSearch> searchIndex;
\r
72 private List<String> selectedNotebooks;
\r
74 private List<Note> masterNoteIndex;
\r
75 private List<String> unsynchronizedNotes;
\r
76 private List<String> selectedTags;
\r
77 private String selectedSearch;
\r
78 ThreadSignal signals;
\r
79 public StatusSignal status;
\r
80 private final CounterRunner notebookCounterRunner;
\r
81 private final QThread notebookThread;
\r
82 private final CounterRunner tagCounterRunner;
\r
83 private final QThread tagThread;
\r
85 private final CounterRunner trashCounterRunner;
\r
86 private final QThread trashThread;
\r
87 public TrashSignal trashSignal;
\r
88 public HashMap<String,Integer> titleColors;
\r
90 private List<NotebookCounter> notebookCounter; // count of displayed notes in each notebook
\r
91 private List<TagCounter> tagCounter; // count of displayed notes for each tag
\r
93 private EnSearch enSearch;
\r
94 private boolean enSearchChanged;
\r
95 public HashMap<String, String> wordMap;
\r
96 public TagSignal tagSignal;
\r
97 public NotebookSignal notebookSignal;
\r
98 private int trashCount;
\r
99 private final int id;
\r
100 SaveRunner saveRunner; // Thread used to save content. Used because the xml conversion is slowwwww
\r
101 QThread saveThread;
\r
104 public ListManager(DatabaseConnection d, ApplicationLogger l, int instance_id) {
\r
109 status = new StatusSignal();
\r
110 signals = new ThreadSignal();
\r
112 // setup index locks
\r
113 enSearchChanged = false;
\r
116 masterNoteIndex = null;
\r
117 selectedTags = new ArrayList<String>();
\r
119 notebookCounter = new ArrayList<NotebookCounter>();
\r
120 tagCounter = new ArrayList<TagCounter>();
\r
121 selectedNotebooks = new ArrayList<String>();
\r
122 unsynchronizedNotes = new ArrayList<String>();
\r
126 notebookSignal = new NotebookSignal();
\r
127 notebookCounterRunner = new CounterRunner("notebook_counter.log", CounterRunner.NOTEBOOK, Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
\r
128 notebookCounterRunner.setNoteIndex(getNoteIndex());
\r
129 notebookCounterRunner.notebookSignal.countsChanged.connect(this, "setNotebookCounter(List)");
\r
130 notebookThread = new QThread(notebookCounterRunner, "Notebook Counter Thread");
\r
131 notebookThread.start();
\r
133 tagSignal = new TagSignal();
\r
134 tagCounterRunner = new CounterRunner("tag_counter.log", CounterRunner.TAG, Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
\r
135 tagCounterRunner.setNoteIndex(getNoteIndex());
\r
136 tagCounterRunner.tagSignal.countsChanged.connect(this, "setTagCounter(List)");
\r
137 tagThread = new QThread(tagCounterRunner, "Tag Counter Thread");
\r
140 trashSignal = new TrashSignal();
\r
141 trashCounterRunner = new CounterRunner("trash_counter.log", CounterRunner.TRASH, Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
\r
142 trashCounterRunner.trashSignal.countChanged.connect(this, "trashSignalReceiver(Integer)");
\r
143 trashThread = new QThread(trashCounterRunner, "Trash Counter Thread");
\r
144 trashThread.start();
\r
145 reloadTrashCount();
\r
147 wordMap = new HashMap<String, String>();
\r
148 tagSignal = new TagSignal();
\r
150 logger.log(logger.EXTREME, "Setting save thread");
\r
151 saveRunner = new SaveRunner("saveRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
\r
152 saveThread = new QThread(saveRunner, "Save Runner Thread");
\r
153 saveThread.start();
\r
155 loadNoteTitleColors();
\r
159 public void stop() {
\r
160 saveRunner.addWork("stop", "");
\r
161 tagCounterRunner.release(CounterRunner.EXIT);
\r
162 notebookCounterRunner.release(CounterRunner.EXIT);
\r
163 trashCounterRunner.release(CounterRunner.EXIT);
\r
165 logger.log(logger.MEDIUM, "Waiting for notebookCounterThread to stop");
\r
167 notebookThread.join();
\r
168 } catch (InterruptedException e) {
\r
169 e.printStackTrace();
\r
172 logger.log(logger.MEDIUM, "Waiting for tagCounterThread to stop");
\r
175 } catch (InterruptedException e) {
\r
176 e.printStackTrace();
\r
179 logger.log(logger.MEDIUM, "Waiting for trashThread to stop");
\r
181 trashThread.join();
\r
182 } catch (InterruptedException e) {
\r
183 e.printStackTrace();
\r
187 logger.log(logger.MEDIUM, "Waiting for saveThread to stop");
\r
189 saveThread.join(0);
\r
190 } catch (InterruptedException e) {
\r
191 e.printStackTrace();
\r
197 //***************************************************************
\r
198 //***************************************************************
\r
199 //* Refresh lists after a db sync
\r
200 //***************************************************************
\r
201 //***************************************************************
\r
202 public void refreshLists(Note n, boolean dirty, String content) {
\r
204 // conn.getNoteTable().updateNoteContent(n.getGuid(), n.getContent());
\r
205 saveRunner.addWork(n.getGuid(), content);
\r
206 conn.getNoteTable().updateNoteTitle(n.getGuid(), n.getTitle());
\r
209 setSavedSearchIndex(conn.getSavedSearchTable().getAll());
\r
210 setTagIndex(conn.getTagTable().getAll());
\r
211 setNotebookIndex(conn.getNotebookTable().getAll());
\r
213 List<Notebook> local = conn.getNotebookTable().getAllLocal();
\r
214 localNotebookIndex = new ArrayList<String>();
\r
215 for (int i=0; i<local.size(); i++)
\r
216 localNotebookIndex.add(local.get(i).getGuid());
\r
218 masterNoteIndex = conn.getNoteTable().getAllNotes();
\r
219 // For performance reasons, we didn't get the tags for every note individually. We now need to
\r
221 List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();
\r
222 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
223 List<String> tags = new ArrayList<String>();
\r
224 List<String> names = new ArrayList<String>();
\r
225 for (int j=0; j<noteTags.size(); j++) {
\r
226 if (masterNoteIndex.get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
\r
227 tags.add(noteTags.get(j).tagGuid);
\r
228 names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
\r
232 masterNoteIndex.get(i).setTagGuids(tags);
\r
233 masterNoteIndex.get(i).setTagNames(names);
\r
237 setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
\r
239 enSearchChanged = true;
\r
242 public void reloadIndexes() {
\r
243 setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
\r
245 List<Notebook> local = conn.getNotebookTable().getAllLocal();
\r
246 localNotebookIndex = new ArrayList<String>();
\r
247 for (int i=0; i<local.size(); i++)
\r
248 localNotebookIndex.add(local.get(i).getGuid());
\r
251 setTagIndex(conn.getTagTable().getAll());
\r
253 setNotebookIndex(conn.getNotebookTable().getAll());
\r
254 // load archived notebooks (if note using the EN interface)
\r
255 setArchiveNotebookIndex(conn.getNotebookTable().getAllArchived());
\r
256 // load saved search index
\r
257 setSavedSearchIndex(conn.getSavedSearchTable().getAll());
\r
258 // Load search helper utility
\r
259 enSearch = new EnSearch(conn, logger, "", getTagIndex(), Global.getMinimumWordLength(), Global.getRecognitionWeight());
\r
260 logger.log(logger.HIGH, "Building note index");
\r
262 if (masterNoteIndex == null) {
\r
263 masterNoteIndex = conn.getNoteTable().getAllNotes();
\r
265 // For performance reasons, we didn't get the tags for every note individually. We now need to
\r
267 List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();
\r
268 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
269 List<String> tags = new ArrayList<String>();
\r
270 List<String> names = new ArrayList<String>();
\r
271 for (int j=0; j<noteTags.size(); j++) {
\r
272 if (masterNoteIndex.get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
\r
273 tags.add(noteTags.get(j).tagGuid);
\r
274 names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
\r
278 masterNoteIndex.get(i).setTagGuids(tags);
\r
279 masterNoteIndex.get(i).setTagNames(names);
\r
282 setNoteIndex(masterNoteIndex);
\r
286 //***************************************************************
\r
287 //***************************************************************
\r
288 //* selected notebooks
\r
289 //***************************************************************
\r
290 //***************************************************************
\r
291 // Return the selected notebook(s)
\r
292 public List<String> getSelectedNotebooks() {
\r
293 return selectedNotebooks;
\r
295 // Set the current selected notebook(s)
\r
296 public void setSelectedNotebooks(List <String> s) {
\r
298 s = new ArrayList<String>();
\r
299 selectedNotebooks = s;
\r
303 //***************************************************************
\r
304 //***************************************************************
\r
305 //** These functions deal with setting & retrieving the master lists
\r
306 //***************************************************************
\r
307 //***************************************************************
\r
308 // save the saved search index
\r
309 private void setSavedSearchIndex(List<SavedSearch> t) {
\r
312 // Retrieve the Tag index
\r
313 public List<SavedSearch> getSavedSearchIndex() {
\r
314 return searchIndex;
\r
317 // save the tag index
\r
318 private void setTagIndex(List<Tag> t) {
\r
321 // Retrieve the Tag index
\r
322 public List<Tag> getTagIndex() {
\r
325 private void setNotebookIndex(List<Notebook> t) {
\r
328 private void setArchiveNotebookIndex(List<Notebook> t) {
\r
329 archiveNotebookIndex = t;
\r
331 // Retrieve the Notebook index
\r
332 public List<Notebook> getNotebookIndex() {
\r
333 return notebookIndex;
\r
336 public List<Notebook> getArchiveNotebookIndex() {
\r
337 return archiveNotebookIndex;
\r
339 // Save the current note list
\r
340 private void setNoteIndex(List<Note> n) {
\r
343 // Get the note index
\r
344 public synchronized List<Note> getNoteIndex() {
\r
347 // Save the count of notes per notebook
\r
348 public void setNotebookCounter(List<NotebookCounter> n) {
\r
349 notebookCounter = n;
\r
350 notebookSignal.refreshNotebookTreeCounts.emit(getNotebookIndex(), notebookCounter);
\r
352 public List<NotebookCounter> getNotebookCounter() {
\r
353 return notebookCounter;
\r
355 // Save the count of notes for each tag
\r
356 public void setTagCounter(List<TagCounter> n) {
\r
358 tagSignal.refreshTagTreeCounts.emit(tagCounter);
\r
360 public List<TagCounter> getTagCounter() {
\r
363 public List<String> getLocalNotebooks() {
\r
364 return localNotebookIndex;
\r
366 // Unsynchronized Note List
\r
367 public List<String> getUnsynchronizedNotes() {
\r
368 return unsynchronizedNotes;
\r
370 public void setUnsynchronizedNotes(List<String> l) {
\r
371 unsynchronizedNotes = l;
\r
373 // Return a count of items in the trash
\r
374 public int getTrashCount() {
\r
377 // get the EnSearch variable
\r
378 public EnSearch getEnSearch() {
\r
381 public List<Note> getMasterNoteIndex() {
\r
382 return masterNoteIndex;
\r
385 //***************************************************************
\r
386 //***************************************************************
\r
387 //** These functions deal with setting & retrieving filters
\r
388 //***************************************************************
\r
389 //***************************************************************
\r
390 public void setEnSearch(String t) {
\r
391 enSearch = new EnSearch(conn,logger, t, getTagIndex(), Global.getMinimumWordLength(), Global.getRecognitionWeight());
\r
392 enSearchChanged = true;
\r
394 // Save search tags
\r
395 public void setSelectedTags(List<String> selectedTags) {
\r
396 this.selectedTags = selectedTags;
\r
398 // Save seleceted search
\r
399 public void setSelectedSavedSearch(String s) {
\r
400 this.selectedSearch = s;
\r
403 public List<String> getSelectedTags() {
\r
404 return selectedTags;
\r
406 // Get saved search
\r
407 public String getSelectedSearch() {
\r
408 return selectedSearch;
\r
414 //***************************************************************
\r
415 //***************************************************************
\r
416 //** Note functions
\r
417 //***************************************************************
\r
418 //***************************************************************
\r
420 public void saveNoteTags(String noteGuid, List<String> tags) {
\r
421 logger.log(logger.HIGH, "Entering ListManager.saveNoteTags");
\r
423 conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
\r
424 List<String> tagGuids = new ArrayList<String>();
\r
425 boolean newTagCreated = false;
\r
427 for (int i=0; i<tags.size(); i++) {
\r
428 tagName = tags.get(i);
\r
429 boolean found = false;
\r
430 for (int j=0; j<tagIndex.size(); j++) {
\r
431 if (tagIndex.get(j).getName().equalsIgnoreCase(tagName)) {
\r
432 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, tagIndex.get(j).getGuid());
\r
433 tagGuids.add(tagIndex.get(j).getGuid());
\r
434 j=tagIndex.size()+1;
\r
439 Tag nTag = new Tag();
\r
440 nTag.setName(tagName);
\r
441 Calendar currentTime = new GregorianCalendar();
\r
442 Long l = new Long(currentTime.getTimeInMillis());
\r
444 while (l==prevTime) {
\r
445 currentTime = new GregorianCalendar();
\r
446 l=currentTime.getTimeInMillis();
\r
448 String randint = new String(Long.toString(l));
\r
450 nTag.setUpdateSequenceNum(0);
\r
451 nTag.setGuid(randint);
\r
452 conn.getTagTable().addTag(nTag, true);
\r
453 getTagIndex().add(nTag);
\r
454 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, nTag.getGuid());
\r
455 tagGuids.add(nTag.getGuid());
\r
456 newTagCreated = true;
\r
460 for (int i=0; i<noteIndex.size(); i++) {
\r
461 if (noteIndex.get(i).getGuid().equals(noteGuid)) {
\r
462 noteIndex.get(i).setTagNames(tags);
\r
463 noteIndex.get(i).setTagGuids(tagGuids);
\r
464 i=noteIndex.size()+1;
\r
468 tagSignal.listChanged.emit();
\r
469 logger.log(logger.HIGH, "Leaving ListManager.saveNoteTags");
\r
472 public void deleteNote(String guid) {
\r
473 trashCounterRunner.abortCount = true;
\r
474 Calendar currentTime = new GregorianCalendar();
\r
475 Long l = new Long(currentTime.getTimeInMillis());
\r
477 while (l==prevTime) {
\r
478 currentTime = new GregorianCalendar();
\r
479 l=currentTime.getTimeInMillis();
\r
482 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
483 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
484 masterNoteIndex.get(i).setActive(false);
\r
485 masterNoteIndex.get(i).setDeleted(l);
\r
486 i=masterNoteIndex.size();
\r
489 for (int i=0; i<getNoteIndex().size(); i++) {
\r
490 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
491 getNoteIndex().get(i).setActive(false);
\r
492 getNoteIndex().get(i).setDeleted(l);
\r
493 i=getNoteIndex().size();
\r
496 conn.getNoteTable().deleteNote(guid);
\r
497 reloadTrashCount();
\r
500 public void restoreNote(String guid) {
\r
501 trashCounterRunner.abortCount = true;
\r
502 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
503 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
504 masterNoteIndex.get(i).setActive(true);
\r
505 masterNoteIndex.get(i).setDeleted(0);
\r
506 i=masterNoteIndex.size();
\r
509 for (int i=0; i<getNoteIndex().size(); i++) {
\r
510 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
511 getNoteIndex().get(i).setActive(true);
\r
512 getNoteIndex().get(i).setDeleted(0);
\r
513 i=getNoteIndex().size();
\r
516 conn.getNoteTable().restoreNote(guid);
\r
517 reloadTrashCount();
\r
519 public void updateNote(Note n) {
\r
521 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
522 if (masterNoteIndex.get(i).getGuid().equals(n.getGuid())) {
\r
523 masterNoteIndex.remove(i);
\r
524 masterNoteIndex.add(n);
\r
527 for (int i=0; i<getNoteIndex().size(); i++) {
\r
528 if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {
\r
529 getNoteIndex().get(i).setActive(true);
\r
530 getNoteIndex().get(i).setDeleted(0);
\r
531 i=getNoteIndex().size();
\r
534 conn.getNoteTable().updateNote(n, true);
\r
537 public void addNote(Note n) {
\r
538 getNoteIndex().add(n);
\r
539 masterNoteIndex.add(n);
\r
542 public void expungeNote(String guid) {
\r
543 trashCounterRunner.abortCount = true;
\r
544 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
545 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
546 masterNoteIndex.remove(i);
\r
547 i=masterNoteIndex.size();
\r
550 for (int i=0; i<getNoteIndex().size(); i++) {
\r
551 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
552 getNoteIndex().remove(i);
\r
553 i=getNoteIndex().size();
\r
556 conn.getNoteTable().expungeNote(guid, false, true);
\r
557 reloadTrashCount();
\r
560 public void emptyTrash() {
\r
561 trashCounterRunner.abortCount = true;
\r
562 for (int i=masterNoteIndex.size()-1; i>=0; i--) {
\r
563 if (!masterNoteIndex.get(i).isActive()) {
\r
564 masterNoteIndex.remove(i);
\r
568 for (int i=getNoteIndex().size()-1; i>=0; i--) {
\r
569 if (!getNoteIndex().get(i).isActive()) {
\r
570 getNoteIndex().remove(i);
\r
574 conn.getNoteTable().expungeAllDeletedNotes();
\r
575 reloadTrashCount();
\r
577 // The trash counter thread has produced a result
\r
578 @SuppressWarnings("unused")
\r
579 private void trashSignalReceiver(Integer i) {
\r
581 trashSignal.countChanged.emit(i);
\r
583 // Update note contents
\r
584 public void updateNoteContent(String guid, String content) {
\r
585 logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");
\r
586 // EnmlConverter enml = new EnmlConverter(logger);
\r
587 // String text = enml.convert(guid, content);
\r
589 // Update the list tables
\r
590 /* for (int i=0; i<masterNoteIndex.size(); i++) {
\r
591 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
592 masterNoteIndex.get(i).setContent(text);
\r
593 i = masterNoteIndex.size();
\r
596 // Update the list tables
\r
597 for (int i=0; i<getNoteIndex().size(); i++) {
\r
598 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
599 getNoteIndex().get(i).setContent(text);
\r
600 i = getNoteIndex().size();
\r
604 // Check if any new tags were encountered
\r
605 /* if (enml.saveInvalidXML) {
\r
606 List<String> elements = Global.invalidElements;
\r
607 for (int i=0; i<elements.size(); i++) {
\r
608 conn.getInvalidXMLTable().addInvalidElement(elements.get(i));
\r
610 for (String key : Global.invalidAttributes.keySet()) {
\r
611 ArrayList<String> attributes = Global.invalidAttributes.get(key);
\r
612 for (int i=0; i<attributes.size(); i++) {
\r
613 conn.getInvalidXMLTable().addInvalidAttribute(key, attributes.get(i));
\r
618 saveRunner.addWork(guid, content);
\r
619 // conn.getNoteTable().updateNoteContent(guid, content);
\r
620 logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");
\r
622 // Update a note creation date
\r
623 public void updateNoteCreatedDate(String guid, QDateTime date) {
\r
624 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
625 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
626 masterNoteIndex.get(i).setCreated(date.toTime_t()*1000);
\r
627 i = masterNoteIndex.size();
\r
630 // Update the list tables
\r
631 for (int i=0; i<getNoteIndex().size(); i++) {
\r
632 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
633 getNoteIndex().get(i).setCreated(date.toTime_t()*1000);
\r
634 i = getNoteIndex().size();
\r
637 conn.getNoteTable().updateNoteCreatedDate(guid, date);
\r
639 // Subject date has been changed
\r
640 public void updateNoteSubjectDate(String guid, QDateTime date) {
\r
641 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
642 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
643 masterNoteIndex.get(i).getAttributes().setSubjectDate(date.toTime_t()*1000);
\r
644 i = masterNoteIndex.size();
\r
647 // Update the list tables
\r
648 for (int i=0; i<getNoteIndex().size(); i++) {
\r
649 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
650 getNoteIndex().get(i).setCreated(date.toTime_t()*1000);
\r
651 i = getNoteIndex().size();
\r
654 conn.getNoteTable().updateNoteSubjectDate(guid, date);
\r
656 // Author has changed
\r
657 public void updateNoteAuthor(String guid, String author) {
\r
658 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
659 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
660 masterNoteIndex.get(i).getAttributes().setAuthor(author);
\r
661 masterNoteIndex.get(i).getAttributes().setAltitudeIsSet(true);
\r
662 i = masterNoteIndex.size();
\r
665 // Update the list tables
\r
666 for (int i=0; i<getNoteIndex().size(); i++) {
\r
667 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
668 getNoteIndex().get(i).getAttributes().setAuthor(author);
\r
669 getNoteIndex().get(i).getAttributes().setAuthorIsSet(true);
\r
670 i = getNoteIndex().size();
\r
673 conn.getNoteTable().updateNoteAuthor(guid, author);
\r
675 // Author has changed
\r
676 public void updateNoteGeoTag(String guid, Double lon, Double lat, Double alt) {
\r
677 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
678 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
679 masterNoteIndex.get(i).getAttributes().setLongitude(lon);
\r
680 masterNoteIndex.get(i).getAttributes().setLongitudeIsSet(true);
\r
681 masterNoteIndex.get(i).getAttributes().setLatitude(lat);
\r
682 masterNoteIndex.get(i).getAttributes().setLatitudeIsSet(true);
\r
683 masterNoteIndex.get(i).getAttributes().setAltitude(alt);
\r
684 masterNoteIndex.get(i).getAttributes().setAltitudeIsSet(true);
\r
685 i = masterNoteIndex.size();
\r
688 // Update the list tables
\r
689 for (int i=0; i<getNoteIndex().size(); i++) {
\r
690 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
691 getNoteIndex().get(i).getAttributes().setLongitude(lon);
\r
692 getNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);
\r
693 getNoteIndex().get(i).getAttributes().setLatitude(lat);
\r
694 getNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);
\r
695 getNoteIndex().get(i).getAttributes().setAltitude(alt);
\r
696 getNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);
\r
697 i = getNoteIndex().size();
\r
700 conn.getNoteTable().updateNoteGeoTags(guid, lon, lat, alt);
\r
702 // Author has changed
\r
703 public void updateNoteSourceUrl(String guid, String url) {
\r
704 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
705 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
706 masterNoteIndex.get(i).getAttributes().setSourceURL(url);
\r
707 masterNoteIndex.get(i).getAttributes().setSourceURLIsSet(true);
\r
708 i = masterNoteIndex.size();
\r
711 // Update the list tables
\r
712 for (int i=0; i<getNoteIndex().size(); i++) {
\r
713 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
714 getNoteIndex().get(i).getAttributes().setSourceURL(url);
\r
715 getNoteIndex().get(i).getAttributes().setSourceURLIsSet(true);
\r
716 i = getNoteIndex().size();
\r
719 conn.getNoteTable().updateNoteSourceUrl(guid, url);
\r
721 // Update a note last changed date
\r
722 public void updateNoteAlteredDate(String guid, QDateTime date) {
\r
723 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
724 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
725 masterNoteIndex.get(i).setUpdated(date.toTime_t()*1000);
\r
726 i = masterNoteIndex.size();
\r
729 // Update the list tables
\r
730 for (int i=0; i<getNoteIndex().size(); i++) {
\r
731 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
732 getNoteIndex().get(i).setUpdated(date.toTime_t()*1000);
\r
733 i = getNoteIndex().size();
\r
737 conn.getNoteTable().updateNoteAlteredDate(guid, date);
\r
739 // Update a note title
\r
740 public void updateNoteTitle(String guid, String title) {
\r
741 logger.log(logger.HIGH, "Entering ListManager.updateNoteTitle");
\r
742 conn.getNoteTable().updateNoteTitle(guid, title);
\r
744 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
745 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
746 masterNoteIndex.get(i).setTitle(title);
\r
747 i = masterNoteIndex.size();
\r
750 // Update the list tables
\r
751 for (int i=0; i<getNoteIndex().size(); i++) {
\r
752 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
753 getNoteIndex().get(i).setTitle(title);
\r
754 i = getNoteIndex().size();
\r
758 logger.log(logger.HIGH, "Leaving ListManager.updateNoteTitle");
\r
760 // Update a note's notebook
\r
761 public void updateNoteNotebook(String guid, String notebookGuid) {
\r
762 logger.log(logger.HIGH, "Entering ListManager.updateNoteNotebook");
\r
763 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
764 if (masterNoteIndex.get(i).getGuid().equals(guid)) {
\r
765 masterNoteIndex.get(i).setNotebookGuid(notebookGuid);
\r
766 i=masterNoteIndex.size();
\r
769 for (int i=0; i<getNoteIndex().size(); i++) {
\r
770 if (getNoteIndex().get(i).getGuid().equals(guid)) {
\r
771 getNoteIndex().get(i).setNotebookGuid(notebookGuid);
\r
772 i=masterNoteIndex.size();
\r
775 conn.getNoteTable().updateNoteNotebook(guid, notebookGuid, true);
\r
776 logger.log(logger.HIGH, "Leaving ListManager.updateNoteNotebook");
\r
778 // Update a note sequence number
\r
779 public void updateNoteSequence(String guid, int sequence) {
\r
780 logger.log(logger.HIGH, "Entering ListManager.updateNoteSequence");
\r
782 conn.getNoteTable().updateNoteSequence(guid, sequence);
\r
784 for (int i=0; i<noteIndex.size(); i++) {
\r
785 if (noteIndex.get(i).getGuid().equals(guid)) {
\r
786 noteIndex.get(i).setUpdateSequenceNum(sequence);
\r
787 i=noteIndex.size()+1;
\r
790 logger.log(logger.HIGH, "Leaving ListManager.updateNoteSequence");
\r
792 public void updateNoteGuid(String oldGuid, String newGuid, boolean updateDatabase) {
\r
793 logger.log(logger.HIGH, "Entering ListManager.updateNoteGuid");
\r
795 if (updateDatabase)
\r
796 conn.getNoteTable().updateNoteGuid(oldGuid, newGuid);
\r
798 for (int i=0; i<masterNoteIndex.size(); i++) {
\r
799 if (masterNoteIndex.get(i).getGuid() != null && masterNoteIndex.get(i).getGuid().equals(oldGuid)) {
\r
800 masterNoteIndex.get(i).setGuid(newGuid);
\r
801 i=masterNoteIndex.size()+1;
\r
804 for (int i=0; i<noteIndex.size(); i++) {
\r
805 if (noteIndex.get(i).getGuid() != null && noteIndex.get(i).getGuid().equals(oldGuid)) {
\r
806 noteIndex.get(i).setGuid(newGuid);
\r
807 i=noteIndex.size()+1;
\r
810 logger.log(logger.HIGH, "Leaving ListManager.updateNoteGuid");
\r
815 //************************************************************************************
\r
816 //************************************************************************************
\r
818 //************************************************************************************
\r
819 //************************************************************************************
\r
820 // Update a tag sequence number
\r
821 public void updateTagSequence(String guid, int sequence) {
\r
822 logger.log(logger.HIGH, "Entering ListManager.updateTagSequence");
\r
824 conn.getTagTable().updateTagSequence(guid, sequence);
\r
825 for (int i=0; i<tagIndex.size(); i++) {
\r
826 if (tagIndex.get(i).getGuid().equals(guid)) {
\r
827 getTagIndex().get(i).setUpdateSequenceNum(sequence);
\r
828 i=tagIndex.size()+1;
\r
831 logger.log(logger.HIGH, "Leaving ListManager.updateTagSequence");
\r
833 // Update a tag guid number
\r
834 public void updateTagGuid(String oldGuid, String newGuid) {
\r
835 logger.log(logger.HIGH, "Entering ListManager.updateTagGuid");
\r
837 conn.getTagTable().updateTagGuid(oldGuid, newGuid);
\r
838 for (int i=0; i<tagIndex.size(); i++) {
\r
839 if (tagIndex.get(i).getGuid().equals(oldGuid)) {
\r
840 tagIndex.get(i).setGuid(newGuid);
\r
841 i=tagIndex.size()+1;
\r
844 logger.log(logger.HIGH, "Leaving ListManager.updateTagGuid");
\r
847 // Count tag results
\r
848 // @SuppressWarnings("unused")
\r
849 // private void reloadTagCount() {
\r
850 // tagCounterRunner.threadLock.lock();
\r
851 // tagCounterRunner.setNoteIndex(getNoteIndex());
\r
852 // QThreadPool.globalInstance().tryStart(tagCounterRunner);
\r
853 // tagCounterRunner.threadLock.unlock();
\r
856 //************************************************************************************
\r
857 //************************************************************************************
\r
858 //** Notebook functions
\r
859 //************************************************************************************
\r
860 //************************************************************************************
\r
861 // Delete a notebook
\r
862 public void deleteNotebook(String guid) {
\r
863 for (int i=0; i<getNotebookIndex().size(); i++) {
\r
864 if (getNotebookIndex().get(i).getGuid().equals(guid)) {
\r
865 getNotebookIndex().remove(i);
\r
866 i=masterNoteIndex.size();
\r
869 conn.getNotebookTable().expungeNotebook(guid, true);
\r
871 // Update a notebook sequence number
\r
872 public void updateNotebookSequence(String guid, int sequence) {
\r
873 logger.log(logger.HIGH, "Entering ListManager.updateNotebookSequence");
\r
875 conn.getNotebookTable().updateNotebookSequence(guid, sequence);
\r
877 for (int i=0; i<notebookIndex.size(); i++) {
\r
878 if (notebookIndex.get(i).getGuid().equals(guid)) {
\r
879 notebookIndex.get(i).setUpdateSequenceNum(sequence);
\r
880 i=notebookIndex.size()+1;
\r
883 logger.log(logger.HIGH, "Leaving ListManager.updateNotebookSequence");
\r
886 // Update a notebook Guid number
\r
887 public void updateNotebookGuid(String oldGuid, String newGuid) {
\r
888 logger.log(logger.HIGH, "Entering ListManager.updateNotebookGuid");
\r
890 conn.getNotebookTable().updateNotebookGuid(oldGuid, newGuid);
\r
892 for (int i=0; i<notebookIndex.size(); i++) {
\r
893 if (notebookIndex.get(i).getGuid().equals(oldGuid)) {
\r
894 notebookIndex.get(i).setGuid(newGuid);
\r
895 i=notebookIndex.size()+1;
\r
898 logger.log(logger.HIGH, "Leaving ListManager.updateNotebookGuid");
\r
903 //************************************************************************************
\r
904 //************************************************************************************
\r
905 //** Load and filter the note index
\r
906 //************************************************************************************
\r
907 //************************************************************************************
\r
908 // public void clearNoteIndexSearch() {
\r
909 // setNoteIndex(masterNoteIndex);
\r
911 // Load the note index based upon what the user wants.
\r
912 public void loadNotesIndex() {
\r
913 logger.log(logger.EXTREME, "Entering ListManager.loadNotesIndex()");
\r
914 tagCounterRunner.abortCount = true;
\r
915 notebookCounterRunner.abortCount = true;
\r
916 trashCounterRunner.abortCount = true;
\r
918 List<Note> index = new ArrayList<Note>();
\r
920 List<Note> matches;
\r
921 if (enSearchChanged || masterNoteIndex == null)
\r
922 matches = enSearch.matchWords();
\r
924 matches = masterNoteIndex;
\r
926 if (matches == null)
\r
927 matches = masterNoteIndex;
\r
929 for (int i=0; i<matches.size(); i++) {
\r
930 Note n = matches.get(i);
\r
931 boolean goodNotebook = false;
\r
932 boolean goodTag = false;
\r
933 boolean goodAttribute = false;
\r
934 boolean goodStatus = false;
\r
936 // Check note status
\r
937 if (!n.isActive() && Global.showDeleted)
\r
940 if (n.isActive() && !Global.showDeleted)
\r
942 // Begin filtering results
\r
944 goodNotebook = filterByNotebook(n.getNotebookGuid());
\r
946 goodTag = filterByTag(n.getTagGuids());
\r
948 goodAttribute = conn.getNoteTable().checkAttributeSelection(n);
\r
954 countNotebookResults(index);
\r
955 countTagResults(index);
\r
956 enSearchChanged = false;
\r
957 setNoteIndex(index);
\r
958 reloadTrashCount();
\r
959 logger.log(logger.EXTREME, "Leaving ListManager.loadNotesIndex()");
\r
961 public void countNotebookResults(List<Note> index) {
\r
962 logger.log(logger.EXTREME, "Entering ListManager.countNotebookResults()");
\r
963 if (!Global.mimicEvernoteInterface) {
\r
964 notebookCounterRunner.setNoteIndex(index);
\r
965 notebookCounterRunner.release(CounterRunner.NOTEBOOK);
\r
967 notebookCounterRunner.setNoteIndex(masterNoteIndex);
\r
968 notebookCounterRunner.release(CounterRunner.NOTEBOOK_ALL);
\r
970 logger.log(logger.EXTREME, "Leaving ListManager.countNotebookResults()");
\r
972 public void countTagResults(List<Note> index) {
\r
973 logger.log(logger.EXTREME, "Entering ListManager.countTagResults");
\r
974 if (!Global.tagBehavior().equalsIgnoreCase("DoNothing")) {
\r
975 tagCounterRunner.setNoteIndex(index);
\r
976 tagCounterRunner.release(CounterRunner.TAG);
\r
978 tagCounterRunner.setNoteIndex(null);
\r
979 tagCounterRunner.release(CounterRunner.TAG_ALL);
\r
981 logger.log(logger.EXTREME, "Leaving ListManager.countTagResults()");
\r
983 // Update the count of items in the trash
\r
984 public void reloadTrashCount() {
\r
985 logger.log(logger.EXTREME, "Entering ListManager.reloadTrashCount");
\r
986 trashCounterRunner.setNoteIndex(getNoteIndex());
\r
987 trashCounterRunner.release(CounterRunner.TRASH);
\r
988 logger.log(logger.EXTREME, "Leaving ListManager.reloadTrashCount");
\r
991 private boolean filterByNotebook(String guid) {
\r
992 boolean good = false;
\r
993 if (selectedNotebooks.size() == 0)
\r
995 if (!good && selectedNotebooks.contains(guid))
\r
998 for (int i=0; i<getArchiveNotebookIndex().size() && good; i++) {
\r
999 if (guid.equals(getArchiveNotebookIndex().get(i).getGuid())) {
\r
1006 private boolean filterByTag(List<String> noteTags) {
\r
1007 if (noteTags == null || selectedTags == null)
\r
1010 if (selectedTags.size() == 0)
\r
1013 for (int i=0; i<selectedTags.size(); i++) {
\r
1014 String selectedGuid = selectedTags.get(i);
\r
1015 if (noteTags.contains(selectedGuid))
\r
1023 public void updateNoteTitleColor(String guid, Integer color) {
\r
1024 titleColors.remove(guid);
\r
1025 titleColors.put(guid, color);
\r
1026 conn.getNoteTable().setNoteTitleColor(guid, color);
\r
1028 public void loadNoteTitleColors() {
\r
1029 List<Pair<String,Integer>> colors = conn.getNoteTable().getNoteTitleColors();
\r
1030 if (titleColors == null)
\r
1031 titleColors = new HashMap<String,Integer>();
\r
1033 titleColors.clear();
\r
1034 for (int i=0; i<colors.size(); i++) {
\r
1035 titleColors.put(colors.get(i).getFirst(), colors.get(i).getSecond());
\r
1039 //********************************************************************************
\r
1040 //********************************************************************************
\r
1041 //* Support signals from the index thread
\r
1042 //********************************************************************************
\r
1043 //********************************************************************************
\r
1044 // Reset a flag if an index is needed
\r
1045 public void setIndexNeeded(String guid, String type, Boolean b) {
\r
1046 if (Global.keepRunning && type.equalsIgnoreCase("content"))
\r
1047 conn.getNoteTable().setIndexNeeded(guid, false);
\r
1048 if (Global.keepRunning && type.equalsIgnoreCase("resource")) {
\r
1049 conn.getNoteTable().noteResourceTable.setIndexNeeded(guid, b);
\r
1055 public boolean threadCheck(int id) {
\r
1056 if (id == Global.notebookCounterThreadId)
\r
1057 return notebookThread.isAlive();
\r
1058 if (id == Global.tagCounterThreadId)
\r
1059 return tagThread.isAlive();
\r
1060 if (id == Global.trashCounterThreadId)
\r
1061 return trashThread.isAlive();
\r
1062 if (id == Global.saveThreadId)
\r
1063 return saveThread.isAlive();
\r
1069 //********************************************************************************
\r
1070 //********************************************************************************
\r
1071 //* Utility Functions
\r
1072 //********************************************************************************
\r
1073 //********************************************************************************
\r
1074 public void compactDatabase() {
\r
1075 conn.compactDatabase();
\r
1076 // IndexConnection idx = new IndexConnection(logger, "nevernote-compact");
\r
1078 // idx.dbShutdown();
\r
1081 // Rebuild the note HTML to something usable
\r
1082 public List<String> scanNoteForResources(Note n) {
\r
1083 logger.log(logger.HIGH, "Entering ListManager.scanNoteForResources");
\r
1084 logger.log(logger.EXTREME, "Note guid: " +n.getGuid());
\r
1085 QDomDocument doc = new QDomDocument();
\r
1086 QDomDocument.Result result = doc.setContent(n.getContent());
\r
1087 if (!result.success) {
\r
1088 logger.log(logger.MEDIUM, "Parse error when scanning note for resources.");
\r
1089 logger.log(logger.MEDIUM, "Note guid: " +n.getGuid());
\r
1093 List<String> returnArray = new ArrayList<String>();
\r
1094 QDomNodeList anchors = doc.elementsByTagName("en-media");
\r
1095 for (int i=0; i<anchors.length(); i++) {
\r
1096 QDomElement enmedia = anchors.at(i).toElement();
\r
1097 if (enmedia.hasAttribute("type")) {
\r
1098 QDomAttr hash = enmedia.attributeNode("hash");
\r
1099 returnArray.add(hash.value().toString());
\r
1102 logger.log(logger.HIGH, "Leaving ListManager.scanNoteForResources");
\r
1103 return returnArray;
\r
1105 // Given a list of tags, produce a string list of tag names
\r
1106 public String getTagNamesForNote(Note n) {
\r
1107 StringBuffer buffer = new StringBuffer(100);
\r
1108 Vector<String> v = new Vector<String>();
\r
1109 List<String> guids = n.getTagGuids();
\r
1111 if (guids == null)
\r
1114 for (int i=0; i<guids.size(); i++) {
\r
1115 v.add(getTagNameByGuid(guids.get(i)));
\r
1117 Comparator<String> comparator = Collections.reverseOrder();
\r
1118 Collections.sort(v,comparator);
\r
1119 Collections.reverse(v);
\r
1121 for (int i = 0; i<v.size(); i++) {
\r
1123 buffer.append(", ");
\r
1124 buffer.append(v.get(i));
\r
1127 return buffer.toString();
\r
1129 // Get a tag name when given a tag guid
\r
1130 public String getTagNameByGuid(String guid) {
\r
1131 for (int i=0; i<getTagIndex().size(); i++) {
\r
1132 String s = getTagIndex().get(i).getGuid();
\r
1133 if (s.equals(guid)) {
\r
1134 return getTagIndex().get(i).getName();
\r
1139 // For a notebook guid, return the name
\r
1140 public String getNotebookNameByGuid(String guid) {
\r
1141 if (notebookIndex == null)
\r
1143 for (int i=0; i<notebookIndex.size(); i++) {
\r
1144 String s = notebookIndex.get(i).getGuid();
\r
1145 if (s.equals(guid)) {
\r
1146 return notebookIndex.get(i).getName();
\r