OSDN Git Service

GitHub最初のコミット(SourceForge.jp 128fa38 2013-02-28 15:28:57 と同じ内容)
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / utilities / ListManager.java
1 /*
2  * This file is part of NixNote 
3  * Copyright 2009 Randy Baumgarte
4  * 
5  * This file may be licensed under the terms of of the
6  * GNU General Public License Version 2 (the ``GPL'').
7  *
8  * Software distributed under the License is distributed
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
10  * express or implied. See the GPL for the specific language
11  * governing rights and limitations.
12  *
13  * You should have received a copy of the GPL along with this
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html
15  * or write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18 */
19
20 package cx.fbn.nevernote.utilities;
21
22 import java.util.ArrayList;
23 import java.util.Calendar;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.GregorianCalendar;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Vector;
30
31 import com.evernote.edam.type.LinkedNotebook;
32 import com.evernote.edam.type.Note;
33 import com.evernote.edam.type.Notebook;
34 import com.evernote.edam.type.SavedSearch;
35 import com.evernote.edam.type.Tag;
36 import com.trolltech.qt.QThread;
37 import com.trolltech.qt.core.QDateTime;
38 import com.trolltech.qt.gui.QImage;
39 import com.trolltech.qt.gui.QPixmap;
40 import com.trolltech.qt.sql.QSqlQuery;
41 import com.trolltech.qt.xml.QDomAttr;
42 import com.trolltech.qt.xml.QDomDocument;
43 import com.trolltech.qt.xml.QDomElement;
44 import com.trolltech.qt.xml.QDomNodeList;
45
46 import cx.fbn.nevernote.Global;
47 import cx.fbn.nevernote.evernote.NoteMetadata;
48 import cx.fbn.nevernote.filters.EnSearch;
49 import cx.fbn.nevernote.filters.NotebookCounter;
50 import cx.fbn.nevernote.filters.TagCounter;
51 import cx.fbn.nevernote.gui.NoteTableModel;
52 import cx.fbn.nevernote.signals.NotebookSignal;
53 import cx.fbn.nevernote.signals.StatusSignal;
54 import cx.fbn.nevernote.signals.TagSignal;
55 import cx.fbn.nevernote.signals.ThreadSignal;
56 import cx.fbn.nevernote.signals.TrashSignal;
57 import cx.fbn.nevernote.sql.DatabaseConnection;
58 import cx.fbn.nevernote.threads.CounterRunner;
59 import cx.fbn.nevernote.threads.SaveRunner;
60
61
62 public class ListManager  {
63
64         
65         private final ApplicationLogger logger;  
66         DatabaseConnection                              conn;
67         QSqlQuery                                               deleteWords;
68         QSqlQuery                                               insertWords;
69         
70         private List<Tag>                               tagIndex;
71         private List<Notebook>                  notebookIndex;
72         private List<Notebook>                  archiveNotebookIndex;
73         private List<String>                    localNotebookIndex;
74         private List<LinkedNotebook>    linkedNotebookIndex;
75
76         private List<SavedSearch>               searchIndex;
77
78         private List<String>                    selectedNotebooks;
79         private final NoteTableModel                    noteModel;
80         
81         
82         private List<String>                    selectedTags;
83         private String                                  selectedSearch;
84         ThreadSignal                                    signals;
85         public StatusSignal                             status;
86         private final CounterRunner             notebookCounterRunner;
87         private final QThread                   notebookThread;
88         private final CounterRunner             tagCounterRunner;
89         private final QThread                   tagThread;
90         
91         private final CounterRunner             trashCounterRunner;
92         private final QThread                   trashThread;
93         public TrashSignal                              trashSignal;
94         
95         private List<NotebookCounter>   notebookCounter;                                // count of displayed notes in each notebook
96         private List<TagCounter>                tagCounter;                                             // count of displayed notes for each tag
97         
98         private EnSearch                                enSearch;
99         private boolean                                 enSearchChanged;
100         public HashMap<String, String>  wordMap;
101         public TagSignal                                tagSignal;
102         public NotebookSignal                   notebookSignal;
103         public boolean                                  refreshCounters;                        // Used to control when to recount lists
104         private int                                             trashCount;
105     public SaveRunner                           saveRunner;                                     // Thread used to save content.  Used because the xml conversion is slowwwww
106     QThread                                                     saveThread;
107         
108 //    private final HashMap<String, QImage> thumbnailList;
109     
110         // Constructor
111         public ListManager(DatabaseConnection d, ApplicationLogger l) {
112                 conn = d;
113                 logger = l;
114                         
115                 conn.getTagTable().cleanupTags();
116         status = new StatusSignal();
117                 signals = new ThreadSignal();
118                 
119                 // setup index locks
120                 enSearchChanged = false;
121                 
122                 // Setup arrays
123                 noteModel = new NoteTableModel(this);
124                 selectedTags = new ArrayList<String>();
125
126                 notebookCounter = new ArrayList<NotebookCounter>();
127                 tagCounter = new ArrayList<TagCounter>();
128                 selectedNotebooks = new ArrayList<String>();
129                                 
130                 reloadIndexes();
131                 
132                 notebookSignal = new NotebookSignal();
133                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
134                 notebookCounterRunner = new CounterRunner("notebook_counter.log", CounterRunner.NOTEBOOK, 
135                                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
136                                                 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
137                 notebookCounterRunner.setNoteIndex(getNoteIndex());
138                 notebookCounterRunner.notebookSignal.countsChanged.connect(this, "setNotebookCounter(List)");
139                 notebookThread = new QThread(notebookCounterRunner, "Notebook Counter Thread");
140                 notebookThread.start();
141                 
142                 tagSignal = new TagSignal();
143                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
144                 tagCounterRunner = new CounterRunner("tag_counter.log", CounterRunner.TAG, 
145                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
146                                 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
147                 tagCounterRunner.setNoteIndex(getNoteIndex());
148                 tagCounterRunner.tagSignal.countsChanged.connect(this, "setTagCounter(List)");
149                 tagThread = new QThread(tagCounterRunner, "Tag Counter Thread");
150                 tagThread.start();
151                 
152                 trashSignal = new TrashSignal();
153                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
154                 trashCounterRunner = new CounterRunner("trash_counter.log", CounterRunner.TRASH, 
155                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
156                                 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
157                 trashCounterRunner.trashSignal.countChanged.connect(this, "trashSignalReceiver(Integer)");
158                 trashThread = new QThread(trashCounterRunner, "Trash Counter Thread");
159                 trashThread.start();
160 //              reloadTrashCount();
161                 
162                 wordMap = new HashMap<String, String>();
163                 tagSignal = new TagSignal();
164                 
165                 logger.log(logger.EXTREME, "Setting save thread");
166                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
167                 saveRunner = new SaveRunner("saveRunner.log", 
168                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
169                                 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
170                 saveThread = new QThread(saveRunner, "Save Runner Thread");
171                 saveThread.start();
172                 
173 //              thumbnailList = conn.getNoteTable().getThumbnails();
174 //              thumbnailList = new HashMap<String,QImage>();
175                 
176                 linkedNotebookIndex = conn.getLinkedNotebookTable().getAll();
177                 loadNoteTitleColors();
178                 refreshCounters = true;
179                 refreshCounters();
180                                 
181         }
182         
183         public void stop() {
184                 saveRunner.addWork("stop", "");
185                 tagCounterRunner.release(CounterRunner.EXIT);
186                 notebookCounterRunner.release(CounterRunner.EXIT);
187                 trashCounterRunner.release(CounterRunner.EXIT);
188                 
189                 logger.log(logger.MEDIUM, "Waiting for notebookCounterThread to stop");                         
190                 try {
191                         notebookThread.join();
192                 } catch (InterruptedException e) {
193                         e.printStackTrace();
194                 }
195                 
196                 logger.log(logger.MEDIUM, "Waiting for tagCounterThread to stop");                      
197                 try {
198                         tagThread.join();
199                 } catch (InterruptedException e) {
200                         e.printStackTrace();
201                 }
202
203                 logger.log(logger.MEDIUM, "Waiting for trashThread to stop");                   
204                 try {
205                         trashThread.join();
206                 } catch (InterruptedException e) {
207                         e.printStackTrace();
208                 }
209
210
211                 logger.log(logger.MEDIUM, "Waiting for saveThread to stop");                    
212                 try {
213                         saveThread.join(0);
214                 } catch (InterruptedException e) {
215                         e.printStackTrace();
216                 }
217
218         }
219
220         //***************************************************************
221         //***************************************************************
222         //* Refresh lists after a db sync
223         //***************************************************************
224         //***************************************************************
225         public void refreshLists(Note n, boolean dirty, String content) {
226                 if (dirty) {
227 //                      conn.getNoteTable().updateNoteContent(n.getGuid(), n.getContent());
228                         saveRunner.addWork(n.getGuid(), content);
229                         conn.getNoteTable().updateNoteTitle(n.getGuid(), n.getTitle());
230                 }
231                 
232                 setSavedSearchIndex(conn.getSavedSearchTable().getAll());
233                 setTagIndex(conn.getTagTable().getAll());
234                 setNotebookIndex(conn.getNotebookTable().getAll());
235                 
236                 List<Notebook> local = conn.getNotebookTable().getAllLocal();
237                 localNotebookIndex = new ArrayList<String>();
238                 for (int i=0; i<local.size(); i++)
239                         localNotebookIndex.add(local.get(i).getGuid());
240                 
241                 noteModel.setMasterNoteIndex(conn.getNoteTable().getAllNotes());
242                 // For performance reasons, we didn't get the tags for every note individually.  We now need to 
243                 // get them
244                 List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();
245                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
246                         List<String> tags = new ArrayList<String>();
247                         List<String> names = new ArrayList<String>();
248                         for (int j=0; j<noteTags.size(); j++) {
249                                 if (getMasterNoteIndex().get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
250                                         tags.add(noteTags.get(j).tagGuid);
251                                         names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
252                                 }
253                         }
254                         
255                         getMasterNoteIndex().get(i).setTagGuids(tags);
256                         getMasterNoteIndex().get(i).setTagNames(names);
257                 }
258                 
259                 
260                 //setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
261                 
262                 linkedNotebookIndex = conn.getLinkedNotebookTable().getAll();
263                 
264                 enSearchChanged = true;
265         }
266
267         public void reloadTagIndex() {
268                 setTagIndex(conn.getTagTable().getAll());       
269         }
270         public void reloadIndexes() {
271                 //setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
272
273                 List<Notebook> local = conn.getNotebookTable().getAllLocal();
274                 localNotebookIndex = new ArrayList<String>();
275                 for (int i=0; i<local.size(); i++)
276                         localNotebookIndex.add(local.get(i).getGuid());
277                 
278                 reloadTagIndex();
279                 // Load notebooks
280                 setNotebookIndex(conn.getNotebookTable().getAll());
281                 // load archived notebooks (if note using the EN interface)
282                 setArchiveNotebookIndex(conn.getNotebookTable().getAllArchived());
283                 // load saved search index
284                 setSavedSearchIndex(conn.getSavedSearchTable().getAll());
285                 // Load search helper utility
286                 enSearch = new EnSearch(conn,  logger, "", getTagIndex(), Global.getRecognitionWeight());
287                 logger.log(logger.HIGH, "Building note index");
288
289 //              if (getMasterNoteIndex() == null) { 
290                         noteModel.setMasterNoteIndex(conn.getNoteTable().getAllNotes());
291 //              }
292                 // For performance reasons, we didn't get the tags for every note individually.  We now need to 
293                 // get them
294                 List<cx.fbn.nevernote.sql.NoteTagsRecord> noteTags = conn.getNoteTable().noteTagsTable.getAllNoteTags();
295                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
296                         List<String> tags = new ArrayList<String>();
297                         List<String> names = new ArrayList<String>();
298                         for (int j=0; j<noteTags.size(); j++) {
299                                 if (getMasterNoteIndex().get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
300                                         tags.add(noteTags.get(j).tagGuid);
301                                         names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
302                                 }
303                         }
304                         
305                         getMasterNoteIndex().get(i).setTagGuids(tags);
306                         getMasterNoteIndex().get(i).setTagNames(names);
307                 }
308                 
309                 setNoteIndex(getMasterNoteIndex());
310
311         }
312         
313         //***************************************************************
314         //***************************************************************
315         //* selected notebooks
316         //***************************************************************
317         //***************************************************************
318         // Return the selected notebook(s)
319         public List<String> getSelectedNotebooks() {
320                 return selectedNotebooks;
321         }
322         // Set the current selected notebook(s)
323         public void setSelectedNotebooks(List <String> s) {
324                 if (s == null) 
325                         s = new ArrayList<String>();
326                 selectedNotebooks = s;
327         }
328         
329                                 
330     //***************************************************************
331     //***************************************************************
332     //** These functions deal with setting & retrieving the master lists
333     //***************************************************************
334     //***************************************************************
335         // Get the note table model
336         public NoteTableModel getNoteTableModel() {
337                 return noteModel;
338         }
339         // save the saved search index
340         private void setSavedSearchIndex(List<SavedSearch> t) {
341                 searchIndex = t;
342         }
343         // Retrieve the Tag index
344         public List<SavedSearch> getSavedSearchIndex() {
345                 return searchIndex;
346
347         }
348         // save the tag index
349         private void setTagIndex(List<Tag> t) {
350                 tagIndex = t;
351         }       
352         // Retrieve the Tag index
353         public List<Tag> getTagIndex() {
354                 return tagIndex;
355         }
356         private void setNotebookIndex(List<Notebook> t) {
357                 notebookIndex = t;
358         }
359         private void setArchiveNotebookIndex(List<Notebook> t) {
360                 archiveNotebookIndex = t;
361         }
362         // Retrieve the Notebook index
363         public List<Notebook> getNotebookIndex() {
364                 return notebookIndex;
365
366         }
367         public List<LinkedNotebook> getLinkedNotebookIndex() {
368                 return linkedNotebookIndex;
369         }
370         public List<Notebook> getArchiveNotebookIndex() {
371                 return archiveNotebookIndex;
372         }
373         // Save the current note list
374         private void setNoteIndex(List<Note> n) {
375                 noteModel.setNoteIndex(n);
376                 refreshNoteMetadata();
377         }
378         public void refreshNoteMetadata() {
379                 noteModel.setNoteMetadata(conn.getNoteTable().getNotesMetaInformation());
380         }
381         // Update a note's meta data
382         public void updateNoteMetadata(NoteMetadata meta) {
383                 noteModel.metaData.remove(meta);
384                 noteModel.metaData.put(meta.getGuid(), meta);
385                 conn.getNoteTable().updateNoteMetadata(meta);
386         }
387         // Get the note index
388         public synchronized List<Note> getNoteIndex() {
389                 return noteModel.getNoteIndex();
390         }
391         // Save the count of notes per notebook
392         public void setNotebookCounter(List<NotebookCounter> n) {
393                 notebookCounter = n;
394                 notebookSignal.refreshNotebookTreeCounts.emit(getNotebookIndex(), notebookCounter);
395         }
396         public List<NotebookCounter> getNotebookCounter() {
397                 return notebookCounter;
398         }
399         // Save the count of notes for each tag
400         public void setTagCounter(List<TagCounter> n) {
401                 tagCounter = n;
402                 tagSignal.refreshTagTreeCounts.emit(tagCounter);
403         }
404         public List<TagCounter> getTagCounter() {
405                 return tagCounter;
406         }
407         public List<String> getLocalNotebooks() {
408                 return localNotebookIndex;
409         }
410
411 //      public void setUnsynchronizedNotes(List<String> l) {
412 //              noteModel.setUnsynchronizedNotes(l);
413 //      }
414         // Return a count of items in the trash
415         public int getTrashCount() {
416                 return trashCount;
417         }
418         // get the EnSearch variable
419         public EnSearch getEnSearch() {
420                 return enSearch;
421         }
422         public List<Note> getMasterNoteIndex() {
423                 return noteModel.getMasterNoteIndex();
424         }
425         // Thumbnails
426 //      public HashMap<String, QImage> getThumbnails() {
427 //              return thumbnailList;
428 //      }
429         public HashMap<String, NoteMetadata> getNoteMetadata() {
430                 return noteModel.metaData;
431         }
432         public QImage getThumbnail(String guid) {
433 //              if (getThumbnails().containsKey(guid))
434 //                      return getThumbnails().get(guid);
435                 
436                 QImage img = new QImage();
437                 img = QImage.fromData(conn.getNoteTable().getThumbnail(guid));
438                 if (img == null || img.isNull()) 
439                         return null;
440                 //getThumbnails().put(guid, img);
441                 return img;
442         }
443         public QPixmap getThumbnailPixmap(String guid) {
444 //              if (getThumbnails().containsKey(guid))
445 //                      return getThumbnails().get(guid);
446                 
447                 QPixmap img = new QPixmap();
448                 img.loadFromData(conn.getNoteTable().getThumbnail(guid));
449                 if (img == null || img.isNull()) 
450                         return null;
451                 //getThumbnails().put(guid, img);
452                 return img;
453         }
454     //***************************************************************
455     //***************************************************************
456     //** These functions deal with setting & retrieving filters
457     //***************************************************************
458     //***************************************************************
459         public void setEnSearch(String t) {
460                 enSearch = new EnSearch(conn,logger, t, getTagIndex(), Global.getRecognitionWeight());
461                 enSearchChanged = true;
462         }
463         // Save search tags
464         public void setSelectedTags(List<String> selectedTags) {
465                 this.selectedTags = selectedTags;
466         }
467         // Save seleceted search
468         public void setSelectedSavedSearch(String s) {
469                 this.selectedSearch = s;
470         }
471         // Get search tags
472         public List<String> getSelectedTags() {
473                 return selectedTags;
474         }
475         // Get saved search
476         public String getSelectedSearch() {
477                 return selectedSearch;
478         }
479         
480         
481         
482         
483     //***************************************************************
484     //***************************************************************
485     //** Note functions
486     //***************************************************************
487     //***************************************************************
488         // Save Note Tags
489         public void saveNoteTags(String noteGuid, List<String> tags, boolean isDirty) {\r
490                 logger.log(logger.HIGH, "Entering ListManager.saveNoteTags");
491                 // ICHANGED 同じタグが付けられた履歴を記録(必ずdeleteNoteTagの前にやる)
492                 for (int i = 0; i < tags.size(); i++) {
493                         String tagName = tags.get(i);
494                         for (int j = 0; j < tagIndex.size(); j++) {
495                                 if (tagIndex.get(j).getName().equalsIgnoreCase(tagName)) {
496                                         conn.getHistoryTable().addSameTagHistory(noteGuid, tagIndex.get(j).getGuid());
497                                 }
498                         }
499                 }
500                 
501                 String tagName;
502                 conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
503                 List<String> tagGuids = new ArrayList<String>();
504                 boolean newTagCreated = false;
505                 
506                 for (int i=0; i<tags.size(); i++) {
507                         tagName = tags.get(i);
508                         boolean found = false;
509                         for (int j=0; j<tagIndex.size(); j++) {
510                                 if (tagIndex.get(j).getName().equalsIgnoreCase(tagName)) {
511                                         conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, tagIndex.get(j).getGuid(), isDirty);\r
512                                         tagGuids.add(tagIndex.get(j).getGuid());
513                                         j=tagIndex.size()+1;
514                                         found = true;
515                                 }
516                         }
517                         if (!found) {
518                                 Tag nTag = new Tag();
519                                 nTag.setName(tagName);
520                                 Calendar currentTime = new GregorianCalendar();
521                                 Long l = new Long(currentTime.getTimeInMillis());
522                                 long prevTime = l;
523                                 while (l==prevTime) {
524                                         currentTime = new GregorianCalendar();
525                                         l=currentTime.getTimeInMillis();
526                                 }
527                                 String randint = new String(Long.toString(l));
528                         
529                                 nTag.setUpdateSequenceNum(0);
530                                 nTag.setGuid(randint);
531                                 conn.getTagTable().addTag(nTag, true);
532                                 getTagIndex().add(nTag);
533                                 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, nTag.getGuid(), isDirty);\r
534                                 tagGuids.add(nTag.getGuid());
535                                 newTagCreated = true;
536                         }
537                 }
538                 
539                 for (int i=0; i<getNoteIndex().size(); i++) {
540                         if (getNoteIndex().get(i).getGuid().equals(noteGuid)) {
541                                 getNoteIndex().get(i).setTagNames(tags);
542                                 getNoteIndex().get(i).setTagGuids(tagGuids);
543                                 i=getNoteIndex().size()+1;
544                         }
545                 }
546                 if (newTagCreated)
547                         tagSignal.listChanged.emit();
548                 logger.log(logger.HIGH, "Leaving ListManager.saveNoteTags");
549         }
550         // Delete a note
551         public void deleteNote(String guid) {
552                 trashCounterRunner.abortCount = true;
553                 Calendar currentTime = new GregorianCalendar();
554                 Long l = new Long(currentTime.getTimeInMillis());
555                 long prevTime = l;
556                 while (l==prevTime) {
557                         currentTime = new GregorianCalendar();
558                         l=currentTime.getTimeInMillis();
559                 }
560                 
561                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
562                         if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
563                                 getMasterNoteIndex().get(i).setActive(false);
564                                 getMasterNoteIndex().get(i).setDeleted(l);
565                                 i=getMasterNoteIndex().size();
566                         }
567                 }
568                 for (int i=0; i<getNoteIndex().size(); i++) {
569                         if (getNoteIndex().get(i).getGuid().equals(guid)) {
570                                 getNoteIndex().get(i).setActive(false);
571                                 getNoteIndex().get(i).setDeleted(l);
572                                 i=getNoteIndex().size();
573                         }
574                 }
575                 conn.getNoteTable().deleteNote(guid);
576                 reloadTrashCount();
577         }
578         // Delete a note
579         public void restoreNote(String guid) {
580                 trashCounterRunner.abortCount = true;
581                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
582                         if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
583                                 getMasterNoteIndex().get(i).setActive(true);
584                                 getMasterNoteIndex().get(i).setDeleted(0);
585                                 i=getMasterNoteIndex().size();
586                         }
587                 }
588                 for (int i=0; i<getNoteIndex().size(); i++) {
589                         if (getNoteIndex().get(i).getGuid().equals(guid)) {
590                                 getNoteIndex().get(i).setActive(true);
591                                 getNoteIndex().get(i).setDeleted(0);
592                                 i=getNoteIndex().size();
593                         }
594                 }
595                 conn.getNoteTable().restoreNote(guid);
596                 reloadTrashCount();
597         }
598         public void updateNote(Note n) {
599                 
600                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
601                         if (getMasterNoteIndex().get(i).getGuid().equals(n.getGuid())) {
602                                 getMasterNoteIndex().remove(i);
603                                 getMasterNoteIndex().add(n);
604                         }
605                 }
606                 for (int i=0; i<getNoteIndex().size(); i++) {
607                         if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {
608                                 getNoteIndex().get(i).setActive(true);
609                                 getNoteIndex().get(i).setDeleted(0);
610                                 i=getNoteIndex().size();
611                         }
612                 }
613                 conn.getNoteTable().updateNote(n);
614         }
615         // Add a note.  
616         public void addNote(Note n, NoteMetadata meta) {
617                 noteModel.addNote(n, meta);
618                 noteModel.metaData.put(n.getGuid(), meta);
619         }
620         // Expunge a note
621         public void expungeNote(String guid) {
622                 trashCounterRunner.abortCount = true;
623                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
624                         if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
625                                 getMasterNoteIndex().remove(i);
626                                 i=getMasterNoteIndex().size();
627                         }
628                 }
629                 for (int i=0; i<getNoteIndex().size(); i++) {
630                         if (getNoteIndex().get(i).getGuid().equals(guid)) {
631                                 getNoteIndex().remove(i);
632                                 i=getNoteIndex().size();
633                         }
634                 }
635                 conn.getNoteTable().expungeNote(guid, false, true);
636                 reloadTrashCount();
637         }
638         // Expunge a note
639         public void emptyTrash() {
640                 trashCounterRunner.abortCount = true;           
641                 for (int i=getMasterNoteIndex().size()-1; i>=0; i--) {
642                         if (!getMasterNoteIndex().get(i).isActive()) {
643                                 getMasterNoteIndex().remove(i);
644                         }
645                 }
646                 
647                 for (int i=getNoteIndex().size()-1; i>=0; i--) {
648                         if (!getNoteIndex().get(i).isActive()) {
649                                 getNoteIndex().remove(i);
650                         } 
651                 }
652
653                 conn.getNoteTable().expungeAllDeletedNotes();
654                 reloadTrashCount();
655         }
656         // The trash counter thread has produced a result
657         @SuppressWarnings("unused")
658         private void trashSignalReceiver(Integer i) {
659                 trashCount = i;
660                 trashSignal.countChanged.emit(i);
661         }
662         // Update note contents
663         public void updateNoteContent(String guid, String content) {
664                 logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");
665 //              EnmlConverter enml = new EnmlConverter(logger);
666 //              String text = enml.convert(guid, content);
667                 
668                 // Update the list tables 
669 /*              for (int i=0; i<masterNoteIndex.size(); i++) {
670                         if (masterNoteIndex.get(i).getGuid().equals(guid)) {
671                                 masterNoteIndex.get(i).setContent(text);
672                                 i = masterNoteIndex.size();
673                         }
674                 }
675                 // Update the list tables 
676                 for (int i=0; i<getNoteIndex().size(); i++) {
677                         if (getNoteIndex().get(i).getGuid().equals(guid)) {
678                                 getNoteIndex().get(i).setContent(text);
679                                 i = getNoteIndex().size();
680                         }
681                 }
682 */              
683                 // Check if any new tags were encountered
684 /*              if (enml.saveInvalidXML) {
685                         List<String> elements = Global.invalidElements;
686                         for (int i=0; i<elements.size(); i++) {
687                                 conn.getInvalidXMLTable().addInvalidElement(elements.get(i));
688                         }
689                         for (String key : Global.invalidAttributes.keySet()) {
690                                 ArrayList<String> attributes = Global.invalidAttributes.get(key);
691                                 for (int i=0; i<attributes.size(); i++) {
692                                         conn.getInvalidXMLTable().addInvalidAttribute(key, attributes.get(i));
693                                 }
694                         }
695                 }
696 */
697                 saveRunner.addWork(guid, content);
698 //              conn.getNoteTable().updateNoteContent(guid, content);
699                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");
700         }
701         // Update a note creation date
702         public void updateNoteCreatedDate(String guid, QDateTime date) {
703                 noteModel.updateNoteCreatedDate(guid, date);
704                 conn.getNoteTable().updateNoteCreatedDate(guid, date);
705         }
706         // Subject date has been changed
707         public void updateNoteSubjectDate(String guid, QDateTime date) {
708                 noteModel.updateNoteSubjectDate(guid, date);
709                 conn.getNoteTable().updateNoteSubjectDate(guid, date);
710         }
711         // Author has changed
712         public void updateNoteAuthor(String guid, String author) {
713                 noteModel.updateNoteAuthor(guid, author);
714                 conn.getNoteTable().updateNoteAuthor(guid, author);
715         }
716         // Author has changed
717         public void updateNoteGeoTag(String guid, Double lon, Double lat, Double alt) {
718                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
719                         if (getMasterNoteIndex().get(i).getGuid().equals(guid)) {
720                                 getMasterNoteIndex().get(i).getAttributes().setLongitude(lon);
721                                 getMasterNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);
722                                 getMasterNoteIndex().get(i).getAttributes().setLatitude(lat);
723                                 getMasterNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);
724                                 getMasterNoteIndex().get(i).getAttributes().setAltitude(alt);
725                                 getMasterNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);
726                                 i = getMasterNoteIndex().size();
727                         }       
728                 }
729                 // Update the list tables 
730                 for (int i=0; i<getNoteIndex().size(); i++) {
731                         if (getNoteIndex().get(i).getGuid().equals(guid)) {
732                                 getNoteIndex().get(i).getAttributes().setLongitude(lon);
733                                 getNoteIndex().get(i).getAttributes().setLongitudeIsSet(true);
734                                 getNoteIndex().get(i).getAttributes().setLatitude(lat);
735                                 getNoteIndex().get(i).getAttributes().setLatitudeIsSet(true);
736                                 getNoteIndex().get(i).getAttributes().setAltitude(alt);
737                                 getNoteIndex().get(i).getAttributes().setAltitudeIsSet(true);
738                                 i = getNoteIndex().size();
739                         }
740                 }
741                 conn.getNoteTable().updateNoteGeoTags(guid, lon, lat, alt);
742         }
743         // Source URL changed
744         public void updateNoteSourceUrl(String guid, String url) {
745                 noteModel.updateNoteSourceUrl(guid, url);
746                 conn.getNoteTable().updateNoteSourceUrl(guid, url);
747         }
748         // Update a note last changed date
749         public void updateNoteAlteredDate(String guid, QDateTime date) {
750                 noteModel.updateNoteChangedDate(guid, date);
751                 conn.getNoteTable().updateNoteAlteredDate(guid, date);
752         }
753         // Update a note title
754         public void updateNoteTitle(String guid, String title) {
755                 logger.log(logger.HIGH, "Entering ListManager.updateNoteTitle");
756                 conn.getNoteTable().updateNoteTitle(guid, title);
757                 noteModel.updateNoteTitle(guid, title);
758                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteTitle");
759         }
760         // Update a note's notebook
761         public void updateNoteNotebook(String guid, String notebookGuid) {
762                 logger.log(logger.HIGH, "Entering ListManager.updateNoteNotebook");
763                 noteModel.updateNoteNotebook(guid, notebookGuid);
764                 conn.getNoteTable().updateNoteNotebook(guid, notebookGuid, true);
765                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteNotebook");
766         }
767         // Update a note sequence number
768         public void updateNoteSequence(String guid, int sequence) {
769                 logger.log(logger.HIGH, "Entering ListManager.updateNoteSequence");
770
771                 conn.getNoteTable().updateNoteSequence(guid, sequence);
772                 
773                 for (int i=0; i<noteModel.getMasterNoteIndex().size(); i++) {
774                         if (noteModel.getMasterNoteIndex().get(i).getGuid().equals(guid)) {
775                                 noteModel.getMasterNoteIndex().get(i).setUpdateSequenceNum(sequence);
776                                 i=noteModel.getMasterNoteIndex().size()+1;
777                         }
778                 }
779                 
780                 for (int i=0; i<getNoteIndex().size(); i++) {
781                         if (getNoteIndex().get(i).getGuid().equals(guid)) {
782                                 getNoteIndex().get(i).setUpdateSequenceNum(sequence);
783                                 i=getNoteIndex().size()+1;
784                         }
785                 }
786                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteSequence");
787         }
788         public void updateNoteGuid(String oldGuid, String newGuid, boolean updateDatabase) {
789                 logger.log(logger.HIGH, "Entering ListManager.updateNoteGuid");
790                 if (updateDatabase) 
791                         conn.getNoteTable().updateNoteGuid(oldGuid, newGuid);
792                 noteModel.updateNoteGuid(oldGuid, newGuid);
793                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteGuid");
794
795         }
796
797         
798         //************************************************************************************
799         //************************************************************************************
800         //**  Tag functions
801         //************************************************************************************
802         //************************************************************************************  
803         // Update a tag sequence number
804         public void updateTagSequence(String guid, int sequence) {
805                 logger.log(logger.HIGH, "Entering ListManager.updateTagSequence");
806
807                 conn.getTagTable().updateTagSequence(guid, sequence);   
808                 for (int i=0; i<tagIndex.size(); i++) {
809                         if (tagIndex.get(i).getGuid().equals(guid)) {
810                                 getTagIndex().get(i).setUpdateSequenceNum(sequence);
811                                 i=tagIndex.size()+1;
812                         }
813                 }
814                 logger.log(logger.HIGH, "Leaving ListManager.updateTagSequence");
815         }
816         // Update a tag guid number
817         public void updateTagGuid(String oldGuid, String newGuid) {
818                 logger.log(logger.HIGH, "Entering ListManager.updateTagGuid");
819
820                 conn.getTagTable().updateTagGuid(oldGuid, newGuid);     
821                 for (int i=0; i<tagIndex.size(); i++) {
822                         if (tagIndex.get(i).getGuid().equals(oldGuid)) {
823                                 tagIndex.get(i).setGuid(newGuid);
824                                 i=tagIndex.size()+1;
825                         }
826                 }
827                 logger.log(logger.HIGH, "Leaving ListManager.updateTagGuid");
828
829         }
830         // Find all children for a tag
831         public List<Tag> findAllChildren(String guid) {
832                 List<Tag> tags = new ArrayList<Tag>();
833                 return findAllChildrenRecursive(guid, tags);
834         }
835         public List<Tag> findAllChildrenRecursive(String guid, List<Tag> tags) {
836                 
837                 // Start looping through the tags.  If we find a tag which has a parent that
838                 // matches guid, then we add it to the list of tags & search for its children.
839                 for (int i=0; i<getTagIndex().size(); i++) {
840                         if (getTagIndex().get(i).getParentGuid() != null && getTagIndex().get(i).getParentGuid().equals(guid)) {
841                                 tags.add(getTagIndex().get(i));
842                                 tags = findAllChildrenRecursive(getTagIndex().get(i).getGuid(), tags);
843                         }
844                 }
845                 return tags;
846         }
847         // Give a list of tags, does any of them match a child tag?
848         public boolean checkNoteForChildTags(String guid, List<String> noteTags) {
849                 boolean returnValue = false;
850                 List<Tag> children = findAllChildren(guid);
851                 for (int i=0; i<noteTags.size(); i++) {
852                         String noteTag = noteTags.get(i);
853                         for (int j=0; j<children.size(); j++) {
854                                 if (noteTag.equals(children.get(j).getGuid()))
855                                         return true;
856                         }
857                 }
858                 return returnValue;
859         }
860
861
862         //************************************************************************************
863         //************************************************************************************
864         //**  Notebook functions
865         //************************************************************************************
866         //************************************************************************************  
867         // Delete a notebook
868         public void deleteNotebook(String guid) {
869                 for (int i=0; i<getNotebookIndex().size(); i++) {
870                         if (getNotebookIndex().get(i).getGuid().equals(guid)) {
871                                 getNotebookIndex().remove(i);
872                                 i=getMasterNoteIndex().size();
873                         }
874                 }
875                 conn.getNotebookTable().expungeNotebook(guid, true);            
876         }
877         // Rename a stack
878         public void renameStack(String oldName, String newName) {
879                 for (int i=0; i<getNotebookIndex().size(); i++) {
880                         if (getNotebookIndex().get(i).getStack() != null && 
881                                         getNotebookIndex().get(i).getStack().equalsIgnoreCase(oldName)) {
882                                 getNotebookIndex().get(i).setStack(newName);
883                         }
884                 }       
885         }
886         // Update a notebook sequence number
887         public void updateNotebookSequence(String guid, int sequence) {
888                 logger.log(logger.HIGH, "Entering ListManager.updateNotebookSequence");
889
890                 conn.getNotebookTable().updateNotebookSequence(guid, sequence);
891                 
892                 for (int i=0; i<notebookIndex.size(); i++) {
893                         if (notebookIndex.get(i).getGuid().equals(guid)) {
894                                 notebookIndex.get(i).setUpdateSequenceNum(sequence);
895                                 i=notebookIndex.size()+1;
896                         }
897                 }
898                 logger.log(logger.HIGH, "Leaving ListManager.updateNotebookSequence");
899
900         }
901         // Update a notebook Guid number
902         public void updateNotebookGuid(String oldGuid, String newGuid) {
903                 logger.log(logger.HIGH, "Entering ListManager.updateNotebookGuid");
904
905                 conn.getNotebookTable().updateNotebookGuid(oldGuid, newGuid);
906                 
907                 for (int i=0; i<notebookIndex.size(); i++) {
908                         if (notebookIndex.get(i).getGuid().equals(oldGuid)) {
909                                 notebookIndex.get(i).setGuid(newGuid);
910                                 i=notebookIndex.size()+1;
911                         }
912                 }
913                 logger.log(logger.HIGH, "Leaving ListManager.updateNotebookGuid");
914
915         }
916         // Update a notebook Guid number
917         public void updateNotebookStack(String oldGuid, String stack) {
918                 logger.log(logger.HIGH, "Entering ListManager.updateNotebookGuid");
919
920                 conn.getNotebookTable().setStack(oldGuid, stack);
921                 
922                 for (int i=0; i<notebookIndex.size(); i++) {
923                         if (notebookIndex.get(i).getGuid().equals(oldGuid)) {
924                                 notebookIndex.get(i).setStack(stack);
925                                 i=notebookIndex.size()+1;
926                         }
927                 }
928                 logger.log(logger.HIGH, "Leaving ListManager.updateNotebookGuid");
929
930         }
931         
932         
933         //************************************************************************************
934         //************************************************************************************
935         //**  Load and filter the note index
936         //************************************************************************************
937         //************************************************************************************
938         
939         public void noteDownloaded(Note n) {
940                 boolean found = false;
941                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
942                         if (getMasterNoteIndex().get(i).getGuid().equals(n.getGuid())) {
943                                 getMasterNoteIndex().set(i,n);
944                                 found = true;
945                                 i=getMasterNoteIndex().size();
946                         }
947                 }
948                 
949                 if (!found)
950                         getMasterNoteIndex().add(n);
951                 
952                 for (int i=0; i<getNoteIndex().size(); i++) {
953                         if (getNoteIndex().get(i).getGuid().equals(n.getGuid())) {
954                                 if (filterRecord(getNoteIndex().get(i)))
955                                         getNoteIndex().add(n);
956                                 getNoteIndex().remove(i);
957                                 i=getNoteIndex().size();
958                         }
959                 }
960                 
961                 if (filterRecord(n))
962                         getNoteIndex().add(n);
963                 
964         }
965         // Check if a note matches the currently selected notebooks, tags, or attribute searches.
966         public boolean filterRecord(Note n) {
967                                 
968                 boolean goodNotebook = false;
969                 boolean goodTag = false;
970                 boolean goodStatus = false;
971                         
972                 // Check note status
973                 if (!n.isActive() && Global.showDeleted)
974                         return true;
975                 else {
976                         if (n.isActive() && !Global.showDeleted)
977                                 goodStatus = true;
978                 }
979                 
980                 // Begin filtering results
981                 if (goodStatus)
982                         goodNotebook = filterByNotebook(n.getNotebookGuid());
983                 if (goodNotebook) 
984                         goodTag = filterByTag(n.getTagGuids());
985                 if (goodTag) {
986                         boolean goodCreatedBefore = false;
987                         boolean goodCreatedSince = false;
988                         boolean goodChangedBefore = false;
989                         boolean goodChangedSince = false;
990                         boolean goodContains = false;
991                         if (!Global.createdBeforeFilter.hasSelection())
992                                 goodCreatedBefore = true;
993                         else
994                                 goodCreatedBefore = Global.createdBeforeFilter.check(n);
995                                 
996                         if (!Global.createdSinceFilter.hasSelection())
997                                 goodCreatedSince = true;
998                         else
999                                 goodCreatedSince = Global.createdSinceFilter.check(n);
1000                                 
1001                         if (!Global.changedBeforeFilter.hasSelection())
1002                                 goodChangedBefore = true;
1003                         else
1004                                 goodChangedBefore = Global.changedBeforeFilter.check(n);
1005                                 if (!Global.changedSinceFilter.hasSelection())
1006                                 goodChangedSince = true;
1007                         else
1008                                 goodChangedSince = Global.changedSinceFilter.check(n);
1009                         if (!Global.containsFilter.hasSelection())
1010                                 goodContains = true;
1011                         else
1012                                 goodContains = Global.containsFilter.check(conn.getNoteTable(), n);
1013                                 
1014                         if (goodCreatedSince && goodCreatedBefore && goodChangedSince && goodChangedBefore && goodContains)
1015                                 return true;
1016                 }       
1017                 return false;
1018         }
1019         
1020         // Trigger a recount of counters
1021         public void refreshCounters() {
1022 //              refreshCounters= false;
1023                 if (!refreshCounters)
1024                         return;
1025                 refreshCounters = false;
1026                 tagCounterRunner.abortCount = true;
1027                 notebookCounterRunner.abortCount = true;
1028                 trashCounterRunner.abortCount = true;
1029                 countNotebookResults(getNoteIndex());
1030                 countTagResults(getNoteIndex());
1031                 reloadTrashCount();
1032
1033         }
1034         // Load the note index based upon what the user wants.
1035         public void loadNotesIndex() {
1036                 logger.log(logger.EXTREME, "Entering ListManager.loadNotesIndex()");
1037                 
1038                 List<Note> matches;
1039                 if (enSearchChanged || getMasterNoteIndex() == null)
1040                         matches = enSearch.matchWords();
1041                 else
1042                         matches = getMasterNoteIndex();
1043                 
1044                 if (matches == null)
1045                         matches = getMasterNoteIndex();
1046                 
1047                 setNoteIndex(new ArrayList<Note>());
1048                 for (int i=0; i<matches.size(); i++) {
1049                         if (filterRecord(matches.get(i)))
1050                                 getNoteIndex().add(matches.get(i));
1051                 }
1052                 refreshCounters = true;
1053                 enSearchChanged = false;
1054                 logger.log(logger.EXTREME, "Leaving ListManager.loadNotesIndex()");
1055         }
1056         public void countNotebookResults(List<Note> index) {
1057                 logger.log(logger.EXTREME, "Entering ListManager.countNotebookResults()");
1058                 notebookCounterRunner.abortCount = true;
1059                 if (!Global.mimicEvernoteInterface) 
1060                         notebookCounterRunner.setNoteIndex(index);
1061                 else 
1062                         notebookCounterRunner.setNoteIndex(getMasterNoteIndex());
1063                 notebookCounterRunner.release(CounterRunner.NOTEBOOK);
1064                 logger.log(logger.EXTREME, "Leaving ListManager.countNotebookResults()");
1065         }
1066         public void countTagResults(List<Note> index) {
1067                 logger.log(logger.EXTREME, "Entering ListManager.countTagResults");
1068                 trashCounterRunner.abortCount = true;
1069                 if (!Global.tagBehavior().equalsIgnoreCase("DoNothing")) 
1070                         tagCounterRunner.setNoteIndex(index);
1071                 else
1072                         tagCounterRunner.setNoteIndex(getMasterNoteIndex());
1073                 tagCounterRunner.release(CounterRunner.TAG);
1074                 logger.log(logger.EXTREME, "Leaving ListManager.countTagResults()");
1075         }
1076         // Update the count of items in the trash
1077         public void reloadTrashCount() {
1078                 logger.log(logger.EXTREME, "Entering ListManager.reloadTrashCount");
1079                 trashCounterRunner.abortCount = true;
1080                 trashCounterRunner.setNoteIndex(getMasterNoteIndex());
1081                 trashCounterRunner.release(CounterRunner.TRASH);
1082                 logger.log(logger.EXTREME, "Leaving ListManager.reloadTrashCount");
1083         }       
1084         
1085         private boolean filterByNotebook(String guid) {
1086                 boolean good = false;
1087                 if (selectedNotebooks.size() == 0)
1088                         good = true;
1089                 if (!good && selectedNotebooks.contains(guid)) 
1090                         good = true;
1091
1092                 for (int i=0; i<getArchiveNotebookIndex().size() && good; i++) {
1093                         if (guid.equals(getArchiveNotebookIndex().get(i).getGuid())) {
1094                                 good = false;
1095                                 return good;
1096                         }
1097                 }
1098                 return good;
1099         }
1100         private boolean filterByTag(List<String> noteTags) {
1101                 // If either the note has no tags or there are
1102                 // no selected tags, then any note is good.
1103                 if (noteTags == null || selectedTags == null)
1104                         return true;
1105                 
1106                 // If there are no tags selected, then any note  is good
1107                 if (selectedTags.size() == 0) 
1108                         return true;
1109                 
1110                 // If ALL tags must be matched, then check ALL note tags, 
1111                 // otherwise we match on any criteria.
1112                 if (!Global.anyTagSelectionMatch()) {
1113                         for (int i=0; i<selectedTags.size(); i++) {
1114                                 String selectedGuid = selectedTags.get(i);
1115                                 boolean childMatch = false;
1116                                 // If we should include children in the results
1117                                 if (Global.includeTagChildren()) {
1118                                         childMatch = checkNoteForChildTags(selectedGuid, noteTags);
1119                                         // Do we have a match with this tag or any children
1120                                         if (!noteTags.contains(selectedGuid)&& !childMatch)
1121                                                 return false;
1122                                 } else {
1123                                         // Does this note have a matching tag
1124                                         if (!noteTags.contains(selectedGuid))
1125                                                 return false;
1126                                 }
1127                         }
1128                         return true;
1129                 } else {
1130                         // Any match is displayed.
1131                         for (int i=0; i<selectedTags.size(); i++) {
1132                                 String selectedGuid = selectedTags.get(i);
1133                                 // If we have a simple match, then we're good
1134                                 if (noteTags.contains(selectedGuid))
1135                                                 return true;
1136                                 // If we have a match with one of the children tags && we should include child tags
1137                                 if (Global.includeTagChildren() && checkNoteForChildTags(selectedGuid, noteTags))
1138                                         return true;
1139                         }
1140                         return false;
1141                 }
1142         }
1143
1144         public void setNoteSynchronized(String guid, boolean value) {
1145                 getNoteTableModel().updateNoteSyncStatus(guid, value);
1146         }
1147         
1148         public void updateNoteTitleColor(String guid, Integer color) {
1149                 NoteMetadata meta = getNoteMetadata().get(guid);
1150                 if (meta != null) {
1151                         noteModel.updateNoteTitleColor(guid, color);
1152                         meta.setColor(color);
1153                         conn.getNoteTable().updateNoteMetadata(meta);
1154                 }
1155         }
1156         public void loadNoteTitleColors() {
1157                 noteModel.setMetaData(getNoteMetadata());
1158         }
1159         
1160         //********************************************************************************
1161         //********************************************************************************
1162         //* Support signals from the index thread
1163         //********************************************************************************
1164         //********************************************************************************
1165         // Reset a flag if an index is needed
1166         public void setIndexNeeded(String guid, String type, Boolean b) {
1167                 if (Global.keepRunning && type.equalsIgnoreCase("content"))
1168                         conn.getNoteTable().setIndexNeeded(guid, false);
1169                 if (Global.keepRunning && type.equalsIgnoreCase("resource")) {
1170                         conn.getNoteTable().noteResourceTable.setIndexNeeded(guid, b);
1171                 }
1172         }
1173         
1174         public boolean threadCheck(int id) {
1175                 if (id == Global.notebookCounterThreadId) 
1176                         return notebookThread.isAlive();
1177                 if (id == Global.tagCounterThreadId) 
1178                         return tagThread.isAlive();
1179                 if (id == Global.trashCounterThreadId) 
1180                         return trashThread.isAlive();
1181                 if (id == Global.saveThreadId) 
1182                         return saveThread.isAlive();
1183                 return false;
1184         }
1185         
1186         
1187         
1188         //********************************************************************************
1189         //********************************************************************************
1190         //* Utility Functions
1191         //********************************************************************************
1192         //********************************************************************************
1193         public void compactDatabase() {
1194                 conn.compactDatabase();
1195 //              IndexConnection idx = new IndexConnection(logger, "nevernote-compact");
1196 //              idx.dbSetup();
1197 //              idx.dbShutdown();
1198         }
1199
1200         // Rebuild the note HTML to something usable
1201         public List<String> scanNoteForResources(Note n) {
1202                 logger.log(logger.HIGH, "Entering ListManager.scanNoteForResources");
1203                 logger.log(logger.EXTREME, "Note guid: " +n.getGuid());
1204                 QDomDocument doc = new QDomDocument();
1205                 QDomDocument.Result result = doc.setContent(n.getContent());
1206                 if (!result.success) {
1207                         logger.log(logger.MEDIUM, "Parse error when scanning note for resources.");
1208                         logger.log(logger.MEDIUM, "Note guid: " +n.getGuid());
1209                         return null;
1210                 }
1211                                 
1212                 List<String> returnArray = new ArrayList<String>();
1213                 QDomNodeList anchors = doc.elementsByTagName("en-media");
1214                 for (int i=0; i<anchors.length(); i++) {
1215                         QDomElement enmedia = anchors.at(i).toElement();
1216                         if (enmedia.hasAttribute("type")) {
1217                                 QDomAttr hash = enmedia.attributeNode("hash");
1218                                 returnArray.add(hash.value().toString());
1219                         }
1220                 }
1221                 logger.log(logger.HIGH, "Leaving ListManager.scanNoteForResources");
1222                 return returnArray;
1223         }
1224         // Given a list of tags, produce a string list of tag names
1225         public String getTagNamesForNote(Note n) {
1226                 StringBuffer buffer = new StringBuffer(100);
1227                 Vector<String> v = new Vector<String>();
1228                 List<String> guids = n.getTagGuids();
1229                 
1230                 if (guids == null) 
1231                         return "";
1232                 
1233                 for (int i=0; i<guids.size(); i++) {
1234                         v.add(getTagNameByGuid(guids.get(i)));
1235                 }
1236                 Comparator<String> comparator = Collections.reverseOrder();
1237                 Collections.sort(v,comparator);
1238                 Collections.reverse(v);
1239                 
1240                 for (int i = 0; i<v.size(); i++) {
1241                         if (i>0) 
1242                                 buffer.append(", ");
1243                         buffer.append(v.get(i));
1244                 }
1245                 
1246                 return buffer.toString();
1247         }
1248         // Get a tag name when given a tag guid
1249         public String getTagNameByGuid(String guid) {
1250                 for (int i=0; i<getTagIndex().size(); i++) {
1251                         String s = getTagIndex().get(i).getGuid();
1252                         if (s.equals(guid)) { 
1253                                 return getTagIndex().get(i).getName();
1254                         }
1255                 }
1256                 return "";
1257         }
1258         // For a notebook guid, return the name
1259         public String getNotebookNameByGuid(String guid) {
1260                 if (notebookIndex == null)
1261                         return null;
1262                 for (int i=0; i<notebookIndex.size(); i++) {
1263                         String s = notebookIndex.get(i).getGuid();
1264                         if (s.equals(guid)) { 
1265                                 return notebookIndex.get(i).getName();
1266                         }
1267                 }
1268                 return "";
1269         }
1270         
1271         
1272         // Reload the note's tag names.  This is called when a tag's name changes by
1273         // the user.  It updates all notes with that tag to the new tag name.
1274         public void reloadNoteTagNames(String tagGuid, String newName) {
1275                 
1276                 // Set the master index
1277                 for (int i=0; i<getMasterNoteIndex().size(); i++) {
1278                         for (int j=0; j<getMasterNoteIndex().get(i).getTagGuids().size(); j++) {
1279                                 if (getMasterNoteIndex().get(i).getTagGuids().get(j).equals(tagGuid)) {
1280                                         getMasterNoteIndex().get(i).getTagNames().set(j, newName);
1281                                 }
1282                         }
1283                 }
1284                 
1285                 // Set the current index
1286                 for (int i=0; i<getNoteIndex().size(); i++) {
1287                         for (int j=0; j<getNoteIndex().get(i).getTagGuids().size(); j++) {
1288                                 if (getNoteIndex().get(i).getTagGuids().get(j).equals(tagGuid)) {
1289                                         getNoteIndex().get(i).getTagNames().set(j, newName);
1290                                 }
1291                         }
1292                 }
1293         }
1294         
1295 }