OSDN Git Service

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