OSDN Git Service

Allow users to specify sleep interval between looking for unindexed notes.
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / NeverNote.java
1 /*
2  * This file is part of NeverNote 
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 package cx.fbn.nevernote;
20 import java.awt.Desktop;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.security.MessageDigest;
25 import java.security.NoSuchAlgorithmException;
26 import java.sql.Connection;
27 import java.sql.DriverManager;
28 import java.sql.SQLException;
29 import java.text.SimpleDateFormat;
30 import java.util.ArrayList;
31 import java.util.Calendar;
32 import java.util.Collections;
33 import java.util.Comparator;
34 import java.util.Date;
35 import java.util.GregorianCalendar;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.SortedMap;
39 import java.util.Vector;
40
41 import org.apache.thrift.TException;
42
43 import com.evernote.edam.error.EDAMNotFoundException;
44 import com.evernote.edam.error.EDAMSystemException;
45 import com.evernote.edam.error.EDAMUserException;
46 import com.evernote.edam.notestore.NoteFilter;
47 import com.evernote.edam.notestore.NoteVersionId;
48 import com.evernote.edam.type.Data;
49 import com.evernote.edam.type.Note;
50 import com.evernote.edam.type.NoteAttributes;
51 import com.evernote.edam.type.Notebook;
52 import com.evernote.edam.type.QueryFormat;
53 import com.evernote.edam.type.Resource;
54 import com.evernote.edam.type.SavedSearch;
55 import com.evernote.edam.type.Tag;
56 import com.evernote.edam.type.User;
57 import com.trolltech.qt.QThread;
58 import com.trolltech.qt.core.QByteArray;
59 import com.trolltech.qt.core.QDataStream;
60 import com.trolltech.qt.core.QDateTime;
61 import com.trolltech.qt.core.QDir;
62 import com.trolltech.qt.core.QFile;
63 import com.trolltech.qt.core.QFileInfo;
64 import com.trolltech.qt.core.QFileSystemWatcher;
65 import com.trolltech.qt.core.QIODevice;
66 import com.trolltech.qt.core.QIODevice.OpenModeFlag;
67 import com.trolltech.qt.core.QLocale;
68 import com.trolltech.qt.core.QModelIndex;
69 import com.trolltech.qt.core.QSize;
70 import com.trolltech.qt.core.QTemporaryFile;
71 import com.trolltech.qt.core.QTextCodec;
72 import com.trolltech.qt.core.QThreadPool;
73 import com.trolltech.qt.core.QTimer;
74 import com.trolltech.qt.core.QTranslator;
75 import com.trolltech.qt.core.QUrl;
76 import com.trolltech.qt.core.Qt;
77 import com.trolltech.qt.core.Qt.ItemDataRole;
78 import com.trolltech.qt.core.Qt.SortOrder;
79 import com.trolltech.qt.core.Qt.WidgetAttribute;
80 import com.trolltech.qt.gui.QAbstractItemView;
81 import com.trolltech.qt.gui.QAbstractItemView.ScrollHint;
82 import com.trolltech.qt.gui.QAction;
83 import com.trolltech.qt.gui.QApplication;
84 import com.trolltech.qt.gui.QCloseEvent;
85 import com.trolltech.qt.gui.QColor;
86 import com.trolltech.qt.gui.QComboBox;
87 import com.trolltech.qt.gui.QComboBox.InsertPolicy;
88 import com.trolltech.qt.gui.QDesktopServices;
89 import com.trolltech.qt.gui.QDialog;
90 import com.trolltech.qt.gui.QFileDialog;
91 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
92 import com.trolltech.qt.gui.QFileDialog.FileMode;
93 import com.trolltech.qt.gui.QGridLayout;
94 import com.trolltech.qt.gui.QHBoxLayout;
95 import com.trolltech.qt.gui.QIcon;
96 import com.trolltech.qt.gui.QImage;
97 import com.trolltech.qt.gui.QLabel;
98 import com.trolltech.qt.gui.QListWidget;
99 import com.trolltech.qt.gui.QMainWindow;
100 import com.trolltech.qt.gui.QMenu;
101 import com.trolltech.qt.gui.QMessageBox;
102 import com.trolltech.qt.gui.QMessageBox.StandardButton;
103 import com.trolltech.qt.gui.QPixmap;
104 import com.trolltech.qt.gui.QPrintDialog;
105 import com.trolltech.qt.gui.QPrinter;
106 import com.trolltech.qt.gui.QProgressBar;
107 import com.trolltech.qt.gui.QSizePolicy;
108 import com.trolltech.qt.gui.QSizePolicy.Policy;
109 import com.trolltech.qt.gui.QSpinBox;
110 import com.trolltech.qt.gui.QSplashScreen;
111 import com.trolltech.qt.gui.QSplitter;
112 import com.trolltech.qt.gui.QStatusBar;
113 import com.trolltech.qt.gui.QSystemTrayIcon;
114 import com.trolltech.qt.gui.QTableWidgetItem;
115 import com.trolltech.qt.gui.QTextEdit;
116 import com.trolltech.qt.gui.QToolBar;
117 import com.trolltech.qt.gui.QTreeWidgetItem;
118 import com.trolltech.qt.webkit.QWebPage.WebAction;
119 import com.trolltech.qt.webkit.QWebSettings;
120 import com.trolltech.qt.xml.QDomAttr;
121 import com.trolltech.qt.xml.QDomDocument;
122 import com.trolltech.qt.xml.QDomElement;
123 import com.trolltech.qt.xml.QDomNodeList;
124
125 import cx.fbn.nevernote.config.FileManager;
126 import cx.fbn.nevernote.config.InitializationException;
127 import cx.fbn.nevernote.config.StartupConfig;
128 import cx.fbn.nevernote.dialog.AccountDialog;
129 import cx.fbn.nevernote.dialog.ConfigDialog;
130 import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
131 import cx.fbn.nevernote.dialog.DatabaseStatus;
132 import cx.fbn.nevernote.dialog.FindDialog;
133 import cx.fbn.nevernote.dialog.LoginDialog;
134 import cx.fbn.nevernote.dialog.NotebookArchive;
135 import cx.fbn.nevernote.dialog.NotebookEdit;
136 import cx.fbn.nevernote.dialog.OnlineNoteHistory;
137 import cx.fbn.nevernote.dialog.SavedSearchEdit;
138 import cx.fbn.nevernote.dialog.TagEdit;
139 import cx.fbn.nevernote.dialog.ThumbnailViewer;
140 import cx.fbn.nevernote.dialog.WatchFolder;
141 import cx.fbn.nevernote.filters.EnSearch;
142 import cx.fbn.nevernote.gui.AttributeTreeWidget;
143 import cx.fbn.nevernote.gui.BrowserWindow;
144 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
145 import cx.fbn.nevernote.gui.MainMenuBar;
146 import cx.fbn.nevernote.gui.NotebookTreeWidget;
147 import cx.fbn.nevernote.gui.PDFPreview;
148 import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
149 import cx.fbn.nevernote.gui.TableView;
150 import cx.fbn.nevernote.gui.TagTreeWidget;
151 import cx.fbn.nevernote.gui.Thumbnailer;
152 import cx.fbn.nevernote.gui.TrashTreeWidget;
153 import cx.fbn.nevernote.sql.DatabaseConnection;
154 import cx.fbn.nevernote.sql.WatchFolderRecord;
155 import cx.fbn.nevernote.threads.IndexRunner;
156 import cx.fbn.nevernote.threads.SyncRunner;
157 import cx.fbn.nevernote.utilities.AESEncrypter;
158 import cx.fbn.nevernote.utilities.ApplicationLogger;
159 import cx.fbn.nevernote.utilities.FileImporter;
160 import cx.fbn.nevernote.utilities.FileUtils;
161 import cx.fbn.nevernote.utilities.ListManager;
162 import cx.fbn.nevernote.utilities.SyncTimes;
163 import cx.fbn.nevernote.xml.ExportData;
164 import cx.fbn.nevernote.xml.ImportData;
165 import cx.fbn.nevernote.xml.XMLInsertHilight;
166
167
168 public class NeverNote extends QMainWindow{
169         
170         QStatusBar                              statusBar;                                      // Application status bar
171         
172         DatabaseConnection              conn;
173         
174         MainMenuBar                             menuBar;                                        // Main menu bar
175         FindDialog                              find;                                           // Text search in note dialog
176         List<String>                    emitLog;                                        // Messages displayed in the status bar;
177         QSystemTrayIcon                 trayIcon;                                       // little tray icon
178         QMenu                                   trayMenu;                                       // System tray menu
179         QAction                                 trayExitAction;                         // Exit the application
180         QAction                                 trayShowAction;                         // toggle the show/hide action          
181         QAction                                 trayAddNoteAction;                      // Add a note from the system tray
182         
183     NotebookTreeWidget          notebookTree;                           // List of notebooks
184     AttributeTreeWidget         attributeTree;                          // List of note attributes
185     TagTreeWidget                       tagTree;                                        // list of user created tags
186     SavedSearchTreeWidget       savedSearchTree;                        // list of saved searches
187     TrashTreeWidget                     trashTree;                                      // Trashcan
188     TableView                           noteTableView;                          //      List of notes (the widget).
189
190     public BrowserWindow        browserWindow;                          // Window containing browser & labels
191     public QToolBar             toolBar;                                        // The tool bar under the menu
192 //    QLineEdit                                 searchField;                            // The search filter bar on the toolbar
193     QComboBox                           searchField;                            // search filter bar on the toolbar;
194     boolean                                     searchPerformed = false;        // Search was done?
195     QProgressBar                        quotaBar;                                       // The current quota usage
196     
197     ApplicationLogger           logger;
198     List<String>                        selectedNotebookGUIDs;          // List of notebook GUIDs
199     List<String>                        selectedTagGUIDs;                       // List of selected tag GUIDs
200     List<String>                        selectedNoteGUIDs;                      // List of selected notes
201     String                                      selectedSavedSearchGUID;        // Currently selected saved searches
202     
203     NoteFilter                          filter;                                         // Note filter
204     String                                      currentNoteGuid;                        // GUID of the current note 
205     Note                                        currentNote;                            // The currently viewed note
206     boolean                                     noteDirty;                                      // Has the note been changed?
207     boolean                             inkNote;                    // if this is an ink note, it is read only
208   
209     ListManager                         listManager;                                    // DB runnable task
210     
211     List<QTemporaryFile>        tempFiles;                                      // Array of temporary files;
212     
213     QTimer                                      indexTimer;                                     // timer to start the index thread
214     IndexRunner                         indexRunner;                            // thread to index notes
215     QThread                                     indexThread;
216     
217     QTimer                                      syncTimer;                                      // Sync on an interval
218     QTimer                                      syncDelayTimer;                         // Sync delay to free up database
219     SyncRunner                          syncRunner;                                     // thread to do a sync.
220     QThread                                     syncThread;
221     QTimer                                      saveTimer;                                      // Timer to save note contents
222     
223     QTimer                                      authTimer;                                      // Refresh authentication
224     QTimer                                      externalFileSaveTimer;          // Save files altered externally
225     List<String>                        externalFiles;                          // External files to save later
226     List<String>                        importFilesKeep;                        // Auto-import files to save later
227     List<String>                        importFilesDelete;                      // Auto-import files to save later
228     
229     int                                         indexTime;                                      // how often to try and index
230     boolean                                     indexRunning;                           // Is indexing running?
231     boolean                                     indexDisabled;                          // Is indexing disabled?
232     
233     int                                         syncThreadsReady;                       // number of sync threads that are free
234     int                                         syncTime;                                       // Sync interval
235     boolean                                     syncRunning;                            // Is sync running?
236     boolean                                     automaticSync;                          // do sync automatically?
237     QTreeWidgetItem                     attributeTreeSelected;
238
239     QAction                             prevButton;                                     // Go to the previous item viewed
240     QAction                             nextButton;                                     // Go to the next item in the history
241     QAction                             downButton;                                     // Go to the next item in the list
242     QAction                             upButton;                                       // Go to the prev. item in the list;
243     QAction                             synchronizeButton;                      // Synchronize with Evernote
244     List<QIcon>                 synchronizeAnimation;           // Synchronize movie
245     QTimer                              synchronizeAnimationTimer;      // Timer to change animation button
246     int                                 synchronizeFrame;                       // Current frame being viewed
247     QAction                     printButton;                            // Print Button
248     QAction                             tagButton;                                      // Tag edit button
249     QAction                             attributeButton;                        // Attribute information button
250     QAction                     emailButton;                            // Email button
251     QAction                     deleteButton;                           // Delete button
252     QAction                             newButton;                                      // new Note Button;
253     QSpinBox                    zoomSpinner;                            // Zoom zoom
254     QAction                             searchClearButton;                      // Clear the search field
255     
256     QSplitter                   mainLeftRightSplitter;          // main splitter for left/right side
257     QSplitter                   leftSplitter1;                          // first left hand splitter
258     QSplitter                   browserIndexSplitter;           // splitter between note index & note text
259     
260     QFileSystemWatcher  importKeepWatcher;                      // Watch & keep auto-import
261     QFileSystemWatcher  importDeleteWatcher;            // Watch & Delete auto-import
262     List<String>                importedFiles;                          // History of imported files (so we don't import twice)
263     
264     OnlineNoteHistory   historyWindow;                          // online history window 
265     List<NoteVersionId> versions;                                       // history versions
266     
267     QTimer                              threadMonitorTimer;                     // Timer to watch threads.
268     int                                 dbThreadDeadCount=0;            // number of consecutive dead times for the db thread
269     int                                 syncThreadDeadCount=0;          // number of consecutive dead times for the sync thread
270     int                                 indexThreadDeadCount=0;         // number of consecutive dead times for the index thread
271     int                                 notebookThreadDeadCount=0;      // number of consecutive dead times for the notebook thread
272     int                                 tagDeadCount=0;                         // number of consecutive dead times for the tag thread
273     int                                 trashDeadCount=0;                       // number of consecutive dead times for the trash thread
274     int                                 saveThreadDeadCount=0;          // number of consecutive dead times for the save thread
275     
276     HashMap<String, String>             noteCache;                      // Cash of note content 
277     List<String>                historyGuids;                           // GUIDs of previously viewed items
278     int                                 historyPosition;                        // Position within the viewed items
279     boolean                             fromHistory;                            // Is this from the history queue?
280     String                              trashNoteGuid;                          // Guid to restore / set into or out of trash to save position
281     Thumbnailer                 preview;                                        // generate preview image
282     ThumbnailViewer             thumbnailViewer;                        // View preview thumbnail; 
283     
284     String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
285         
286         
287     //***************************************************************
288     //***************************************************************
289     //** Constructor & main entry point
290     //***************************************************************
291     //***************************************************************
292     // Application Constructor  
293         public NeverNote(DatabaseConnection dbConn)  {
294                 conn = dbConn;          
295
296                 thread().setPriority(Thread.MAX_PRIORITY);
297                 
298                 logger = new ApplicationLogger("nevernote.log");
299                 logger.log(logger.HIGH, "Starting Application");
300
301                 conn.checkDatabaseVersion();
302                 
303                 // Start building the invalid XML tables
304                 Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
305                 List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
306                 
307                 for (int i=0; i<elements.size(); i++) {
308                         Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i)));
309                 }
310                 
311                 logger.log(logger.EXTREME, "Starting GUI build");
312
313                 QTranslator qtTranslator = new QTranslator();
314                 qtTranslator.load("classpath:/translations/qt_" + QLocale.system().name() + ".qm");
315                 QApplication.instance().installTranslator(qtTranslator);
316
317                 QTranslator nevernoteTranslator = new QTranslator();
318                 nevernoteTranslator.load("classpath:/translations/nevernote_"+QLocale.system().name()+ ".qm");
319                 QApplication.instance().installTranslator(nevernoteTranslator);
320
321                 Global.originalPalette = QApplication.palette();
322                 QApplication.setStyle(Global.getStyle());
323                 if (Global.useStandardPalette())
324                         QApplication.setPalette(QApplication.style().standardPalette());
325         setWindowTitle("NeverNote");
326         
327         mainLeftRightSplitter = new QSplitter();
328         setCentralWidget(mainLeftRightSplitter);
329         leftSplitter1 = new QSplitter();
330         leftSplitter1.setOrientation(Qt.Orientation.Vertical);
331                 
332         browserIndexSplitter = new QSplitter();
333         browserIndexSplitter.setOrientation(Qt.Orientation.Vertical);
334         
335         //* Setup threads & thread timers
336         int indexRunnerCount = Global.getIndexThreads();
337         indexRunnerCount = 1;
338         QThreadPool.globalInstance().setMaxThreadCount(indexRunnerCount+5);     // increase max thread count
339
340                 logger.log(logger.EXTREME, "Building list manager");
341         listManager = new ListManager(conn, logger);
342         
343                 logger.log(logger.EXTREME, "Building index runners & timers");
344         indexRunner = new IndexRunner("indexRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
345                 indexThread = new QThread(indexRunner, "Index Thread");
346                 indexThread.start();
347                 
348         synchronizeAnimationTimer = new QTimer();
349         synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()");
350         
351                 indexTimer = new QTimer();
352                 indexTime = 1000*Global.getIndexThreadSleepInterval();  
353                 indexTimer.start(indexTime);  // Start indexing timer
354                 indexTimer.timeout.connect(this, "indexTimer()");
355                 indexDisabled = false;
356                 indexRunning = false;
357                                 
358                 logger.log(logger.EXTREME, "Setting sync thread & timers");
359                 syncThreadsReady=1;
360                 syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
361                 syncTime = new SyncTimes().timeValue(Global.getSyncInterval());
362                 syncTimer = new QTimer();
363                 syncTimer.timeout.connect(this, "syncTimer()");
364         syncRunner.status.message.connect(this, "setMessage(String)");
365         syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)");
366         syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()");
367         syncRunning = false;    
368                 if (syncTime > 0) {
369                         automaticSync = true;
370                         syncTimer.start(syncTime*60*1000);
371                 } else {
372                         automaticSync = false;
373                         syncTimer.stop();
374                 }
375                 syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount());
376                 syncThread = new QThread(syncRunner, "Synchronization Thread");
377                 syncThread.start();
378                 
379                 
380                 logger.log(logger.EXTREME, "Starting authentication timer");
381                 authTimer = new QTimer();
382                 authTimer.timeout.connect(this, "authTimer()");
383                 authTimer.start(1000*60*15);
384                 syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)");
385                 
386                 logger.log(logger.EXTREME, "Setting save note timer");
387                 saveTimer = new QTimer();
388                 saveTimer.timeout.connect(this, "saveNote()");
389                 if (Global.getAutoSaveInterval() > 0) {
390                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval()); 
391 //                      saveTimer.setInterval(1000*10); // auto save every 20 seconds;
392                         saveTimer.start();
393                 }
394                 listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)");
395                 
396                 logger.log(logger.EXTREME, "Starting external file monitor timer");
397                 externalFileSaveTimer = new QTimer();
398                 externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()");
399                 externalFileSaveTimer.setInterval(1000*5);   // save every 5 seconds;
400                 externalFiles = new ArrayList<String>();
401                 importFilesDelete = new ArrayList<String>();
402                 importFilesKeep = new ArrayList<String>();
403                 externalFileSaveTimer.start();
404                 
405         notebookTree = new NotebookTreeWidget();
406         attributeTree = new AttributeTreeWidget();
407         tagTree = new TagTreeWidget(conn);
408         savedSearchTree = new SavedSearchTreeWidget();
409         trashTree = new TrashTreeWidget();
410         noteTableView = new TableView(logger, listManager);
411         
412         QGridLayout leftGrid = new QGridLayout();
413         leftSplitter1.setLayout(leftGrid);
414         leftGrid.addWidget(notebookTree, 1, 1);
415         leftGrid.addWidget(tagTree,2,1);
416         leftGrid.addWidget(attributeTree,3,1);
417         leftGrid.addWidget(savedSearchTree,4,1);
418         leftGrid.addWidget(trashTree, 5, 1);
419         
420         // Setup the browser window
421         noteCache = new HashMap<String,String>();
422         browserWindow = new BrowserWindow(conn);
423
424         browserIndexSplitter.addWidget(noteTableView);
425         browserIndexSplitter.addWidget(browserWindow);
426         
427         mainLeftRightSplitter.addWidget(leftSplitter1);
428         mainLeftRightSplitter.addWidget(browserIndexSplitter);
429
430         searchField = new QComboBox();
431         searchField.setEditable(true);
432         searchField.activatedIndex.connect(this, "searchFieldChanged()");
433         searchField.setDuplicatesEnabled(false);
434         searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)");
435         
436         quotaBar = new QProgressBar();
437         
438         // Setup the thumbnail viewer
439         thumbnailViewer = new ThumbnailViewer();
440         thumbnailViewer.upArrow.connect(this, "upAction()");
441         thumbnailViewer.downArrow.connect(this, "downAction()");
442         thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
443         thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
444
445         listManager.loadNotesIndex();
446         initializeNotebookTree();
447         initializeTagTree();
448         initializeSavedSearchTree();
449         attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)");
450         attributeTreeSelected = null;
451         initializeNoteTable();    
452
453                 selectedNoteGUIDs = new ArrayList<String>();
454                 statusBar = new QStatusBar();
455                 setStatusBar(statusBar);
456                 menuBar = new MainMenuBar(this);
457                 emitLog = new ArrayList<String>();
458                 
459                 tagTree.setDeleteAction(menuBar.tagDeleteAction);
460                 tagTree.setEditAction(menuBar.tagEditAction);
461                 tagTree.setAddAction(menuBar.tagAddAction);
462                 tagTree.setVisible(Global.isWindowVisible("tagTree"));
463                 tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)");
464                 menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree"));
465                 listManager.tagSignal.listChanged.connect(this, "reloadTagTree()");
466         
467                 notebookTree.setDeleteAction(menuBar.notebookDeleteAction);
468                 notebookTree.setEditAction(menuBar.notebookEditAction);
469                 notebookTree.setAddAction(menuBar.notebookAddAction);
470                 notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
471                 notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
472                 menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
473
474                 savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
475                 savedSearchTree.setEditAction(menuBar.savedSearchEditAction);
476                 savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction);
477                 savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()");
478                 savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree"));
479                 menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree"));
480                         
481                 noteTableView.setAddAction(menuBar.noteAdd);
482                 noteTableView.setDeleteAction(menuBar.noteDelete);
483                 noteTableView.setRestoreAction(menuBar.noteRestoreAction);
484                 noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction);
485                 noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
486                 noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
487                 noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
488                 noteTableView.rowChanged.connect(this, "scrollToGuid(String)");
489                 noteTableView.resetViewport.connect(this, "scrollToCurrentGuid()");
490                 noteTableView.doubleClicked.connect(this, "listDoubleClick()");
491                 listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
492                 trashTree.load();
493         trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
494                 trashTree.setEmptyAction(menuBar.emptyTrashAction);
495                 trashTree.setVisible(Global.isWindowVisible("trashTree"));
496                 menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
497                 trashTree.updateCounts(listManager.getTrashCount());
498
499                 attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
500                 menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
501
502                 noteTableView.setVisible(Global.isWindowVisible("noteList"));
503                 menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList"));
504                 
505                 if (!Global.isWindowVisible("editorButtonBar"))
506                         toggleEditorButtonBar();
507                 if (!Global.isWindowVisible("leftPanel"))
508                         menuBar.hideLeftSide.setChecked(true);
509                 
510                 setMenuBar(menuBar);
511                 setupToolBar();
512                 find = new FindDialog();
513                 find.getOkButton().clicked.connect(this, "doFindText()");
514                 
515                 // Setup the tray icon menu bar
516                 trayShowAction = new QAction("Show/Hide", this);
517                 trayExitAction = new QAction("Exit", this);
518                 trayAddNoteAction = new QAction("Add Note", this);
519                 
520                 trayExitAction.triggered.connect(this, "close()");
521                 trayAddNoteAction.triggered.connect(this, "addNote()");
522                 trayShowAction.triggered.connect(this, "trayToggleVisible()");
523                 
524                 trayMenu = new QMenu(this);
525                 trayMenu.addAction(trayAddNoteAction);
526                 trayMenu.addAction(trayShowAction);
527                 trayMenu.addAction(trayExitAction);
528                 
529                 
530                 trayIcon = new QSystemTrayIcon(this);
531                 trayIcon.setToolTip("NeverNote");
532                 trayIcon.setContextMenu(trayMenu);
533                 trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
534
535                 currentNoteGuid="";
536                 currentNoteGuid = Global.getLastViewedNoteGuid();
537         historyGuids = new ArrayList<String>();
538         historyPosition = 0;
539         fromHistory = false;
540                 noteDirty = false;
541                 if (!currentNoteGuid.trim().equals("")) {
542                         currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
543                 }
544                 
545                 noteIndexUpdated(true);
546                 showColumns();
547                 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
548                 if (menuBar.showEditorBar.isChecked())
549                 showEditorButtons();
550                 tagIndexUpdated(true);
551                 savedSearchIndexUpdated();
552                 notebookIndexUpdated();
553                 updateQuotaBar();
554         setupSyncSignalListeners();        
555         setupBrowserSignalListeners();
556         setupIndexListeners();
557               
558         
559         tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
560         tagTree.showAllTags(true);
561
562                 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
563         setWindowIcon(appIcon);
564         trayIcon.setIcon(appIcon);
565         if (Global.showTrayIcon())
566                 trayIcon.show();
567         else
568                 trayIcon.hide();
569         
570         scrollToGuid(currentNoteGuid);
571         if (Global.automaticLogin()) {
572                 remoteConnect();
573                 if (Global.isConnected)
574                         syncTimer();
575         }
576         setupFolderImports();
577         
578         loadStyleSheet();
579         restoreWindowState();
580         
581         if (Global.mimicEvernoteInterface) {
582                 notebookTree.selectGuid("");
583         }
584         
585         threadMonitorTimer = new QTimer();
586         threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
587         threadMonitorTimer.start(1000*10);  // Check for threads every 10 seconds;              
588         
589         historyGuids.add(currentNoteGuid);
590         historyPosition = 1;
591         
592         int sortCol = Global.getSortColumn();
593                 int sortOrder = Global.getSortOrder();
594                 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
595         }
596
597         
598         // Main entry point
599         public static void main(String[] args) {
600                 QApplication.initialize(args);
601                 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
602                 QSplashScreen splash = new QSplashScreen(pixmap);
603                 boolean showSplash;
604                 
605                 DatabaseConnection dbConn;
606
607         try {
608             initializeGlobalSettings(args);
609
610             showSplash = Global.isWindowVisible("SplashScreen");
611             if (showSplash)
612                 splash.show();
613
614             dbConn = setupDatabaseConnection();
615
616             // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
617             Global.getFileManager().purgeResDirectory();
618
619         } catch (InitializationException e) {
620             // Fatal
621             e.printStackTrace();
622             QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
623             return;
624         }
625
626         NeverNote application = new NeverNote(dbConn);
627
628                 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
629                 if (Global.wasWindowMaximized())
630                         application.showMaximized();
631                 else
632                         application.show();
633                 if (showSplash)
634                         splash.finish(application);
635                 QApplication.exec();
636                 System.out.println("Goodbye.");
637                 QApplication.exit();
638         }
639
640     /**
641      * Open the internal database, or create if not present
642      *
643      * @throws InitializationException when opening the database fails, e.g. because another process has it locked
644      */
645     private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
646         ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
647         DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
648
649         if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
650             boolean goodCheck = false;
651             while (!goodCheck) {
652                 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
653                 dialog.exec();
654                 if (!dialog.okPressed())
655                     System.exit(0);
656                 Global.cipherPassword = dialog.getPassword();
657                 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
658                         Global.getDatabaseUserPassword(), Global.cipherPassword);
659             }
660         }
661         return dbConn;
662     }
663
664         private static void initializeGlobalSettings(String[] args) throws InitializationException {
665                 StartupConfig startupConfig = new StartupConfig();
666
667                 for (String arg : args) {
668                         String lower = arg.toLowerCase();
669                         if (lower.startsWith("--name="))
670                                 startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
671                         if (lower.startsWith("--home="))
672                                 startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
673                         if (lower.startsWith("--disable-viewing"))
674                                 startupConfig.setDisableViewing(true);
675                 }
676
677                 Global.setup(startupConfig);
678         }
679
680     // Exit point
681         @Override
682         public void closeEvent(QCloseEvent event) {     
683                 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
684                 waitCursor(true);
685                 
686                 if (currentNote!= null & browserWindow!=null) {
687                         if (!currentNote.getTitle().equals(browserWindow.getTitle()))
688                                 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle());
689                 }
690                 saveNote();
691                 setMessage(tr("Beginning shutdown."));
692
693                 externalFileEditedSaver();
694                 if (Global.isConnected && Global.synchronizeOnClose()) {
695                         setMessage(tr("Performing synchronization before closing."));
696                         syncRunner.addWork("SYNC");
697                 }
698                 setMessage("Closing Program.");
699                 threadMonitorTimer.stop();
700
701                 syncRunner.addWork("STOP");
702                 indexRunner.addWork("STOP");
703                 saveNote();
704                 listManager.stop();
705                 saveWindowState();
706
707                 if (tempFiles != null)
708                         tempFiles.clear();
709
710                 browserWindow.noteSignal.tagsChanged.disconnect();
711                 browserWindow.noteSignal.titleChanged.disconnect();
712                 browserWindow.noteSignal.noteChanged.disconnect();
713                 browserWindow.noteSignal.notebookChanged.disconnect();
714                 browserWindow.noteSignal.createdDateChanged.disconnect();
715                 browserWindow.noteSignal.alteredDateChanged.disconnect();
716                 syncRunner.searchSignal.listChanged.disconnect();
717                 syncRunner.tagSignal.listChanged.disconnect();
718         syncRunner.notebookSignal.listChanged.disconnect();
719         syncRunner.noteIndexSignal.listChanged.disconnect();
720
721
722                 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
723                 Global.setColumnPosition("noteTableCreationPosition", position);
724                 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
725                 Global.setColumnPosition("noteTableTagPosition", position);
726                 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
727                 Global.setColumnPosition("noteTableNotebookPosition", position);
728                 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
729                 Global.setColumnPosition("noteTableChangedPosition", position);
730                 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
731                 Global.setColumnPosition("noteTableAuthorPosition", position);
732                 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
733                 Global.setColumnPosition("noteTableSourceUrlPosition", position);
734                 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
735                 Global.setColumnPosition("noteTableSubjectDatePosition", position);
736                 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
737                 Global.setColumnPosition("noteTableTitlePosition", position);
738                 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
739                 Global.setColumnPosition("noteTableSynchronizedPosition", position);
740
741                 Global.saveWindowVisible("toolBar", toolBar.isVisible());
742                 saveNoteIndexWidth();
743                 
744                 int width = notebookTree.columnWidth(0);
745                 Global.setColumnWidth("notebookTreeName", width);
746                 width = tagTree.columnWidth(0);
747                 Global.setColumnWidth("tagTreeName", width);
748                 
749                 Global.saveWindowMaximized(isMaximized());
750                 Global.saveCurrentNoteGuid(currentNoteGuid);
751                         
752                 int sortCol = noteTableView.proxyModel.sortColumn();
753                 int sortOrder = noteTableView.proxyModel.sortOrder().value();
754                 Global.setSortColumn(sortCol);
755                 Global.setSortOrder(sortOrder);
756                 
757                 hide();
758                 trayIcon.hide();
759                 Global.keepRunning = false;
760                 try {
761                         logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
762                         indexRunner.thread().join(50);
763                         logger.log(logger.MEDIUM, "Index thread has stopped");
764                 } catch (InterruptedException e1) {
765                         e1.printStackTrace();
766                 }
767                 if (!syncRunner.isIdle()) {
768                         try {
769                                 logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
770                                 syncThread.join();
771                                 logger.log(logger.MEDIUM, "Sync thread has stopped");
772                         } catch (InterruptedException e1) {
773                                 e1.printStackTrace();
774                         }
775                 }
776
777                 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
778         }
779
780         public void setMessage(String s) {
781                 logger.log(logger.HIGH, "Entering NeverNote.setMessage");
782                 logger.log(logger.HIGH, "Message: " +s);
783                 statusBar.showMessage(s);
784                 emitLog.add(s);
785                 logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
786         }
787                 
788         private void waitCursor(boolean wait) {
789 //              if (wait)
790 //                      QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
791 //              else
792 //                      QApplication.restoreOverrideCursor();
793         }
794         
795         private void setupIndexListeners() {
796                 indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
797                 indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
798 //                      indexRunner.threadSignal.indexNeeded.connect(listManager, "setIndexNeeded(String, String, Boolean)");
799         }
800         private void setupSyncSignalListeners() {
801                 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
802         syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
803         syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
804         syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
805         syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
806         
807                 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
808                 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
809                 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
810                 
811                 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
812                 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
813                 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
814                 syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)");
815                 
816                 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
817         }
818         
819         private void setupBrowserSignalListeners() {
820                 
821                 browserWindow.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
822                 browserWindow.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
823             browserWindow.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
824                 //browserWindow.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
825             browserWindow.noteSignal.noteChanged.connect(this, "setNoteDirty()");
826             browserWindow.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
827             browserWindow.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
828             browserWindow.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
829             browserWindow.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
830             browserWindow.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
831             browserWindow.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
832             browserWindow.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
833             browserWindow.noteSignal.geoChanged.connect(this, "setNoteDirty()");
834             browserWindow.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
835             browserWindow.focusLost.connect(this, "saveNote()");
836             browserWindow.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
837         }
838
839         
840
841         //***************************************************************
842         //***************************************************************
843         //* Settings and look & feel
844         //***************************************************************
845         //***************************************************************
846         @SuppressWarnings("unused")
847         private void settings() {
848                 logger.log(logger.HIGH, "Entering NeverNote.settings");
849         ConfigDialog settings = new ConfigDialog(this);
850         String dateFormat = Global.getDateFormat();
851         String timeFormat = Global.getTimeFormat();
852         
853                 indexTime = 1000*Global.getIndexThreadSleepInterval();  
854                 indexTimer.start(indexTime);  // reset indexing timer
855         
856         settings.exec();
857         if (Global.showTrayIcon())
858                 trayIcon.show();
859         else
860                 trayIcon.hide();
861         showColumns();
862         if (menuBar.showEditorBar.isChecked())
863                 showEditorButtons();
864         
865         // Reset the save timer
866         if (Global.getAutoSaveInterval() > 0)
867                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
868         else
869                 saveTimer.stop();
870         
871         // This is a hack to force a reload of the index in case the date or time changed.
872 //        if (!dateFormat.equals(Global.getDateFormat()) ||
873 //                      !timeFormat.equals(Global.getTimeFormat())) {
874                 noteCache.clear();
875                 noteIndexUpdated(true);
876 //        }
877         
878         logger.log(logger.HIGH, "Leaving NeverNote.settings");
879         }
880         // Restore things to the way they were
881         private void restoreWindowState() {
882                 // We need to name things or this doesn't work.
883                 setObjectName("NeverNote");
884                 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
885                 browserIndexSplitter.setObjectName("browserIndexSplitter");
886                 leftSplitter1.setObjectName("leftSplitter1");   
887                 
888                 // Restore the actual positions.
889                 restoreGeometry(Global.restoreGeometry(objectName()));
890         mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
891         browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
892         leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
893        
894         }
895         // Save window positions for the next start
896         private void saveWindowState() {
897                 Global.saveGeometry(objectName(), saveGeometry());
898                 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
899                 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
900                 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
901         }    
902         // Load the style sheet
903         private void loadStyleSheet() {
904                 String fileName = Global.getFileManager().getQssDirPath("default.qss");
905                 QFile file = new QFile(fileName);
906                 file.open(OpenModeFlag.ReadOnly);
907                 String styleSheet = file.readAll().toString();
908                 file.close();
909                 setStyleSheet(styleSheet);
910         }
911         // Save column widths for the next time
912         private void saveNoteIndexWidth() {
913                 int width;
914         width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
915         Global.setColumnWidth("noteTableCreationPosition", width);
916                 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
917                 Global.setColumnWidth("noteTableChangedPosition", width);
918                 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
919                 Global.setColumnWidth("noteTableGuidPosition", width);
920                 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
921                 Global.setColumnWidth("noteTableNotebookPosition", width);
922                 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
923                 Global.setColumnWidth("noteTableTagPosition", width);
924                 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
925                 Global.setColumnWidth("noteTableTitlePosition", width);
926                 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
927                 Global.setColumnWidth("noteTableSourceUrlPosition", width);
928                 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
929                 Global.setColumnWidth("noteTableAuthorPosition", width);
930                 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
931                 Global.setColumnWidth("noteTableSubjectDatePosition", width);
932                 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
933                 Global.setColumnWidth("noteTableSynchronizedPosition", width);
934         }
935         
936         
937     //***************************************************************
938     //***************************************************************
939     //** These functions deal with Notebook menu items
940     //***************************************************************
941     //***************************************************************
942     // Setup the tree containing the user's notebooks.
943     private void initializeNotebookTree() {       
944         logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
945         notebookTree.itemSelectionChanged.connect(this, "notebookTreeSelection()");
946         listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
947  //     notebookTree.resize(Global.getSize("notebookTree"));
948         logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
949     }   
950     // Listener when a notebook is selected
951         private void notebookTreeSelection() {
952                 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
953
954                 clearTrashFilter();
955                 clearAttributeFilter();
956                 clearSavedSearchFilter();
957                 if (Global.mimicEvernoteInterface) {
958                         clearTagFilter();
959                         searchField.clear();
960                 }
961                 menuBar.noteRestoreAction.setVisible(false);            
962         menuBar.notebookEditAction.setEnabled(true);
963         menuBar.notebookDeleteAction.setEnabled(true);
964         List<QTreeWidgetItem> selections = notebookTree.selectedItems();
965         QTreeWidgetItem currentSelection;
966         selectedNotebookGUIDs.clear();
967         if (!Global.mimicEvernoteInterface) {
968                 for (int i=0; i<selections.size(); i++) {
969                         currentSelection = selections.get(i);
970                         selectedNotebookGUIDs.add(currentSelection.text(2));
971                 }
972         
973                 
974                 // There is the potential for no notebooks to be selected if this 
975                 // happens then we make it look like all notebooks were selecetd.
976                 // If that happens, just select the "all notebooks"
977                 selections = notebookTree.selectedItems();
978                 if (selections.size()==0) {
979                         selectedNotebookGUIDs.clear();
980                         menuBar.notebookEditAction.setEnabled(false);
981                         menuBar.notebookDeleteAction.setEnabled(false);
982                 }
983         } else {
984                 String guid = "";
985                 if (selections.size() > 0)
986                         guid = (selections.get(0).text(2));
987                 if (!guid.equals(""))
988                         selectedNotebookGUIDs.add(guid);
989         }
990         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
991         listManager.loadNotesIndex();
992         noteIndexUpdated(false);
993                 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
994
995     }
996     private void clearNotebookFilter() {
997         notebookTree.blockSignals(true);
998         notebookTree.clearSelection();
999                 menuBar.noteRestoreAction.setVisible(false);
1000         menuBar.notebookEditAction.setEnabled(false);
1001         menuBar.notebookDeleteAction.setEnabled(false);
1002         selectedNotebookGUIDs.clear();
1003         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1004         notebookTree.blockSignals(false);
1005     }
1006         // Triggered when the notebook DB has been updated
1007         private void notebookIndexUpdated() {
1008                 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1009                 if (selectedNotebookGUIDs == null)
1010                         selectedNotebookGUIDs = new ArrayList<String>();
1011                 List<Notebook> books = conn.getNotebookTable().getAll();
1012                 for (int i=books.size()-1; i>=0; i--) {
1013                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1014                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1015                                         books.remove(i);
1016                                         j=listManager.getArchiveNotebookIndex().size();
1017                                 }
1018                         }
1019                 }
1020                 
1021                 
1022                 listManager.countNotebookResults(listManager.getNoteIndex());
1023                 notebookTree.blockSignals(true);
1024         notebookTree.load(books, listManager.getLocalNotebooks());
1025         for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1026                 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1027                 if (!found)
1028                         selectedNotebookGUIDs.remove(i);
1029         }
1030         notebookTree.blockSignals(false);
1031         
1032                 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1033     }
1034     // Show/Hide note information
1035         private void toggleNotebookWindow() {
1036                 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1037         if (notebookTree.isVisible())
1038                 notebookTree.hide();
1039         else
1040                 notebookTree.show();
1041         menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1042         Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1043         logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1044     }   
1045         // Add a new notebook
1046         @SuppressWarnings("unused")
1047         private void addNotebook() {
1048                 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1049                 NotebookEdit edit = new NotebookEdit();
1050                 edit.setNotebooks(listManager.getNotebookIndex());
1051                 edit.exec();
1052         
1053                 if (!edit.okPressed())
1054                         return;
1055         
1056                 Calendar currentTime = new GregorianCalendar();
1057                 Long l = new Long(currentTime.getTimeInMillis());
1058                 String randint = new String(Long.toString(l));
1059         
1060                 Notebook newBook = new Notebook();
1061                 newBook.setUpdateSequenceNum(0);
1062                 newBook.setGuid(randint);
1063                 newBook.setName(edit.getNotebook());
1064                 newBook.setServiceCreated(new Date().getTime());
1065                 newBook.setServiceUpdated(new Date().getTime());
1066                 newBook.setDefaultNotebook(false);
1067                 newBook.setPublished(false);
1068                 
1069                 listManager.getNotebookIndex().add(newBook);
1070                 if (edit.isLocal())
1071                         listManager.getLocalNotebooks().add(newBook.getGuid());
1072                 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1073                 notebookIndexUpdated();
1074                 listManager.countNotebookResults(listManager.getNoteIndex());
1075 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1076                 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1077         }
1078         // Edit an existing notebook
1079         @SuppressWarnings("unused")
1080         private void editNotebook() {
1081                 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1082                 NotebookEdit edit = new NotebookEdit();
1083                 edit.setTitle(tr("Edit Notebook"));
1084                 edit.setLocalCheckboxEnabled(false);
1085                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1086                 QTreeWidgetItem currentSelection;
1087                 currentSelection = selections.get(0);
1088                 edit.setNotebook(currentSelection.text(0));
1089                 edit.setNotebooks(listManager.getNotebookIndex());
1090                 edit.exec();
1091         
1092                 if (!edit.okPressed())
1093                         return;
1094         
1095                 String guid = currentSelection.text(2);
1096                 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1097                 currentSelection.setText(0, edit.getNotebook());
1098                 
1099                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1100                         if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1101                                 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1102                                 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1103                                 i=listManager.getNotebookIndex().size();
1104                         }
1105                 }
1106                 
1107                 // Build a list of non-closed notebooks
1108                 List<Notebook> nbooks = new ArrayList<Notebook>();
1109                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1110                         boolean found=false;
1111                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1112                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1113                                         found = true;
1114                         }
1115                         if (!found)
1116                                 nbooks.add(listManager.getNotebookIndex().get(i));
1117                 }
1118                 
1119                 browserWindow.setNotebookList(nbooks);
1120                 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1121         }
1122         // Delete an existing notebook
1123         @SuppressWarnings("unused")
1124         private void deleteNotebook() {
1125                 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1126                 boolean assigned = false;
1127                 // Check if any notes have this notebook
1128                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1129         for (int i=0; i<selections.size(); i++) {
1130                 QTreeWidgetItem currentSelection;
1131                 currentSelection = selections.get(i);
1132                 String guid = currentSelection.text(2);
1133                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
1134                         String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
1135                         if (noteGuid.equals(guid)) {
1136                                 assigned = true;
1137                                 j=listManager.getNoteIndex().size();
1138                                 i=selections.size();
1139                         }
1140                 }
1141         }
1142                 if (assigned) {
1143                         QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+
1144                                         "Please delete the notes or move them to another notebook before deleting any notebooks."));
1145                         return;
1146                 }
1147                 
1148                 if (conn.getNotebookTable().getAll().size() == 1) {
1149                         QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook."));
1150                         return;
1151                 }
1152         
1153         // If all notebooks are clear, verify the delete
1154                 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected notebooks?"),
1155                         QMessageBox.StandardButton.Yes, 
1156                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1157                         return;
1158                 }
1159                 
1160                 // If confirmed, delete the notebook
1161         for (int i=selections.size()-1; i>=0; i--) {
1162                 QTreeWidgetItem currentSelection;
1163                 currentSelection = selections.get(i);
1164                 String guid = currentSelection.text(2);
1165                 conn.getNotebookTable().expungeNotebook(guid, true);
1166                 listManager.deleteNotebook(guid);
1167         }
1168 //        for (int i=<dbRunner.getLocalNotebooks().size()-1; i>=0; i--) {
1169  //             if (dbRunner.getLocalNotebooks().get(i).equals(arg0))
1170  //       }
1171         notebookTreeSelection();
1172         notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
1173         listManager.countNotebookResults(listManager.getNoteIndex());
1174 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1175         logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1176         }
1177         // A note's notebook has been updated
1178         @SuppressWarnings("unused")
1179         private void updateNoteNotebook(String guid, String notebookGuid) {
1180                 
1181                 // Update the list manager
1182                 listManager.updateNoteNotebook(guid, notebookGuid);
1183                 listManager.countNotebookResults(listManager.getNoteIndex());
1184 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());    
1185                 
1186                 // Find the name of the notebook
1187                 String notebookName = null;
1188                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1189                         if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
1190                                 notebookName = listManager.getNotebookIndex().get(i).getName();
1191                                 break;
1192                         }
1193                 }
1194                 
1195                 // If we found the name, update the browser window
1196                 if (notebookName != null) {
1197                         updateListNoteNotebook(guid, notebookName);
1198                         if (guid.equals(currentNoteGuid)) {
1199                                 int pos =  browserWindow.notebookBox.findText(notebookName);
1200                                 if (pos >=0)
1201                                         browserWindow.notebookBox.setCurrentIndex(pos);
1202                         }
1203                 }
1204                 
1205                 // If we're dealing with the current note, then we need to be sure and update the notebook there
1206                 if (guid.equals(currentNoteGuid)) {
1207                         if (currentNote != null) {
1208                                 currentNote.setNotebookGuid(notebookGuid);
1209                         }
1210                 }
1211         }
1212         // Open/close notebooks
1213         @SuppressWarnings("unused")
1214         private void closeNotebooks() {
1215                 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
1216                 na.exec();
1217                 if (!na.okClicked())
1218                         return;
1219                 
1220                 waitCursor(true);
1221                 listManager.getArchiveNotebookIndex().clear();
1222                 
1223                 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
1224                         String text = na.getClosedBookList().takeItem(i).text();
1225                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1226                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1227                                         Notebook n = listManager.getNotebookIndex().get(j);
1228                                         conn.getNotebookTable().setArchived(n.getGuid(),true);
1229                                         listManager.getArchiveNotebookIndex().add(n);
1230                                         j=listManager.getNotebookIndex().size();
1231                                 }
1232                         }
1233                 }
1234                 
1235                 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
1236                         String text = na.getOpenBookList().takeItem(i).text();
1237                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1238                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1239                                         Notebook n = listManager.getNotebookIndex().get(j);
1240                                         conn.getNotebookTable().setArchived(n.getGuid(),false);
1241                                         j=listManager.getNotebookIndex().size();
1242                                 }
1243                         }
1244                 }
1245                 notebookTreeSelection();
1246                 listManager.loadNotesIndex();
1247                 notebookIndexUpdated();
1248                 noteIndexUpdated(false);
1249 //              noteIndexUpdated(false);
1250                 
1251                 // Build a list of non-closed notebooks
1252                 List<Notebook> nbooks = new ArrayList<Notebook>();
1253                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1254                         boolean found=false;
1255                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1256                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1257                                         found = true;
1258                         }
1259                         if (!found)
1260                                 nbooks.add(listManager.getNotebookIndex().get(i));
1261                 }
1262                 waitCursor(false);
1263                 browserWindow.setNotebookList(nbooks);
1264         }
1265
1266         
1267         
1268         
1269         
1270     //***************************************************************
1271     //***************************************************************
1272     //** These functions deal with Tag menu items
1273     //***************************************************************
1274     //***************************************************************
1275         // Add a new notebook
1276         @SuppressWarnings("unused")
1277         private void addTag() {
1278                 logger.log(logger.HIGH, "Inside NeverNote.addTag");
1279                 TagEdit edit = new TagEdit();
1280                 edit.setTagList(listManager.getTagIndex());
1281                 edit.exec();
1282         
1283                 if (!edit.okPressed())
1284                         return;
1285         
1286                 Calendar currentTime = new GregorianCalendar();
1287                 Long l = new Long(currentTime.getTimeInMillis());
1288                 String randint = new String(Long.toString(l));
1289         
1290                 Tag newTag = new Tag();
1291                 newTag.setUpdateSequenceNum(0);
1292                 newTag.setGuid(randint);
1293                 newTag.setName(edit.getTag());
1294                 conn.getTagTable().addTag(newTag, true);
1295                 listManager.getTagIndex().add(newTag);
1296                 reloadTagTree();
1297                 
1298                 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
1299         }
1300         private void reloadTagTree() {
1301                 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
1302                 tagIndexUpdated(false);
1303                 boolean filter = false;
1304                 listManager.countTagResults(listManager.getNoteIndex());
1305                 if (notebookTree.selectedItems().size() > 0 
1306                                                   && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
1307                                                   filter = true;
1308                 if (tagTree.selectedItems().size() > 0)
1309                         filter = true;
1310                 tagTree.showAllTags(!filter);
1311                 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
1312         }
1313         // Edit an existing tag
1314         @SuppressWarnings("unused")
1315         private void editTag() {
1316                 logger.log(logger.HIGH, "Entering NeverNote.editTag");
1317                 TagEdit edit = new TagEdit();
1318                 edit.setTitle("Edit Tag");
1319                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1320                 QTreeWidgetItem currentSelection;
1321                 currentSelection = selections.get(0);
1322                 edit.setTag(currentSelection.text(0));
1323                 edit.setTagList(listManager.getTagIndex());
1324                 edit.exec();
1325         
1326                 if (!edit.okPressed())
1327                         return;
1328         
1329                 String guid = currentSelection.text(2);
1330                 currentSelection.setText(0,edit.getTag());
1331                 
1332                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1333                         if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
1334                                 listManager.getTagIndex().get(i).setName(edit.getTag());
1335                                 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
1336                                 updateListTagName(guid);
1337                                 if (currentNote != null && currentNote.getTagGuids().contains(guid))
1338                                         browserWindow.setTag(getTagNamesForNote(currentNote));
1339                                 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
1340                                 return;
1341                         }
1342                 }
1343                 browserWindow.setTag(getTagNamesForNote(currentNote));
1344                 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
1345         }
1346         // Delete an existing tag
1347         @SuppressWarnings("unused")
1348         private void deleteTag() {
1349                 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
1350                 
1351                 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"),
1352                         QMessageBox.StandardButton.Yes, 
1353                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1354                                                         return;
1355                 }
1356                 
1357                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1358         for (int i=selections.size()-1; i>=0; i--) {
1359                 QTreeWidgetItem currentSelection;
1360                 currentSelection = selections.get(i);                   
1361                 removeTagItem(currentSelection.text(2));
1362         }
1363         tagIndexUpdated(true);
1364         tagTreeSelection();
1365         listManager.countTagResults(listManager.getNoteIndex());
1366 //              tagTree.updateCounts(listManager.getTagCounter());
1367         logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
1368         }
1369         // Remove a tag tree item.  Go recursively down & remove the children too
1370         private void removeTagItem(String guid) {
1371         for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {             
1372                 String parent = listManager.getTagIndex().get(j).getParentGuid();
1373                 if (parent != null && parent.equals(guid)) {            
1374                         //Remove this tag's children
1375                         removeTagItem(listManager.getTagIndex().get(j).getGuid());
1376                 }
1377         }
1378         //Now, remove this tag
1379         removeListTagName(guid);
1380         conn.getTagTable().expungeTag(guid, true);                      
1381         for (int a=0; a<listManager.getTagIndex().size(); a++) {
1382                 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
1383                         listManager.getTagIndex().remove(a);
1384                         return;
1385                 }
1386         }
1387         }
1388         // Setup the tree containing the user's tags
1389     private void initializeTagTree() {
1390         logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
1391         tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
1392         listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
1393         logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
1394     }
1395     // Listener when a tag is selected
1396         private void tagTreeSelection() {
1397         logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
1398                 
1399         clearTrashFilter();
1400         clearAttributeFilter();
1401         clearSavedSearchFilter();
1402         
1403                 menuBar.noteRestoreAction.setVisible(false);
1404                 
1405         List<QTreeWidgetItem> selections = tagTree.selectedItems();
1406         QTreeWidgetItem currentSelection;
1407         selectedTagGUIDs.clear();
1408         for (int i=0; i<selections.size(); i++) {
1409                 currentSelection = selections.get(i);
1410                 selectedTagGUIDs.add(currentSelection.text(2));
1411         }
1412         if (selections.size() > 0) {
1413                 menuBar.tagEditAction.setEnabled(true);
1414                 menuBar.tagDeleteAction.setEnabled(true);
1415         }
1416         else {
1417                 menuBar.tagEditAction.setEnabled(false);
1418                 menuBar.tagDeleteAction.setEnabled(false);
1419         }
1420         listManager.setSelectedTags(selectedTagGUIDs);
1421         listManager.loadNotesIndex();
1422         noteIndexUpdated(false);
1423         logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
1424     }
1425     // trigger the tag index to be refreshed
1426     @SuppressWarnings("unused")
1427         private void tagIndexUpdated() {
1428         tagIndexUpdated(true);
1429     }
1430     private void tagIndexUpdated(boolean reload) {
1431         logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
1432                 if (selectedTagGUIDs == null)
1433                         selectedTagGUIDs = new ArrayList<String>();
1434 //              selectedTagGUIDs.clear();  // clear out old entries
1435
1436                 tagTree.blockSignals(true);
1437                 if (reload)
1438                         tagTree.load(listManager.getTagIndex());
1439         for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
1440                 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
1441                 if (!found)
1442                         selectedTagGUIDs.remove(i);
1443         }
1444         tagTree.blockSignals(false);
1445         
1446                 browserWindow.setTag(getTagNamesForNote(currentNote));
1447         logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
1448     }   
1449     // Show/Hide note information
1450         private void toggleTagWindow() {
1451                 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
1452         if (tagTree.isVisible())
1453                 tagTree.hide();
1454         else
1455                 tagTree.show();
1456         menuBar.hideTags.setChecked(tagTree.isVisible());
1457         Global.saveWindowVisible("tagTree", tagTree.isVisible());
1458         logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
1459     }   
1460         // A note's tags have been updated
1461         @SuppressWarnings("unused")
1462         private void updateNoteTags(String guid, List<String> tags) {
1463                 // Save any new tags.  We'll need them later.
1464                 List<String> newTags = new ArrayList<String>();
1465                 for (int i=0; i<tags.size(); i++) {
1466                         if (conn.getTagTable().findTagByName(tags.get(i))==null) 
1467                                 newTags.add(tags.get(i));
1468                 }
1469                 
1470                 listManager.saveNoteTags(guid, tags);
1471                 listManager.countTagResults(listManager.getNoteIndex());
1472                 StringBuffer names = new StringBuffer("");
1473                 for (int i=0; i<tags.size(); i++) {
1474                         names = names.append(tags.get(i));
1475                         if (i<tags.size()-1) {
1476                                 names.append(Global.tagDelimeter + " ");
1477                         }
1478                 }
1479                 browserWindow.setTag(names.toString());
1480                 noteDirty = true;
1481                 
1482                 // Now, we need to add any new tags to the tag tree
1483                 for (int i=0; i<newTags.size(); i++) 
1484                         tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i)));
1485         }
1486         // Get a string containing all tag names for a note
1487         private String getTagNamesForNote(Note n) {
1488                 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
1489                 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
1490                         return "";
1491                 StringBuffer buffer = new StringBuffer(100);
1492                 Vector<String> v = new Vector<String>();
1493                 List<String> guids = n.getTagGuids();
1494                 
1495                 if (guids == null) 
1496                         return "";
1497                 
1498                 for (int i=0; i<guids.size(); i++) {
1499                         v.add(listManager.getTagNameByGuid(guids.get(i)));
1500                 }
1501                 Comparator<String> comparator = Collections.reverseOrder();
1502                 Collections.sort(v,comparator);
1503                 Collections.reverse(v);
1504                 
1505                 for (int i = 0; i<v.size(); i++) {
1506                         if (i>0) 
1507                                 buffer.append(", ");
1508                         buffer.append(v.get(i));
1509                 }
1510                 
1511                 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
1512                 return buffer.toString();
1513         }       
1514         // Tags were added via dropping notes from the note list
1515         @SuppressWarnings("unused")
1516         private void tagsAdded(String noteGuid, String tagGuid) {
1517                 String tagName = null;
1518                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1519                         if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
1520                                 tagName = listManager.getTagIndex().get(i).getName();
1521                                 i=listManager.getTagIndex().size();
1522                         }
1523                 }
1524                 if (tagName == null)
1525                         return;
1526                 
1527                 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
1528                         if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) {
1529                                 List<String> tagNames = new ArrayList<String>();
1530                                 tagNames.add(new String(tagName));
1531                                 Note n = listManager.getMasterNoteIndex().get(i);
1532                                 for (int j=0; j<n.getTagNames().size(); j++) {
1533                                         tagNames.add(new String(n.getTagNames().get(j)));
1534                                 }
1535                                 listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames);
1536                                 if (n.getGuid().equals(currentNoteGuid)) {
1537                                         Collections.sort(tagNames);
1538                                         String display = "";
1539                                         for (int j=0; j<tagNames.size(); j++) {
1540                                                 display = display+tagNames.get(j);
1541                                                 if (j+2<tagNames.size()) 
1542                                                         display = display+Global.tagDelimeter+" ";
1543                                         }
1544                                         browserWindow.setTag(display);
1545                                 }
1546                                 i=listManager.getMasterNoteIndex().size();
1547                         }
1548                 }
1549                 
1550                 
1551                 listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false);
1552         }
1553         private void clearTagFilter() {
1554                 tagTree.blockSignals(true);
1555                 tagTree.clearSelection();
1556                 menuBar.noteRestoreAction.setVisible(false);
1557                 menuBar.tagEditAction.setEnabled(false);
1558                 menuBar.tagDeleteAction.setEnabled(false);
1559                 selectedTagGUIDs.clear();
1560         listManager.setSelectedTags(selectedTagGUIDs);
1561         tagTree.blockSignals(false);
1562         }
1563         
1564         
1565     //***************************************************************
1566     //***************************************************************
1567     //** These functions deal with Saved Search menu items
1568     //***************************************************************
1569     //***************************************************************
1570         // Add a new notebook
1571         @SuppressWarnings("unused")
1572         private void addSavedSearch() {
1573                 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
1574                 SavedSearchEdit edit = new SavedSearchEdit();
1575                 edit.setSearchList(listManager.getSavedSearchIndex());
1576                 edit.exec();
1577         
1578                 if (!edit.okPressed())
1579                         return;
1580         
1581                 Calendar currentTime = new GregorianCalendar();         
1582                 Long l = new Long(currentTime.getTimeInMillis());
1583                 String randint = new String(Long.toString(l));
1584         
1585                 SavedSearch search = new SavedSearch();
1586                 search.setUpdateSequenceNum(0);
1587                 search.setGuid(randint);
1588                 search.setName(edit.getName());
1589                 search.setQuery(edit.getQuery());
1590                 search.setFormat(QueryFormat.USER);
1591                 listManager.getSavedSearchIndex().add(search);
1592                 conn.getSavedSearchTable().addSavedSearch(search, true);
1593                 savedSearchIndexUpdated();
1594                 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
1595         }
1596         // Edit an existing tag
1597         @SuppressWarnings("unused")
1598         private void editSavedSearch() {
1599                 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
1600                 SavedSearchEdit edit = new SavedSearchEdit();
1601                 edit.setTitle(tr("Edit Search"));
1602                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1603                 QTreeWidgetItem currentSelection;
1604                 currentSelection = selections.get(0);
1605                 String guid = currentSelection.text(1);
1606                 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
1607                 edit.setName(currentSelection.text(0));
1608                 edit.setQuery(s.getQuery());
1609                 edit.setSearchList(listManager.getSavedSearchIndex());
1610                 edit.exec();
1611         
1612                 if (!edit.okPressed())
1613                         return;
1614         
1615                 List<SavedSearch> list = listManager.getSavedSearchIndex();
1616                 SavedSearch search = null;
1617                 boolean found = false;
1618                 for (int i=0; i<list.size(); i++) {
1619                         search = list.get(i);
1620                         if (search.getGuid().equals(guid)) {
1621                                 i=list.size();
1622                                 found = true;
1623                         }
1624                 }
1625                 if (!found)
1626                         return;
1627                 search.setName(edit.getName());
1628                 search.setQuery(edit.getQuery());
1629                 conn.getSavedSearchTable().updateSavedSearch(search, true);
1630                 savedSearchIndexUpdated();
1631                 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
1632         }
1633         // Delete an existing tag
1634         @SuppressWarnings("unused")
1635         private void deleteSavedSearch() {
1636                 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
1637                 
1638                 if (QMessageBox.question(this, "Confirmation", "Delete the selected search?",
1639                         QMessageBox.StandardButton.Yes, 
1640                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1641                                                         return;
1642                 }
1643                 
1644                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1645         for (int i=selections.size()-1; i>=0; i--) {
1646                 QTreeWidgetItem currentSelection;
1647                 currentSelection = selections.get(i);
1648                 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
1649                         if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
1650                                 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
1651                                 listManager.getSavedSearchIndex().remove(j);
1652                                 j=listManager.getSavedSearchIndex().size()+1;
1653                         }
1654                 }
1655                 selections.remove(i);
1656         }
1657         savedSearchIndexUpdated();
1658         logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
1659         }
1660     // Setup the tree containing the user's tags
1661     private void initializeSavedSearchTree() {
1662         logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
1663         savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
1664         logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
1665     }
1666     // Listener when a tag is selected
1667     @SuppressWarnings("unused")
1668         private void savedSearchTreeSelection() {
1669         logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
1670
1671         clearNotebookFilter();
1672         clearTagFilter();
1673         clearTrashFilter();
1674         clearAttributeFilter();
1675         
1676         String currentGuid = selectedSavedSearchGUID;
1677         menuBar.savedSearchEditAction.setEnabled(true);
1678         menuBar.savedSearchDeleteAction.setEnabled(true);
1679         List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1680         QTreeWidgetItem currentSelection;
1681         selectedSavedSearchGUID = "";
1682         for (int i=0; i<selections.size(); i++) {
1683                 currentSelection = selections.get(i);
1684                 if (currentSelection.text(1).equals(currentGuid)) {
1685                         currentSelection.setSelected(false);
1686                 } else {
1687                         selectedSavedSearchGUID = currentSelection.text(1);
1688                 }
1689 //              i = selections.size() +1;
1690         }
1691         
1692         // There is the potential for no notebooks to be selected if this 
1693         // happens then we make it look like all notebooks were selecetd.
1694         // If that happens, just select the "all notebooks"
1695         if (selections.size()==0) {
1696                 clearSavedSearchFilter();
1697         }
1698         listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
1699         
1700         logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
1701     }
1702     private void clearSavedSearchFilter() {
1703         menuBar.savedSearchEditAction.setEnabled(false);
1704         menuBar.savedSearchDeleteAction.setEnabled(false);
1705         savedSearchTree.blockSignals(true);
1706         savedSearchTree.clearSelection();
1707         savedSearchTree.blockSignals(false);
1708         selectedSavedSearchGUID = "";
1709         searchField.setEditText("");
1710         searchPerformed = false;
1711         listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
1712     }
1713     // trigger the tag index to be refreshed
1714         private void savedSearchIndexUpdated() { 
1715                 if (selectedSavedSearchGUID == null)
1716                         selectedSavedSearchGUID = new String();
1717                 savedSearchTree.blockSignals(true);
1718         savedSearchTree.load(listManager.getSavedSearchIndex());
1719         savedSearchTree.selectGuid(selectedSavedSearchGUID);
1720         savedSearchTree.blockSignals(false);
1721     }
1722     // trigger when the saved search selection changes
1723     @SuppressWarnings("unused")
1724         private void updateSavedSearchSelection() {
1725                 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
1726                 
1727         menuBar.savedSearchEditAction.setEnabled(true);
1728         menuBar.savedSearchDeleteAction.setEnabled(true);
1729         List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1730
1731         if (selections.size() > 0) {
1732                 menuBar.savedSearchEditAction.setEnabled(true);
1733                 menuBar.savedSearchDeleteAction.setEnabled(true);
1734                 selectedSavedSearchGUID = selections.get(0).text(1);
1735                 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
1736                 searchField.setEditText(s.getQuery());
1737         } else { 
1738                 menuBar.savedSearchEditAction.setEnabled(false);
1739                 menuBar.savedSearchDeleteAction.setEnabled(false);
1740                 selectedSavedSearchGUID = "";
1741                 searchField.setEditText("");
1742         }
1743         searchFieldChanged();
1744         
1745                 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
1746
1747         
1748     }
1749     // Show/Hide note information
1750         private void toggleSavedSearchWindow() {
1751                 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
1752         if (savedSearchTree.isVisible())
1753                 savedSearchTree.hide();
1754         else
1755                 savedSearchTree.show();
1756         menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
1757                                 
1758                 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
1759         logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
1760     }
1761         
1762         
1763         
1764         
1765     //***************************************************************
1766     //***************************************************************
1767     //** These functions deal with Help menu & tool menu items
1768     //***************************************************************
1769     //***************************************************************
1770         // Show database status
1771         @SuppressWarnings("unused")
1772         private void databaseStatus() {
1773                 waitCursor(true);
1774                 int dirty = conn.getNoteTable().getDirtyCount();
1775                 int unindexed = conn.getNoteTable().getUnindexedCount();
1776                 DatabaseStatus status = new DatabaseStatus();
1777                 status.setUnsynchronized(dirty);
1778                 status.setUnindexed(unindexed);
1779                 status.setNoteCount(conn.getNoteTable().getNoteCount());
1780                 status.setNotebookCount(listManager.getNotebookIndex().size());
1781                 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
1782                 status.setTagCount(listManager.getTagIndex().size());
1783                 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
1784                 status.setWordCount(conn.getWordsTable().getWordCount());
1785                 waitCursor(false);
1786                 status.exec();
1787         }
1788         // Compact the database
1789         @SuppressWarnings("unused")
1790         private void compactDatabase() {
1791         logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
1792                 if (QMessageBox.question(this, tr("Confirmation"), tr("This will free unused space in the database, "+
1793                                 "but please be aware that depending upon the size of your database this can be time consuming " +
1794                                 "and NeverNote will be unresponsive until it is complete.  Do you wish to continue?"),
1795                                 QMessageBox.StandardButton.Yes, 
1796                                 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
1797                                                         return;
1798                 }
1799                 setMessage("Compacting database.");
1800                 waitCursor(true);
1801                 listManager.compactDatabase();
1802                 waitCursor(false);
1803                 setMessage("Database compact is complete.");            
1804         logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
1805     }
1806         @SuppressWarnings("unused")
1807         private void accountInformation() {
1808                 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
1809                 AccountDialog dialog = new AccountDialog();
1810                 dialog.show();
1811                 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
1812         }
1813         @SuppressWarnings("unused")
1814         private void releaseNotes() {
1815                 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
1816                 QDialog dialog = new QDialog(this);
1817                 QHBoxLayout layout = new QHBoxLayout();
1818                 QTextEdit textBox = new QTextEdit();
1819                 layout.addWidget(textBox);
1820                 textBox.setReadOnly(true);
1821                 QFile file = new QFile(Global.getFileManager().getHomeDirPath("release.txt"));
1822                 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
1823                 QIODevice.OpenModeFlag.Text)))
1824                         return;
1825                 textBox.setText(file.readAll().toString());
1826                 file.close();
1827                 dialog.setWindowTitle(tr("Release Notes"));
1828                 dialog.setLayout(layout);
1829                 dialog.show();
1830                 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
1831         }
1832         // Called when user picks Log from the help menu
1833         @SuppressWarnings("unused")
1834         private void logger() {
1835                 logger.log(logger.HIGH, "Entering NeverNote.logger");
1836                 QDialog dialog = new QDialog(this);
1837                 QHBoxLayout layout = new QHBoxLayout();
1838                 QListWidget textBox = new QListWidget();
1839                 layout.addWidget(textBox);
1840                 textBox.addItems(emitLog);
1841                 
1842                 dialog.setLayout(layout);
1843                 dialog.setWindowTitle(tr("Mesasge Log"));
1844                 dialog.show();
1845                 logger.log(logger.HIGH, "Leaving NeverNote.logger");
1846         }
1847         // Menu option "help/about" was selected
1848         @SuppressWarnings("unused")
1849         private void about() {
1850                 logger.log(logger.HIGH, "Entering NeverNote.about");
1851                 QMessageBox.about(this, 
1852                                                 tr("About NeverNote"),
1853                                                 tr("<h4><center><b>NeverNote</b></center></h4><hr><center>Version ")
1854                                                 +Global.version
1855                                                 +tr("<hr></center>Evernote"
1856                                                                 +"An Open Source Evernote Client.<br><br>" 
1857                                                                 +"Licensed under GPL v2.  <br><hr><br>"
1858                                                                 +"Evernote is copyright 2001-2010 by Evernote Corporation<br>"
1859                                                                 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
1860                                                                 +"PDFRenderer is licened under the LGPL<br>"
1861                                                                 +"JTidy is copyrighted under the World Wide Web Consortium<br>"
1862                                                                 +"Apache Common Utilities licensed under the Apache License Version 2.0<br>"
1863                                                                 +"Jazzy is licened under the LGPL<br>"
1864                                                                 +"Java is a registered trademark of Oracle Corporation.<br><hr>"));     
1865                 logger.log(logger.HIGH, "Leaving NeverNote.about");
1866         }
1867         // Hide the entire left hand side
1868         @SuppressWarnings("unused")
1869         private void toggleLeftSide() {
1870                 boolean hidden;
1871                 
1872                 hidden = !menuBar.hideLeftSide.isChecked();
1873                 menuBar.hideLeftSide.setChecked(!hidden);
1874                 
1875                 if (notebookTree.isVisible() != hidden)
1876                         toggleNotebookWindow();
1877                 if (savedSearchTree.isVisible() != hidden)
1878                         toggleSavedSearchWindow();
1879                 if (tagTree.isVisible() != hidden)
1880                         toggleTagWindow();
1881                 if (attributeTree.isVisible() != hidden)
1882                         toggleAttributesWindow();
1883                 if (trashTree.isVisible() != hidden)
1884                         toggleTrashWindow();
1885                 
1886                 Global.saveWindowVisible("leftPanel", hidden);
1887                 
1888         }
1889                         
1890         
1891     //***************************************************************
1892     //***************************************************************
1893     //** These functions deal with the Toolbar
1894     //***************************************************************
1895     //***************************************************************  
1896         // Text in the search bar has been cleared
1897         private void searchFieldCleared() {
1898                 searchField.setEditText("");
1899                 saveNoteIndexWidth();
1900         }
1901         // text in the search bar changed.  We only use this to tell if it was cleared, 
1902         // otherwise we trigger off searchFieldChanged.
1903         @SuppressWarnings("unused")
1904         private void searchFieldTextChanged(String text) {
1905                 if (text.trim().equals("")) {
1906                         searchFieldCleared();
1907                         if (searchPerformed) {
1908                                 noteCache.clear();
1909                                 listManager.setEnSearch("");
1910 /////                           listManager.clearNoteIndexSearch();
1911                                 //noteIndexUpdated(true);
1912                                 listManager.loadNotesIndex();
1913                                 refreshEvernoteNote(true);
1914                                 noteIndexUpdated(false);
1915                         }
1916                         searchPerformed = false;
1917                 }
1918         }
1919     // Text in the toolbar has changed
1920     private void searchFieldChanged() {
1921         logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
1922         noteCache.clear();
1923         saveNoteIndexWidth();
1924         String text = searchField.currentText();
1925         listManager.setEnSearch(text.trim());
1926         listManager.loadNotesIndex();
1927 //--->>>        noteIndexUpdated(true);
1928         noteIndexUpdated(false);
1929         refreshEvernoteNote(true);
1930         searchPerformed = true;
1931         logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
1932     }
1933
1934     // Build the window tool bar
1935     private void setupToolBar() {
1936         logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
1937         toolBar = addToolBar(tr("Tool Bar"));   
1938         menuBar.setupToolBarVisible();
1939         if (!Global.isWindowVisible("toolBar"))
1940                 toolBar.setVisible(false);
1941         else
1942                 toolBar.setVisible(true);
1943
1944         prevButton = toolBar.addAction("Previous");
1945         QIcon prevIcon = new QIcon(iconPath+"back.png");
1946         prevButton.setIcon(prevIcon);
1947         prevButton.triggered.connect(this, "previousViewedAction()");   
1948         
1949         nextButton = toolBar.addAction("Next");
1950         QIcon nextIcon = new QIcon(iconPath+"forward.png");
1951         nextButton.setIcon(nextIcon);
1952         nextButton.triggered.connect(this, "nextViewedAction()");       
1953         
1954         upButton = toolBar.addAction("Up");
1955         QIcon upIcon = new QIcon(iconPath+"up.png");
1956         upButton.setIcon(upIcon);
1957         upButton.triggered.connect(this, "upAction()");         
1958         
1959         downButton = toolBar.addAction("Down");
1960         QIcon downIcon = new QIcon(iconPath+"down.png");
1961         downButton.setIcon(downIcon);
1962         downButton.triggered.connect(this, "downAction()");
1963         
1964         synchronizeButton = toolBar.addAction("Synchronize");
1965         synchronizeAnimation = new ArrayList<QIcon>();
1966         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-0.png"));
1967         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-1.png"));
1968         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-2.png"));
1969         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-3.png"));
1970         synchronizeButton.setIcon(synchronizeAnimation.get(0));
1971         synchronizeFrame = 0;
1972         synchronizeButton.triggered.connect(this, "evernoteSync()");
1973         
1974         printButton = toolBar.addAction("Print");
1975         QIcon printIcon = new QIcon(iconPath+"print.png");
1976         printButton.setIcon(printIcon);
1977         printButton.triggered.connect(this, "printNote()");
1978         
1979         tagButton = toolBar.addAction("Tag"); 
1980         QIcon tagIcon = new QIcon(iconPath+"tag.png");
1981         tagButton.setIcon(tagIcon);
1982         tagButton.triggered.connect(browserWindow, "modifyTags()");
1983         
1984         attributeButton = toolBar.addAction("Attributes"); 
1985         QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
1986         attributeButton.setIcon(attributeIcon);
1987         attributeButton.triggered.connect(this, "toggleNoteInformation()");
1988                 
1989         emailButton = toolBar.addAction("Email");
1990         QIcon emailIcon = new QIcon(iconPath+"email.png");
1991         emailButton.setIcon(emailIcon);
1992         emailButton.triggered.connect(this, "emailNote()");
1993         
1994         deleteButton = toolBar.addAction("Delete");     
1995         QIcon deleteIcon = new QIcon(iconPath+"delete.png");
1996         deleteButton.setIcon(deleteIcon);
1997         deleteButton.triggered.connect(this, "deleteNote()");
1998                 
1999         newButton = toolBar.addAction("New");
2000         QIcon newIcon = new QIcon(iconPath+"new.png");
2001         newButton.triggered.connect(this, "addNote()");
2002         newButton.setIcon(newIcon);
2003         toolBar.addSeparator();
2004         toolBar.addWidget(new QLabel(tr("Quota:")));
2005         toolBar.addWidget(quotaBar);
2006         //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
2007         updateQuotaBar();
2008         
2009         // Setup the zoom
2010         zoomSpinner = new QSpinBox();
2011         zoomSpinner.setMinimum(10);
2012         zoomSpinner.setMaximum(1000);
2013         zoomSpinner.setAccelerated(true);
2014         zoomSpinner.setSingleStep(10);
2015         zoomSpinner.setValue(100);
2016         zoomSpinner.valueChanged.connect(this, "zoomChanged()");
2017         toolBar.addWidget(new QLabel(tr("Zoom")));
2018         toolBar.addWidget(zoomSpinner);
2019         
2020         //toolBar.addWidget(new QLabel("                    "));
2021         toolBar.addSeparator();
2022         toolBar.addWidget(new QLabel(tr("  Search:")));
2023         toolBar.addWidget(searchField);
2024         QSizePolicy sizePolicy = new QSizePolicy();
2025         sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
2026         searchField.setSizePolicy(sizePolicy);
2027         searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
2028
2029         searchClearButton = toolBar.addAction("Search Clear");
2030         QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
2031         searchClearButton.setIcon(searchClearIcon);
2032         searchClearButton.triggered.connect(this, "searchFieldCleared()");
2033         
2034         logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
2035     }
2036     // Update the sychronize button picture
2037     @SuppressWarnings("unused")
2038         private void updateSyncButton() {
2039         synchronizeFrame++;
2040         if (synchronizeFrame == 4) 
2041                 synchronizeFrame = 0;
2042         synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame));
2043     }
2044     // Synchronize with Evernote
2045         @SuppressWarnings("unused")
2046         private void evernoteSync() {
2047         logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
2048         if (!Global.isConnected)
2049                 remoteConnect();
2050         if (Global.isConnected)
2051                 synchronizeAnimationTimer.start(200);
2052         syncTimer();
2053         logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
2054     }
2055     private void updateQuotaBar() {
2056         long limit = Global.getUploadLimit();
2057         long amount = Global.getUploadAmount();
2058         if (amount>0 && limit>0) {
2059                 int percent =(int)(amount*100/limit);
2060                 quotaBar.setValue(percent);
2061         } else 
2062                 quotaBar.setValue(0);
2063     }
2064         // Zoom changed
2065     @SuppressWarnings("unused")
2066         private void zoomChanged() {
2067         browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
2068     }
2069
2070     //****************************************************************
2071     //****************************************************************
2072     //* System Tray functions
2073     //****************************************************************
2074     //****************************************************************
2075         private void trayToggleVisible() {
2076         if (isVisible()) {
2077                 hide();
2078         } else {
2079                 show();
2080                 raise();
2081         }
2082     }
2083     @SuppressWarnings("unused")
2084         private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
2085         if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
2086                 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
2087                 trayToggleVisible();
2088         }
2089     }
2090     
2091     
2092     //***************************************************************
2093     //***************************************************************
2094     //** These functions deal with the trash tree
2095     //***************************************************************
2096     //***************************************************************    
2097     // Setup the tree containing the trash.
2098     @SuppressWarnings("unused")
2099         private void trashTreeSelection() {     
2100         logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
2101         
2102         clearNotebookFilter();
2103         clearTagFilter();
2104         clearAttributeFilter();
2105         clearSavedSearchFilter();
2106         
2107         String tempGuid = currentNoteGuid;
2108         
2109 //      currentNoteGuid = "";
2110         currentNote = new Note();
2111         selectedNoteGUIDs.clear();
2112         listManager.getSelectedNotebooks().clear();
2113         listManager.getSelectedTags().clear();
2114         listManager.setSelectedSavedSearch("");
2115         browserWindow.clear();
2116     
2117         // toggle the add buttons
2118         newButton.setEnabled(!newButton.isEnabled());
2119         menuBar.noteAdd.setEnabled(newButton.isEnabled());
2120         menuBar.noteAdd.setVisible(true);
2121         
2122         List<QTreeWidgetItem> selections = trashTree.selectedItems();
2123         if (selections.size() == 0) {
2124                 currentNoteGuid = trashNoteGuid;
2125                         trashNoteGuid = tempGuid;
2126                 Global.showDeleted = false;
2127                 menuBar.noteRestoreAction.setEnabled(false);
2128                 menuBar.noteRestoreAction.setVisible(false);
2129         }
2130         else {
2131                 currentNoteGuid = trashNoteGuid;
2132                         trashNoteGuid = tempGuid;
2133                 menuBar.noteRestoreAction.setEnabled(true);
2134                 menuBar.noteRestoreAction.setVisible(true);
2135                 Global.showDeleted = true;
2136         }
2137         listManager.loadNotesIndex();
2138         noteIndexUpdated(false);
2139 ////            browserWindow.setEnabled(newButton.isEnabled());
2140         browserWindow.setReadOnly(!newButton.isEnabled());
2141         logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
2142     }
2143     // Empty the trash file
2144     @SuppressWarnings("unused")
2145         private void emptyTrash() {
2146 //      browserWindow.clear();
2147         listManager.emptyTrash();
2148         if (trashTree.selectedItems().size() > 0) {
2149                 listManager.getSelectedNotebooks().clear();
2150                 listManager.getSelectedTags().clear();
2151                 listManager.setSelectedSavedSearch("");
2152                 newButton.setEnabled(!newButton.isEnabled());
2153                 menuBar.noteAdd.setEnabled(newButton.isEnabled());
2154                 menuBar.noteAdd.setVisible(true);
2155                 browserWindow.clear();
2156                 
2157                 clearTagFilter();
2158                 clearNotebookFilter();
2159                 clearSavedSearchFilter();
2160                 clearAttributeFilter();
2161                         
2162                 Global.showDeleted = false;
2163                 menuBar.noteRestoreAction.setEnabled(false);
2164                 menuBar.noteRestoreAction.setVisible(false);
2165                 
2166                 listManager.loadNotesIndex();
2167 //--->>>                noteIndexUpdated(true);
2168                 noteIndexUpdated(false);
2169         }       
2170    }
2171     // Show/Hide trash window
2172         private void toggleTrashWindow() {
2173                 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
2174         if (trashTree.isVisible())
2175                 trashTree.hide();
2176         else
2177                 trashTree.show();
2178         menuBar.hideTrash.setChecked(trashTree.isVisible());
2179         
2180                 Global.saveWindowVisible("trashTree", trashTree.isVisible());
2181         logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
2182     }    
2183         private void clearTrashFilter() {
2184                 Global.showDeleted = false;
2185         newButton.setEnabled(true);
2186         menuBar.noteAdd.setEnabled(true);
2187         menuBar.noteAdd.setVisible(true);
2188                 trashTree.blockSignals(true);
2189                 trashTree.clearSelection();
2190                 trashTree.blockSignals(false);
2191                 
2192         }
2193     
2194    
2195     //***************************************************************
2196     //***************************************************************
2197     //** These functions deal with connection settings
2198     //***************************************************************
2199     //***************************************************************
2200         // SyncRunner had a problem and things are disconnected
2201         @SuppressWarnings("unused")
2202         private void remoteErrorDisconnect() {
2203                 menuBar.connectAction.setText(tr("Connect"));
2204                 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
2205                 menuBar.synchronizeAction.setEnabled(false);
2206                 synchronizeAnimationTimer.stop();
2207                 return;
2208         }
2209         // Do a manual connect/disconnect
2210     private void remoteConnect() {
2211         logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
2212
2213         if (Global.isConnected) {
2214                 Global.isConnected = false;
2215                 syncRunner.enDisconnect();
2216                 setupConnectMenuOptions();
2217                 setupOnlineMenu();
2218                 return;
2219         }
2220         
2221         AESEncrypter aes = new AESEncrypter();
2222         try {
2223                         aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("secure.txt")));
2224                 } catch (FileNotFoundException e) {
2225                         // File not found, so we'll just get empty strings anyway. 
2226                 }
2227                 String userid = aes.getUserid();
2228                 String password = aes.getPassword();
2229                 if (!userid.equals("") && !password.equals("")) {
2230                 Global.username = userid;
2231                 Global.password = password;
2232                 }               
2233
2234         // Show the login dialog box
2235                 if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) {
2236                         LoginDialog login = new LoginDialog();
2237                         login.exec();
2238                 
2239                         if (!login.okPressed()) {
2240                                 return;
2241                         }
2242         
2243                         Global.username = login.getUserid();
2244                         Global.password = login.getPassword();
2245                 }
2246                 syncRunner.username = Global.username;
2247                 syncRunner.password = Global.password;
2248                 syncRunner.userStoreUrl = Global.userStoreUrl;
2249                 syncRunner.noteStoreUrl = Global.noteStoreUrl;
2250                 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
2251                 syncRunner.enConnect();
2252                 Global.isConnected = syncRunner.isConnected;
2253                 setupOnlineMenu();
2254                 setupConnectMenuOptions();
2255                 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
2256     }
2257     private void setupConnectMenuOptions() {
2258         logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
2259                 if (!Global.isConnected) {
2260                         menuBar.connectAction.setText(tr("Connect"));
2261                         menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
2262                         menuBar.synchronizeAction.setEnabled(false);
2263                 } else {
2264                         menuBar.connectAction.setText(tr("Disconnect"));
2265                         menuBar.connectAction.setToolTip(tr("Disconnect from Evernote"));
2266                         menuBar.synchronizeAction.setEnabled(true);
2267                 }
2268                 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
2269     }
2270     
2271     
2272     
2273     //***************************************************************
2274     //***************************************************************
2275     //** These functions deal with the GUI Attribute tree
2276     //***************************************************************
2277     //***************************************************************    
2278     @SuppressWarnings("unused")
2279         private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
2280         
2281         clearTagFilter();
2282         clearNotebookFilter();
2283         clearTrashFilter();
2284         clearSavedSearchFilter();
2285
2286         if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
2287                 if (item.childCount() > 0) {
2288                         item.setSelected(false);
2289                 } else {
2290                 Global.createdBeforeFilter.reset();
2291                 Global.createdSinceFilter.reset();
2292                 Global.changedBeforeFilter.reset();
2293                 Global.changedSinceFilter.reset();
2294                 Global.containsFilter.reset();
2295                         attributeTreeSelected = item;
2296                         DateAttributeFilterTable f = null;
2297                         f = findDateAttributeFilterTable(item.parent());
2298                         if (f!=null)
2299                                 f.select(item.parent().indexOfChild(item));
2300                         else {
2301                                 Global.containsFilter.select(item.parent().indexOfChild(item));
2302                         }
2303                 }
2304                 listManager.loadNotesIndex();
2305                 noteIndexUpdated(false);
2306                 return;
2307         }
2308                 attributeTreeSelected = null;
2309                 item.setSelected(false);
2310         Global.createdBeforeFilter.reset();
2311         Global.createdSinceFilter.reset();
2312         Global.changedBeforeFilter.reset();
2313         Global.changedSinceFilter.reset();
2314         Global.containsFilter.reset();
2315         listManager.loadNotesIndex();
2316                 noteIndexUpdated(false); 
2317     }
2318     // This determines what attribute filter we need, depending upon the selection
2319     private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
2320                 if (w.parent() != null && w.childCount() > 0) {
2321                         QTreeWidgetItem parent = w.parent();
2322                         if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created && 
2323                                 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
2324                                         return Global.createdSinceFilter;
2325                         if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created && 
2326                         w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
2327                                         return Global.createdBeforeFilter;
2328                         if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified && 
2329                         w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
2330                                         return Global.changedSinceFilter;
2331                 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified && 
2332                         w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
2333                                                 return Global.changedBeforeFilter;
2334                 }
2335                 return null;
2336     }
2337
2338     // Show/Hide attribute search window
2339         private void toggleAttributesWindow() {
2340                 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
2341         if (attributeTree.isVisible())
2342                 attributeTree.hide();
2343         else
2344                 attributeTree.show();
2345         menuBar.hideAttributes.setChecked(attributeTree.isVisible());
2346         
2347                 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
2348         logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
2349     }    
2350         private void clearAttributeFilter() {
2351         Global.createdBeforeFilter.reset();
2352         Global.createdSinceFilter.reset();
2353         Global.changedBeforeFilter.reset();
2354         Global.changedSinceFilter.reset();
2355         Global.containsFilter.reset();
2356         attributeTreeSelected = null;
2357                 attributeTree.blockSignals(true);
2358                 attributeTree.clearSelection();
2359                 attributeTree.blockSignals(false);
2360         }
2361     
2362         
2363     //***************************************************************
2364     //***************************************************************
2365     //** These functions deal with the GUI Note index table
2366     //***************************************************************
2367     //***************************************************************    
2368     // Initialize the note list table
2369         private void initializeNoteTable() {
2370                 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
2371                 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
2372                 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
2373                 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
2374         }       
2375     // Show/Hide trash window
2376         @SuppressWarnings("unused")
2377         private void toggleNoteListWindow() {
2378                 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
2379         if (noteTableView.isVisible())
2380                 noteTableView.hide();
2381         else
2382                 noteTableView.show();
2383         menuBar.hideNoteList.setChecked(noteTableView.isVisible());
2384         
2385                 Global.saveWindowVisible("noteList", noteTableView.isVisible());
2386         logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
2387     }   
2388         // Handle the event that a user selects a note from the table
2389     @SuppressWarnings("unused")
2390         private void noteTableSelection() {
2391                 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
2392                 saveNote();
2393                 if (historyGuids.size() == 0) {
2394                         historyGuids.add(currentNoteGuid);
2395                         historyPosition = 1;
2396                 }
2397         noteTableView.showColumn(Global.noteTableGuidPosition);
2398         
2399         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2400         noteTableView.hideColumn(Global.noteTableGuidPosition);
2401         
2402         if (selections.size() > 0) {
2403                 QModelIndex index;
2404                 menuBar.noteDuplicateAction.setEnabled(true);
2405                 menuBar.noteOnlineHistoryAction.setEnabled(true);
2406                 menuBar.noteMergeAction.setEnabled(true);
2407                 selectedNoteGUIDs.clear();
2408                 if (selections.size() != 1 || Global.showDeleted) {
2409                         menuBar.noteDuplicateAction.setEnabled(false);
2410                 }
2411                 if (selections.size() != 1 || !Global.isConnected) {
2412                         menuBar.noteOnlineHistoryAction.setEnabled(false);
2413                 }
2414                 if (selections.size() == 1) {
2415                         menuBar.noteMergeAction.setEnabled(false);
2416                 }
2417                 for (int i=0; i<selections.size(); i++) {
2418                         int row = selections.get(i).row();
2419                         if (row == 0) 
2420                                 upButton.setEnabled(false);
2421                         else
2422                                 upButton.setEnabled(true);
2423                         if (row < listManager.getNoteTableModel().rowCount()-1)
2424                                 downButton.setEnabled(true);
2425                         else
2426                                 downButton.setEnabled(false);
2427                         index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
2428                         SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
2429                         currentNoteGuid = (String)ix.values().toArray()[0];
2430                         selectedNoteGUIDs.add(currentNoteGuid);
2431                 }
2432         }
2433         
2434         nextButton.setEnabled(true);
2435                 prevButton.setEnabled(true);
2436         if (!fromHistory) {
2437                 int endPosition = historyGuids.size()-1;
2438                 for (int j=historyPosition; j<=endPosition; j++) {
2439                         historyGuids.remove(historyGuids.size()-1);
2440                 }
2441                 historyGuids.add(currentNoteGuid);
2442                 historyPosition = historyGuids.size();
2443         } 
2444         if (historyPosition <= 1)
2445                 prevButton.setEnabled(false);
2446         if (historyPosition == historyGuids.size())
2447                 nextButton.setEnabled(false);
2448                 
2449         fromHistory = false;
2450         scrollToGuid(currentNoteGuid);
2451         refreshEvernoteNote(true);
2452                 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
2453     }    
2454         // Trigger a refresh when the note db has been updated
2455         private void noteIndexUpdated(boolean reload) {
2456                 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
2457                 saveNote();
2458         refreshEvernoteNoteList();
2459         logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
2460         noteTableView.load(reload);
2461         scrollToGuid(currentNoteGuid);
2462                 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
2463     }
2464         // Called when the list of notes is updated
2465     private void refreshEvernoteNoteList() {
2466         logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
2467         browserWindow.setDisabled(false);
2468                 if (selectedNoteGUIDs == null)
2469                         selectedNoteGUIDs = new ArrayList<String>();
2470                 selectedNoteGUIDs.clear();  // clear out old entries
2471                 
2472                 String saveCurrentNoteGuid = new String();
2473                 String tempNoteGuid = new String();
2474                                 
2475                 historyGuids.clear();
2476                 historyPosition = 0;
2477                 prevButton.setEnabled(false);
2478                 nextButton.setEnabled(false);
2479                 
2480                 if (currentNoteGuid == null) 
2481                         currentNoteGuid = new String();
2482                 
2483                 for (Note note : listManager.getNoteIndex()) {
2484                         tempNoteGuid = note.getGuid();
2485                         if (currentNoteGuid.equals(tempNoteGuid)) {
2486                                 saveCurrentNoteGuid = new String(tempNoteGuid);
2487                         }
2488                 }
2489                 
2490                 if (listManager.getNoteIndex().size() == 0) {
2491                         currentNoteGuid = "";
2492                         currentNote = null;
2493                         browserWindow.clear();
2494                         browserWindow.setDisabled(true);
2495                 } 
2496                 
2497                 if (saveCurrentNoteGuid.equals("") && listManager.getNoteIndex().size() >0) {
2498                         currentNoteGuid = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1).getGuid();
2499                         currentNote = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1);
2500                         refreshEvernoteNote(true);
2501                 } else {
2502                         refreshEvernoteNote(false);
2503                 }
2504                 reloadTagTree();
2505
2506                 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
2507         } 
2508     // Called when the previous arrow button is clicked 
2509     @SuppressWarnings("unused")
2510         private void previousViewedAction() {
2511         if (!prevButton.isEnabled())
2512                 return;
2513         if (historyPosition == 0)
2514                 return;
2515                 historyPosition--;
2516         if (historyPosition <= 0)
2517                 return;
2518         String historyGuid = historyGuids.get(historyPosition-1);
2519         fromHistory = true;
2520         for (int i=0; i<noteTableView.model().rowCount(); i++) {
2521                 QModelIndex modelIndex =  noteTableView.model().index(i, Global.noteTableGuidPosition);
2522                 if (modelIndex != null) {
2523                         SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
2524                         String tableGuid =  (String)ix.values().toArray()[0];
2525                         if (tableGuid.equals(historyGuid)) {
2526                                 noteTableView.selectRow(i);
2527                                 return;
2528                         }       
2529                 }
2530         }
2531     }
2532     @SuppressWarnings("unused")
2533         private void nextViewedAction() {
2534         if (!nextButton.isEnabled())
2535                 return;
2536         String historyGuid = historyGuids.get(historyPosition);
2537         historyPosition++;
2538         fromHistory = true;
2539         for (int i=0; i<noteTableView.model().rowCount(); i++) {
2540                 QModelIndex modelIndex =  noteTableView.model().index(i, Global.noteTableGuidPosition);
2541                 if (modelIndex != null) {
2542                         SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
2543                         String tableGuid =  (String)ix.values().toArray()[0];
2544                         if (tableGuid.equals(historyGuid)) {
2545                                 noteTableView.selectRow(i);
2546                                 return;
2547                         }       
2548                 }
2549         }       
2550     }
2551     // Called when the up arrow is clicked 
2552     @SuppressWarnings("unused")
2553         private void upAction() {
2554         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2555         int row = selections.get(0).row();
2556         if (row > 0) {
2557                 noteTableView.selectRow(row-1);
2558         }
2559     }
2560     // Called when the down arrow is clicked 
2561     @SuppressWarnings("unused")
2562         private void downAction() {
2563         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2564         int row = selections.get(0).row();
2565         int max = listManager.getNoteTableModel().rowCount();
2566         if (row < max-1) {
2567                 noteTableView.selectRow(row+1);
2568         }
2569     }
2570     // Update a tag string for a specific note in the list
2571     @SuppressWarnings("unused")
2572         private void updateListTags(String guid, List<String> tags) {
2573         logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
2574         StringBuffer tagBuffer = new StringBuffer();
2575         for (int i=0; i<tags.size(); i++) {
2576                 tagBuffer.append(tags.get(i));
2577                 if (i<tags.size()-1)
2578                         tagBuffer.append(", ");
2579         }
2580         
2581         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2582                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2583                 if (modelIndex != null) {
2584                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2585                         String tableGuid =  (String)ix.values().toArray()[0];
2586                         if (tableGuid.equals(guid)) {
2587                                 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString());
2588                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2589                                 return;
2590                         }
2591                 }
2592         }
2593         logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
2594     }
2595     // Update a title for a specific note in the list
2596     @SuppressWarnings("unused")
2597         private void updateListAuthor(String guid, String author) {
2598         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2599
2600         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2601                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2602                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2603                 if (modelIndex != null) {
2604 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2605                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2606                         String tableGuid =  (String)ix.values().toArray()[0];
2607                         if (tableGuid.equals(guid)) {
2608                                 listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author);
2609                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2610                                 return;
2611                         }       
2612                 }
2613         }
2614         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2615     }
2616         private void updateListNoteNotebook(String guid, String notebook) {
2617         logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook");
2618         listManager.getNoteTableModel().updateNoteSyncStatus(guid, false);
2619         logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook");
2620     }
2621     // Update a title for a specific note in the list
2622     @SuppressWarnings("unused")
2623         private void updateListSourceUrl(String guid, String url) {
2624         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2625
2626         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2627                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2628                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2629                 if (modelIndex != null) {
2630 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2631                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2632                         String tableGuid =  (String)ix.values().toArray()[0];
2633                         if (tableGuid.equals(guid)) {
2634                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2635                                 listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url);
2636                                 return;
2637                         }       
2638                 }
2639         }
2640         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2641     }
2642         private void updateListGuid(String oldGuid, String newGuid) {
2643         logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
2644
2645         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2646                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2647                 if (modelIndex != null) {
2648                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2649                         String tableGuid =  (String)ix.values().toArray()[0];
2650                         if (tableGuid.equals(oldGuid)) {
2651                                 listManager.getNoteTableModel().setData(i, Global.noteTableGuidPosition,newGuid);
2652                                 //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2653                                 return;
2654                         }       
2655                 }
2656         }
2657         logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
2658     }
2659         private void updateListTagName(String guid) {
2660         logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
2661                 
2662                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2663                         if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
2664                                 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
2665
2666                                 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2667                                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2668                                         if (modelIndex != null) {
2669                                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2670                                                 String noteGuid = (String)ix.values().toArray()[0];
2671                                                 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
2672                                                         listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
2673                                                         //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2674                                                         i=listManager.getNoteTableModel().rowCount();
2675                                                 }
2676                                         }
2677                                 }
2678                         }
2679                 }       
2680         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
2681     }
2682         private void removeListTagName(String guid) {
2683         logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
2684                 
2685                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2686                         if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
2687                                 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
2688                                         if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid))
2689                                                 listManager.getNoteIndex().get(j).getTagGuids().remove(i);
2690                                 }
2691                                 
2692                                 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
2693                                 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2694                                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2695                                         if (modelIndex != null) {
2696                                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2697                                                 String noteGuid = (String)ix.values().toArray()[0];
2698                                                 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
2699                                                         listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
2700 //                                                      listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2701                                                         i=listManager.getNoteTableModel().rowCount();
2702                                                 }
2703                                         }
2704                                 }
2705                         }
2706                 }       
2707         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
2708     }
2709     private void updateListNotebookName(String oldName, String newName) {
2710         logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName");
2711
2712         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2713                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableNotebookPosition); 
2714                 if (modelIndex != null) {
2715                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2716                         String tableName =  (String)ix.values().toArray()[0];
2717                         if (tableName.equalsIgnoreCase(oldName)) {
2718 //                              listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2719                                 listManager.getNoteTableModel().setData(i, Global.noteTableNotebookPosition, newName);
2720                         }
2721                 }
2722         }
2723         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName");
2724     }
2725     @SuppressWarnings("unused")
2726         private void updateListDateCreated(String guid, QDateTime date) {
2727         logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated");
2728
2729         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2730                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2731                 if (modelIndex != null) {
2732                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2733                         String tableGuid =  (String)ix.values().toArray()[0];
2734                         if (tableGuid.equals(guid)) {
2735                                 listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
2736                                 return;
2737                         }
2738                 }
2739         }
2740         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
2741     }
2742     @SuppressWarnings("unused")
2743         private void updateListDateSubject(String guid, QDateTime date) {
2744         logger.log(logger.HIGH, "Entering NeverNote.updateListDateSubject");
2745
2746         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2747                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2748                 if (modelIndex != null) {
2749                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2750                         String tableGuid =  (String)ix.values().toArray()[0];
2751                         if (tableGuid.equals(guid)) {
2752                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2753                                 listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
2754                                 return;
2755                         }
2756                 }
2757         }
2758         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
2759     }
2760     @SuppressWarnings("unused")
2761         private void updateListDateChanged(String guid, QDateTime date) {
2762         logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
2763
2764         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2765                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2766                 if (modelIndex != null) {
2767                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2768                         String tableGuid =  (String)ix.values().toArray()[0];
2769                         if (tableGuid.equals(guid)) {
2770                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2771                                 listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
2772                                 return;
2773                         }
2774                 }
2775         }
2776         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
2777     }
2778     private void updateListDateChanged() {
2779         logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
2780         QDateTime date = new QDateTime(QDateTime.currentDateTime());
2781         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2782                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2783                 if (modelIndex != null) {
2784                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2785                         String tableGuid =  (String)ix.values().toArray()[0];
2786                         if (tableGuid.equals(currentNoteGuid)) {
2787                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2788                                 listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
2789                                 return;
2790                         }
2791                 }
2792         }
2793         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
2794     }  
2795     // Redo scroll
2796     @SuppressWarnings("unused")
2797         private void scrollToCurrentGuid() {
2798         //scrollToGuid(currentNoteGuid);
2799         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2800         if (selections.size() == 0)
2801                 return;
2802         QModelIndex index = selections.get(0);
2803         int row = selections.get(0).row();
2804         String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data();
2805         scrollToGuid(guid);
2806     }
2807     // Scroll to a particular index item
2808     private void scrollToGuid(String guid) {
2809         if (currentNote == null || guid == null) 
2810                 return;
2811         if (currentNote.isActive() && Global.showDeleted) {
2812                 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
2813                         if (!listManager.getNoteIndex().get(i).isActive()) {
2814                                 currentNote = listManager.getNoteIndex().get(i);
2815                                 currentNoteGuid =  currentNote.getGuid();
2816                                 i = listManager.getNoteIndex().size();
2817                         }
2818                 }
2819         }
2820         
2821         if (!currentNote.isActive() && !Global.showDeleted) {
2822                 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
2823                         if (listManager.getNoteIndex().get(i).isActive()) {
2824                                 currentNote = listManager.getNoteIndex().get(i);
2825                                 currentNoteGuid =  currentNote.getGuid();
2826                                 i = listManager.getNoteIndex().size();
2827                         }
2828                 }
2829         }
2830         
2831         QModelIndex index; 
2832         for (int i=0; i<noteTableView.model().rowCount(); i++) {
2833                 index = noteTableView.model().index(i, Global.noteTableGuidPosition);
2834                 if (currentNoteGuid.equals(index.data())) {
2835 //                      noteTableView.setCurrentIndex(index);
2836                         noteTableView.selectRow(i);
2837                         noteTableView.scrollTo(index, ScrollHint.EnsureVisible);  // This should work, but it doesn't
2838                                 i=listManager.getNoteTableModel().rowCount();
2839                 }
2840         }
2841     }
2842     // Show/Hide columns
2843     private void showColumns() {
2844                 noteTableView.setColumnHidden(Global.noteTableCreationPosition, !Global.isColumnVisible("dateCreated"));
2845                 noteTableView.setColumnHidden(Global.noteTableChangedPosition, !Global.isColumnVisible("dateChanged"));
2846                 noteTableView.setColumnHidden(Global.noteTableSubjectDatePosition, !Global.isColumnVisible("dateSubject"));
2847                 noteTableView.setColumnHidden(Global.noteTableAuthorPosition, !Global.isColumnVisible("author"));
2848                 noteTableView.setColumnHidden(Global.noteTableSourceUrlPosition, !Global.isColumnVisible("sourceUrl"));
2849                 noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags"));
2850                 noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook"));
2851                 noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized"));
2852     }
2853     // Open a separate window
2854     @SuppressWarnings("unused")
2855         private void listDoubleClick() {
2856
2857     }
2858     // Title color has changed
2859     @SuppressWarnings("unused")
2860         private void titleColorChanged(Integer color) {
2861         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2862
2863         QColor backgroundColor = new QColor();
2864                 QColor foregroundColor = new QColor(QColor.black);
2865                 backgroundColor.setRgb(color);
2866                 
2867                 if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb())
2868                         foregroundColor.setRgb(QColor.white.rgb());
2869         
2870                 if (selectedNoteGUIDs.size() == 0)
2871                         selectedNoteGUIDs.add(currentNoteGuid);
2872                 
2873         for (int j=0; j<selectedNoteGUIDs.size(); j++) {
2874                 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2875                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2876                         if (modelIndex != null) {
2877                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2878                                 String tableGuid =  (String)ix.values().toArray()[0];
2879                                 if (tableGuid.equals(selectedNoteGUIDs.get(j))) {
2880                                         for (int k=0; k<Global.noteTableColumnCount; k++) {
2881                                                 listManager.getNoteTableModel().setData(i, k, backgroundColor, Qt.ItemDataRole.BackgroundRole);
2882                                                 listManager.getNoteTableModel().setData(i, k, foregroundColor, Qt.ItemDataRole.ForegroundRole);
2883                                                 listManager.updateNoteTitleColor(selectedNoteGUIDs.get(j), backgroundColor.rgb());
2884                                         }
2885                                         i=listManager.getNoteTableModel().rowCount();
2886                                 }
2887                         }
2888                 }
2889         }
2890         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2891     }
2892     
2893     
2894     //***************************************************************
2895     //***************************************************************
2896     //** These functions deal with Note specific things
2897     //***************************************************************
2898     //***************************************************************    
2899     @SuppressWarnings("unused")
2900         private void setNoteDirty() {
2901                 logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()");
2902                 
2903                 // If the note is dirty, then it is unsynchronized by default.
2904                 if (noteDirty) 
2905                         return;
2906                 
2907                 // Set the note as dirty and check if its status is synchronized in the display table
2908                 noteDirty = true;
2909                 for (int i=0; i<listManager.getUnsynchronizedNotes().size(); i++) {
2910                         if (listManager.getUnsynchronizedNotes().get(i).equals(currentNoteGuid))
2911                                 return;
2912                 }
2913                 
2914                 // If this wasn't already marked as unsynchronized, then we need to update the table
2915                 listManager.getNoteTableModel().updateNoteSyncStatus(currentNoteGuid, false);
2916 /*      listManager.getUnsynchronizedNotes().add(currentNoteGuid);
2917         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
2918                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
2919                 if (modelIndex != null) {
2920                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
2921                         String tableGuid =  (String)ix.values().toArray()[0];
2922                         if (tableGuid.equals(currentNoteGuid)) {
2923                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
2924                                 return;
2925                         }
2926                 }
2927         }
2928  */     
2929                 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
2930     }
2931     private void saveNote() {
2932                 logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
2933         if (noteDirty) {
2934                         logger.log(logger.EXTREME, "Note is dirty.");
2935                 waitCursor(true);
2936                 
2937                         preview = new Thumbnailer(currentNoteGuid, new QSize(1024,768));
2938                         preview.finished.connect(this, "saveThumbnail(String)");
2939                         preview.setContent(browserWindow.getContent());
2940                 
2941                         logger.log(logger.EXTREME, "Saving to cache");
2942                         QTextCodec codec = QTextCodec.codecForLocale();
2943 //              QTextDecoder decoder = codec.makeDecoder();
2944                         codec = QTextCodec.codecForName("UTF-8");
2945                 QByteArray unicode =  codec.fromUnicode(browserWindow.getContent());
2946                 noteCache.put(currentNoteGuid, unicode.toString());
2947                         
2948                 logger.log(logger.EXTREME, "updating list manager");
2949                 listManager.updateNoteContent(currentNoteGuid, browserWindow.getContent());
2950 //              noteCache.put(currentNoteGuid, browserWindow.getContent());
2951                         logger.log(logger.EXTREME, "Updating title");
2952                 listManager.updateNoteTitle(currentNoteGuid, browserWindow.getTitle());
2953                 updateListDateChanged();
2954
2955                         logger.log(logger.EXTREME, "Looking through note index for refreshed note");
2956                 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
2957                         if (listManager.getNoteIndex().get(i).getGuid().equals(currentNoteGuid)) {
2958                                 currentNote = listManager.getNoteIndex().get(i);
2959                                 i = listManager.getNoteIndex().size();
2960                         }
2961                 }
2962                 noteDirty = false;
2963                 waitCursor(false);
2964         }
2965     }
2966     // Get a note from Evernote (and put it in the browser)
2967         private void refreshEvernoteNote(boolean reload) {
2968                 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote");
2969                 if (Global.disableViewing) {
2970                         browserWindow.setEnabled(false);
2971                         return;
2972                 }
2973                 inkNote = false;
2974                 if (!Global.showDeleted)
2975                         browserWindow.setReadOnly(false);
2976                 Global.cryptCounter =0;
2977                 if (currentNoteGuid.equals("")) {
2978                         browserWindow.setReadOnly(true);
2979                         return;
2980                 }
2981                 if (!reload)
2982                         return;
2983                 
2984                 waitCursor(true);
2985                 browserWindow.loadingData(true);
2986
2987                 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
2988                 if (currentNote == null) 
2989                         return;
2990
2991                 if (!noteCache.containsKey(currentNoteGuid) || conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
2992                         QByteArray js = new QByteArray();
2993                         // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly 
2994                         js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");               
2995                         js.append("<style type=\"text/css\">en-crypt-temp { border-style:solid; border-color:blue; padding:0.5mm 0.5mm 0.5mm 0.5mm; }</style>");
2996                         js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");
2997                         js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
2998                         js.append("</head>");
2999                         js.append(rebuildNoteHTML(currentNoteGuid, currentNote.getContent()));
3000                         js.append("</HTML>");
3001                         js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
3002                         js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");
3003                         js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");
3004                         browserWindow.getBrowser().setContent(js);
3005                         noteCache.put(currentNoteGuid, js.toString());
3006                         if (conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
3007                                 preview = new Thumbnailer(currentNoteGuid, new QSize(1024,768));
3008                                 preview.finished.connect(this, "saveThumbnail(String)");
3009                                 preview.setContent(js.toString());
3010                         }
3011                 } else {
3012                         logger.log(logger.HIGH, "Note content is being pulled from the cache");
3013                         String cachedContent = modifyCachedTodoTags(noteCache.get(currentNoteGuid));
3014                         browserWindow.getBrowser().setContent(new QByteArray(cachedContent));
3015                 }
3016                 
3017                 browserWindow.getBrowser().page().setContentEditable(!inkNote);  // We don't allow editing of ink notes
3018                 browserWindow.setNote(currentNote);
3019                 
3020                 // Build a list of non-closed notebooks
3021                 List<Notebook> nbooks = new ArrayList<Notebook>();
3022                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
3023                         boolean found=false;
3024                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
3025                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) 
3026                                         found = true;
3027                         }
3028                         if (!found)
3029                                 nbooks.add(listManager.getNotebookIndex().get(i));
3030                 }
3031                 
3032                 browserWindow.setNotebookList(nbooks);
3033                 browserWindow.setTitle(currentNote.getTitle());
3034                 browserWindow.setTag(getTagNamesForNote(currentNote));
3035                 browserWindow.setAuthor(currentNote.getAttributes().getAuthor());
3036                 
3037                 browserWindow.setAltered(currentNote.getUpdated());
3038                 browserWindow.setCreation(currentNote.getCreated());
3039                 if (currentNote.getAttributes().getSubjectDate() > 0)
3040                         browserWindow.setSubjectDate(currentNote.getAttributes().getSubjectDate());
3041                 else
3042                         browserWindow.setSubjectDate(currentNote.getCreated());
3043                 browserWindow.setUrl(currentNote.getAttributes().getSourceURL());
3044                 browserWindow.setAllTags(listManager.getTagIndex());
3045                 browserWindow.setCurrentTags(currentNote.getTagNames());
3046                 noteDirty = false;
3047                 scrollToGuid(currentNoteGuid);
3048                 
3049                 browserWindow.loadingData(false);
3050                 if (thumbnailViewer.isActiveWindow())
3051                         thumbnailView();
3052                 waitCursor(false);
3053                 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
3054         }
3055         // Save a generated thumbnail
3056         @SuppressWarnings("unused")
3057         private void saveThumbnail(String guid) {
3058                 QFile tFile = new QFile(Global.getFileManager().getResDirPath("thumbnail-" + guid + ".png"));
3059                 tFile.open(OpenModeFlag.ReadOnly);
3060                 QByteArray imgBytes = tFile.readAll();
3061                 tFile.close();
3062                 conn.getNoteTable().setThumbnail(guid, imgBytes);
3063                 conn.getNoteTable().setThumbnailNeeded(guid, false);
3064                 thumbnailViewer.setThumbnail(QImage.fromData(imgBytes));
3065                 if (thumbnailViewer.isVisible()) 
3066                         thumbnailViewer.showFullScreen();
3067                 
3068                 /*              
3069                 QByteArray img2 = new QByteArray(conn.getNoteTable().getThumbnail(guid));
3070                 QFile file = new QFile(Global.currentDir+"res/aaaa.png");
3071                 file.open(OpenModeFlag.WriteOnly);
3072                 file.write(img2);
3073                 file.close(); 
3074                 */
3075         }
3076     // Show/Hide note information
3077         @SuppressWarnings("unused")
3078         private void toggleNoteInfor