OSDN Git Service

3153cd9f540223bc75c950d9b9e461c3a478a0b8
[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                 // NFC TODO: who creates this - H2? should it be parameterized with databaseName like in RDatabaseConnection? 
836                 String fileName = Global.getFileManager().getDbDirPath("NeverNote.lock.db");
837 //              QFile.remove(fileName);
838                 if (QFile.exists(fileName)) {
839                         QMessageBox.question(this, "Lock File Detected",
840                                         "While starting I've found a database lock file.\n" +
841                                         "to prevent multiple instances from accessing the database \n"+
842                                         "at the same time.  Please stop any other program, or (if you\n" +
843                                         "are sure nothing else is using the database) remove the file\n" +
844                                         fileName +".");
845                         return false;
846                         
847                 }
848                 return true;
849 /*              String fileName = Global.currentDir +"nevernote.lock";
850
851                 
852                 if (QFile.exists(fileName)) {
853                         if (QMessageBox.question(this, "Confirmation",
854                                 "While starting I've found a lock file.  This file is used to prevent multiple "+
855                                 "instances of this program running at once.  If NeverNote has crashed this " +
856                                 "is just a file that wasn't cleaned up and you can safely, "+
857                                 "continue, but if there is another instance of this running you are " +
858                                 "running the risk of creating problems.\n\n" +
859                                 "Are you sure you want to continue?",
860                                 QMessageBox.StandardButton.Yes, 
861                                 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
862                                         return false;
863                                 }
864                 }
865                 
866                 QFile file = new QFile(fileName);
867                 file.open(OpenModeFlag.WriteOnly);
868                 file.write(new QByteArray("This file is used to prevent multiple instances " +
869                                 "of NeverNote running more than once.  " +
870                                 "It should be deleted when NeverNote ends"));
871                 file.close();
872                 return true;
873 */
874         }
875         private void unlockApplication() {
876                 String fileName = Global.currentDir +"nevernote.lock";
877                 if (QFile.exists(fileName)) {
878                         QFile.remove(fileName);
879                 }
880         }
881         
882
883         //***************************************************************
884         //***************************************************************
885         //* Settings and look & feel
886         //***************************************************************
887         //***************************************************************
888         @SuppressWarnings("unused")
889         private void settings() {
890                 logger.log(logger.HIGH, "Entering NeverNote.settings");
891         ConfigDialog settings = new ConfigDialog(this);
892         String dateFormat = Global.getDateFormat();
893         String timeFormat = Global.getTimeFormat();
894         
895         settings.exec();
896         if (Global.showTrayIcon())
897                 trayIcon.show();
898         else
899                 trayIcon.hide();
900         showColumns();
901         if (menuBar.showEditorBar.isChecked())
902                 showEditorButtons();
903         
904         // Reset the save timer
905         if (Global.getAutoSaveInterval() > 0)
906                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
907         else
908                 saveTimer.stop();
909         
910         // This is a hack to force a reload of the index in case the date or time changed.
911 //        if (!dateFormat.equals(Global.getDateFormat()) ||
912 //                      !timeFormat.equals(Global.getTimeFormat())) {
913                 noteCache.clear();
914                 noteIndexUpdated(true);
915 //        }
916         
917         logger.log(logger.HIGH, "Leaving NeverNote.settings");
918         }
919         // Restore things to the way they were
920         private void restoreWindowState() {
921                 // We need to name things or this doesn't work.
922                 setObjectName("NeverNote");
923                 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
924                 browserIndexSplitter.setObjectName("browserIndexSplitter");
925                 leftSplitter1.setObjectName("leftSplitter1");   
926                 
927                 // Restore the actual positions.
928                 restoreGeometry(Global.restoreGeometry(objectName()));
929         mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
930         browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
931         leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
932        
933         }
934         // Save window positions for the next start
935         private void saveWindowState() {
936                 Global.saveGeometry(objectName(), saveGeometry());
937                 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
938                 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
939                 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
940         }    
941         // Load the style sheet
942         private void loadStyleSheet() {
943                 String fileName = Global.currentDir +"qss"+System.getProperty("file.separator")+ "default.qss";
944                 QFile file = new QFile(fileName);
945                 file.open(OpenModeFlag.ReadOnly);
946                 String styleSheet = file.readAll().toString();
947                 file.close();
948                 setStyleSheet(styleSheet);
949         }
950         // Save column widths for the next time
951         private void saveNoteIndexWidth() {
952                 int width;
953         width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
954         Global.setColumnWidth("noteTableCreationPosition", width);
955                 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
956                 Global.setColumnWidth("noteTableChangedPosition", width);
957                 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
958                 Global.setColumnWidth("noteTableGuidPosition", width);
959                 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
960                 Global.setColumnWidth("noteTableNotebookPosition", width);
961                 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
962                 Global.setColumnWidth("noteTableTagPosition", width);
963                 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
964                 Global.setColumnWidth("noteTableTitlePosition", width);
965                 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
966                 Global.setColumnWidth("noteTableSourceUrlPosition", width);
967                 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
968                 Global.setColumnWidth("noteTableAuthorPosition", width);
969                 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
970                 Global.setColumnWidth("noteTableSubjectDatePosition", width);
971                 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
972                 Global.setColumnWidth("noteTableSynchronizedPosition", width);
973         }
974         
975         
976     //***************************************************************
977     //***************************************************************
978     //** These functions deal with Notebook menu items
979     //***************************************************************
980     //***************************************************************
981     // Setup the tree containing the user's notebooks.
982     private void initializeNotebookTree() {       
983         logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
984         notebookTree.itemSelectionChanged.connect(this, "notebookTreeSelection()");
985         listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
986  //     notebookTree.resize(Global.getSize("notebookTree"));
987         logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
988     }   
989     // Listener when a notebook is selected
990     @SuppressWarnings("unused")
991         private void notebookTreeSelection() {
992                 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
993
994                 clearTrashFilter();
995                 clearAttributeFilter();
996                 clearSavedSearchFilter();
997                 if (Global.mimicEvernoteInterface) {
998                         clearTagFilter();
999                         searchField.clear();
1000                 }
1001                 
1002                 menuBar.noteRestoreAction.setVisible(false);            
1003         menuBar.notebookEditAction.setEnabled(true);
1004         menuBar.notebookDeleteAction.setEnabled(true);
1005         List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1006         QTreeWidgetItem currentSelection;
1007         selectedNotebookGUIDs.clear();
1008         if (!Global.mimicEvernoteInterface) {
1009                 for (int i=0; i<selections.size(); i++) {
1010                         currentSelection = selections.get(i);
1011                         selectedNotebookGUIDs.add(currentSelection.text(2));
1012                 }
1013         
1014                 
1015                 // There is the potential for no notebooks to be selected if this 
1016                 // happens then we make it look like all notebooks were selecetd.
1017                 // If that happens, just select the "all notebooks"
1018                 selections = notebookTree.selectedItems();
1019                 if (selections.size()==0) {
1020                         selectedNotebookGUIDs.clear();
1021                         menuBar.notebookEditAction.setEnabled(false);
1022                         menuBar.notebookDeleteAction.setEnabled(false);
1023                 }
1024         } else {
1025                 String guid = "";
1026                 if (selections.size() > 0)
1027                         guid = (selections.get(0).text(2));
1028                 if (!guid.equals(""))
1029                         selectedNotebookGUIDs.add(guid);
1030         }
1031         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1032         listManager.loadNotesIndex();
1033         noteIndexUpdated(false);
1034                 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
1035
1036     }
1037     private void clearNotebookFilter() {
1038         notebookTree.blockSignals(true);
1039         notebookTree.clearSelection();
1040                 menuBar.noteRestoreAction.setVisible(false);
1041         menuBar.notebookEditAction.setEnabled(false);
1042         menuBar.notebookDeleteAction.setEnabled(false);
1043         selectedNotebookGUIDs.clear();
1044         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1045         notebookTree.blockSignals(false);
1046     }
1047         // Triggered when the notebook DB has been updated
1048         private void notebookIndexUpdated() {
1049                 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1050                 if (selectedNotebookGUIDs == null)
1051                         selectedNotebookGUIDs = new ArrayList<String>();
1052                 List<Notebook> books = conn.getNotebookTable().getAll();
1053                 for (int i=books.size()-1; i>=0; i--) {
1054                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1055                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1056                                         books.remove(i);
1057                                         j=listManager.getArchiveNotebookIndex().size();
1058                                 }
1059                         }
1060                 }
1061                 
1062                 
1063                 listManager.countNotebookResults(listManager.getNoteIndex());
1064                 notebookTree.blockSignals(true);
1065         notebookTree.load(books, listManager.getLocalNotebooks());
1066         for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1067                 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1068                 if (!found)
1069                         selectedNotebookGUIDs.remove(i);
1070         }
1071         notebookTree.blockSignals(false);
1072         
1073                 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1074     }
1075     // Show/Hide note information
1076         private void toggleNotebookWindow() {
1077                 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1078         if (notebookTree.isVisible())
1079                 notebookTree.hide();
1080         else
1081                 notebookTree.show();
1082         menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1083         Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1084         logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1085     }   
1086         // Add a new notebook
1087         @SuppressWarnings("unused")
1088         private void addNotebook() {
1089                 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1090                 NotebookEdit edit = new NotebookEdit();
1091                 edit.setNotebooks(listManager.getNotebookIndex());
1092                 edit.exec();
1093         
1094                 if (!edit.okPressed())
1095                         return;
1096         
1097                 Calendar currentTime = new GregorianCalendar();
1098                 Long l = new Long(currentTime.getTimeInMillis());
1099                 String randint = new String(Long.toString(l));
1100         
1101                 Notebook newBook = new Notebook();
1102                 newBook.setUpdateSequenceNum(0);
1103                 newBook.setGuid(randint);
1104                 newBook.setName(edit.getNotebook());
1105                 newBook.setServiceCreated(new Date().getTime());
1106                 newBook.setServiceUpdated(new Date().getTime());
1107                 newBook.setDefaultNotebook(false);
1108                 newBook.setPublished(false);
1109                 
1110                 listManager.getNotebookIndex().add(newBook);
1111                 if (edit.isLocal())
1112                         listManager.getLocalNotebooks().add(newBook.getGuid());
1113                 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1114                 notebookIndexUpdated();
1115                 listManager.countNotebookResults(listManager.getNoteIndex());
1116 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1117                 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1118         }
1119         // Edit an existing notebook
1120         @SuppressWarnings("unused")
1121         private void editNotebook() {
1122                 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1123                 NotebookEdit edit = new NotebookEdit();
1124                 edit.setTitle("Edit Notebook");
1125                 edit.setLocalCheckboxEnabled(false);
1126                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1127                 QTreeWidgetItem currentSelection;
1128                 currentSelection = selections.get(0);
1129                 edit.setNotebook(currentSelection.text(0));
1130                 edit.setNotebooks(listManager.getNotebookIndex());
1131                 edit.exec();
1132         
1133                 if (!edit.okPressed())
1134                         return;
1135         
1136                 String guid = currentSelection.text(2);
1137                 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1138                 currentSelection.setText(0, edit.getNotebook());
1139                 
1140                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1141                         if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1142                                 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1143                                 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1144                                 i=listManager.getNotebookIndex().size();
1145                         }
1146                 }
1147                 
1148                 // Build a list of non-closed notebooks
1149                 List<Notebook> nbooks = new ArrayList<Notebook>();
1150                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1151                         boolean found=false;
1152                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1153                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1154                                         found = true;
1155                         }
1156                         if (!found)
1157                                 nbooks.add(listManager.getNotebookIndex().get(i));
1158                 }
1159                 
1160                 browserWindow.setNotebookList(nbooks);
1161                 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1162         }
1163         // Delete an existing notebook
1164         @SuppressWarnings("unused")
1165         private void deleteNotebook() {
1166                 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1167                 boolean assigned = false;
1168                 // Check if any notes have this notebook
1169                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1170         for (int i=0; i<selections.size(); i++) {
1171                 QTreeWidgetItem currentSelection;
1172                 currentSelection = selections.get(i);
1173                 String guid = currentSelection.text(2);
1174                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
1175                         String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
1176                         if (noteGuid.equals(guid)) {
1177                                 assigned = true;
1178                                 j=listManager.getNoteIndex().size();
1179                                 i=selections.size();
1180                         }
1181                 }
1182         }
1183                 if (assigned) {
1184                         QMessageBox.information(this, "Unable to Delete", "Some of the selected notebook(s) contain notes.\n"+
1185                                         "Please delete the notes or move them to another notebook before deleting any notebooks.");
1186                         return;
1187                 }
1188                 
1189                 if (conn.getNotebookTable().getAll().size() == 1) {
1190                         QMessageBox.information(this, "Unable to Delete", "You must have at least one notebook.");
1191                         return;
1192                 }
1193         
1194         // If all notebooks are clear, verify the delete
1195                 if (QMessageBox.question(this, "Confirmation", "Delete the selected notebooks?",
1196                         QMessageBox.StandardButton.Yes, 
1197                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1198                         return;
1199                 }
1200                 
1201                 // If confirmed, delete the notebook
1202         for (int i=selections.size()-1; i>=0; i--) {
1203                 QTreeWidgetItem currentSelection;
1204                 currentSelection = selections.get(i);
1205                 String guid = currentSelection.text(2);
1206                 conn.getNotebookTable().expungeNotebook(guid, true);
1207                 listManager.deleteNotebook(guid);
1208         }
1209 //        for (int i=<dbRunner.getLocalNotebooks().size()-1; i>=0; i--) {
1210  //             if (dbRunner.getLocalNotebooks().get(i).equals(arg0))
1211  //       }
1212         notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
1213         listManager.countNotebookResults(listManager.getNoteIndex());
1214 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1215         logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1216         }
1217         // A note's notebook has been updated
1218         @SuppressWarnings("unused")
1219         private void updateNoteNotebook(String guid, String notebookGuid) {
1220                 
1221                 // Update the list manager
1222                 listManager.updateNoteNotebook(guid, notebookGuid);
1223                 listManager.countNotebookResults(listManager.getNoteIndex());
1224 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());    
1225                 
1226                 // Find the name of the notebook
1227                 String notebookName = null;
1228                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1229                         if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
1230                                 notebookName = listManager.getNotebookIndex().get(i).getName();
1231                                 i=listManager.getNotebookIndex().size();
1232                         }
1233                 }
1234                 
1235                 // If we found the name, update the browser window
1236                 if (notebookName != null) {
1237                         updateListNoteNotebook(guid, notebookName);
1238                         if (guid.equals(currentNoteGuid)) {
1239                                 int pos =  browserWindow.notebookBox.findText(notebookName);
1240                                 if (pos >=0)
1241                                         browserWindow.notebookBox.setCurrentIndex(pos);
1242                         }
1243                 }
1244                 
1245                 // If we're dealing with the current note, then we need to be sure and update the notebook there
1246                 if (guid.equals(currentNoteGuid)) {
1247                         if (currentNote != null) {
1248                                 currentNote.setNotebookGuid(notebookGuid);
1249                         }
1250                 }
1251         }
1252         // Open/close notebooks
1253         @SuppressWarnings("unused")
1254         private void closeNotebooks() {
1255                 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
1256                 na.exec();
1257                 if (!na.okClicked())
1258                         return;
1259                 
1260                 waitCursor(true);
1261                 listManager.getArchiveNotebookIndex().clear();
1262                 
1263                 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
1264                         String text = na.getClosedBookList().takeItem(i).text();
1265                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1266                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1267                                         Notebook n = listManager.getNotebookIndex().get(j);
1268                                         conn.getNotebookTable().setArchived(n.getGuid(),true);
1269                                         listManager.getArchiveNotebookIndex().add(n);
1270                                         j=listManager.getNotebookIndex().size();
1271                                 }
1272                         }
1273                 }
1274                 
1275                 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
1276                         String text = na.getOpenBookList().takeItem(i).text();
1277                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1278                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1279                                         Notebook n = listManager.getNotebookIndex().get(j);
1280                                         conn.getNotebookTable().setArchived(n.getGuid(),false);
1281                                         j=listManager.getNotebookIndex().size();
1282                                 }
1283                         }
1284                 }
1285                 
1286                 listManager.loadNotesIndex();
1287                 notebookIndexUpdated();
1288                 noteIndexUpdated(true);
1289 //              noteIndexUpdated(false);
1290                 
1291                 // Build a list of non-closed notebooks
1292                 List<Notebook> nbooks = new ArrayList<Notebook>();
1293                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1294                         boolean found=false;
1295                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1296                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1297                                         found = true;
1298                         }
1299                         if (!found)
1300                                 nbooks.add(listManager.getNotebookIndex().get(i));
1301                 }
1302                 waitCursor(false);
1303                 browserWindow.setNotebookList(nbooks);
1304         }
1305
1306         
1307         
1308         
1309         
1310     //***************************************************************
1311     //***************************************************************
1312     //** These functions deal with Tag menu items
1313     //***************************************************************
1314     //***************************************************************
1315         // Add a new notebook
1316         @SuppressWarnings("unused")
1317         private void addTag() {
1318                 logger.log(logger.HIGH, "Inside NeverNote.addTag");
1319                 TagEdit edit = new TagEdit();
1320                 edit.setTagList(listManager.getTagIndex());
1321                 edit.exec();
1322         
1323                 if (!edit.okPressed())
1324                         return;
1325         
1326                 Calendar currentTime = new GregorianCalendar();
1327                 Long l = new Long(currentTime.getTimeInMillis());
1328                 String randint = new String(Long.toString(l));
1329         
1330                 Tag newTag = new Tag();
1331                 newTag.setUpdateSequenceNum(0);
1332                 newTag.setGuid(randint);
1333                 newTag.setName(edit.getTag());
1334                 conn.getTagTable().addTag(newTag, true);
1335                 listManager.getTagIndex().add(newTag);
1336                 reloadTagTree();
1337                 
1338                 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
1339         }
1340         private void reloadTagTree() {
1341                 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
1342                 tagIndexUpdated(false);
1343                 boolean filter = false;
1344                 listManager.countTagResults(listManager.getNoteIndex());
1345                 if (notebookTree.selectedItems().size() > 0 
1346                                                   && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
1347                                                   filter = true;
1348                 if (tagTree.selectedItems().size() > 0)
1349                         filter = true;
1350                 tagTree.showAllTags(!filter);
1351                 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
1352         }
1353         // Edit an existing tag
1354         @SuppressWarnings("unused")
1355         private void editTag() {
1356                 logger.log(logger.HIGH, "Entering NeverNote.editTag");
1357                 TagEdit edit = new TagEdit();
1358                 edit.setTitle("Edit Tag");
1359                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1360                 QTreeWidgetItem currentSelection;
1361                 currentSelection = selections.get(0);
1362                 edit.setTag(currentSelection.text(0));
1363                 edit.setTagList(listManager.getTagIndex());
1364                 edit.exec();
1365         
1366                 if (!edit.okPressed())
1367                         return;
1368         
1369                 String guid = currentSelection.text(2);
1370                 currentSelection.setText(0,edit.getTag());
1371                 
1372                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1373                         if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
1374                                 listManager.getTagIndex().get(i).setName(edit.getTag());
1375                                 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
1376                                 updateListTagName(guid);
1377                                 if (currentNote != null && currentNote.getTagGuids().contains(guid))
1378                                         browserWindow.setTag(getTagNamesForNote(currentNote));
1379                                 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
1380                                 return;
1381                         }
1382                 }
1383                 browserWindow.setTag(getTagNamesForNote(currentNote));
1384                 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
1385         }
1386         // Delete an existing tag
1387         @SuppressWarnings("unused")
1388         private void deleteTag() {
1389                 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
1390                 
1391                 if (QMessageBox.question(this, "Confirmation", "Delete the selected tags?",
1392                         QMessageBox.StandardButton.Yes, 
1393                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1394                                                         return;
1395                 }
1396                 
1397                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1398         for (int i=selections.size()-1; i>=0; i--) {
1399                 QTreeWidgetItem currentSelection;
1400                 currentSelection = selections.get(i);                   
1401                 removeTagItem(currentSelection.text(2));
1402         }
1403         tagIndexUpdated(true);
1404         listManager.countTagResults(listManager.getNoteIndex());
1405 //              tagTree.updateCounts(listManager.getTagCounter());
1406         logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
1407         }
1408         // Remove a tag tree item.  Go recursively down & remove the children too
1409         private void removeTagItem(String guid) {
1410         for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {             
1411                 String parent = listManager.getTagIndex().get(j).getParentGuid();
1412                 if (parent != null && parent.equals(guid)) {            
1413                         //Remove this tag's children
1414                         removeTagItem(listManager.getTagIndex().get(j).getGuid());
1415                 }
1416         }
1417         //Now, remove this tag
1418         removeListTagName(guid);
1419         conn.getTagTable().expungeTag(guid, true);                      
1420         for (int a=0; a<listManager.getTagIndex().size(); a++) {
1421                 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
1422                         listManager.getTagIndex().remove(a);
1423                         return;
1424                 }
1425         }
1426         }
1427         // Setup the tree containing the user's tags
1428     private void initializeTagTree() {
1429         logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
1430         tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
1431         listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
1432         logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
1433     }
1434     // Listener when a tag is selected
1435     @SuppressWarnings("unused")
1436         private void tagTreeSelection() {
1437         logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
1438         
1439         List<QTreeWidgetItem> x = tagTree.selectedItems();
1440         for (int i=0; i<x.size(); i++) {
1441         }
1442         
1443         clearTrashFilter();
1444         clearAttributeFilter();
1445         clearSavedSearchFilter();
1446         
1447                 menuBar.noteRestoreAction.setVisible(false);
1448                 
1449         List<QTreeWidgetItem> selections = tagTree.selectedItems();
1450         QTreeWidgetItem currentSelection;
1451         selectedTagGUIDs.clear();
1452         for (int i=0; i<selections.size(); i++) {
1453                 currentSelection = selections.get(i);
1454                 selectedTagGUIDs.add(currentSelection.text(2));
1455         }
1456         if (selections.size() > 0) {
1457                 menuBar.tagEditAction.setEnabled(true);
1458                 menuBar.tagDeleteAction.setEnabled(true);
1459         }
1460         else {
1461                 menuBar.tagEditAction.setEnabled(false);
1462                 menuBar.tagDeleteAction.setEnabled(false);
1463         }
1464         listManager.setSelectedTags(selectedTagGUIDs);
1465         listManager.loadNotesIndex();
1466         noteIndexUpdated(false);
1467         logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
1468     }
1469     // trigger the tag index to be refreshed
1470     @SuppressWarnings("unused")
1471         private void tagIndexUpdated() {
1472         tagIndexUpdated(true);
1473     }
1474     private void tagIndexUpdated(boolean reload) {
1475         logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
1476                 if (selectedTagGUIDs == null)
1477                         selectedTagGUIDs = new ArrayList<String>();
1478 //              selectedTagGUIDs.clear();  // clear out old entries
1479
1480                 tagTree.blockSignals(true);
1481                 if (reload)
1482                         tagTree.load(listManager.getTagIndex());
1483         for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
1484                 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
1485                 if (!found)
1486                         selectedTagGUIDs.remove(i);
1487         }
1488         tagTree.blockSignals(false);
1489         
1490                 browserWindow.setTag(getTagNamesForNote(currentNote));
1491         logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
1492     }   
1493     // Show/Hide note information
1494         private void toggleTagWindow() {
1495                 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
1496         if (tagTree.isVisible())
1497                 tagTree.hide();
1498         else
1499                 tagTree.show();
1500         menuBar.hideTags.setChecked(tagTree.isVisible());
1501         Global.saveWindowVisible("tagTree", tagTree.isVisible());
1502         logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
1503     }   
1504         // A note's tags have been updated
1505         @SuppressWarnings("unused")
1506         private void updateNoteTags(String guid, List<String> tags) {
1507                 listManager.saveNoteTags(guid, tags);
1508                 listManager.countTagResults(listManager.getNoteIndex());
1509                 StringBuffer names = new StringBuffer("");
1510                 for (int i=0; i<tags.size(); i++) {
1511                         names = names.append(tags.get(i));
1512                         if (i<tags.size()-1) {
1513                                 names.append(Global.tagDelimeter + " ");
1514                         }
1515                 }
1516                 browserWindow.setTag(names.toString());
1517                 noteDirty = true;
1518 //              tagTree.updateCounts(listManager.getTagCounter());
1519         }
1520         // Get a string containing all tag names for a note
1521         private String getTagNamesForNote(Note n) {
1522                 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
1523                 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
1524                         return "";
1525                 StringBuffer buffer = new StringBuffer(100);
1526                 Vector<String> v = new Vector<String>();
1527                 List<String> guids = n.getTagGuids();
1528                 
1529                 if (guids == null) 
1530                         return "";
1531                 
1532                 for (int i=0; i<guids.size(); i++) {
1533                         v.add(listManager.getTagNameByGuid(guids.get(i)));
1534                 }
1535                 Comparator<String> comparator = Collections.reverseOrder();
1536                 Collections.sort(v,comparator);
1537                 Collections.reverse(v);
1538                 
1539                 for (int i = 0; i<v.size(); i++) {
1540                         if (i>0) 
1541                                 buffer.append(", ");
1542                         buffer.append(v.get(i));
1543                 }
1544                 
1545                 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
1546                 return buffer.toString();
1547         }       
1548         // Tags were added via dropping notes from the note list
1549         @SuppressWarnings("unused")
1550         private void tagsAdded(String noteGuid, String tagGuid) {
1551                 String tagName = null;
1552                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1553                         if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
1554                                 tagName = listManager.getTagIndex().get(i).getName();
1555                                 i=listManager.getTagIndex().size();
1556                         }
1557                 }
1558                 if (tagName == null)
1559                         return;
1560                 
1561                 for (int i=0; i<noteTableView.model.rowCount(); i++) {
1562                         QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
1563                         if (modelIndex != null) {
1564                                 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
1565                                 String titleGuid = (String)ix.values().toArray()[0];
1566                                 if (titleGuid.equals(noteGuid)) {
1567                                         String text = (String)noteTableView.model.data(i, Global.noteTableTagPosition);
1568                                         if (!text.trim().equals(""))
1569                                                 text = text + Global.tagDelimeter + " " +tagName;
1570                                         else
1571                                                 text = tagName;
1572                                         noteTableView.model.setData(i, Global.noteTableTagPosition, text);
1573                                         noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
1574                                         if (noteGuid.equals(currentNoteGuid))
1575                                                 browserWindow.setTag(text);
1576                                         i=noteTableView.model.rowCount();
1577                                 }
1578                         }
1579                 }
1580         }
1581         private void clearTagFilter() {
1582                 tagTree.blockSignals(true);
1583                 tagTree.clearSelection();
1584                 menuBar.noteRestoreAction.setVisible(false);
1585                 menuBar.tagEditAction.setEnabled(false);
1586                 menuBar.tagDeleteAction.setEnabled(false);
1587                 selectedTagGUIDs.clear();
1588         listManager.setSelectedTags(selectedTagGUIDs);
1589         tagTree.blockSignals(false);
1590         }
1591         
1592         
1593     //***************************************************************
1594     //***************************************************************
1595     //** These functions deal with Saved Search menu items
1596     //***************************************************************
1597     //***************************************************************
1598         // Add a new notebook
1599         @SuppressWarnings("unused")
1600         private void addSavedSearch() {
1601                 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
1602                 SavedSearchEdit edit = new SavedSearchEdit();
1603                 edit.setSearchList(listManager.getSavedSearchIndex());
1604                 edit.exec();
1605         
1606                 if (!edit.okPressed())
1607                         return;
1608         
1609                 Calendar currentTime = new GregorianCalendar();         
1610                 Long l = new Long(currentTime.getTimeInMillis());
1611                 String randint = new String(Long.toString(l));
1612         
1613                 SavedSearch search = new SavedSearch();
1614                 search.setUpdateSequenceNum(0);
1615                 search.setGuid(randint);
1616                 search.setName(edit.getName());
1617                 search.setQuery(edit.getQuery());
1618                 search.setFormat(QueryFormat.USER);
1619                 listManager.getSavedSearchIndex().add(search);
1620                 conn.getSavedSearchTable().addSavedSearch(search, true);
1621                 savedSearchIndexUpdated();
1622                 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
1623         }
1624         // Edit an existing tag
1625         @SuppressWarnings("unused")
1626         private void editSavedSearch() {
1627                 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
1628                 SavedSearchEdit edit = new SavedSearchEdit();
1629                 edit.setTitle("Edit Search");
1630                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1631                 QTreeWidgetItem currentSelection;
1632                 currentSelection = selections.get(0);
1633                 String guid = currentSelection.text(1);
1634                 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
1635                 edit.setName(currentSelection.text(0));
1636                 edit.setQuery(s.getQuery());
1637                 edit.setSearchList(listManager.getSavedSearchIndex());
1638                 edit.exec();
1639         
1640                 if (!edit.okPressed())
1641                         return;
1642         
1643                 List<SavedSearch> list = listManager.getSavedSearchIndex();
1644                 SavedSearch search = null;
1645                 boolean found = false;
1646                 for (int i=0; i<list.size(); i++) {
1647                         search = list.get(i);
1648                         if (search.getGuid().equals(guid)) {
1649                                 i=list.size();
1650                                 found = true;
1651                         }
1652                 }
1653                 if (!found)
1654                         return;
1655                 search.setName(edit.getName());
1656                 search.setQuery(edit.getQuery());
1657                 conn.getSavedSearchTable().updateSavedSearch(search, true);
1658                 savedSearchIndexUpdated();
1659                 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
1660         }
1661         // Delete an existing tag
1662         @SuppressWarnings("unused")
1663         private void deleteSavedSearch() {
1664                 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
1665                 
1666                 if (QMessageBox.question(this, "Confirmation", "Delete the selected search?",
1667                         QMessageBox.StandardButton.Yes, 
1668                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1669                                                         return;
1670                 }
1671                 
1672                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1673         for (int i=selections.size()-1; i>=0; i--) {
1674                 QTreeWidgetItem currentSelection;
1675                 currentSelection = selections.get(i);
1676                 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
1677                         if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
1678                                 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
1679                                 listManager.getSavedSearchIndex().remove(j);
1680                                 j=listManager.getSavedSearchIndex().size()+1;
1681                         }
1682                 }
1683                 selections.remove(i);
1684         }
1685         savedSearchIndexUpdated();
1686         logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
1687         }
1688     // Setup the tree containing the user's tags
1689     private void initializeSavedSearchTree() {
1690         logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
1691         savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
1692         logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
1693     }
1694     // Listener when a tag is selected
1695     @SuppressWarnings("unused")
1696         private void savedSearchTreeSelection() {
1697         logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
1698
1699         clearNotebookFilter();
1700         clearTagFilter();
1701         clearTrashFilter();
1702         clearAttributeFilter();
1703         
1704         String currentGuid = selectedSavedSearchGUID;
1705         menuBar.savedSearchEditAction.setEnabled(true);
1706         menuBar.savedSearchDeleteAction.setEnabled(true);
1707         List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1708         QTreeWidgetItem currentSelection;
1709         selectedSavedSearchGUID = "";
1710         for (int i=0; i<selections.size(); i++) {
1711                 currentSelection = selections.get(i);
1712                 if (currentSelection.text(1).equals(currentGuid)) {
1713                         currentSelection.setSelected(false);
1714                 } else {
1715                         selectedSavedSearchGUID = currentSelection.text(1);
1716                 }
1717 //              i = selections.size() +1;
1718         }
1719         
1720         // There is the potential for no notebooks to be selected if this 
1721         // happens then we make it look like all notebooks were selecetd.
1722         // If that happens, just select the "all notebooks"
1723         if (selections.size()==0) {
1724                 clearSavedSearchFilter();
1725         }
1726         listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
1727         
1728         logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
1729     }
1730     private void clearSavedSearchFilter() {
1731         menuBar.savedSearchEditAction.setEnabled(false);
1732         menuBar.savedSearchDeleteAction.setEnabled(false);
1733         savedSearchTree.blockSignals(true);
1734         savedSearchTree.clearSelection();
1735         savedSearchTree.blockSignals(false);
1736         selectedSavedSearchGUID = "";
1737         searchField.setEditText("");
1738         searchPerformed = false;
1739         listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
1740     }
1741     // trigger the tag index to be refreshed
1742         private void savedSearchIndexUpdated() { 
1743                 if (selectedSavedSearchGUID == null)
1744                         selectedSavedSearchGUID = new String();
1745                 savedSearchTree.blockSignals(true);
1746         savedSearchTree.load(listManager.getSavedSearchIndex());
1747         savedSearchTree.selectGuid(selectedSavedSearchGUID);
1748         savedSearchTree.blockSignals(false);
1749     }
1750     // trigger when the saved search selection changes
1751     @SuppressWarnings("unused")
1752         private void updateSavedSearchSelection() {
1753                 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
1754                 
1755         menuBar.savedSearchEditAction.setEnabled(true);
1756         menuBar.savedSearchDeleteAction.setEnabled(true);
1757         List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1758
1759         if (selections.size() > 0) {
1760                 menuBar.savedSearchEditAction.setEnabled(true);
1761                 menuBar.savedSearchDeleteAction.setEnabled(true);
1762                 selectedSavedSearchGUID = selections.get(0).text(1);
1763                 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
1764                 searchField.setEditText(s.getQuery());
1765         } else { 
1766                 menuBar.savedSearchEditAction.setEnabled(false);
1767                 menuBar.savedSearchDeleteAction.setEnabled(false);
1768                 selectedSavedSearchGUID = "";
1769                 searchField.setEditText("");
1770         }
1771         searchFieldChanged();
1772         
1773                 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
1774
1775         
1776     }
1777     // Show/Hide note information
1778         private void toggleSavedSearchWindow() {
1779                 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
1780         if (savedSearchTree.isVisible())
1781                 savedSearchTree.hide();
1782         else
1783                 savedSearchTree.show();
1784         menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
1785                                 
1786                 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
1787         logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
1788     }
1789         
1790         
1791         
1792         
1793     //***************************************************************
1794     //***************************************************************
1795     //** These functions deal with Help menu & tool menu items
1796     //***************************************************************
1797     //***************************************************************
1798         // Show database status
1799         @SuppressWarnings("unused")
1800         private void databaseStatus() {
1801                 waitCursor(true);
1802                 int dirty = conn.getNoteTable().getDirtyCount();
1803                 int unindexed = conn.getNoteTable().getUnindexedCount();
1804                 DatabaseStatus status = new DatabaseStatus();
1805                 status.setUnsynchronized(dirty);
1806                 status.setUnindexed(unindexed);
1807                 status.setNoteCount(conn.getNoteTable().getNoteCount());
1808                 status.setNotebookCount(listManager.getNotebookIndex().size());
1809                 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
1810                 status.setTagCount(listManager.getTagIndex().size());
1811                 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
1812                 status.setWordCount(conn.getWordsTable().getWordCount());
1813                 waitCursor(false);
1814                 status.exec();
1815         }
1816         // Compact the database
1817         @SuppressWarnings("unused")
1818         private void compactDatabase() {
1819         logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
1820                 if (QMessageBox.question(this, "Confirmation", "This will free unused space in the database, "+
1821                                 "but please be aware that depending upon the size of your database this can be time consuming " +
1822                                 "and NeverNote will be unresponsive until it is complete.  Do you wish to continue?",
1823                                 QMessageBox.StandardButton.Yes, 
1824                                 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
1825                                                         return;
1826                 }
1827                 setMessage("Compacting database.");
1828                 waitCursor(true);
1829                 listManager.compactDatabase();
1830                 waitCursor(false);
1831                 setMessage("Database compact is complete.");            
1832         logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
1833     }
1834         @SuppressWarnings("unused")
1835         private void accountInformation() {
1836                 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
1837                 AccountDialog dialog = new AccountDialog();
1838                 dialog.show();
1839                 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
1840         }
1841         @SuppressWarnings("unused")
1842         private void releaseNotes() {
1843                 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
1844                 QDialog dialog = new QDialog(this);
1845                 QHBoxLayout layout = new QHBoxLayout();
1846                 QTextEdit textBox = new QTextEdit();
1847                 layout.addWidget(textBox);
1848                 textBox.setReadOnly(true);
1849                 QFile file = new QFile(Global.getDirectoryPath()+"release.txt");
1850                 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
1851                 QIODevice.OpenModeFlag.Text)))
1852                         return;
1853                 textBox.setText(file.readAll().toString());
1854                 file.close();
1855                 dialog.setWindowTitle("Release Notes");
1856                 dialog.setLayout(layout);
1857                 dialog.show();
1858                 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
1859         }
1860         // Called when user picks Log from the help menu
1861         @SuppressWarnings("unused")
1862         private void logger() {
1863                 logger.log(logger.HIGH, "Entering NeverNote.logger");
1864                 QDialog dialog = new QDialog(this);
1865                 QHBoxLayout layout = new QHBoxLayout();
1866                 QListWidget textBox = new QListWidget();
1867                 layout.addWidget(textBox);
1868                 textBox.addItems(emitLog);
1869                 
1870                 dialog.setLayout(layout);
1871                 dialog.setWindowTitle("Mesasge Log");
1872                 dialog.show();
1873                 logger.log(logger.HIGH, "Leaving NeverNote.logger");
1874         }
1875         // Menu option "help/about" was selected
1876         @SuppressWarnings("unused")
1877         private void about() {
1878                 logger.log(logger.HIGH, "Entering NeverNote.about");
1879                 QMessageBox.about(this, 
1880                                                 tr("About NeverNote"),
1881                                                 tr("<h4><center><b>NeverNote</b></center></h4><hr><center>Version "+Global.version+"<hr></center>Evernote"
1882                                                                 +" Generic client.<br><br>" 
1883                                                                 +"Licensed under GPL v2.  <br><hr><br>"
1884                                                                 +"Evernote is copyright 2001-2010 by Evernote Corporation<br>"
1885                                                                 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
1886                                                                 +"PDFRenderer is licened under the LGPL<br>"
1887                                                                 +"Jazzy is licened under the LGPL<br>"
1888                                                                 +"Java is a registered trademark of Sun Microsystems.<br><hr>"));       
1889                 logger.log(logger.HIGH, "Leaving NeverNote.about");
1890         }
1891         // Hide the entire left hand side
1892         @SuppressWarnings("unused")
1893         private void toggleLeftSide() {
1894                 boolean hidden;
1895                 
1896                 hidden = !menuBar.hideLeftSide.isChecked();
1897                 menuBar.hideLeftSide.setChecked(!hidden);
1898                 
1899                 if (notebookTree.isVisible() != hidden)
1900                         toggleNotebookWindow();
1901                 if (savedSearchTree.isVisible() != hidden)
1902                         toggleSavedSearchWindow();
1903                 if (tagTree.isVisible() != hidden)
1904                         toggleTagWindow();
1905                 if (attributeTree.isVisible() != hidden)
1906                         toggleAttributesWindow();
1907                 if (trashTree.isVisible() != hidden)
1908                         toggleTrashWindow();
1909                 
1910                 Global.saveWindowVisible("leftPanel", hidden);
1911                 
1912         }
1913                         
1914         
1915     //***************************************************************
1916     //***************************************************************
1917     //** These functions deal with the Toolbar
1918     //***************************************************************
1919     //***************************************************************  
1920         // Text in the search bar has been cleared
1921         private void searchFieldCleared() {
1922                 searchField.setEditText("");
1923                 saveNoteIndexWidth();
1924         }
1925         // text in the search bar changed.  We only use this to tell if it was cleared, 
1926         // otherwise we trigger off searchFieldChanged.
1927         @SuppressWarnings("unused")
1928         private void searchFieldTextChanged(String text) {
1929                 if (text.trim().equals("")) {
1930                         searchFieldCleared();
1931                         if (searchPerformed) {
1932                                 noteCache.clear();
1933                                 listManager.setEnSearch("");
1934 /////                           listManager.clearNoteIndexSearch();
1935                                 //noteIndexUpdated(true);
1936                                 listManager.loadNotesIndex();
1937                                 refreshEvernoteNote(true);
1938                                 noteIndexUpdated(false);
1939                         }
1940                         searchPerformed = false;
1941                 }
1942         }
1943     // Text in the toolbar has changed
1944     private void searchFieldChanged() {
1945         logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
1946         noteCache.clear();
1947         saveNoteIndexWidth();
1948         String text = searchField.currentText();
1949         listManager.setEnSearch(text.trim());
1950         listManager.loadNotesIndex();
1951 //--->>>        noteIndexUpdated(true);
1952         noteIndexUpdated(false);
1953         refreshEvernoteNote(true);
1954         searchPerformed = true;
1955         logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
1956     }
1957     // Build the window tool bar
1958     private void setupToolBar() {
1959         logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
1960         toolBar = addToolBar(tr("toolBar"));    
1961
1962         prevButton = toolBar.addAction("Previous");
1963         QIcon prevIcon = new QIcon(iconPath+"back.png");
1964         prevButton.setIcon(prevIcon);
1965         prevButton.triggered.connect(this, "previousViewedAction()");   
1966         
1967         nextButton = toolBar.addAction("Next");
1968         QIcon nextIcon = new QIcon(iconPath+"forward.png");
1969         nextButton.setIcon(nextIcon);
1970         nextButton.triggered.connect(this, "nextViewedAction()");       
1971         
1972         upButton = toolBar.addAction("Up");
1973         QIcon upIcon = new QIcon(iconPath+"up.png");
1974         upButton.setIcon(upIcon);
1975         upButton.triggered.connect(this, "upAction()");         
1976         
1977         downButton = toolBar.addAction("Down");
1978         QIcon downIcon = new QIcon(iconPath+"down.png");
1979         downButton.setIcon(downIcon);
1980         downButton.triggered.connect(this, "downAction()");
1981         
1982         synchronizeButton = toolBar.addAction("Synchronize");
1983         synchronizeAnimation = new ArrayList<QIcon>();
1984         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-0.png"));
1985         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-1.png"));
1986         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-2.png"));
1987         synchronizeAnimation.add(new QIcon(iconPath+"synchronize-3.png"));
1988         synchronizeButton.setIcon(synchronizeAnimation.get(0));
1989         synchronizeFrame = 0;
1990         synchronizeButton.triggered.connect(this, "evernoteSync()");
1991         
1992         printButton = toolBar.addAction("Print");
1993         QIcon printIcon = new QIcon(iconPath+"print.png");
1994         printButton.setIcon(printIcon);
1995         printButton.triggered.connect(this, "printNote()");
1996         
1997         tagButton = toolBar.addAction("Tag"); 
1998         QIcon tagIcon = new QIcon(iconPath+"tag.png");
1999         tagButton.setIcon(tagIcon);
2000         tagButton.triggered.connect(browserWindow, "modifyTags()");
2001         
2002         attributeButton = toolBar.addAction("Attributes"); 
2003         QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
2004         attributeButton.setIcon(attributeIcon);
2005         attributeButton.triggered.connect(this, "toggleNoteInformation()");
2006                 
2007         emailButton = toolBar.addAction("Email");
2008         QIcon emailIcon = new QIcon(iconPath+"email.png");
2009         emailButton.setIcon(emailIcon);
2010         emailButton.triggered.connect(this, "emailNote()");
2011         
2012         deleteButton = toolBar.addAction("Delete");     
2013         QIcon deleteIcon = new QIcon(iconPath+"delete.png");
2014         deleteButton.setIcon(deleteIcon);
2015         deleteButton.triggered.connect(this, "deleteNote()");
2016                 
2017         newButton = toolBar.addAction("New");
2018         QIcon newIcon = new QIcon(iconPath+"new.png");
2019         newButton.triggered.connect(this, "addNote()");
2020         newButton.setIcon(newIcon);
2021         toolBar.addSeparator();
2022         toolBar.addWidget(new QLabel("Quota:"));
2023         toolBar.addWidget(quotaBar);
2024         //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
2025         updateQuotaBar();
2026         
2027         // Setup the zoom
2028         zoomSpinner = new QSpinBox();
2029         zoomSpinner.setMinimum(10);
2030         zoomSpinner.setMaximum(1000);
2031         zoomSpinner.setAccelerated(true);
2032         zoomSpinner.setSingleStep(10);
2033         zoomSpinner.setValue(100);
2034         zoomSpinner.valueChanged.connect(this, "zoomChanged()");
2035         toolBar.addWidget(new QLabel("Zoom"));
2036         toolBar.addWidget(zoomSpinner);
2037         
2038         //toolBar.addWidget(new QLabel("                    "));
2039         toolBar.addSeparator();
2040         toolBar.addWidget(new QLabel("  Search:"));
2041         toolBar.addWidget(searchField);
2042         QSizePolicy sizePolicy = new QSizePolicy();
2043         sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
2044         searchField.setSizePolicy(sizePolicy);
2045         searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
2046
2047         searchClearButton = toolBar.addAction("Search Clear");
2048         QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
2049         searchClearButton.setIcon(searchClearIcon);
2050         searchClearButton.triggered.connect(this, "searchFieldCleared()");
2051         
2052         logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
2053     }
2054     // Update the sychronize button picture
2055     @SuppressWarnings("unused")
2056         private void updateSyncButton() {
2057         synchronizeFrame++;
2058         if (synchronizeFrame == 4) 
2059                 synchronizeFrame = 0;
2060         synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame));
2061     }
2062     // Synchronize with Evernote
2063         @SuppressWarnings("unused")
2064         private void evernoteSync() {
2065         logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
2066         if (!Global.isConnected)
2067                 remoteConnect();
2068         if (Global.isConnected)
2069                 synchronizeAnimationTimer.start(200);
2070         syncTimer();
2071         logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
2072     }
2073     private void updateQuotaBar() {
2074         long limit = Global.getUploadLimit();
2075         long amount = Global.getUploadAmount();
2076         if (amount>0 && limit>0) {
2077                 int percent =(int)(amount*100/limit);
2078                 quotaBar.setValue(percent);
2079         } else 
2080                 quotaBar.setValue(0);
2081     }
2082         // Zoom changed
2083     @SuppressWarnings("unused")
2084         private void zoomChanged() {
2085         browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
2086     }
2087
2088     //****************************************************************
2089     //****************************************************************
2090     //* System Tray functions
2091     //****************************************************************
2092     //****************************************************************
2093         private void trayToggleVisible() {
2094         if (isVisible()) {
2095                 hide();
2096         } else {
2097                 show();
2098                 raise();
2099         }
2100     }
2101     @SuppressWarnings("unused")
2102         private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
2103         if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
2104                 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
2105                 trayToggleVisible();
2106         }
2107     }
2108     
2109     
2110     //***************************************************************
2111     //***************************************************************
2112     //** These functions deal with the trash tree
2113     //***************************************************************
2114     //***************************************************************    
2115     // Setup the tree containing the trash.
2116     @SuppressWarnings("unused")
2117         private void trashTreeSelection() {     
2118         logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
2119         
2120         clearNotebookFilter();
2121         clearTagFilter();
2122         clearAttributeFilter();
2123         clearSavedSearchFilter();
2124         
2125         String tempGuid = currentNoteGuid;
2126         
2127 //      currentNoteGuid = "";
2128         currentNote = new Note();
2129         selectedNoteGUIDs.clear();
2130         listManager.getSelectedNotebooks().clear();
2131         listManager.getSelectedTags().clear();
2132         listManager.setSelectedSavedSearch("");
2133         browserWindow.clear();
2134     
2135         // toggle the add buttons
2136         newButton.setEnabled(!newButton.isEnabled());
2137         menuBar.noteAdd.setEnabled(newButton.isEnabled());
2138         menuBar.noteAdd.setVisible(true);
2139         
2140         List<QTreeWidgetItem> selections = trashTree.selectedItems();
2141         if (selections.size() == 0) {
2142                 currentNoteGuid = trashNoteGuid;
2143                         trashNoteGuid = tempGuid;
2144                 Global.showDeleted = false;
2145                 menuBar.noteRestoreAction.setEnabled(false);
2146                 menuBar.noteRestoreAction.setVisible(false);
2147         }
2148         else {
2149                 currentNoteGuid = trashNoteGuid;
2150                         trashNoteGuid = tempGuid;
2151                 menuBar.noteRestoreAction.setEnabled(true);
2152                 menuBar.noteRestoreAction.setVisible(true);
2153                 Global.showDeleted = true;
2154         }
2155         listManager.loadNotesIndex();
2156         noteIndexUpdated(false);
2157 ////            browserWindow.setEnabled(newButton.isEnabled());
2158         browserWindow.setReadOnly(!newButton.isEnabled());
2159         logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
2160     }
2161     // Empty the trash file
2162     @SuppressWarnings("unused")
2163         private void emptyTrash() {
2164 //      browserWindow.clear();
2165         listManager.emptyTrash();
2166         if (trashTree.selectedItems().size() > 0) {
2167                 listManager.getSelectedNotebooks().clear();
2168                 listManager.getSelectedTags().clear();
2169                 listManager.setSelectedSavedSearch("");
2170                 newButton.setEnabled(!newButton.isEnabled());
2171                 menuBar.noteAdd.setEnabled(newButton.isEnabled());
2172                 menuBar.noteAdd.setVisible(true);
2173                 browserWindow.clear();
2174                 
2175                 clearTagFilter();
2176                 clearNotebookFilter();
2177                 clearSavedSearchFilter();
2178                 clearAttributeFilter();
2179                         
2180                 Global.showDeleted = false;
2181                 menuBar.noteRestoreAction.setEnabled(false);
2182                 menuBar.noteRestoreAction.setVisible(false);
2183                 
2184                 listManager.loadNotesIndex();
2185 //--->>>                noteIndexUpdated(true);
2186                 noteIndexUpdated(false);
2187         }       
2188    }
2189     // Show/Hide trash window
2190         private void toggleTrashWindow() {
2191                 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
2192         if (trashTree.isVisible())
2193                 trashTree.hide();
2194         else
2195                 trashTree.show();
2196         menuBar.hideTrash.setChecked(trashTree.isVisible());
2197         
2198                 Global.saveWindowVisible("trashTree", trashTree.isVisible());
2199         logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
2200     }    
2201         private void clearTrashFilter() {
2202                 Global.showDeleted = false;
2203         newButton.setEnabled(true);
2204         menuBar.noteAdd.setEnabled(true);
2205         menuBar.noteAdd.setVisible(true);
2206                 trashTree.blockSignals(true);
2207                 trashTree.clearSelection();
2208                 trashTree.blockSignals(false);
2209                 
2210         }
2211     
2212    
2213     //***************************************************************
2214     //***************************************************************
2215     //** These functions deal with connection settings
2216     //***************************************************************
2217     //***************************************************************
2218         // SyncRunner had a problem and things are disconnected
2219         @SuppressWarnings("unused")
2220         private void remoteErrorDisconnect() {
2221                 menuBar.connectAction.setText("Connect");
2222                 menuBar.connectAction.setToolTip("Connect to Evernote");
2223                 menuBar.synchronizeAction.setEnabled(false);
2224                 synchronizeAnimationTimer.stop();
2225                 return;
2226         }
2227         // Do a manual connect/disconnect
2228     private void remoteConnect() {
2229         logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
2230
2231         if (Global.isConnected) {
2232                 Global.isConnected = false;
2233                 syncRunner.enDisconnect();
2234                 setupConnectMenuOptions();
2235                 setupOnlineMenu();
2236                 return;
2237         }
2238         
2239         AESEncrypter aes = new AESEncrypter();
2240         try {
2241                         aes.decrypt(new FileInputStream(Global.getDirectoryPath()+"secure.txt"));
2242                 } catch (FileNotFoundException e) {
2243                         // File not found, so we'll just get empty strings anyway. 
2244                 }
2245                 String userid = aes.getUserid();
2246                 String password = aes.getPassword();
2247                 if (!userid.equals("") && !password.equals("")) {
2248                 Global.username = userid;
2249                 Global.password = password;
2250                 }               
2251
2252         // Show the login dialog box
2253                 if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) {
2254                         LoginDialog login = new LoginDialog();
2255                         login.exec();
2256                 
2257                         if (!login.okPressed()) {
2258                                 return;
2259                         }
2260         
2261                         Global.username = login.getUserid();
2262                         Global.password = login.getPassword();
2263                 }
2264                 syncRunner.username = Global.username;
2265                 syncRunner.password = Global.password;
2266                 syncRunner.userStoreUrl = Global.userStoreUrl;
2267                 syncRunner.noteStoreUrl = Global.noteStoreUrl;
2268                 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
2269                 syncRunner.enConnect();
2270                 Global.isConnected = syncRunner.isConnected;
2271                 setupOnlineMenu();
2272                 setupConnectMenuOptions();
2273                 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
2274     }
2275     private void setupConnectMenuOptions() {
2276         logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
2277                 if (!Global.isConnected) {
2278                         menuBar.connectAction.setText("Connect");
2279                         menuBar.connectAction.setToolTip("Connect to Evernote");
2280                         menuBar.synchronizeAction.setEnabled(false);
2281                 } else {
2282                         menuBar.connectAction.setText("Disconnect");
2283                         menuBar.connectAction.setToolTip("Disconnect from Evernote");
2284                         menuBar.synchronizeAction.setEnabled(true);
2285                 }
2286                 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
2287     }
2288     
2289     
2290     
2291     //***************************************************************
2292     //***************************************************************
2293     //** These functions deal with the GUI Attribute tree
2294     //***************************************************************
2295     //***************************************************************    
2296     @SuppressWarnings("unused")
2297         private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
2298         
2299         clearTagFilter();
2300         clearNotebookFilter();
2301         clearTrashFilter();
2302         clearSavedSearchFilter();
2303
2304         if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
2305                 if (item.childCount() > 0) {
2306                         item.setSelected(false);
2307                 } else {
2308                 Global.createdBeforeFilter.reset();
2309                 Global.createdSinceFilter.reset();
2310                 Global.changedBeforeFilter.reset();
2311                 Global.changedSinceFilter.reset();
2312                 Global.containsFilter.reset();
2313                         attributeTreeSelected = item;
2314                         DateAttributeFilterTable f = null;
2315                         f = findDateAttributeFilterTable(item.parent());
2316                         if (f!=null)
2317                                 f.select(item.text(0));
2318                         else {
2319                                 String text = item.text(0);
2320                                 Global.containsFilter.select(text);
2321                         }
2322                 }
2323                 listManager.loadNotesIndex();
2324                 noteIndexUpdated(false);
2325                 return;
2326         }
2327                 attributeTreeSelected = null;
2328                 item.setSelected(false);
2329         Global.createdBeforeFilter.reset();
2330         Global.createdSinceFilter.reset();
2331         Global.changedBeforeFilter.reset();
2332         Global.changedSinceFilter.reset();
2333         Global.containsFilter.reset();
2334         listManager.loadNotesIndex();
2335                 noteIndexUpdated(false); 
2336     }
2337     // This determines what attribute filter we need, depending upon the selection
2338     private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
2339                 if (w.parent() != null && w.childCount() > 0) {
2340                         QTreeWidgetItem parent = w.parent();
2341                         if (parent.text(0).equalsIgnoreCase("created") && 
2342                                 w.text(0).equalsIgnoreCase("since"))
2343                                         return Global.createdSinceFilter;
2344                         if (parent.text(0).equalsIgnoreCase("created") && 
2345                         w.text(0).equalsIgnoreCase("before"))
2346                                         return Global.createdBeforeFilter;
2347                         if (parent.text(0).equalsIgnoreCase("last modified") && 
2348                         w.text(0).equalsIgnoreCase("since"))
2349                                         return Global.changedSinceFilter;
2350                 if (parent.text(0).equalsIgnoreCase("last modified") && 
2351                         w.text(0).equalsIgnoreCase("before"))
2352                                                 return Global.changedBeforeFilter;
2353                 }
2354                 return null;
2355     }
2356     // Show/Hide attribute search window
2357         private void toggleAttributesWindow() {
2358                 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
2359         if (attributeTree.isVisible())
2360                 attributeTree.hide();
2361         else
2362                 attributeTree.show();
2363         menuBar.hideAttributes.setChecked(attributeTree.isVisible());
2364         
2365                 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
2366         logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
2367     }    
2368         private void clearAttributeFilter() {
2369         Global.createdBeforeFilter.reset();
2370         Global.createdSinceFilter.reset();
2371         Global.changedBeforeFilter.reset();
2372         Global.changedSinceFilter.reset();
2373         Global.containsFilter.reset();
2374         attributeTreeSelected = null;
2375                 attributeTree.blockSignals(true);
2376                 attributeTree.clearSelection();
2377                 attributeTree.blockSignals(false);
2378         }
2379     
2380         
2381     //***************************************************************
2382     //***************************************************************
2383     //** These functions deal with the GUI Note index table
2384     //***************************************************************
2385     //***************************************************************    
2386     // Initialize the note list table
2387         private void initializeNoteTable() {
2388                 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
2389                 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
2390                 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
2391                 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
2392         }       
2393     // Show/Hide trash window
2394         @SuppressWarnings("unused")
2395         private void toggleNoteListWindow() {
2396                 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
2397         if (noteTableView.isVisible())
2398                 noteTableView.hide();
2399         else
2400                 noteTableView.show();
2401         menuBar.hideNoteList.setChecked(noteTableView.isVisible());
2402         
2403                 Global.saveWindowVisible("noteList", noteTableView.isVisible());
2404         logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
2405     }   
2406         // Handle the event that a user selects a note from the table
2407     @SuppressWarnings("unused")
2408         private void noteTableSelection() {
2409                 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
2410                 saveNote();
2411                 if (historyGuids.size() == 0) {
2412                         historyGuids.add(currentNoteGuid);
2413                         historyPosition = 1;
2414                 }
2415         noteTableView.showColumn(Global.noteTableGuidPosition);
2416         
2417         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2418         noteTableView.hideColumn(Global.noteTableGuidPosition);
2419         
2420         if (selections.size() > 0) {
2421                 QModelIndex index;
2422                 menuBar.noteDuplicateAction.setEnabled(true);
2423                 menuBar.noteOnlineHistoryAction.setEnabled(true);
2424                 menuBar.noteMergeAction.setEnabled(true);
2425                 selectedNoteGUIDs.clear();
2426                 if (selections.size() != 1 || Global.showDeleted) {
2427                         menuBar.noteDuplicateAction.setEnabled(false);
2428                 }
2429                 if (selections.size() != 1 || !Global.isConnected) {
2430                         menuBar.noteOnlineHistoryAction.setEnabled(false);
2431                 }
2432                 if (selections.size() == 1) {
2433                         menuBar.noteMergeAction.setEnabled(false);
2434                 }
2435                 for (int i=0; i<selections.size(); i++) {
2436                         int row = selections.get(i).row();
2437                         if (row == 0) 
2438                                 upButton.setEnabled(false);
2439                         else
2440                                 upButton.setEnabled(true);
2441                         if (row < noteTableView.model.rowCount()-1)
2442                                 downButton.setEnabled(true);
2443                         else
2444                                 downButton.setEnabled(false);
2445                         index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
2446                         SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
2447                         currentNoteGuid = (String)ix.values().toArray()[0];
2448                         selectedNoteGUIDs.add(currentNoteGuid);
2449                 }
2450         }
2451         
2452         nextButton.setEnabled(true);
2453                 prevButton.setEnabled(true);
2454         if (!fromHistory) {
2455                 int endPosition = historyGuids.size()-1;
2456                 for (int j=historyPosition; j<=endPosition; j++) {
2457                         historyGuids.remove(historyGuids.size()-1);
2458                 }
2459                 historyGuids.add(currentNoteGuid);
2460                 historyPosition = historyGuids.size();
2461         } 
2462         if (historyPosition <= 1)
2463                 prevButton.setEnabled(false);
2464         if (historyPosition == historyGuids.size())
2465                 nextButton.setEnabled(false);
2466                 
2467         fromHistory = false;
2468         scrollToGuid(currentNoteGuid);
2469         refreshEvernoteNote(true);
2470                 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
2471     }    
2472         // Trigger a refresh when the note db has been updated
2473         private void noteIndexUpdated(boolean reload) {
2474                 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
2475                 Global.traceReset();  
2476                 saveNote();
2477         refreshEvernoteNoteList();
2478         logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
2479         noteTableView.load(listManager, reload);
2480         scrollToGuid(currentNoteGuid);
2481                 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
2482     }
2483         // Called when the list of notes is updated
2484     private void refreshEvernoteNoteList() {
2485         logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
2486         browserWindow.setDisabled(false);
2487                 if (selectedNoteGUIDs == null)
2488                         selectedNoteGUIDs = new ArrayList<String>();
2489                 selectedNoteGUIDs.clear();  // clear out old entries
2490                 
2491                 String saveCurrentNoteGuid = new String();
2492                 String tempNoteGuid = new String();
2493                                 
2494                 historyGuids.clear();
2495                 historyPosition = 0;
2496                 prevButton.setEnabled(false);
2497                 nextButton.setEnabled(false);
2498                 
2499                 if (currentNoteGuid == null) 
2500                         currentNoteGuid = new String();
2501                 
2502                 for (Note note : listManager.getNoteIndex()) {
2503                         tempNoteGuid = note.getGuid();
2504                         if (currentNoteGuid.equals(tempNoteGuid)) {
2505                                 saveCurrentNoteGuid = new String(tempNoteGuid);
2506                         }
2507                 }
2508                 
2509                 if (listManager.getNoteIndex().size() == 0) {
2510                         currentNoteGuid = "";
2511                         currentNote = null;
2512                         browserWindow.clear();
2513                         browserWindow.setDisabled(true);
2514                 } 
2515                 
2516                 if (saveCurrentNoteGuid.equals("") && listManager.getNoteIndex().size() >0) {
2517                         currentNoteGuid = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1).getGuid();
2518                         currentNote = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1);
2519                         refreshEvernoteNote(true);
2520                 } else {
2521                         refreshEvernoteNote(false);
2522                 }
2523                 reloadTagTree();
2524
2525                 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
2526         } 
2527     // Called when the previous arrow button is clicked 
2528     @SuppressWarnings("unused")
2529         private void previousViewedAction() {
2530         if (!prevButton.isEnabled())
2531                 return;
2532         if (historyPosition == 0)
2533                 return;
2534                 historyPosition--;
2535         if (historyPosition <= 0)
2536                 return;
2537         String historyGuid = historyGuids.get(historyPosition-1);
2538         fromHistory = true;
2539         for (int i=0; i<noteTableView.model().rowCount(); i++) {
2540                 QModelIndex modelIndex =  noteTableView.model().index(i, Global.noteTableGuidPosition);
2541                 if (modelIndex != null) {
2542                         SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
2543                         String tableGuid =  (String)ix.values().toArray()[0];
2544                         if (tableGuid.equals(historyGuid)) {
2545                                 noteTableView.selectRow(i);
2546                                 return;
2547                         }       
2548                 }
2549         }
2550     }
2551     @SuppressWarnings("unused")
2552         private void nextViewedAction() {
2553         if (!nextButton.isEnabled())
2554                 return;
2555         String historyGuid = historyGuids.get(historyPosition);
2556         historyPosition++;
2557         fromHistory = true;
2558         for (int i=0; i<noteTableView.model().rowCount(); i++) {
2559                 QModelIndex modelIndex =  noteTableView.model().index(i, Global.noteTableGuidPosition);
2560                 if (modelIndex != null) {
2561                         SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
2562                         String tableGuid =  (String)ix.values().toArray()[0];
2563                         if (tableGuid.equals(historyGuid)) {
2564                                 noteTableView.selectRow(i);
2565                                 return;
2566                         }       
2567                 }
2568         }       
2569     }
2570     // Called when the up arrow is clicked 
2571     @SuppressWarnings("unused")
2572         private void upAction() {
2573         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2574         int row = selections.get(0).row();
2575         if (row > 0) {
2576                 noteTableView.selectRow(row-1);
2577         }
2578     }
2579     // Called when the down arrow is clicked 
2580     @SuppressWarnings("unused")
2581         private void downAction() {
2582         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2583         int row = selections.get(0).row();
2584         int max = noteTableView.model.rowCount();
2585         if (row < max-1) {
2586                 noteTableView.selectRow(row+1);
2587         }
2588     }
2589     // Update a tag string for a specific note in the list
2590     @SuppressWarnings("unused")
2591         private void updateListTags(String guid, List<String> tags) {
2592         logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
2593         StringBuffer tagBuffer = new StringBuffer();
2594         for (int i=0; i<tags.size(); i++) {
2595                 tagBuffer.append(tags.get(i));
2596                 if (i<tags.size()-1)
2597                         tagBuffer.append(", ");
2598         }
2599         
2600         for (int i=0; i<noteTableView.model.rowCount(); i++) {
2601                 QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2602                 if (modelIndex != null) {
2603                         SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2604                         String tableGuid =  (String)ix.values().toArray()[0];
2605                         if (tableGuid.equals(guid)) {
2606                                 noteTableView.model.setData(i, Global.noteTableTagPosition,tagBuffer.toString());
2607                                 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2608                                 return;
2609                         }
2610                 }
2611         }
2612         logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
2613     }
2614     // Update a title for a specific note in the list
2615     @SuppressWarnings("unused")
2616         private void updateListTitle(String guid, String title) {
2617         logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
2618
2619         for (int i=0; i<noteTableView.model.rowCount(); i++) {
2620                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2621                 QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2622                 if (modelIndex != null) {
2623 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2624                         SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2625                         String tableGuid =  (String)ix.values().toArray()[0];
2626                         if (tableGuid.equals(guid)) {
2627                                 noteTableView.model.setData(i, Global.noteTableTitlePosition,title);
2628                                 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2629                                 return;
2630                         }       
2631                 }
2632         }
2633         logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
2634     }
2635     // Update a title for a specific note in the list
2636     @SuppressWarnings("unused")
2637         private void updateListAuthor(String guid, String author) {
2638         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2639
2640         for (int i=0; i<noteTableView.model.rowCount(); i++) {
2641                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2642                 QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2643                 if (modelIndex != null) {
2644 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2645                         SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2646                         String tableGuid =  (String)ix.values().toArray()[0];
2647                         if (tableGuid.equals(guid)) {
2648                                 noteTableView.model.setData(i, Global.noteTableAuthorPosition,author);
2649                                 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2650                                 return;
2651                         }       
2652                 }
2653         }
2654         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2655     }
2656         private void updateListNoteNotebook(String guid, String notebook) {
2657         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2658
2659         for (int i=0; i<noteTableView.model.rowCount(); i++) {
2660                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2661                 QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2662                 if (modelIndex != null) {
2663 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2664                         SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2665                         String tableGuid =  (String)ix.values().toArray()[0];
2666                         if (tableGuid.equals(guid)) {
2667                                 noteTableView.model.setData(i, Global.noteTableNotebookPosition,notebook);
2668                                 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2669                                 return;
2670                         }       
2671                 }
2672         }
2673         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2674     }
2675     // Update a title for a specific note in the list
2676     @SuppressWarnings("unused")
2677         private void updateListSourceUrl(String guid, String url) {
2678         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2679
2680         for (int i=0; i<noteTableView.model.rowCount(); i++) {
2681                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2682                 QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2683                 if (modelIndex != null) {
2684 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2685                         SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2686                         String tableGuid =  (String)ix.values().toArray()[0];
2687                         if (tableGuid.equals(guid)) {
2688                                 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2689                                 noteTableView.model.setData(i, Global.noteTableSourceUrlPosition,url);
2690                                 return;
2691                         }       
2692                 }
2693         }
2694         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2695     }
2696         private void updateListGuid(String oldGuid, String newGuid) {
2697         logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
2698
2699         for (int i=0; i<noteTableView.model.rowCount(); i++) {
2700                 QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2701                 if (modelIndex != null) {
2702                         SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2703                         String tableGuid =  (String)ix.values().toArray()[0];
2704                         if (tableGuid.equals(oldGuid)) {
2705                                 noteTableView.model.setData(i, Global.noteTableGuidPosition,newGuid);
2706                                 //noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2707                                 return;
2708                         }       
2709                 }
2710         }
2711         logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
2712     }
2713         private void updateListTagName(String guid) {
2714         logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
2715                 
2716                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2717                         if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
2718                                 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
2719
2720                                 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2721                                         QModelIndex modelIndex =  noteTableView.model.index(i, Global.noteTableGuidPosition);
2722                                         if (modelIndex != null) {
2723                                                 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2724                                                 String noteGuid = (String)ix.values().toArray()[0];
2725                                                 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
2726                                                         noteTableView.model.setData(i, Global.noteTableTagPosition, newName);
2727                                                         //noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2728                                                         i=noteTableView.model.rowCount();
2729                                                 }
2730                                         }
2731                                 }
2732                         }
2733                 }       
2734         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
2735     }
2736         private void removeListTagName(String guid) {
2737         logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
2738                 
2739                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2740                         if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
2741                                 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
2742                                         if (listManager.get