2 * This file is part of NeverNote
3 * Copyright 2009 Randy Baumgarte
5 * This file may be licensed under the terms of of the
6 * GNU General Public License Version 2 (the ``GPL'').
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.
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.
19 package cx.fbn.nevernote;
20 import java.awt.Desktop;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.security.MessageDigest;
25 import java.security.NoSuchAlgorithmException;
26 import java.sql.Connection;
27 import java.sql.DriverManager;
28 import java.sql.SQLException;
29 import java.text.SimpleDateFormat;
30 import java.util.ArrayList;
31 import java.util.Calendar;
32 import java.util.Collections;
33 import java.util.Comparator;
34 import java.util.Date;
35 import java.util.GregorianCalendar;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.SortedMap;
39 import java.util.Vector;
41 import org.apache.thrift.TException;
43 import com.evernote.edam.error.EDAMNotFoundException;
44 import com.evernote.edam.error.EDAMSystemException;
45 import com.evernote.edam.error.EDAMUserException;
46 import com.evernote.edam.notestore.NoteFilter;
47 import com.evernote.edam.notestore.NoteVersionId;
48 import com.evernote.edam.type.Data;
49 import com.evernote.edam.type.Note;
50 import com.evernote.edam.type.NoteAttributes;
51 import com.evernote.edam.type.Notebook;
52 import com.evernote.edam.type.QueryFormat;
53 import com.evernote.edam.type.Resource;
54 import com.evernote.edam.type.SavedSearch;
55 import com.evernote.edam.type.Tag;
56 import com.evernote.edam.type.User;
57 import com.trolltech.qt.QThread;
58 import com.trolltech.qt.core.QByteArray;
59 import com.trolltech.qt.core.QDataStream;
60 import com.trolltech.qt.core.QDateTime;
61 import com.trolltech.qt.core.QDir;
62 import com.trolltech.qt.core.QFile;
63 import com.trolltech.qt.core.QFileInfo;
64 import com.trolltech.qt.core.QFileSystemWatcher;
65 import com.trolltech.qt.core.QIODevice;
66 import com.trolltech.qt.core.QIODevice.OpenModeFlag;
67 import com.trolltech.qt.core.QModelIndex;
68 import com.trolltech.qt.core.QSize;
69 import com.trolltech.qt.core.QTemporaryFile;
70 import com.trolltech.qt.core.QTextCodec;
71 import com.trolltech.qt.core.QThreadPool;
72 import com.trolltech.qt.core.QTimer;
73 import com.trolltech.qt.core.QUrl;
74 import com.trolltech.qt.core.Qt;
75 import com.trolltech.qt.core.Qt.SortOrder;
76 import com.trolltech.qt.core.Qt.WidgetAttribute;
77 import com.trolltech.qt.gui.QAbstractItemView;
78 import com.trolltech.qt.gui.QAbstractItemView.ScrollHint;
79 import com.trolltech.qt.gui.QAction;
80 import com.trolltech.qt.gui.QApplication;
81 import com.trolltech.qt.gui.QCloseEvent;
82 import com.trolltech.qt.gui.QColor;
83 import com.trolltech.qt.gui.QComboBox;
84 import com.trolltech.qt.gui.QComboBox.InsertPolicy;
85 import com.trolltech.qt.gui.QCursor;
86 import com.trolltech.qt.gui.QDesktopServices;
87 import com.trolltech.qt.gui.QDialog;
88 import com.trolltech.qt.gui.QFileDialog;
89 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
90 import com.trolltech.qt.gui.QFileDialog.FileMode;
91 import com.trolltech.qt.gui.QGridLayout;
92 import com.trolltech.qt.gui.QHBoxLayout;
93 import com.trolltech.qt.gui.QIcon;
94 import com.trolltech.qt.gui.QImage;
95 import com.trolltech.qt.gui.QLabel;
96 import com.trolltech.qt.gui.QListWidget;
97 import com.trolltech.qt.gui.QMainWindow;
98 import com.trolltech.qt.gui.QMenu;
99 import com.trolltech.qt.gui.QMessageBox;
100 import com.trolltech.qt.gui.QMessageBox.StandardButton;
101 import com.trolltech.qt.gui.QPixmap;
102 import com.trolltech.qt.gui.QPrintDialog;
103 import com.trolltech.qt.gui.QPrinter;
104 import com.trolltech.qt.gui.QProgressBar;
105 import com.trolltech.qt.gui.QSizePolicy;
106 import com.trolltech.qt.gui.QSizePolicy.Policy;
107 import com.trolltech.qt.gui.QSpinBox;
108 import com.trolltech.qt.gui.QSplashScreen;
109 import com.trolltech.qt.gui.QSplitter;
110 import com.trolltech.qt.gui.QStatusBar;
111 import com.trolltech.qt.gui.QSystemTrayIcon;
112 import com.trolltech.qt.gui.QTableWidgetItem;
113 import com.trolltech.qt.gui.QTextEdit;
114 import com.trolltech.qt.gui.QToolBar;
115 import com.trolltech.qt.gui.QTreeWidgetItem;
116 import com.trolltech.qt.webkit.QWebPage.WebAction;
117 import com.trolltech.qt.webkit.QWebSettings;
118 import com.trolltech.qt.xml.QDomAttr;
119 import com.trolltech.qt.xml.QDomDocument;
120 import com.trolltech.qt.xml.QDomElement;
121 import com.trolltech.qt.xml.QDomNodeList;
123 import cx.fbn.nevernote.config.FileManager;
124 import cx.fbn.nevernote.config.InitializationException;
125 import cx.fbn.nevernote.config.StartupConfig;
126 import cx.fbn.nevernote.dialog.AccountDialog;
127 import cx.fbn.nevernote.dialog.ConfigDialog;
128 import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
129 import cx.fbn.nevernote.dialog.DatabaseStatus;
130 import cx.fbn.nevernote.dialog.FindDialog;
131 import cx.fbn.nevernote.dialog.LoginDialog;
132 import cx.fbn.nevernote.dialog.NotebookArchive;
133 import cx.fbn.nevernote.dialog.NotebookEdit;
134 import cx.fbn.nevernote.dialog.OnlineNoteHistory;
135 import cx.fbn.nevernote.dialog.SavedSearchEdit;
136 import cx.fbn.nevernote.dialog.TagEdit;
137 import cx.fbn.nevernote.dialog.ThumbnailViewer;
138 import cx.fbn.nevernote.dialog.WatchFolder;
139 import cx.fbn.nevernote.filters.EnSearch;
140 import cx.fbn.nevernote.gui.AttributeTreeWidget;
141 import cx.fbn.nevernote.gui.BrowserWindow;
142 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
143 import cx.fbn.nevernote.gui.MainMenuBar;
144 import cx.fbn.nevernote.gui.NotebookTreeWidget;
145 import cx.fbn.nevernote.gui.PDFPreview;
146 import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
147 import cx.fbn.nevernote.gui.TableView;
148 import cx.fbn.nevernote.gui.TagTreeWidget;
149 import cx.fbn.nevernote.gui.Thumbnailer;
150 import cx.fbn.nevernote.gui.TrashTreeWidget;
151 import cx.fbn.nevernote.sql.DatabaseConnection;
152 import cx.fbn.nevernote.sql.WatchFolderRecord;
153 import cx.fbn.nevernote.threads.IndexRunner;
154 import cx.fbn.nevernote.threads.SyncRunner;
155 import cx.fbn.nevernote.utilities.AESEncrypter;
156 import cx.fbn.nevernote.utilities.ApplicationLogger;
157 import cx.fbn.nevernote.utilities.FileImporter;
158 import cx.fbn.nevernote.utilities.FileUtils;
159 import cx.fbn.nevernote.utilities.ListManager;
160 import cx.fbn.nevernote.utilities.SyncTimes;
161 import cx.fbn.nevernote.xml.ExportData;
162 import cx.fbn.nevernote.xml.ImportData;
163 import cx.fbn.nevernote.xml.XMLInsertHilight;
166 public class NeverNote extends QMainWindow{
168 QStatusBar statusBar; // Application status bar
170 DatabaseConnection conn;
172 MainMenuBar menuBar; // Main menu bar
173 FindDialog find; // Text search in note dialog
174 List<String> emitLog; // Messages displayed in the status bar;
175 QSystemTrayIcon trayIcon; // little tray icon
176 QMenu trayMenu; // System tray menu
177 QAction trayExitAction; // Exit the application
178 QAction trayShowAction; // toggle the show/hide action
179 QAction trayAddNoteAction; // Add a note from the system tray
181 NotebookTreeWidget notebookTree; // List of notebooks
182 AttributeTreeWidget attributeTree; // List of note attributes
183 TagTreeWidget tagTree; // list of user created tags
184 SavedSearchTreeWidget savedSearchTree; // list of saved searches
185 TrashTreeWidget trashTree; // Trashcan
186 TableView noteTableView; // List of notes (the widget).
188 public BrowserWindow browserWindow; // Window containing browser & labels
189 QToolBar toolBar; // The tool bar under the menu
190 // QLineEdit searchField; // The search filter bar on the toolbar
191 QComboBox searchField; // search filter bar on the toolbar;
192 boolean searchPerformed = false; // Search was done?
193 QProgressBar quotaBar; // The current quota usage
195 ApplicationLogger logger;
196 List<String> selectedNotebookGUIDs; // List of notebook GUIDs
197 List<String> selectedTagGUIDs; // List of selected tag GUIDs
198 List<String> selectedNoteGUIDs; // List of selected notes
199 String selectedSavedSearchGUID; // Currently selected saved searches
201 NoteFilter filter; // Note filter
202 String currentNoteGuid; // GUID of the current note
203 Note currentNote; // The currently viewed note
204 boolean noteDirty; // Has the note been changed?
205 boolean inkNote; // if this is an ink note, it is read only
207 ListManager listManager; // DB runnable task
209 List<QTemporaryFile> tempFiles; // Array of temporary files;
211 QTimer indexTimer; // timer to start the index thread
212 IndexRunner indexRunner; // thread to index notes
215 QTimer syncTimer; // Sync on an interval
216 QTimer syncDelayTimer; // Sync delay to free up database
217 SyncRunner syncRunner; // thread to do a sync.
219 QTimer saveTimer; // Timer to save note contents
221 QTimer authTimer; // Refresh authentication
222 QTimer externalFileSaveTimer; // Save files altered externally
223 List<String> externalFiles; // External files to save later
224 List<String> importFilesKeep; // Auto-import files to save later
225 List<String> importFilesDelete; // Auto-import files to save later
227 int indexTime; // how often to try and index
228 boolean indexRunning; // Is indexing running?
229 boolean indexDisabled; // Is indexing disabled?
231 int syncThreadsReady; // number of sync threads that are free
232 int syncTime; // Sync interval
233 boolean syncRunning; // Is sync running?
234 boolean automaticSync; // do sync automatically?
235 QTreeWidgetItem attributeTreeSelected;
237 QAction prevButton; // Go to the previous item viewed
238 QAction nextButton; // Go to the next item in the history
239 QAction downButton; // Go to the next item in the list
240 QAction upButton; // Go to the prev. item in the list;
241 QAction synchronizeButton; // Synchronize with Evernote
242 List<QIcon> synchronizeAnimation; // Synchronize movie
243 QTimer synchronizeAnimationTimer; // Timer to change animation button
244 int synchronizeFrame; // Current frame being viewed
245 QAction printButton; // Print Button
246 QAction tagButton; // Tag edit button
247 QAction attributeButton; // Attribute information button
248 QAction emailButton; // Email button
249 QAction deleteButton; // Delete button
250 QAction newButton; // new Note Button;
251 QSpinBox zoomSpinner; // Zoom zoom
252 QAction searchClearButton; // Clear the search field
254 QSplitter mainLeftRightSplitter; // main splitter for left/right side
255 QSplitter leftSplitter1; // first left hand splitter
256 QSplitter browserIndexSplitter; // splitter between note index & note text
258 QFileSystemWatcher importKeepWatcher; // Watch & keep auto-import
259 QFileSystemWatcher importDeleteWatcher; // Watch & Delete auto-import
260 List<String> importedFiles; // History of imported files (so we don't import twice)
262 OnlineNoteHistory historyWindow; // online history window
263 List<NoteVersionId> versions; // history versions
265 QTimer threadMonitorTimer; // Timer to watch threads.
266 int dbThreadDeadCount=0; // number of consecutive dead times for the db thread
267 int syncThreadDeadCount=0; // number of consecutive dead times for the sync thread
268 int indexThreadDeadCount=0; // number of consecutive dead times for the index thread
269 int notebookThreadDeadCount=0; // number of consecutive dead times for the notebook thread
270 int tagDeadCount=0; // number of consecutive dead times for the tag thread
271 int trashDeadCount=0; // number of consecutive dead times for the trash thread
272 int saveThreadDeadCount=0; // number of consecutive dead times for the save thread
274 HashMap<String, String> noteCache; // Cash of note content
275 List<String> historyGuids; // GUIDs of previously viewed items
276 int historyPosition; // Position within the viewed items
277 boolean fromHistory; // Is this from the history queue?
278 String trashNoteGuid; // Guid to restore / set into or out of trash to save position
279 Thumbnailer preview; // generate preview image
280 ThumbnailViewer thumbnailViewer; // View preview thumbnail;
282 String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
285 //***************************************************************
286 //***************************************************************
287 //** Constructor & main entry point
288 //***************************************************************
289 //***************************************************************
290 // Application Constructor
291 public NeverNote(DatabaseConnection dbConn) {
294 thread().setPriority(Thread.MAX_PRIORITY);
296 logger = new ApplicationLogger("nevernote.log");
297 logger.log(logger.HIGH, tr("Starting Application"));
299 conn.checkDatabaseVersion();
301 // Start building the invalid XML tables
302 Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
303 List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
305 for (int i=0; i<elements.size(); i++) {
306 Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i)));
309 logger.log(logger.EXTREME, tr("Starting GUI build"));
310 Global.originalPalette = QApplication.palette();
311 QApplication.setStyle(Global.getStyle());
312 if (Global.useStandardPalette())
313 QApplication.setPalette(QApplication.style().standardPalette());
314 setWindowTitle("NeverNote");
316 mainLeftRightSplitter = new QSplitter();
317 setCentralWidget(mainLeftRightSplitter);
318 leftSplitter1 = new QSplitter();
319 leftSplitter1.setOrientation(Qt.Orientation.Vertical);
321 browserIndexSplitter = new QSplitter();
322 browserIndexSplitter.setOrientation(Qt.Orientation.Vertical);
324 //* Setup threads & thread timers
325 int indexRunnerCount = Global.getIndexThreads();
326 indexRunnerCount = 1;
327 QThreadPool.globalInstance().setMaxThreadCount(indexRunnerCount+5); // increase max thread count
329 logger.log(logger.EXTREME, tr("Building list manager"));
330 listManager = new ListManager(conn, logger, Global.mainThreadId);
332 logger.log(logger.EXTREME, tr("Building index runners & timers"));
333 indexRunner = new IndexRunner("indexRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
334 indexThread = new QThread(indexRunner, "Index Thread");
337 synchronizeAnimationTimer = new QTimer();
338 synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()");
340 indexTimer = new QTimer();
341 indexTime = 1000*60*5; // look for unindexed every 5 minutes
342 // indexTime = 1000*5;
343 indexTimer.start(indexTime); // Start indexing timer
344 indexTimer.timeout.connect(this, "indexTimer()");
345 indexDisabled = false;
346 indexRunning = false;
348 logger.log(logger.EXTREME, tr("Setting sync thread & timers"));
350 syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
351 syncTime = new SyncTimes().timeValue(Global.getSyncInterval());
352 syncTimer = new QTimer();
353 syncTimer.timeout.connect(this, "syncTimer()");
354 syncRunner.status.message.connect(this, "setMessage(String)");
355 syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)");
356 syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()");
359 automaticSync = true;
360 syncTimer.start(syncTime*60*1000);
362 automaticSync = false;
365 syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount());
366 syncThread = new QThread(syncRunner, "Synchronization Thread");
370 logger.log(logger.EXTREME, tr("Starting authentication timer"));
371 authTimer = new QTimer();
372 authTimer.timeout.connect(this, "authTimer()");
373 authTimer.start(1000*60*15);
374 syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)");
376 logger.log(logger.EXTREME, tr("Setting save note timer"));
377 saveTimer = new QTimer();
378 saveTimer.timeout.connect(this, "saveNote()");
379 if (Global.getAutoSaveInterval() > 0) {
380 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
381 // saveTimer.setInterval(1000*10); // auto save every 20 seconds;
386 logger.log(logger.EXTREME, tr("Starting external file monitor timer"));
387 externalFileSaveTimer = new QTimer();
388 externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()");
389 externalFileSaveTimer.setInterval(1000*5); // save every 5 seconds;
390 externalFiles = new ArrayList<String>();
391 importFilesDelete = new ArrayList<String>();
392 importFilesKeep = new ArrayList<String>();
393 externalFileSaveTimer.start();
395 notebookTree = new NotebookTreeWidget();
396 attributeTree = new AttributeTreeWidget();
397 tagTree = new TagTreeWidget(conn);
398 savedSearchTree = new SavedSearchTreeWidget();
399 trashTree = new TrashTreeWidget();
400 noteTableView = new TableView(logger);
402 QGridLayout leftGrid = new QGridLayout();
403 leftSplitter1.setLayout(leftGrid);
404 leftGrid.addWidget(notebookTree, 1, 1);
405 leftGrid.addWidget(tagTree,2,1);
406 leftGrid.addWidget(attributeTree,3,1);
407 leftGrid.addWidget(savedSearchTree,4,1);
408 leftGrid.addWidget(trashTree, 5, 1);
410 // Setup the browser window
411 noteCache = new HashMap<String,String>();
412 browserWindow = new BrowserWindow(conn);
414 browserIndexSplitter.addWidget(noteTableView);
415 browserIndexSplitter.addWidget(browserWindow);
417 mainLeftRightSplitter.addWidget(leftSplitter1);
418 mainLeftRightSplitter.addWidget(browserIndexSplitter);
420 searchField = new QComboBox();
421 searchField.setEditable(true);
422 searchField.activatedIndex.connect(this, "searchFieldChanged()");
423 searchField.setDuplicatesEnabled(false);
424 searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)");
426 quotaBar = new QProgressBar();
428 // Setup the thumbnail viewer
429 thumbnailViewer = new ThumbnailViewer();
430 thumbnailViewer.upArrow.connect(this, "upAction()");
431 thumbnailViewer.downArrow.connect(this, "downAction()");
432 thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
433 thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
435 listManager.loadNotesIndex();
436 initializeNotebookTree();
438 initializeSavedSearchTree();
439 attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)");
440 attributeTreeSelected = null;
441 initializeNoteTable();
443 selectedNoteGUIDs = new ArrayList<String>();
444 statusBar = new QStatusBar();
445 setStatusBar(statusBar);
446 menuBar = new MainMenuBar(this);
447 emitLog = new ArrayList<String>();
449 tagTree.setDeleteAction(menuBar.tagDeleteAction);
450 tagTree.setEditAction(menuBar.tagEditAction);
451 tagTree.setAddAction(menuBar.tagAddAction);
452 tagTree.setVisible(Global.isWindowVisible("tagTree"));
453 tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)");
454 menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree"));
455 listManager.tagSignal.listChanged.connect(this, "reloadTagTree()");
457 notebookTree.setDeleteAction(menuBar.notebookDeleteAction);
458 notebookTree.setEditAction(menuBar.notebookEditAction);
459 notebookTree.setAddAction(menuBar.notebookAddAction);
460 notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
461 notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
462 menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
464 savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
465 savedSearchTree.setEditAction(menuBar.savedSearchEditAction);
466 savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction);
467 savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()");
468 savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree"));
469 menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree"));
471 noteTableView.setAddAction(menuBar.noteAdd);
472 noteTableView.setDeleteAction(menuBar.noteDelete);
473 noteTableView.setRestoreAction(menuBar.noteRestoreAction);
474 noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction);
475 noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
476 noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
477 noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
478 noteTableView.rowChanged.connect(this, "scrollToGuid(String)");
479 noteTableView.resetViewport.connect(this, "scrollToCurrentGuid()");
480 noteTableView.doubleClicked.connect(this, "listDoubleClick()");
481 listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
483 trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
484 trashTree.setEmptyAction(menuBar.emptyTrashAction);
485 trashTree.setVisible(Global.isWindowVisible("trashTree"));
486 menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
487 trashTree.updateCounts(listManager.getTrashCount());
489 attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
490 menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
492 noteTableView.setVisible(Global.isWindowVisible("noteList"));
493 menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList"));
495 if (!Global.isWindowVisible("editorButtonBar"))
496 toggleEditorButtonBar();
497 if (!Global.isWindowVisible("leftPanel"))
498 menuBar.hideLeftSide.setChecked(true);
502 find = new FindDialog();
503 find.getOkButton().clicked.connect(this, "doFindText()");
505 // Setup the tray icon menu bar
506 trayShowAction = new QAction("Show/Hide", this);
507 trayExitAction = new QAction("Exit", this);
508 trayAddNoteAction = new QAction("Add Note", this);
510 trayExitAction.triggered.connect(this, "close()");
511 trayAddNoteAction.triggered.connect(this, "addNote()");
512 trayShowAction.triggered.connect(this, "trayToggleVisible()");
514 trayMenu = new QMenu(this);
515 trayMenu.addAction(trayAddNoteAction);
516 trayMenu.addAction(trayShowAction);
517 trayMenu.addAction(trayExitAction);
520 trayIcon = new QSystemTrayIcon(this);
521 trayIcon.setToolTip("NeverNote");
522 trayIcon.setContextMenu(trayMenu);
523 trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
526 currentNoteGuid = Global.getLastViewedNoteGuid();
527 historyGuids = new ArrayList<String>();
531 if (!currentNoteGuid.trim().equals("")) {
532 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
535 noteIndexUpdated(true);
537 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
538 if (menuBar.showEditorBar.isChecked())
540 tagIndexUpdated(true);
541 savedSearchIndexUpdated();
542 notebookIndexUpdated();
544 setupSyncSignalListeners();
545 setupBrowserSignalListeners();
546 setupIndexListeners();
549 tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
550 tagTree.showAllTags(true);
552 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
553 setWindowIcon(appIcon);
554 trayIcon.setIcon(appIcon);
555 if (Global.showTrayIcon())
560 scrollToGuid(currentNoteGuid);
561 if (Global.automaticLogin()) {
563 if (Global.isConnected)
566 setupFolderImports();
569 restoreWindowState();
571 if (Global.mimicEvernoteInterface) {
572 notebookTree.selectGuid("");
575 threadMonitorTimer = new QTimer();
576 threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
577 threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds;
579 historyGuids.add(currentNoteGuid);
582 int sortCol = Global.getSortColumn();
583 int sortOrder = Global.getSortOrder();
584 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
589 public static void main(String[] args) {
590 QApplication.initialize(args);
591 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
592 QSplashScreen splash = new QSplashScreen(pixmap);
595 DatabaseConnection dbConn;
598 initializeGlobalSettings(args);
600 showSplash = Global.isWindowVisible("SplashScreen");
604 dbConn = setupDatabaseConnection();
606 // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
607 Global.getFileManager().purgeResDirectory();
609 } catch (InitializationException e) {
612 QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
616 NeverNote application = new NeverNote(dbConn);
618 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
619 if (Global.wasWindowMaximized())
620 application.showMaximized();
624 splash.finish(application);
626 System.out.println("Goodbye.");
631 * Open the internal database, or create if not present
633 * @throws InitializationException when opening the database fails, e.g. because another process has it locked
635 private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
636 ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
637 DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
639 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
640 boolean goodCheck = false;
642 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
644 if (!dialog.okPressed())
646 Global.cipherPassword = dialog.getPassword();
647 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
648 Global.getDatabaseUserPassword(), Global.cipherPassword);
654 private static void initializeGlobalSettings(String[] args) throws InitializationException {
655 StartupConfig startupConfig = new StartupConfig();
657 for (String arg : args) {
658 String lower = arg.toLowerCase();
659 if (lower.startsWith("--name="))
660 startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
661 if (lower.startsWith("--home="))
662 startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
663 if (lower.startsWith("--disable-viewing"))
664 startupConfig.setDisableViewing(true);
667 Global.setup(startupConfig);
672 public void closeEvent(QCloseEvent event) {
673 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
676 if (currentNote!= null & browserWindow!=null) {
677 if (!currentNote.getTitle().equals(browserWindow.getTitle()))
678 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle());
681 setMessage("Beginning shutdown.");
683 externalFileEditedSaver();
684 if (Global.isConnected && Global.synchronizeOnClose()) {
685 setMessage("Performing synchronization before closing.");
686 syncRunner.addWork("SYNC");
688 setMessage("Closing Program.");
689 threadMonitorTimer.stop();
691 syncRunner.addWork("STOP");
692 indexRunner.addWork("STOP");
697 if (tempFiles != null)
700 browserWindow.noteSignal.tagsChanged.disconnect();
701 browserWindow.noteSignal.titleChanged.disconnect();
702 browserWindow.noteSignal.noteChanged.disconnect();
703 browserWindow.noteSignal.notebookChanged.disconnect();
704 browserWindow.noteSignal.createdDateChanged.disconnect();
705 browserWindow.noteSignal.alteredDateChanged.disconnect();
706 syncRunner.searchSignal.listChanged.disconnect();
707 syncRunner.tagSignal.listChanged.disconnect();
708 syncRunner.notebookSignal.listChanged.disconnect();
709 syncRunner.noteIndexSignal.listChanged.disconnect();
712 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
713 Global.setColumnPosition("noteTableCreationPosition", position);
714 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
715 Global.setColumnPosition("noteTableTagPosition", position);
716 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
717 Global.setColumnPosition("noteTableNotebookPosition", position);
718 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
719 Global.setColumnPosition("noteTableChangedPosition", position);
720 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
721 Global.setColumnPosition("noteTableAuthorPosition", position);
722 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
723 Global.setColumnPosition("noteTableSourceUrlPosition", position);
724 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
725 Global.setColumnPosition("noteTableSubjectDatePosition", position);
726 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
727 Global.setColumnPosition("noteTableTitlePosition", position);
728 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
729 Global.setColumnPosition("noteTableSynchronizedPosition", position);
731 saveNoteIndexWidth();
733 int width = notebookTree.columnWidth(0);
734 Global.setColumnWidth("notebookTreeName", width);
735 width = tagTree.columnWidth(0);
736 Global.setColumnWidth("tagTreeName", width);
738 Global.saveWindowMaximized(isMaximized());
739 Global.saveCurrentNoteGuid(currentNoteGuid);
741 int sortCol = noteTableView.proxyModel.sortColumn();
742 int sortOrder = noteTableView.proxyModel.sortOrder().value();
743 Global.setSortColumn(sortCol);
744 Global.setSortOrder(sortOrder);
748 Global.keepRunning = false;
750 logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
751 indexRunner.thread().join(50);
752 logger.log(logger.MEDIUM, "Index thread has stopped");
753 } catch (InterruptedException e1) {
754 e1.printStackTrace();
756 if (!syncRunner.isIdle()) {
758 logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
760 logger.log(logger.MEDIUM, "Sync thread has stopped");
761 } catch (InterruptedException e1) {
762 e1.printStackTrace();
766 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
769 public void setMessage(String s) {
770 logger.log(logger.HIGH, "Entering NeverNote.setMessage");
771 logger.log(logger.HIGH, "Message: " +s);
772 statusBar.showMessage(s);
774 logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
777 private void waitCursor(boolean wait) {
779 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
781 QApplication.restoreOverrideCursor();
784 private void setupIndexListeners() {
785 indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
786 indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
787 // indexRunner.threadSignal.indexNeeded.connect(listManager, "setIndexNeeded(String, String, Boolean)");
789 private void setupSyncSignalListeners() {
790 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
791 syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
792 syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
793 syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
794 syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
796 // syncRunner.syncSignal.setSequenceDate.connect(this,"setSequenceDate(long)");
797 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
798 // syncRunner.syncSignal.setUpdateSequenceNumber.connect(this,"setUpdateSequenceNumber(int)");
799 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
800 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
802 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
803 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
804 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
806 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
809 private void setupBrowserSignalListeners() {
811 browserWindow.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
812 browserWindow.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
813 browserWindow.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
814 browserWindow.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
815 browserWindow.noteSignal.noteChanged.connect(this, "setNoteDirty()");
816 browserWindow.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
817 browserWindow.noteSignal.titleChanged.connect(this, "updateListTitle(String, String)");
818 browserWindow.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
819 browserWindow.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
820 browserWindow.noteSignal.createdDateChanged.connect(this, "updateListDateCreated(String, QDateTime)");
821 browserWindow.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
822 browserWindow.noteSignal.alteredDateChanged.connect(this, "updateListDateChanged(String, QDateTime)");
823 browserWindow.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
824 browserWindow.noteSignal.subjectDateChanged.connect(this, "updateListDateSubject(String, QDateTime)");
825 browserWindow.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
826 browserWindow.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
827 browserWindow.noteSignal.authorChanged.connect(this, "updateListAuthor(String, String)");
828 browserWindow.noteSignal.geoChanged.connect(this, "setNoteDirty()");
829 browserWindow.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
830 browserWindow.noteSignal.sourceUrlChanged.connect(this, "updateListSourceUrl(String, String)");
831 browserWindow.focusLost.connect(this, "saveNote()");
832 browserWindow.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
833 // browserWindow.resourceSignal.externalFileEdit.connect(this, "saveResourceLater(String, String)");
838 //***************************************************************
839 //***************************************************************
840 //* Settings and look & feel
841 //***************************************************************
842 //***************************************************************
843 @SuppressWarnings("unused")
844 private void settings() {
845 logger.log(logger.HIGH, "Entering NeverNote.settings");
846 ConfigDialog settings = new ConfigDialog(this);
847 String dateFormat = Global.getDateFormat();
848 String timeFormat = Global.getTimeFormat();
851 if (Global.showTrayIcon())
856 if (menuBar.showEditorBar.isChecked())
859 // Reset the save timer
860 if (Global.getAutoSaveInterval() > 0)
861 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
865 // This is a hack to force a reload of the index in case the date or time changed.
866 // if (!dateFormat.equals(Global.getDateFormat()) ||
867 // !timeFormat.equals(Global.getTimeFormat())) {
869 noteIndexUpdated(true);
872 logger.log(logger.HIGH, "Leaving NeverNote.settings");
874 // Restore things to the way they were
875 private void restoreWindowState() {
876 // We need to name things or this doesn't work.
877 setObjectName("NeverNote");
878 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
879 browserIndexSplitter.setObjectName("browserIndexSplitter");
880 leftSplitter1.setObjectName("leftSplitter1");
882 // Restore the actual positions.
883 restoreGeometry(Global.restoreGeometry(objectName()));
884 mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
885 browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
886 leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
889 // Save window positions for the next start
890 private void saveWindowState() {
891 Global.saveGeometry(objectName(), saveGeometry());
892 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
893 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
894 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
896 // Load the style sheet
897 private void loadStyleSheet() {
898 String fileName = Global.getFileManager().getQssDirPath("default.qss");
899 QFile file = new QFile(fileName);
900 file.open(OpenModeFlag.ReadOnly);
901 String styleSheet = file.readAll().toString();
903 setStyleSheet(styleSheet);
905 // Save column widths for the next time
906 private void saveNoteIndexWidth() {
908 width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
909 Global.setColumnWidth("noteTableCreationPosition", width);
910 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
911 Global.setColumnWidth("noteTableChangedPosition", width);
912 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
913 Global.setColumnWidth("noteTableGuidPosition", width);
914 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
915 Global.setColumnWidth("noteTableNotebookPosition", width);
916 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
917 Global.setColumnWidth("noteTableTagPosition", width);
918 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
919 Global.setColumnWidth("noteTableTitlePosition", width);
920 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
921 Global.setColumnWidth("noteTableSourceUrlPosition", width);
922 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
923 Global.setColumnWidth("noteTableAuthorPosition", width);
924 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
925 Global.setColumnWidth("noteTableSubjectDatePosition", width);
926 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
927 Global.setColumnWidth("noteTableSynchronizedPosition", width);
931 //***************************************************************
932 //***************************************************************
933 //** These functions deal with Notebook menu items
934 //***************************************************************
935 //***************************************************************
936 // Setup the tree containing the user's notebooks.
937 private void initializeNotebookTree() {
938 logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
939 notebookTree.itemSelectionChanged.connect(this, "notebookTreeSelection()");
940 listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
941 // notebookTree.resize(Global.getSize("notebookTree"));
942 logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
944 // Listener when a notebook is selected
945 @SuppressWarnings("unused")
946 private void notebookTreeSelection() {
947 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
950 clearAttributeFilter();
951 clearSavedSearchFilter();
952 if (Global.mimicEvernoteInterface) {
957 menuBar.noteRestoreAction.setVisible(false);
958 menuBar.notebookEditAction.setEnabled(true);
959 menuBar.notebookDeleteAction.setEnabled(true);
960 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
961 QTreeWidgetItem currentSelection;
962 selectedNotebookGUIDs.clear();
963 if (!Global.mimicEvernoteInterface) {
964 for (int i=0; i<selections.size(); i++) {
965 currentSelection = selections.get(i);
966 selectedNotebookGUIDs.add(currentSelection.text(2));
970 // There is the potential for no notebooks to be selected if this
971 // happens then we make it look like all notebooks were selecetd.
972 // If that happens, just select the "all notebooks"
973 selections = notebookTree.selectedItems();
974 if (selections.size()==0) {
975 selectedNotebookGUIDs.clear();
976 menuBar.notebookEditAction.setEnabled(false);
977 menuBar.notebookDeleteAction.setEnabled(false);
981 if (selections.size() > 0)
982 guid = (selections.get(0).text(2));
983 if (!guid.equals(""))
984 selectedNotebookGUIDs.add(guid);
986 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
987 listManager.loadNotesIndex();
988 noteIndexUpdated(false);
989 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
992 private void clearNotebookFilter() {
993 notebookTree.blockSignals(true);
994 notebookTree.clearSelection();
995 menuBar.noteRestoreAction.setVisible(false);
996 menuBar.notebookEditAction.setEnabled(false);
997 menuBar.notebookDeleteAction.setEnabled(false);
998 selectedNotebookGUIDs.clear();
999 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1000 notebookTree.blockSignals(false);
1002 // Triggered when the notebook DB has been updated
1003 private void notebookIndexUpdated() {
1004 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1005 if (selectedNotebookGUIDs == null)
1006 selectedNotebookGUIDs = new ArrayList<String>();
1007 List<Notebook> books = conn.getNotebookTable().getAll();
1008 for (int i=books.size()-1; i>=0; i--) {
1009 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1010 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1012 j=listManager.getArchiveNotebookIndex().size();
1018 listManager.countNotebookResults(listManager.getNoteIndex());
1019 notebookTree.blockSignals(true);
1020 notebookTree.load(books, listManager.getLocalNotebooks());
1021 for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1022 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1024 selectedNotebookGUIDs.remove(i);
1026 notebookTree.blockSignals(false);
1028 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1030 // Show/Hide note information
1031 private void toggleNotebookWindow() {
1032 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1033 if (notebookTree.isVisible())
1034 notebookTree.hide();
1036 notebookTree.show();
1037 menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1038 Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1039 logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1041 // Add a new notebook
1042 @SuppressWarnings("unused")
1043 private void addNotebook() {
1044 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1045 NotebookEdit edit = new NotebookEdit();
1046 edit.setNotebooks(listManager.getNotebookIndex());
1049 if (!edit.okPressed())
1052 Calendar currentTime = new GregorianCalendar();
1053 Long l = new Long(currentTime.getTimeInMillis());
1054 String randint = new String(Long.toString(l));
1056 Notebook newBook = new Notebook();
1057 newBook.setUpdateSequenceNum(0);
1058 newBook.setGuid(randint);
1059 newBook.setName(edit.getNotebook());
1060 newBook.setServiceCreated(new Date().getTime());
1061 newBook.setServiceUpdated(new Date().getTime());
1062 newBook.setDefaultNotebook(false);
1063 newBook.setPublished(false);
1065 listManager.getNotebookIndex().add(newBook);
1067 listManager.getLocalNotebooks().add(newBook.getGuid());
1068 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1069 notebookIndexUpdated();
1070 listManager.countNotebookResults(listManager.getNoteIndex());
1071 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1072 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1074 // Edit an existing notebook
1075 @SuppressWarnings("unused")
1076 private void editNotebook() {
1077 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1078 NotebookEdit edit = new NotebookEdit();
1079 edit.setTitle("Edit Notebook");
1080 edit.setLocalCheckboxEnabled(false);
1081 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1082 QTreeWidgetItem currentSelection;
1083 currentSelection = selections.get(0);
1084 edit.setNotebook(currentSelection.text(0));
1085 edit.setNotebooks(listManager.getNotebookIndex());
1088 if (!edit.okPressed())
1091 String guid = currentSelection.text(2);
1092 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1093 currentSelection.setText(0, edit.getNotebook());
1095 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1096 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1097 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1098 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1099 i=listManager.getNotebookIndex().size();
1103 // Build a list of non-closed notebooks
1104 List<Notebook> nbooks = new ArrayList<Notebook>();
1105 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1106 boolean found=false;
1107 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1108 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1112 nbooks.add(listManager.getNotebookIndex().get(i));
1115 browserWindow.setNotebookList(nbooks);
1116 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1118 // Delete an existing notebook
1119 @SuppressWarnings("unused")
1120 private void deleteNotebook() {
1121 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1122 boolean assigned = false;
1123 // Check if any notes have this notebook
1124 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1125 for (int i=0; i<selections.size(); i++) {
1126 QTreeWidgetItem currentSelection;
1127 currentSelection = selections.get(i);
1128 String guid = currentSelection.text(2);
1129 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
1130 String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
1131 if (noteGuid.equals(guid)) {
1133 j=listManager.getNoteIndex().size();
1134 i=selections.size();
1139 QMessageBox.information(this, "Unable to Delete", "Some of the selected notebook(s) contain notes.\n"+
1140 "Please delete the notes or move them to another notebook before deleting any notebooks.");
1144 if (conn.getNotebookTable().getAll().size() == 1) {
1145 QMessageBox.information(this, "Unable to Delete", "You must have at least one notebook.");
1149 // If all notebooks are clear, verify the delete
1150 if (QMessageBox.question(this, "Confirmation", "Delete the selected notebooks?",
1151 QMessageBox.StandardButton.Yes,
1152 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1156 // If confirmed, delete the notebook
1157 for (int i=selections.size()-1; i>=0; i--) {
1158 QTreeWidgetItem currentSelection;
1159 currentSelection = selections.get(i);
1160 String guid = currentSelection.text(2);
1161 conn.getNotebookTable().expungeNotebook(guid, true);
1162 listManager.deleteNotebook(guid);
1164 // for (int i=<dbRunner.getLocalNotebooks().size()-1; i>=0; i--) {
1165 // if (dbRunner.getLocalNotebooks().get(i).equals(arg0))
1167 notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
1168 listManager.countNotebookResults(listManager.getNoteIndex());
1169 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1170 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1172 // A note's notebook has been updated
1173 @SuppressWarnings("unused")
1174 private void updateNoteNotebook(String guid, String notebookGuid) {
1176 // Update the list manager
1177 listManager.updateNoteNotebook(guid, notebookGuid);
1178 listManager.countNotebookResults(listManager.getNoteIndex());
1179 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1181 // Find the name of the notebook
1182 String notebookName = null;
1183 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1184 if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
1185 notebookName = listManager.getNotebookIndex().get(i).getName();
1186 i=listManager.getNotebookIndex().size();
1190 // If we found the name, update the browser window
1191 if (notebookName != null) {
1192 updateListNoteNotebook(guid, notebookName);
1193 if (guid.equals(currentNoteGuid)) {
1194 int pos = browserWindow.notebookBox.findText(notebookName);
1196 browserWindow.notebookBox.setCurrentIndex(pos);
1200 // If we're dealing with the current note, then we need to be sure and update the notebook there
1201 if (guid.equals(currentNoteGuid)) {
1202 if (currentNote != null) {
1203 currentNote.setNotebookGuid(notebookGuid);
1207 // Open/close notebooks
1208 @SuppressWarnings("unused")
1209 private void closeNotebooks() {
1210 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
1212 if (!na.okClicked())
1216 listManager.getArchiveNotebookIndex().clear();
1218 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
1219 String text = na.getClosedBookList().takeItem(i).text();
1220 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1221 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1222 Notebook n = listManager.getNotebookIndex().get(j);
1223 conn.getNotebookTable().setArchived(n.getGuid(),true);
1224 listManager.getArchiveNotebookIndex().add(n);
1225 j=listManager.getNotebookIndex().size();
1230 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
1231 String text = na.getOpenBookList().takeItem(i).text();
1232 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1233 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1234 Notebook n = listManager.getNotebookIndex().get(j);
1235 conn.getNotebookTable().setArchived(n.getGuid(),false);
1236 j=listManager.getNotebookIndex().size();
1241 listManager.loadNotesIndex();
1242 notebookIndexUpdated();
1243 noteIndexUpdated(true);
1244 // noteIndexUpdated(false);
1246 // Build a list of non-closed notebooks
1247 List<Notebook> nbooks = new ArrayList<Notebook>();
1248 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1249 boolean found=false;
1250 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1251 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1255 nbooks.add(listManager.getNotebookIndex().get(i));
1258 browserWindow.setNotebookList(nbooks);
1265 //***************************************************************
1266 //***************************************************************
1267 //** These functions deal with Tag menu items
1268 //***************************************************************
1269 //***************************************************************
1270 // Add a new notebook
1271 @SuppressWarnings("unused")
1272 private void addTag() {
1273 logger.log(logger.HIGH, "Inside NeverNote.addTag");
1274 TagEdit edit = new TagEdit();
1275 edit.setTagList(listManager.getTagIndex());
1278 if (!edit.okPressed())
1281 Calendar currentTime = new GregorianCalendar();
1282 Long l = new Long(currentTime.getTimeInMillis());
1283 String randint = new String(Long.toString(l));
1285 Tag newTag = new Tag();
1286 newTag.setUpdateSequenceNum(0);
1287 newTag.setGuid(randint);
1288 newTag.setName(edit.getTag());
1289 conn.getTagTable().addTag(newTag, true);
1290 listManager.getTagIndex().add(newTag);
1293 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
1295 private void reloadTagTree() {
1296 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
1297 tagIndexUpdated(false);
1298 boolean filter = false;
1299 listManager.countTagResults(listManager.getNoteIndex());
1300 if (notebookTree.selectedItems().size() > 0
1301 && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
1303 if (tagTree.selectedItems().size() > 0)
1305 tagTree.showAllTags(!filter);
1306 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
1308 // Edit an existing tag
1309 @SuppressWarnings("unused")
1310 private void editTag() {
1311 logger.log(logger.HIGH, "Entering NeverNote.editTag");
1312 TagEdit edit = new TagEdit();
1313 edit.setTitle("Edit Tag");
1314 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1315 QTreeWidgetItem currentSelection;
1316 currentSelection = selections.get(0);
1317 edit.setTag(currentSelection.text(0));
1318 edit.setTagList(listManager.getTagIndex());
1321 if (!edit.okPressed())
1324 String guid = currentSelection.text(2);
1325 currentSelection.setText(0,edit.getTag());
1327 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1328 if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
1329 listManager.getTagIndex().get(i).setName(edit.getTag());
1330 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
1331 updateListTagName(guid);
1332 if (currentNote != null && currentNote.getTagGuids().contains(guid))
1333 browserWindow.setTag(getTagNamesForNote(currentNote));
1334 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
1338 browserWindow.setTag(getTagNamesForNote(currentNote));
1339 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
1341 // Delete an existing tag
1342 @SuppressWarnings("unused")
1343 private void deleteTag() {
1344 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
1346 if (QMessageBox.question(this, "Confirmation", "Delete the selected tags?",
1347 QMessageBox.StandardButton.Yes,
1348 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1352 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1353 for (int i=selections.size()-1; i>=0; i--) {
1354 QTreeWidgetItem currentSelection;
1355 currentSelection = selections.get(i);
1356 removeTagItem(currentSelection.text(2));
1358 tagIndexUpdated(true);
1359 listManager.countTagResults(listManager.getNoteIndex());
1360 // tagTree.updateCounts(listManager.getTagCounter());
1361 logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
1363 // Remove a tag tree item. Go recursively down & remove the children too
1364 private void removeTagItem(String guid) {
1365 for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {
1366 String parent = listManager.getTagIndex().get(j).getParentGuid();
1367 if (parent != null && parent.equals(guid)) {
1368 //Remove this tag's children
1369 removeTagItem(listManager.getTagIndex().get(j).getGuid());
1372 //Now, remove this tag
1373 removeListTagName(guid);
1374 conn.getTagTable().expungeTag(guid, true);
1375 for (int a=0; a<listManager.getTagIndex().size(); a++) {
1376 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
1377 listManager.getTagIndex().remove(a);
1382 // Setup the tree containing the user's tags
1383 private void initializeTagTree() {
1384 logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
1385 tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
1386 listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
1387 logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
1389 // Listener when a tag is selected
1390 @SuppressWarnings("unused")
1391 private void tagTreeSelection() {
1392 logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
1394 List<QTreeWidgetItem> x = tagTree.selectedItems();
1395 for (int i=0; i<x.size(); i++) {
1399 clearAttributeFilter();
1400 clearSavedSearchFilter();
1402 menuBar.noteRestoreAction.setVisible(false);
1404 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1405 QTreeWidgetItem currentSelection;
1406 selectedTagGUIDs.clear();
1407 for (int i=0; i<selections.size(); i++) {
1408 currentSelection = selections.get(i);
1409 selectedTagGUIDs.add(currentSelection.text(2));
1411 if (selections.size() > 0) {
1412 menuBar.tagEditAction.setEnabled(true);
1413 menuBar.tagDeleteAction.setEnabled(true);
1416 menuBar.tagEditAction.setEnabled(false);
1417 menuBar.tagDeleteAction.setEnabled(false);
1419 listManager.setSelectedTags(selectedTagGUIDs);
1420 listManager.loadNotesIndex();
1421 noteIndexUpdated(false);
1422 logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
1424 // trigger the tag index to be refreshed
1425 @SuppressWarnings("unused")
1426 private void tagIndexUpdated() {
1427 tagIndexUpdated(true);
1429 private void tagIndexUpdated(boolean reload) {
1430 logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
1431 if (selectedTagGUIDs == null)
1432 selectedTagGUIDs = new ArrayList<String>();
1433 // selectedTagGUIDs.clear(); // clear out old entries
1435 tagTree.blockSignals(true);
1437 tagTree.load(listManager.getTagIndex());
1438 for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
1439 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
1441 selectedTagGUIDs.remove(i);
1443 tagTree.blockSignals(false);
1445 browserWindow.setTag(getTagNamesForNote(currentNote));
1446 logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
1448 // Show/Hide note information
1449 private void toggleTagWindow() {
1450 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
1451 if (tagTree.isVisible())
1455 menuBar.hideTags.setChecked(tagTree.isVisible());
1456 Global.saveWindowVisible("tagTree", tagTree.isVisible());
1457 logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
1459 // A note's tags have been updated
1460 @SuppressWarnings("unused")
1461 private void updateNoteTags(String guid, List<String> tags) {
1462 listManager.saveNoteTags(guid, tags);
1463 listManager.countTagResults(listManager.getNoteIndex());
1464 StringBuffer names = new StringBuffer("");
1465 for (int i=0; i<tags.size(); i++) {
1466 names = names.append(tags.get(i));
1467 if (i<tags.size()-1) {
1468 names.append(Global.tagDelimeter + " ");
1471 browserWindow.setTag(names.toString());
1473 // tagTree.updateCounts(listManager.getTagCounter());
1475 // Get a string containing all tag names for a note
1476 private String getTagNamesForNote(Note n) {
1477 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
1478 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
1480 StringBuffer buffer = new StringBuffer(100);
1481 Vector<String> v = new Vector<String>();
1482 List<String> guids = n.getTagGuids();
1487 for (int i=0; i<guids.size(); i++) {
1488 v.add(listManager.getTagNameByGuid(guids.get(i)));
1490 Comparator<String> comparator = Collections.reverseOrder();
1491 Collections.sort(v,comparator);
1492 Collections.reverse(v);
1494 for (int i = 0; i<v.size(); i++) {
1496 buffer.append(", ");
1497 buffer.append(v.get(i));
1500 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
1501 return buffer.toString();
1503 // Tags were added via dropping notes from the note list
1504 @SuppressWarnings("unused")
1505 private void tagsAdded(String noteGuid, String tagGuid) {
1506 String tagName = null;
1507 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1508 if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
1509 tagName = listManager.getTagIndex().get(i).getName();
1510 i=listManager.getTagIndex().size();
1513 if (tagName == null)
1516 for (int i=0; i<noteTableView.model.rowCount(); i++) {
1517 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
1518 if (modelIndex != null) {
1519 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
1520 String titleGuid = (String)ix.values().toArray()[0];
1521 if (titleGuid.equals(noteGuid)) {
1522 String text = (String)noteTableView.model.data(i, Global.noteTableTagPosition);
1523 if (!text.trim().equals(""))
1524 text = text + Global.tagDelimeter + " " +tagName;
1527 noteTableView.model.setData(i, Global.noteTableTagPosition, text);
1528 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
1529 if (noteGuid.equals(currentNoteGuid))
1530 browserWindow.setTag(text);
1531 i=noteTableView.model.rowCount();
1536 private void clearTagFilter() {
1537 tagTree.blockSignals(true);
1538 tagTree.clearSelection();
1539 menuBar.noteRestoreAction.setVisible(false);
1540 menuBar.tagEditAction.setEnabled(false);
1541 menuBar.tagDeleteAction.setEnabled(false);
1542 selectedTagGUIDs.clear();
1543 listManager.setSelectedTags(selectedTagGUIDs);
1544 tagTree.blockSignals(false);
1548 //***************************************************************
1549 //***************************************************************
1550 //** These functions deal with Saved Search menu items
1551 //***************************************************************
1552 //***************************************************************
1553 // Add a new notebook
1554 @SuppressWarnings("unused")
1555 private void addSavedSearch() {
1556 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
1557 SavedSearchEdit edit = new SavedSearchEdit();
1558 edit.setSearchList(listManager.getSavedSearchIndex());
1561 if (!edit.okPressed())
1564 Calendar currentTime = new GregorianCalendar();
1565 Long l = new Long(currentTime.getTimeInMillis());
1566 String randint = new String(Long.toString(l));
1568 SavedSearch search = new SavedSearch();
1569 search.setUpdateSequenceNum(0);
1570 search.setGuid(randint);
1571 search.setName(edit.getName());
1572 search.setQuery(edit.getQuery());
1573 search.setFormat(QueryFormat.USER);
1574 listManager.getSavedSearchIndex().add(search);
1575 conn.getSavedSearchTable().addSavedSearch(search, true);
1576 savedSearchIndexUpdated();
1577 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
1579 // Edit an existing tag
1580 @SuppressWarnings("unused")
1581 private void editSavedSearch() {
1582 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
1583 SavedSearchEdit edit = new SavedSearchEdit();
1584 edit.setTitle("Edit Search");
1585 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1586 QTreeWidgetItem currentSelection;
1587 currentSelection = selections.get(0);
1588 String guid = currentSelection.text(1);
1589 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
1590 edit.setName(currentSelection.text(0));
1591 edit.setQuery(s.getQuery());
1592 edit.setSearchList(listManager.getSavedSearchIndex());
1595 if (!edit.okPressed())
1598 List<SavedSearch> list = listManager.getSavedSearchIndex();
1599 SavedSearch search = null;
1600 boolean found = false;
1601 for (int i=0; i<list.size(); i++) {
1602 search = list.get(i);
1603 if (search.getGuid().equals(guid)) {
1610 search.setName(edit.getName());
1611 search.setQuery(edit.getQuery());
1612 conn.getSavedSearchTable().updateSavedSearch(search, true);
1613 savedSearchIndexUpdated();
1614 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
1616 // Delete an existing tag
1617 @SuppressWarnings("unused")
1618 private void deleteSavedSearch() {
1619 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
1621 if (QMessageBox.question(this, "Confirmation", "Delete the selected search?",
1622 QMessageBox.StandardButton.Yes,
1623 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1627 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1628 for (int i=selections.size()-1; i>=0; i--) {
1629 QTreeWidgetItem currentSelection;
1630 currentSelection = selections.get(i);
1631 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
1632 if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
1633 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
1634 listManager.getSavedSearchIndex().remove(j);
1635 j=listManager.getSavedSearchIndex().size()+1;
1638 selections.remove(i);
1640 savedSearchIndexUpdated();
1641 logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
1643 // Setup the tree containing the user's tags
1644 private void initializeSavedSearchTree() {
1645 logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
1646 savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
1647 logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
1649 // Listener when a tag is selected
1650 @SuppressWarnings("unused")
1651 private void savedSearchTreeSelection() {
1652 logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
1654 clearNotebookFilter();
1657 clearAttributeFilter();
1659 String currentGuid = selectedSavedSearchGUID;
1660 menuBar.savedSearchEditAction.setEnabled(true);
1661 menuBar.savedSearchDeleteAction.setEnabled(true);
1662 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1663 QTreeWidgetItem currentSelection;
1664 selectedSavedSearchGUID = "";
1665 for (int i=0; i<selections.size(); i++) {
1666 currentSelection = selections.get(i);
1667 if (currentSelection.text(1).equals(currentGuid)) {
1668 currentSelection.setSelected(false);
1670 selectedSavedSearchGUID = currentSelection.text(1);
1672 // i = selections.size() +1;
1675 // There is the potential for no notebooks to be selected if this
1676 // happens then we make it look like all notebooks were selecetd.
1677 // If that happens, just select the "all notebooks"
1678 if (selections.size()==0) {
1679 clearSavedSearchFilter();
1681 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
1683 logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
1685 private void clearSavedSearchFilter() {
1686 menuBar.savedSearchEditAction.setEnabled(false);
1687 menuBar.savedSearchDeleteAction.setEnabled(false);
1688 savedSearchTree.blockSignals(true);
1689 savedSearchTree.clearSelection();
1690 savedSearchTree.blockSignals(false);
1691 selectedSavedSearchGUID = "";
1692 searchField.setEditText("");
1693 searchPerformed = false;
1694 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
1696 // trigger the tag index to be refreshed
1697 private void savedSearchIndexUpdated() {
1698 if (selectedSavedSearchGUID == null)
1699 selectedSavedSearchGUID = new String();
1700 savedSearchTree.blockSignals(true);
1701 savedSearchTree.load(listManager.getSavedSearchIndex());
1702 savedSearchTree.selectGuid(selectedSavedSearchGUID);
1703 savedSearchTree.blockSignals(false);
1705 // trigger when the saved search selection changes
1706 @SuppressWarnings("unused")
1707 private void updateSavedSearchSelection() {
1708 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
1710 menuBar.savedSearchEditAction.setEnabled(true);
1711 menuBar.savedSearchDeleteAction.setEnabled(true);
1712 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
1714 if (selections.size() > 0) {
1715 menuBar.savedSearchEditAction.setEnabled(true);
1716 menuBar.savedSearchDeleteAction.setEnabled(true);
1717 selectedSavedSearchGUID = selections.get(0).text(1);
1718 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
1719 searchField.setEditText(s.getQuery());
1721 menuBar.savedSearchEditAction.setEnabled(false);
1722 menuBar.savedSearchDeleteAction.setEnabled(false);
1723 selectedSavedSearchGUID = "";
1724 searchField.setEditText("");
1726 searchFieldChanged();
1728 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
1732 // Show/Hide note information
1733 private void toggleSavedSearchWindow() {
1734 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
1735 if (savedSearchTree.isVisible())
1736 savedSearchTree.hide();
1738 savedSearchTree.show();
1739 menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
1741 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
1742 logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
1748 //***************************************************************
1749 //***************************************************************
1750 //** These functions deal with Help menu & tool menu items
1751 //***************************************************************
1752 //***************************************************************
1753 // Show database status
1754 @SuppressWarnings("unused")
1755 private void databaseStatus() {
1757 int dirty = conn.getNoteTable().getDirtyCount();
1758 int unindexed = conn.getNoteTable().getUnindexedCount();
1759 DatabaseStatus status = new DatabaseStatus();
1760 status.setUnsynchronized(dirty);
1761 status.setUnindexed(unindexed);
1762 status.setNoteCount(conn.getNoteTable().getNoteCount());
1763 status.setNotebookCount(listManager.getNotebookIndex().size());
1764 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
1765 status.setTagCount(listManager.getTagIndex().size());
1766 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
1767 status.setWordCount(conn.getWordsTable().getWordCount());
1771 // Compact the database
1772 @SuppressWarnings("unused")
1773 private void compactDatabase() {
1774 logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
1775 if (QMessageBox.question(this, "Confirmation", "This will free unused space in the database, "+
1776 "but please be aware that depending upon the size of your database this can be time consuming " +
1777 "and NeverNote will be unresponsive until it is complete. Do you wish to continue?",
1778 QMessageBox.StandardButton.Yes,
1779 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
1782 setMessage("Compacting database.");
1784 listManager.compactDatabase();
1786 setMessage("Database compact is complete.");
1787 logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
1789 @SuppressWarnings("unused")
1790 private void accountInformation() {
1791 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
1792 AccountDialog dialog = new AccountDialog();
1794 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
1796 @SuppressWarnings("unused")
1797 private void releaseNotes() {
1798 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
1799 QDialog dialog = new QDialog(this);
1800 QHBoxLayout layout = new QHBoxLayout();
1801 QTextEdit textBox = new QTextEdit();
1802 layout.addWidget(textBox);
1803 textBox.setReadOnly(true);
1804 QFile file = new QFile(Global.getFileManager().getHomeDirPath("release.txt"));
1805 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
1806 QIODevice.OpenModeFlag.Text)))
1808 textBox.setText(file.readAll().toString());
1810 dialog.setWindowTitle("Release Notes");
1811 dialog.setLayout(layout);
1813 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
1815 // Called when user picks Log from the help menu
1816 @SuppressWarnings("unused")
1817 private void logger() {
1818 logger.log(logger.HIGH, "Entering NeverNote.logger");
1819 QDialog dialog = new QDialog(this);
1820 QHBoxLayout layout = new QHBoxLayout();
1821 QListWidget textBox = new QListWidget();
1822 layout.addWidget(textBox);
1823 textBox.addItems(emitLog);
1825 dialog.setLayout(layout);
1826 dialog.setWindowTitle("Mesasge Log");
1828 logger.log(logger.HIGH, "Leaving NeverNote.logger");
1830 // Menu option "help/about" was selected
1831 @SuppressWarnings("unused")
1832 private void about() {
1833 logger.log(logger.HIGH, "Entering NeverNote.about");
1834 QMessageBox.about(this,
1835 tr("About NeverNote"),
1836 tr("<h4><center><b>NeverNote</b></center></h4><hr><center>Version "+Global.version+"<hr></center>Evernote"
1837 +" Generic client.<br><br>"
1838 +"Licensed under GPL v2. <br><hr><br>"
1839 +"Evernote is copyright 2001-2010 by Evernote Corporation<br>"
1840 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
1841 +"PDFRenderer is licened under the LGPL<br>"
1842 +"Jazzy is licened under the LGPL<br>"
1843 +"Java is a registered trademark of Sun Microsystems.<br><hr>"));
1844 logger.log(logger.HIGH, "Leaving NeverNote.about");
1846 // Hide the entire left hand side
1847 @SuppressWarnings("unused")
1848 private void toggleLeftSide() {
1851 hidden = !menuBar.hideLeftSide.isChecked();
1852 menuBar.hideLeftSide.setChecked(!hidden);
1854 if (notebookTree.isVisible() != hidden)
1855 toggleNotebookWindow();
1856 if (savedSearchTree.isVisible() != hidden)
1857 toggleSavedSearchWindow();
1858 if (tagTree.isVisible() != hidden)
1860 if (attributeTree.isVisible() != hidden)
1861 toggleAttributesWindow();
1862 if (trashTree.isVisible() != hidden)
1863 toggleTrashWindow();
1865 Global.saveWindowVisible("leftPanel", hidden);
1870 //***************************************************************
1871 //***************************************************************
1872 //** These functions deal with the Toolbar
1873 //***************************************************************
1874 //***************************************************************
1875 // Text in the search bar has been cleared
1876 private void searchFieldCleared() {
1877 searchField.setEditText("");
1878 saveNoteIndexWidth();
1880 // text in the search bar changed. We only use this to tell if it was cleared,
1881 // otherwise we trigger off searchFieldChanged.
1882 @SuppressWarnings("unused")
1883 private void searchFieldTextChanged(String text) {
1884 if (text.trim().equals("")) {
1885 searchFieldCleared();
1886 if (searchPerformed) {
1888 listManager.setEnSearch("");
1889 ///// listManager.clearNoteIndexSearch();
1890 //noteIndexUpdated(true);
1891 listManager.loadNotesIndex();
1892 refreshEvernoteNote(true);
1893 noteIndexUpdated(false);
1895 searchPerformed = false;
1898 // Text in the toolbar has changed
1899 private void searchFieldChanged() {
1900 logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
1902 saveNoteIndexWidth();
1903 String text = searchField.currentText();
1904 listManager.setEnSearch(text.trim());
1905 listManager.loadNotesIndex();
1906 //--->>> noteIndexUpdated(true);
1907 noteIndexUpdated(false);
1908 refreshEvernoteNote(true);
1909 searchPerformed = true;
1910 logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
1912 // Build the window tool bar
1913 private void setupToolBar() {
1914 logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
1915 toolBar = addToolBar(tr("toolBar"));
1917 prevButton = toolBar.addAction("Previous");
1918 QIcon prevIcon = new QIcon(iconPath+"back.png");
1919 prevButton.setIcon(prevIcon);
1920 prevButton.triggered.connect(this, "previousViewedAction()");
1922 nextButton = toolBar.addAction("Next");
1923 QIcon nextIcon = new QIcon(iconPath+"forward.png");
1924 nextButton.setIcon(nextIcon);
1925 nextButton.triggered.connect(this, "nextViewedAction()");
1927 upButton = toolBar.addAction("Up");
1928 QIcon upIcon = new QIcon(iconPath+"up.png");
1929 upButton.setIcon(upIcon);
1930 upButton.triggered.connect(this, "upAction()");
1932 downButton = toolBar.addAction("Down");
1933 QIcon downIcon = new QIcon(iconPath+"down.png");
1934 downButton.setIcon(downIcon);
1935 downButton.triggered.connect(this, "downAction()");
1937 synchronizeButton = toolBar.addAction("Synchronize");
1938 synchronizeAnimation = new ArrayList<QIcon>();
1939 synchronizeAnimation.add(new QIcon(iconPath+"synchronize-0.png"));
1940 synchronizeAnimation.add(new QIcon(iconPath+"synchronize-1.png"));
1941 synchronizeAnimation.add(new QIcon(iconPath+"synchronize-2.png"));
1942 synchronizeAnimation.add(new QIcon(iconPath+"synchronize-3.png"));
1943 synchronizeButton.setIcon(synchronizeAnimation.get(0));
1944 synchronizeFrame = 0;
1945 synchronizeButton.triggered.connect(this, "evernoteSync()");
1947 printButton = toolBar.addAction("Print");
1948 QIcon printIcon = new QIcon(iconPath+"print.png");
1949 printButton.setIcon(printIcon);
1950 printButton.triggered.connect(this, "printNote()");
1952 tagButton = toolBar.addAction("Tag");
1953 QIcon tagIcon = new QIcon(iconPath+"tag.png");
1954 tagButton.setIcon(tagIcon);
1955 tagButton.triggered.connect(browserWindow, "modifyTags()");
1957 attributeButton = toolBar.addAction("Attributes");
1958 QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
1959 attributeButton.setIcon(attributeIcon);
1960 attributeButton.triggered.connect(this, "toggleNoteInformation()");
1962 emailButton = toolBar.addAction("Email");
1963 QIcon emailIcon = new QIcon(iconPath+"email.png");
1964 emailButton.setIcon(emailIcon);
1965 emailButton.triggered.connect(this, "emailNote()");
1967 deleteButton = toolBar.addAction("Delete");
1968 QIcon deleteIcon = new QIcon(iconPath+"delete.png");
1969 deleteButton.setIcon(deleteIcon);
1970 deleteButton.triggered.connect(this, "deleteNote()");
1972 newButton = toolBar.addAction("New");
1973 QIcon newIcon = new QIcon(iconPath+"new.png");
1974 newButton.triggered.connect(this, "addNote()");
1975 newButton.setIcon(newIcon);
1976 toolBar.addSeparator();
1977 toolBar.addWidget(new QLabel("Quota:"));
1978 toolBar.addWidget(quotaBar);
1979 //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
1983 zoomSpinner = new QSpinBox();
1984 zoomSpinner.setMinimum(10);
1985 zoomSpinner.setMaximum(1000);
1986 zoomSpinner.setAccelerated(true);
1987 zoomSpinner.setSingleStep(10);
1988 zoomSpinner.setValue(100);
1989 zoomSpinner.valueChanged.connect(this, "zoomChanged()");
1990 toolBar.addWidget(new QLabel("Zoom"));
1991 toolBar.addWidget(zoomSpinner);
1993 //toolBar.addWidget(new QLabel(" "));
1994 toolBar.addSeparator();
1995 toolBar.addWidget(new QLabel(" Search:"));
1996 toolBar.addWidget(searchField);
1997 QSizePolicy sizePolicy = new QSizePolicy();
1998 sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
1999 searchField.setSizePolicy(sizePolicy);
2000 searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
2002 searchClearButton = toolBar.addAction("Search Clear");
2003 QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
2004 searchClearButton.setIcon(searchClearIcon);
2005 searchClearButton.triggered.connect(this, "searchFieldCleared()");
2007 logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
2009 // Update the sychronize button picture
2010 @SuppressWarnings("unused")
2011 private void updateSyncButton() {
2013 if (synchronizeFrame == 4)
2014 synchronizeFrame = 0;
2015 synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame));
2017 // Synchronize with Evernote
2018 @SuppressWarnings("unused")
2019 private void evernoteSync() {
2020 logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
2021 if (!Global.isConnected)
2023 if (Global.isConnected)
2024 synchronizeAnimationTimer.start(200);
2026 logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
2028 private void updateQuotaBar() {
2029 long limit = Global.getUploadLimit();
2030 long amount = Global.getUploadAmount();
2031 if (amount>0 && limit>0) {
2032 int percent =(int)(amount*100/limit);
2033 quotaBar.setValue(percent);
2035 quotaBar.setValue(0);
2038 @SuppressWarnings("unused")
2039 private void zoomChanged() {
2040 browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
2043 //****************************************************************
2044 //****************************************************************
2045 //* System Tray functions
2046 //****************************************************************
2047 //****************************************************************
2048 private void trayToggleVisible() {
2056 @SuppressWarnings("unused")
2057 private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
2058 if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
2059 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
2060 trayToggleVisible();
2065 //***************************************************************
2066 //***************************************************************
2067 //** These functions deal with the trash tree
2068 //***************************************************************
2069 //***************************************************************
2070 // Setup the tree containing the trash.
2071 @SuppressWarnings("unused")
2072 private void trashTreeSelection() {
2073 logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
2075 clearNotebookFilter();
2077 clearAttributeFilter();
2078 clearSavedSearchFilter();
2080 String tempGuid = currentNoteGuid;
2082 // currentNoteGuid = "";
2083 currentNote = new Note();
2084 selectedNoteGUIDs.clear();
2085 listManager.getSelectedNotebooks().clear();
2086 listManager.getSelectedTags().clear();
2087 listManager.setSelectedSavedSearch("");
2088 browserWindow.clear();
2090 // toggle the add buttons
2091 newButton.setEnabled(!newButton.isEnabled());
2092 menuBar.noteAdd.setEnabled(newButton.isEnabled());
2093 menuBar.noteAdd.setVisible(true);
2095 List<QTreeWidgetItem> selections = trashTree.selectedItems();
2096 if (selections.size() == 0) {
2097 currentNoteGuid = trashNoteGuid;
2098 trashNoteGuid = tempGuid;
2099 Global.showDeleted = false;
2100 menuBar.noteRestoreAction.setEnabled(false);
2101 menuBar.noteRestoreAction.setVisible(false);
2104 currentNoteGuid = trashNoteGuid;
2105 trashNoteGuid = tempGuid;
2106 menuBar.noteRestoreAction.setEnabled(true);
2107 menuBar.noteRestoreAction.setVisible(true);
2108 Global.showDeleted = true;
2110 listManager.loadNotesIndex();
2111 noteIndexUpdated(false);
2112 //// browserWindow.setEnabled(newButton.isEnabled());
2113 browserWindow.setReadOnly(!newButton.isEnabled());
2114 logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
2116 // Empty the trash file
2117 @SuppressWarnings("unused")
2118 private void emptyTrash() {
2119 // browserWindow.clear();
2120 listManager.emptyTrash();
2121 if (trashTree.selectedItems().size() > 0) {
2122 listManager.getSelectedNotebooks().clear();
2123 listManager.getSelectedTags().clear();
2124 listManager.setSelectedSavedSearch("");
2125 newButton.setEnabled(!newButton.isEnabled());
2126 menuBar.noteAdd.setEnabled(newButton.isEnabled());
2127 menuBar.noteAdd.setVisible(true);
2128 browserWindow.clear();
2131 clearNotebookFilter();
2132 clearSavedSearchFilter();
2133 clearAttributeFilter();
2135 Global.showDeleted = false;
2136 menuBar.noteRestoreAction.setEnabled(false);
2137 menuBar.noteRestoreAction.setVisible(false);
2139 listManager.loadNotesIndex();
2140 //--->>> noteIndexUpdated(true);
2141 noteIndexUpdated(false);
2144 // Show/Hide trash window
2145 private void toggleTrashWindow() {
2146 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
2147 if (trashTree.isVisible())
2151 menuBar.hideTrash.setChecked(trashTree.isVisible());
2153 Global.saveWindowVisible("trashTree", trashTree.isVisible());
2154 logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
2156 private void clearTrashFilter() {
2157 Global.showDeleted = false;
2158 newButton.setEnabled(true);
2159 menuBar.noteAdd.setEnabled(true);
2160 menuBar.noteAdd.setVisible(true);
2161 trashTree.blockSignals(true);
2162 trashTree.clearSelection();
2163 trashTree.blockSignals(false);
2168 //***************************************************************
2169 //***************************************************************
2170 //** These functions deal with connection settings
2171 //***************************************************************
2172 //***************************************************************
2173 // SyncRunner had a problem and things are disconnected
2174 @SuppressWarnings("unused")
2175 private void remoteErrorDisconnect() {
2176 menuBar.connectAction.setText("Connect");
2177 menuBar.connectAction.setToolTip("Connect to Evernote");
2178 menuBar.synchronizeAction.setEnabled(false);
2179 synchronizeAnimationTimer.stop();
2182 // Do a manual connect/disconnect
2183 private void remoteConnect() {
2184 logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
2186 if (Global.isConnected) {
2187 Global.isConnected = false;
2188 syncRunner.enDisconnect();
2189 setupConnectMenuOptions();
2194 AESEncrypter aes = new AESEncrypter();
2196 aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("secure.txt")));
2197 } catch (FileNotFoundException e) {
2198 // File not found, so we'll just get empty strings anyway.
2200 String userid = aes.getUserid();
2201 String password = aes.getPassword();
2202 if (!userid.equals("") && !password.equals("")) {
2203 Global.username = userid;
2204 Global.password = password;
2207 // Show the login dialog box
2208 if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) {
2209 LoginDialog login = new LoginDialog();
2212 if (!login.okPressed()) {
2216 Global.username = login.getUserid();
2217 Global.password = login.getPassword();
2219 syncRunner.username = Global.username;
2220 syncRunner.password = Global.password;
2221 syncRunner.userStoreUrl = Global.userStoreUrl;
2222 syncRunner.noteStoreUrl = Global.noteStoreUrl;
2223 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
2224 syncRunner.enConnect();
2225 Global.isConnected = syncRunner.isConnected;
2227 setupConnectMenuOptions();
2228 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
2230 private void setupConnectMenuOptions() {
2231 logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
2232 if (!Global.isConnected) {
2233 menuBar.connectAction.setText("Connect");
2234 menuBar.connectAction.setToolTip("Connect to Evernote");
2235 menuBar.synchronizeAction.setEnabled(false);
2237 menuBar.connectAction.setText("Disconnect");
2238 menuBar.connectAction.setToolTip("Disconnect from Evernote");
2239 menuBar.synchronizeAction.setEnabled(true);
2241 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
2246 //***************************************************************
2247 //***************************************************************
2248 //** These functions deal with the GUI Attribute tree
2249 //***************************************************************
2250 //***************************************************************
2251 @SuppressWarnings("unused")
2252 private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
2255 clearNotebookFilter();
2257 clearSavedSearchFilter();
2259 if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
2260 if (item.childCount() > 0) {
2261 item.setSelected(false);
2263 Global.createdBeforeFilter.reset();
2264 Global.createdSinceFilter.reset();
2265 Global.changedBeforeFilter.reset();
2266 Global.changedSinceFilter.reset();
2267 Global.containsFilter.reset();
2268 attributeTreeSelected = item;
2269 DateAttributeFilterTable f = null;
2270 f = findDateAttributeFilterTable(item.parent());
2272 f.select(item.text(0));
2274 String text = item.text(0);
2275 Global.containsFilter.select(text);
2278 listManager.loadNotesIndex();
2279 noteIndexUpdated(false);
2282 attributeTreeSelected = null;
2283 item.setSelected(false);
2284 Global.createdBeforeFilter.reset();
2285 Global.createdSinceFilter.reset();
2286 Global.changedBeforeFilter.reset();
2287 Global.changedSinceFilter.reset();
2288 Global.containsFilter.reset();
2289 listManager.loadNotesIndex();
2290 noteIndexUpdated(false);
2292 // This determines what attribute filter we need, depending upon the selection
2293 private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
2294 if (w.parent() != null && w.childCount() > 0) {
2295 QTreeWidgetItem parent = w.parent();
2296 if (parent.text(0).equalsIgnoreCase("created") &&
2297 w.text(0).equalsIgnoreCase("since"))
2298 return Global.createdSinceFilter;
2299 if (parent.text(0).equalsIgnoreCase("created") &&
2300 w.text(0).equalsIgnoreCase("before"))
2301 return Global.createdBeforeFilter;
2302 if (parent.text(0).equalsIgnoreCase("last modified") &&
2303 w.text(0).equalsIgnoreCase("since"))
2304 return Global.changedSinceFilter;
2305 if (parent.text(0).equalsIgnoreCase("last modified") &&
2306 w.text(0).equalsIgnoreCase("before"))
2307 return Global.changedBeforeFilter;
2311 // Show/Hide attribute search window
2312 private void toggleAttributesWindow() {
2313 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
2314 if (attributeTree.isVisible())
2315 attributeTree.hide();
2317 attributeTree.show();
2318 menuBar.hideAttributes.setChecked(attributeTree.isVisible());
2320 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
2321 logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
2323 private void clearAttributeFilter() {
2324 Global.createdBeforeFilter.reset();
2325 Global.createdSinceFilter.reset();
2326 Global.changedBeforeFilter.reset();
2327 Global.changedSinceFilter.reset();
2328 Global.containsFilter.reset();
2329 attributeTreeSelected = null;
2330 attributeTree.blockSignals(true);
2331 attributeTree.clearSelection();
2332 attributeTree.blockSignals(false);
2336 //***************************************************************
2337 //***************************************************************
2338 //** These functions deal with the GUI Note index table
2339 //***************************************************************
2340 //***************************************************************
2341 // Initialize the note list table
2342 private void initializeNoteTable() {
2343 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
2344 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
2345 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
2346 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
2348 // Show/Hide trash window
2349 @SuppressWarnings("unused")
2350 private void toggleNoteListWindow() {
2351 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
2352 if (noteTableView.isVisible())
2353 noteTableView.hide();
2355 noteTableView.show();
2356 menuBar.hideNoteList.setChecked(noteTableView.isVisible());
2358 Global.saveWindowVisible("noteList", noteTableView.isVisible());
2359 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
2361 // Handle the event that a user selects a note from the table
2362 @SuppressWarnings("unused")
2363 private void noteTableSelection() {
2364 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
2366 if (historyGuids.size() == 0) {
2367 historyGuids.add(currentNoteGuid);
2368 historyPosition = 1;
2370 noteTableView.showColumn(Global.noteTableGuidPosition);
2372 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2373 noteTableView.hideColumn(Global.noteTableGuidPosition);
2375 if (selections.size() > 0) {
2377 menuBar.noteDuplicateAction.setEnabled(true);
2378 menuBar.noteOnlineHistoryAction.setEnabled(true);
2379 menuBar.noteMergeAction.setEnabled(true);
2380 selectedNoteGUIDs.clear();
2381 if (selections.size() != 1 || Global.showDeleted) {
2382 menuBar.noteDuplicateAction.setEnabled(false);
2384 if (selections.size() != 1 || !Global.isConnected) {
2385 menuBar.noteOnlineHistoryAction.setEnabled(false);
2387 if (selections.size() == 1) {
2388 menuBar.noteMergeAction.setEnabled(false);
2390 for (int i=0; i<selections.size(); i++) {
2391 int row = selections.get(i).row();
2393 upButton.setEnabled(false);
2395 upButton.setEnabled(true);
2396 if (row < noteTableView.model.rowCount()-1)
2397 downButton.setEnabled(true);
2399 downButton.setEnabled(false);
2400 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
2401 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
2402 currentNoteGuid = (String)ix.values().toArray()[0];
2403 selectedNoteGUIDs.add(currentNoteGuid);
2407 nextButton.setEnabled(true);
2408 prevButton.setEnabled(true);
2410 int endPosition = historyGuids.size()-1;
2411 for (int j=historyPosition; j<=endPosition; j++) {
2412 historyGuids.remove(historyGuids.size()-1);
2414 historyGuids.add(currentNoteGuid);
2415 historyPosition = historyGuids.size();
2417 if (historyPosition <= 1)
2418 prevButton.setEnabled(false);
2419 if (historyPosition == historyGuids.size())
2420 nextButton.setEnabled(false);
2422 fromHistory = false;
2423 scrollToGuid(currentNoteGuid);
2424 refreshEvernoteNote(true);
2425 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
2427 // Trigger a refresh when the note db has been updated
2428 private void noteIndexUpdated(boolean reload) {
2429 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
2430 Global.traceReset();
2432 refreshEvernoteNoteList();
2433 logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
2434 noteTableView.load(listManager, reload);
2435 scrollToGuid(currentNoteGuid);
2436 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
2438 // Called when the list of notes is updated
2439 private void refreshEvernoteNoteList() {
2440 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
2441 browserWindow.setDisabled(false);
2442 if (selectedNoteGUIDs == null)
2443 selectedNoteGUIDs = new ArrayList<String>();
2444 selectedNoteGUIDs.clear(); // clear out old entries
2446 String saveCurrentNoteGuid = new String();
2447 String tempNoteGuid = new String();
2449 historyGuids.clear();
2450 historyPosition = 0;
2451 prevButton.setEnabled(false);
2452 nextButton.setEnabled(false);
2454 if (currentNoteGuid == null)
2455 currentNoteGuid = new String();
2457 for (Note note : listManager.getNoteIndex()) {
2458 tempNoteGuid = note.getGuid();
2459 if (currentNoteGuid.equals(tempNoteGuid)) {
2460 saveCurrentNoteGuid = new String(tempNoteGuid);
2464 if (listManager.getNoteIndex().size() == 0) {
2465 currentNoteGuid = "";
2467 browserWindow.clear();
2468 browserWindow.setDisabled(true);
2471 if (saveCurrentNoteGuid.equals("") && listManager.getNoteIndex().size() >0) {
2472 currentNoteGuid = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1).getGuid();
2473 currentNote = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1);
2474 refreshEvernoteNote(true);
2476 refreshEvernoteNote(false);
2480 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
2482 // Called when the previous arrow button is clicked
2483 @SuppressWarnings("unused")
2484 private void previousViewedAction() {
2485 if (!prevButton.isEnabled())
2487 if (historyPosition == 0)
2490 if (historyPosition <= 0)
2492 String historyGuid = historyGuids.get(historyPosition-1);
2494 for (int i=0; i<noteTableView.model().rowCount(); i++) {
2495 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
2496 if (modelIndex != null) {
2497 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
2498 String tableGuid = (String)ix.values().toArray()[0];
2499 if (tableGuid.equals(historyGuid)) {
2500 noteTableView.selectRow(i);
2506 @SuppressWarnings("unused")
2507 private void nextViewedAction() {
2508 if (!nextButton.isEnabled())
2510 String historyGuid = historyGuids.get(historyPosition);
2513 for (int i=0; i<noteTableView.model().rowCount(); i++) {
2514 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
2515 if (modelIndex != null) {
2516 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
2517 String tableGuid = (String)ix.values().toArray()[0];
2518 if (tableGuid.equals(historyGuid)) {
2519 noteTableView.selectRow(i);
2525 // Called when the up arrow is clicked
2526 @SuppressWarnings("unused")
2527 private void upAction() {
2528 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2529 int row = selections.get(0).row();
2531 noteTableView.selectRow(row-1);
2534 // Called when the down arrow is clicked
2535 @SuppressWarnings("unused")
2536 private void downAction() {
2537 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
2538 int row = selections.get(0).row();
2539 int max = noteTableView.model.rowCount();
2541 noteTableView.selectRow(row+1);
2544 // Update a tag string for a specific note in the list
2545 @SuppressWarnings("unused")
2546 private void updateListTags(String guid, List<String> tags) {
2547 logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
2548 StringBuffer tagBuffer = new StringBuffer();
2549 for (int i=0; i<tags.size(); i++) {
2550 tagBuffer.append(tags.get(i));
2551 if (i<tags.size()-1)
2552 tagBuffer.append(", ");
2555 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2556 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2557 if (modelIndex != null) {
2558 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2559 String tableGuid = (String)ix.values().toArray()[0];
2560 if (tableGuid.equals(guid)) {
2561 noteTableView.model.setData(i, Global.noteTableTagPosition,tagBuffer.toString());
2562 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2567 logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
2569 // Update a title for a specific note in the list
2570 @SuppressWarnings("unused")
2571 private void updateListTitle(String guid, String title) {
2572 logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
2574 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2575 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2576 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2577 if (modelIndex != null) {
2578 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2579 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2580 String tableGuid = (String)ix.values().toArray()[0];
2581 if (tableGuid.equals(guid)) {
2582 noteTableView.model.setData(i, Global.noteTableTitlePosition,title);
2583 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2588 logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
2590 // Update a title for a specific note in the list
2591 @SuppressWarnings("unused")
2592 private void updateListAuthor(String guid, String author) {
2593 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2595 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2596 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2597 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2598 if (modelIndex != null) {
2599 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2600 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2601 String tableGuid = (String)ix.values().toArray()[0];
2602 if (tableGuid.equals(guid)) {
2603 noteTableView.model.setData(i, Global.noteTableAuthorPosition,author);
2604 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2609 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2611 private void updateListNoteNotebook(String guid, String notebook) {
2612 logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook");
2614 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2615 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2616 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2617 if (modelIndex != null) {
2618 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2619 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2620 String tableGuid = (String)ix.values().toArray()[0];
2621 if (tableGuid.equals(guid)) {
2622 noteTableView.model.setData(i, Global.noteTableNotebookPosition,notebook);
2623 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2628 logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook");
2630 // Update a title for a specific note in the list
2631 @SuppressWarnings("unused")
2632 private void updateListSourceUrl(String guid, String url) {
2633 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
2635 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2636 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
2637 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2638 if (modelIndex != null) {
2639 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
2640 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2641 String tableGuid = (String)ix.values().toArray()[0];
2642 if (tableGuid.equals(guid)) {
2643 noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2644 noteTableView.model.setData(i, Global.noteTableSourceUrlPosition,url);
2649 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
2651 private void updateListGuid(String oldGuid, String newGuid) {
2652 logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
2654 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2655 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2656 if (modelIndex != null) {
2657 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2658 String tableGuid = (String)ix.values().toArray()[0];
2659 if (tableGuid.equals(oldGuid)) {
2660 noteTableView.model.setData(i, Global.noteTableGuidPosition,newGuid);
2661 //noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2666 logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
2668 private void updateListTagName(String guid) {
2669 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
2671 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2672 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
2673 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
2675 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2676 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2677 if (modelIndex != null) {
2678 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2679 String noteGuid = (String)ix.values().toArray()[0];
2680 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
2681 noteTableView.model.setData(i, Global.noteTableTagPosition, newName);
2682 //noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2683 i=noteTableView.model.rowCount();
2689 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
2691 private void removeListTagName(String guid) {
2692 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
2694 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2695 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
2696 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
2697 if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid))
2698 listManager.getNoteIndex().get(j).getTagGuids().remove(i);
2701 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
2702 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2703 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2704 if (modelIndex != null) {
2705 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2706 String noteGuid = (String)ix.values().toArray()[0];
2707 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
2708 noteTableView.model.setData(i, Global.noteTableTagPosition, newName);
2709 // noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2710 i=noteTableView.model.rowCount();
2716 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
2718 private void updateListNotebookName(String oldName, String newName) {
2719 logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName");
2721 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2722 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableNotebookPosition);
2723 if (modelIndex != null) {
2724 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2725 String tableName = (String)ix.values().toArray()[0];
2726 if (tableName.equalsIgnoreCase(oldName)) {
2727 // noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false");
2728 noteTableView.model.setData(i, Global.noteTableNotebookPosition, newName);
2732 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName");
2734 @SuppressWarnings("unused")
2735 private void updateListDateCreated(String guid, QDateTime date) {
2736 logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated");
2738 for (int i=0; i<noteTableView.model.rowCount(); i++) {
2739 QModelIndex modelIndex = noteTableView.model.index(i, Global.noteTableGuidPosition);
2740 if (modelIndex != null) {
2741 SortedMap<Integer, Object> ix = noteTableView.model.itemData(modelIndex);
2742 String tableGuid = (String)ix.values().toArray()[0];
2743 if (tableGuid.equals(guid)) {
2744 noteTableView.model.setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
2749 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");