OSDN Git Service

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